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(); } }
void where(char *arg, struct pathelement *pathlist ) { struct stat sb; /* loop through pathlist until finding command and return it. Return NULL when not found. */ // if(argCount==1){ // fprintf(stderr,"%s\n", "Usage: where [name]"); // return; // } if(!pathlist){ fprintf(stderr, "%s\n", "PATH is empty."); return; } char *cmd = malloc((strlen(arg)+1)*sizeof(char)); strncpy(cmd,arg,strlen(arg)); cmd[strlen(arg)] = '\0'; int found = 0; if(isBuiltInCommand(cmd)!=-1){ printf("%s: %s\n", cmd,"shell built-in Command."); found++; } struct pathelement *path_head = pathlist; DIR *dirp; struct dirent *entry; while(path_head){//iterate each path element //open one directory stream. if(!isDir(path_head->element, &sb)){ path_head = path_head->next; continue; } dirp = opendir(path_head->element); // read each of the entry in DIR while((entry = readdir(dirp)) != NULL){ // if(path_head->) if(strcmp(entry->d_name,cmd)==0){ // found found++; printf("%s/%s\n", path_head->element, cmd); break; } } //move to next. closedir(dirp); path_head = path_head->next; } if(!found){ fprintf(stderr,"%s: %s\n", cmd,"Not found."); // printf("%s\n", arg); } free(cmd); }
void which(char *arg, struct pathelement *pathlist ) { struct stat sb; /* loop through pathlist until finding command and return it. Return NULL when not found. */ if(pathlist==NULL){ fprintf(stderr, "%s\n", "PATH is empty."); return; } char *cmd = malloc(ARG_MAX_LENGTH*sizeof(char)); strncpy(cmd,arg,strlen(arg)); cmd[strlen(arg)] = '\0'; if(isBuiltInCommand(cmd)!=-1){ printf("%s: %s\n", cmd,"shell built-in Command."); free(cmd); return; } struct pathelement *path_head = pathlist; DIR *dirp; struct dirent *entry; // int len = strlen(arg); while(path_head){//iterate each path element // printf("%s\n", "here!!"); if(!isDir(path_head->element, &sb)){ path_head = path_head->next; continue; } dirp = opendir(path_head->element);//open one directory stream. while((entry = readdir(dirp)) != NULL){ // read each of the entry in DIR if(strcmp(entry->d_name,cmd)==0){ // found printf("%s/%s\n", path_head->element, cmd); closedir(dirp); free(cmd); return; } } closedir(dirp); path_head = path_head->next; } fprintf(stderr,"%s: %s\n", cmd,"Not found."); 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; }
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; }