0

The following code successfully lists the contents of current directory on Ubuntu bash and MacOS bash.

int main() {
    char* args[3];
    args[0] = "ls";
    args[1] = NULL;
    args[2] = NULL;
    execvp(args[0], args);
    return 0;
}

The following code doesn't print anything on Ubuntu bash but prints ls is /bin/ls on MacOS bash.

int main() {
    //pid_t pid = fork();
    char * args[3];
    args[0] = "type";
    args[1] = "ls";
    args[2] = NULL;
    //if (!pid) 
    execvp(args[0], args);
    return 0;
}

When I run type on Ubuntu bash directly, it prints ls is hashed (/bin/ls).

The difference is that type is a bash internal command while ls is not. But why does bash on Ubuntu behave differently from that on MacOS?

Ubuntu bash version: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

MacOS bash version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

Judging purely by version numbers (which may be an incorrect thing to do), older version prints output correctly while newer version doesn't?

John Elaine
  • 359
  • 5
  • 22
  • What is your [`PATH`](https://en.wikipedia.org/wiki/PATH_(variable))? It probably is different on MacOSX. Or the directories there are not the same. Perhaps MacOSX has some `/usr/bin/type` thing but Ubuntu has not any such stuff – Basile Starynkevitch Sep 20 '18 at 06:04

2 Answers2

4

You forgot to test against failure of execvp. Try at least to code:

if (execvp(args[0], args)) {
   fprintf(stderr, "execvp %s failed: %s\n",
           args[0], strerror(errno));
   exit(EXIT_FAILURE);
} 

Probably on your Ubuntu execvp of type fails. Perhaps MacOSX has some /usr/bin/type or whatever is found in your PATH.

Read carefully the documentation of execvp(3) on both systems. Consider also using strace(1) on Linux to understand what is going on (you can find a similar thing for MacOSX).

Notice that execvp works only on executable files (not on shell builtin commands)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    execvp type failed: No such file or directory. You are right: MacOS gives `/usr/bin/type` when I run `whereis type` while Ubuntu gives `type:`. – John Elaine Sep 20 '18 at 06:21
  • So is there any way to execute `type` on Ubuntu from a C program? – John Elaine Sep 20 '18 at 06:24
  • 2
    You can run `bash -c 'type %'` but that's obviously specific to your shell. (So in fact is `/usr/bin/type` on MacOS; it runs `/bin/sh` and executes `builtin type ${1+"$@"}`.) – tripleee Sep 20 '18 at 07:17
1

There is no bash in your question. That is to say, nothing in the execution of that program has anything to do with bash.

execvp is, effectively, a system call which has the effect (if it succeeds, which should not be taken for granted) of replacing the current execution environment with a new process image, loading the executable from the file indicated as the first argument. The OS neither needs or seeks assistance from bash to execute the program.

If you want to use bash, you need to ask the OS to run bash. This might be useful if you want to run a bash built-in command:

char* args[] = { "bash", "-c", "type ls", 0};
execvp(args[0], args);

But since you are not invoking bash, you rely on the existence of an external command utility named type. And it is the existence or not of that utility which leads to the different behaviour. It has nothing to do with bash or any other shell.

rici
  • 234,347
  • 28
  • 237
  • 341