I have to extend and modify the program to:
Redirect(>)standard output from a command to a file. If the file already exist, it will beerased and overwritten without warning.
Examples:
Code:
COP$ ls > 1
COP$ sort myshell.c > 2
Append( >>)standard output from a command to a file if the file exists; if the file does not exist,create one. Examples:
Code:
COP$ sort myshell.c >> 1
COP$ echo "Add A Line" >> 1
Redirect the standard input to be from a file, rather than the keyboard. For example:
Code:
COP$ sort < myshell.c
COP$ sort < myshell.c > 1
COP$ sort > 1 < myshell.c
and lastly pass ( |)the standard output of one command to another for further processing. Examples:
Code:
COP$ ls | sort
COP$ sort < myshell.c | grep main | cat > output
Heres what I got so far:
Code:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define MAX_ARGS 20
#define BUFSIZ 1024
int get_args(char* cmdline, char* args[])
{
int i = 0;
/* if no args */
if((args[0] = strtok(cmdline, "\n\t ")) == NULL)
return 0;
while((args[++i] = strtok(NULL, "\n\t ")) != NULL) {
if(i >= MAX_ARGS) {
printf("Too many arguments!\n");
exit(1);
}
}
/* the last one is always NULL */
return i;
}
void execute(char* cmdline)
{
int pid, async;
char* args[MAX_ARGS];
int nargs = get_args(cmdline, args);
if(nargs <= 0) return;
if(!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) {
exit(0);
}
/* check if async call */
if(!strcmp(args[nargs-1], "&")) { async = 1; args[--nargs] = 0; }
else async = 0;
pid = fork();
if(pid == 0) { /* child process */
execvp(args[0], args);
/* return only when exec fails */
perror("exec failed");
exit(-1);
} else if(pid > 0) { /* parent process */
if(!async) waitpid(pid, NULL, 0);
else printf("this is an async call\n");
} else { /* error occurred */
perror("fork failed");
exit(1);
}
}
int main (int argc, char* argv [])
{
char cmdline[BUFSIZ];
for(;;) {
printf("COP4338$ ");
if(fgets(cmdline, BUFSIZ, stdin) == NULL) {
perror("fgets failed");
exit(1);
}
execute(cmdline) ;
}
return 0;
}