0

对于我的班级,我们将实现一个带有输出重定向的 shell。我的输出重定向工作正常,除了我的第一个命令总是损坏请参阅:

$ echo this doesn't work
H<@?4echo
No such file or directory
$ echo this does work
this does work

但是之后的每个命令似乎都很好。我使用什么技术来查找导致此问题的错误?

我认为这与没有正确冲洗有关。我把它洒在我的代码周围(这很愚蠢),看看它在循环期间是否有帮助,但没有。我还尝试打印出我的 OrderedIds 列表,该列表只是一个命令列表,用于检查是否可以在任何地方找到 H<@?4 ,但即使我初始化它,它也不起作用。

谢谢你的帮助。

#define LENGTH 1000
#define MAXCMD 11
#define MAX_STR_LEN 20
void init(char *temp);
void clean(char **orderedIds);
void init_pid(int *temp);
void reap(int *temp,int ret_status); 
void jobs(int *pid_list, char **orderedIds);
int ioRedir(char **orderedIds);
void reap(int *temp,int ret_status){//chainsaws all zombies
    int a;  
    for (a=0; a<LENGTH; a++ ){
        waitpid(temp[a],&ret_status,WNOHANG) == temp[a];
    }
}
void init(char *temp){//Function to initialize/reset the cmd array
    int i;
    for(i=0; i<LENGTH; i++){
        temp[i] = 0; 
    }
}
void init_pid(int *temp){//Function to initialize/reset the pid list
    int i;
    for(i=0; i<LENGTH; i++){
        temp[i] = -777; 
    }
}
void clean(char **orderedIds){//garbage collection 
    int i; 
    for(i=0; i<MAXCMD; i++){
        free(orderedIds[i]);
    }
    free(orderedIds);
} 
void jobs(int *pid_list, char **orderedIds){//function to check for background proccesses
    printf("Jobs:\n");
    int y; 
    for(y=0; y<LENGTH; y++){
        if(kill(pid_list[y], 0) == 0){
            printf("%d\n", pid_list[y]); 
        }               
    }
    clean(orderedIds);
    printf("$ ");
}
int ioRedir(char **orderedIds){ 
    int i; 
    for ( i = 0; i<MAXCMD; i++){
        if(orderedIds[i] == NULL){
            return -1; 
        }
        if(strcmp(orderedIds[i],">")==0){
            return (i+1); 
        }

    }
}

int main (int argc, char *argv[], char *envp[])
{ 
    char temp[LENGTH];
    char * tok;
    char c = '\0';
    int saved_stdout;
    int pid_list[LENGTH];
    int ret_status;
    int numFile;
    int pid_counter = 0;
    int outputfd = -1;   
    char outputFile[MAX_STR_LEN]; 
    pid_t pid; 
    printf("$ ");
    int i, j, y, background= 0;  
    init_pid(pid_list); 
    while(c !=EOF) { //while not ^D // Source: LinuxGazzette Ramankutty
        outputfd = -1;
        fflush(0);
        c = getchar();    
        if(c=='\n'){ //entered command
            reap(pid_list, ret_status); 
            char **orderedIds = malloc(MAXCMD * sizeof(char*)); 
            for (i=0; i<MAXCMD; i++){
                 orderedIds[i] = malloc(MAXCMD * sizeof(char*)); 
            }
            int k=0; 
            tok = strtok(temp, " \n\t\r"); 
            while (tok !=NULL){ 
                strcpy(orderedIds[k], tok);
                k++;
                tok = strtok (NULL, " \n\t\r");
            }
            orderedIds[k] = NULL; //END with NULL 
            init(temp); //initialize the array
            if(orderedIds[0] ==NULL){
                printf("\n$ ");
                continue; 
            }
            numFile = ioRedir(orderedIds);
            if(strcmp(orderedIds[0],"exit")==0){// if exit
                printf("now exiting...\n"); 
                break;  
            }
            if(strcmp(orderedIds[k-1], "&")==0){//if background
                 orderedIds[k-1] = NULL; 
                 background = 1;
            }else background = 0; 

            if(strcmp(orderedIds[0], "jobs") == 0){//if jobs command    
                jobs(pid_list, orderedIds); 
                continue; 
            }   
            if(strcmp(orderedIds[0], "cd") == 0){ //if change directory command
                chdir(orderedIds[1]);
                printf("$ ");
                continue;
            }
            pid = fork();
            if (pid!=0 && background == 1)
            {
                //go to end of list in pid and put it in 
                pid_list[pid_counter] = pid; 
                pid_counter++; 
                printf("To the background: %d\n", pid);
            } else if (pid==0 && background == 1) {
                    fclose(stdin); //close child's stdin
                    fopen("/dev/null", "r"); //open a new stdin that is always empty.
                if(execvp(orderedIds[0], orderedIds)){
                    printf("%s\n", orderedIds[0]);
                    puts(strerror(errno));
                    exit(127); 
                }
            }
            if (pid != 0 && !background){
                //printf("Waiting for child (%d)\n", pid);
                fflush(0);
                pid = wait(&ret_status);
            }  else if (pid == 0 && !background) {
                    if(numFile > 0){
                        strncpy(outputFile, orderedIds[numFile], strlen(orderedIds[numFile])); 
                        numFile = 0;
                        //open the output file 
                        outputfd = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH); 
                        if (outputfd < 0) {
                            exit(EXIT_FAILURE);
                        }
                        //close STDOUT
                        if(close(STDOUT_FILENO) < 0 ){
                            perror("close(2) file: STDOUT_FILENO");
                            close(outputfd); 
                            exit(EXIT_FAILURE); 
                        }
                        //use dup to rerout the output
                        if(saved_stdout = dup(outputfd) != STDOUT_FILENO){
                            perror("dup(2)");
                            close(outputfd);
                            exit(EXIT_FAILURE);
                        }
                        close(outputfd);

                    }

                if (execvp(orderedIds[0], orderedIds)){
                    printf("%s\n", orderedIds[0]);
                    puts(strerror(errno));
                    exit(127);
                }
            }
            dup2(saved_stdout,outputfd);
            clean(orderedIds);
            fflush(0);
            printf("$ ");
        } else {
            strncat(temp, &c, 1); 
        }
    }
    fflush(0);
    return 0;    
}
4

1 回答 1

2

垃圾的原因是您从未tempmain(). 您init(temp)在处理完每个命令后调用。

您的代码中还有很多其他问题:

orderedIds[i] = malloc(MAXCMD * sizeof(char*));

由于orderedIds[i]是 char 数组,而不是 char*,因此您应该将大小乘以sizeof(char). 此外,尚不清楚为什么要使用MAXCMD大小 - 在上一行中,这是一行中的最大单词数,而不是单词中的字符数。

strcpy(orderedIds[k], tok);

您应该使用strncpy()以确保您不会复制超过orderedIds[k].

另一种选择是首先预先分配所有的orderedIds[i]。而不是使用strcpy(),使用strdup()并将其分配给orderedIds[k]; 如果你这样做,你必须记住free()所有这些字符串。

第三种选择是根本不复制字符串。只需将返回的指针分配给strtok()to orderedIds[k]。但在这种情况下,您必须init(tmp)在分叉后才能调用。

strncpy(outputFile, orderedIds[numFile], strlen(orderedIds[numFile])); 

限制应该是 的大小outputFile,而不是 的长度orderedIds[numFile]strncpy()永远不会复制超过源的长度,您需要告诉它目标的最大大小以防止缓冲区溢出。

outputfd = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH); 
if (outputfd < 0) {
   exit(EXIT_FAILURE);
}

您应该致电perror()报告open()失败的原因。

puts(strerror(errno));

打电话perror(),就像你在别处做的那样。

于 2013-03-02T06:08:42.010 回答