繁体   English   中英

C管道-命令2错误

[英]Piping in C - Error in Command 2

因此,我认为我在模仿bash外壳方面走上了正确的轨道,但是我在管道方面遇到了问题。 执行第二个命令时出现错误。 我想知道是否有人可以向我解释如何解决此问题以及为什么会出错。 我对C和Linux命令非常陌生,因此也将对任何可以帮助我的补充信息表示赞赏。

非常感谢您的参与。 我的代码在下面,但是有很多。 我的问题发生在exec_pipe函数中。 我通常会包括我用于输入的内容以及我将用于输出的内容,但是我的示例输入实际上是教授提供给我们进行测试的可执行文件。 不幸的是,我的外壳无法像在外壳中那样工作。 我只是打印出我的错误:

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 to create the fork functions and to deal with 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] is the write end of the pipe
    // pipe[0] is the read end of the pipe
    // making a 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 will be executed by 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 to the pipe
            dup2(pipefd[1], STDOUT_FILENO);
            //Close descriptors
            close(pipefd[0]);
            close(pipefd[1]);
            //Execute Command1
            execvp(cmd1[0], cmd1);
            //execvp should not return, so if it does
            //there is an error!
            printf("Error in EXECVP cmd1");
            exit(1);
        default:
            //parent
            close(STDIN_FILENO);
            //direct input to the pipe
            dup2(pipefd[0],STDIN_FILENO);
            //close descriptors
            close(pipefd[0]);
            close(pipefd[1]);
            //execute command 2
            execvp(cmd2[0],cmd2);
            //if execvp makes it 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 a bunch of flags to compare for the right return value
    (2)Loop over the entire line and set the flags
    (3)Add a bunch of if statements to compare flags
    (4)If there is more than one flag for pipe, we can't handle it. Regurn 9.
    (5)If there is &, we can't handle.
    (6)Return the right value
*/
    int pipe_found = 0;
    int input_found = 0;
    int redirection = 0;
    int i = 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 and some online libraries to get this 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 for this 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 the user does not enter a command line argument, get one after typing "myshell-%"
    (2)Call parse_command on the user input to get the right return value
    (3)Begin parsing the 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 the in/outfiles
    infile = trim(infile);
    outfile = trim(outfile);
    /*
    Start breaking up cmd[0] and cmd[1] into smaller chunks and saving into the 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 a switch statement to process all the return values (0 ot 9) of parse_command.
    Our program should execute the “line” if the return code from parse_command
    function is 0 to 8, that is the line is deemed “valid”. For return code 9,
    our program simply output ”Not handled at this 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 at this time!\n");
}

    return 0;
}

没有访问您提供的输入文件的权限,很难说是怎么回事,但是这里有一些调试它的技巧。

首先,当发生您不了解的事情时,最好将其简化为一个最小的,可工作的,自包含的示例 ,以证明问题所在。 有时,仅将其缩减为一个小例子的过程就可以帮助您发现问题。 但是,如果不是这样,它会为您提供一个小得多的示例。

接下来,在放入这些打印语句以调试正在发生的事情时,请给自己更多的上下文。 特别是在表示错误的那一个中; 打印出错误是什么,以及失败函数的参数是什么。 不仅仅是:

printf("Error in Pipe EXECVP cmd2");

您可以使用strerror获得代表错误号的字符串:

printf("Error %d in Pipe EXECVP cmd2: %s\n", errno, strerror(errno));

您还可以打印出命令和所有参数:

for (char **arg = cmd2; *arg != NULL; ++arg) {
    printf("cmd2[%ld] = %s", arg - cmd2, *arg);
}

在打印出实际错误与打印出命令名称和所有参数之间,这将有助于您调试问题。

如果您可以将这些信息添加到您的问题中,并且可以将您的示例缩减为一个更简单的示例,并显示一个导致问题的输入的最小示例,那么我们可能会提供更多帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM