您好,感谢您的关注。我正在尝试实现自己的shell。我有一些关于我的代码和任务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)来自用户的最后一个标志是&#39;&amp;&#39;我需要在后台运行我的程序。我已经读过,如果我不打电话等,我可以这样做。我做得好还是应该换一些东西?
2)如果我发现&#34;&gt;&gt;&#34;我应该将输出重定向到文件。例如,我得到ls&gt;&gt;输出,所有目录和文件应写入文件&#34;输出&#34;。不幸的是,它只运行一次。在此之后我的程序停止了。我认为过程从未完成,然后我无法写下一个命令。我试图杀死那个过程,但它没有用,或者我做错了什么。
3)在我的shell中,我应该使用|创建任意长度的管道标志。我不知道如何解决这个问题...
感谢您的回答和帮助。
答案 0 :(得分:0)
回答1
在shell中,创建的进程是shell的子进程,需要通过访问stdout,stdin和stderr来控制终端
signal(SIGTTOU, SIG_IGN);
setpgid(getpid(),getpid());
if(background==false) //shell for foreground process
{
tcsetpgrp(0,getpgid(getpid())); //access to stdin
tcsetpgrp(1,getpgid(getpid())); //access to stdout
tcsetpgrp(2,getpgid(getpid())); //access to stderr
}
execvp(command,args);