Neither ISO C nor POSIX offer functionality to determine the underlying OS during runtime. From a theoretical point of view, it doesn't matter since C offers wrappers for the most common system calls, and from a nit-picking point of view, there doesn't even have to be an underlying OS.
However, in many real-world scenarios, it has proven helpful to know more about the host environment than C is willing to share, e.g. in order to find out where to store config files or how to call select(), so:
Is there an idiomatic way for an application written in C to determine the underlying OS during runtime?
At least, can I easily decide between Linux, Windows, BSD and MacOS?
My current guess is to check for the existence of certain files/directories, such as C:\ or /, but this approach seems unreliable. Maybe querying a series of such sources may help to establish the notion of "OS fingerprints", thus increasing reliability. Anyway, I'm looking forward to your suggestions.
Actually, most systems have a uname command which shows the current kernel in use. On Mac OS, this is usually "Darwin", on Linux it's just plain "Linux", on Windows it's "ERROR" and FreeBSD will return "FreeBSD".
More complete list of uname outputs
I'm pretty sure that there's a C equivalent for uname, so you won't need system()
IF you are on a POSIX system, you can call uname() from <sys/utsname.h>.
This obviously isn't 100% portable, but I don't think there will be any method that can grant that at runtime.
see the man page for details
Runtime isn't the time to determine this, being that without epic kludges binaries for one platform won't run on another, you should just use #ifdefs around the platform sensitive code.
The accepted answer states uname, but doesn't provide a minimal working example, so here it is for anyone interested-hope it will save you the time it took for me:
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
int main(void) {
struct utsname buffer;
if (uname(&buffer) != 0) {
perror("uname");
exit(0);
}
printf("OS: %s\n", buffer.sysname);
return 0;
}
(Possible) Output:
OS: Linux
PS: Unfortunately, this uses a POSIX header: Compilation fails due to missing file sys/utsname.h, which most probably won't work in Windows.
if (strchr(getenv("PATH"),'\\'))
puts("You may be on windows...");
Even do I agree that "Runtime isn't the time to determine this..."
Related
I am writing a cross-platform (big 3 - Linux, MAC, Windows) backup program, so I need to know if a file has been edited since last time. My plan is to save the last save time in a file and check the real situation of a folder against the data in the file to determine which files need to be backed up or updated.
I would like to avoid methods that require a lot of processing power (like diff, or counting bytes).
In this similar post, people suggested to use fstat(), but that solution would be a last resort for me because I was hoping for a cross-platform solution that can be solved with pure C. As far as I know, fstat is a (2), and in my man page it appears as (1), which (to my understanding) means that it is a system function in Linux and isn't a part of the standard C library. I have searched for fstat on windows, but could only find some android version.
Is there some other way to access file metadata? Is there some other solution to this? I am open to any suggestions and am ok if it sometimes false-flags, as long as it backs up data correctly and doesn't waste resources on backing up everything all the time.
Please help!
Thank you!
fstat is still the way to do this, but on Windows it's called _fstat. You can check for the _MSC_VER macro which will be defined if you're building with MSVC, and if so create a macro alias for fstat.
You can do the same for struct stat which MSVC calls struct _stat:
#ifdef _MSC_VER
#define fstat(fd,buf) _fstat(fd,buf)
typedef struct _stat stat_struct;
#else
typedef struct stat stat_struct;
#endif
Then you can use fstat and pass it an argument of type stat_struct for the second argument.
I have a decently sized cross platform open source application that uses this technique.
My plan is to save the last save time in a file and check the real situation of a folder against the data in the file to determine which files need to be backed up or updated.
Ok.
I was hoping for a cross-platform solution that can be solved with pure C.
If by "pure C" you mean relying on only language features and library functions defined by the C language specification, then I'm afraid you're out of luck. Pure C (in that sense) has no concept of persistent file metadata such as modification timestamps. All functions and data structures dealing with such things are extensions or third-party libraries.
You can rely on standard POSIX facilities (such as fstat()) for both Linux and Mac, but Windows does not provide that. At least, Windows does not provide it exactly. The Microsoft C library does provide some POSIX compatibility functions, but it somewhat maddeningly uses modified names for them. In particular, it offers several flavors of _fstat() (note leading underscore). With a little bit of macro glue, it should not be too hard to make your program use POSIX fstat() on Linux and Mac, and use one of the _fstat() flavors on Windows.
i was wondering if it is possible to modify a piece of C program (or other binary) while it is running ?
I wrote this small C program :
#include <stdio.h>
#include <stdint.h>
static uint32_t gcui32_val_A = 0xAABBCCDD;
int main(int argc, char *argv[]) {
uint32_t ui32_val_B = 0;
uint32_t ui32_cpt = 0;
printf("\n\n Program SHOW\n\n");
while(1) {
if(gcui32_val_A != ui32_val_B) {
printf("Value[%d] of A : %x\n",ui32_cpt,gcui32_val_A);
ui32_val_B = gcui32_val_A;
ui32_cpt++;
}
}
return 0;
}
With a Hex editor i'm able to find "0xAABBCCDD" and modify it when the program is stopped. The modification works when I relauch the program. Cool !
I would like to do this when the program s running is it possible ?
Here is a simple example to understand the phenomena and play a little with it but my true project is bigger.
I have an old DOS game called Dangerous Dave.
I'm able to modify the tiles by simply editing the binary (thanks to http://www.shikadi.net/moddingwiki/Dangerous_Dave)
I developped a small editor that do this pretty well and had fun with it.
I launch the DOS game by using DOSBOX, it works !
I would like to do this dynamically when the game is running. Is it possible ?
PS : I work under Debian 64bit
regards
I was wondering if it is possible to modify a piece of C program (or other binary) while it is running ?
Not in standard (and portable) C11. Read the n1570 specification to check. Notice that most of the time in practice, it is not the C source program (made of several translation units) which is running, but an executable result of some compiler & linker.
However, on Linux (e.g. Debian/Sid/x86-64) you could use some of the following tricks (often with function pointers):
use plugins, so design your program to accept them and define conventions about your plugins. A plugin is a shared object ELF file (some *.so) containing position-independent code (so it should be compiled with specific options). You'll use dlopen(3) & dlsym(3) to do the dynamic loading of the plugin.
use some JIT-compiling library, like GCCJIT or LLVM or libjit or asmjit.
alter your virtual address space (not recommended) manually, using mprotect(2) and mmap(2); then you could overwrite something in a code segment (you really should not do that). This might be tricky (e.g. because of ASLR) and brittle.
perhaps use debug related facilities, either with ptrace(2) or by scripting or extending the gdb debugger.
I suggest to play a bit with /proc/ (see proc(5)) and try at least to run in some terminal the following commands
cat /proc/self/maps
cat /proc/$$/maps
ls /proc/$$/fd/
(and read enough things to understand their outputs) to understand a bit more what a process "is".
So overwriting your text segment (if you really need to do that) is possible, but perhaps more tricky than what you believe !
(do you mind working for several weeks or months simply to improve some old gaming experience?)
Read also about homoiconic programming languages (try Common Lisp with SBCL), about dynamic software updating, about persistence, about application checkpointing, and about operating systems (I recommend: Operating Systems: Three Easy Pieces & OsDev wiki)
I work under Debian 64bit
I suppose you have programming skills and do know C. Then you should read ALP or some newer Linux programming book (and of course look into intro(2) & syscalls(2) & intro(3) and other man pages etc...)
BTW, in your particular case, perhaps the "OS" is DOSBOX (acting as some virtual machine). You might use strace(1) on DOSBOX (or on other commands or processes), or study its source code.
You mention games in your question. If you want to code some, consider libraries like SDL, SFML, Qt, GTK+, ....
Yes you can modify piece of code while running in C. You got to have pointer to your program memory area, and compiled pieces of code that you want to change. Naturally this is considered to be a dangerous practice, with lot of restrictions, and with many possibilities for error. However, this was practice at olden times when the memory was precious.
I'm writing a library that emits Linux kernel 4.4 errno values when things go wrong --- these are defined in a header for the program and aren't necessarily the same as the host errno values. (There's a good reason for doing this, and I can't change this part of it.) But I'm guaranteed that the environment it's running on:
can run ELF64 executables
implements the libc interface for all syscalls (i.e. I'm guaranteed that the system has a function named open with the same signature and semantics as open(2)).
I realize that in theory, the C/POSIX standards allow errno values to be whatever the implementer wants them to be, and in theory, I could compile my own kernel with whatever bizarre errno values I want. But then I would never be able to reliably use any binary that I didn't compile myself, so I'm probably going to have a bad time, and I'm not going to be surprised when things break at random.
In practice, can I count on this kind of host having the same errno values as the values defined in the kernel's errno.h? i.e. can I rely on getting sensible behavior from the host's perror if I directly set errno in my library?
Here's a very large list comparing ERRNO values from POSIX with the actual associated messages and numbers on various systems. Some differences between Linux and BSD for instance are obvious in the spreadsheet:
http://www.ioplex.com/~miallen/errcmp.html
So the answer is, maybe in practice it's fairly safe, depending on exactly what code you are looking at? For instance ENOMEM, EACCESS, are the same on all listed platforms here.
But in general no.
The names are reliable, at least the ones which are in Posix. The actual values, not. They certainly differ between Linux and *BSD, for example.
If you translate using the host's errno.h, you will be fine. Anything else is speculative.
Actually it really depends on the error. Below about 35 they are the same, except for EAGAIN which isn't so much changed but split differently. (Who gets the old number? EAGAIN or EDEADLK?)
I can think of two things that would work:
Perhaps you can just return errors that are common to Linux, OSX, and BSD.
You could compile a master include (thanks, #Chris Beck) and make some kind of hash map keyed by printable names, then return the right value at runtime.
I am porting an application(in C language) from HP-UX to Linux(icc compiler). i have a problem with pstat.h. It's there only in HP-UX but not in Linux and im getting error "pstat_getproc is undeclared". Is there any alternate solution to this? Is there any substitute for sys/pstat.h? As of now I am planning to replace that whole code with something that will work on Linux. Looking forward to your solutions.
There is no direct equivalent; the whole family of pstat functions is extremely HP/UX specific. Probably the closest equivalent is the /proc interface -- to get information on the current process, for instance, one can examine the pseudofiles in /proc/self.
You will, indeed, probably need to replace most of the code which makes use of pstat.
I know that standard C doesn't give me any ability to do anything with folders, but I would like a fairly portable and cross-platform way to access folders. At this time, all I need to do is make a folder, check if a folder exists, and possibly delete a folder. I can forsee needing to read files from a folder in the near future, but that's not a very pressing need.
Anyway, I was wondering if there was a good cross-platform C library for working with directories. In an absolute pinch I can probably roll my own to work on POSIX and Windows, but I was wondering if there were any good ones already out there. I've been considering GLib or the Apache Portable Runtime, but both of those come with a lot more stuff than I really need, and I'd like to keep this fairly lightweight. I've also considered using the internals of a popular scripting language, like Perl or Python, but that also seems like a lot of overhead just for directory functions.
If anyone has anything to add to this list that I should look into, or wants to make a good case for one of the options I've already listed, please tell me. I don't want to sound like I'm asking for code, but if you posted a simple function like int direxist(char *dirname) that returned true if the directory exists and false otherwise, just to illustrate the API for your library of choice, that would be really awesome, and I imagine not too hard. If you want to advocate using POSIX/rolling my own, do that too, because I'm a sucker for learning new stuff like this by doing it myself.
Just to make sure, I want C, not C++. I'm sure boost is good, but I'm not interested in C++ solutions.
I would jump on the APR bandwagon. It does give you a lot more than directory access, but it is the best multi-platform C library that I've used. Chances are that you will find yourself needing some of the other components of it in the future anyway, so you might as well have them handy.
The other option is to implement the POSIX API set over Win32 and just write everything in POSIX. The bonus here is that the Windows is quickly becoming the only modern OS that does not include a POSIX runtime implementation.
I've been considering GLib or the Apache Portable Runtime, but both of those come with a lot more stuff than I really need, and I'd like to keep this fairly lightweight.
It's quite probable that GLib will already be installed (on GNU/Linux, at least). The only problem is that it will add a dependency.
I've also considered using the internals of a popular scripting language, like Perl or Python, but that also seems like a lot of overhead just for directory functions.
I would rather use Python in the first place, and possibly use C for specific parts of code.
>>> def direxist(dirname):
... return os.path.isdir(dirname)
...
>>> direxist('/')
True
>>> direxist('/home')
True
>>> direxist('/home/bastien/Petites leçons de typographie.pdf')
False
About writing your own C function, it would go something like this:
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
int direxist(const char* dirname)
{
#ifdef _WIN32
/* ... */
#else
struct stat fileinfo;
int ret = -1;
if (stat(dirname, &fileinfo) == -1)
{
perror("direxist");
}
else
{
if (S_ISDIR(fileinfo.st_mode))
{
ret = 1;
}
else
{
ret = 0;
}
}
return ret;
#endif
}
int
main (void)
{
printf("%d\n", direxist("/"));
return 0;
}
I don't how to do it with Win32, so you'll to find that yourself.
However, I would strongly recommend using an external library. You don't go far with just the C library or by reinventing the wheel.
I think you should use APR or something in the same vein. Designing a POSIX API and then implement it for windows does not work well in my experience (which is quite limited I must confess).
File IO, and related semantics are just too different, so you have to design your API to deal with windows right away. There are also different constraints on what can be put in the public API. One example of such a problem is the python C API for file handling. It was clearly designed with a POSIX POV, and it is very difficult to use it on windows because of things like sharing C runtimes objects, etc...