Why does execve sometimes set errno and not print the error message?

214 views Asked by At

Yes, I have read the homework policy here.

Notice here how, for ls ls it prints the error message but, for cd test (test does not exist), it sets the errno to 2 (no such file or directory) but does not print the error message. Why is there this difference in behavior?

I am trying to implement a simple shell using child processes. My operating system is Ubuntu Desktop 22lts. execve seems to sometimes allow the program to print its error message but other times will just set an errno.

Here is the code which runs in the child process.

            int val;
            if(strcmp(tokens[0], "cd") == 0){
                val = execve("/bin/cd", tokens, NULL);

            }
            if(strcmp(tokens[0], "ls") == 0){
                val = execve("/bin/ls", tokens , NULL);

            }
            if(strcmp(tokens[0], "cat") == 0){
                val = execve("/bin/cat", tokens, NULL);

            }
            if(strcmp(tokens[0], "echo") == 0){
                val = execve("/bin/echo", tokens, NULL);

            }
            if(strcmp(tokens[0], "sleep") == 0){
                val = execve("/bin/sleep", tokens, NULL);

            }
            if(strcmp(tokens[0], "date") == 0){
                val = execve("/bin/date", tokens, NULL);

            }
            if(strcmp(tokens[0], "pwd") == 0){
                val = execve("/bin/pwd", tokens, NULL);

            }
            if(val == -1){
                int err = errno;
                printf("%d", errno);
                printf("Incorrect command.\n");
            }

Here is the outputenter image description here

1

There are 1 answers

0
John Bollinger On

execve seems to sometimes allow the program to print its error message but other times will just set an errno.

execve() does not particularly constrain the behavior of the programs it starts. After all, it is involved in starting almost every program that ever starts.

What you're seeing is a difference between execve() itself failing on one hand, and execve() succeeding, but the resulting program failing on the other. If execve() succeeds in loading and starting a new program image then its job is done. It does not return, in part because there is nothing left to return to. The new image has replaced the one in which execve() was called. Any error reporting that is performed will be performed by the new process, which is what you see for ls ls.

Only if execve() fails does it return. This is most often because the first argument does not identify an existing file that execve() is capable of launching. When it fails, yes, it sets errno. This is what you observe in the cd case -- not because test does not exist, but because /bin/cd does not.

By the way, you might want to look into perror(). It will print a more informative message than the raw errno value.