Sam Trenholme's webpage
This article was posted to the Usenet group alt.hackers in 1995; any technical information is probably outdated.

Re: Smallest Unix Shell


Article: 8667 of alt.hackers
Newsgroups: alt.hackers
From: mrs@netcom.com (Morgan Schweers)
Subject: Re: Smallest Unix Shell
Message-ID: mrsDFArxq.DJ8@netcom.com
Organization: Foxsoft Cyberware
Date: Fri, 22 Sep 1995 08:08:14 GMT
Approved:  Yah, youbetcha.
Lines: 71
Sender: mrs@netcom17.netcom.com
Status: RO

Some time ago wkt@dolphin.cs.adfa.oz.au (Warren Toomey) happily mumbled:
>ObHack: A challenge with a friend to come up with the smallest Unix shell
>in C.
>Here's the results, the smallest being 123 characters (124 with a \n):

   (I've also split all of them across two lines.  For optimal use,
recombine on one line.  All of them SHOULD be, however, split on
'safe' splits, all identically (so you can compare the second line for
size...) so even as is, the code should compile.)

   Interesting.  I'm not familiar with the 'strsep' function...  My preferred
version is this one (*K&R* C legal...  Yep.  Disgusting, ain't it?  No, the
lack of 'char' at the beginning isn't a typo.):

My smallest at offhand at 121 bytes:

a,b[99],*c,d[99];main(){while(printf(">"),c=d,*c=a=gets(b)){
for(;*++c=strtok(a," ");a=0);fork()?wait(0):execvp(*d,d+1);}}

Your smallest (so far) at 122 bytes:
char*c,b[99],*v[99],i;main(){while(putchar(62),gets(b)){for(
c=b,i=0;v[i++]=strsep(&c," "););fork()?wait(0):execvp(*v,v);}}

   has three bugs:
   o   Enter an invalid command (like hitting ENTER) and the fork goes back
       and prompts you, thus going another level down...
   o   It requires that you add a 'spare' parameter (which gets ignored).
   o   The first 'parameter' passed (as argv[1]) is the same as the name
       of the program.  (This is a function/problem of execv and execvp,
       at least under SunOS 4.1.3.)

   o   (And, though not a bug, I've not found a machine that recognizes
       'strsep' yet...)

   My code still has the first bug, but not the remaining two, and uses
'strtok'.

   The first bug is fixed by the following code (127 bytes):

a,b[99],*c,d[99];main(){while(printf(">"),c=d,*c=a=gets(b)){
for(;*++c=strtok(a," ");a=0);fork()?wait(0):exit(execvp(*d,d+1));}}

   Now...  What bugs remain, that aren't feature enhancements?  (Note:
You can shrink it by another byte by making it call 'execv' instead of
execvp, and entering the path for each program you want to execute
entirely by hand.)

(Presuming that 'strsep' returns a pointer into the string being
modified at the point of the latest 'seperator', while placing a 0
just before it in the string, returning NULL when there are no more
seperators...) The following is a 'strsep' version with bugs 2 and 3
fixed.  (Bug #1 still takes an additional 6 bytes to fix.)  This is
down to 119 bytes, but I don't know of any platforms that work with
'strsep', so I can't test it...:

a,*c,b[99],v[99];main(){while(printf(">"),c=v,*c=a=gets(b)){
for(;*++c=strsep(&a," "););fork()?wait(0):execvp(*v,v+1);}}

>I've broken them into 2 lines each for easier reading. Fixing the small bug
>that all four versions have would increase the size by at least 10
characters.
>
>	Warren

   Which small bug...?	(One I've missed?)

						       --  Morgan Schweers
--
Morgan Schweers |  New Chrome Grass!  Finger mrs@netcom.com for my PGP key   |
Live fast, die	 \ B1 S4 a b g j++! k l? p r- s t+ u v- w+ x y- z, approx.__/
old, and leave a smouldering pile of metal as a corpse...  It's never enough,
until your heart stops beating, the deeper you get, the sweeter the pain...



Parent

Back to index