【发布时间】:2017-09-19 07:14:46
【问题描述】:
您好,感谢您的关注。我正在尝试实现自己的外壳。我有一些关于我的代码和任务 ro resolv 的问题。下面我介绍我之前的代码和问题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
void parse(char *line, char **argv, char **argv2)
{
while (*line != '\0')
{
while (*line == ' ' || *line == '\t' || *line == '\n')
{
*line++ = '\0';
}
if(*line == '>' && *(line+1) == '>')
{
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
{
line++;
}
while (*line == ' ' || *line == '\t' || *line == '\n')
{
*line++ = '\0';
}
*argv2 = line;
break;
}
if(*line == '&')
{
break;
}
*argv++ = line;
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
{
line++;
}
}
*argv = '\0';
}
void execute(char **argv, int option)
{
pid_t pid;
int status;
if ((pid = fork()) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
else if (pid == 0)
{
if (execvp(*argv, argv) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
}
else if(option == 1)
{
while (wait(&status) != pid);
}
}
void execute2(char *command, char **argv, char **argv2)
{
pid_t pid;
int status;
if ((pid = fork()) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
else if (pid == 0)
{
//close(1);
parse(command, argv, argv2);
int output = open(*argv2, O_APPEND | O_WRONLY);
dup2(output,1);
if (strcmp(argv[0], "exit") == 0)
exit(0);
if (execvp(*argv, argv) < 0)
{
printf("*** ERROR ***\n");
exit(1);
}
close(output);
}
else
{
while (wait(&status) != pid);
}
}
int specialChar(char *argv)
{
int i=0;
while(argv[i]!='\0')
{
if(argv[i]=='>' && argv[i+1]=='>')
return 1;
else if(argv[i]=='&')
return 2;
else if(argv[i]=='|')
return 3;
i++;
}
}
void main()
{
char command[20];
char *argv[64];
char *argv2[1];
char **history = (char**)malloc(20*sizeof(char*));
int counterHistory1=-1;
int counterHistory2=0;
int i;
for(counterHistory2 = 0; counterHistory2<20; counterHistory2++)
{
history[counterHistory2]=(char*)malloc(100*sizeof(char));
}
FILE *file;
file=fopen("history", "w");
if(!file)
printf("ERROR");
while (1)
{
printf("Shell -> ");
gets(command);
counterHistory1++;
strcpy(history[counterHistory1],command);
fopen("history", "w");
if(counterHistory1<20)
for(i=0; i<=counterHistory1; i++)
{
fprintf(file,"%s\n",history[i]);
}
else
for(i=counterHistory1-20; i<counterHistory1; i++)
{
fprintf(file,"%s\n",history[i]);
}
fflush(file);
printf("\n");
switch(specialChar(command))
{
case 1:
//close(1);
execute2(command,argv,argv2);
break;
case 2: //running program in background
parse(command, argv, argv2);
if (strcmp(argv[0], "exit") == 0)
exit(0);
execute(argv,0);
break;
case 3:
break;
default:
parse(command, argv, argv2);
if (strcmp(argv[0], "exit") == 0)
exit(0);
execute(argv,1);
break;
}
fclose(file);
}
}
1) 当用户的最后一次登录是“&”时,我需要在后台运行我的程序。我已经读过,如果我不打电话等待,我可以做到这一点。我做得很好还是应该改变一些东西?
2) 如果我找到“>>”,我应该将输出重定向到文件。例如我得到 ls >> 输出,所有目录和文件都应该写入文件“输出”。不幸的是,它只工作一次。在此之后我的程序停止。我认为过程从未完成,然后我无法编写下一个命令。我试图杀死该进程,但没有成功,或者我做错了什么。
3) 在我的 shell 中,我应该使用 | 创建任意长度的管道。标志。我不知道如何解决这个问题...
感谢您的回答和帮助。
【问题讨论】:
-
子点 2) 得到改进
-
你的意思是你想自己写解释器?你能解释一下什么是“counterHistory1,2”、“history”吗?
-
只是一些建议-如果您无法打开历史文件,为什么不粉碎呢?为什么你使用最大长度为 20 的命令?这没什么!
-
是大学项目。我应该检查用户执行了多少命令,我需要保存最后 20 条命令,这就是我使用 counterHistory 的原因。
-
我的意思是你的每个命令限制为 20 个字符。这是为什么呢?