0

Two example outputs (provided by my professor) are (these are inputted in the Linux terminal):

 ibrahim@ibrahim-latech:~$ ./prog2 .
 Current working directory: /home/ibrahim
 Executing ls . --all -l --human-readable
 total 24M
 drwxr-xr-x 74 ibrahim ibrahim 20K Oct 26 16:08 .
 drwxr-xr-x 6 root root 4.0K Apr 10 2014 ..
 -rw-r--r-- 1 ibrahim ibrahim 4.1K Sep 13 12:09 .bashrc
 drwxr-xr-x 7 ibrahim ibrahim 4.0K Oct 11 14:51 Desktop/
 ...snip...
 Exit status: 0

so the Exit status is 0 if the code works but this example:

 ibrahim@ibrahim-latech:~$ ./prog2 /root
 Current working directory: /home/ibrahim
 Executing ls /root --all -l --human-readable
 Can't chdir to /root
 Exit status: 1 

The exit status is 1 because it is false.

Here is my code:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
    pid_t pid;
    pid = fork();
    char cwd[255];
    if(pid == 0){
        printf("Current working directory: %s\n",getcwd(cwd, sizeof(cwd)));
        printf("Executing ls %s --all -l --human-readable\n",argv[1]);
        if(chdir(argv[1])!=0){
            printf("this is not a valid directory");
        }
        else{
            execl("/bin/ls","ls","--all","-l","--human-readable", NULL);
        }
    }
    else{
        wait(NULL):
        printf("Exit status:");// not sure how to put the 1 or 0 in this
    }
}

The exit status must be outputted from the parent process. I can't figure out how to get the exit status to work.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Damion Owens
  • 25
  • 1
  • 7
  • 1
    See also [Why does `wait()` set status to 256 instead of the 1 exit status of the forked process?](https://stackoverflow.com/questions/3659616/why-does-wait-set-status-to-256-instead-of-the-1-exit-status-of-the-forked-pr/3659673#3659673) and [`execvp()` doesn't return an error on an unknown command](https://stackoverflow.com/questions/26435219/execvp-doesnt-return-an-error-on-an-unknown-command/26435319#26435319). – Jonathan Leffler Oct 31 '19 at 22:14

1 Answers1

3

Transferring key information from comments into an answer.

The wait() function tells you the PID and the exit status — you just have to capture them, not ignore them. You'll need to use WIFEXITED and WEXITSTATUS (and if WIFEXITED reports false, there are other macros to use for signals and core dumps, etc).

Modifying your code:

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

#ifndef LS_PATH
#define LS_PATH "/bin/ls"
#endif

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s directory\n", argv[0]);
        return 1;
    }
    pid_t pid = fork();
    if (pid == 0)
    {
        char cwd[255];
        printf("Current working directory: %s\n", getcwd(cwd, sizeof(cwd)));
        printf("Executing 'ls -a -l' in %s\n", argv[1]);
        if (chdir(argv[1]) != 0)
        {
            fprintf(stderr, "%s: %s is not a valid directory\n", argv[0], argv[1]);
            return 1;
        }
        //execl(LS_PATH, "ls", "--all", "-l", "--human-readable", (char*) NULL);
        execl(LS_PATH, "ls", "-a", "-l", (char*) NULL);
        fprintf(stderr, "Failed to execute %s\n", LS_PATH);
        return 1;
    }
    else
    {
        int status;
        int corpse = wait(&status);
        if (corpse < 0)
            printf("Failed to wait for process %d (errno = %d)\n", (int)pid, errno);
        else if (corpse != pid)
            printf("Got corpse of process %d (status 0x%.4X) when expecting PID %d\n",
                   corpse, status, (int)pid);
        else if (WIFEXITED(status))
            printf("Process %d exited with normal status 0x%.4X (status %d = 0x%.2X)\n",
                   corpse, status, WEXITSTATUS(status), WEXITSTATUS(status));
        else if (WIFSIGNALED(status))
            printf("Process %d exited because of a signal 0x%.4X (signal %d = 0x%.2X)\n",
                   corpse, status, WTERMSIG(status), WTERMSIG(status));
        else
            printf("Process %d exited with status 0x%.4X which is %s\n",
                   corpse, status, "neither a normal exit nor the result of a signal");
    }
    return 0;
}

I work on a Mac which doesn't use GNU ls so I've made the code compile-time configurable for the location of ls and it only uses portable options (-a and -l and not the double-dash options). I've changed the messaging and detected some more errors. Like your code, this assumes fork() does not fail — it should check for an error there too.

Sample output (abbreviated) — from program es61 compiled from es61.c:

$ es61 /orthography
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /orthography
es61: /orthography is not a valid directory
Process 64463 exited with normal status 0x0100 (status 1 = 0x01)
$ es61 $PWD
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /Users/jonathanleffler/soq
total 1016
drwxr-xr-x  100 jonathanleffler  staff   3200 Oct 31 15:53 .
drwxr-xr-x+  69 jonathanleffler  staff   2208 Oct 31 15:53 ..
…
-rwxr-xr-x    1 jonathanleffler  staff   9028 Oct 31 15:53 es61
-rw-r--r--    1 jonathanleffler  staff   1806 Oct 31 15:53 es61.c
drwxr-xr-x    3 jonathanleffler  staff     96 Oct 31 15:43 es61.dSYM
drwxr-xr-x    9 jonathanleffler  staff    288 Nov  5  2018 etc
…
-rw-r--r--    1 jonathanleffler  staff    390 Nov 16  2017 makefile
…
Process 64557 exited with normal status 0x0000 (status 0 = 0x00)
$
alk
  • 69,737
  • 10
  • 105
  • 255
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278