一个简易的shell

来源:互联网 发布:linux 查看路由 编辑:程序博客网 时间:2024/05/16 07:56

《Unix系统》课程大作业,支持不定长度参数、管道和I/O重定向。暂不支持正则和cd命令。以后有时间再增加更多内容。

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pwd.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#define MAXLEN 1000void swap(int *a, int *b){    int t = *a;    *a = *b;    *b = t;}int parse_cmd(char *content, int *argc, char *argv[]){    char *p;    int num = 0;    if (argc == NULL || argv == NULL)        return -1;    p = content;    argv[num++] = p;    while (*p)    {        if ((*p == '\r') || (*p == '\n'))        {            *p = '\0';            break;        }        if (*p == '|' )        {            *p = 0;            p++;            argv[num++] = p;            continue;        }        p++;    }    *argc = num;    return 0;}int parse_parameter(char *content, int *argc, char *argv[]){    char *p;    int num = 0;    int start = 1;    if (argc == NULL || argv == NULL)        return -1;    p = content;    while (*p)    {        if ((*p == '\r') || (*p == '\n'))        {            *p = '\0';            break;        }        if ((*p == ' ') || (*p == '\t') || (*p == '\'') || (*p == '\"'))        {            start = 1;            *p = '\0';            p++;            continue;        }        if (start)        {            argv[num++] = p;            start = 0;        }        p++;    }    argv[num++] = 0;    *argc = num;    return 0;}void work(int argc, char *argv[]){        if (argc > 3)        {            if (strcmp(argv[argc - 3], "<") == 0)            {                int file = open(argv[argc - 2], O_RDWR | O_NONBLOCK);                if (file < 0)                {                    printf("Can not open this file\n");                    return;                }                argv[argc - 2] = argv[argc - 3] = 0;                dup2(file, 0);                close(file);                dup2(0, 0);            }            else if (strcmp(argv[argc - 3], ">") == 0)            {                int file = open(argv[argc - 2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);                if (file < 0)                {                    printf("Can not open this file\n");                    return;                }                argv[argc - 2] = argv[argc - 3] = 0;                dup2(file, 1);                close(file);                dup2(1, 1);            }        }        if (execvp(argv[0], argv) < 0)        {            printf("Command failed\n");        }}void do_pipe(int depth, int cmd_num, char *cmds[]){    int argc = 0;    int pid;    char *argv[MAXLEN];    parse_parameter(cmds[depth], &argc, argv);    if (depth == cmd_num - 1)    {        pid = fork();        if (pid == 0)            work(argc, argv);        wait(pid, NULL, 0);        return;    }    int fd[2];    pipe(fd);    pid=fork();    if (pid == 0)    {        dup2(fd[1], 1);        close(fd[0]);        close(fd[1]);        work(argc, argv);    }    dup2(fd[0], 0);    close(fd[0]);    close(fd[1]);    wait(pid, NULL, 0);    do_pipe(depth + 1, cmd_num, cmds);}int main(){    struct passwd* pwd;    char host[MAXLEN];    char cwd[MAXLEN];    char content[MAXLEN];    int argc = 0;    int cmd_num = 0;    char *cmds[MAXLEN];    char *argv[MAXLEN];    memset(content, 0, sizeof(content));    printf("Myshall\n");    printf("please input \"exit\" or \"quit\" to exit\n");    while (1)    {        pwd = getpwuid(getuid());        gethostname(host, MAXLEN);        getcwd(cwd, MAXLEN);        printf("%s@%s:%s$ ", pwd -> pw_name, host, cwd);        while(strlen(content) == 0)            fflush(stdin),gets(content);        parse_cmd(content, &cmd_num, cmds);        if (strcmp(cmds[0], "exit") == 0 || strcmp(cmds[0], "quit") == 0)            break;        int pid = fork();        if (pid == 0)        {            do_pipe(0, cmd_num, cmds);            return 0;        }        wait(pid, 0, NULL);        memset(content, 0, sizeof(content));    }    return 0;}