I am trying to complete an assignment which consists in emulating a simple shell program, that gets only 2 parameters and it runs sequentially or concurrently, depending on the user input.
Alhough, I am having a hard time implementing the concurrent version, because when I type in the input sleep 1 &
(the ampersan indicates concurrency), the parent does not wait for the child as expected and keeps iterating, but when it goes to the second iteration of the while loop the readSplit
function, instead of pausing the program to wait to the user input, it takes the empty buff
as input.
Nevertheless, if I write sleep 1
, ls
or any command that only requires 2 parameters it works fine.
Some clarifications:
-readSplit
just gets the input of the user. It works like the read() function, but it stops reading when it arrives to the separation character. (I know there is a better function that does the same, but this code was provided by the course).
int readSplit( int fin, char* buff, char* s, int maxlen ) {
int i = 0;
int oneread = 1;
char c = *s+1;
while(c != *s && c != '\n' && oneread == 1 && i < maxlen) {
oneread = read( fin, &c, 1);
if(c != *s && c != '\n' && oneread == 1) {
buff[i] = c;
i++;
}
}
if(c=='\n') *s = c;
if(i < maxlen) buff[i] = '\0';
return i;
}
-startTimer
and endTimer
can be ignored, they are just measuring the execution time.
MAIN code:
#include <sys/types.h> /* pid_t */
#include <sys/wait.h> /* waitpid */
#include <sys/types.h> /* pid_t */
#include <sys/wait.h> /* waitpid */
#include <stdio.h> /* printf, perror */
#include <stdlib.h> /* exit */
#include <unistd.h> /* _exit, fork */
#include <string.h>
#include "myutils.h"
int main(void) {
int ret;
int status;
char buff[80];
char buff_aux[80];
char ampersan[1];
long timer;
int continueloop = 1;
while (continueloop == 1) {
char s = ' '; //Separator
/*Cleaning the information in each loop*/
memset(buff, 0, sizeof (buff));
memset(buff_aux, 0, sizeof (buff_aux));
memset(ampersan, 0, sizeof (ampersan));
write(1, ">", 1);
/*Reading user input*/
readSplit(0, buff, &s, 80);
printf("%s its my buff string\n", buff);
if (strcmp(buff, "exit") == 0)break; //If the user wants to exit
/*If the user has one more parameter we read it and put it in the buff_aux*/
if (s == ' ' ) {
if (readSplit(0, buff_aux, &s, 80) == 0)
exit(1);
}
printf("%s is my buff_aux string\n", buff_aux);
if (s == ' ' ) {
readSplit(0, ampersan, &s, 1);
printf("%c is the letter read by ampersan\n", ampersan[0]);
}
startTimer();
/*Creating child*/
ret = fork();
printf("ret %d\n", ret);
printf("im checking if it is a child\n");
if (ret == 0) {
printf("im a child\n");
if (buff[0] == 0) {
printf("Son: shell program does not exist\n");
exit(255);
} else if (buff_aux[0] == 0 || buff_aux[0] == '&') {
printf("Im about to execute 1\n");
execlp(buff, buff, NULL);
exit(2);
} else {
printf("Im about to execute 2\n");
execlp(buff, buff, buff_aux, NULL);
exit(2);
}
}
if (ampersan[0] != '&') {
wait(NULL);
timer = endTimer();
printf("The process finished and lasted ... %li miliseconds\n", timer);
}
}
/*waiting to children to finish*/
while (wait(NULL) > 0);
timer=endTimer();
printf("Father waited for son\n");
if (WIFEXITED(status)) {
status = WEXITSTATUS(status);
if (status > 0) printf("Father: shell program does not exist\n");
}
return 0;
}
Thank you in advance!
if you input sleep 1 &
, input buffer is sleep 1 &\n
first while:
readSplit(0, buff, &s, 80);
, buff
is sleep
, input buffer left 1 &\n
readSplit(0, buff_aux, &s, 80)
, buffer_aux
is 1
, input buffer left &\n
readSplit(0, ampersan, &s, 1);
ampersan
is &
, input buffer left \n
next while:
input buffer left \n
readSplit(0, buff, &s, 80);
, buff
is empty, c is \n
, in child process will call:if (buff[0] == 0) {
printf("Son: shell program does not exist\n");
exit(255);
}
you should handle \n
in each while