void executeCommand(_Bool in_background, char *tokens[]) { if (isBuiltInCommand(tokens)) { executeBuiltInCommand(tokens); } else { //external command, execute as separate process pid_t pID = fork(); if (pID == 0) { //in child /* execvp() ONLY returns is an error has occurred. Otherwise child * process is chest-popped by the call to execvp (it is terminated)*/ if (execvp(tokens[0], tokens) == -1) { write(STDOUT_FILENO, strerror(errno), strlen(strerror(errno))); write(STDOUT_FILENO, "\n", strlen("\n")); exit(0); } } else if (pID < 0) { perror("Failed to fork"); return; } //parent if (!in_background) { if (waitpid(pID, NULL, 0) == -1) perror("Error waiting for child to exit"); } else { //give time for child to finish executing before returning to loop //to ensure new prompt is printed after results of previous command usleep(10000); } cleanupZombies(); } }
int main(int argc, char *argv[]) { char command[200]; getInstanceDetails(); while(1) { generateShellPrompt(); gets(command); const char token_parm[2] = ";"; char *token; char command_parsed[100][100]; int token_counter = 0; token = strtok(command, token_parm); while(token != NULL) { strcpy(command_parsed[token_counter], token); token_counter++; token = strtok(NULL, token_parm); } int i; for(i=0; i<token_counter; i++) { char *specific_token; const char specific_parm[2] = " "; char specific_parsed[100][100]; int specific_counter = 0; specific_token = strtok(command_parsed[i], specific_parm); while(specific_token != NULL) { strcpy(specific_parsed[specific_counter], specific_token); specific_counter++; specific_token = strtok(NULL, specific_parm); } if(strcmp(specific_parsed[0], "cd")==0 || strcmp(specific_parsed[0], "echo")==0 || strcmp(specific_parsed[0],"pwd")==0) { executeBuiltInCommand(specific_parsed); } else if(strcmp(specific_parsed[0],"exit")==0) { return 0; } else { pid_t pid; int status; pid = fork(); int t; char *arg[100]; for(t=0;t<specific_counter;t++) { arg[t] = specific_parsed[t]; } if(pid < 0) { perror("ERROR: in forking new process\n"); exit(1); } else if(pid==0) { int ret; ret = execvp(arg[0], arg); if(ret < 0) { perror("ERROR : in execvp()\n"); exit(1); } exit(0); } for(t=0;t<specific_counter;t++) { arg[t] = '\0'; } wait(); } } } return 0; }
int main(int argc, char *argv[]) { struct CommandData* Cmd_Data = malloc(sizeof(*Cmd_Data)); pid_t pid1, pid2; //character array initialized to the size of PATH_MAX+1, PATH_MAX is the //maximum length a path can be. From limits.h char currentDir[PATH_MAX + 1]; //Character line that will be passed to the parser char* line; //Line to be parsed int tempBuiltIn; int tempFdIn = 1, tempFdOut = 0, fdIn = -1, fdOut = -1; int fd[2]; fd[READ] = -1; //output fd[WRITE] = -1; //input int pipeNeeded = 0; //No pipe needed at first int loopcntr = 1; //Not sure if this is correct setenv("DEBUG", "NO",1); //Loop forever while(loopcntr){ //character arrays to store both the environment variable name and value char* envName[256]; char* envVal[256]; //initializing them for(int i = 0; i <= 256; i++){ if(i == 256){ envName[i-1] = '\0'; envVal[i-1] = '\0'; } else{ envName[i] = "."; envVal[i] = "."; } } //Print shell prompt if (getcwd(currentDir, sizeof(currentDir)) != NULL){ fprintf(stdout, "%s>", currentDir); } //Read in the line of commands line = read_line(); //Parse the line memset(Cmd_Data , 0, sizeof(*Cmd_Data)); ParseCommandLine(line, Cmd_Data); tempBuiltIn = is_built_in(Cmd_Data); //Was the command entered a built in command? if(tempBuiltIn != -1){ //if the input string had an assignment operation, extract the name //and value from the input string and store them in envName, envVal. if(isEnvAssignment == 1){ int cntr = 0; int j = 0; while(j < sizeof(*line)){ if(line[j] == ' ') break; j++; } for(int i = j; i < sizeof(*line); i++){ if(line[i] == '\0') envVal[i] = '\0'; else if(line[i] == '='){ envName[i] = '\0'; cntr = i; } else if(i > cntr) envVal[i] = &line[i]; else envName[i] = &line[i]; } isEnvAssignment = 0; fprintf(stdout, "Command: %s\n", envVal[0]); setenv(*envName, *envVal, 0); } //execute the built in command. envName, and envVal are passed in to //allow export to execute. executeBuiltInCommand(Cmd_Data, tempBuiltIn, &loopcntr, *envName, *envVal); } else{ //Check if input file needs to be opened if(Cmd_Data->infile != NULL){ char* temp = Cmd_Data->infile; fdIn = open(temp, O_RDONLY, 0); //Get FD for the file tempFdIn = dup(STDIN_FILENO); } //Check if output file needs to be opened if(Cmd_Data->outfile != NULL){ char* temp = Cmd_Data->outfile; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fdOut = open(temp, O_WRONLY | O_CREAT | O_TRUNC, mode); tempFdOut = dup(STDOUT_FILENO); } //Is a pipe needed? if(Cmd_Data->numcommands > 1){ pipe(fd); pipeNeeded = 1; //Set as true } //Create a child process pid1 = fork(); //Was there an error during the fork? if(pid1 == -1){ fprintf(stderr,"ERROR WITH FORK\n"); } //Child process else if(pid1 == 0){ if(pipeNeeded){ //Fork again pid2 = fork(); //Was there an error during the fork? if(pid2 == -1){ fprintf(stderr,"ERROR WITH FORK\n"); } //Child process else if(pid2 == 0){ //Was an output file opened? if(fdOut != -1){ dup2(fdOut, STDOUT_FILENO); //Make STDOUT point at fdIn close(fdOut); //Not needed anymore } ; close(fd[WRITE]); dup2(fd[READ], STDIN_FILENO); close(fd[READ]); execCmd(Cmd_Data, 1); close(STDIN_FILENO); } //Parent process else{ //Was an input file opened? if(fdIn != -1){ dup2(fdIn, STDIN_FILENO); //Make STDIN point at fdIn close(fdIn); //Not needed anymore } close(fd[READ]); dup2(fd[WRITE], STDOUT_FILENO); close(fd[WRITE]); execCmd(Cmd_Data, 0); close(STDOUT_FILENO); } } else{ //Was an input file opened? if(fdIn != -1){ dup2(fdIn, STDIN_FILENO); //Make STDIN point at fdIn close(fdIn); //Not needed anymore } //Was an output file opened? if(fdOut != -1){ dup2(fdOut, STDOUT_FILENO); //Make STDOUT point at fdOut close(fdOut); //Not needed anymore } execCmd(Cmd_Data, 0); } } //Parent process else{ //Command running in background? if(!Cmd_Data->background){ for(int i = 0; i < 2; i++) wait(NULL); //Wait on the child process } //Close the fds in parent close(fdIn); close(fdOut); close(fd[0]); close(fd[1]); //Reset pipe variable pipeNeeded = 0; //Reset fd values fdIn = fdOut = fd[READ] = fd[WRITE] = -1; //Return STDIN and STDOUT to their proper fd's dup2(tempFdIn, STDIN_FILENO); dup2(tempFdOut, STDOUT_FILENO); } } //char* aux = getenv("DEBUG"); //if(*aux == "NO") print_info(Cmd_Data); } exit(0); }
int main(int argc, char *argv[]) { initShell(); //signal(SIGCHLD, SIG_IGN); //Declarations int bytes_read,no_of_tokens,no_of_commands=0,redirectFlag=0; char uname[80],homedir[256],input[1024],hostname[80],tempstr[256],cwd[256]; char *cmdline, *sentence, *line, *token,**savedTokens, **command, *cmd, *mcptr, *com; size_t length,homedirlen; pid_t childPid; //Change Shell home dir to ~ getcwd(homedir , sizeof(homedir) ); getusername(uname); homedirlen=strlen(homedir); strcpy(cwd,homedir); /* int ptr=0; for(ptr=0;ptr<=1000;ptr++) { jobs[ptr]=NULL; }*/ int exit_flag=0; while (1) { sigset_t mask, prevmask; //Initialize mask with just the SIGCHLD signal sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &prevmask); /*block SIGCHLD, get previous mask*/ no_of_tokens=0; command=malloc ( 200 * sizeof(char)); //Number of commands there can be will be stored in 2D Array cmdline = (char *) malloc (1025 * sizeof(char)); line = (char *) malloc (1025 * sizeof(char)); cmd = (char *) malloc (1025 * sizeof(char)); savedTokens=malloc ( 100 * sizeof(char)); //Number of tokens there can be strcpy(line,"\n"); gethostname(hostname, sizeof(hostname)); getcwd(cwd , sizeof(cwd) ); //printf("PRINT THIS : %s\n",cwd+homedirlen ); //printf("CWD: %d HOMEDIR: %d\n",strlen(cwd),strlen(homedir) ); if( strncmp( cwd, homedir, homedirlen-1) == 0) // && strncmp( cwd, homedir, homedirlen-1)!=0) //If the current working directory is not ~ { strcpy(tempstr,"~"); //printf("HOME DIR IS: %s\n",tempstr ); strcat(tempstr,cwd+homedirlen); strcpy(cwd, tempstr); } int jumper=setjmp(env); printf("<%s@%s:%s>",uname,hostname,cwd ); //PROMPT getline (&line, &length+1, stdin); //PARSING: //Stage 1: Handling multiple commands: int k=0; token = strtok (line, ";"); command[k]=token; while ( token!=NULL ) { command[k]=token; token = strtok (NULL,";"); k++; } no_of_commands=k-1; if(no_of_commands==-1) { printf("Exiting main shell!\n"); printf("\n"); return 0; } else if(command[no_of_commands]!=NULL) { int len=strlen(command[no_of_commands]); command[no_of_commands][len-1]=0; //Last token gets an extra \n .. therefore removed here. } //STAGE 2: for(k=0;k<=no_of_commands;k++) { /* sigset_t mask, prevmask; //Initialize mask with just the SIGCHLD signal sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &prevmask); /*block SIGCHLD, get previous mask*/ cmdline = command[k]; com = (char *) malloc (1025 * sizeof(char)); if(command[k]!=NULL) strcpy(com,command[k]); //com stores the whole command to be executed else com=NULL; //Stage 3: Piping int no_of_pipes=0; if(com!=NULL) { redirectFlag=isRedirect(com); no_of_pipes=isPipeJob(com); } if(no_of_pipes!=0) { int status; pid_t procid=fork(); if(procid==0) { executePipe(no_of_pipes,com,redirectFlag,homedir); } else { sigprocmask(SIG_SETMASK, &prevmask, NULL); //Unblocking wait(&status); } } else { int i=0; token = strtok(cmdline,">"); token = strtok(cmdline,"<"); token = strtok(cmdline," \t\n"); if(token==NULL) { no_of_commands=-1; } while(token != NULL) { savedTokens[i]=token; i++; token = strtok (NULL, " \t\n"); } if(i!=0) { no_of_tokens=i-1; cmd=savedTokens[0]; } else { no_of_tokens=0; cmd=NULL; } int len=0; if(savedTokens[no_of_tokens]!=NULL) { len=strlen(savedTokens[no_of_tokens]); } //savedTokens[no_of_tokens][len-1]=0; //Last token gets an extra \n .. therefore removed here. //if ((cmd!=NULL) && ((strcmp("exit",cmd)==0) || (strcmp("Exit",cmd)==0) || (strcmp("exit ",cmd)==0) || (strcmp("Exit ",cmd)==0))) if ((cmd!=NULL) && ((strcmp("quit",cmd)==0) || (strcmp("quit ",cmd)==0) || (strcmp(" quit",cmd)==0))) { //exit(1); exit_flag=1; break; } /*int j=0; while(j<=no_of_tokens) { printf("TOKEN %d: %s\n",j,savedTokens[j]); j++; } */ //record command in history list (GNU readline history ?) int std_out; if(no_of_commands!=-1) { if ( (cmd!=NULL) && isBuiltInCommand(cmd)==1 ) { if(redirectFlag!=0) { executeRedirect(cmd,com,redirectFlag); } if(outfile!=0) { int fd1; if(outfile==1) { fd1=open(output,O_CREAT|O_RDWR|O_TRUNC,00666); lseek(fd1, 0, SEEK_SET); } else if(outfile==2) { fd1=open(output,O_APPEND|O_CREAT|O_RDWR,00666); } if(fd1==-1) { fprintf(stderr, "Can't open file %s for output!\n",output); memset(output, 0, 10); outfile=0; continue; } std_out=dup(1); dup2(fd1,STDOUT_FILENO); close(fd1); memset(output, 0, 10); outfile=0; } if(infile==3) { int fd2; fd2=open(inputfile,O_RDWR,00666); if(fd2==-1) { fprintf(stderr, "Can't open file for input! 4\n"); memset(inputfile, 0, 10); infile=0; continue; } dup2(fd2,STDIN_FILENO); close(fd2); memset(inputfile, 0, 10); infile=0; } job_no++; addJob(0,cmd,0,job_no); executeBuiltInCommand(cmd,savedTokens,no_of_tokens,homedir); dup2(std_out,1); } else { if((com!=NULL) && isBackgroundJob(com)==1) { savedTokens[no_of_tokens]=NULL; } int status; childPid = fork(); switch (childPid) { case 0: //Child Process //setpgid(0,0); //make the current process the group leader //tcsetpgrp(0,getpid()); if(redirectFlag!=0) { executeRedirect(cmd,com,redirectFlag); } if(outfile!=0) { int fd1; if(outfile==1) { fd1=open(output,O_CREAT|O_RDWR|O_TRUNC,00666); lseek(fd1, 0, SEEK_SET); } else if(outfile==2) { fd1=open(output,O_APPEND|O_CREAT|O_RDWR,00666); } if(fd1==-1) { fprintf(stderr, "Can't open file for output 6!\n"); memset(output, 0, 10); outfile=0; continue; } dup2(fd1,STDOUT_FILENO); close(fd1); memset(output, 0, 10); outfile=0; } if(infile==3) { int fd2; printf("%s\n",inputfile); fd2=open(inputfile,O_RDWR,00666); if(fd2==-1) { fprintf(stderr, "Can't open file for input! 5\n"); memset(inputfile, 0, 10); infile=0; continue; } dup2(fd2,STDIN_FILENO); close(fd2); memset(inputfile, 0, 10); infile=0; } executeCommand(cmd,savedTokens,no_of_tokens); //calls execvp /* if exec returns there was an error. */ perror(savedTokens[0]); exit(-1); case -1: perror("Fork"); return -1; default: //In Parent sigprocmask(SIG_SETMASK, &prevmask, NULL); //Unblocking //handler(childPid,cmd,job_no,jobs); //Check if any of the childs exited if (isBackgroundJob(com)==1) { setpgid(childPid,childPid); //added the background process to its own group //tcsetpgrp(0,childPid); savedTokens[no_of_tokens]=NULL; // add pid to some list to track jobs job_no++; printf("[%d][proc %d started]\n",job_no, childPid); addJob(childPid,cmd,1,job_no); // sigprocmask(SIG_SETMASK, &prevmask, NULL); //Unblocking } else { //Add foreground jobs to list: job_no++; //printf("Parent: Here total jobs are %d \n",job_no ); addJob(childPid,cmd,0,job_no); curpid=childPid; // printf("jobs[%d]->cmd: %s\n",job_no,jobs[job_no]->cmd); sigprocmask(SIG_SETMASK, &prevmask, NULL); //Unblocking pid_t wpid; do { wpid = waitpid(childPid, &status, WUNTRACED); //WUNTRACED->status of child processes will be reported here! } while (!WIFEXITED(status) && !WIFSIGNALED(status)); //WIFEXITED reports normal termination and //WIFSIGNALED not 0 status if child process stopped but wasnt caught! removeJob(wpid); curpid=getpid(); //printf("I am removing the fg job with pid %d\n",wpid ); //waitpid (childPid); //printf("HERE! 2\n" ); } } } } } }//end of k loop if(exit_flag==1) break; //free(line); // } //End of while loop return 0; }
int executePipe( int no_of_pipes, char *com, int redirectFlag,char *homedir) { pc *pcmd=malloc(100 * sizeof(pc)); int fd[2]; int isFirstPipe=1; int count = 0; char *commandline=malloc(1024*sizeof(char)); strcpy(commandline,com); char *command=malloc(1024*sizeof(char)); char **argv=malloc ( 100 * sizeof(char)); //Number of tokens there can be char *token=malloc(1024*sizeof(char)); int i=0,j=0; command = strtok ( com,"|"); //first command while( command!=NULL) { pcmd[i].argv=command; pcmd[i].redirectFlag=isRedirect(command); command = strtok (NULL, "|"); i++; } //Tokenise command for execution //parseCommand(pcmd[0].argv,argv); int in=0; for(i=0;i<no_of_pipes;i++) { pipe(fd); spawn_proc(in,fd[1],pcmd[i],pcmd[i].redirectFlag,homedir); close(fd[1]); in=fd[0]; } if(in!=0) dup2(in,0); //last command infile=0; outfile=0; int random=isRedirect(pcmd[i].argv); int no_of_tokens=parseCommand(pcmd[i].argv,argv,pcmd[i].redirectFlag); int std_out=dup(1); if(outfile!=0) { int fd1; if(outfile==1) { fd1=open(output,O_CREAT|O_RDWR|O_TRUNC,00666); lseek(fd1, 0, SEEK_SET); } else if(outfile==2) { fd1=open(output,O_APPEND|O_CREAT|O_RDWR,00666); } if(fd1==-1) { fprintf(stderr, "Can't open file for output 1!\n"); memset(output, 0, 10); outfile=0; return; } dup2(fd1,STDOUT_FILENO); close(fd1); memset(output, 0, 10); outfile=0; //redirectFlag=0; } if(infile==3) { int fd2; fd2=open(inputfile,O_RDWR,00666); if(fd2==-1) { fprintf(stderr, "Can't open file for input! 3\n"); memset(inputfile, 0, 10); infile=0; return; } dup2(fd2,STDIN_FILENO); close(fd2); memset(inputfile, 0, 10); infile=0; //redirectFlag=0; } if(isBuiltInCommand(argv[0])==1) { job_no++; addJob(0,argv[0],0,job_no); executeBuiltInCommand(argv[0],argv,no_of_tokens,homedir); _exit(1); dup2(std_out,1); return(0); } else return(execvp(argv[0],argv)); }
int spawn_proc(int in,int out,pc node,int redirectFlag,char *homedir) { int no_of_tokens=0,std_out; pid_t pid; char **argv=malloc ( 100 * sizeof(char)); //Number of tokens there can be pid=fork(); if(pid<0) { fprintf(stderr, "Error in Piping!\n" ); } else if(pid==0) /* Child */ { infile=0; outfile=0; int random=isRedirect(node.argv); no_of_tokens=parseCommand(node.argv,argv,redirectFlag); if(in!=0) { dup2(in,0); close(in); } if(out!=1) { dup2(out,1); close(out); } if(outfile!=0) { int fd1; if(outfile==1) { fd1=open(output,O_CREAT|O_RDWR|O_TRUNC,00666); lseek(fd1, 0, SEEK_SET); } else if(outfile==2) { fd1=open(output,O_APPEND|O_CREAT|O_RDWR,00666); } if(fd1==-1) { fprintf(stderr, "Can't open file for output!\n"); memset(output, 0, 10); outfile=0; return; } int std_out=dup(1); dup2(fd1,STDOUT_FILENO); close(fd1); memset(output, 0, 10); outfile=0; //redirectFlag=0; } if(infile==3) { int fd2; fd2=open(inputfile,O_RDWR,00666); if(fd2==-1) { fprintf(stderr, "Can't open file for input! 2\n"); memset(inputfile, 0, 10); infile=0; return; } dup2(fd2,STDIN_FILENO); close(fd2); memset(inputfile, 0, 10); infile=0; //redirectFlag=0; } if(isBuiltInCommand(argv[0])==1) { job_no++; addJob(0,argv[0],0,job_no); executeBuiltInCommand(argv[0],argv,no_of_tokens,homedir); dup2(std_out,1); _exit(1); } else return (execvp(argv[0],argv)); } return pid; }