void shutdown(void) { freecmd(); for (int i = 0; i < file.nused; i++) Fclose(file.filepptr[i]); if (!downloaded) Fclose(cmd); if (genc) free(genc); Strclose(&cmdstr); Strclose(&lastpat); Strclose(&lastregexp); Strclose(&genstr); Strclose(&rhs); Strclose(&wd); Strclose(&plan9cmd); if (file.listptr) free(file.listptr); if (tempfile.listptr) free(tempfile.listptr); freecmdlists(); freebufs(); }
int getcmd(char *prompt, char *args[], int *background) { int length, i = 0; char *token, *loc; char *line = NULL; size_t linecap = 0; printf("%s", prompt); length = getline(&line, &linecap, stdin); if (length <= 0) { exit(-1); } // Check if background is specified.. if ((loc = index(line, '&')) != NULL) { *background = 1; *loc = ' '; } else *background = 0; while ((token = strsep(&line, " \t\n")) != NULL) { int j; for (j = 0; j < strlen(token); j++) if (token[j] <= 32) token[j] = '\0'; if (strlen(token) > 0) args[i++] = token; } freecmd(line); return i; }
void cmdloop(void) { Cmd *cmdp; File *ocurfile; int loaded; for(;;){ if(!downloaded && curfile && curfile->unread) load(curfile); if((cmdp = parsecmd(0))==0){ if(downloaded){ rescue(); exits("eof"); } break; } ocurfile = curfile; loaded = curfile && !curfile->unread; if(cmdexec(curfile, cmdp) == 0) break; freecmd(); cmdupdate(); update(); if(downloaded && curfile && (ocurfile!=curfile || (!loaded && !curfile->unread))) outTs(Hcurrent, curfile->tag); /* don't allow type ahead on files that aren't bound */ if(downloaded && curfile && curfile->rasp == 0) terminp = termoutp; } }
void resetcmd(void) { linep = line; *linep = 0; terminp = termoutp = termline; freecmd(); }
int execute_builtin(cmd_t* cmd, job_list_t* jobs, history_t* hist) { // List jobs. if (strcmp(cmd->args[0], "jobs") == 0) { add_to_history(hist, cmd); return builtin_jobs(jobs); } // List history. if (strcmp(cmd->args[0], "history") == 0) { int exit_code = builtin_history(hist); add_to_history(hist, cmd); return exit_code; } // Exit. if (strcmp(cmd->args[0], "exit") == 0) { return builtin_exit(); } // Change directory. if (strcmp(cmd->args[0], "cd") == 0) { int exit_code = builtin_cd(cmd); if (exit_code == 0) { add_to_history(hist, cmd); } return exit_code; } // Print working directory. if (strcmp(cmd->args[0], "pwd") == 0) { add_to_history(hist, cmd); return builtin_pwd(); } // Bring to foreground. if (strcmp(cmd->args[0], "fg") == 0) { int exit_code = builtin_fg(cmd, jobs); if (exit_code == 0) { add_to_history(hist, cmd); } return exit_code; } // Execute from history. char* endptr = NULL; long num = strtol(cmd->args[0], &endptr, 10); if (*endptr == '\0' && !(num == 0 && errno == EINVAL)) { // Do not save to history to avoid confusion. int exit_code = builtin_exec_from_history(cmd, jobs, hist); freecmd(cmd); return exit_code; } // Command not found. return COMMAND_NOT_FOUND; }
void editerror(char *fmt, ...) { va_list arg; char *s; va_start(arg, fmt); s = vsmprint(fmt, arg); va_end(arg); freecmd(); allwindows(allelogterm, nil); /* truncate the edit logs */ sendp(editerrc, s); threadexits(nil); }
void editthread(void*) { Cmd *cmdp; threadsetname("editthread"); while((cmdp=parsecmd(0)) != 0){ // ocurfile = curfile; // loaded = curfile && !curfile->unread; if(cmdexec(curtext, cmdp) == 0) break; freecmd(); } sendp(editerrc, nil); }
int getcmd(char *prompt, char *args[], int *background) { int length, j, i=0, len=MAX_LINE; char *token, *loc, *line = NULL; size_t linecap = 0; freecmd(args); printf("%s", prompt); length = getline(&line, &linecap, stdin); // will realloc if linecap too small if (length <= 1) return -1; // Check if background is specified.. if ((loc = index(line, '&')) != NULL) { *background = 1; *loc = ' '; } else *background = 0; if (MAX_LINE > strlen(line)+1) len = strlen(line)+1; memcpy(hist[pos%(MAX_HISTORY+1)].lineptr, line, len); // line segmented by '\0', must copy for later use if ((loc = index(hist[pos%(MAX_HISTORY+1)].lineptr, '\n')) != NULL) *loc = '\0'; // if no delimeter found, token taken to be entire &line, and &line made NULL while ((token = strsep(&line, " \t\n")) != NULL) { for (j=0; j < strlen(token); j++) if (token[j] <= 32) token[j] = '\0'; if (strlen(token) > 0) { args[i] = token; i++; } } hist[pos%(MAX_HISTORY+1)].count = i; pos++; return i; }
void getcmdFromHist(char *args[], char *line) { int j, i=0, len=MAX_LINE; char *token; freecmd(args); if (MAX_LINE > strlen(line)+1) len = strlen(line)+1; memcpy(hist[(pos-1)%(MAX_HISTORY+1)].lineptr, line, len); // if no delimiter found, token taken to be entire &line, and &line made NULL while ((token = strsep(&line, " \t\n")) != NULL) { for (j=0; j < strlen(token); j++) if (token[j] <= 32) token[j] = '\0'; if (strlen(token) > 0) { args[i] = token; i++; } } hist[(pos-1)%(MAX_HISTORY+1)].count = i; return; }
int main() { char *args[MAX_ARGS]; int bg, status; pid_t pid, ppid = getpid(); pos = 0; jobs = 0; headP = malloc(sizeof(proc)); if (headP == NULL) return -1; char *parLine = "shell"; push(headP, 0, parLine); // set head proc to parent shell for convenience while (1) { signal(SIGUSR1, histHandler); // signal(SIGCHLD, procHandler); int cnt = getcmd("\n>> ", args, &bg); if (cnt < 0) continue; status = isBuiltIn(args, cnt); if (status == 0) continue; else if (status == 1) if (!isBuiltIn(args, cnt)) continue; pid = fork(); if (pid == -1) perror("fork"); // child else if (pid == 0) { if (execvp(args[0], args) < 0) { printf("exec failure: %s\n", strerror(errno)); kill(ppid, SIGUSR1); exit(EXIT_FAILURE); } else exit(EXIT_SUCCESS); } // parent // note: background processes are implemented such that calling 'r x' on a process implemented as a background process // requires an additional '&' to run that process as a background process as well else { if (bg == 1) { bg = 0; push(headP, pid, hist[(pos-1)%(MAX_HISTORY+1)].lineptr); freecmd(args); kill(ppid, SIGCONT); } else { status=0; waitpid(pid, &status, WUNTRACED); if (status == -1) printf("An error occured in waiting for child proccess %d\n", pid); } } } return 0; }
struct cmdline *readcmd(char *prompt) { static struct cmdline *static_cmdline = 0; struct cmdline *s = static_cmdline; char *line; char **words; int i; char *w; char **cmd; char ***seq; size_t cmd_len, seq_len; line = readline(prompt); if (line == NULL) { if (s) { freecmd(s); free(s); } return static_cmdline = 0; } #ifdef USE_GNU_READLINE else add_history(line); #endif cmd = xmalloc(sizeof(char *)); cmd[0] = 0; cmd_len = 0; seq = xmalloc(sizeof(char **)); seq[0] = 0; seq_len = 0; words = split_in_words(line); free(line); if (!s) { static_cmdline = s = xmalloc(sizeof(struct cmdline)); } else { freecmd(s); } s->err = 0; s->in = 0; s->out = 0; s->seq = 0; s->bg = 0; i = 0; while ((w = words[i++]) != 0) { switch (w[0]) { case '<': /* Tricky : the word can only be "<" */ if (s->in) { s->err = "only one input file supported"; goto error; } if (words[i] == 0) { s->err = "filename missing for input redirection"; goto error; } s->in = words[i++]; break; case '>': /* Tricky : the word can only be ">" */ if (s->out) { s->err = "only one output file supported"; goto error; } if (words[i] == 0) { s->err = "filename missing for output redirection"; goto error; } s->out = words[i++]; break; case '&': /* Tricky : the word can only be "&" */ if (cmd_len == 0) { s->err = "misplaced ampersand"; goto error; } if (s->bg == 1) { s->err = "only one ampersand supported"; goto error; } s->bg = 1; break; case '|': /* Tricky : the word can only be "|" */ if (cmd_len == 0) { s->err = "misplaced pipe"; goto error; } seq = xrealloc(seq, (seq_len + 2) * sizeof(char **)); seq[seq_len++] = cmd; seq[seq_len] = 0; cmd = xmalloc(sizeof(char *)); cmd[0] = 0; cmd_len = 0; break; default: cmd = xrealloc(cmd, (cmd_len + 2) * sizeof(char *)); cmd[cmd_len++] = w; cmd[cmd_len] = 0; } } if (cmd_len != 0) { seq = xrealloc(seq, (seq_len + 2) * sizeof(char **)); seq[seq_len++] = cmd; seq[seq_len] = 0; } else if (seq_len != 0) { s->err = "misplaced pipe"; i--; goto error; } else free(cmd); free(words); s->seq = seq; return s; error: while ((w = words[i++]) != 0) { switch (w[0]) { case '<': case '>': case '|': break; default: free(w); } } free(words); freeseq(seq); for (i = 0; cmd[i] != 0; i++) { free(cmd[i]); } free(cmd); if (s->in) { free(s->in); s->in = 0; } if (s->out) { free(s->out); s->out = 0; } return s; }
int main() { char *args[20]; int argc; struct indexed_string* history[10]; int hist_entry, hist_index = 0; //history_index counts modulo 10 in the struct history array. hist_entry counts the number of the current command we're storing for(int i=0; i<10; i++) history[i]=(struct indexed_string*) malloc(sizeof(struct indexed_string)); //this breaks getline() in getcmd() so that i need to allocate *line before it works int bg, output_r, cnt, child_return, save_history; pid_t child_pid; pid_t pids[MAX_PIDS]; int pid_index=0; while (1) { /* the steps are: (1) fork a child process using fork() (2) the child process will invoke execvp() (3) if background == 0, the parent will wait, otherwise gets the next command... */ bg = 0; save_history = 1; cnt = getcmd("\n>> ", args, &argc, &bg, &output_r); //Print Args for (int i = 0; i < cnt; i++) printf("\nArg[%d] = %s", i, args[i]); //Print Background or No Background (& at the end of cmd) if (bg) printf("\nBackground enabled..\n"); else printf("\nBackground not enabled \n"); printf("\n\n"); //Built-in Commands if (!strcmp(*args,"cd")) { chdir(args[1]); } else if(!strcmp(*args,"pwd")) { char buffer[100]; printf("Current working directory is: \n %s \n", getcwd(buffer,sizeof(buffer))); } else if(!strcmp(*args,"exit")) { exit(1); } else if(!strcmp(*args,"history")) { print_indexed_strings(history,10); } else if(!strcmp(*args,"fg")){ if ((child_pid = atoi(args[1]))) { waitpid(child_pid,&child_return,0); erase_process(pids, child_pid, MAX_PIDS); //erase process id from list of background processes } } else if(!strcmp(*args,"jobs")){ print_int_array(pids, MAX_PIDS); } else { // Fork and create CHILD PROCESS if ((child_pid = fork())) { /* parent doesn't wait: save child process to list */ if (bg) { pids[pid_index]=child_pid; pid_index = (pid_index + 1) % MAX_PIDS; } /* parent waits */ else { waitpid(child_pid, &child_return, 0); //wait for child if int bg is set to 0 if (child_return) save_history=0; //child_return is false only if execvp executed an erroneous command } } else { printf("CHILD PROCESS\n"); // int n = output_redirected(args, argc); output_redirected() is broken and doesn't work // printf("DEBUG: %d redirects\n", output_r); if (*args[1] == '>'){ printf("yes file name %s \n", args[2]); FILE *fd = fopen(args[2],"w"); dup2(fd, 1); // close(1); printf("about to call\n"); // if (!open(args[2])) exit(-1); //unable to redirect output execvp(*args,&*args); } printf("about to execvp with child\n"); execvp(*args, args); exit(-1); } } // c processes logical operators from left to right if (save_history && store_command(history, *args, &hist_index, &hist_entry)) { printf("history index: %d history string: %s\n",history[hist_index]->index,history[hist_index]->string); hist_entry++; hist_index=(hist_index+1)%10; printf("hist index %d\n", hist_index); } print_indexed_strings(history,10); freecmd(args); } }