Joke shell wanted (sources posted)

Noah Friedman friedman at apple-gunkies.ai.mit.edu
Sat Dec 1 05:58:19 AEST 1990


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 at 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 <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile complaints marvin.c marvin.h marvin.man6 msh.c
#   msh.man6 complaints/1 complaints/10 complaints/11 complaints/12
#   complaints/2 complaints/3 complaints/4 complaints/5 complaints/6
#   complaints/7 complaints/8 complaints/9 complaints/number
# Wrapped by friedman at churchy.ai.mit.edu on Fri Nov 30 13:33:24 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(221 characters\)
sed "s/^X//" >'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 <stdio.h>
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 at 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 <stdio.h>
X#include <string.h>
X#include <signal.h>
X#include <ctype.h>
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<exiting msh>\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 at 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). <sigh>
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



More information about the Alt.sources mailing list