How can I determine if the operating system is POSIX in C?

前端 未结 3 724
谎友^
谎友^ 2021-01-31 09:39

Related questions
How can I detect the operating system in C/C++?

How can I find out what operating system I am runni

相关标签:
3条回答
  • 2021-01-31 09:54

    Here is what I ended up with:

    #include <stdio.h>
    /*
    NAME
        basename -- return pointer to last component of a pathname
    
    Distribution: This function is in the public domain. 
    
    Origin of function:
    http://www.koders.com/c/fidEB79B7607A210C3BB7B813E793465F9D469AE912.aspx
    
    
    SYNOPSIS
        char *basename (const char *name)
    
    DESCRIPTION
        Given a pointer to a string containing a typical pathname
        (/usr/src/cmd/ls/ls.c for example), returns a pointer to the
        last component of the pathname ("ls.c" in this case).
    
    Restrictions:
        Presumes a UNIX or DOS/Windows style path with UNIX or DOS/Windows 
        style separators.
    */
    
    /*
    NAME:
        basename: 
    
    Function:
        return pointer to last component of a pathname
    
    Distribution: 
        This function is in the public domain. 
    
    Origin of function:
        http://www.koders.com/c/fidEB79B7607A210C3BB7B813E793465F9D469AE912.aspx
    
    
    SYNOPSIS:
        char *basename (const char *name)
    
    DESCRIPTION:
        Given a pointer to a string containing a typical pathname
        (/usr/src/cmd/ls/ls.c for example), returns a pointer to the
        last component of the pathname ("ls.c" in this case).
    
    Restrictions:
        Presumes a UNIX or DOS/Windows style path with UNIX or
        DOS/Windows style separators.
        Windows volumes are only a-zA-Z.
        The original code suggests ISALPHA.
    
    */
    
    char * basename (const char *name)
    {
    const char *base;
    // predefined OS symbols
    // http://sourceforge.net/apps/mediawiki/predef/index.php?title=Operating_Systems#UNIX_Environment
    
    #ifndef DIR_SEPARATOR
    #  define DIR_SEPARATOR '/'
    #endif
    
    #ifndef DIR_SEPARATOR_2 
    #  define DIR_SEPARATOR_2 '\\'
    #endif
    
    // Check if we are running Unix like os
    //   else assume Windows.  Note if we guess wrong, it's not
    //   so bad because Windows includes the Unix separator.
    #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
    #  define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
    #else
    #  define IS_DIR_SEPARATOR(ch) \
    (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
    /* Skip over the disk name in MSDOS pathnames. */
    if (isalpha(name[0]) && name[1] == ':') 
        name += 2;
    #endif
    
    
    for (base = name; *name; name++)
        {
        if (IS_DIR_SEPARATOR (*name))
            {
            base = name + 1;
            }
        }
    return (char *) base;
    }
    
    
    
    
    int main (int argc, const char * argv[]) {
        /* Return the basename of a pathname. */
    
    
    #define S1 "/usr/src/cmd/ls/ls.c"
    #define S2 "/usr/src/cmd/ls/abc"
    #define S3 "a:/usr/src/cmd/ls/def"
    #define S4 "ghi"
    #define S5 "jkl.txt"
    #define S6 "d:\\usr\\src\\cmd\\mno.txt"
    #define S7 "d:pqm.txt"
    
    printf(S1 "  \t is %s\n",basename(S1));
    printf(S2 "  \t is %s\n",basename(S2));
    printf(S3 "  \t is %s\n",basename(S3));
    printf(S4 "  \t is %s\n",basename(S4));
    printf(S5 "  \t is %s\n",basename(S5));
    printf(S6 "  \t is %s\n",basename(S6));
    printf(S7 "  \t is %s\n",basename(S7));
        return 0;
    

    }

    0 讨论(0)
  • 2021-01-31 09:59

    The Single UNIX Specification requires the existence of unistd.h, which can tell you the POSIX version (via the _POSIX_VERSION macro).

    But how can you include unistd.h if you don't know yet that you are in fact compiling on a UNIX?

    That is where this GCC document comes handy. According to it, testing for the presence, or evaluation-to-true of __unix__ should tell you that the system is a UNIX. So:

    #ifdef __unix__
    /* Yes it is a UNIX because __unix__ is defined.  */
    
    #include <unistd.h>
    
    /* You can find out the version with _POSIX_VERSION.
    ..
    ..  */
    
    #endif
    

    __unix__ is not defined on Mac OS X, so to account for that, you could instead do:

    #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
    

    To get a list of system specific predefined macros on your system, you may execute:

    cpp -dM /dev/null
    

    For example, my GNU/Linux system also additionally defines __linux__ and __gnu_linux__ apart from __unix__ and a bunch of other stuff.


    Another useful document that you must look at is this Wiki.

    It goes on to present a way of detecting the presence and version of POSIX in a way similar to the one I described above.


    EDIT: Since you really want to do all this because you want to decide which directory separator to use, look at this URL. It says:

    Note File I/O functions in the Windows API convert "/" to "\" as part of converting the name to an NT-style name, except when using the "\?\" prefix as detailed in the following sections.

    I don't program on Windows, or know much anything about it, so I can't say I've banked on this.

    0 讨论(0)
  • 2021-01-31 10:07

    It is possible to solve your problem using autoconf tool to discover the presence of unistd.h and then would add a #define HAVE_UNISTD_H 1 line in a generated config.h if unistd.h was found, but I find that autoconf is a little hard to use, and is very out-dated.

    If by any chance you are using cmake, you can solve it the same way. You could create a config.h.in containing something like this:

    #ifndef CONFIG_H
    #define CONFIG_H
    
    #cmakedefine HAVE_UNISTD_H 1
    
    #endif
    

    And your project's CMakeLists.txt would look like this:

    project(MyApp)
    
    include(CheckIncludeFiles)
    check_include_file("unistd.h" HAVE_UNISTD_H)
    
    configure_file(config.h.in config.h @ONLY)
    
    add_executable(${PROJECT_NAME} main.c)
    

    and then to generate from the command line:

    cmake . -G"Unix Makefiles"
    

    or generate Xcode project (OSX only):

    cmake . -G"Xcode"
    

    or generate a visual studio 2013 solution project (Windows only):

    cmake . -G"Visual Studio 12 2013 Win64"
    

    cmake generators = epic win

    If your operating system is POSIX, then your generated config.h should look like this:

    #ifndef CONFIG_H
    #define CONFIG_H
    
    #define HAVE_UNISTD_H 1
    
    #endif
    

    Otherwise, it will look like that:

    #ifndef CONFIG_H
    #define CONFIG_H
    
    /* #undef HAVE_UNISTD_H */
    
    #endif
    

    And then you are free to your your trusted generated config.h :

    #include "config.h"
    
    #if HAVE_UNISTD_H
    #   include <unistd.h>
    #endif
    
    int main (int argc, const char * argv[])
    {
    #if defined(_POSIX_VERSION)
         /* POSIX code here */
    #else
         /* non-POSIX code here */
    #endif
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题