PDA

View Full Version : Piping commands with redirection


opt!kal
Oct29-09, 01:03 AM
1. The problem statement, all variables and given/known data
Hi there,

So im working on this assignment where the user is supposed to input a variety of UNIX commands and they must behave as if one typed it into the terminal. My current problem lies with when a user tries to redirect the inputted commands to some file. Currently it only works when a user has the redirect symbol, like:

ls -l | sort -n > temp.txt

However if I try to input:
ls -l | sort -n

I just segfault. I know the problem most likely lies in how I wrote the redirect option, but I cant seem to figure out how to make it so that the two above commands work.

3. The attempt at a solution
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

/*get args function*/

#define MAXARGS 256
char ** getargs(char * cmd) {
// assumes that cmd ends with NULL
char** argsarray;
int nargs = 0;
int nlen = strlen(cmd);
int i = 0;
argsarray = (char**) malloc(sizeof(char*) * MAXARGS);
argsarray[0] = strtok(cmd," ");
i = 0;
while (argsarray[i] != NULL){
i++;
argsarray[i] = strtok(NULL," ");
}
return argsarray;
}


int main(void){

pid_t childpid;
int fd[256][2];
char cmd[256];
char * sepCmd[256];
char * pch;
char * srch;

printf("Please enter a command sequence: \n");
gets(cmd);
//scanf("%s", cmd);
printf("You have entered: %s \n", cmd);


printf("Attempting to split up command: \n");
pch = strtok (cmd, "|");

srch = strchr(cmd, '>');
*srch++ = '\0'
while (*srch == ' ') ++srch;

int count = 0;
while (pch != NULL && count < 256) {
printf("%s\n", pch);
sepCmd[count] = pch;
printf("The value in this array value is: %s\n", sepCmd[count]);
pch = strtok (NULL, "|");
count++;
}

char ** argue;
int k;

/* Block that deals with the first command given by the user */
k = 0;
pipe(fd[k]);
if(!fork()) {
dup2(fd[k][1], STDOUT_FILENO);
close(fd[k][0]);
argue = getargs(sepCmd[k]);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}

/*Loop that will control all other comands except the last*/
for(k = 1; k <= count - 2; k++) {
close(fd[k-1][1]);
pipe(fd[k]);

if(!fork()) {
close(fd[k][0]);
dup2(fd[k-1][0], STDIN_FILENO);
dup2(fd[k][1], STDOUT_FILENO);
argue = getargs(sepCmd[k]);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}
}


/*Block that will take care of the last command in the sequence*/
k = count - 1;

close(fd[k-1][1]);
if(!fork()) {
dup2(fd[k-1][0], STDIN_FILENO);
argue = getargs(sepCmd[k]);
if (srch) dup2(open(srch, O_RDWR|O_CREAT), STDOUT_FILENO);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}
while(waitpid(-1, NULL, 0) != -1);
}


Any help is greatly appreciated

opt!kal
Oct29-09, 11:56 AM
So a little update,

I changed gets to fgets and it seems like it will take any amount of comannds piped together, but only if it ends with a redirection operator or else I get errors like:

<COMMAND>: invalid option -- '

where COMMAND is the last command in the sequence