在自己的shell中执行命令 - C.

时间:2016-06-28 11:04:00

标签: c shell command cd

我在C中创建自己的shell时遇到了麻烦。这是我到目前为止的代码

#include "interpreter.h"

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



void readconfig(int *timeout, char *file){
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    char * token;
    fp = fopen(CONFIG, "r");
    if (fp == NULL)
    {

        *timeout = DEFAULTTIME;

    }
    else
    {
        while ((getline(&line, &len, fp)) != -1){
            token = strtok(line, TOKEN);
            if ((strcmp(token,TIME_PERIOD) == 0)){
                *timeout = atoi(strtok(NULL, TOKEN));
            }
            if ((strcmp(token,HISTORY)==0)){
                strcpy(file,trim_command(strtok(NULL, TOKEN)));             
            }
        }
    }
}


int waitPeriod(pid_t pid){
    if(pid) {
     int stat_val;
pid_t child_pid;
    int time = 0;

    while(time < TIME_PERIOD){
        child_pid = waitpid(pid, &stat_val, WNOHANG);     
        if (child_pid == pid){
            break;
            } else if (child_pid == 0) {
                time++;
                sleep(1);
            }
        }

        if (time == TIME_PERIOD){
            printf("Process ended. Execution time was over. \n");
            kill(pid, SIGINT);
            if (kill(pid, 0) == 0){
                kill(pid, SIGKILL);
            }
        }               

        if(WIFEXITED(stat_val)) {
            return WEXITSTATUS(stat_val);
        }

        return 0;
    } else {
        return -1;
    }
}

void splitCommand(char ** parameters, char * command, int count){
    char * cm = strtok(command, " ");
    int i = 0;
    while (cm != NULL){     
        parameters[i] = malloc(strlen(cm) * sizeof(char *));
        parameters[i] = cm;
        i++;
        cm = strtok (NULL, " ");
    }       
    i++;
    parameters[i] = NULL;
}

int getParamsCount(char command[]){
    int i;
    int count = 1;
    int com_length = strlen(command);
    for(i=0; i<com_length; i++){
        if (command[i] == ' '){
            count++;
        }
    }
    return count;
}

void getHistory(FILE * history_file, char ** history_commands){ 
    char line[MAX_INPUT];
    int i = 0;
    int j;
    rewind(history_file);
    while (fgets(line, MAX_INPUT, history_file)!= NULL){
        history_commands[i] = malloc(strlen(line) * sizeof(char *));        
        history_commands[i] = strdup(line);
        for(j=0; j<MAX_INPUT; j++){
            if (history_commands[i][j] == '\n'){
                history_commands[i][j] = '\0';
                break;
            }
        }
        i++;
    }
}

int getNumberOfRows(FILE * history_file){
    rewind(history_file);
    int lines = 0;
    char ch;
    while(!feof(history_file)){
        ch = fgetc(history_file);
        if(ch == '\n'){
            lines++;
        }
    }
    return lines;
}

void printCommands(char ** history_commands, int lines){
    int i = 0;
    int j = 0;


    for(j = i; j < lines; j++){
        printf("[%d] %s\n", j, history_commands[j]);
    }
}

int runCommand(pid_t pid, char * command, char ** parameters, int child){
    int count = 0;

    switch(pid) {
        case -1 :
            return -1;
        case 0 :
            count = getParamsCount(command);
            parameters = malloc((count+1) * sizeof(char *));
            splitCommand(parameters, command, count);
            if (strncmp("cd", parameters[0], 2) == 0){
                chdir(parameters[1]);
            } else {
                execvp(parameters[0], parameters[0]);
            }
            free(parameters);
            return 0;
        default :
            child = waitPeriod(pid);
            printf("Child status: %d\n", child);
            command[0] = 0;
            free(command);          
            return 0;
    }
}

char * trim_command(char * string){
    int l = strlen(string);
    int i;
    for (i = 0; i<l; i++){
        if (string[i] == '\n'){
            string[i] = '\0';
        }
    }

    return string;
}



int main(){


    char * command;

    FILE * history;

    char cwd[MAX_INPUT];

    pid_t pid = 0;  
    int child = 0;  

    int number_of_rows = 0;
    int count = 0;

    char ** history_commands;   
    char ** parameters[10];

    printf("                              Safe comand line interpreter                         \n");
    printf("                    Type \"quit\" to cancel interpreter or command                  \n");
    printf("                    Type \"history\" to show full command history                  \n");
    printf("                    Type \"history number\" to execute command from history       \n");
    printf("________________________________________________________________________________________\n");
    sleep(1);

    history = fopen(HISTORY, "a+");
    if (history == NULL){
        printf("Could not open history file\n");
        return -1;
    }

    while(1){
        getcwd(cwd, sizeof(cwd));
        printf("Command: [%d]%s : ", child, cwd);

        command = malloc(MAX_INPUT * sizeof(char *));
        fgets(command, MAX_INPUT, stdin);
        trim_command(command);

        if (strncmp(QUIT, command, 4) == 0) {
            fclose(history);
            return EXIT_SUCCESS;
        } else if (strncmp("history", command, 7) == 0) {                                                       
            number_of_rows = getNumberOfRows(history);                                              
            history_commands = malloc(number_of_rows * sizeof(char *));                     
            getHistory(history, history_commands);
            count = getParamsCount(command);

                if (strcmp("history", command) == 0){
                    printf("HISTORY OF COMMANDS\n");
                    printCommands(history_commands, number_of_rows);
                } else {
                    char * cm = strtok(command, " ");
                    cm = strtok(NULL, " ");

                    int x;
                    x = atoi(cm);

                    if (x >= number_of_rows){
                        printf("Command does not exist\n");
                        continue;
                    }

                    command = strdup(history_commands[x]);
                    count = getParamsCount(command);
                    trim_command(command);

                    fprintf(history, "%s\n", command);

                    pid = fork();
                    runCommand(pid, command, parameters, child);
                }


        } else if (command[0] != 0){
            fprintf(history, "%s\n", command);

            pid = fork();
            runCommand(pid, command, parameters, child);            
        }
    }

    fclose(history);
    return 0;
}

问题是,它不执行 cd 命令。当我在 runCommand 方法中注释 malloc free 行时, cd 命令开始工作,但是每个其他命令都没有参数不管用... 有人可以帮我吗?

0 个答案:

没有答案