1

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!

Asfourhundred
  • 3,003
  • 2
  • 13
  • 18

1 Answers1

1

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I actually figured it out a while ago! – Asfourhundred Oct 17 '16 at 09:49
  • It is actually way simpler than I imagined. I realized that the function execvp() returns -1 whenever it fails to execute. So I just put the condition if(execvp(argv[0], argv) ==-1) printf("Error executing binary: %s", argv[0]); – Asfourhundred Oct 17 '16 at 09:52
  • 1
    You never need to check the return code form an `exec*()` function. If any of the `exec*()` family of functions returns, it is because it failed, so the condition is not necessary — simply report the error. Remember that error messages get written to `stderr`, not `stdout` — that's why it is the standard error stream. – Jonathan Leffler Oct 17 '16 at 13:51