lase
lase

Reputation: 2634

execv() quirks concerning arguments

I'm trying to output the results of 'ps' for an assignment, but I've ran into some slight quirks that I'd like to figure out.

This works correctly, and displays ps's output in the shell:

//Create "ps -u laser"
int pid_ps = fork();
char *argv[1] = {"-u laser"};
if (pid_ps == 0) {
   execv("/bin/ps", argv);
}

Now, this is the format that was given in my slides, but just gives the "usage:" and "format is one or more of:" notifications for ps when it's run:

//Create "ps -u laser"
int pid_ps = fork();
char *argv[2] = {"-u", "laser"};
if (pid_ps == 0) {
   execv("/bin/ps", argv);
}

I also tried putting 0 and NULL on the end of the array, which was suggested in other answers, but no luck.

I'm probably overlooking something minor, but I'm not too familiar with c. Any insight is appreciated.

Upvotes: 2

Views: 11734

Answers (2)

uzluisf
uzluisf

Reputation: 3076

From the Library Functions Manual for exec (emphasis mine):

The char *const argv[] argument is an array of pointers to null- terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

Thus if you want to run ps -u laser using execv, argv could look like this:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    pid_t pid = fork();
    if (pid == 0) {
        char *const argv[] = {
            "ps",         // executable's filename
            "-u",         // flag
            "laser",      // argument
            (char *) NULL // mark the end
        };

        execv(
            "/bin/ps", // executable
            argv
        );
    }
    
    wait(NULL);
}

Now, if you don't care about argv's first argument being the executable's path, you can do the following instead, as Erik has done here:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    pid_t pid = fork();
    if (pid == 0) {
        char *const argv[] = {
            "/bin/ps",    // executable/filename
            "-u",         // flag
            "laser",      // argument
            (char *) NULL // mark the end
        };

        execv(argv[0], argv);
    }

    wait(NULL);
}

Upvotes: 0

Erik
Erik

Reputation: 91270

Use char *argv[] = {"/bin/ps", "-u", "laser", 0}; - the first argument is the executable name.

EDIT: Sample.

int pid_ps = fork();
if (pid_ps == 0) {
  char *argv[] = {"/bin/ps", "-u", "laser", 0};
  execv("/bin/ps", argv);
}

The above snippet is tested and working.

Upvotes: 12

Related Questions