0

In a C program, I need to find the OSTYPE during runtime, on the basis of which I will do some operations.

Here is the code

#include <stdlib.h>
#include <string.h>

int main () {
    const char * ostype = getenv("OSTYPE");
    if (strcasecmp(ostype, /* insert os name */) == 0) ... 
    return 0;
}

But getenv returns NULL (and there is segmentation fault). When I do a echo $OSTYPE in the terminal it prints darwin15 . But when I do env | grep OSTYPE nothing gets printed, which means it is not in the list of environment variables. To make it work on my local machine I can go to the .bash_profile and export the OSTYPE manually but that doesn't solve the problem if I want to run a generated executable on a new machine.

Why is OSTYPE available while running terminal, but apparently not there in the list of environment variables. How to get around this ?

abkds
  • 1,764
  • 7
  • 27
  • 43
  • yes, but that is supposed to be a UNIX, right ? https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getenv.3.html – abkds Sep 08 '16 at 02:09
  • Because bash sets it. No bash, no variable. – Ignacio Vazquez-Abrams Sep 08 '16 at 02:09
  • @iharob if I run the executable somewhere else, then I need to know the OSTYPE. – abkds Sep 08 '16 at 02:10
  • @PaulGriffiths , so that means that if OSTYPE hasn't been exported, program will not run ? (Whatever machine it is) – abkds Sep 08 '16 at 02:13
  • have you tried wrapping it in a call to `system` ? – bruceg Sep 08 '16 at 02:14
  • Stack overflow is just such a dismal community, sigh. I mean what's wrong with the question. I did my fair bit of research, found that the existing questions didn't answer my question and then I asked it. But still you get a downvote. – abkds Sep 08 '16 at 02:18
  • May be a new developer couldn't find the relevant question. If it is please provide the link, I am happy to remove my question. – abkds Sep 08 '16 at 02:19
  • 1
    @bruceg I will give it a shot. – abkds Sep 08 '16 at 02:19
  • 1
    Can you just use the output from `uname` instead? – Crowman Sep 08 '16 at 02:21
  • @bruceg I was able to do it using the `popen` function. Thanks – abkds Sep 08 '16 at 02:28
  • Not an OSX person, but suspect OSTYPE is a local and not external variable. The shell sees both locals and externals. Try "export OSTYPE" before running your program as a test. For getenv() you must ALWAYS check for NULL returns that indicate the value was not found. If you only care about the OS type, and not how you find it, look into uname(2) function. This is a POSIX thing I hope OSX supports. http://pubs.opengroup.org/onlinepubs/009695399/functions/uname.html – Gilbert Sep 08 '16 at 03:01
  • Mac OS X has an entry for `uname(3)` (but not `uname(2)`). It ends up being much the same; it just means BSD has a different system call that provides the information (`sysctl(3)` judging from the `uname()` manual page), and uses a `uname()` function to map the data from the alternative to meet the POSIX requirements. – Jonathan Leffler Sep 08 '16 at 06:48

1 Answers1

1

For the crash, you should check if the return was NULL or not before using it in strcmp or any function. From man 3 getenv:

The getenv() function returns a pointer to the value in the environment, or NULL if there is no match.

If you're at POSIX (most Unix's and somehow all Linux's), I agree with Paul's comment on uname.

But actually you can check for OSTYPE at compile time with precompiler (with #ifdef's), here's a similar question on so: Determine OS during runtime

Edit: uname

Good point Jonathan. man 2 uname on my linux tells how to use (and begin POSIX, macos has the same header, too):

SYNOPSIS

   #include <sys/utsname.h>

   int uname(struct utsname *buf);

DESCRIPTION uname() returns system information in the structure pointed to by buf. The utsname struct is defined in :

       struct utsname {
           char sysname[];    /* Operating system name (e.g., "Linux") */
           char nodename[];   /* Name within "some implementation-defined
                                 network" */
           char release[];    /* Operating system release (e.g., "2.6.28") */
           char version[];    /* Operating system version */
           char machine[];    /* Hardware identifier */
       #ifdef _GNU_SOURCE
           char domainname[]; /* NIS or YP domain name */
       #endif
       };
Community
  • 1
  • 1
AlbusMPiroglu
  • 645
  • 3
  • 13
  • The OP may be wanting to tell the difference between `darwin14` and `darwin15` at runtime, after the code was compiled on a platform that means it could work with either. It isn't clear. – Jonathan Leffler Sep 08 '16 at 06:45