bash - Piping in C - Error in Command 2 -
so, thought on right track trying imitate bash shell, i'm having issues piping. getting error executing second command. wondering if explain me how fix , why it's going wrong. i'm new c & linux commands supplemental information me along way appreciated.
thank time. code below, there lot of it. issue occurring in exec_pipe function. include have used input , getting output, sample input executable files professor gave testing. unfortunately, mine not working in shell. getting error print out:
inside case 5 inside exec_pipe error in pipe execvp cmd2
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <stdbool.h> #include <time.h> #include <limits.h> #include <fcntl.h> #include <sys/wait.h> #define bufsize 1024 #define cstrsize 100 #define cmdsize 30 #define debug 1 //i referenced our blackboard source code files create fork functions , deal file descriptors void exec_cmd(char** cmd1){ pid_t pid; if((pid = fork()) < 0){ printf("child process failed\n"); }else if(pid == 0){ if(execvp(cmd1[0], cmd1) < 0){ printf("execution failed\n"); exit(1); } }else{ wait(null); } } void exec_cmd_in(char** cmd1, char* infile){ pid_t pid; int fdi; if((pid = fork()) < 0){ printf("child process failed\n"); }else if(pid == 0){ fdi = open(infile, o_rdonly); if(fdi == -1){ printf("no infile"); } } } void exec_cmd_opt_in_append(char** cmd1, char* infile, char* outfile){ /* pid_t pid; int fdi, fdo; if((pid = fork()) < 0){ printf("child process failed\n"); }else if(pid == 0){ fdo = open(outfile, o_rdwr | o_append | o_creat, s_irusr | s_iwusr); if(fdo == -1){ printf("no outfile"); } if(dup2(fdi, 0) == -1){ printf("infile not updated"); } if(dup2(fdo, 1) == -1){ printf("outfile not updated"); } close(fdi); close(fdo); if(execvp(cmd1[0], cmd1) < 0){ printf("execution failed\n"); exit(1); } }else{ wait(null); } */ } void exec_cmd_opt_in_write(char** cmd1, char* infile, char* outfile){ /* pid_t pid; int fdi, fdo; if((pid = fork()) < 0 ){ printf("fork error"); exit(1); }else if(pid == 0 ){ fdo = open(outfile, o_rdwr | o_creat, s_irusr | s_iwusr); if(fdo == -1){ printf("no outfile"); } if(dup2(fdi, 0) == -1){ printf("infile not updated"); } if(dup2(fdo, 1) == -1){ printf("outfile not updated"); } close(fdi); close(fdo); if(execvp(cmd1[0], cmd1) < 0){ printf("execution failed\n"); exit(1); } }else{ wait(null); } */ } void exec_pipe(char** cmd1, char** cmd2){ pid_t pid; int pipefd[2]; // pipe[1] write end of pipe // pipe[0] read end of pipe // making pipe printf("inside exec_pipe\n"); pid = fork(); switch(pid){ case -1: //error in fork printf("fork error\n"); //exit exit(1); case 0: //child break; default: //parent wait(null); } //this executed child process if(pipe(pipefd) < 0 ) { //error condition printf("pipe error"); exit(1); } pid = fork(); switch(pid){ case -1: //error in fork printf("fork error\n"); //exit case 0: //child close(stdin_fileno); //direct stdout pipe dup2(pipefd[1], stdout_fileno); //close descriptors close(pipefd[0]); close(pipefd[1]); //execute command1 execvp(cmd1[0], cmd1); //execvp should not return, if //there error! printf("error in execvp cmd1"); exit(1); default: //parent close(stdin_fileno); //direct input pipe dup2(pipefd[0],stdin_fileno); //close descriptors close(pipefd[0]); close(pipefd[1]); //execute command 2 execvp(cmd2[0],cmd2); //if execvp makes back, error condition printf("error in pipe execvp cmd2"); exit(1); } } void exec_pipe_opt_in_append(char** cmd1, char** cmd2, char* infile, char* outfile){ } void exec_pipe_opt_in_write(char** cmd1, char** cmd2, char* infile, char* outfile){ } int parse_command(char* line, char** cmd1, char** cmd2, char* infile, char* outfile){ /* (1)create bunch of flags compare right return value (2)loop on entire line , set flags (3)add bunch of if statements compare flags (4)if there more 1 flag pipe, can't handle it. regurn 9. (5)if there &, can't handle. (6)return right value */ int pipe_found = 0; int input_found = 0; int redirection = 0; int = 0; int spaces = 0; int append = 0; int special = 0; while(line[i] != '\0'){ if(line[i] == '|'){ pipe_found++; } if(line[i] == '<'){ input_found = 1; } if((line[i] == '&') || (line[i] == '*') || (line[i] == '^') || (line[i] == '%') || (line[i] == '#') || (line[i] == '!') || (line[i] == '@') || (line[i] == '(') || (line[i] == ')')){ special = 1; } if(line[i] == '>'){ redirection = 1; if(line[i+1] == '>'){ append = 1; } } if(line[i] == ' '){ spaces++; } i++; } if((strlen(line) >=4) && (line[0] == 'q') && (line[1] == 'u') && (line[2] == 'i') && (line[3] == 't')){ return 0; } if((pipe_found == 0) && (special == 0)){ if((redirection == 0) && (input_found == 0)){ return 1; }else if((redirection == 0) && (input_found == 1)){ return 2; }else if(append == 1){ return 3; }else if(redirection == 1){ return 4; } }else if((pipe_found == 1) && (special == 0)){ if((redirection == 0) && (input_found == 0)){ return 5; }else if((redirection == 0) && (input_found == 1)){ return 6; }else if(append == 1){ return 7; }else if(redirection == 1){ return 8; } } return 9; } //i referenced stackoverflow , online libraries tokenize function char ** tokenize(char *str, char *delim, unsigned int *number_tokens) { char *pch = strtok(str, delim); unsigned int ntok = 0; if(pch != null) { ntok = 1; }else{ return null; } char **tokens = realloc(null, sizeof(char *)*ntok); tokens[ntok-1] = pch; while(pch != null) { pch = strtok(null, delim); ntok++; tokens = realloc(tokens, sizeof(char *)*ntok); tokens[ntok-1] = pch; } if(number_tokens) { *number_tokens = ntok; } return tokens; } //i referenced stackoverflow.com trim function char *trim(char *str) { char *end; if(str == null){ return null; } while(isspace(*str)){ str++; } end = str + strlen(str) - 1; while(end > str && isspace(*end)) { end--; } *(end+1) = 0; return str; } int main(int argc, char *argv[]){ int returnvalue = 0; char *infile = null; char *outfile = null; char **cmd = null; char **cmd1_tokens = null; char **cmd2_tokens = null; char *input; int current_cmd = 0; /* (1)if user not enter command line argument, 1 after typing "myshell-%" (2)call parse_command on user input right return value (3)begin parsing user input within main */ if(argc == 1){ printf("myshell-%%\n"); fgets (input, 20, stdin); returnvalue = parse_command(input, cmd1_tokens, cmd2_tokens, infile, outfile); cmd = tokenize(input, "|", null); }else{ returnvalue = parse_command(argv[1], cmd1_tokens, cmd2_tokens, infile, outfile); cmd = tokenize(argv[1], "|", null); } int infileit = 0; while(cmd[current_cmd] != null) { unsigned int number_tokens = 0; char **infile_token = tokenize(cmd[current_cmd], "<", &number_tokens); if(number_tokens > 1){ while(infile_token[infileit] != null){ infileit++; } } if(infile_token[1] != null) { number_tokens = 0; char **infile_outfile_token = tokenize(infile_token[1], ">", &number_tokens); if(number_tokens > 1){ infile = infile_outfile_token[0]; infile = infile_token[1]; } } number_tokens = 0; char **outfile_token = tokenize(cmd[current_cmd], ">", &number_tokens); if(number_tokens > 1){ outfile = outfile_token[1]; } current_cmd++; } //trim in/outfiles infile = trim(infile); outfile = trim(outfile); /* start breaking cmd[0] , cmd[1] smaller chunks , saving appropriate cmd */ cmd1_tokens = tokenize(cmd[0], " ", null); if(cmd[1] != null){ cmd2_tokens = tokenize(cmd[1], " ", null); } int cmd1args = 0; while(cmd1_tokens[cmd1args] != null){ cmd1args++; } int cmd2args= 0; if(cmd2_tokens != null){ while(cmd2_tokens[cmd2args] != null){ cmd2args++; } } int iterator = 0; while((iterator < cmd1args) && (cmd1args != 0)){ printf("cmd1: %s\n", cmd1_tokens[iterator]); iterator++; } iterator = 0; while((iterator < cmd2args)&&(cmd2args != 0)){ printf("cmd2: %s\n", cmd2_tokens[iterator]); iterator++; } if(infile != null){ printf("infile: %s\n", infile); } if(outfile != null){ printf("outfile: %s\n", outfile); } /*use switch statement process return values (0 ot 9) of parse_command. our program should execute “line” if return code parse_command function 0 8, line deemed “valid”. return code 9, our program output ”not handled @ time!”.*/ switch(returnvalue){ case 0 : printf("exiting program.\n"); exit(1); break; case 1 : printf("inside case 1\n"); exec_cmd(cmd1_tokens); break; case 2 : printf("inside case 2\n"); exec_cmd_in(cmd1_tokens, infile); break; case 3 : printf("inside case 3\n"); exec_cmd_opt_in_append(cmd1_tokens, infile, outfile); break; case 4 : printf("inside case 4\n"); exec_cmd_opt_in_write(cmd1_tokens, infile, outfile); break; case 5 : printf("inside case 5\n"); exec_pipe(cmd1_tokens, cmd2_tokens); break; case 6 : printf("inside case 6\n"); //exec_pipe_in(cmd1_tokens, cmd2_tokens, infile); break; case 7 : printf("inside case 7\n"); exec_pipe_opt_in_append(cmd1_tokens, cmd2_tokens, infile, outfile); break; case 8 : printf("inside case 8\n"); exec_pipe_opt_in_write(cmd1_tokens, cmd2_tokens, infile, outfile); break; default : printf("inside case 9\n"); printf("not handled @ time!\n"); } return 0; }
without having access input file you're giving it, it's little hard what's going on, here tips debugging it.
first, when don't understand happening, can idea strip down minimal, working, self contained example demonstrates problem. sometimes, process of cutting down small example can find problem; if not, gives smaller example ask about.
next, when putting in these print statements debug what's going on, give little more context. in 1 indicates error; print out error is, , arguments function failed. rather just:
printf("error in pipe execvp cmd2");
you can use strerror
string representing error number:
printf("error %d in pipe execvp cmd2: %s\n", errno, strerror(errno));
and can print out command , of arguments were:
for (char **arg = cmd2; *arg != null; ++arg) { printf("cmd2[%ld] = %s", arg - cmd2, *arg); }
between printing out actual error , printing out command name , of arguments, should debug problem.
if add information question, , maybe cut example down more minimal example showing minimal example of input causes problem, out lot more.
Comments
Post a Comment