Advertisement
shortspecialbus

shell.c

May 19th, 2021
913
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.33 KB | None | 0 0
  1. /*
  2.  * cs537 Project 1 - Shell
  3.  *
  4.  * Written by Stefan Strandberg (stefan@cs.wisc.edu)
  5.  * $Id: shell.c,v 1.10 2004/09/23 22:00:27 stefan Exp $
  6.  *
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <sys/wait.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include "shell.h"
  16. #include "job.h"
  17.  
  18. #define MAX_INPUT_SIZE 512
  19. #define MAX_JOBS 32766
  20.  
  21.  
  22. ///////////////////////
  23. //
  24. // create_shell()
  25. //
  26. //   * creates a shell and returns it
  27. //
  28. ///////////////////////
  29.  
  30. shell_t *create_shell(void) {
  31.     shell_t *shell = (shell_t*)malloc(MAX_INPUT_SIZE);
  32.     if(shell == NULL) {
  33.         fprintf(stderr, "Unable to malloc() in create_shell!!\n");
  34.         exit(1);
  35.     }
  36.     shell->prompt = "turtle > ";
  37.    
  38.     return shell;
  39. }
  40.  
  41.  
  42.  
  43. /////////////////////////
  44. //
  45. // do_jobcmd()
  46. //
  47. //   * executes what's needed for the 'j' shell command
  48. //
  49. //   * FIXME: pid/waitpid problems, although it works.
  50. //
  51. /////////////////////////
  52.  
  53. void do_jobcmd(job_t *job[], int jobnums) {
  54.     int c, result, status;
  55.     for (c = 0 ; c < jobnums - 1 ; c++) {
  56.         result = waitpid(job[c]->pid, &status, WNOHANG);
  57.         // the below shouldn't really work, but it seems to.  I don't care.
  58.         switch (result) {
  59.             case (0): // still running
  60.                 print_job(job[c]);
  61.             case (-1):  // who cares, as long as it's not running.  Probably
  62.                         // got reaped weird or something.
  63.             default: // being reaped.
  64.             break;
  65.         }
  66.     }
  67.     return;
  68. }
  69.  
  70.  
  71.  
  72. //////////////////////////
  73. //
  74. // do_waitcmd()
  75. //
  76. //   * does what's needed for the 'w' shell command
  77. //
  78. //////////////////////////
  79.  
  80. void do_waitcmd(job_t *job) {
  81.     int status;
  82.     waitpid(job->pid, &status, 0);
  83.     printf("Job %d terminated\n", job->jid);
  84.    
  85. }
  86.  
  87.  
  88.  
  89. ////////////////////////////
  90. //
  91. // run_shell()
  92. //
  93. //   * runs the shell, pretty much does everything.  lots going on here
  94. //  
  95. //   *FIXME:  Memory leak stuff
  96. //   *FIXME:  Extra code here, but I'm out of time
  97. //
  98. ///////////////////////////
  99.  
  100. int run_shell(shell_t *shell, int interactive, int *jobnum, job_t *job,
  101.               FILE *inbuffer) {
  102.     action_t retval = NORMAL;
  103.     char *exitcmd = "exit";
  104.     char *backgroundcmd = "&";
  105.     char *jobcmd = "j";
  106.     char *waitcmd = "w";
  107.     char *command;
  108.     char *args[MAX_INPUT_SIZE];
  109.     char *lastarg = NULL;
  110.     int arg_counter = 0;
  111.     int background = 0;
  112.     int status;
  113.    
  114.     char buffer[2 * MAX_INPUT_SIZE];
  115.     char *input = malloc(2 * MAX_INPUT_SIZE);
  116.     if (input == NULL) {
  117.         fprintf(stderr, "Unable to malloc() in run_shell()!!\n\n");
  118.         exit(1);
  119.     }
  120.     if (interactive)
  121.         printf("%s", shell->prompt);
  122.     input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
  123.     // what the heck do we do with the rest of the line if more than 512??
  124.     if (input == NULL)  { // EOF or Ctrl-D
  125.         return EXITVAL;
  126.     }
  127.     //printf("%s\n", inbuffer);
  128.     if ((strlen(input)) >= MAX_INPUT_SIZE) {
  129.         fprintf(stderr, "Error: Command too long!!\n");
  130.         if (!interactive) { // echo it
  131.             printf("%s\n", input);
  132.             //fflush(stdout);
  133.         }
  134.         while ((strlen(input)) >= MAX_INPUT_SIZE) { // flush it
  135.             // reallocate the pointer
  136. //          free(input);
  137. //          char *input = malloc(2 * MAX_INPUT_SIZE);
  138. //          if (input == NULL) {
  139. //              fprintf(stderr, "Unable to malloc() in run_shell()!!\n\n");
  140. //              exit(1);
  141. //          }
  142.             input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
  143.             // reset input
  144.             fflush(inbuffer);
  145.         }
  146.         // flush it one more time
  147.         input = fgets(buffer, MAX_INPUT_SIZE + 1, inbuffer);
  148.         *jobnum += 1; // inc the job counter
  149.         return (NORMAL);
  150.  
  151.     }
  152.    
  153.     if (input == NULL)  { // EOF or Ctrl-D
  154.         retval = EXITVAL;
  155.     }
  156.     else
  157.         if (!interactive) {
  158.             printf("%s", input);
  159.             //fflush(stdout); // add this back if i turn buffering back on
  160.         }
  161.  
  162.     char *token = strtok(input, " \n\t");
  163.     if (token == NULL) {// just ignore an all whitespace string
  164.         return retval;
  165.     }
  166.  
  167.     // ignore a single &
  168.     if ((!retval) && !(strcmp(token, backgroundcmd) == 0)){
  169.         command = token;
  170.         args[arg_counter++] = token; // first arg should be program
  171.         // check for the wait command
  172.         while((token != NULL) && (retval < 1) && (retval != WAITERROR)) { // we don't want a jid retval
  173.             lastarg = token;
  174.             args[arg_counter++] = token = strtok(NULL, " \n\t");
  175.         }
  176.         if (lastarg[strlen(lastarg) - 1] == '&') {
  177.             background = 1;
  178.             if (strcmp(lastarg, backgroundcmd) == 0)
  179.                 // remove the last arg, it's a single &
  180.                 args[--arg_counter] = NULL;
  181.             else {
  182.                 // erase the last character
  183.                 args[arg_counter - 2] = strtok(lastarg, "&");
  184.             }
  185.         }
  186.         // check to see if we had a shell command
  187.         if (strcmp(command, waitcmd) == 0) {
  188.             // check to see if we had right number of args
  189.             if (arg_counter != 3)
  190.                 retval = WAITERROR;
  191.             else {
  192.                 retval = atoi(args[arg_counter - 2]);
  193.                 // check for 0 retval, it's bad
  194.                 if (retval == 0)
  195.                     retval = WAITERROR; // treat it as a bad arg, no jid of 0
  196.             }
  197.         }
  198.         if(strcmp(command, exitcmd) == 0) {
  199.             retval = EXITVAL;
  200.         }
  201.         if(strcmp(command, jobcmd) == 0)
  202.             retval = JOBVAL;
  203.         // create a job
  204.         if (retval == 0) {
  205.             create_job(*jobnum, 0, command, --arg_counter, args,
  206.                              background, job);
  207.             *jobnum += 1;
  208.            
  209.             //// DO THE JOB!!
  210.             job->pid = fork();
  211.             if (job->pid == -1) {
  212.                 fprintf(stderr, "UNABLE TO FORK!! DYING!!\n");
  213.                 exit(1);
  214.             }
  215.    
  216.             if (job->pid > 1) { // we are the parent...deal with stuff
  217.                 if (!job->background) { // just wait for it to die
  218.                     waitpid(job->pid, &status, 0);
  219.                 }
  220.             } else { // we are the child!!
  221.                 if ((execv(job->command, job->args)) < 0) {
  222.                     fprintf(stderr, "Unable to exececute your command\n");
  223.                     retval = CHILDEXIT; // 1 makes it exit...
  224.  
  225.                 }
  226.             }
  227.         }
  228.     }
  229.    
  230.     return retval;         
  231. }
  232.  
  233.  
  234.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement