Home > Software design >  Exit status of process not good in case of error
Exit status of process not good in case of error

Time:11-27

I have a problem regarding of mini program that will return me the exit status of my child process in case of error occuring during execve.

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




int main ()
{
    char *argv[] = {"ls",NULL};
    char *envp[] = {NULL};
    int status;
    int pid;
    int err;
    pid = fork();
    if (pid == 0)
    {
        execve("/usr/bin/lds", argv, envp);
        perror("error");
        
    }
    else
    {
    waitpid(pid, &status, 0);
    printf("%d\n", status);
    if (WIFEXITED(status))
        err = WEXITSTATUS(status);
    exit(status);
    }
}

The above code is just demo to make me understand how process exit status work, the problem is when when I put a wrong path such /usr/bin/lds the status code print is 0 while an error occured in my child process, while when a command is not found in bash the status code sent back is 127 my question is how to make it return 127 as bash does when a bad command is entered ?

CodePudding user response:

exec(2) family functions return -1 on failure. So you can't get the shell's return code.

Your code current returns 0 for child's status because you're not returning anything on error and thus the child process returns 0 exiting main.

You could instead do:

if (pid == 0)
{
    int r = execve("/usr/bin/dls", argv, envp);
    perror("error");
    exit(r);
}

You can also inspect errno and return specific values from the child to parent:

if (pid == 0)
{
    int r = execve("/usr/bin/dls", argv, envp);
    exit(errno);
}

And the parent can inspect child's return code and print appropriate message or return value.

Alternatively you can map the errno values returned by execve to shell's return values and then return those values yourself so that it matches shell's return value.

if (pid == 0)
{
    int r = execve("/usr/bin/dls", argv, envp);
    if (errno == ENOENT)
        exit(127);
    else if (errno == ...)
    /* and so on */
}

This is more work for little benefit. Typically you only need to know when exec failed and not exactly what shell returned on failure.

CodePudding user response:

The exit status sent from a program to the host environment is:

  • If the program calls exit, _Exit, or quickexit, the value passed to that routine.
  • If the program calls abort, an implementation-defined unsuccessful termination.
  • If the initial call to main executes return, the value given in the return statement.
  • If execution of the initial call to main flows to its terminating }, zero.

waitpid does none of these and does not affect the program exit status. To send 127 for the exit status to the host environment, you should execute exit(127) or return 127; after perror("error"); or at the end of main.

  • Related