一个简易的shell

《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 1000

void 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值