0

I wrote a program to use execl and I want to have the same functionality but instead use execv.

here is my program from execl:

    #include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
  int pid, status,waitPid, childPid;

     pid = fork (); / Duplicate /
     if (pid == 0 && pid != -1) / Branch based on return value from fork () /
     {
       childPid = getpid();
       printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
       execl("/bin/cat","cat","-b","-t","-v",argv[1],(char*)NULL);
   }
     else
   {
     printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
     waitPid = wait(childPid,&status,0); / Wait for PID 0 (child) to finish . /
   }
   return 1; 
}

I then tried modifying it as such in order to use execv instead, but I could not get it to work (as in it would say no such file or directory found)

You call the program with ./ProgramName testfile.txt

Here is my attempting at execv:

#include <stdio.h>
#include <unistd.h>

int main ()
{
  int pid, status,waitPid, childPid;
  char *cmd_str = "cat/bin";
  char *argv[] = {cmd_str, "cat","-b","-t","-v", NULL };
     pid = fork (); / Duplicate /
     if (pid == 0 && pid != -1) / Branch based on return value from fork () /
     {
       childPid = getpid();
       printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
       execv(cmd_str,argv);
   }
     else
   {
     printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
     waitPid = wait(childPid,&status,0); / Wait for PID 0 (child) to finish . /
   }
   return 1; 
}

Any help would be huge, have been stuck on this for quite a while now. Thanks!

Lain
  • 2,166
  • 4
  • 23
  • 47
  • 3
    `cat/bin` is not `/bin/cat` or `/usr/bin/cat`. Where are you getting it from? – Charles Duffy Feb 03 '15 at 23:13
  • Also, if you're putting `cmd_str` at the top of your argv list, you probably shouldn't _also_ have a bare `cat` in that list. – Charles Duffy Feb 03 '15 at 23:15
  • Well the first code was given to me, I beleive it is since cat is inside of the bin folder. First code works fine when it is run. when I try using bin/cat on 2nd one tho it doesnt work at all. – Lain Feb 03 '15 at 23:16
  • `if (pid == 0 && pid != -1)` makes no sense. Consider the three cases. Case 1) `pid==0` the first test passes, and the second test is meaningless since the first test already guarantees that `pid != -1`. Case 2) `pid == -1` the first test fails, the second test is skipped due to [short circuit evaluation](http://en.wikipedia.org/wiki/Short-circuit_evaluation). Case 3) `pid == N` where N is any number besides 0 or -1. The first test fails, the second test is skipped. – user3386109 Feb 03 '15 at 23:25
  • Yes lol I relized that, but as I said I was given that code, I was also confused why they possibly would do that:D – Lain Feb 03 '15 at 23:28
  • @CharlesDuffy Ya I missed the cat/bin and /bin/cat I changed it and it runs but it just sits and waits for unput now. – Lain Feb 03 '15 at 23:33
  • @Lain, of course `cat` will sit and wait for input. That's what it does if you don't give it any filenames on its command line. – Charles Duffy Feb 03 '15 at 23:35
  • @CharlesDuffy but I DO give it a file. I run it as such ./Program Test.txt – Lain Feb 03 '15 at 23:36
  • @Lain, but where do you put that filename into your argv array? It's on your program's command line, but not on cat's command line. – Charles Duffy Feb 03 '15 at 23:37
  • ...you'll see that @InnocentBystander has fixed this in their answer, if you take a closer look at it. – Charles Duffy Feb 03 '15 at 23:39

1 Answers1

4

You have a few errors in the code, which I marked down:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])     // <-- missing argc/argv
{
    int pid, status,waitPid, childPid;
    char *cmd_str = "/bin/cat";      // <-- copy/pasta error
    char *args[] = { "cat", "-b", "-t", "-v", argv[1], NULL }; // <-- renamed to args and added argv[1]
    pid = fork (); // Duplicate /
    if (pid == 0) // Branch based on return value from fork () /
    {
        childPid = getpid();
        printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
        execv(cmd_str,args);         // <-- renamed to args
    }
    else
    {
        printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
        waitPid = wait(childPid,&status,0); // Wait for PID 0 (child) to finish . /
    }
    return 1; 
}
  • Tried this after reading charles comment. This makes it so when I run the program it waits for input after doing the print lines for pid (as in it doesnt display the file information) – Lain Feb 03 '15 at 23:21
  • Plus Uno. You beat me to it. Only remaining issue is that `argc` should be checked to verify that `argv[1]` is actually valid. – user3386109 Feb 03 '15 at 23:39
  • @user3386109, can it ever have an invalid value other than NUL? If we were taking `argv[2]`, it'd be more of a risk. – Charles Duffy Feb 03 '15 at 23:40
  • This solved it, thank you so much. I was missing the thing in main in the parameters, thank you so much – Lain Feb 03 '15 at 23:40
  • 1
    @all, I omitted all error checking. Eg, result of `fork` should also be checked for -1, etc – Super-intelligent Shade Feb 03 '15 at 23:44
  • @CharlesDuffy In this program, NULL is a bad choice since `cat` will then wait on `stdin`, but error checking omitted... so it's just a comment for OP to think about. – user3386109 Feb 03 '15 at 23:49
  • @user3386109, true, that. :) – Charles Duffy Feb 03 '15 at 23:54