Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * cs537 Project 1 - Shell
- *
- * Written by Stefan Strandberg (stefan@cs.wisc.edu)
- * $Id: shell.c,v 1.10 2004/09/23 22:00:27 stefan Exp $
- *
- */
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "shell.h"
- #include "job.h"
- #define MAX_INPUT_SIZE 512
- #define MAX_JOBS 32766
- ///////////////////////
- //
- // create_shell()
- //
- // * creates a shell and returns it
- //
- ///////////////////////
- shell_t *create_shell(void) {
- shell_t *shell = (shell_t*)malloc(MAX_INPUT_SIZE);
- if(shell == NULL) {
- fprintf(stderr, "Unable to malloc() in create_shell!!\n");
- exit(1);
- }
- shell->prompt = "turtle > ";
- return shell;
- }
- /////////////////////////
- //
- // do_jobcmd()
- //
- // * executes what's needed for the 'j' shell command
- //
- // * FIXME: pid/waitpid problems, although it works.
- //
- /////////////////////////
- void do_jobcmd(job_t *job[], int jobnums) {
- int c, result, status;
- for (c = 0 ; c < jobnums - 1 ; c++) {
- result = waitpid(job[c]->pid, &status, WNOHANG);
- // the below shouldn't really work, but it seems to. I don't care.
- switch (result) {
- case (0): // still running
- print_job(job[c]);
- case (-1): // who cares, as long as it's not running. Probably
- // got reaped weird or something.
- default: // being reaped.
- break;
- }
- }
- return;
- }
- //////////////////////////
- //
- // do_waitcmd()
- //
- // * does what's needed for the 'w' shell command
- //
- //////////////////////////
- void do_waitcmd(job_t *job) {
- int status;
- waitpid(job->pid, &status, 0);
- printf("Job %d terminated\n", job->jid);
- }
- ////////////////////////////
- //
- // run_shell()
- //
- // * runs the shell, pretty much does everything. lots going on here
- //
- // *FIXME: Memory leak stuff
- // *FIXME: Extra code here, but I'm out of time
- //
- ///////////////////////////
- int run_shell(shell_t *shell, int interactive, int *jobnum, job_t *job,
- FILE *inbuffer) {
- action_t retval = NORMAL;
- char *exitcmd = "exit";
- char *backgroundcmd = "&";
- char *jobcmd = "j";
- char *waitcmd = "w";
- char *command;
- char *args[MAX_INPUT_SIZE];
- char *lastarg = NULL;
- int arg_counter = 0;
- int background = 0;
- int status;
- char buffer[2 * MAX_INPUT_SIZE];
- char *input = malloc(2 * MAX_INPUT_SIZE);
- if (input == NULL) {
- fprintf(stderr, "Unable to malloc() in run_shell()!!\n\n");
- exit(1);
- }
- if (interactive)
- printf("%s", shell->prompt);
- input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
- // what the heck do we do with the rest of the line if more than 512??
- if (input == NULL) { // EOF or Ctrl-D
- return EXITVAL;
- }
- //printf("%s\n", inbuffer);
- if ((strlen(input)) >= MAX_INPUT_SIZE) {
- fprintf(stderr, "Error: Command too long!!\n");
- if (!interactive) { // echo it
- printf("%s\n", input);
- //fflush(stdout);
- }
- while ((strlen(input)) >= MAX_INPUT_SIZE) { // flush it
- // reallocate the pointer
- // free(input);
- // char *input = malloc(2 * MAX_INPUT_SIZE);
- // if (input == NULL) {
- // fprintf(stderr, "Unable to malloc() in run_shell()!!\n\n");
- // exit(1);
- // }
- input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
- // reset input
- fflush(inbuffer);
- }
- // flush it one more time
- input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
- *jobnum += 1; // inc the job counter
- return (NORMAL);
- }
- if (input == NULL) { // EOF or Ctrl-D
- retval = EXITVAL;
- }
- else
- if (!interactive) {
- printf("%s", input);
- //fflush(stdout); // add this back if i turn buffering back on
- }
- char *token = strtok(input, " \n\t");
- if (token == NULL) {// just ignore an all whitespace string
- return retval;
- }
- // ignore a single &
- if ((!retval) && !(strcmp(token, backgroundcmd) == 0)){
- command = token;
- args[arg_counter++] = token; // first arg should be program
- // check for the wait command
- while((token != NULL) && (retval < 1) && (retval != WAITERROR)) { // we don't want a jid retval
- lastarg = token;
- args[arg_counter++] = token = strtok(NULL, " \n\t");
- }
- if (lastarg[strlen(lastarg) - 1] == '&') {
- background = 1;
- if (strcmp(lastarg, backgroundcmd) == 0)
- // remove the last arg, it's a single &
- args[--arg_counter] = NULL;
- else {
- // erase the last character
- args[arg_counter - 2] = strtok(lastarg, "&");
- }
- }
- // check to see if we had a shell command
- if (strcmp(command, waitcmd) == 0) {
- // check to see if we had right number of args
- if (arg_counter != 3)
- retval = WAITERROR;
- else {
- retval = atoi(args[arg_counter - 2]);
- // check for 0 retval, it's bad
- if (retval == 0)
- retval = WAITERROR; // treat it as a bad arg, no jid of 0
- }
- }
- if(strcmp(command, exitcmd) == 0) {
- retval = EXITVAL;
- }
- if(strcmp(command, jobcmd) == 0)
- retval = JOBVAL;
- // create a job
- if (retval == 0) {
- create_job(*jobnum, 0, command, --arg_counter, args,
- background, job);
- *jobnum += 1;
- //// DO THE JOB!!
- job->pid = fork();
- if (job->pid == -1) {
- fprintf(stderr, "UNABLE TO FORK!! DYING!!\n");
- exit(1);
- }
- if (job->pid > 1) { // we are the parent...deal with stuff
- if (!job->background) { // just wait for it to die
- waitpid(job->pid, &status, 0);
- }
- } else { // we are the child!!
- if ((execv(job->command, job->args)) < 0) {
- fprintf(stderr, "Unable to exececute your command\n");
- retval = CHILDEXIT; // 1 makes it exit...
- }
- }
- }
- }
- return retval;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement