Capturing a Program’s Return Value in Linux

As I wrote in last week’s Lesson, the system() function can’t be used in Linux to obtain a program’s return value. Instead, you must use one of the execl() family of functions. Further, this function must be spawned as a child process. This task involves using the fork() and wait() functions.

The fork() function and the the execl() function have already been covered on this blog. The wait() function is defined in the sys/wait.h header file. Here is the man page format:

pid_t wait(int *stat_loc);

The function consumes the address of an integer value *stat_loc and returns a pid_t value, a process ID.

What the wait() function does is to wait (duh) for a child process to complete. Information about the child process is obtained from the integer variable referenced as the function’s argument. Various macros, defined in sys/wait.h, assist you in divining the wisdom packed into the referenced integer.

To obtain the return value from another program run as a child process your code must fork. The child fork (pid zero) contains the execl() function to “execute and leave” another program. The parent fork contains the wait() function, which suspends execution until the child process completes its task.

2022_02_12-Lesson.c

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    pid_t p;
    int stat;

    /* split this program into two processes */
    p = fork();
    
    if( p==0 )        /* child process is running */
    {
        execl("twelve",NULL);
    }
    else            /* parent process is running */
    {
        wait(&stat);                /* wait for the child */
        if( WIFEXITED(stat))        /* examine exit status */
            printf("Child process exit status = %d\n",WEXITSTATUS(stat));
        else
            printf("Unable to locate exit status\n");
    }

    return(0);
}

The fork() function at Line 11 spawns a second version of the program. The process ID is returned in variable p.

The if decision at Line 13 uses variable p to determine whether the child or parent is running. For p==0, the child is running and the twelve program is executed. It’s assumed that this program is in the same directory as the current program. Refer to last week’s Lesson for the twelve program’s code (Github).

The parent process is handled by the else part of the decision. The wait() function pauses execution until the child exits. The wait() function’s argument, stat, stores details about the child process’s termination.

The WIFEXITED macro examines the stat variable and returns TRUE when the child process has an exit status. Macro WEXITSTATUS extracts the chid program’s exit status from the stat variable, which is output.

Here’s a sample run:

I return the value 12 to the operating system
Child process exit status = 12

And it works.

This method is the only way I’ve found (so far) to fetch and identify a return value from another program run in Linux: You must spawn a child process, wait for it to finish, then examine the wait() function’s argument. The setup is clunkier than using the system() function in Windows, but it works.

Leave a Reply