在c - wc命令中实现一个简单的shell无法正常工作

时间:2015-07-30 20:50:19

标签: c linux bash shell

我在c中为一个类实现了一个简单的shell。有许多要求,但我关注的一件事是这一系列命令:

ls>测试

wc<测试

将ls命令的结果输出到文件test和wc 然后命令将计算单词,字节,字符(或其他东西)的数量 那样的文件。

无论如何,第一个命令工作,并且成功创建了测试文件 预期的内容。然而,wc命令不起作用。它触发与execv语句相关的错误"命令无法执行。我的输入重定向作为命令,如: grep test<测试工作完美。我的问题是,为什么我的shell不识别wc命令?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>

void parse(char buffer[2048], char *arguments[512]){
    //these characters(space, tab, new line, return)represent white space
    //that separate words
    char * delim = " \t\r\n\f";
    char * token;
    int count = 0;
    //Finds the first word in buffer
    token = strtok (buffer, delim);
    //While a token still exists
    while (token != NULL){
        //if token is not empty it is added to arguments
        if (strlen (token) > 0){
            arguments[count]=token;
            count++;
        }
        //Find the next token.
        token = strtok (NULL, delim);

        arguments[count+1]=NULL;
    }

int checkInput(char *arguments[512]){
    int loc = 0;
    int count = 0;
    while (arguments[count]!=NULL){
        if (strcmp(arguments[count],"<")==0){
            loc = count;
        }
        count++;
    }
    return loc;
}

void redirectInput(int input,char *arguments[512]){
    int in;
    int in2;
    char*inFile = arguments[input+1];

    in = open(inFile, O_RDONLY);
    if (in < 0){
        perror("Error Opening File");
        exit(1);
    }
    in2 = dup2(in, 0);
    if (in2 < 0){
        perror("Error redirecting stdin");
        exit(1);
    }
    close(in);
}

int checkOutput(char *arguments[512]){
    int loc = 0;
    int count = 0;
    while (arguments[count]!=NULL){
        if (strcmp(arguments[count],">")==0){
            loc = count;
        }
        count++;
    }
    return loc;
}

void redirectOutput(int output,char *arguments[512]){
    int out;
    int out2;
    char*outFile=arguments[output+1];

    out = open(outFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
    if (out < 0){
        perror("Error Opening File");
        exit(1);
    }
    out2 = dup2(out, 1);
    if (out2 < 0){
        perror("Error redirecting stdout");
        exit(1);
    }
    close(out);
}

int main(int argc, char **argv){
    //buffer is to hold the commands that the user will type in
    char buffer[512];
    char buffer2[512];
    //bin/program_name is the arguments to pass to execv
    //if we want to run ls, "/bin/ls" is required to be passed to execv()
    char* path = "/bin/";
    char * arguments[512];
    char * args_copy[512];
    //This will be the final path to the program is passed to execv
    char prog[512];
    char directory[512];
    pid_t pid,w;
    int status;
    int isValid;
    int input;
    int output;

    getcwd(directory,sizeof(directory));

    while(1){
        isValid = 0;
        while(!isValid){
            //print the prompt
            printf(":");
            fflush(stdout);
            //get input
            fgets(buffer, 512, stdin);
            if(buffer[0]!='\n' && buffer[0] != '#'){
                isValid=1;
            }
        }

        strcpy(buffer2, buffer);
        parse(buffer2, args_copy);
        //Handle the builtin functions without before forking
        if (strcmp(args_copy[0],"exit")==0){
            exit(0);
        }
        else if (strcmp(args_copy[0],"status")==0){
            printf("exit value %d\n",WEXITSTATUS(status));
        }else if( strcmp(args_copy[0],"cd") == 0 ){
            if(args_copy[1]==NULL){
                chdir(directory);
            }
            else{
                chdir(args_copy[1]);
            }
        }
        else{
            //fork!
            pid = fork();
            //Error checking to see if fork works
            if (pid < 0) {
                perror("fork");
                exit(EXIT_FAILURE);
            }
            //If pid !=0 then it's the parent
            if(pid!=0){
                do {
                    w = waitpid(pid, &status, WUNTRACED | WCONTINUED);
                    if (w == -1) {
                        perror("waitpid");
                        exit(EXIT_FAILURE);
                   }
                   if (WIFEXITED(status)) {
                   }
                   else if (WIFSIGNALED(status)) {
                       printf("killed by signal %d\n", WTERMSIG(status));
                   }
                   else if (WIFSTOPPED(status)) {
                       printf("stopped by signal %d\n", WSTOPSIG(status));
                   }
                   else if (WIFCONTINUED(status)) {
                       printf("continued\n");
                   }
                }while (!WIFEXITED(status) && !WIFSIGNALED(status));
            }
            else{
                //parse the user input into an array of strings(arguments)
                parse(buffer, arguments);
                input = checkInput(arguments);

                if (input){
                    redirectInput(input,arguments);
                    arguments[input]=NULL;
                }

                output = checkOutput(arguments);

                if (output){
                    redirectOutput(output,arguments);
                    arguments[output]=NULL;
                }
                //First we copy a /bin/ to prog
                strcpy(prog, path);
                //Then we concancate the program name to /bin/
                //If the program name is ls, then it'll be /bin/ls
                strcat(prog, arguments[0]);
                //pass the prepared arguments to execv and we're done!
                int rv=execv(prog, arguments);
                if (rv == -1) {
                    perror("Command can't execute");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:3)

这是因为wc/usr/bin/wc,而不是/bin/wc

您可以使用execvp代替execv自动在$PATH中搜索您的可执行文件。在这种情况下,您不会将/bin/添加到路径中。