I was on the irc.quakenet.org #cplusplus channel, and some of the developers got to talking, and started to try and think up a way to determine the current operating system at runtime. We are aware of how to do it at compile time quite easily and that it wouldn't make sense to do it at runtime, but we just wanted a challenge. So far, we have yet to come up with a surefire way of doing this during runtime. Does anyone know of any solution/hack/trick/etc that would allow this?
Wouldn't you need to know this at compile-time? At least for C++. I know Java can tell you via the System class. This problem makes much more sense on a language like Java, where you don't know at compile time what OS you're going to be running on.
I guess if this is just for funsies, you could do some OS fingerprinting like what Nmap does, though even that's not perfect and would require the loopback interface to be up.
There are various ways you could do it, like testing for the presence of a C:\Windows directory to detect Windows (edit: if the OS accepts a path like that at all then it's at least part of the DOS family), but none of them are foolproof. Here's one way (although it's cheating):
Does anyone know of any solution/hack/trick/etc that would allow this?
I know Java can tell you via the System class
Well, I suppose you could use a "trick" by making your C++ script call a java process for a little help. Have your C++ program call a tiny Java applet packages with your program, the Java applet should find the system info and return it to your main program however you want it to be returned.
Credit to MiiNiPaa for a partial solution to this one. A little while ago a similar topic came up and he had mentioned that HTML has a way of determining the host machines OS. I can't think of a platform agnostic way to invoke it though.
I would just use Boost.Predef like naraku and I suggested. It seems to be the best and most complete way.
Alternatively you can design a series of run-time tests. Using the path separator is not really reliable because not only Windows uses backwards-slash: all DOS family operating systems -- MS-DOS, all versions of MS Windows (including Windows 1.x which scarcely compatible with modern Windows) and IBM OS/2 -- as well as the open source Windows clone Haiku and WINE running on Linux and Mac, all accept backwards-slashes in paths. Further, not all OSes that accept forwards-slash are UNIXes, and not all UNIXes are fully compatible.
You could separate Windows from DOS and OS/2 by testing for the WINDIR environment variable. Windows NT and later also have a SYSTEMROOT variable whose value is equal to that of WINDIR. Although, it's possible for someone to set the WINDIR and SYSTEMROOT environment variables manually on DOS, OS/2 and pre-NT Windows, which would confuse your detection.
Sorry about the thread necromancy here guys but evidently I'm developing a split personality that wakes me up at 3:30 AM and won't let me fall asleep without posting to a thread that is almost a month old.
You can ID the OS based on the third parameter passed to main by whatever shell is running it. The names of the environment variables seem to be unique so simply searching the array for the labels of certain entries should tell you what OS you are on. Conveniently Windows provides an environment variable called "OS" that tells you what OS family you're running in. If *nix provides a similarly labeled variable, even if a regex were to be necessary, then we have our solution. I haven't fully hashed out this idea given my current local time but here is an illustration for anyone who cares:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
int main(int Args, char* Arguments, char* Env)
int Index = 0;
while(Env[Index] != NULL)
std::cout << Env[Index] << "\n";
Now if my brain doesn't let me get any sleep after this then the very next experiment we'll be doing will involve assessing the effects of rapidly increasing amounts of ethanol.
EDIT: An interesting thing happens when this gets kicked off on that cpp.sh site. It seems like it gives us a bit of info on the site running it.
The envp argument to main is not portable. It's not specified by any C standard, nor SUS/POSIX. The standard only specifies getenv for interacting with the system enviornment, POSIX/SUS also specifies putenv and unsetenv and BSD specifies setenv.
The basic OS (Windows, Linux, Mac OS, AIX) is known at compile time. It is a waste to throw that information away and spend time and effort trying to write code to figure out whether your program is running on Windows or Linux.
The next issue is figuring out what version of the OS is running. That is almost always possible to determine. A good number of OSes actually provide ways for you to discover that.
On Windows, use the GetVersion() function.
On Linux, it is quite a bit more involved, but a good combination of the uname() function and digging around /etc/ and the /proc filesystem (see /proc/version) is a good start. Beyond that you have to know something about the distribution you wish to identify.