0

I encounter a question while I am reading a textbook - Unix System Programming

How big is the argument array passed as the second argument to execvp when you execute execcmd of Program 3.5 with the following command line?

execcmd ls -l *.c

Answer: The answer depends on the number of .c files in the current directory because the shell expands *.c before passing the command line to execcmd.

Program 3.5:

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "restart.h"
int main(int argc, char *argv[]) {
   pid_t childpid;
   if (argc < 2){     /* check for valid number of command-line arguments */
      fprintf (stderr, "Usage: %s command arg1 arg2 ...\n", argv[0]);
      return 1;
   }
   childpid = fork();
   if (childpid == -1) {
      perror("Failed to fork");
      return 1; 
   }
   if (childpid == 0) {
      execvp(argv[1], &argv[1]);
      perror("Child failed to execvp the command");
      return 1;
   }
   if (childpid != r_wait(NULL)) {
      perror("Parent failed to wait");
      return 1;
   }
   return 0;
}

Why is the size of argument array passed depending on the number of .c files in the current directory? Isn't it the argument array just something like

argv[0] = "execcmd";
argv[1] = "ls";
argv[2] = "-l";
argv[3] = "*.c";
argv[4] = NULL;

Update: Find a link explains pretty well about the shell expansion. May useful for someone who see this post later also do not understand shell expansion. Description about shell expansion

David Foerster
  • 1,461
  • 1
  • 14
  • 23
user5574376
  • 371
  • 1
  • 5
  • 12
  • 1
    The command shell first expands `*.c` depending on the contents of the current working directory. The resulting list of file names replaces `*.c` in the argument list. The expanded argument list is then passed to the application program as `argv`. It never sees the `*.c` as an argument. From its perspective, it is indistinguishable from a command line in which the user manually typed all of the file names. – Tom Karzes Feb 04 '16 at 03:59
  • @TomKarzes Thanks, I get it now :) – user5574376 Feb 04 '16 at 04:06

1 Answers1

1

No, because the shell does the wild card expansion. It finds files in the directory that match the expression, so for instance you can use "echo *.c" to discover what the shell would match. Then it lists out, every filename matching *.c on the exec call or if none *.c which is likely to result in an error message about file not found.

It is more powerful that the shell does the expansion, the same file wildcarding is immediately available for all programs, like cat, echo, ls, cc.

Rob11311
  • 1,396
  • 8
  • 10
  • So command line argument is not stored into an array as a string? – user5574376 Feb 04 '16 at 03:48
  • this is why you find questions on how to prevent it being 'nice' http://stackoverflow.com/questions/11456403/stop-shell-wildcard-character-expansion – pm100 Feb 04 '16 at 03:49
  • @pm100 Oh,ok, I get it now. This link explains pretty well. Maybe for someone who also don't understand shell expansion it is a good reference. [link](http://linuxcommand.org/lc3_lts0080.php) – user5574376 Feb 04 '16 at 03:59
  • Well USP calls it "shell expansion" because it's the shell that does it. The Robin's book explains a lot of stuff pretty well. – Rob11311 Feb 04 '16 at 11:01