在C中编写shell - 重定向/高级重定向实现

时间:2016-05-26 16:16:18

标签: c shell

对于重定向(>)和高级(>+),我不确定如何开始。我试图遍历我的空间链接lst(由;\n空格标记化)并查看它是否">"并将我的重定向结构的progAndArgs的prev节点和下一个节点保存为outFile。

我认为我正确地做了,但这很可能是错误的。

parse* p = tokenize_line_semicolons(pinput);

        myPrint("HERE\n");
        // setup redirection struct
        parse *temp2_p = p; 
        space *spc2;
        while (temp2_p != NULL) {
            spc2 = tokenize_space(temp2_p->cmd);
            space* temp_s = spc2;
            char* prev = temp_s->spc;
            if (strcmp(prev,"\n")==0)
                error();
            temp_s = temp_s->next;
            while (temp_s != NULL) {
                if (strcmp(temp_s->spc, ">") == 0) {
                    redirection r;
                    r.progAndArgs = prev;
                    if (temp_s->next->spc != NULL)
                        r.outFile = temp_s->next->spc;
                    else 
                        error();
                }
                temp_s = temp_s->next;
            }
            temp2_p = temp2_p->next;
        }

但是一旦我正确地获得了重定向结构,我就不能确定如何使用dup / dup2 / creat / write / open / read来做>和> +(我阅读了手册页)。请帮忙!

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

void myPrint(char *msg)
{
    write(STDOUT_FILENO, msg, strlen(msg));
}

void error() 
{
    char error_message[30] = "An error has occurred\n";
    write(STDOUT_FILENO, error_message, strlen(error_message));
}



typedef struct parse
{
    char* cmd;
    struct parse* next;
} parse;

typedef struct space
{
    char* spc;
    struct space* next;
} space;
typedef struct dble
{
    space* s;
    struct dble* next;
} dble;

typedef struct redirection
{
    char* progAndArgs;
    char* outFile;
} redirection;



char** p_to_char(space *s) 
{
    char** args = (char**)malloc(sizeof(char*)*514);
    space *temp = s;
    int i = 0;

    while (temp != NULL) {
        args[i] = strdup(temp->spc);
        // myPrint(args[i]);
        // myPrint("\n");
        temp = temp->next;
        i++;
    }
    return args;
}

parse* setparse(char* s) 
{
    parse* p = (parse*)malloc(sizeof(parse));
    p->cmd = strdup(s);
    p->next = NULL;

    return p;
}

space* setspace(char* s) 
{
    space* sp = (space*)malloc(sizeof(space));
    sp->spc = strdup(s);
    sp->next = NULL;

    return sp;
}

dble* setdble(space* spc) 
{
    dble* d = (dble*)malloc(sizeof(dble));

    space* temp = spc;
    while (temp != NULL) {
        d->s = temp;
        d->next = (dble*)malloc(sizeof(dble));
        d = d->next;
        temp = temp->next;
    }
    return d;
}

void show_parse(parse* p)
{
    //myPrint("Show parse\n");
    parse* temp = p;
    while(temp != NULL) {
        // myPrint(temp->cmd);
        // myPrint("->");
        temp = temp->next;
    }
    //myPrint("\n");
}

void show_space(space* sp)
{
   // myPrint("Show space\n");
    space* temp = sp;
    while(temp != NULL) {
        // myPrint(temp->spc);
        // myPrint("->");
        temp = temp->next;
    }
    //myPrint("\n");
}

// TODO - SEE IF DBLE PRINTING RIGHT OR SET UP WRONG
void show_dble(dble* d)
{
    dble* temp = d;
    //myPrint("Show dble\n");
    while(temp != NULL) {
        show_space(temp->s);
        temp = temp->next;
    }
    //myPrint("\n");
}

/* tokenized by spaces's - SEPARATE COMMANDS AND PARAMETERS */
space* tokenize_space(char* cmd) 
{
    char* token_ptr = strdup(cmd);

    char *token, *token2;
    token =  strtok_r(token_ptr, " ", &token2);
    space* s = setspace(token);
    space* fst = s;

    while (token != NULL) {
        token = strtok_r(NULL," ", &token2);
        if (token==NULL){
            return fst;
        }
        s->next = setspace(token);
        s = s->next;
    }
    return fst;
}

/* tokenized by newline and ;'s - SEPARATE COMMANDS WITH PARAMTERS*/
parse* tokenize_line_semicolons(char* input) 
{
    //myPrint("Starting Tokens!\n");

    if (strcmp(input,"\n")) {
        error();
        return NULL;
    }
    else {
        myPrint("HERE\n");
    char* token_ptr = input;

    char *token;
    token =  strtok_r(token_ptr, ";\n", &token_ptr);
    parse* p = setparse(token);
    parse* fst = p;

    while (token != NULL) {
        token = strtok_r(NULL,";\n", &token_ptr);
        if (token==NULL){
            return fst;
        }
        p->next = setparse(token);
        //tokenize_redirect(p);
        p = p->next;
    }
    return fst;
    }
}

void do_cd(char* param) 
{
    int v;
    // myPrint(param);
    // myPrint("\n");

    if (strcmp(param, "") == 0 || strcmp(param, "~") == 0) {
        char *directory = getenv("HOME");
        v = chdir(directory);
    } else if (param[0] == '/') {
        //myPrint("~ /\n");
        char* directory = param;
        v = chdir(directory);
        //exit(v);
    } else {
        char buf[100];
        char *directory = getcwd(buf,100);
        strcat(buf,"/");
        strcat(buf,param);
        //myPrint(directory);
        v = chdir(directory);
    }
    if (v == -1)  // chdir error returning
        error();
}


int run_cmds(char* cmd, char** args, space* s)
{

// myPrint("START run_cmds!!! s->spc: ");
// myPrint(s->spc);
// myPrint(", cmd: ");
// myPrint(cmd);
// myPrint("\n");

    // all cmds return 0 if pass (from exho $?)
    if (strcmp(s->spc, "exit") == 0) {
        // myPrint("DOING exit\n");
        exit(0);
    }
    else if (strcmp(s->spc, "pwd") == 0) {
        // myPrint("DOING pwd\n");
        char* buff = (char*)malloc(sizeof(char)*100);
        myPrint(getcwd(buff,100));
        myPrint("\n");
    } else if (strcmp(s->spc, "cd") == 0) {
        //myPrint("DOING cd\n");
        do_cd(s->next->spc);
    }
    else {
        // myPrint("FORK");
        // myPrint("\n");
        pid_t pid = fork();

        if (pid == 0) {
            // myPrint("CHILD");
            // myPrint("\n");
            // myPrint(args[0]);
            // myPrint("\n");
            if (execvp(args[0], args) < 0) 
                error();
            exit(0);
        } else {
            // myPrint("PARENT");
            // myPrint("\n");
            int status;
            pid_t ppid = waitpid(pid,&status,WUNTRACED);  
            // myPrint("PARENT 2");
            // myPrint("\n");
            return ppid; 
        }
    }
    return 0;
}

//Redirect throws an error if the file already exists or no file specified

int main(int argc, char *argv[]) 
{
    char cmd_buff[100];
    char *pinput;

    // implementing batch mode
        if (argc > 1) {
            int len = strlen(argv[1]);
            if (argv[1][0] == '[' && argv[1][len-1] == ']') {
                argv[1]++;
                argv[1][len-2] = '\0';
            }

            FILE *fp = fopen(argv[1],"r");
            if (fp == NULL) {
                error();
                exit(1);
            }
            char buff[514];
            //myPrint("we are about to fgets\n");
            while (fgets(buff,514,fp) != NULL) {
                // myPrint("We are fgetsing\n");
                // myPrint(buff);
                tokenize_line_semicolons(buff);
            }
            fclose(fp);
        } else if (argc >= 3) {
            error();
            exit(1);
        } 

    while (1) {
       myPrint("myshell> ");
        pinput = fgets(cmd_buff, 100, stdin);

        if (!pinput) {
            myPrint("pinput\n");
            exit(0);
        }

        // if 513th char is neither \n or null terminator, its invalid input
        if (strlen(pinput) > 512) {
            // myPrint(pinput);
            // myPrint("\n");
            error();
            exit(1);
        }

        parse* p = tokenize_line_semicolons(pinput);

        myPrint("HERE\n");
        // setup redirection struct
        parse *temp2_p = p; 
        space *spc2;
        while (temp2_p != NULL) {
            spc2 = tokenize_space(temp2_p->cmd);
            space* temp_s = spc2;
            char* prev = temp_s->spc;
            if (strcmp(prev,"\n"))
                error();
            temp_s = temp_s->next;
            while (temp_s != NULL) {
                if (strcmp(temp_s->spc, ">") == 0) {
                    redirection r;
                    r.progAndArgs = prev;
                    if (temp_s->next->spc != NULL)
                        r.outFile = temp_s->next->spc;
                    else 
                        error();
                }
                temp_s = temp_s->next;
            }
            temp2_p = temp2_p->next;
        }

        parse* temp_p = p;
        space *spc; 
        dble *d = (dble*)malloc(sizeof(dble));
        dble* tmp_d = d;

        while (temp_p != NULL) {
            spc = tokenize_space(temp_p->cmd);
            d->s = spc;
            d->next = (dble*)malloc(sizeof(dble));
            d = d->next;
            temp_p = temp_p->next;
        }       

        show_parse(p);
        show_dble(tmp_d);

        char** args = p_to_char(spc);
        //myPrint("HERE");
        while (p != NULL) {
            run_cmds(p->cmd, args, tmp_d->s);
            p = p->next;
            tmp_d = tmp_d->next;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你调用setparse(token)使用它的参数而不检查它是否为null。