簡體   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