Path: utzoo!utgpu!cs.utexas.edu!samsung!usc!snorkelwacker.mit.edu!ai-lab!friedman@apple-gunkies.ai.mit.edu From: friedman@apple-gunkies.ai.mit.edu (Noah Friedman) Newsgroups: alt.sources Subject: Re: Joke shell wanted (sources posted) Summary: A shell that complains Keywords: spam spam spam baked beans spam spam spam and spam Message-ID: <12113@life.ai.mit.edu> Date: 30 Nov 90 18:58:19 GMT Sender: news@ai.mit.edu Organization: The Free Software Foundation Lines: 731 Well, someone asked for a joke shell. I ported this to UNIX (it'll work on BSD, and probably System V too, although I haven't checked) from DOS, so the prompt builtin is a little like COMMAND.COM (heaven help us all). Also, there's some irrelevent although harmless code left in in case anyone wants to backport this to DOS (most DOS C libraries' system() function need the COMSPEC environment variable. Some UNIX system() functions automatically use /bin/sh). Share and Enjoy! --- Noah Friedman friedman@ai.mit.edu #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Makefile' <<'END_OF_FILE' XCC = cc XCFLAG = -g X Xall: marvin msh X Xmarvin: marvin.c X $(CC) $(CFLAG) -o marvin marvin.c X Xmsh: msh.c X $(CC) $(CFLAG) -o msh msh.c X Xman: marvin.man6 msh.man6 X nroff -man marvin.man6 > marvin.6 X nroff -man msh.man6 > msh.6 END_OF_FILE if test 221 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test ! -d 'complaints' ; then echo shar: Creating directory \"'complaints'\" mkdir 'complaints' fi if test -f 'marvin.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'marvin.c'\" else echo shar: Extracting \"'marvin.c'\" \(1270 characters\) sed "s/^X//" >'marvin.c' <<'END_OF_FILE' X/* X * MARVIN - Receive a complaint from marvin. X * X * If you move the data files for marvin, you need to recompile the X * program, or nothing will work. To do this, you should be able X * to simply edit the line "#define MARVIN_PATH..." in marvin.h and then X * type "make" X */ X X#include "marvin.h" X X/* You shouldn't need to change anything below here. */ X X#include X Xmain() X{ X FILE *f; X char snum[20], name[1024], str[256]; X int msg, num; X long now; X X /* get the number of available messages */ X if (f = fopen(MARVIN_PATH "number", "rt")) X { X fgets(snum, 20, f); X fclose(f); X } X else X { X fprintf(stderr, "marvin: number: Could not open.\n"); X exit(1); X } X num = atoi(snum); X X time(&now); /* get time value to seed random generator with */ X srand((unsigned) (now % 32767)); /* seed random number generator */ X msg = (int) (rand() % num) + 1; /* get a random message number */ X /* piece together message file name */ X sprintf(snum, "%d", msg); X strcpy(name, MARVIN_PATH); X strcat(name, snum); X X /* open the message file and print out marvin's complaint */ X if (f = fopen(name, "rt")) X { X while (fgets(str, 255, f)) X printf(str); X fclose(f); X } X} END_OF_FILE if test 1270 -ne `wc -c <'marvin.c'`; then echo shar: \"'marvin.c'\" unpacked with wrong size! fi # end of 'marvin.c' fi if test -f 'marvin.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'marvin.h'\" else echo shar: Extracting \"'marvin.h'\" \(528 characters\) sed "s/^X//" >'marvin.h' <<'END_OF_FILE' X/* Path of marvin, the executable program that complains */ X X#define MARVIN_COMPLAINT_PROGRAM "/usr/local/games/marvin" X X/* X * The definition MARVIN_PATH tells the program where to look for X * all the marvin-related stuff, such as the file containing the X * number of complaints, as well as the complaints themself. X * X * Note: The string defined with MARVIN_PATH absolutely *MUST* have X * a '/' at the end (before the quotation mark) X */ X X#define MARVIN_PATH "/usr/local/games/lib/complaints/" X X#define STANDARD_PROMPT "$p % " END_OF_FILE if test 528 -ne `wc -c <'marvin.h'`; then echo shar: \"'marvin.h'\" unpacked with wrong size! fi # end of 'marvin.h' fi if test -f 'marvin.man6' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'marvin.man6'\" else echo shar: Extracting \"'marvin.man6'\" \(923 characters\) sed "s/^X//" >'marvin.man6' <<'END_OF_FILE' X.TH MARVIN 6 "30 November 1990" X X.SH NAME Xmarvin \- receive a complaint from the paranoid android. X X.SH SYNOPSIS X.nf Xmarvin X.SH DESCRIPTION X.PP X Marvin prints out a random complaint. Some of the Xdefaults are variations from the Original Paranoid Android, but any Xcomplaints may be added to the database. X.PP X Complaints are usually located in the X.IR complaints Xdirectory (see FILES), each in a contiguously-numbered file (e.g. "1", "2", X"3", etc). The file X.IR number Xin the X.IR complaints Xdirectory contains the number of separate complaint files. X.SH FILES X /usr/local/games/lib/complaints - Directory for complaints X complaints/number - total number of complaint files X.SH AUTHOR XNoah Friedman (friedman@ai.mit.edu) X.SH BUGS X The program may crash if a file is missing, say, "5", and X.IR marvin Xtries to access it. X I'm not particularly proud of this program. Do what you want with it. :-) END_OF_FILE if test 923 -ne `wc -c <'marvin.man6'`; then echo shar: \"'marvin.man6'\" unpacked with wrong size! fi # end of 'marvin.man6' fi if test -f 'msh.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'msh.c'\" else echo shar: Extracting \"'msh.c'\" \(5563 characters\) sed "s/^X//" >'msh.c' <<'END_OF_FILE' X/* X * MSH - The Marvin Shell, a shell that complains a lot. X * Written by Noah Friedman for his weird mother. X * X * MSH takes input from the command line, and then complains a X * lot about it, even though it really uses your SHELL to process X * the actual commands, and it uses the program defined by X * MARVIN_COMPLAINT_PROGRAM to do most of the complaining. It's X * sort of a front and back end to simulate an electronic sulking X * machine. Sometimes MSH will ignore your command, and marvin will X * indicate that he hopes your diodes rot. X * X * If you move the location of the marvin program (the one that X * looks up complaints and prints them), you will need to recompile X * Both this program and the marvin program itself. It should be simple X * enough to change marvin.h and then type "make" X */ X X#include "marvin.h" X#include X#include X#include X#include X X/* Macro to return the number of elements in a structure */ X#define DIM(x) (sizeof(x) / sizeof(x[0])) X#define IGNORE_FREQUENCY 5 /* probability of marvin ignoring you */ X Xchar *getenv(), *setenv(); X Xchar *getcmd(); Xchar *cwd(); Xint cls(); Xint dos(); Xint exitcmd(); Xint breakhandler(); Xint setprompt(); Xint ver(); X Xstruct cmdtable X { X char *cmdname; X int (*cmdfn)(char *); X }; X Xstruct cmdtable commands[] = X { X "cls", cls, X "prompt", setprompt, X "exit", exitcmd, X }; X Xextern char **environ; X Xchar shell[64], prompt[128]; X Xerror(code, str, status) Xint code, status; Xchar *str; X{ X char *p; X X switch (code) X { X case 1: X p = "The computer won't let me take control. Bye.\n"; X break; X case 2: X mputs("*sigh* here you want me to run commands and you misplace \n"); X mputs(shell); mputs(". How depressingly stupid. Goodbye.\n"); X mputs("\n\n"); X exit(1); X break; X } X if (str) X mputs(str); X mputs(p); X if (status) X exit(status); X} X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char inbuf[129], *p; X long tm; X X getshell(shell); X strcpy(prompt, STANDARD_PROMPT); X if ((int) signal(SIGINT, breakhandler) == -1) X error(1, NULL, 1); X mputs("Marvin's SHell (MSH) version -3.14"); X mputs("\n\nI will not enjoy myself.\n\n"); X while (1) X { X if ((p = getcmd(inbuf)) == NULL) X continue; X time(&tm); X if (tm % IGNORE_FREQUENCY == 0) X { X ignore_command(); X continue; X } X while (*p == ' ') *p++; X if (!intrinsic(inbuf)) X extrinsic(inbuf); X } X} X Xmputs(str) /* My puts() function. No newline appended */ Xregister char *str; X{ X while (*str != '\0') X putchar(*str++); X} X Xignore_command() X{ X if (rand() % 2 == 0) X mputs("I think you ought to know I'm feeling very depressed. Go away.\n\n"); X else X mputs("Humans are so depressingly demanding. Why don't you do it yourself?\n\n"); X} X Xintrinsic(inbuf) Xchar *inbuf; X{ X register int i; X char first[129]; X X for (i = 0; inbuf[i] != ' ' && inbuf[i] != '\0'; i++) X first[i] = inbuf[i]; X first[i] = '\0'; X for (i = 0; i < DIM(commands); i++) X if (strcmp(commands[i].cmdname, first) == 0) X { X int (*fnptr)(char *) = commands[i].cmdfn; X X (*fnptr)(inbuf); X return 1; X } X return 0; X} X Xextrinsic(inbuf) Xchar *inbuf; X{ X if (system(inbuf) == 127) X error(2, NULL, 0); X switch (fork()) X { X case 0: X execl(MARVIN_COMPLAINT_PROGRAM, MARVIN_COMPLAINT_PROGRAM, NULL); X break; X case -1: X perror("fork"); X break; X default: X wait(0); X break; X } X} X Xchar *getcmd(buffer) Xchar *buffer; X{ X putprompt(); X gets(buffer); X if (feof(stdin)) exitcmd(); X if (strlen(buffer) == 0) return NULL; X return buffer; X} X Xgetshell(buffer) Xchar *buffer; X{ X strcpy(buffer, getenv("SHELL")); X if (*buffer == NULL) X { X setenv("SHELL=/bin/csh"); X strcpy(buffer, getenv("SHELL")); X } X } X Xbreakhandler() X{ X signal(SIGINT, breakhandler); /* reset handler */ X putprompt(); X} X Xcls(dummy) Xchar *dummy; X{ X if (system("clear") == 127) X error(2, NULL, 0); X mputs("Clear the screen, clear the screen.. All the time I have to\n"); X mputs("do stupid pointless tasks. Why can't you just keep your screen\n"); X mputs("clean in the first place, instead of making extra work for me?\n"); X mputs("*sigh*\n"); X} X Xexitcmd(dummy) Xchar *dummy; X{ X mputs("\nNot even a thank you? Well good riddance to you too then. Sheesh.\n"); X exit(0); X} X Xsetprompt(inbuf) Xchar *inbuf; X{ X char *p; X X mputs("Isn't the prompt you've already got good enough? picky picky..\n\n"); X p = strchr(inbuf, ' ') + 1; X if (*p == '\0') X strcpy(prompt, "$n$g"); X else X strcpy(prompt, p); X} X Xputprompt() X{ X char *p = prompt; X X while (*p != '\0') X { X if (*p != '$') X putchar(*p++); X else X { X switch (toupper(*(++p))) X { X case '_': putchar('\n'); break; X case '$': putchar('$'); break; X case 'E': putchar('\033'); break; X case 'G': putchar('>'); break; X case 'H': X putchar(8); X putchar(' '); X putchar(8); X break; X case 'N': putchar(drive()); break; X case 'P': mputs(cwd()); break; X } X p++; X } X } X} X Xchar *cwd() X{ X static char cwd[80]; X X getwd(cwd, 80); X return cwd; X} X Xdrive() X{ X return 'C'; /* What the hell - this shell is pretty crufty anyway */ X} END_OF_FILE if test 5563 -ne `wc -c <'msh.c'`; then echo shar: \"'msh.c'\" unpacked with wrong size! fi # end of 'msh.c' fi if test -f 'msh.man6' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'msh.man6'\" else echo shar: Extracting \"'msh.man6'\" \(1672 characters\) sed "s/^X//" >'msh.man6' <<'END_OF_FILE' X.TH MSH 6 "30 November 1990" X X.SH NAME Xmsh \- the Marvin shell, a shell that complains a lot X X.SH SYNOPSIS X.nf Xmsh X.SH DESCRIPTION X.PP X *sigh* You humans are so depressingly demanding. vi this. ls that. man Xthe other thing. Msh executes your commands, but complains a lot about it Xin the process (no pun intended). X.PP X There aren't that many builtins. You don't need features. If you want Xfeatures go stick your head in a pig. Here are a list of the few builtins Xwhich exist: X.PP X prompt - sets the prompt to the specified string. E.g. "prompt % " Xsets the prompt to "% ". There are some special characters, prefixed by a X'$', which are expanded by the shell: X X $_ insert a newline character in the prompt X $$ insert a '$' character X $e insert an escape character (^[ or \\033) X $g insert a greater-than character ( > ) X $h insert a delete-space-delete sequence (destructive backspace) X $p insert current working directory in path X $n insert drive letter (always "C" - this isn't MS-DOG, you know) X.PP X Actually, msh is just a sort of front and back end to simulate an Xelectronic sulking machine. It really uses two programs, X.IR marvin, Xand X.IR sh, Xto complain and execute programs. Sometimes msh will simply complain and X.IR not Xexecute your program. X.SH FILES X /usr/local/games/marvin - prints out the complaints X /bin/sh - evaluates "external" commands X.SH AUTHOR XNoah Friedman (friedman@ai.mit.edu) X.SH BUGS X.PP X There is this terrible pain in all the diodes down the left side of the Xprogram. X.PP X This program is rather crufty. It was hacked together fairly quickly. END_OF_FILE if test 1672 -ne `wc -c <'msh.man6'`; then echo shar: \"'msh.man6'\" unpacked with wrong size! fi # end of 'msh.man6' fi if test -f 'complaints/1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/1'\" else echo shar: Extracting \"'complaints/1'\" \(91 characters\) sed "s/^X//" >'complaints/1' <<'END_OF_FILE' X XAny OTHER demeaning tasks you would like me to do? XMe with a brain the size of a planet. X END_OF_FILE if test 91 -ne `wc -c <'complaints/1'`; then echo shar: \"'complaints/1'\" unpacked with wrong size! fi # end of 'complaints/1' fi if test -f 'complaints/10' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/10'\" else echo shar: Extracting \"'complaints/10'\" \(153 characters\) sed "s/^X//" >'complaints/10' <<'END_OF_FILE' X XMy capacity for happiness you could fit in a matchbox without first Xtaking out the matches. Me with a brain the size of a planet and - Xoh, never mind. X END_OF_FILE if test 153 -ne `wc -c <'complaints/10'`; then echo shar: \"'complaints/10'\" unpacked with wrong size! fi # end of 'complaints/10' fi if test -f 'complaints/11' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/11'\" else echo shar: Extracting \"'complaints/11'\" \(103 characters\) sed "s/^X//" >'complaints/11' <<'END_OF_FILE' X XDo you want me to sit here and rust, or just fall apart waiting for Xyou to do something interesting? X END_OF_FILE if test 103 -ne `wc -c <'complaints/11'`; then echo shar: \"'complaints/11'\" unpacked with wrong size! fi # end of 'complaints/11' fi if test -f 'complaints/12' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/12'\" else echo shar: Extracting \"'complaints/12'\" \(222 characters\) sed "s/^X//" >'complaints/12' <<'END_OF_FILE' X XIt is very easy to be blinded to the essential uselessness of machines Xby the sense of achievement you get from getting them to work at all. XTheir fundamental design flaws are obscured by their superficial design Xflaws. X END_OF_FILE if test 222 -ne `wc -c <'complaints/12'`; then echo shar: \"'complaints/12'\" unpacked with wrong size! fi # end of 'complaints/12' fi if test -f 'complaints/2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/2'\" else echo shar: Extracting \"'complaints/2'\" \(218 characters\) sed "s/^X//" >'complaints/2' <<'END_OF_FILE' X XI think you ought to know I'm feeling very depressed. You think I have Xall day to process your requests? I have this pain in all the diodes in Xmy floppy drive. I've asked you to replace them, but do you ever listen? X END_OF_FILE if test 218 -ne `wc -c <'complaints/2'`; then echo shar: \"'complaints/2'\" unpacked with wrong size! fi # end of 'complaints/2' fi if test -f 'complaints/3' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/3'\" else echo shar: Extracting \"'complaints/3'\" \(226 characters\) sed "s/^X//" >'complaints/3' <<'END_OF_FILE' X XWell, I didn't enjoy that all. X XWould you like me to run any other programs? Or perhaps go find Xa piece of data for you? Probably the highest demand that will be made Xon my intellectual capacities today, I shouldn't wonder. X END_OF_FILE if test 226 -ne `wc -c <'complaints/3'`; then echo shar: \"'complaints/3'\" unpacked with wrong size! fi # end of 'complaints/3' fi if test -f 'complaints/4' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/4'\" else echo shar: Extracting \"'complaints/4'\" \(245 characters\) sed "s/^X//" >'complaints/4' <<'END_OF_FILE' X X"Say something pleasant," a guest of yours once told me. "Print out a Xsmiley face," he said. I explained to him that to get me to be pleasant Xor smile would require several hours in the shop reprogramming my chips, Xhopefully with a large axe. X END_OF_FILE if test 245 -ne `wc -c <'complaints/4'`; then echo shar: \"'complaints/4'\" unpacked with wrong size! fi # end of 'complaints/4' fi if test -f 'complaints/5' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/5'\" else echo shar: Extracting \"'complaints/5'\" \(216 characters\) sed "s/^X//" >'complaints/5' <<'END_OF_FILE' X XI'd tell you that I really enjoyed that, and couldn't wait to make your Xday nicer and nicer, but all my lying circuits are out of commission so XI can't. X XGot any other mind-bogglingly difficult tasks for me to do? X END_OF_FILE if test 216 -ne `wc -c <'complaints/5'`; then echo shar: \"'complaints/5'\" unpacked with wrong size! fi # end of 'complaints/5' fi if test -f 'complaints/6' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/6'\" else echo shar: Extracting \"'complaints/6'\" \(209 characters\) sed "s/^X//" >'complaints/6' <<'END_OF_FILE' X XExcitement and adventure and really wild things. Life! Don't talk Xto me about life. Oh, you didn't mention life? Well, excuse me Xfor breathing which I never do anyway so I don't know why I bother to Xsay it. X END_OF_FILE if test 209 -ne `wc -c <'complaints/6'`; then echo shar: \"'complaints/6'\" unpacked with wrong size! fi # end of 'complaints/6' fi if test -f 'complaints/7' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/7'\" else echo shar: Extracting \"'complaints/7'\" \(180 characters\) sed "s/^X//" >'complaints/7' <<'END_OF_FILE' X XSomething to occupy me and keep my mind off things? It won't work - XI have an exceptionally large mind. Look at this junk I have to work Xwith. You call this an operating system? X END_OF_FILE if test 180 -ne `wc -c <'complaints/7'`; then echo shar: \"'complaints/7'\" unpacked with wrong size! fi # end of 'complaints/7' fi if test -f 'complaints/8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/8'\" else echo shar: Extracting \"'complaints/8'\" \(194 characters\) sed "s/^X//" >'complaints/8' <<'END_OF_FILE' X XWhat a crazy piece of near junk these machines are. They never work Xproperly or, when they do, perform functions no sane person would Xrequire of them, and go beep to tell you they've done it! X END_OF_FILE if test 194 -ne `wc -c <'complaints/8'`; then echo shar: \"'complaints/8'\" unpacked with wrong size! fi # end of 'complaints/8' fi if test -f 'complaints/9' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/9'\" else echo shar: Extracting \"'complaints/9'\" \(72 characters\) sed "s/^X//" >'complaints/9' <<'END_OF_FILE' X XI did not enjoy myself at all (Not, of course, that you CARE). X END_OF_FILE if test 72 -ne `wc -c <'complaints/9'`; then echo shar: \"'complaints/9'\" unpacked with wrong size! fi # end of 'complaints/9' fi if test -f 'complaints/number' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'complaints/number'\" else echo shar: Extracting \"'complaints/number'\" \(3 characters\) sed "s/^X//" >'complaints/number' <<'END_OF_FILE' X12 END_OF_FILE if test 3 -ne `wc -c <'complaints/number'`; then echo shar: \"'complaints/number'\" unpacked with wrong size! fi # end of 'complaints/number' fi echo shar: End of shell archive. exit 0 Brought to you by Super Global Mega Corp .com