home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2176 / msh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  5.4 KB  |  264 lines

  1. /*
  2.  * MSH - The Marvin Shell, a shell that complains a lot.
  3.  *       Written by Noah Friedman for his weird mother.
  4.  *
  5.  *   MSH takes input from the command line, and then complains a
  6.  *   lot about it, even though it really uses your SHELL to process
  7.  *   the actual commands, and it uses the program defined by
  8.  *   MARVIN_COMPLAINT_PROGRAM to do most of the complaining. It's
  9.  *   sort of a front and back end to simulate an electronic sulking
  10.  *   machine. Sometimes MSH will ignore your command, and marvin will
  11.  *   indicate that he hopes your diodes rot.
  12.  *
  13.  *   If you move the location of the marvin program (the one that
  14.  *   looks up complaints and prints them), you will need to recompile
  15.  *   Both this program and the marvin program itself. It should be simple
  16.  *   enough to change marvin.h and then type "make"
  17.  */
  18.  
  19. #include "marvin.h"
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <signal.h>
  23. #include <ctype.h>
  24.  
  25. /* Macro to return the number of elements in a structure */
  26. #define DIM(x) (sizeof(x) / sizeof(x[0]))
  27. #define IGNORE_FREQUENCY 5 /* probability of marvin ignoring you */
  28.  
  29. char *getenv(), *setenv();
  30.  
  31. char *getcmd();
  32. char *cwd();
  33. int cls();
  34. int dos();
  35. int exitcmd();
  36. int breakhandler();
  37. int setprompt();
  38. int ver();
  39.  
  40. struct cmdtable
  41.   {
  42.    char *cmdname;
  43.    int (*cmdfn)(char *);
  44.   };
  45.  
  46. struct cmdtable commands[] =
  47.   {
  48.    "cls", cls,
  49.    "prompt", setprompt,
  50.    "exit", exitcmd,
  51.   };
  52.  
  53. extern char **environ;
  54.  
  55. char shell[64], prompt[128];
  56.  
  57. error(code, str, status)
  58. int code, status;
  59. char *str;
  60. {
  61.  char *p;
  62.  
  63.     switch (code)
  64.       {
  65.        case 1:
  66.           p = "The computer won't let me take control. Bye.\n";
  67.           break;
  68.        case 2:
  69.           mputs("*sigh* here you want me to run commands and you misplace \n");
  70.           mputs(shell); mputs(". How depressingly stupid. Goodbye.\n");
  71.           mputs("\n<exiting msh>\n");
  72.           exit(1);
  73.           break;
  74.       }
  75.     if (str)
  76.        mputs(str);
  77.     mputs(p);
  78.     if (status)
  79.        exit(status);
  80. }
  81.  
  82. main(argc, argv)
  83. int argc;
  84. char **argv;
  85. {
  86.  char inbuf[129], *p;
  87.  long tm;
  88.  
  89.     getshell(shell);
  90.     strcpy(prompt, STANDARD_PROMPT);
  91.     if ((int) signal(SIGINT, breakhandler) == -1)
  92.        error(1, NULL, 1);
  93.     mputs("Marvin's SHell (MSH) version -3.14");
  94.     mputs("\n\nI will not enjoy myself.\n\n");
  95.     while (1)
  96.       {
  97.        if ((p = getcmd(inbuf)) == NULL)
  98.           continue;
  99.        time(&tm);
  100.        if (tm % IGNORE_FREQUENCY == 0)
  101.          {
  102.           ignore_command();
  103.           continue;
  104.          }
  105.        while (*p == ' ') *p++;
  106.        if (!intrinsic(inbuf))
  107.           extrinsic(inbuf);
  108.       }
  109. }
  110.  
  111. mputs(str) /* My puts() function. No newline appended */
  112. register char *str;
  113. {
  114.  while (*str != '\0')
  115.     putchar(*str++);
  116. }
  117.  
  118. ignore_command()
  119. {
  120.  if (rand() % 2 == 0)
  121.     mputs("I think you ought to know I'm feeling very depressed. Go away.\n\n");
  122.  else
  123.     mputs("Humans are so depressingly demanding. Why don't you do it yourself?\n\n");
  124. }
  125.  
  126. intrinsic(inbuf)
  127. char *inbuf;
  128. {
  129.  register int i;
  130.  char first[129];
  131.  
  132.     for (i = 0; inbuf[i] != ' ' && inbuf[i] != '\0'; i++)
  133.        first[i] = inbuf[i];
  134.     first[i] = '\0';
  135.     for (i = 0; i < DIM(commands); i++)
  136.        if (strcmp(commands[i].cmdname, first) == 0)
  137.          {
  138.           int (*fnptr)(char *) = commands[i].cmdfn;
  139.  
  140.              (*fnptr)(inbuf);
  141.              return 1;
  142.          }
  143.     return 0;
  144. }
  145.  
  146. extrinsic(inbuf)
  147. char *inbuf;
  148. {
  149.  if (system(inbuf) == 127)
  150.     error(2, NULL, 0);
  151.  switch (fork())
  152.    {
  153.     case 0:
  154.         execl(MARVIN_COMPLAINT_PROGRAM, MARVIN_COMPLAINT_PROGRAM, NULL);
  155.         break;
  156.     case -1:
  157.        perror("fork");
  158.        break;
  159.     default:
  160.        wait(0);
  161.        break;
  162.    }
  163. }
  164.  
  165. char *getcmd(buffer)
  166. char *buffer;
  167. {
  168.  putprompt();
  169.  gets(buffer);
  170.  if (feof(stdin)) exitcmd();
  171.  if (strlen(buffer) == 0) return NULL;
  172.  return buffer;
  173. }
  174.  
  175. getshell(buffer)
  176. char *buffer;
  177. {
  178.  strcpy(buffer, getenv("SHELL"));
  179.  if (*buffer == NULL)
  180.    {
  181.     setenv("SHELL=/bin/csh");
  182.     strcpy(buffer, getenv("SHELL"));
  183.    }
  184.  }
  185.  
  186. breakhandler()
  187. {
  188.  signal(SIGINT, breakhandler); /* reset handler */
  189.  putprompt();
  190. }
  191.  
  192. cls(dummy)  
  193. char *dummy;
  194. {
  195.  if (system("clear") == 127)
  196.     error(2, NULL, 0);
  197.  mputs("Clear the screen, clear the screen.. All the time I have to\n");
  198.  mputs("do stupid pointless tasks. Why can't you just keep your screen\n");
  199.  mputs("clean in the first place, instead of making extra work for me?\n");
  200.  mputs("*sigh*\n");
  201. }
  202.  
  203. exitcmd(dummy)
  204. char *dummy;
  205. {
  206.  mputs("\nNot even a thank you? Well good riddance to you too then. Sheesh.\n");
  207.  exit(0);
  208. }
  209.  
  210. setprompt(inbuf)
  211. char *inbuf;
  212. {
  213.  char *p;
  214.  
  215.  mputs("Isn't the prompt you've already got good enough? picky picky..\n\n");
  216.  p = strchr(inbuf, ' ') + 1;
  217.  if (*p == '\0')
  218.     strcpy(prompt, "$n$g");
  219.  else
  220.     strcpy(prompt, p);
  221. }
  222.  
  223. putprompt()
  224. {
  225.  char *p = prompt;
  226.  
  227.     while (*p != '\0')
  228.       {
  229.        if (*p != '$')
  230.           putchar(*p++);
  231.        else
  232.          {
  233.           switch (toupper(*(++p)))
  234.             {
  235.              case '_': putchar('\n');    break;
  236.              case '$': putchar('$');     break;
  237.              case 'E': putchar('\033');  break;
  238.              case 'G': putchar('>');     break;
  239.              case 'H':
  240.                 putchar(8);
  241.                 putchar(' ');
  242.                 putchar(8);
  243.                 break;
  244.              case 'N': putchar(drive()); break;
  245.              case 'P': mputs(cwd());     break;
  246.             }
  247.           p++;
  248.          }
  249.       }
  250. }
  251.  
  252. char *cwd()
  253. {
  254.  static char cwd[80];
  255.  
  256.     getwd(cwd, 80);
  257.     return cwd;
  258. }
  259.  
  260. drive()
  261. {
  262.  return 'C'; /* What the hell - this shell is pretty crufty anyway */
  263. }
  264.