0

we were given an assignment that would take in two commands from the terminal and pipe the first one into the second. I believe I have the structure of the code correct, however, when trying to compile it complains that my initial char *cmd is not a valid statement. Why is this happening? I'm confused, any assistance would be appreciated.

Code:

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

void main(int argc, char *argv[])
{
    int f_des[2];

    if(pipe(f_des) == -1)
    {
        perror("pipe");
        exit(1);
    }

    switch(fork())
    {
        case -1: perror("fork");
            exit(2);
            case 0: dup2(f_des[1], fileno(stdout));
            close(f_des[0]);
            close(f_des[1]);
            char *cmd[] = {"/usr/bin/"+argv[1],argv[1], (char *)0};
            char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
            int ret;
            ret = execvp(cmd,path);
            exit(3);
        case default: dup2(f_des[0], fileno(stdin));
            close(f_des[0]);
            close(f_des[1]);
            char *cmd[] = {"/usr/bin/"+argv[2], argv[2], (char *)0};
            char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
            int ret;
            ret = execvp(cmd,path);
            exit(4);
    }
}

Error:

cc: Error: lab1.c, line 22: Invalid statement.
char *cmd[] = {"/usr/bin/"+argv[1],argv[1], (char *)0};
^
cc: Error: lab1.c, line 22: Missing ";".
char *cmd[] = {"/usr/bin/"+argv[1],argv[1], (char *)0};
-----------------------------------------------------^
cc: Error: lab1.c, line 23: Invalid statement.
char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
^
cc: Error: lab1.c, line 23: Missing ";".
char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
------------------------------------------------------------^
cc: Error: lab1.c, line 24: Invalid statement.
int ret;
^
cc: Error: lab1.c, line 27: Invalid expression.
case default: dup2(f_des[0], fileno(stdin));
-----^
cc: Error: lab1.c, line 30: Invalid statement.
char *cmd[] = {"/usr/bin/"+argv[2], argv[2], (char *)0};
^
cc: Error: lab1.c, line 30: Missing ";".
char *cmd[] = {"/usr/bin/"+argv[2], argv[2], (char *)0};
------------------------------------------------------^
cc: Error: lab1.c, line 31: Invalid statement.
char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
^
cc: Error: lab1.c, line 31: Missing ";".
char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
------------------------------------------------------------^
cc: Error: lab1.c, line 32: Invalid statement.
int ret;
^
cc: Error: lab1.c, line 25: In this statement, "ret" is not declared.
ret = execvp(cmd,path);
^
cc: Error: lab1.c, line 25: In this statement, "cmd" is not declared.
ret = execvp(cmd,path);
-------------^
cc: Error: lab1.c, line 25: In this statement, "path" is not declared.
ret = execvp(cmd,path);
-----------------^
13
  • 7
    You can't add two strings with + like "/usr/bin/"+argv[1]. Don't make up syntax just because you can do that in other languages. Commented Dec 11, 2014 at 3:00
  • 3
    And it looks like you're compiling as C89. And it's default:, not case default:. Commented Dec 11, 2014 at 3:02
  • 2
    Which compiler are you using, on which platform? You're using a feature that is only available in C99 or C11, not in the old C89/C90, but it looks like your compiler is assuming C90. If you can't set compiler options to work in C99, you'll have to move the variable declarations to just after an {, if necessary adding the { and matching } to create a block in which you can declare the variables. For example: case 0: { char *cmd[] = { argv[1], argv[1], (char *)0 }; ... break; } or thereabouts. Commented Dec 11, 2014 at 3:54
  • 1
    If it was last updated in the 90s, then (a) you should find a better place to study — the equipment shouldn't be more than a decade old — and (b) you can safely assume it is not supporting C11 and empirical evidence indicates it is not supporting C99 by default. Which variant of Unix is it running? Try cc -V or cc -v or cc -version or cc --version; one of those might produce a version number. uname -a contains lots of information too. Commented Dec 11, 2014 at 3:58
  • 1
    So, you're running a DEC compiler, perhaps on an Alpha, perhaps on a VAX? Anyway, a date in 1995 precludes C99 or C11 support. So, you'll have to make sure that your variable declarations only appear at the start of a block, before any executable statements, as in my suggested workaround. Commented Dec 11, 2014 at 4:02

2 Answers 2

2

I try to remove the errors. I am not sure this is working correctly.

char *cmd[] = {"/usr/bin/"+argv[1],argv[1], (char *)0};

change the + as ,.

char *cmd[] = {"/usr/bin/",argv[1],argv[1], (char *)0};

case dafault:

to

default:

And make the cases as with in a block. using the parameters. { }.

While passing the argument to the execvp first argument is char * not char *[].

Then try this code. I am not sure this is working, but the all errors is cleared.

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

void main(int argc, char *argv[])
{
    int f_des[2];

   if(pipe(f_des) == -1)
    {
       perror("pipe");
       exit(1);
     }

     switch(fork())
     {
         case -1: perror("fork");
                 exit(2);
         case 0: { dup2(f_des[1], fileno(stdout));
                   close(f_des[0]);
                   close(f_des[1]);
                   char *cmd = "/usr/bin/";
                   char *const path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
                   int ret;
                   ret = execvp(cmd,path);
                   exit(3); }
         default: { dup2(f_des[0], fileno(stdin));
                   close(f_des[0]);
                   close(f_des[1]);
                   char *cmd = "/usr/bin/";
                   char *path[] = {"HOME=/usr/home/", "LOGNAME=home", (char *)0};
                   int ret;
                   ret = execvp(cmd,path);
                   exit(4); }
        } 
  }  
Sign up to request clarification or add additional context in comments.

Comments

1

Firstly, to concatenate to strings in C/C++, you use <string.h>'s strcat(const char *,const char *) function. Secondly, the second argument for execvp() is const char *argv[]. Third, the first argument is for execvp() is const char *cmd not char *cmd[], but char *cmd. It has to be a single string. Also, it is default: not case default:, as you put in your code. Fourthly, you should declare ret,cmd, and path/cmdargs outside of the switching statement.

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

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

 if(pipe(f_des) == -1)
 {
     perror("pipe");
     exit(1);
 }

 char *cmd;
 char *cmdargs[/*<numcmdargs>*/];
 int ret;

 switch(fork())
 {
    case -1: perror("fork");
        exit(2);
    case 0: dup2(f_des[1], fileno(stdout));
        close(f_des[0]);
        close(f_des[1]);
        cmd = strcat("/usr/bin",argv[1]);
        cmd = strcat(cmd,'\0');
        ret = execvp(cmd,cmdargs);
        exit(3);
    default: dup2(f_des[0], fileno(stdin));
        close(f_des[0]);
        close(f_des[1]);
        cmd = strcat("/usr/bin/",argv[2]);
        cmd = strcat(cmd,'\0');
        ret = execvp(cmd,cmdargs);
        exit(4);
 }
}

Note: this code will compile with no warnings on clang, but will probably require some modification to run. (It gives a Bus Error: 10 when run).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.