1

I'm new to C and trying to understand why this code just return current directory file listing rather than the directory i pass to.

I used c11 standard gcc compiler

and just using ./a.out filedirectory .....

int main(int argc, char *argv[])
{

        char*args[3];
        if(argc > 1)
        {
                args[0] = "/bin/ls";
                args[1] = "-l";
                if(argv[2])
                {
                        args[2] = argv[2];
                        args[3] = NULL;
                }
                else
                {
                        args[2] = NULL;
                }

                execvp(args[0],args);

                return 0;
        }
}
Shawn Chen
  • 11
  • 2
  • Did you *carefully* read the documentation of [execvp(3)](http://man7.org/linux/man-pages/man3/execvp.3.html) and of [execve(2)](http://man7.org/linux/man-pages/man2/execve.2.html)? BTW, your question lacks a `Linux` or `Posix` tag since `execvp` is not defined in the C11 standard. Read also [*Advanced Linux Programming*](http://advancedlinuxprogramming.com/) – Basile Starynkevitch Jun 03 '17 at 05:21
  • As usual, compile with all warnings & debug info (`gcc -Wall -Wextra -g`) and **use the debugger `gdb`** (so spend several hours learning it). You may also find [strace(1)](http://man7.org/linux/man-pages/man1/strace.1.html) useful. – Basile Starynkevitch Jun 03 '17 at 05:22
  • 1
    Side note: with `char *args[3]`, accessing `args[3]` is undefined. – dhke Jun 03 '17 at 05:40
  • Thank you Basile, I'll check the documentation of execvp again. – Shawn Chen Jun 03 '17 at 07:00

1 Answers1

2

You did not tell how are your running your program myprog. Let's suppose you run it as (for example) ./myprog /tmp/.

In the C programming language (read n1570) array indexes start at 0!

Then when entering your main you have

  • argc is 2
  • argv[0] is the "./myprog" string
  • argv[1] is the "/tmp/" string
  • argv[2] is the NULL pointer (this is guaranteed by the C specification of main and implemented by crt0) since it is the main function

(In all other cases in C, arrays of pointers are not implicitly NULL terminated, but main's argv is special)

Follow with a pencil or with the gdb debugger your program source. The first if (argc > 0) succeeds but the second one if (argv[2]) fails. Then you have args[0] set to "/bin/ls", args[1] set to "-l" and args[2] set to NULL before the execvp call.

See execvp(3), execve(2) and read Advanced Linux Programming

You really should take the habit of compiling with all warnings & debug info (gcc -Wall -Wextra -g with GCC, e.g. compile yoursource.c source file into myprog executable with gcc -Wall -Wextra -g yoursource.c -o myprog) and learn how to use the debugger gdb.

BTW, your use of args[3] is undefined behavior (out of bound indexing or buffer overflow), so you should be scared, since args was declared as an array of dimension 3 (so valid indexes are only 0, 1 and 2). In your case a recent GCC would warn you.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    There is also the strange bit of logic of the nested `if..else` inside of `if (argc > 0)` (which will always be true). Instead, a single `if (argc > 1) ... else ...` could accomplish what looks to be his goal. – David C. Rankin Jun 03 '17 at 06:08