Code:
void launchProg(char **args, int background){
int err = -1;
if((pid=fork())==-1){
printf("Child process could not be created\n");
return;
}
// pid == 0 implies the following code is related to the child process
if(pid==0){
// We set the child to ignore SIGINT signals (we want the parent
// process to handle them with signalHandler_int)
signal(SIGINT, SIG_IGN);
// We set parent=<pathname>/simple-c-shell as an environment variable
// for the child
setenv("parent",getcwd(currentDirectory, 1024),1);
// If we launch non-existing commands we end the process
if (execvp(args[0],args)==err){
printf("Command not found");
kill(getpid(),SIGTERM);
}
}
if (background == 0){
waitpid(pid,NULL,0);
}else{
printf("Process created with PID: %d\n",pid);
}
}
void fileIO(char * args[], char* inputFile, char* outputFile, int option){
int err = -1;
int fileDescriptor; // between 0 and 19, describing the output or input file
if((pid=fork())==-1){
printf("Child process could not be created\n");
return;
}
if(pid==0){
// Option 0: output redirection
if (option == 0){
// We open (create) the file truncating it at 0, for write only
fileDescriptor = open(outputFile, O_CREAT | O_TRUNC | O_WRONLY, 0600);
// We replace de standard output with the appropriate file
dup2(fileDescriptor, STDOUT_FILENO);
close(fileDescriptor);
// Option 1: input and output redirection
}else if (option == 1){
// We open file for read only (it's STDIN)
fileDescriptor = open(inputFile, O_RDONLY, 0600);
// We replace de standard input with the appropriate file
dup2(fileDescriptor, STDIN_FILENO);
close(fileDescriptor);
// Same as before for the output file
fileDescriptor = open(outputFile, O_CREAT | O_TRUNC | O_WRONLY, 0600);
dup2(fileDescriptor, STDOUT_FILENO);
close(fileDescriptor);
}
setenv("parent",getcwd(currentDirectory, 1024),1);
if (execvp(args[0],args)==err){
printf("err");
kill(getpid(),SIGTERM);
}
}
waitpid(pid,NULL,0);
}
void pipeHandler(char * args[]){
// File descriptors
int filedes[2]; // pos. 0 output, pos. 1 input of the pipe
int filedes2[2];
int num_cmds = 0;
char *command[256];
pid_t pid;
int err = -1;
int end = 0;
// Variables used for the different loops
int i = 0;
int j = 0;
int k = 0;
int l = 0;
// First we calculate the number of commands (they are separated
// by '|')
while (args[l] != NULL){
if (strcmp(args[l],"|") == 0){
num_cmds++;
}
l++;
}
num_cmds++;
while (args[j] != NULL && end != 1){
k = 0;
while (strcmp(args[j],"|") != 0){
command[k] = args[j];
j++;
if (args[j] == NULL){
end = 1;
k++;
break;
}
k++;
}
command[k] = NULL;
j++;
if (i % 2 != 0){
pipe(filedes); // for odd i
}else{
pipe(filedes2); // for even i
}
pid=fork();
if(pid==-1){
if (i != num_cmds - 1){
if (i % 2 != 0){
close(filedes[1]); // for odd i
}else{
close(filedes2[1]); // for even i
}
}
printf("Child process could not be created\n");
return;
}
if(pid==0){
if (i == 0){
dup2(filedes2[1], STDOUT_FILENO);
}
else if (i == num_cmds - 1){
if (num_cmds % 2 != 0){ // for odd number of commands
dup2(filedes[0],STDIN_FILENO);
}else{ // for even number of commands
dup2(filedes2[0],STDIN_FILENO);
}
}else{ // for odd i
if (i % 2 != 0){
dup2(filedes2[0],STDIN_FILENO);
dup2(filedes[1],STDOUT_FILENO);
}else{ // for even i
dup2(filedes[0],STDIN_FILENO);
dup2(filedes2[1],STDOUT_FILENO);
}
}
if (execvp(command[0],command)==err){
kill(getpid(),SIGTERM);
}
}
if (i == 0){
close(filedes2[1]);
}
else if (i == num_cmds - 1){
if (num_cmds % 2 != 0){
close(filedes[0]);
}else{
close(filedes2[0]);
}
}else{
if (i % 2 != 0){
close(filedes2[0]);
close(filedes[1]);
}else{
close(filedes[0]);
close(filedes2[1]);
}
}
waitpid(pid,NULL,0);
i++;
}
}
int commandHandler(char * args[]){
int i = 0;
int j = 0;
int fileDescriptor;
int standardOut;
int aux;
int background = 0;
char *args_aux[256];
while ( args[j] != NULL){
if ( (strcmp(args[j],">") == 0) || (strcmp(args[j],"<") == 0) || (strcmp(args[j],"&") == 0)){
break;
}
args_aux[j] = args[j];
j++;
}
// 'exit' command quits the shell
if(strcmp(args[0],"exit") == 0) exit(0);
// 'pwd' command prints the current directory
else if (strcmp(args[0],"pwd") == 0){
if (args[j] != NULL){
// If we want file output
if ( (strcmp(args[j],">") == 0) && (args[j+1] != NULL) ){
fileDescriptor = open(args[j+1], O_CREAT | O_TRUNC | O_WRONLY, 0600);
// We replace de standard output with the appropriate file
standardOut = dup(STDOUT_FILENO);
dup2(fileDescriptor, STDOUT_FILENO);
close(fileDescriptor);
printf("%s\n", getcwd(currentDirectory, 1024));
dup2(standardOut, STDOUT_FILENO);
}
}else{
printf("%s\n", getcwd(currentDirectory, 1024));
}
}
// 'clear' command clears the screen
else if (strcmp(args[0],"clear") == 0) system("clear");
// 'cd' command to change directory
else if (strcmp(args[0],"cd") == 0) changeDirectory(args);
// 'environ' command to list the environment variables
else if (strcmp(args[0],"environ") == 0){
if (args[j] != NULL){
// If we want file output
if ( (strcmp(args[j],">") == 0) && (args[j+1] != NULL) ){
fileDescriptor = open(args[j+1], O_CREAT | O_TRUNC | O_WRONLY, 0600);
// We replace de standard output with the appropriate file
standardOut = dup(STDOUT_FILENO);
dup2(fileDescriptor, STDOUT_FILENO);
close(fileDescriptor);
manageEnviron(args,0);
dup2(standardOut, STDOUT_FILENO);
}
}else{
manageEnviron(args,0);
}
}
// 'setenv' command to set environment variables
else if (strcmp(args[0],"setenv") == 0) manageEnviron(args,1);
// 'unsetenv' command to undefine environment variables
else if (strcmp(args[0],"unsetenv") == 0) manageEnviron(args,2);
else{
while (args[i] != NULL && background == 0){
if (strcmp(args[i],"&") == 0){
background = 1;
}else if (strcmp(args[i],"|") == 0){
pipeHandler(args);
return 1;
}else if (strcmp(args[i],"<") == 0){
aux = i+1;
if (args[aux] == NULL || args[aux+1] == NULL || args[aux+2] == NULL ){
printf("Not enough input arguments\n");
return -1;
}else{
if (strcmp(args[aux+1],">") != 0){
printf("Usage: Expected '>' and found %s\n",args[aux+1]);
return -2;
}
}
fileIO(args_aux,args[i+1],args[i+3],1);
return 1;
}
else if (strcmp(args[i],">") == 0){
if (args[i+1] == NULL){
printf("Not enough input arguments\n");
return -1;
}
fileIO(args_aux,NULL,args[i+1],0);
return 1;
}
i++;
}
launchProg(args_aux,background);
}
return 1;
}