《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;
}