void execute(char *line) { char *cmd; /* command */ int start, end; /* expression delimiters */ if(setExpressionDelimiters(line, "[^| ]([^|]*[^| ])?", &start, &end)) { cmd = getExpression(line, start, end, 0); ignoreSignals(); if(hasPipe(line)) { executePipe(line + end, cmd); } else if(!tryInternalCommand(cmd, JOBS_CONTROL)) { executeExternalCommand(cmd); } free(cmd); } }
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; }