2

I am writing own shell-like program and I keep getting errors on exec* function call.

Here is source code of core processes.c:

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

#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/uio.h>

#define BUFSIZE 128
#define EXIT_STR "exit"

int main(int argc, char ** argv) {
    const char *prompt = "> ";
    char buffer[BUFSIZE];
    int bytes_read;
    int status;
    pid_t child_p;

    while(1) {
        printf("%s", prompt);
        fflush(stdout);
        bytes_read = read(0, buffer, BUFSIZE);
        buffer[bytes_read-1] = '\0';

        if(strncmp(EXIT_STR, buffer, bytes_read) == 0)
            exit(0);

        if((child_p = fork()) == 0) {
            printf("[*] %d executing: %s\n", getpid(), buffer);
            execlp(buffer, buffer);
            printf("[*] %d got error on execlp\n", getpid());
            exit(1);
        } else {
            waitpid(child_p, &status, 0);
            printf("[*] child returned: %d\n", status);
        }
    }
}

I have also simple other.c program for testing:

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

int main(int argc, char **argv){
    printf("Hello. I am %s with pid: %d\n", argv[0], getpid());
    exit(0);
}

I use llvm on MacOS High Sierra for compilation:

 $  llvm-gcc processes.c -o processes -Wall
 $  ./processes
> other
[*] 6040 executing: other
[*] 6040 got error on execl
[*] child returned: 256
> ls
[*] 6041 executing: ls
[*] 6041 got error on execl
[*] child returned: 256
> exit

What am I missing?

9
  • 4
    Well, for one thing, you must terminate the argument list to execlp() with a null pointer of type char *. Commented Jan 3, 2018 at 18:50
  • What’s in buffer? Unless it is a single word command like ls or who, it won’t work. Note that a newline would screw things up. Shells take care of newlines for you. When you write your own shell, you have to take care of them. Commented Jan 3, 2018 at 18:50
  • 1
    Note also that outputting error messages via perror() is usually more informative than is printing return codes. Commented Jan 3, 2018 at 18:51
  • 1
    No, @gonczor, that's not at all the same thing. You do need to terminate each argument string with a null terminator, but what I'm talking about is adding (char *) NULL as a whole additional argument. Commented Jan 3, 2018 at 18:52
  • 2
    @JohnBollinger it helped. I'll be happy to accept it as an answer. Commented Jan 3, 2018 at 18:54

1 Answer 1

1

Together, the second argument argument to execlp() and any subsequent arguments correspond to the strings provided to the new program's main() function in its argument vector. They must all be pointers to null-terminated C strings, except that the end of the list must be marked by a null pointer of type char *. For example:

execlp(buffer, buffer, (char *) NULL);

This is a documented requirement for the arguments to this function, and your program mail fail if you do not satisfy it. If you wish, you may rationalize it as providing a means for the system to count the elements of the argument vector, so as to pass that number to the new main(). You may also consider that the argument vector itself is documented to be terminated by a null pointer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.