home *** CD-ROM | disk | FTP | other *** search
- /*
- * MSH - The Marvin Shell, a shell that complains a lot.
- * Written by Noah Friedman for his weird mother.
- *
- * MSH takes input from the command line, and then complains a
- * lot about it, even though it really uses your SHELL to process
- * the actual commands, and it uses the program defined by
- * MARVIN_COMPLAINT_PROGRAM to do most of the complaining. It's
- * sort of a front and back end to simulate an electronic sulking
- * machine. Sometimes MSH will ignore your command, and marvin will
- * indicate that he hopes your diodes rot.
- *
- * If you move the location of the marvin program (the one that
- * looks up complaints and prints them), you will need to recompile
- * Both this program and the marvin program itself. It should be simple
- * enough to change marvin.h and then type "make"
- */
-
- #include "marvin.h"
- #include <stdio.h>
- #include <string.h>
- #include <signal.h>
- #include <ctype.h>
-
- /* Macro to return the number of elements in a structure */
- #define DIM(x) (sizeof(x) / sizeof(x[0]))
- #define IGNORE_FREQUENCY 5 /* probability of marvin ignoring you */
-
- char *getenv(), *setenv();
-
- char *getcmd();
- char *cwd();
- int cls();
- int dos();
- int exitcmd();
- int breakhandler();
- int setprompt();
- int ver();
-
- struct cmdtable
- {
- char *cmdname;
- int (*cmdfn)(char *);
- };
-
- struct cmdtable commands[] =
- {
- "cls", cls,
- "prompt", setprompt,
- "exit", exitcmd,
- };
-
- extern char **environ;
-
- char shell[64], prompt[128];
-
- error(code, str, status)
- int code, status;
- char *str;
- {
- char *p;
-
- switch (code)
- {
- case 1:
- p = "The computer won't let me take control. Bye.\n";
- break;
- case 2:
- mputs("*sigh* here you want me to run commands and you misplace \n");
- mputs(shell); mputs(". How depressingly stupid. Goodbye.\n");
- mputs("\n<exiting msh>\n");
- exit(1);
- break;
- }
- if (str)
- mputs(str);
- mputs(p);
- if (status)
- exit(status);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char inbuf[129], *p;
- long tm;
-
- getshell(shell);
- strcpy(prompt, STANDARD_PROMPT);
- if ((int) signal(SIGINT, breakhandler) == -1)
- error(1, NULL, 1);
- mputs("Marvin's SHell (MSH) version -3.14");
- mputs("\n\nI will not enjoy myself.\n\n");
- while (1)
- {
- if ((p = getcmd(inbuf)) == NULL)
- continue;
- time(&tm);
- if (tm % IGNORE_FREQUENCY == 0)
- {
- ignore_command();
- continue;
- }
- while (*p == ' ') *p++;
- if (!intrinsic(inbuf))
- extrinsic(inbuf);
- }
- }
-
- mputs(str) /* My puts() function. No newline appended */
- register char *str;
- {
- while (*str != '\0')
- putchar(*str++);
- }
-
- ignore_command()
- {
- if (rand() % 2 == 0)
- mputs("I think you ought to know I'm feeling very depressed. Go away.\n\n");
- else
- mputs("Humans are so depressingly demanding. Why don't you do it yourself?\n\n");
- }
-
- intrinsic(inbuf)
- char *inbuf;
- {
- register int i;
- char first[129];
-
- for (i = 0; inbuf[i] != ' ' && inbuf[i] != '\0'; i++)
- first[i] = inbuf[i];
- first[i] = '\0';
- for (i = 0; i < DIM(commands); i++)
- if (strcmp(commands[i].cmdname, first) == 0)
- {
- int (*fnptr)(char *) = commands[i].cmdfn;
-
- (*fnptr)(inbuf);
- return 1;
- }
- return 0;
- }
-
- extrinsic(inbuf)
- char *inbuf;
- {
- if (system(inbuf) == 127)
- error(2, NULL, 0);
- switch (fork())
- {
- case 0:
- execl(MARVIN_COMPLAINT_PROGRAM, MARVIN_COMPLAINT_PROGRAM, NULL);
- break;
- case -1:
- perror("fork");
- break;
- default:
- wait(0);
- break;
- }
- }
-
- char *getcmd(buffer)
- char *buffer;
- {
- putprompt();
- gets(buffer);
- if (feof(stdin)) exitcmd();
- if (strlen(buffer) == 0) return NULL;
- return buffer;
- }
-
- getshell(buffer)
- char *buffer;
- {
- strcpy(buffer, getenv("SHELL"));
- if (*buffer == NULL)
- {
- setenv("SHELL=/bin/csh");
- strcpy(buffer, getenv("SHELL"));
- }
- }
-
- breakhandler()
- {
- signal(SIGINT, breakhandler); /* reset handler */
- putprompt();
- }
-
- cls(dummy)
- char *dummy;
- {
- if (system("clear") == 127)
- error(2, NULL, 0);
- mputs("Clear the screen, clear the screen.. All the time I have to\n");
- mputs("do stupid pointless tasks. Why can't you just keep your screen\n");
- mputs("clean in the first place, instead of making extra work for me?\n");
- mputs("*sigh*\n");
- }
-
- exitcmd(dummy)
- char *dummy;
- {
- mputs("\nNot even a thank you? Well good riddance to you too then. Sheesh.\n");
- exit(0);
- }
-
- setprompt(inbuf)
- char *inbuf;
- {
- char *p;
-
- mputs("Isn't the prompt you've already got good enough? picky picky..\n\n");
- p = strchr(inbuf, ' ') + 1;
- if (*p == '\0')
- strcpy(prompt, "$n$g");
- else
- strcpy(prompt, p);
- }
-
- putprompt()
- {
- char *p = prompt;
-
- while (*p != '\0')
- {
- if (*p != '$')
- putchar(*p++);
- else
- {
- switch (toupper(*(++p)))
- {
- case '_': putchar('\n'); break;
- case '$': putchar('$'); break;
- case 'E': putchar('\033'); break;
- case 'G': putchar('>'); break;
- case 'H':
- putchar(8);
- putchar(' ');
- putchar(8);
- break;
- case 'N': putchar(drive()); break;
- case 'P': mputs(cwd()); break;
- }
- p++;
- }
- }
- }
-
- char *cwd()
- {
- static char cwd[80];
-
- getwd(cwd, 80);
- return cwd;
- }
-
- drive()
- {
- return 'C'; /* What the hell - this shell is pretty crufty anyway */
- }
-