I am trying to learn Unix C and doing some exercises for practice. I am currently working on writing my own shell that works similar to the linux bash shell.
The code I have below provides for a fairly basic shell. It now provides I/O redirection. I am trying to add support for piping. Initially, I just want to add support for a single pipe.
I have tried to go through some tutorials online but can't quite figure out where to start.
Currently, the shell below can handle commands commands such as the following. ls > abc, cat< file1 > file2, etc.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#define TRUE 1
int main(void)
{
char *arg_list[10];
int status;
int counter = 0;
int counter2 = 0;
pid_t pid;
char buf[100];
char inFile[10];
char outFile[10];
int fdIn, fdOut;
while(TRUE)
{
printf("> ");
if (!fgets(buf, 100, stdin))
return 0;
pid = fork();
switch(pid)
{
case -1:
return 1;
case 0:
{
arg_list[counter] = strtok(buf, " \n");
counter = 0;
while(arg_list[counter] != NULL)
{
counter++;
arg_list[counter] = strtok(NULL, " \n");
}
counter2 = 0;
while(arg_list[counter2] != NULL)
{
if(!strcmp(arg_list[counter2], "<"))
{
if(arg_list[counter2+1] != NULL)
{
fdIn = open(arg_list[counter2+1], O_RDONLY);
dup2(fdIn, STDIN_FILENO);
}
开发者_如何学Pythonelse
{
printf("No input file specified");
}
arg_list[counter2] = 0;
}
else if(!strcmp(arg_list[counter2], ">"))
{
if(arg_list[counter2+1] != NULL)
{
fdOut = open(arg_list[counter2+1], O_CREAT | O_WRONLY | O_TRUNC, 0666);
dup2(fdOut, STDOUT_FILENO);
}
else
{
printf("No output file specified");
}
arg_list[counter2] = 0;
}
counter2++;
}
execvp(arg_list[0], arg_list);
break;
}
default:
waitpid(-1, &status, 0);
break;
}
}
return 0;
}
If somebody can point me in the right direction, that would be appreciated.
After you use dup2()
(successfully), you have two file descriptors open for the one file. You need to close the original file descriptor; the executed process should not have the extra file descriptors open.
You are also going to need to open the files in the appropriate way before using dup2()
. Amongst other things, that means strtok()
is not a good choice because it blats out the delimiter but you need to know which file to open for reading and which for writing).
You are also going to need to fettle the argument list; it should contain just the command name and a null pointer, not the two file names.
Why do you need to check the type of command? Unix shells don't treat any commands specially; all redirections, including pipes, are handled the same way. One thing to watch out for is that redirections can happen anywhere in a command, so you should parse them out first; try
>foo ls <bar -la
in a shell sometime. (Pipes are an obvious exception to this, since they also delimit commands; syntactically |
is the same as ;
, although semantically there is redirection involved in addition.)
精彩评论