• Forum
  • Lounge
  • Determining an operating system at runti

 
Determining an operating system at runtime?

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.

EDIT:
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.
Last edited on
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):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <boost/predef.h>

enum class OperatingSystem {
    // ...
    Windows
   // ...
};

OperatingSystem DetectOperatingSystem()
{
#ifdef BOOST_OS_WINDOWS
    return OperatingSystem::Windows;
#endif
}


[edit] Also, if you just want a name to show the user, then on POSIX systems you can use uname(2).
Last edited on
uname with the right flag should just show the OS.

The directory thing is something I thought about, but would that really work on *nix systems given they can varying filesystems?
NTFS on Linux still uses the /a/b path style.
$ touch "C:\\Windows"
$ echo $?
0


sorry, you wanted a directory
$ mkdir "C:\\Windows"
$ echo $?
0
Last edited on
Little Bobby Tables wrote:
Does anyone know of any solution/hack/trick/etc that would allow this?
ResidentBiscuit wrote:
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.

EDIT: I imagine that their are probably more lightweight process calls from other languages besides Java that have access to OS information... Here's what looks like a way to do it in Python: https://docs.python.org/2/library/platform.html#platform.system

Then if you needed more info you can just use the return of that with a bunch of if's and then call the OS specific ones for Windows/Mac/Linux/etc
Last edited on
The only problem with that is you're relying on the machine having python installed.
I have relied on a working (yet, sort-of hackish) solution:

I use boost library and retrieve the "prefferred" separator:

1
2
3
4
5
6
7
8
9
char sep(boost::filesystem::path("/").make_preferred().string()[0]);
if(sep == '/')
{
    /* It's unix/linux (or possibly mac...  still working on that one) */
}
else if(sep == '\\')
{
    /** it's windows...*/
}


It works on windows and linux, but I haven't tested it on a mac... You can try it on a mac.
@IWishIKnew
If you're going to use boost anyway, might as well use predef
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <boost/predef.h>

using namespace std;

int main() {
	if(BOOST_OS_WINDOWS)
        std::cout << "Windows" << std::endl;
    else if(BOOST_OS_LINUX)
        std::cout << "Linux" << std::endl;
    else
        std::cout << "Other" << std::endl;
}
http://coliru.stacked-crooked.com/a/39a53279d53e6a8a
http://www.boost.org/doc/libs/1_55_0/libs/predef/doc/html/index.html
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
#include <iostream>


int main(int Args, char* Arguments[], char* Env[])
{
    int Index = 0;

    while(Env[Index] != NULL)
    {
        std::cout << Env[Index] << "\n";
        Index++;
    }

    return 0;
}


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.
Last edited on
wow... that's amazing. I never knew you could have a third argument for main...

EDIT:

It would seem there is more to it... http://en.wikipedia.org/wiki/Main_function_%28programming%29#C_and_C.2B.2B

Apparently, on apple computers there is a fourth argument that passes other information as well.

You can also retrieve the environment variables through getenv() (cstdlib).
Last edited on
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.

I would be wary of using environment variables in general: http://www.dwheeler.com/secure-class/Secure-Programs-HOWTO/environment-variables.html
Last edited on
Still running, eh?

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.

On Mac, see http://stackoverflow.com/questions/11072804/how-do-i-determine-the-os-version-at-runtime-in-os-x-or-ios-without-using-gesta

Hope this helps.
Registered users can post here. Sign in or register to post.