Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unix C - Portable WEXITSTATUS

I'm trying to get the exit code of a subprocess. On Linux and FreeBSD I can go like so:

[0] [ishpeck@kiyoshi /tmp]$ uname
FreeBSD
[0] [ishpeck@kiyoshi /tmp]$ cat tinker.c 
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    FILE *proc = popen("ls", "r");
    printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
    return 0;
}
[0] [ishpeck@kiyoshi /tmp]$ gcc tinker.c -o tinker
[0] [ishpeck@kiyoshi /tmp]$ ./tinker
Exit code: 0
[0] [ishpeck@kiyoshi /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h 
#define WEXITSTATUS(x)  (_W_INT(x) >> 8)

However, on OpenBSD, I get complaints from the compiler...

[0] [ishpeck@ishberk-00 /tmp]$ uname   
OpenBSD
[0] [ishpeck@ishberk-00 /tmp]$ cat tinker.c                                    
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    FILE *proc = popen("ls", "r");
    printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
    return 0;
}
[0] [ishpeck@ishberk-00 /tmp]$ gcc tinker.c -o tinker                          
tinker.c: In function 'main':
tinker.c:7: error: lvalue required as unary '&' operand
[1] [ishpeck@ishberk-00 /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h        
#define WEXITSTATUS(x)  (int)(((unsigned)_W_INT(x) >> 8) & 0xff)

I don't really care how it's done, I just need the exit code.

This leads me to believe that I would also have this problem on Mac: http://web.archiveorange.com/archive/v/8XiUWJBLMIKYSCRJnZK5#F4GgyRGRAgSCEG1

Is there a more portable way to use the WEXITSTATUS macro? Or is there a more portable alternative?

like image 280
Ishpeck Avatar asked Dec 02 '12 22:12

Ishpeck


People also ask

What is Wexitstatus in C?

This macro queries the child termination status provided by the wait and waitpid functions. If the WIFEXITED macro indicates that the child process exited normally, the WEXITSTATUS macro returns the exit code specified by the child process.

Which header file has to be included to use the Wexitstatus?

The simple answer is "sys/types. h is a fundamental header and contains many types required by other headers".


1 Answers

OpenBSD's implementation of WEXITSTATUS uses the address-of operator (unary &) on its argument, effectively requiring that its argument have storage. You are calling it with the return value of a function, which doesn't have storage, so the compiler complains.

It is unclear whether OpenBSD's WEXITSTATUS is POSIX-compliant, but the problem can be easily worked around by assigning the return value of pclose() to a variable:

    int status = pclose(proc);
    printf("Exit code: %d\n", WEXITSTATUS(status));
like image 115
user4815162342 Avatar answered Oct 30 '22 23:10

user4815162342