我发现了同样的问题,但没有答案。
在构建我自己的unix shell时,我的输出重定向工作正常,但是当我尝试输入时它没有做任何事情。如果你能帮助我找出那个很棒的问题。 这是我的exec函数代码:
void execute (char **args)
{
int pid, status;
pid = fork ();
if (pid < 0)
{
perror ("Error forking!");
return;
}
else if (pid > 0)
{
fflush(0);
while (wait (&status) != pid)
continue;
}
else if (pid == 0)
{
int i,in=0,out=0;
char input[BUF_SIZE],output[BUF_SIZE];
for(i=0;args[i]!=NULL;i++)
{
if(strcmp(args[i],"<")==0)
{
args[i]=NULL;
strcpy(input,args[i+1]);
in=2;
}
if(strcmp(args[i],">")==0)
{
args[i]=NULL;
strcpy(output,args[i+1]);
out=2;
}
}
if(in)
{
int fd0;
if ((fd0 = open(input, O_RDONLY, 0)) < 0)
{
perror("Couldn't open input file");
exit(0);
}
dup2(fd0, 0);
close(fd0);
}
if (out)
{
int fd1;
if ((fd1 = creat(output , 0644)) < 0)
{
perror("Couldn't open the output file");
exit(0);
}
dup2(fd1, 1);
close(fd1);
}
execvp (*args, args);
perror("execvp");
_exit(1);
}
以下是我的全部代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ARGSIZE 20
#define BUF_SIZE 1024
void execute (char **args);
void cd (char *directory);
int killpid (char *pitstr, int sig);
int main (void)
{
char line[BUF_SIZE] = {0};
char *args[ARGSIZE] = {NULL};
char *token;
int i, argIndex = 0;
while (1)
{
argIndex = 0;
for (i = 0; i < ARGSIZE; i++)
args[i] = NULL;
printf ("shell> ");
if (fgets (line, BUF_SIZE, stdin) == NULL)
{
printf ("EOF received\n");
return 0;
}
if (*line == '\n')
continue;
token = strtok (line, " \n");
while (token != NULL)
{
args[argIndex] = token;
token = strtok (NULL, " \n");
argIndex++;
}
if (!argIndex)
continue;
if (strcmp (args[0], "quit") == 0 || strcmp (args[0], "exit") == 0)
break;
if ((strcmp (args[0], "cd") == 0))
cd (args[1]);
else if ((strcmp (args[0], "kill") == 0))
{
if (args[1])
killpid (args[1], SIGTERM);
}
else
execute (args);
}
return 0;
}
void execute (char **args)
{
int pid, status;
pid = fork ();
if (pid < 0)
{
perror ("Error forking!");
return;
}
else if (pid > 0)
{
fflush(0);
while (wait (&status) != pid)
continue;
}
else if (pid == 0)
{
int i,in=0,out=0;
char input[BUF_SIZE],output[BUF_SIZE];
for(i=0;args[i]!=NULL;i++)
{
if(strcmp(args[i],"<")==0)
{
args[i]=NULL;
strcpy(input,args[i+1]);
in=2;
}
if(strcmp(args[i],">")==0)
{
args[i]=NULL;
strcpy(output,args[i+1]);
out=2;
}
}
if(in)
{
int fd0;
if ((fd0 = open(input, O_RDONLY, 0)) < 0)
{
perror("Couldn't open input file");
exit(0);
}
dup2(fd0, 0);
close(fd0);
}
if (out)
{
int fd1;
if ((fd1 = creat(output , 0644)) < 0)
{
perror("Couldn't open the output file");
exit(0);
}
dup2(fd1, 1);
close(fd1);
}
execvp (*args, args);
perror("execvp");
_exit(1);
}
}
void cd (char *directory)
{
char dir[BUF_SIZE] = {0};
if (!directory)
{
directory = getenv ("HOME");
if (chdir (directory))
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
return;
}
if (*directory == '~')
{
strcpy (dir, getenv ("HOME"));
strcat (dir, "/");
strcat (dir, directory + 2);
if (chdir (dir))
fprintf (stderr, "Failed to enter directory: %s\n", dir);
else
printf ("%s\n", dir);
return;
}
if (chdir (directory))
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
}
int killpid (char *pidstr, int sig)
{
pid_t pid = (pid_t)atoi (pidstr);
if (pid < 1)
{
fprintf (stderr, "warning: requested pid < 1, ignoring\n");
return (int)pid;
}
printf (" killing pid '%d' with signal '%d'\n", (int)pid, sig);
return 0;
}
答案 0 :(得分:1)
当你在args数组中看到<
时
if(strcmp(args[i],"<")==0)
您将args [i]设置为NULL
args[i]=NULL;
然后,您将其传递给strcmp()
if(strcmp(args[i],">")==0)
并且您的子进程将很乐意进行段错误。在这里使用if-else
- 构造:
if(strcmp(args[i],"<")==0) {
args[i]=NULL;
strcpy(input,args[i+1]);
in=2;
} else if(strcmp(args[i],">")==0) {
args[i]=NULL;
strcpy(output,args[i+1]);
out=2;
}
这应该可以解决错误。
此外,这可能会派上用场检测这种情况:
...
while (wait (&status) != pid)
continue;
if (WIFSIGNALED(status))
printf("Killed by signal %d%s\n",
WTERMSIG(status), WCOREDUMP(status)?" (Core dumped)":"");