Search code examples
cmessageexecvpsigintsigaction

C - Replace "No such file or directory" message


I'm trying to make a shell that whenever it can't execute a command it says "Error executing binary: -nameOfBinary-". But the thing is that it always gives me the message "No such file or directory". Heres part of my code:

void handle_SIGINT() {
  write(STDOUT_FILENO,line,strlen(line));
  printf("\n");
  struct sigaction handler;
  handler.sa_handler = handle_SIGINT;
  sigaction(SIGINT, &handler, NULL);
}

void runcommand(char* argv[]) {
  int p =fork();
  if(p==0) {
    struct sigaction handler;
    handler.sa_handler = SIG_IGN;
    sigaction(SIGINT, &handler, NULL);
    execvp(argv[0],argv);
    perror("Error executing binary");
    exit(1);
  } else {
    wait(NULL);
  }

}

With the code as it is it always gives me the message "Error executing binary: No such file or directory" which is close to what I want! How can I fix it? Thanks in advance!


Solution

  • The function perror() prints the string you supply, a colon and a space, and then adds the string corresponding to the current value of errno (ENOENT or 'No such file or directory' in your case) and a newline. If that's not the message you want, you have to write and call your own error reporting function.

    You can cheat and simply use:

    perror(argv[0]);
    

    which will give you something like:

    name-of-binary: No such file or directory
    

    or you can write your own:

    #include <errno.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void err_syserr(const char *fmt, ...)
    {
        int errnum = errno;
        va_list args;
        va_start(args, fmt);
        vfprintf(stderr, fmt, args);
        if (errnum != 0)
            fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
        putc('\n', stderr);
        exit(EXIT_FAILURE);
    }
    

    and then call it:

    err_syserr("Error executing binary: %s: ", argv[0]);
    

    Since the function calls exit(), it could be decorated with _Noreturn to indicate that it does not return, and you don't need the exit(1); in the calling code.

    There are those who argue that printing the error number as well as the message is A Bad Thing™ but (as you can guess) I don't agree for most of the work I do. It might matter in web-facing code, but this isn't likely to be web-facing code.