rc

[fork] interactive rc shell
Log | Files | Refs | README | LICENSE

commit 53cf1b1c1c3f0c2b5067afccc2976b99a574a089
parent b87bfedf65c289bf0ee5338c9e10492b70b1e8e0
Author: tim <tim>
Date:   Wed, 14 May 1997 15:30:41 +0000

Initial revision

Diffstat:
DCHANGES | 278-------------------------------------------------------------------------------
DCOPYRIGHT | 26--------------------------
DEXAMPLES | 749-------------------------------------------------------------------------------
DMakefile.in | 80-------------------------------------------------------------------------------
DREADME | 197-------------------------------------------------------------------------------
Daddon.c | 22----------------------
Daddon.h | 38--------------------------------------
Mbuiltins.c | 44+++++++++++++++++++++++++-------------------
Dconfig.h.in | 44--------------------------------------------
Dconfigure | 2541-------------------------------------------------------------------------------
Dconfigure.in | 287-------------------------------------------------------------------------------
Dcpp | 38--------------------------------------
Dexcept.c | 140-------------------------------------------------------------------------------
Dexec.c | 132-------------------------------------------------------------------------------
Dexecve.c | 61-------------------------------------------------------------
Dfn.c | 257-------------------------------------------------------------------------------
Dfootobar.c | 337-------------------------------------------------------------------------------
Dgetopt.c | 50--------------------------------------------------
Dglob.c | 278-------------------------------------------------------------------------------
Dglom.c | 433-------------------------------------------------------------------------------
Dgroup.h | 9---------
Dhash.c | 304-------------------------------------------------------------------------------
Dheredoc.c | 156-------------------------------------------------------------------------------
Dhistory/history.1 | 234-------------------------------------------------------------------------------
Dhistory/history.c | 341-------------------------------------------------------------------------------
Dinput.c | 363-------------------------------------------------------------------------------
Dinstall-sh | 250-------------------------------------------------------------------------------
Djbwrap.h | 9---------
Dlex.c | 395-------------------------------------------------------------------------------
Dlist.c | 57---------------------------------------------------------
Dmain.c | 121-------------------------------------------------------------------------------
Dmatch.c | 99-------------------------------------------------------------------------------
Dmksignal | 76----------------------------------------------------------------------------
Dnalloc.c | 139-------------------------------------------------------------------------------
Dopen.c | 25-------------------------
Dparse.y | 174-------------------------------------------------------------------------------
Dprint.c | 482-------------------------------------------------------------------------------
Dproto.h | 40----------------------------------------
Drc.1 | 1881-------------------------------------------------------------------------------
Drc.h | 406-------------------------------------------------------------------------------
Dredir.c | 77-----------------------------------------------------------------------------
Drlimit.h | 42------------------------------------------
Dsignal.c | 80-------------------------------------------------------------------------------
Dstatus.c | 147-------------------------------------------------------------------------------
Dtree.c | 172-------------------------------------------------------------------------------
Dtrip.rc | 0
Dutils.c | 116-------------------------------------------------------------------------------
Dvar.c | 225-------------------------------------------------------------------------------
Dversion.c | 1-
Dwait.c | 129-------------------------------------------------------------------------------
Dwalk.c | 358-------------------------------------------------------------------------------
Dwhich.c | 121-------------------------------------------------------------------------------
Dy.tab.c | 1070-------------------------------------------------------------------------------
Dy.tab.h | 33---------------------------------
54 files changed, 25 insertions(+), 14139 deletions(-)

diff --git a/CHANGES b/CHANGES @@ -1,278 +0,0 @@ -Changes since 1.2: (Too many to count!) - -A memory stomping bug was fixed (provoked by assigning a variable -to its old value plus something else). - -Better signal handling; a real signal handler which manages a queue -of pending signals was added. - -rc now ignores SIGQUIT and traps SIGINT even in non-interactive -mode. Thus, - - rc ed.sh - -will not do mysterious things if the shell script "ed.sh" calls a -command like "ed" and then you hit ^C. - -rc now opens 0, 1, 2 on /dev/null if they are inherited closed. -rc -o prevents this. - -A couple of stupid O(n^2) string appends were replaced with O(n) -loops. This should make foo=`{cat /etc/termcap} bar=$^foo a little -faster :-) - -Returning a list of signals from a function is now legal, so "return -$status" should always work. - -The code has been revised, new printing routines have been added. - -rc no longer uses redundant braces when exporting functions. - -A first stab at a verification suite has been added (trip.rc). -(someone, please help me make this comprehensive!) - -rc -p now does not initialize functions from the environment. This -should make it easier to write shell scripts that don't need to -assume anything about the environment. - -Inherited ignored signals are now ignored in the current shell and -passed on ignored to the child processes. whatis -s also reflects -this information. - -A file descriptor leak in the /dev/fd implementation of >{} was -fixed. - -A variable set to '' was not imported from the environment; this -has been fixed. - -Changes since 1.3beta: - -New Makefile/config.h setup. - -builtin echo may now be conditionally included out, to use a Goldwynism. - -builtin exit takes any legal exit status. If the status is not all zeros, -rc exits with 1. (having "exit sigiot" produce a core dump would be going -a little far, I think.) - -limit does not append a unit after a zero limit; 0g was too confusing. - -exec > /nonexistentfile does not cause rc to exit any more. - -If a noninteractive rc is started with sigint ignored, rc does not install -its own signal handler. - -error messages produced by rc in a subshell were cleaned up. (rc erroneously -reset the 'interactive' flag after a fork) - -print.c was cleaned up a little; no functionality was changed, but should -be more portable now. - -a bug in rc-1.3beta (not previous versions) was fixed: setting the first -element of $path to '' caused PATH to be exported as '':etc.. - -getopt's "illegal option" message was gratuitously changed to something -less abrupt. - -some dead code was removed from input.c - -%term was changed to %token in parse.y; apparently newer yacc's don't grok -%term any more. - -a race condition in the signal handler was fixed. - -the variable in for() was getting evaluated each time through the loop -(e.g., for (`{echo i;date>[1=2]} in 1 2 3)echo $i would print the date -three times). This was cleaned up. - -a redundant fork() was removed from walk.c; this showed up when running -a braced command with a redirection in the background. e.g., {a;b}>c& - -man pages for history and rc were cleaned up by david (thanks). - -rc set SIGQUIT and SIGTERM to SIG_DFL on background jobs---even when -trying to do old-style backgrounding (i.e., don't use process groups, -just ignore SIGINT & SIGQUIT & SIGTERM). - -$0 is now changed to the name of the signal when entering a signal -handler. Thus it's possible to write code like - - fn sigint sigterm sigquit { - switch ($0) { - case sigint - ... - case sigterm - ... - -wait with no arguments now prints the pid of any and all children -that died with a signal. e.g., - - ; wait - 25321: terminated - 25325: terminated - -as opposed to - - ; wait - terminated - -An error saving/restoring state in the input stream code would -cause rc to exit with the (erroneous) command: - - eval '|[a' - -FIFO's were not removed in a backgrounded command, e.g., - - cat <{echo hi}& - -Changes since rc-1.4beta: - -getopt was renamed to rc_getopt to avoid libc collisions. - -$cdpath with a / in it caused a cd to sometimes have two //'s at the -front of the path. This is reserved by POSIX, so I changed it to skip -one of the /'s. - -signal handling now emulates sh in the way I described in a previous -message: the race condition present in older rc's whereby some SIGINTs -got lost is now gone; any SIGINT received during a wait() is acted upon -at the end of the wait(), unless of course SIGINT is being deliberately -ignored. - -getopt was renamed to avoid naming conflicts with libc. Also a sound -move since rc_getopt is no longer quite libc-getopt compatible; I had -to add in a mechanism for resetting getopt. - -signal handler code in fn.c was cleaned up; there were several bugs -in rc-1.4beta, notably the shell sometimes spawned background jobs -with SIGTERM ignored. I took the opportunity to make things a little -cleaner here. - -a quasi-memory leak in the code for while() was fixed: a long-running -while that had rc commands allocating memory in it could cause the -shell to grow without bounds. I fixed this by placing the while loop -(*and* test!) inside a new allocation arena each time through the loop. - -A new configuration parameter, NOJOB, was added to allow you to force -v7-style backgrounding (no setpgrp, ignore SIGINT and SIGTERM). - -The FIFO code was reworked a little. It should be more robust now--- -FIFOs get removed at the end of the command of the argument list -that they were on: - - fn foo {echo $*; cat $*} - foo<{echo hi} - -now works as expected. Also FIFO names are pushed onto the exception -stack so that their removal occurs in the face of exceptions and so -on. - -A memory leak in treefree() was plugged up --- the root node of a -function was not getting freed. - -Changes since rc-1.4: - -General changes: - - Some small memory leaks/uninit references revealed by Purify. - - $bqstatus for querying the exit status of a backquote. - - Globbing through unreadable directories. - - More options to whatis. - - History append which always re-opens the file (avoids - inconsistencies over multiple NFS-mounted accesses to - $history). - - Support "rc -s". - ---------- - -Makefile: Added comment referring to README for yacc/malloc problem. - -uiltins.c: Added more options to whatis, protected rlimit prototypes - with #ifndef SYSVR4, renamed SIGCHK to sigchk. - -except.c: Patched nl_on_intr printing to happen only in interactive - shells. - -exec.c: Added comment explaining nl_on_intr variable, renamed SIGCHK - to sigchk. - -fn.c: Replaced by-hand consing of exception stack etc. for signal - handler execution with call to funcall(). Replaced fun2str - call with call on print routines. - -footobar.c: Got rid of memory leak in get_name(), parenthesize count, - flat and var nodes for correctness in unparsing, removed - list2str, made get_name use nalloc space, merge in a - better parse_var from es. - -glob.c: Split out a test so that closedir is called correctly, renamed - SIGCHK to sigchk. - -glom.c: Added bqstatus, renamed SIGCHK to sigchk, removed spurious - setsigdefaults, patched uninit memory reference, rename - "clear" to "memzero", wait for bq subproc to finish on EINTR. - -hash.c: Added options to function/variable print code. - -history/history.c: Added '@' to the list of chars which can precede an - ignored '-'. - -input.c: Got rid of tiny memory leak in closefds, got rid of uninit - memory reference in popinput, moved nul ignored check into - realgchar(), changed history append to always reopen the - history file, replaced SIGCHK with sigchk. Freed memory - returned by call to readline(). - -lex.c: Corrected typo in comment, moved nul character ignore code - to input routines. - -main.c: Added -s flag. - -nalloc.c: Added convenience feature to erealloc. (Allow NULL parameter) - -print.c: Changed use of va_start so broken compilers can compile - print code. - -proto.h: Added fake memset. - -rc.h: Replaced clear() function prototype with a macro call on - memset(), removed SIGCHK, fixed prototypes. - -signal.c: Removed unconditional exit in catcher code, renamed SIGCHK - to sigchk. - -status.c: Rewrite sgetstatus breaking out strstatus so that bqstatus - can be set from glom routines. - -utils.c: Got rid of clear() (use memset from C library), rename SIGCHK - to sigchk. - -var.c: Got rid of memory leak in listassign(), converted list2str() - call to something using the print routines. - -version.c: New version string. - -wait.c: Got rid of memory leak in rc_fork, renamed SIGCHK to sigchk. - -walk.c: Fixed pre-redirection bug, removed spurious setsigdefaults(), - renamed SIGCHK to sigchk. - - -Changes since rc-1.5beta1 - - Configuration: rc now uses GNU autoconf. - - Portability: mksignal works on HPUX 10. - - Portability: resources can be (quad_t). - - Bug: if rc was started with SIGCLD == SIG_IGN (e.g. by Solaris's - rshd) it would loop. Fixed by resetting SIGCLD to SIG_DFL if it - was SIG_IGN when rc was started. - - Portability: POSIXish systems don't have NGROUPS. diff --git a/COPYRIGHT b/COPYRIGHT @@ -1,26 +0,0 @@ -/* - * Copyright 1991 Byron Rakitzis. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * - * 1. The author is not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * - * 4. This notice may not be removed or altered. - * - * [this copyright notice is adapted from Henry Spencer's - * "awf" copyright notice.] - */ diff --git a/EXAMPLES b/EXAMPLES @@ -1,749 +0,0 @@ -There is no repository for useful rc code snippets as yet, so I'm including -a (short) file in the distribution with some helpful/intriguing pieces of -rc code. - -A sample .rcrc --------------- -Here is the .rcrc I use on archone: - -umask 022 -path=(/bin /usr/bin /usr/ucb) -ht=`/usr/arch/bin/hosttype -h=$home -history=$h/.history -bin=$h/bin/$ht -lib=$h/lib/$ht -sh=$h/bin/sh -include=$h/lib/include - -switch ($ht) { -case sun* - OBERON='. '$h/other/oberon - p=/usr/ucb - compiler='gcc -Wall -O -g' - MANPATH=$h/man:/usr/arch/man:/usr/man - if (! ~ $TERM ()) { - stty dec - /usr/arch/bin/msgs -q - } -case next - p=(/usr/ucb /usr/bin /NextApps) - compiler='cc -Wall -O -g -DNODIRENT' - MANPATH=$h/man:/usr/arch/man:/usr/man - if (! ~ $TERM ()) - stty dec -case sgi - p=(/usr/ucb /usr/sbin /usr/bin) - compiler='gcc -Wall -O -g -DNOSIGCLD' - MANPATH=$h/man:/usr/arch/man:/usr/catman - if (!{~ $TERM () || ~ $TERM *iris*}) - stty line 1 intr '' erase '' kill '' -case * - echo .rcrc not configured for this machine -} - -path=(. $sh $bin /usr/arch/bin $p /bin /usr/bin/X11 /etc /usr/etc) -cdpath=(. .. $h $h/src $h/misc $h/other $h/adm) -RNINIT=-d$h' -t -M -2400-h -2400+hfrom'; DOTDIR=$h/misc/news -PRINTER=lw - -fn s { - echo $status -} -fn cd { - builtin cd $1 && \ - switch ($1) { - case () - dir=$home - case * - dir=() - } -} -fn pwd { - if (~ $dir ()) - dir=`/bin/pwd - echo $dir -} -fn x { - if (~ `tty /dev/console) - clear_colormap - clear - exit -} -fn p { - if (~ $history ()) { - echo '$history not set' >[1=2] - return 1 - } - - if (! ~ $#* 0 1 2) { - echo usage: $0 '[egrep pattern] [sed command]' >[1=2] - return 1 - } - - command=`{ - egrep -v '^[ ]*p([ ]+|$)' $history | switch ($#*) { - case 0 - cat - case 1 - egrep $1 - case 2 - egrep $1 | sed $2 - } | tail -1 - } - - echo $command - eval $command -} - -if (~ $TERM dialup network) { - TERM=vt100 - biff y -} - -A front-end to NeXT's "openfile" --------------------------------- - -Named after the sam "B" command for opening a file, this script was written -by Paul Haahr. (Assumes the "pick" command from Kernighan and Pike is also -in your path.) - -#!/bin/rc -if (~ $#* 0) - exec openfile -create = () -files = () -for (i in $*) - if (test -f $i) { - files = ($files $i) - } else { - create = ($create $i) - } -create = `{ pick $create } -files = ($files $create) -for (i in $create) - > $i -if (! ~ $#files 0) - openfile $files - -A read function ---------------- - -Unlike sh, rc doesn't have a read. This clever alternative returns an -exit status as well as fetch a variable. Use as - - read foo - -to set $foo to a single line from the terminal. - -(due to John Mackin <john@syd.dit.csiro.au>) - -fn read { - x=() { - x = `` ($nl) { awk '{print; print 0; exit}' ^ $nl ^ \ - 'END {print 1; print 1}' } - $1 = $x(1) - return $x(2) - } -} - -From cs.wisc.edu!dws Fri Aug 2 18:16:14 1991 - -#------- -# ls front end -#------- -fn ls \ -{ - test -t 1 && * = (-FCb $*) - builtin ls $* -} -#------- -# nl - holds a newline, useful in certain command substitutions -#------- -nl=' -' -#------- -# show - tell me about a name -# -# Runs possibly dangerous things through cat -v in order to protect -# me from the effects of control characters I might have in the -# environment. -#------- -fn show \ -{ - * = `` $nl {whatis -- $*} - for(itis) - { - switch($^itis) - { - case 'fn '* ; echo $itis | cat -v -t - case builtin* ; echo $itis - case /* ; file $itis; ls -ld $itis - case *'='* ; echo $itis | cat -v -t - case * ; echo $itis: UNKNOWN: update show - } - } - itis = () -} -#------- -# Tell me automatically when a command has a nonzero status. -#------- -fn prompt \ -{ - Status = $status - ~ $Status 0 || echo '[status '$Status']' -} - -#------- -# chop - echo the given list, less its final member -# -# e.g. chop (a b c) -> (a b) -#------- -fn chop { - ~ $#* 0 1 && return 0 - ans = '' { # local variable - ans = () - while(! ~ $#* 1) - { - ans = ($ans $1) - shift - } - echo $ans - } -} - -From arnold@audiofax.com Thu May 30 08:49:51 1991 - -# cd.rc --- souped up version of cd - -# this is designed to emulate the fancy version of cd in ksh, -# so if you're a purist, feel free to gag - -_cwd=$home -_oldcwd=$home - -fn cd { - if (~ $#* 0) { - if (~ $_cwd $home) { # do nothing - } else { - builtin cd && { _oldcwd=$_cwd ; _cwd=$home } - } - } else if (~ $#* 1) { - if (~ $1 -) { - _t=$_cwd - builtin cd $_oldcwd && { - _cwd=$_oldcwd - _oldcwd=$_t - echo $_cwd - } - _t=() - } else { - # if a cd happens through the cdpath, rc echos - # the directory on its own. all we have to do - # is track where we end up - _dopwd = 1 - { ~ $1 /* } && _dopwd = 0 # absolute path - builtin cd $1 && { - _oldcwd=$_cwd - _cwd=$1 - { ~ $_dopwd 1 } && _cwd=`/bin/pwd - } - _dopwd=() - } - } else if (~ $#* 2) { - _t=`{ echo $_cwd | sed 's<'$1'<'$2'<' } - builtin cd $_t && { - _oldcwd=$_cwd - _cwd=$_t - echo $_cwd - } - _t=() - } else { - echo cd: takes 0, 1, or 2 arguments >[1=2] - builtin cd $1 && { _oldcwd=$_cwd ; _cwd=`/bin/pwd ; echo $_cwd } - } -} - -fn pwd { echo $_cwd } - -From vlsi.cs.caltech.edu!drazen Tue Jan 21 16:03:14 1992 - -# A kill builtin. - -#ifdef B_KILL -#include <ctype.h> -static void b_kill(char **av) -{ - int signal = SIGTERM; - int n = 1; - pid_t pid; - boolean res; - - if (!av[1]) { - set(TRUE); - return; - } -#undef STRCMP -#define STRCMP strcmp - if ( '-' == av[1][0]) { - char *p = 1+av[1]; - if (0 == strcmp(av[1], "-l")){ - int r; const int nsig = NUMOFSIGNALS; - const int C = 4, R = 1 + (int)((nsig-2)/C); - for (r=1; r<=R; r++){ - int j; - for (j=r; j<nsig; j+=R){ - fprint(1, "%s%d. %s\t", j<10?" ":"", j, signals[j][0]); - } - fprint(1,"\n"); - } - set(TRUE); - return; - } - n++; - if ( (signal=a2u(p)) < 0){ - int i; - for (i = 1; i < NUMOFSIGNALS; i++){ - char UPPER[31], *u=UPPER, *q; - for (q=signals[i][0]; *q; q++, u++) *u = toupper(*q); - *u = '\0'; - - if (*signals[i][0] && - (!STRCMP(signals[i][0], p) || !STRCMP(3+signals[i][0],p) - || !STRCMP(UPPER, p) || !STRCMP(3+UPPER, p) ) ) - { - signal = i; - break; - } - } - if (signal < 0){ - fprint(2,"kill: bad signal %s\n", av[1]); - set(FALSE); - return; - } - } - } -#undef STRCMP - - for (res=TRUE; av[n]; n++){ - if( (pid = (pid_t) a2u(av[n])) < 0){ - fprint(2, "kill: bad process number %s\n", av[n]); - res = FALSE; - continue; - } - if (kill(pid,signal)){ - uerror("kill"); - res = FALSE; - continue; - } - } - set(res); -} -#endif -From acc.stolaf.edu!quanstro Thu Apr 2 02:51:10 1992 -Received: from thor.acc.stolaf.edu ([130.71.192.1]) by archone.tamu.edu with SMTP id <45339>; Thu, 2 Apr 1992 02:50:56 -0600 -Received: by thor.acc.stolaf.edu; Thu, 2 Apr 92 02:49:31 -0600 -Date: Thu, 2 Apr 1992 02:49:31 -0600 -From: quanstro@acc.stolaf.edu -Message-Id: <9204020849.AA26566@thor.acc.stolaf.edu> -To: byron@archone.tamu.edu -Subject: EXAMPLES in 1.4beta -Status: RO - - -I have a little bit of code which might be a little more general than -the souped-up version that is already there. Here it is, if you are -interested. - -# directory functions ################################################### -fn pwd { echo $PWD; } - -fn pushd { - dirs = ($PWD $dirs); - builtin cd $*; - PWD = `{builtin pwd}; -} - -fn popd { - switch ($#*) - { - case 0 - ; - case 1 - echo 'popd: argument '^$1^' ignored.' >[1=2]; - case * - echo 'popd: usage: popd [n].'; - } - - if (! ~ $dirs ()) - { - builtin cd $dirs(1); - PWD = $dirs(1); - echo $PWD; - * = $dirs; - shift - dirs = $*; - } -} - -fn cd { - ~ $* () && * = $home; - !~ $#* 1 && echo 'cd: too many arguments' >[1=2] && return 1; - - if (test -r $* ) { - pushd $*; - } else { - echo cd: $* does not exist. >[1=2] - return 1; - } -} - -fn back { popd $*; } - -fn Back { - cd $home; - PWD = $home; - dirs = (); -} - -fn dirs { - echo $dirs; -} - -PWD = `{builtin pwd} ; dirs = $PWD # kickstart - - - - - -From acc.stolaf.edu!quanstro Thu Apr 2 02:53:40 1992 -Received: from thor.acc.stolaf.edu ([130.71.192.1]) by archone.tamu.edu with SMTP id <45339>; Thu, 2 Apr 1992 02:53:38 -0600 -Received: by thor.acc.stolaf.edu; Thu, 2 Apr 92 02:51:46 -0600 -Date: Thu, 2 Apr 1992 02:51:46 -0600 -From: quanstro@acc.stolaf.edu -Message-Id: <9204020851.AA26573@thor.acc.stolaf.edu> -To: byron@archone.tamu.edu -Subject: EXAMPLES -Status: RO - - -Little yp hack which act's like ~ w/o syntatic sugar (for those who do -not have the luxury of seting up symbolic links to all user's homes - -# user function ######################################################### -fn u user { - info = () - info = `` (':') {ypmatch $1 passwd >[2] /dev/null } - - if (~ $info ()) { - echo user $1 unknown >[1=2]; - return 1; - } else { - echo $info(6) - if (~ $0 user) - cd $info(6) - } -} - - -From stolaf.edu!quanstro Sun Apr 5 04:53:34 1992 -Date: Sun, 5 Apr 1992 04:53:08 -0500 -From: quanstro@stolaf.edu (Erik Quanstrom) -To: byron@archone.tamu.edu -Subject: man written in rc -Status: RO - -I whipped this up because the NeXTs here insist on using MANPAGER -instead of PAGER and otherwise being obnoxious . . . - -Anyway ... I hope you approve - -#!/bin/rc -######################################################################### -# file: man # -# # -# object: display man pages # -# # -# bugs: * slow # -# * does not know about fmt files # -# # -# Erik Quanstrom # -# 11. Februar 1992 # -######################################################################### -PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:$PATH ; -TROFF = (nroff -hq -Tcrt); -macros=an; -sections=(cat1 cat2 cat3 cat4 cat5 cat6 cat7 cat8 catl man1 man2 man3 man4 \ - man5 man6 man7 man8 manl) -$nl=' -' -fn sigint sighup sigquit sigalrm sigterm { rm -f $Bat; exit 2;} - -fn usage { - echo usage: $0 [-] [-t] [-M path] [-T macros] [[section] title] ...>[1=2]; - exit 1; -} - -n=(); -fn shiftn { - n=($n 1) -} - -~ $PAGER () && test -t 1 && PAGER=more; #default pager - -while (~ $1 -*) - { - switch ($1) - { - case - - if (~ $PAGER troff) - echo bad combination of flags >[1=2] && usage; - PAGER=cat; - case -t - ~ TROFF () && TROFF = (troff -t); - ~ TCAT () && PAGER=(lpr -t); - case -M - shift; - ~ $1 () && usage; - - MANPATH=$1; - case -T - shift; - ~ $1 () && usage; - macros=$1; - case -k - fflag=(); kflag=1; - shift; - break; - case -f - # locate related too filenames - kflag=(); fflag=1; - shift; - break; - case -* - echo bad flag '`'^$1^'''' >[1=2]; - usage; - } - shift; - } - -if (!~ $#* 1) { - ~ $1 [l1-8] && { sname=$1 ; sections=(cat man)^$1 ; shift } - #hack for sun-style man pages - ~ $1 [l1-8]? && { sname=$1 ; sections=(cat man)^`{echo $1| cut -c1} ; shift } -} - -if (~ 1 $fflag $kflag) { - dirlist=(); - for (d in ``(:$nl) {echo $MANPATH}) - test -s $d^/whatis && dirlist=($dirlist $d^/whatis); - - ~ $1 () && usage; - - if (~ $fflag 1) { - while (!~ $1 ()) { - cmd=`{echo $1 | sed 's/^.*\///g'} - egrep -h '^'^$cmd' ' $dirlist; - shift; - } - } else { - while (!~ $1 ()) { - grep -h $1 $dirlist; - shift; - } - } - exit 0; -} - -s=0; -while (!~ $1 ()) { - for (dir in ``(:$nl) {echo $MANPATH}) { - filelist=($filelist `{echo $dir/^$sections^/$1^.* |\ - tr ' ' '\12' | grep -v '*'}) - - # coment this out if you don't care about speed, but - # would rather find all the pages. - ~ $filelist () || break; - } - - if (~ $filelist ()) { - if (~ $#sections 2) { - echo no entry for $1 in section '`'$sname'''' of the manual >[1=2]; - } else { - echo no entry for '`'$1'''' found. >[1=2]; - } - s=1; - } else { - - echo $filelist '(' $#filelist ')' >[1=2]; - - for (file in $filelist) { - if (~ $file */cat[1-8l]/*) { - Cat = ($Cat $file); - } else { - # search for dups - dont=() - for (x in $Cat) { - if (~ `{echo $x | sed 's/\/[mc]a[nt][1-8l]//'} \ - `{echo $file | sed 's/\/[mc]a[nt][1-8l]//'}) { - dont=1; - break; - } - } - - if (~ $dont ()) { - cd `{echo $file | sed 's/man[1-8].*//'} - echo -n Formatting ... - $TROFF -m^$macros $file > /tmp/man^$pid^$#n && \ - Bat = ($Bat /tmp/man^$pid^$#n) - - shiftn; - echo ' 'done. - } - } - } - } - shift; -} - -{ !~ () $Cat || !~ () $Bat } && $PAGER $Cat $Bat; - -rm -f $Bat; -~ $s () || exit $s; - -exit 0; - - - -From osf.org!rsalz Thu Apr 23 16:22:32 1992 -Date: Thu, 23 Apr 1992 16:22:07 -0500 -From: rsalz@osf.org -To: byron@archone.tamu.edu -Subject: One for your EXAMPLES file -Status: RO - -Use - trimhist [-#lines] -trims your history file back; useful for folks with dis quota's :-) -fn trimhist { p1=-100 { - cp $history $history^'~' - ~ $#* 1 && p1=$1 - tail $p1 <$history^'~' >$history - rm $history^'~' -} } - -From Pa.dec.com!uucp Mon Apr 27 12:25:02 1992 -Date: Mon, 27 Apr 1992 12:15:18 -0500 -From: haahr@adobe.com -To: Byron Rakitzis <byron@archone.tamu.edu> -Subject: a neat little rc script - -what you have to know to understand this: - $md for me is usually obj.$machine - my mkfiles build *.o, *.a, and the a.outs in $md - this is my acc script, which i use for compiling adobe routines ---- -#! /user/haahr/bin/next/rc - -cc = cc -proto = '-DPROTOTYPES=1' - -switch ($md) { -case noproto.$machine; proto = '-DPROTOTYPES=0' -case gprof.$machine; cc = ($cc -pg) -case prof.$machine; cc = ($cc -p) -case lcomp.$machine; cc = lcomp -} -exec $cc $proto '-DPACKAGE_SPECS="package.h"' '-DISP=isp_mc68020' '-DOS=os_mach' $* - -From rc-owner Tue May 12 14:54:10 1992 -Received: from postman.osf.org ([130.105.1.152]) by archone.tamu.edu with SMTP id <45337>; Tue, 12 May 1992 14:38:16 -0500 -Received: from earth.osf.org by postman.osf.org (5.64+/OSF 1.0) - id AA14480; Tue, 12 May 92 13:25:03 -0400 -Received: by earth.osf.org (5.64/4.7) id AA03499; Tue, 12 May 92 13:25:02 -0400 -Date: Tue, 12 May 1992 12:25:02 -0500 -From: rsalz@osf.org -Message-Id: <9205121725.AA03499@earth.osf.org> -To: rc@archone.tamu.edu -Subject: Useful function -Status: R - -It looks like line noise, but it turns things like - /home/rsalz/foo/bar -into - ~/foo/bar - -Useful for when you put your current directory up in your icon title. -By duplicating the $home section you can make things like - /project/dce/build/dce1.0.1/src/rpc -become - $MYBT/src/rpc - -## If a pathname starts with $home, turn $home into ~. Uses all built-ins. -fn tildepath { p1=() i=() { - p1=$1 - switch ($p1) { - case $home $home/* - # Split arg into components - *=`` (/) { echo -n $p1 } - # Shift down by number of components in $home - for (i in `` (/) { echo -n $home } ) shift - # Glue back together - p1='~' - for (i) p1=$p1 ^ '/' ^ $i - echo $p1 - case * - echo $p1 - } - return 0 -} } - -From osf.org!rsalz Tue May 12 15:47:12 1992 -Received: from postman.osf.org ([130.105.1.152]) by archone.tamu.edu with SMTP id <45316>; Tue, 12 May 1992 15:47:06 -0500 -Received: from earth.osf.org by postman.osf.org (5.64+/OSF 1.0) - id AA21070; Tue, 12 May 92 16:46:58 -0400 -Received: by earth.osf.org (5.64/4.7) id AA09396; Tue, 12 May 92 16:46:56 -0400 -Date: Tue, 12 May 1992 15:46:56 -0500 -From: rsalz@osf.org -Message-Id: <9205122046.AA09396@earth.osf.org> -To: byron@archone.tamu.edu -Subject: Re: Useful function -Status: R - ->wow. thanks, i'll add it to EXAMPLES. -Glad you like. Getting something added to EXAMPLES has been a goal of mine... - -I've been thinking, a bit, about a more general way of doing it. I want -a "prefix-sub" function, like this - prefix $some_path var1 var2 var3 var4 var5 -That would take some_path and replace any leading $var1 (etc) values -with the variable name. Return on the first match. - -Hmm -- come to think of it, that's very easy to do: - -# Use pathprefix filename var1 var2 var3 -# returns filename, with leading prefixes (in $var1...) turned into the -# string $var1... -fn pathprefix { p1=() i=() j=() { - p1=$1 ; shift - for (i) { - ~ $p1 $$i $$i^/* && { - *=`` (/) { echo -n $p1 } - for (j in `` (/) { echo -n $$i } ) shift - p1='$'^$i - for (j) p1=$p1 ^ '/' ^ $j - echo $p1 - return 0 - } - } - echo $p1 - return 0 -} } - -home=/user/users/rsalz -z=/usr/users -pathprefix /usr/users/rsalz home usr # --> $home -pathprefix /usr/users/rsalz z # --> $z/rsalz -pathprefix /usr/users/rsalz/foo z home # --> $z/rsalz/foo -pathprefix /usr/users/rsalz/foo home # --> $home/foo - diff --git a/Makefile.in b/Makefile.in @@ -1,80 +0,0 @@ -# Makefile.in for rc. - -SHELL=/bin/sh - -bindir=@bindir@ -exec_prefix=@exec_prefix@ -mandir=@mandir@ -prefix=@prefix@ - -CC=@CC@ -CFLAGS=@CFLAGS@ -LDFLAGS=@CFLAGS@ -LIBS=@LIBS@ - -INSTALL=@INSTALL@ -INSTALL_DATA=@INSTALL_DATA@ -INSTALL_PROGRAM=@INSTALL_PROGRAM@ -LN=@LN@ -YACC=@YACC@ - -HISTORY=@HISTORY@ - -OBJS=@ADDON@ builtins.o except.o exec.o @EXECVE@ fn.o footobar.o getopt.o \ - glob.o glom.o hash.o heredoc.o input.o lex.o list.o main.o match.o \ - nalloc.o open.o print.o redir.o sigmsgs.o signal.o status.o tree.o \ - utils.o var.o version.o wait.o walk.o which.o y.tab.o - -all: rc $(HISTORY) - -rc: $(OBJS) - $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) - -sigmsgs.c: mksignal - sh mksignal @SIGNAL_H@ - -y.tab.c: parse.y - $(YACC) -d parse.y - -trip: rc - ./rc -p < trip.rc - -clean: force - rm -f rc $(HISTORY) - *.o *.tab.* sigmsgs.* config.cache config.log - -cleaner: clean - rm -f config.status config.h Makefile - -cleanest: cleaner - rm -f configure - -history: force - cd history; make CC="$(CC)" $(HISTORYMAKEFLAGS) - -install: all - $(INSTALL_PROGRAM) rc $(bindir) - $(INSTALL_DATA) rc.1 $(mandir)/man1/rc.1 - case "x$(HISTORY)" in \ - x) \ - ;; \ - *) \ - $(LN) $(HISTORY) - ;\ - $(INSTALL_PROGRAM) - $(bindir) ;\ - $(LN) $(bindir)/- $(bindir)/-- ;\ - $(LN) $(bindir)/- $(bindir)/-p ;\ - $(LN) $(bindir)/- $(bindir)/--p ;\ - $(INSTALL_DATA) history/history.1 $(mandir)/man1/history.1 \ - ;; \ - esac - -force: - -# dependencies: - -$(OBJS): config.h proto.h rc.h -sigmsgs.h: sigmsgs.c -lex.o y.tab.o: y.tab.c - -builtins.o except.o exec.o input.o signal.o utils.o wait.o walk.o: jbwrap.h -builtins.o: rlimit.h -builtins.o fn.o hash.o signal.o status.o: sigmsgs.h diff --git a/README b/README @@ -1,197 +0,0 @@ -This is release 1.5b2 of rc. - -Read COPYRIGHT for copying information. All files are - - Copyright 1991, 1997 Byron Rakitzis. - -COMPILING - -rc was written in portable ANSI C. If you don't have an ANSI compiler -like gcc or something close (e.g., sgi's cc) read further down on -how to convert rc's source to old C. - -The following commands are all you need to configure, build, -test, and install rc. - - $ sh configure - $ make - $ make trip - # make install - -There are lots of options you can give to configure to modify rc's -behaviour. You can also select a command line history library to link -against. For a summary of all options, run `sh configure --help'. - -You can specify Makefile variables by setting the corresponding -environment variables. For example, you might want to set `CC=cc', to -prevent configure looking for gcc, or set an initial value for `LIBS', -as in the example below. - -Here are the configure options you may want to use, in approximately -descending order of usefulness. - - --with-editline - - This option tells rc to use Simmule Turner's and Rich $alz's editline - package, which you can get from the following location. This is - essentially a lightweight version of GNU readline, providing EMACS - style command line editing and history. - - ftp://ftp.pipex.net/people/tim/editline.tar.gz - - If the editline library is not installed in a standard place, you - can tell configure where to find it by setting the environment - variable LIBS. For example, the maintainer builds rc by copying - libedit.a into the rc directory and then running this configure - command. - - LIBS=-L. sh configure --with-editline - - --with-readline - - This option tells rc to use the GNU readline package, which is similar - to editline, but has many more features. The readline package is over - 6 times the size of editline (whether you count lines of code, or the - library itself). You probably need to tell the compiler to link with - the termcap library if you're using readline. For example, here is - the configure command the maintainer uses to build rc with readline. - - LIBS=-ltermcap sh configure --with-readline - - --enable-history - - Use this option if you want to build and install the programs that - support a crude history mechanism. - -You can't use `--with-editline' and `--with-readline' together, of course, -and if you have either of those you probably don't want to bother with -`--enable-history'. - - --prefix=/path - - By default, `prefix' is /usr/local, which means that `make install' - installs rc (and possibly the history programs) in /usr/local/bin, and - man pages in /usr/local/man/man1. Use this option to change where - `make install' puts things. - - --disable-builtin-echo - - By default, the `echo' command is builtin to rc for efficiency reasons. - It is the only builtin which is not essential, and purists may wish - to omit it. - - --disable-def-interp - --enable-def-interp=/bin/foo - - By default, a program that fails with "Exec format error" is handed to - /bin/sh. This does the Right Thing for scripts that start with `:' to - indicate that they are sh scripts. You can disable this behaviour - entirely, or specify a different default interpreter. - - --disable-def-path - --enable-def-path="/usr/local/bin","/usr/bin" - - By default, if rc is started with no PATH, it uses a default path. - The default path is constructed at configure time, and consists - of each of the following directories that exist, in order. - - /usr/local/bin /usr/bin /usr/ucb /bin . - - You can disable this, or specify a different default path. Note - that the quote marks (") must be seen by configure; you will - probably need to quote them to your shell. (Not if it's already - rc, but then you will need to quote the `='.) - - --disable-job - - By default, rc puts backgrounded processes into a new process group, - as though it were a job control shell (it isn't). This is usually - needed to work around bugs in application programs which install - signal handlers for the keyboard signals without checking whether the - signal was being ignored. This option disables the default behaviour, - making rc behave like a traditional sh. You are unlikely to want this - option on any Unix system. - - --disable-protect-env - - By default, rc encodes special characters in environment variables. - This is necessary on all known Unix systems to prevent sh either - dying or discarding the variables. This option disables the default - behaviour. You are unlikely to want this option on any Unix system. - -After you've built rc, you may wish to run it through a test script -to see that everything is ok. Type `make trip' for this. This will -produce some output, and end with "trip is complete". If the trip ends -with "trip took a wrong turn..." please contact the maintainer. (If -you've built in either of the command line history libraries, the trip -will fail near the end with `trip took a wrong turn: dot -i'.) - -BUGS - -Send bug reports to <tim@uk.uu.net> (<tgoodwin@cygnus.co.uk> after -1997-07-27). If a core dump is generated, sending a backtrace will -help a great deal. You can get a backtrace like this. - - ; gdb rc core - (gdb) where - <<<BACKTRACE INFO>>> - (gdb) - -Also, always report the machine, OS (`uname -a'), and compiler used to -make rc; this information is extremely valuable. - -FEEPING CREATURISM - -See the end of the man page, under "INCOMPATABILITIES" for (known?) -differences from the "real" rc. Most of these changes were necessary -to get rc to work in a reasonable fashion on a real (i.e. commercial, -non-Labs) Unix system; a few were changes motivated by concern about -some inadequacies in the original design. - -YACC - -The yacc that Sun ships with SunOS 4.1.1 calls malloc() to allocate -space for the state stack, and requires a call to YYACCEPT or YYABORT to -free this memory. This means that if rc takes an interrupt while parsing -a command (say, if ^C is typed), yacc will leak away this memory. The -solution is to use a yacc which statically allocates this array, such -as the yacc in the BSD distribution. Berkeley yacc-generated y.tab.c -and y.tab.h are shipped with rc in case you cannot get hold of Berkeley -yacc. - -OLD C - -If you need to convert rc's source into K&R C, you need to run the -source through a filter called "unproto", posted in comp.sources.misc. -A sample "cpp" shell script that I used to run unproto under SunOS is -supplied with rc. - -CREDITS - -This shell was written by me, Byron Rakitzis, but kudos go to Paul Haahr -for letting me know what a shell should do and for contributing certain -bits and pieces to rc (notably the limits code, print.c, most of which.c -and the backquote redirection code), and to Hugh Redelmeier for running -rc through his fussy ANSI compiler and thereby provoking interesting -discussions about portability, and also for providing many valuable -suggestions for improving rc's code in general. Finally, many thanks -go to David Sanderson, for reworking the man page to format well with -troff, and for providing many suggestions both for rc and its man page. - -Thanks to Boyd Roberts for the original history.c, and to Hugh again for -re-working parts of that code. - -Of course, without Tom Duff's design of the original rc, I could not -have written this shell (though I probably would have written *a* -shell). Almost of all of the features, with minor exceptions, have been -implemented as described in the Unix v10 manuals. Hats off to td for -designing a C-like, minimal but very useful shell. - -Tom Duff has kindly given permission for the paper he wrote for UKUUG to -be distributed with this version of rc (called "plan9.ps" in the same -ftp directory as the shell). Please read this paper bearing in mind that -it describes a program that was written at AT&T and that the version of -rc presented here differs in some respects. - -The current maintainer of rc is Tim Goodwin, <tim@uk.uu.net> -(<tgoodwin@cygnus.co.uk> after 1997-07-27). diff --git a/addon.c b/addon.c @@ -1,22 +0,0 @@ -/* - This file contains the implementations of any locally defined - builtins. -*/ - -#ifdef DWS - -/* - This is what DaviD Sanderson (dws@cs.wisc.edu) uses. -*/ - -#include <sys/types.h> -#include <sys/file.h> -#include <sys/stat.h> - -#include "rc.h" /* for bool TRUE, FALSE */ -#include "addon.h" - -#include "addon/access.c" -#include "addon/test.c" - -#endif diff --git a/addon.h b/addon.h @@ -1,38 +0,0 @@ -/* - This file is the interface to the rest of rc for any locally - defined addon builtins. By default there are none. - The interface consists of the following macro. - - ADDONS A comma-separated list of pairs of function pointers - and string literals. - - The addon functions must also have proper prototypes in this file. - The builtins all have the form: - - void b_NAME(char **av); - - Builtins report their exit status using set(TRUE) or set(FALSE). - - Example: - - #define ADDONS { b_test, "test" }, - extern void b_test(char **av); -*/ - -#define ADDONS /* no addons by default */ - -#ifdef DWS - -/* - This is what DaviD Sanderson (dws@cs.wisc.edu) uses. -*/ - -#undef ADDONS -#define ADDONS { b_access, "access" },\ - { b_test, "test" },\ - { b_test, "[" }, - -extern void b_access(char **av); -extern void b_test(char **av); - -#endif diff --git a/builtins.c b/builtins.c @@ -7,16 +7,17 @@ because of a bad umask. */ -#include "rc.h" - #include <sys/ioctl.h> #include <setjmp.h> #include <errno.h> - +#include "rc.h" #include "jbwrap.h" #include "sigmsgs.h" +#ifndef NOLIMITS +#include <sys/time.h> +#include <sys/resource.h> +#endif #include "addon.h" -#include "rlimit.h" extern int umask(int); @@ -24,11 +25,10 @@ static void b_break(char **), b_cd(char **), b_eval(char **), b_exit(char **), b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **), b_wait(char **), b_whatis(char **); -#if HAVE_SETRLIMIT +#ifndef NOLIMITS static void b_limit(char **); #endif - -#if RC_ECHO +#ifndef NOECHO static void b_echo(char **); #endif @@ -39,13 +39,13 @@ static struct { { b_break, "break" }, { b_builtin, "builtin" }, { b_cd, "cd" }, -#if RC_ECHO +#ifndef NOECHO { b_echo, "echo" }, #endif { b_eval, "eval" }, { b_exec, "exec" }, { b_exit, "exit" }, -#if HAVE_SETRLIMIT +#ifndef NOLIMITS { b_limit, "limit" }, #endif { b_newpgrp, "newpgrp" }, @@ -100,7 +100,7 @@ static void badnum(char *num) { extern void b_exec(char **av) { } -#if RC_ECHO +#ifndef NOECHO /* echo -n omits a newline. echo -- -n echos '-n' */ static void b_echo(char **av) { @@ -121,7 +121,7 @@ static void b_echo(char **av) { static void b_cd(char **av) { List *s, nil; char *path = NULL; - size_t t, pathlen = 0; + SIZE_T t, pathlen = 0; if (*++av == NULL) { s = varlookup("home"); *av = (s == NULL) ? "/" : s->w; @@ -250,8 +250,7 @@ extern void b_builtin(char **av) { /* wait for a given process, or all outstanding processes */ static void b_wait(char **av) { - int stat; - pid_t pid; + int stat, pid; if (av[1] == NULL) { waitforall(); return; @@ -415,13 +414,15 @@ static void b_newpgrp(char **av) { arg_count("newpgrp"); return; } - setpgid(rc_pid, rc_pid); /* XXX check return value */ - tcsetpgrp(2, rc_pid); /* XXX check return value */ + setpgrp(rc_pid, rc_pid); +#ifdef TIOCSPGRP + ioctl(2, TIOCSPGRP, &rc_pid); +#endif } /* Berkeley limit support was cleaned up by Paul Haahr. */ -#if HAVE_SETRLIMIT +#ifndef NOLIMITS typedef struct Suffix Suffix; struct Suffix { const Suffix *next; @@ -463,9 +464,14 @@ static const Limit limits[] = { { NULL, 0, NULL } }; +#ifndef SYSVR4 +extern int getrlimit(int, struct rlimit *); +extern int setrlimit(int, struct rlimit *); +#endif + static void printlimit(const Limit *limit, bool hard) { struct rlimit rlim; - rlim_t lim; + long lim; getrlimit(limit->flag, &rlim); if (hard) lim = rlim.rlim_max; @@ -480,11 +486,11 @@ static void printlimit(const Limit *limit, bool hard) { lim /= suf->amount; break; } - fprint(1, RLIM_FMT, limit->name, (RLIM_CONV)lim, (suf == NULL || lim == 0) ? "" : suf->name); + fprint(1, "%s \t%d%s\n", limit->name, lim, (suf == NULL || lim == 0) ? "" : suf->name); } } -static rlim_t parselimit(const Limit *limit, char *s) { +static long parselimit(const Limit *limit, char *s) { char *t; int len = strlen(s); long lim = 1; diff --git a/config.h.in b/config.h.in @@ -1,44 +0,0 @@ -/* Header files */ -#undef STDC_HEADERS - -#undef HAVE_SYS_RESOURCE_H -#undef RLIMIT_NEEDS_KERNEL -#undef HAVE_SYS_TIME_H -#undef HAVE_UNISTD_H - -#undef HAVE_DIRENT_H -#undef HAVE_SYS_NDIR_H -#undef HAVE_SYS_DIR_H -#undef HAVE_NDIR_H - -/* Functions */ -#undef HAVE_GETGROUPS -#undef HAVE_SETPGRP -#undef HAVE_SETRLIMIT - -/* Types */ -#undef HAVE_GID_T -#undef HAVE_RLIM_T -#undef HAVE_QUAD_T -#undef RLIM_T_IS_QUAD_T -#undef GETGROUPS_T -#undef gid_t -#undef pid_t -#undef size_t -#undef uid_t - -/* OS features */ -#undef HASH_BANG -#undef HAVE_DEV_FD -#undef HAVE_FIFO -#undef HAVE_PROC_SELF_FD -#undef HAVE_RESTARTABLE_SYSCALLS -#undef SETPGRP_VOID - -/* rc features */ -#undef DEFAULTINTERP -#undef DEFAULTPATH -#undef RC_ECHO -#undef RC_JOB -#undef PROTECT_ENV -#undef READLINE diff --git a/configure b/configure @@ -1,2541 +0,0 @@ -#! /bin/sh - -# Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.12 -# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. - -# Defaults: -ac_help= -ac_default_prefix=/usr/local -# Any additions from configure.in: -ac_help="$ac_help - --disable-builtin-echo Don't include \`echo' as a builtin" -ac_help="$ac_help - --disable-job Don't do job-control-style backgrounding" -ac_help="$ac_help - --disable-protect-env Don't protect environment names" -ac_help="$ac_help - --enable-def-interp=/bin/foo - Use /bin/foo as default interpreter [/bin/sh]" -ac_help="$ac_help - --enable-def-path=\"/usr/local/bin/\",\"/usr/bin\" - Default path [All of these that exist - (/usr/local/bin /usr/bin /usr/ucb /bin .)]" -ac_help="$ac_help - --enable-history Build history subprograms" -ac_help="$ac_help - --with-addon Extra builtins, from addon.c " -ac_help="$ac_help - --with-editline Simmule Turner's line editing" -ac_help="$ac_help - --with-readline Bloated GNU line editing" - -# Initialize some variables set by options. -# The variables have the same names as the options, with -# dashes changed to underlines. -build=NONE -cache_file=./config.cache -exec_prefix=NONE -host=NONE -no_create= -nonopt=NONE -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -target=NONE -verbose= -x_includes=NONE -x_libraries=NONE -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -# Initialize some other variables. -subdirs= -MFLAGS= MAKEFLAGS= -# Maximum number of lines to put in a shell here document. -ac_max_here_lines=12 - -ac_prev= -for ac_option -do - - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - case "$ac_option" in - -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) ac_optarg= ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case "$ac_option" in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - eval "enable_${ac_feature}=no" ;; - - -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "enable_${ac_feature}='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he) - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat << EOF -Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] -Configuration: - --cache-file=FILE cache test results in FILE - --help print this message - --no-create do not create output files - --quiet, --silent do not print \`checking...' messages - --version print the version of autoconf that created configure -Directory and file names: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [same as prefix] - --bindir=DIR user executables in DIR [EPREFIX/bin] - --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] - --libexecdir=DIR program executables in DIR [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data in DIR - [PREFIX/share] - --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data in DIR - [PREFIX/com] - --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] - --libdir=DIR object code libraries in DIR [EPREFIX/lib] - --includedir=DIR C header files in DIR [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - --srcdir=DIR find the sources in DIR [configure dir or ..] - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM - run sed PROGRAM on installed program names -EOF - cat << EOF -Host type: - --build=BUILD configure for building on BUILD [BUILD=HOST] - --host=HOST configure for HOST [guessed] - --target=TARGET configure for TARGET [TARGET=HOST] -Features and packages: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR -EOF - if test -n "$ac_help"; then - echo "--enable and --with options recognized:$ac_help" - fi - exit 0 ;; - - -host | --host | --hos | --ho) - ac_prev=host ;; - -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix="$ac_optarg" ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix="$ac_optarg" ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.12" - exit 0 ;; - - -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "with_${ac_package}='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - eval "with_${ac_package}=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes="$ac_optarg" ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries="$ac_optarg" ;; - - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } - ;; - - *) - if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" 1>&2 - fi - if test "x$nonopt" != xNONE; then - { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } - fi - nonopt="$ac_option" - ;; - - esac -done - -if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } -fi - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 6 checking for... messages and results -# 5 compiler messages saved in config.log -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>./config.log - -echo "\ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. -" 1>&5 - -# Strip out --no-create and --no-recursion so they do not pile up. -# Also quote any args containing shell metacharacters. -ac_configure_args= -for ac_arg -do - case "$ac_arg" in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ac_configure_args="$ac_configure_args '$ac_arg'" ;; - *) ac_configure_args="$ac_configure_args $ac_arg" ;; - esac -done - -# NLS nuisances. -# Only set these to C if already set. These must not be set unconditionally -# because not all systems understand e.g. LANG=C (notably SCO). -# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! -# Non-C LC_CTYPE values break the ctype check. -if test "${LANG+set}" = set; then LANG=C; export LANG; fi -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi -if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi -if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo > confdefs.h - -# A filename unique to this package, relative to the directory that -# configure is in, which we can look for to find out if srcdir is correct. -ac_unique_file=rc.h - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_prog=$0 - ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` - test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } - else - { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } - fi -fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` - -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - echo "loading site script $ac_site_file" - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - echo "loading cache $cache_file" - . $cache_file -else - echo "creating cache $cache_file" - > $cache_file -fi - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - - - - - -# Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:549: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="gcc" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:578: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - ac_prog_rejected=no - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - break - fi - done - IFS="$ac_save_ifs" -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - set dummy "$ac_dir/$ac_word" "$@" - shift - ac_cv_prog_CC="$@" - fi -fi -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } -fi - -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:626: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -cat > conftest.$ac_ext <<EOF -#line 636 "configure" -#include "confdefs.h" -main(){return(0);} -EOF -if { (eval echo configure:640: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - ac_cv_prog_cc_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cc_cross=no - else - ac_cv_prog_cc_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cc_works=no -fi -rm -fr conftest* - -echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 -if test $ac_cv_prog_cc_works = no; then - { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:660: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 -cross_compiling=$ac_cv_prog_cc_cross - -echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:665: checking whether we are using GNU C" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.c <<EOF -#ifdef __GNUC__ - yes; -#endif -EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:674: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes -else - ac_cv_prog_gcc=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then - GCC=yes - ac_test_CFLAGS="${CFLAGS+set}" - ac_save_CFLAGS="$CFLAGS" - CFLAGS= - echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:689: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_cc_g=yes -else - ac_cv_prog_cc_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 - if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" - elif test $ac_cv_prog_cc_g = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-O2" - fi -else - GCC= - test "${CFLAGS+set}" = set || CFLAGS="-g" -fi - -case "x$GCC" in -xyes) - CFLAGS="-Wall $CFLAGS" - ;; -esac - -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } -fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# ./install, which can be erroneously created by make from ./install.sh. -echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:752: checking for a BSD compatible install" >&5 -if test -z "$INSTALL"; then -if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - # Account for people who put trailing slashes in PATH elements. - case "$ac_dir/" in - /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - for ac_prog in ginstall installbsd scoinst install; do - if test -f $ac_dir/$ac_prog; then - if test $ac_prog = install && - grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - # OSF/1 installbsd also uses dspmsg, but is usable. - : - else - ac_cv_path_install="$ac_dir/$ac_prog -c" - break 2 - fi - fi - done - ;; - esac - done - IFS="$ac_save_IFS" - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL="$ac_cv_path_install" - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL="$ac_install_sh" - fi -fi -echo "$ac_t""$INSTALL" 1>&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -for ac_prog in 'bison -y' byacc -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:806: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$YACC"; then - ac_cv_prog_YACC="$YACC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_YACC="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -YACC="$ac_cv_prog_YACC" -if test -n "$YACC"; then - echo "$ac_t""$YACC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -test -n "$YACC" && break -done -test -n "$YACC" || YACC="yacc" - -for ac_prog in ln cp -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:840: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_LN'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$LN"; then - ac_cv_prog_LN="$LN" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_LN="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -LN="$ac_cv_prog_LN" -if test -n "$LN"; then - echo "$ac_t""$LN" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -test -n "$LN" && break -done - - -echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:870: checking how to run the C preprocessor" >&5 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then -if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - # This must be in double quotes, not single quotes, because CPP may get - # substituted into the Makefile and "${CC-cc}" will confuse make. - CPP="${CC-cc} -E" - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. - cat > conftest.$ac_ext <<EOF -#line 885 "configure" -#include "confdefs.h" -#include <assert.h> -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:891: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP="${CC-cc} -E -traditional-cpp" - cat > conftest.$ac_ext <<EOF -#line 902 "configure" -#include "confdefs.h" -#include <assert.h> -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP=/lib/cpp -fi -rm -f conftest* -fi -rm -f conftest* - ac_cv_prog_CPP="$CPP" -fi - CPP="$ac_cv_prog_CPP" -else - ac_cv_prog_CPP="$CPP" -fi -echo "$ac_t""$CPP" 1>&6 - -for ac_hdr in sys/resource.h sys/time.h sys/types.h unistd.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:934: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 939 "configure" -#include "confdefs.h" -#include <$ac_hdr> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:944: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <<EOF -#define $ac_tr_hdr 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi -done - -ac_header_dirent=no -for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:975: checking for $ac_hdr that defines DIR" >&5 -if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 980 "configure" -#include "confdefs.h" -#include <sys/types.h> -#include <$ac_hdr> -int main() { -DIR *dirp = 0; -; return 0; } -EOF -if { (eval echo configure:988: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - eval "ac_cv_header_dirent_$ac_safe=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_dirent_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <<EOF -#define $ac_tr_hdr 1 -EOF - ac_header_dirent=$ac_hdr; break -else - echo "$ac_t""no" 1>&6 -fi -done -# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. -if test $ac_header_dirent = dirent.h; then -echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:1013: checking for opendir in -ldir" >&5 -ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldir $LIBS" -cat > conftest.$ac_ext <<EOF -#line 1021 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir(); - -int main() { -opendir() -; return 0; } -EOF -if { (eval echo configure:1032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - LIBS="$LIBS -ldir" -else - echo "$ac_t""no" 1>&6 -fi - -else -echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:1054: checking for opendir in -lx" >&5 -ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lx $LIBS" -cat > conftest.$ac_ext <<EOF -#line 1062 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir(); - -int main() { -opendir() -; return 0; } -EOF -if { (eval echo configure:1073: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - LIBS="$LIBS -lx" -else - echo "$ac_t""no" 1>&6 -fi - -fi - -echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1096: checking for ANSI C header files" >&5 -if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1101 "configure" -#include "confdefs.h" -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1109: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - rm -rf conftest* - ac_cv_header_stdc=yes -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - ac_cv_header_stdc=no -fi -rm -f conftest* - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. -cat > conftest.$ac_ext <<EOF -#line 1126 "configure" -#include "confdefs.h" -#include <string.h> -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "memchr" >/dev/null 2>&1; then - : -else - rm -rf conftest* - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. -cat > conftest.$ac_ext <<EOF -#line 1144 "configure" -#include "confdefs.h" -#include <stdlib.h> -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "free" >/dev/null 2>&1; then - : -else - rm -rf conftest* - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. -if test "$cross_compiling" = yes; then - : -else - cat > conftest.$ac_ext <<EOF -#line 1165 "configure" -#include "confdefs.h" -#include <ctype.h> -#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int main () { int i; for (i = 0; i < 256; i++) -if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); -exit (0); } - -EOF -if { (eval echo configure:1176: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - : -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_header_stdc=no -fi -rm -fr conftest* -fi - -fi -fi - -echo "$ac_t""$ac_cv_header_stdc" 1>&6 -if test $ac_cv_header_stdc = yes; then - cat >> confdefs.h <<\EOF -#define STDC_HEADERS 1 -EOF - -fi - - -echo $ac_n "checking for signal names in <sys/signal.h>""... $ac_c" 1>&6 -echo "configure:1201: checking for signal names in <sys/signal.h>" >&5 -if eval "test \"`echo '$''{'rc_cv_sys_signal_h'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if grep SIGINT /usr/include/sys/signal.h >/dev/null 2>&1; then - rc_cv_sys_signal_h=yes - else - rc_cv_sys_signal_h=no - fi -fi - -echo "$ac_t""$rc_cv_sys_signal_h" 1>&6 - -case "x$rc_cv_sys_signal_h" in -xyes) - SIGNAL_H=/usr/include/sys/signal.h - ;; -xno) - echo $ac_n "checking for signal names in <asm/signal.h>""... $ac_c" 1>&6 -echo "configure:1220: checking for signal names in <asm/signal.h>" >&5 -if eval "test \"`echo '$''{'rc_cv_asm_signal_h'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if grep SIGINT /usr/include/asm/signal.h >/dev/null 2>&1; then - rc_cv_asm_signal_h=yes - else - rc_cv_asm_signal_h=no - fi -fi - -echo "$ac_t""$rc_cv_asm_signal_h" 1>&6 - - case "x$rc_cv_asm_signal_h" in - xyes) - SIGNAL_H=/usr/include/asm/signal.h - ;; - xno) - { echo "configure: error: Can't find signal names in <sys/signal.h> or <asm/signal.h>" 1>&2; exit 1; } - ;; - esac - ;; -esac - - -echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:1246: checking for uid_t in sys/types.h" >&5 -if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1251 "configure" -#include "confdefs.h" -#include <sys/types.h> -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "uid_t" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_uid_t=yes -else - rm -rf conftest* - ac_cv_type_uid_t=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_type_uid_t" 1>&6 -if test $ac_cv_type_uid_t = no; then - cat >> confdefs.h <<\EOF -#define uid_t int -EOF - - cat >> confdefs.h <<\EOF -#define gid_t int -EOF - -fi - -echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 -echo "configure:1280: checking type of array argument to getgroups" >&5 -if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_type_getgroups=cross -else - cat > conftest.$ac_ext <<EOF -#line 1288 "configure" -#include "confdefs.h" - -/* Thanks to Mike Rendell for this test. */ -#include <sys/types.h> -#define NGID 256 -#undef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -main() -{ - gid_t gidset[NGID]; - int i, n; - union { gid_t gval; long lval; } val; - - val.lval = -1; - for (i = 0; i < NGID; i++) - gidset[i] = val.gval; - n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, - gidset); - /* Exit non-zero if getgroups seems to require an array of ints. This - happens when gid_t is short but getgroups modifies an array of ints. */ - exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); -} - -EOF -if { (eval echo configure:1313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - ac_cv_type_getgroups=gid_t -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_type_getgroups=int -fi -rm -fr conftest* -fi - -if test $ac_cv_type_getgroups = cross; then - cat > conftest.$ac_ext <<EOF -#line 1327 "configure" -#include "confdefs.h" -#include <unistd.h> -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_getgroups=gid_t -else - rm -rf conftest* - ac_cv_type_getgroups=int -fi -rm -f conftest* - -fi -fi - -echo "$ac_t""$ac_cv_type_getgroups" 1>&6 -cat >> confdefs.h <<EOF -#define GETGROUPS_T $ac_cv_type_getgroups -EOF - - -echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:1351: checking for pid_t" >&5 -if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1356 "configure" -#include "confdefs.h" -#include <sys/types.h> -#if STDC_HEADERS -#include <stdlib.h> -#include <stddef.h> -#endif -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_pid_t=yes -else - rm -rf conftest* - ac_cv_type_pid_t=no -fi -rm -f conftest* - -fi -echo "$ac_t""$ac_cv_type_pid_t" 1>&6 -if test $ac_cv_type_pid_t = no; then - cat >> confdefs.h <<\EOF -#define pid_t int -EOF - -fi - -echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1384: checking for size_t" >&5 -if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1389 "configure" -#include "confdefs.h" -#include <sys/types.h> -#if STDC_HEADERS -#include <stdlib.h> -#include <stddef.h> -#endif -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_size_t=yes -else - rm -rf conftest* - ac_cv_type_size_t=no -fi -rm -f conftest* - -fi -echo "$ac_t""$ac_cv_type_size_t" 1>&6 -if test $ac_cv_type_size_t = no; then - cat >> confdefs.h <<\EOF -#define size_t unsigned -EOF - -fi - -echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:1417: checking for uid_t in sys/types.h" >&5 -if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1422 "configure" -#include "confdefs.h" -#include <sys/types.h> -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "uid_t" >/dev/null 2>&1; then - rm -rf conftest* - ac_cv_type_uid_t=yes -else - rm -rf conftest* - ac_cv_type_uid_t=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_type_uid_t" 1>&6 -if test $ac_cv_type_uid_t = no; then - cat >> confdefs.h <<\EOF -#define uid_t int -EOF - - cat >> confdefs.h <<\EOF -#define gid_t int -EOF - -fi - - -for ac_func in getgroups setpgrp setrlimit -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1454: checking for $ac_func" >&5 -if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1459 "configure" -#include "confdefs.h" -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func(); below. */ -#include <assert.h> -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -$ac_func(); -#endif - -; return 0; } -EOF -if { (eval echo configure:1482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_func_$ac_func=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_$ac_func=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - cat >> confdefs.h <<EOF -#define $ac_tr_func 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi -done - - -echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:1508: checking whether setpgrp takes no argument" >&5 -if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } -else - cat > conftest.$ac_ext <<EOF -#line 1516 "configure" -#include "confdefs.h" - -/* - * If this system has a BSD-style setpgrp, which takes arguments, exit - * successfully. - */ -main() -{ - if (setpgrp(1,1) == -1) - exit(0); - else - exit(1); -} - -EOF -if { (eval echo configure:1532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - ac_cv_func_setpgrp_void=no -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_func_setpgrp_void=yes -fi -rm -fr conftest* -fi - - -fi - -echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6 -if test $ac_cv_func_setpgrp_void = yes; then - cat >> confdefs.h <<\EOF -#define SETPGRP_VOID 1 -EOF - -fi - - -echo $ac_n "checking if _KERNEL is required for RLIMIT defines""... $ac_c" 1>&6 -echo "configure:1557: checking if _KERNEL is required for RLIMIT defines" >&5 -if eval "test \"`echo '$''{'rc_cv_kernel_rlimit'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1562 "configure" -#include "confdefs.h" - -#include <sys/types.h> -#include <sys/resource.h> - -int main() { - -int f; -f = RLIMIT_DATA; - -; return 0; } -EOF -if { (eval echo configure:1575: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - rc_cv_kernel_rlimit=no -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - cat > conftest.$ac_ext <<EOF -#line 1583 "configure" -#include "confdefs.h" - -#include <sys/types.h> -#define _KERNEL -#include <sys/resource.h> -#undef _KERNEL - -int main() { - -int f; -f = RLIMIT_DATA; - -; return 0; } -EOF -if { (eval echo configure:1598: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - rc_cv_kernel_rlimit=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - rc_cv_kernel_rlimit=no -fi -rm -f conftest* -fi -rm -f conftest* -fi - -echo "$ac_t""$rc_cv_kernel_rlimit" 1>&6 -case "x$rc_cv_kernel_rlimit" in -xyes) - cat >> confdefs.h <<\EOF -#define RLIMIT_NEEDS_KERNEL 1 -EOF - - ;; -esac - -echo $ac_n "checking for rlim_t""... $ac_c" 1>&6 -echo "configure:1623: checking for rlim_t" >&5 -if eval "test \"`echo '$''{'rc_cv_have_rlim_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1628 "configure" -#include "confdefs.h" - -#include <sys/types.h> -#if RLIMIT_NEEDS_KERNEL -#define _KERNEL -#endif -#include <sys/resource.h> - -EOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "rlim_t" >/dev/null 2>&1; then - rm -rf conftest* - rc_cv_have_rlim_t=yes -else - rm -rf conftest* - rc_cv_have_rlim_t=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$rc_cv_have_rlim_t" 1>&6 - -case "x$rc_cv_have_rlim_t" in -xyes) - cat >> confdefs.h <<\EOF -#define HAVE_RLIM_T 1 -EOF - - ;; -xno) - echo $ac_n "checking for native quad_t""... $ac_c" 1>&6 -echo "configure:1661: checking for native quad_t" >&5 -if eval "test \"`echo '$''{'rc_cv_have_quad_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } -else - cat > conftest.$ac_ext <<EOF -#line 1669 "configure" -#include "confdefs.h" - -#include <sys/types.h> -main() { - quad_t q; - q = 0; - exit((int) q); -} - -EOF -if { (eval echo configure:1680: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - rc_cv_have_quad_t=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - rc_cv_have_quad_t=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$rc_cv_have_quad_t" 1>&6 - - case "x$rc_cv_have_quad_t" in - xyes) - cat >> confdefs.h <<\EOF -#define HAVE_QUAD_T 1 -EOF - - - echo $ac_n "checking if rlimit values are quad_t""... $ac_c" 1>&6 -echo "configure:1704: checking if rlimit values are quad_t" >&5 -if eval "test \"`echo '$''{'rc_cv_rlim_t_is_quad_t'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - $ac_cv_type_quad_t -else - cat > conftest.$ac_ext <<EOF -#line 1712 "configure" -#include "confdefs.h" - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/types.h> -#if RLIMIT_NEEDS_KERNEL -#define _KERNEL -#endif -#include <sys/resource.h> -#if RLIMIT_NEEDS_KERNEL -#undef _KERNEL -#endif -main(){ - struct rlimit rl; - exit(sizeof rl.rlim_cur != sizeof(quad_t)); -} - -EOF -if { (eval echo configure:1731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - rc_cv_rlim_t_is_quad_t=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - rc_cv_rlim_t_is_quad_t=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$rc_cv_rlim_t_is_quad_t" 1>&6 - - case "x$rc_cv_rlim_t_is_quad_t" in - xyes) - cat >> confdefs.h <<\EOF -#define RLIM_T_IS_QUAD_T 1 -EOF - - ;; - esac - ;; - esac - ;; -esac - -echo $ac_n "checking for restartable system calls""... $ac_c" 1>&6 -echo "configure:1761: checking for restartable system calls" >&5 -if eval "test \"`echo '$''{'ac_cv_sys_restartable_syscalls'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } -else - cat > conftest.$ac_ext <<EOF -#line 1769 "configure" -#include "confdefs.h" -/* Exit 0 (true) if wait returns something other than -1, - i.e. the pid of the child, which means that wait was restarted - after getting the signal. */ -#include <sys/types.h> -#include <signal.h> -ucatch (isig) { } -main () { - int i = fork (), status; - if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); } - signal (SIGINT, ucatch); - status = wait(&i); - if (status == -1) wait(&i); - exit (status == -1); -} - -EOF -if { (eval echo configure:1787: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - ac_cv_sys_restartable_syscalls=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_sys_restartable_syscalls=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$ac_cv_sys_restartable_syscalls" 1>&6 -if test $ac_cv_sys_restartable_syscalls = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_RESTARTABLE_SYSCALLS 1 -EOF - -fi - - -# Pull the hash mark out of the macro call to avoid m4 problems. -ac_msg="whether #! works in shell scripts" -echo $ac_n "checking $ac_msg""... $ac_c" 1>&6 -echo "configure:1813: checking $ac_msg" >&5 -if eval "test \"`echo '$''{'ac_cv_sys_interpreter'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo '#! /bin/cat -exit 69 -' > conftest -chmod u+x conftest -(SHELL=/bin/sh; export SHELL; ./conftest >/dev/null) -if test $? -ne 69; then - ac_cv_sys_interpreter=yes -else - ac_cv_sys_interpreter=no -fi -rm -f conftest -fi - -echo "$ac_t""$ac_cv_sys_interpreter" 1>&6 - -case "x$ac_cv_sys_interpreter" in -xyes) - cat >> confdefs.h <<\EOF -#define HASH_BANG 1 -EOF - - EXECVE='' - ;; -xno) - EXECVE=execve.o -esac - - -echo $ac_n "checking for /dev/fd""... $ac_c" 1>&6 -echo "configure:1846: checking for /dev/fd" >&5 -if eval "test \"`echo '$''{'rc_cv_sys_dev_fd'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -d /dev/fd && test -r /dev/fd/0; then - rc_cv_sys_dev_fd=yes - elif test -d /proc/self/fd && test -r /proc/self/fd/0; then - rc_cv_sys_dev_fd=odd - else - rc_cv_sys_dev_fd=no - fi -fi - -echo "$ac_t""$rc_cv_sys_dev_fd" 1>&6 - -case "x$rc_cv_sys_dev_fd" in -xyes) - cat >> confdefs.h <<\EOF -#define HAVE_DEV_FD 1 -EOF - - ;; -xodd) - cat >> confdefs.h <<\EOF -#define HAVE_PROC_SELF_FD 1 -EOF - - ;; -xno) - echo $ac_n "checking for named pipes""... $ac_c" 1>&6 -echo "configure:1876: checking for named pipes" >&5 -if eval "test \"`echo '$''{'rc_cv_sys_fifo'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat >> confdefs.h <<EOF -#define TMPNAM "/tmp/rc$$.0" -EOF - - if test "$cross_compiling" = yes; then - rc_cv_sys_fifo=no -else - cat > conftest.$ac_ext <<EOF -#line 1888 "configure" -#include "confdefs.h" - -#include <sys/types.h> -#include <sys/stat.h> - -main() { - exit(mknod(TMPNAM, S_IFIFO | 0666, 0) != 0); -} - -EOF -if { (eval echo configure:1899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - rc_cv_sys_fifo=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - rc_cv_sys_fifo=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$rc_cv_sys_fifo" 1>&6 - case "x$rc_cv_sys_fifo" in - xyes) - cat >> confdefs.h <<\EOF -#define HAVE_FIFO 1 -EOF - - ;; - esac -esac - -# Check whether --enable-builtin-echo or --disable-builtin-echo was given. -if test "${enable_builtin_echo+set}" = set; then - enableval="$enable_builtin_echo" - test "x$enableval" != "xno" && cat >> confdefs.h <<\EOF -#define RC_ECHO 1 -EOF - -else - cat >> confdefs.h <<\EOF -#define RC_ECHO 1 -EOF - -fi - - -# Check whether --enable-job or --disable-job was given. -if test "${enable_job+set}" = set; then - enableval="$enable_job" - test "x$enableval" != "xno" && cat >> confdefs.h <<\EOF -#define RC_JOB 1 -EOF - -else - cat >> confdefs.h <<\EOF -#define RC_JOB 1 -EOF - -fi - - -# Check whether --enable-protect-env or --disable-protect-env was given. -if test "${enable_protect_env+set}" = set; then - enableval="$enable_protect_env" - test "x$enableval" != "xno" && cat >> confdefs.h <<\EOF -#define PROTECT_ENV 1 -EOF - -else - cat >> confdefs.h <<\EOF -#define PROTECT_ENV 1 -EOF - -fi - - -# Check whether --enable-def-interp or --disable-def-interp was given. -if test "${enable_def_interp+set}" = set; then - enableval="$enable_def_interp" - - case "x$enableval" in - xno) - ;; - xyes) - cat >> confdefs.h <<\EOF -#define DEFAULTINTERP "/bin/sh" -EOF - - ;; - *) - cat >> confdefs.h <<EOF -#define DEFAULTINTERP "$enableval" -EOF - - esac - -else - cat >> confdefs.h <<\EOF -#define DEFAULTINTERP "/bin/sh" -EOF - -fi - - -# Check whether --enable-def-path or --disable-def-path was given. -if test "${enable_def_path+set}" = set; then - enableval="$enable_def_path" - - case "x$enableval" in - xno|xyes) - ;; - *) - cat >> confdefs.h <<EOF -#define DEFAULTPATH $enableval -EOF - - esac - -else - enable_def_path=yes -fi - - -case "x$enable_def_path" in -xyes) - echo $ac_n "checking extant directories for default path""... $ac_c" 1>&6 -echo "configure:2019: checking extant directories for default path" >&5 -if eval "test \"`echo '$''{'rc_cv_def_path'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - rc_cv_def_path='' - for i in /usr/local/bin /usr/bin /usr/ucb /bin .; do - if test -d $i; then - case "x$rc_cv_def_path" in - x) - rc_cv_def_path=\"$i\" - ;; - *) - rc_cv_def_path=$rc_cv_def_path,\"$i\" - ;; - esac - fi - done - cat >> confdefs.h <<EOF -#define DEFAULTPATH $rc_cv_def_path -EOF - - -fi - -echo "$ac_t""$rc_cv_def_path" 1>&6 - ;; -esac - -# Check whether --enable-history or --disable-history was given. -if test "${enable_history+set}" = set; then - enableval="$enable_history" - test "x$enableval" != "xno" && rc_history=yes -else - rc_history=no -fi - -case "x$rc_history" in -xyes) - HISTORY=history/history - ;; -esac - - -# Check whether --with-addon or --without-addon was given. -if test "${with_addon+set}" = set; then - withval="$with_addon" - - case "x$withval" in - xyes) - ADDON=addon.o - ;; - xno) - ADDON='' - ;; - *) - ADDON=$withval - ;; - esac - -fi - - - -# Check whether --with-editline or --without-editline was given. -if test "${with_editline+set}" = set; then - withval="$with_editline" - echo $ac_n "checking for readline in -ledit""... $ac_c" 1>&6 -echo "configure:2087: checking for readline in -ledit" >&5 -ac_lib_var=`echo edit'_'readline | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ledit $LIBS" -cat > conftest.$ac_ext <<EOF -#line 2095 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char readline(); - -int main() { -readline() -; return 0; } -EOF -if { (eval echo configure:2106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define READLINE 1 -EOF - LIBS="$LIBS -ledit" -else - echo "$ac_t""no" 1>&6 -echo "configure: warning: editline library not found" 1>&2 -fi - -fi - - -# Check whether --with-readline or --without-readline was given. -if test "${with_readline+set}" = set; then - withval="$with_readline" - echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6 -echo "configure:2137: checking for readline in -lreadline" >&5 -ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lreadline $LIBS" -cat > conftest.$ac_ext <<EOF -#line 2145 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char readline(); - -int main() { -readline() -; return 0; } -EOF -if { (eval echo configure:2156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define READLINE 1 -EOF - LIBS="$LIBS -lreadline -ltermcap" -else - echo "$ac_t""no" 1>&6 -echo "configure: warning: readline library not found" 1>&2 -fi - -fi - - -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Any assignment to VPATH causes Sun make to only execute -# the first set of double-colon rules, so remove it if not needed. -# If there is a colon in the path, we need to keep it. -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' -fi - -trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 - -DEFS=-DHAVE_CONFIG_H - -# Without the "./", some shells look in PATH for config.status. -: ${CONFIG_STATUS=./config.status} - -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS <<EOF -#! /bin/sh -# Generated automatically by configure. -# Run this file to recreate the current configuration. -# This directory was configured as follows, -# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# $0 $ac_configure_args -# -# Compiler output produced by configure, useful for debugging -# configure, is in ./config.log if it exists. - -ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" -for ac_option -do - case "\$ac_option" in - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" - exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; - -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.12" - exit 0 ;; - -help | --help | --hel | --he | --h) - echo "\$ac_cs_usage"; exit 0 ;; - *) echo "\$ac_cs_usage"; exit 1 ;; - esac -done - -ac_given_srcdir=$srcdir -ac_given_INSTALL="$INSTALL" - -trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS <<EOF - -# Protect against being on the right side of a sed subst in config.status. -sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; - s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF -$ac_vpsub -$extrasub -s%@CFLAGS@%$CFLAGS%g -s%@CPPFLAGS@%$CPPFLAGS%g -s%@CXXFLAGS@%$CXXFLAGS%g -s%@DEFS@%$DEFS%g -s%@LDFLAGS@%$LDFLAGS%g -s%@LIBS@%$LIBS%g -s%@exec_prefix@%$exec_prefix%g -s%@prefix@%$prefix%g -s%@program_transform_name@%$program_transform_name%g -s%@bindir@%$bindir%g -s%@sbindir@%$sbindir%g -s%@libexecdir@%$libexecdir%g -s%@datadir@%$datadir%g -s%@sysconfdir@%$sysconfdir%g -s%@sharedstatedir@%$sharedstatedir%g -s%@localstatedir@%$localstatedir%g -s%@libdir@%$libdir%g -s%@includedir@%$includedir%g -s%@oldincludedir@%$oldincludedir%g -s%@infodir@%$infodir%g -s%@mandir@%$mandir%g -s%@CC@%$CC%g -s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g -s%@INSTALL_DATA@%$INSTALL_DATA%g -s%@YACC@%$YACC%g -s%@LN@%$LN%g -s%@CPP@%$CPP%g -s%@SIGNAL_H@%$SIGNAL_H%g -s%@EXECVE@%$EXECVE%g -s%@HISTORY@%$HISTORY%g -s%@ADDON@%$ADDON%g - -CEOF -EOF - -cat >> $CONFIG_STATUS <<\EOF - -# Split the substitutions into bite-sized pieces for seds with -# small command number limits, like on Digital OSF/1 and HP-UX. -ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. -ac_file=1 # Number of current file. -ac_beg=1 # First line for current file. -ac_end=$ac_max_sed_cmds # Line after last line for current file. -ac_more_lines=: -ac_sed_cmds="" -while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file - else - sed "${ac_end}q" conftest.subs > conftest.s$ac_file - fi - if test ! -s conftest.s$ac_file; then - ac_more_lines=false - rm -f conftest.s$ac_file - else - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f conftest.s$ac_file" - else - ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" - fi - ac_file=`expr $ac_file + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_cmds` - fi -done -if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat -fi -EOF - -cat >> $CONFIG_STATUS <<EOF - -CONFIG_FILES=\${CONFIG_FILES-"Makefile"} -EOF -cat >> $CONFIG_STATUS <<\EOF -for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; - esac - - # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. - - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" - # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` - else - ac_dir_suffix= ac_dots= - fi - - case "$ac_given_srcdir" in - .) srcdir=. - if test -z "$ac_dots"; then top_srcdir=. - else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; - /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; - *) # Relative path. - srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" - top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - - case "$ac_given_INSTALL" in - [/$]*) INSTALL="$ac_given_INSTALL" ;; - *) INSTALL="$ac_dots$ac_given_INSTALL" ;; - esac - - echo creating "$ac_file" - rm -f "$ac_file" - configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." - case "$ac_file" in - *Makefile*) ac_comsub="1i\\ -# $configure_input" ;; - *) ac_comsub= ;; - esac - - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - sed -e "$ac_comsub -s%@configure_input@%$configure_input%g -s%@srcdir@%$srcdir%g -s%@top_srcdir@%$top_srcdir%g -s%@INSTALL@%$INSTALL%g -" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file -fi; done -rm -f conftest.s* - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' -ac_dC='\3' -ac_dD='%g' -# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". -ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='\([ ]\)%\1#\2define\3' -ac_uC=' ' -ac_uD='\4%g' -# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_eB='$%\1#\2define\3' -ac_eC=' ' -ac_eD='%g' - -if test "${CONFIG_HEADERS+set}" != set; then -EOF -cat >> $CONFIG_STATUS <<EOF - CONFIG_HEADERS="config.h" -EOF -cat >> $CONFIG_STATUS <<\EOF -fi -for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; - esac - - echo creating $ac_file - - rm -f conftest.frag conftest.in conftest.out - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - cat $ac_file_inputs > conftest.in - -EOF - -# Transform confdefs.h into a sed script conftest.vals that substitutes -# the proper values into config.h.in to produce config.h. And first: -# Protect against being on the right side of a sed subst in config.status. -# Protect against being in an unquoted here document in config.status. -rm -f conftest.vals -cat > conftest.hdr <<\EOF -s/[\\&%]/\\&/g -s%[\\$`]%\\&%g -s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp -s%ac_d%ac_u%gp -s%ac_u%ac_e%gp -EOF -sed -n -f conftest.hdr confdefs.h > conftest.vals -rm -f conftest.hdr - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >> conftest.vals <<\EOF -s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% -EOF - -# Break up conftest.vals because some shells have a limit on -# the size of here documents, and old seds have small limits too. - -rm -f conftest.tail -while : -do - ac_lines=`grep -c . conftest.vals` - # grep -c gives empty output for an empty file on some AIX systems. - if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi - # Write a limited-size here document to conftest.frag. - echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS - echo 'CEOF - sed -f conftest.frag conftest.in > conftest.out - rm -f conftest.in - mv conftest.out conftest.in -' >> $CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail - rm -f conftest.vals - mv conftest.tail conftest.vals -done -rm -f conftest.vals - -cat >> $CONFIG_STATUS <<\EOF - rm -f conftest.frag conftest.h - echo "/* $ac_file. Generated automatically by configure. */" > conftest.h - cat conftest.in >> conftest.h - rm -f conftest.in - if cmp -s $ac_file conftest.h 2>/dev/null; then - echo "$ac_file is unchanged" - rm -f conftest.h - else - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - fi - rm -f $ac_file - mv conftest.h $ac_file - fi -fi; done - -EOF -cat >> $CONFIG_STATUS <<EOF - -EOF -cat >> $CONFIG_STATUS <<\EOF - -exit 0 -EOF -chmod +x $CONFIG_STATUS -rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 - diff --git a/configure.in b/configure.in @@ -1,287 +0,0 @@ -AC_INIT(rc.h) - -AC_CONFIG_HEADER(config.h) - -AC_PROG_CC -case "x$GCC" in -xyes) - CFLAGS="-Wall $CFLAGS" - ;; -esac - -AC_PROG_INSTALL -AC_PROG_YACC -AC_CHECK_PROGS(LN, ln cp) - -AC_CHECK_HEADERS(sys/resource.h sys/time.h sys/types.h unistd.h) -AC_HEADER_DIRENT -AC_HEADER_STDC - -dnl Linux puts real signal names in /usr/include/asm/signal.h. -AC_CACHE_CHECK(for signal names in <sys/signal.h>, rc_cv_sys_signal_h, - if grep SIGINT /usr/include/sys/signal.h >/dev/null 2>&1; then - rc_cv_sys_signal_h=yes - else - rc_cv_sys_signal_h=no - fi) - -case "x$rc_cv_sys_signal_h" in -xyes) - SIGNAL_H=/usr/include/sys/signal.h - ;; -xno) - AC_CACHE_CHECK(for signal names in <asm/signal.h>, rc_cv_asm_signal_h, - if grep SIGINT /usr/include/asm/signal.h >/dev/null 2>&1; then - rc_cv_asm_signal_h=yes - else - rc_cv_asm_signal_h=no - fi) - - case "x$rc_cv_asm_signal_h" in - xyes) - SIGNAL_H=/usr/include/asm/signal.h - ;; - xno) - AC_MSG_ERROR(Can't find signal names in <sys/signal.h> or <asm/signal.h>) - ;; - esac - ;; -esac -AC_SUBST(SIGNAL_H) - -AC_TYPE_GETGROUPS -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_TYPE_UID_T - -AC_CHECK_FUNCS(getgroups setpgrp setrlimit) - -AC_FUNC_SETPGRP - -dnl HPUX needs _KERNEL defined to pick up RLIMIT_foo defines. (Why?) -AC_CACHE_CHECK(if _KERNEL is required for RLIMIT defines, rc_cv_kernel_rlimit, - AC_TRY_COMPILE([ -#include <sys/types.h> -#include <sys/resource.h> - ], [ -int f; -f = RLIMIT_DATA; - ], rc_cv_kernel_rlimit=no, [ AC_TRY_COMPILE([ -#include <sys/types.h> -#define _KERNEL -#include <sys/resource.h> -#undef _KERNEL - ], [ -int f; -f = RLIMIT_DATA; - ], rc_cv_kernel_rlimit=yes, rc_cv_kernel_rlimit=no)])) -case "x$rc_cv_kernel_rlimit" in -xyes) - AC_DEFINE(RLIMIT_NEEDS_KERNEL) - ;; -esac - -dnl Look for rlim_t in sys/types.h and sys/resource.h -AC_CACHE_CHECK(for rlim_t, rc_cv_have_rlim_t, - AC_EGREP_CPP(rlim_t, [ -#include <sys/types.h> -#if RLIMIT_NEEDS_KERNEL -#define _KERNEL -#endif -#include <sys/resource.h> - ], rc_cv_have_rlim_t=yes, rc_cv_have_rlim_t=no)) - -case "x$rc_cv_have_rlim_t" in -xyes) - AC_DEFINE(HAVE_RLIM_T) - ;; -xno) - AC_CACHE_CHECK(for native quad_t, rc_cv_have_quad_t, - AC_TRY_RUN([ -#include <sys/types.h> -main() { - quad_t q; - q = 0; - exit((int) q); -} - ], rc_cv_have_quad_t=yes, rc_cv_have_quad_t=no)) - - case "x$rc_cv_have_quad_t" in - xyes) - AC_DEFINE(HAVE_QUAD_T) - - AC_CACHE_CHECK(if rlimit values are quad_t, rc_cv_rlim_t_is_quad_t, - AC_TRY_RUN([ -#include <sys/types.h> -#include <sys/time.h> -#include <sys/types.h> -#if RLIMIT_NEEDS_KERNEL -#define _KERNEL -#endif -#include <sys/resource.h> -#if RLIMIT_NEEDS_KERNEL -#undef _KERNEL -#endif -main(){ - struct rlimit rl; - exit(sizeof rl.rlim_cur != sizeof(quad_t)); -} - ], rc_cv_rlim_t_is_quad_t=yes, rc_cv_rlim_t_is_quad_t=no, $ac_cv_type_quad_t)) - - case "x$rc_cv_rlim_t_is_quad_t" in - xyes) - AC_DEFINE(RLIM_T_IS_QUAD_T) - ;; - esac - ;; - esac - ;; -esac - -AC_SYS_RESTARTABLE_SYSCALLS - -dnl Does the kernel handle `#! /interpreter'? -AC_SYS_INTERPRETER -case "x$ac_cv_sys_interpreter" in -xyes) - AC_DEFINE(HASH_BANG) - EXECVE='' - ;; -xno) - EXECVE=execve.o -esac -AC_SUBST(EXECVE) - -AC_CACHE_CHECK(for /dev/fd, rc_cv_sys_dev_fd, - if test -d /dev/fd && test -r /dev/fd/0; then - rc_cv_sys_dev_fd=yes - elif test -d /proc/self/fd && test -r /proc/self/fd/0; then - rc_cv_sys_dev_fd=odd - else - rc_cv_sys_dev_fd=no - fi) - -case "x$rc_cv_sys_dev_fd" in -xyes) - AC_DEFINE(HAVE_DEV_FD) - ;; -xodd) - AC_DEFINE(HAVE_PROC_SELF_FD) - ;; -xno) - AC_CACHE_CHECK(for named pipes, rc_cv_sys_fifo, - AC_DEFINE_UNQUOTED(TMPNAM, "/tmp/rc$$.0") - AC_TRY_RUN([ -#include <sys/types.h> -#include <sys/stat.h> - -main() { - exit(mknod(TMPNAM, S_IFIFO | 0666, 0) != 0); -} - ], rc_cv_sys_fifo=yes, rc_cv_sys_fifo=no, rc_cv_sys_fifo=no)) - case "x$rc_cv_sys_fifo" in - xyes) - AC_DEFINE(HAVE_FIFO) - ;; - esac -esac - -AC_ARG_ENABLE(builtin-echo, [ --disable-builtin-echo Don't include \`echo' as a builtin], - test "x$enableval" != "xno" && AC_DEFINE(RC_ECHO), - AC_DEFINE(RC_ECHO)) - -AC_ARG_ENABLE(job, [ --disable-job Don't do job-control-style backgrounding], - test "x$enableval" != "xno" && AC_DEFINE(RC_JOB), - AC_DEFINE(RC_JOB)) - -AC_ARG_ENABLE(protect-env, [ --disable-protect-env Don't protect environment names], - test "x$enableval" != "xno" && AC_DEFINE(PROTECT_ENV), - AC_DEFINE(PROTECT_ENV)) - -AC_ARG_ENABLE(def-interp, -[ --enable-def-interp=/bin/foo - Use /bin/foo as default interpreter [/bin/sh]], -[ - case "x$enableval" in - xno) - ;; - xyes) - AC_DEFINE(DEFAULTINTERP, "/bin/sh") - ;; - *) - AC_DEFINE_UNQUOTED(DEFAULTINTERP, "$enableval") - esac -], - AC_DEFINE(DEFAULTINTERP, "/bin/sh")) - -AC_ARG_ENABLE(def-path, -[ --enable-def-path=\"/usr/local/bin/\",\"/usr/bin\" - Default path [All of these that exist - (/usr/local/bin /usr/bin /usr/ucb /bin .)]], -[ - case "x$enableval" in - xno|xyes) - ;; - *) - AC_DEFINE_UNQUOTED(DEFAULTPATH, $enableval) - esac -], - enable_def_path=yes) - -case "x$enable_def_path" in -xyes) - AC_CACHE_CHECK(extant directories for default path, rc_cv_def_path,[ - rc_cv_def_path='' - for i in /usr/local/bin /usr/bin /usr/ucb /bin .; do - if test -d $i; then - case "x$rc_cv_def_path" in - x) - rc_cv_def_path=\"$i\" - ;; - *) - rc_cv_def_path=$rc_cv_def_path,\"$i\" - ;; - esac - fi - done - AC_DEFINE_UNQUOTED(DEFAULTPATH, $rc_cv_def_path) - ]) - ;; -esac - -AC_ARG_ENABLE(history, [ --enable-history Build history subprograms], - test "x$enableval" != "xno" && rc_history=yes, - rc_history=no) -case "x$rc_history" in -xyes) - HISTORY=history/history - ;; -esac -AC_SUBST(HISTORY) - -AC_ARG_WITH(addon, [ --with-addon Extra builtins, from addon.c ],[ - case "x$withval" in - xyes) - ADDON=addon.o - ;; - xno) - ADDON='' - ;; - *) - ADDON=$withval - ;; - esac - ]) -AC_SUBST(ADDON) - -AC_ARG_WITH(editline, [ --with-editline Simmule Turner's line editing], - AC_CHECK_LIB(edit, readline, - AC_DEFINE(READLINE) LIBS="$LIBS -ledit", - AC_MSG_WARN(editline library not found))) - -AC_ARG_WITH(readline, [ --with-readline Bloated GNU line editing], - AC_CHECK_LIB(readline, readline, - AC_DEFINE(READLINE) LIBS="$LIBS -lreadline -ltermcap", - AC_MSG_WARN(readline library not found))) - -AC_OUTPUT(Makefile) diff --git a/cpp b/cpp @@ -1,38 +0,0 @@ -#!/bin/sh - -# @(#) cpp.sh 1.3 92/01/15 21:53:22 - -# Unprototypeing preprocessor for pre-ANSI C compilers. On some systems, -# this script can be as simple as: -# -# /lib/cpp "$@" | unproto -# -# However, some cc(1) drivers specify output file names on the -# preprocessor command line, so this shell script must be prepared to -# intercept them. Depending on the driver program, the cpp options may -# even go before or after the file name argument(s). The script below -# tries to tackle all these cases. -# -# You may want to add -Ipath_to_stdarg.h_file, -Dvoid=, -Dvolatile=, -# and even -D__STDC__. - -## (This is what I used while testing with the SunOS C compiler. -## Also, I added "-Qpath ." to CFLAGS so that cpp would be -## run out of the current directory. --- Byron) -cpp_args="-I/u/byron/lib/sun4 -Dconst= -Dvolatile=" - -while : -do - case $1 in - "") break;; - -*) cpp_args="$cpp_args $1";; - *) cpp_args="$cpp_args $1" - case $2 in - ""|-*) ;; - *) exec 1> $2 || exit 1; shift;; - esac;; - esac - shift -done - -/lib/cpp $cpp_args | unproto diff --git a/except.c b/except.c @@ -1,140 +0,0 @@ -#include <setjmp.h> -#include <signal.h> -#include "rc.h" -#include "jbwrap.h" - -/* - A return goes back stack frames to the last return. A break does - not. A signal goes to the last interactive level. (see below) -*/ - -bool nl_on_intr = TRUE; - -static Estack *estack; - -/* add an exception to the input stack. */ - -extern void except(ecodes e, Edata data, Estack *ex) { - ex->prev = estack; - estack = ex; - estack->e = e; - estack->data = data; - if (e == eError || e == eBreak || e == eReturn) - estack->interactive = interactive; -} - -/* remove an exception, restore last interactive value */ - -extern void unexcept() { - switch (estack->e) { - default: - break; - case eError: - interactive = estack->interactive; - break; - case eArena: - restoreblock(estack->data.b); - break; - case eFifo: - unlink(estack->data.name); - break; - case eFd: - close(estack->data.fd); - break; - } - estack = estack->prev; -} - -/* - Raise an exception. The rules are pretty complicated: you can return - from a loop inside a function, but you can't break from a function - inside of a loop. On errors, rc_raise() goes back to the LAST - INTERACTIVE stack frame. If no such frame exists, then rc_raise() - exits the shell. This is what happens, say, when there is a syntax - error in a noninteractive shell script. While traversing the - exception stack backwards, rc_raise() also removes input sources - (closing file-descriptors, etc.) and pops instances of variables - that have been pushed onto the variable stack (e.g., for a function - call (for $*) or a local assignment). -*/ - -extern void rc_raise(ecodes e) { - if (e == eError && rc_pid != getpid()) - exit(1); /* child processes exit on an error/signal */ - for (; estack != NULL; estack = estack->prev) - if (estack->e != e) { - if (e == eBreak && estack->e != eArena) - rc_error("break outside of loop"); - else if (e == eReturn && estack->e == eError) /* can return from loops inside functions */ - rc_error("return outside of function"); - switch (estack->e) { - default: - break; - case eVarstack: - varrm(estack->data.name, TRUE); - break; - case eArena: - restoreblock(estack->data.b); - break; - case eFifo: - unlink(estack->data.name); - break; - case eFd: - close(estack->data.fd); - break; - } - } else { - if (e == eError && !estack->interactive) { - popinput(); - } else { - Jbwrap *j = estack->data.jb; - - interactive = estack->interactive; - estack = estack->prev; - longjmp(j->j, 1); - } - } - rc_exit(1); /* top of exception stack */ -} - -extern bool outstanding_cmdarg() { - return estack->e == eFifo || estack->e == eFd; -} - -extern void pop_cmdarg(bool remove) { - for (; estack != NULL; estack = estack->prev) - switch (estack->e) { - case eFifo: - if (remove) - unlink(estack->data.name); - break; - case eFd: - if (remove) - close(estack->data.fd); - break; - default: - return; - } -} - -/* exception handlers */ - -extern void rc_error(char *s) { - pr_error(s); - set(FALSE); - redirq = NULL; - cond = FALSE; /* no longer inside conditional */ - rc_raise(eError); -} - -extern void sigint(int s) { - if (s != SIGINT) - panic("s != SIGINT in sigint catcher"); - /* this is the newline you see when you hit ^C while typing a command */ - if (interactive && nl_on_intr) - fprint(2, "\n"); - nl_on_intr = TRUE; - redirq = NULL; - cond = FALSE; - rc_raise(eError); -} diff --git a/exec.c b/exec.c @@ -1,132 +0,0 @@ -/* exec.c */ -#include <signal.h> -#include <errno.h> -#include <setjmp.h> -#include "rc.h" -#include "jbwrap.h" - -/* - Takes an argument list and does the appropriate thing (calls a - builtin, calls a function, etc.) -*/ - -extern void exec(List *s, bool parent) { - char **av, **ev = NULL; - int stat; - pid_t pid; - builtin_t *b; - char *path = NULL; - bool didfork, returning, saw_exec, saw_builtin; - av = list2array(s, dashex); - saw_builtin = saw_exec = FALSE; - do { - if (*av == NULL || isabsolute(*av)) - b = NULL; - else if (!saw_builtin && fnlookup(*av) != NULL) - b = funcall; - else - b = isbuiltin(*av); - - /* - a builtin applies only to the immmediately following - command, e.g., builtin exec echo hi - */ - saw_builtin = FALSE; - - if (b == b_exec) { - av++; - saw_exec = TRUE; - parent = FALSE; - } else if (b == b_builtin) { - av++; - saw_builtin = TRUE; - } - } while (b == b_exec || b == b_builtin); - if (*av == NULL && saw_exec) { /* do redirs and return on a null exec */ - doredirs(); - return; - } - /* force an exit on exec with any rc_error, but not for null commands as above */ - if (saw_exec) - rc_pid = -1; - if (b == NULL) { - path = which(*av, TRUE); - if (path == NULL && *av != NULL) { /* perform null commands for redirections */ - set(FALSE); - redirq = NULL; - if (parent) - return; - rc_exit(1); - } - ev = makeenv(); /* environment only needs to be built for execve() */ - } - /* - If parent & the redirq is nonnull, builtin or not it has to fork. - If the fifoq is nonnull, then it must be emptied at the end so we - must fork no matter what. - */ - if ((parent && (b == NULL || redirq != NULL)) || outstanding_cmdarg()) { - pid = rc_fork(); - didfork = TRUE; - } else { - pid = 0; - didfork = FALSE; - } - returning = (!didfork && parent); - switch (pid) { - case -1: - uerror("fork"); - rc_error(NULL); - /* NOTREACHED */ - case 0: - if (!returning) - setsigdefaults(FALSE); - pop_cmdarg(FALSE); - doredirs(); - - /* null commands performed for redirections */ - if (*av == NULL || b != NULL) { - if (b != NULL) - (*b)(av); - if (returning) - return; - rc_exit(getstatus()); - } -#if HASH_BANG - execve(path, (char * const *) av, (char * const *) ev); -#else - my_execve(path, (char * const *) av, (char * const *) ev); /* bogus, huh? */ -#endif - -#ifdef DEFAULTINTERP - if (errno == ENOEXEC) { - *av = path; - *--av = DEFAULTINTERP; - execve(*av, (char * const *) av, (char * const *) ev); - } -#endif - uerror(*av); - rc_exit(1); - /* NOTREACHED */ - default: - redirq = NULL; - rc_wait4(pid, &stat, TRUE); - setstatus(-1, stat); - /* - There is a very good reason for having this weird - nl_on_intr variable: when rc and its child both - process a SIGINT, (i.e., the child has a SIGINT - catcher installed) then you don't want rc to print - a newline when the child finally exits. Here's an - example: ed, <type ^C>, <type "q">. rc does not - and should not print a newline before the next - prompt, even though there's a SIGINT in its signal - vector. - */ - if ((stat & 0xff) == 0) - nl_on_intr = FALSE; - sigchk(); - nl_on_intr = TRUE; - pop_cmdarg(TRUE); - } -} diff --git a/execve.c b/execve.c @@ -1,61 +0,0 @@ -/* execve.c: an execve() for geriatric unices without #! */ - -/* - NOTE: this file depends on a hack in footobar.c which places two free spots before - av[][] so that execve does not have to call malloc. -*/ - -#include <errno.h> -#include "rc.h" - -#define giveupif(x) { if (x) goto fail; } - -extern int my_execve(const char *path, const char **av, const char **ev) { - int fd, len, fst, snd, end; - bool noarg; - char pb[256]; /* arbitrary but generous limit */ - execve(path, av, ev); - if (errno != ENOEXEC) - return -1; - fd = rc_open(path, rFrom); - giveupif(fd < 0); - len = read(fd, pb, sizeof pb); - close(fd); - /* reject scripts which don't begin with #! */ - giveupif(len <= 0 || pb[0] != '#' || pb[1] != '!'); - for (fst = 2; fst < len && (pb[fst] == ' ' || pb[fst] == '\t'); fst++) - ; /* skip leading whitespace */ - giveupif(fst == len); - for (snd = fst; snd < len && pb[snd] != ' ' && pb[snd] != '\t' && pb[snd] != '\n'; snd++) - ; /* skip first arg */ - giveupif(snd == len); - noarg = (pb[snd] == '\n'); - pb[snd++] = '\0'; /* null terminate the first arg */ - if (!noarg) { - while (snd < len && (pb[snd] == ' ' || pb[snd] == '\t')) - snd++; /* skip whitespace to second arg */ - giveupif(snd == len); - noarg = (pb[snd] == '\n'); /* could have trailing whitespace after only one arg */ - if (!noarg) { - for (end = snd; end < len && pb[end] != ' ' && pb[end] != '\t' && pb[end] != '\n'; end++) - ; /* skip to the end of the second arg */ - giveupif(end == len); - if (pb[end] == '\n') { - pb[end] = '\0'; /* null terminate the first arg */ - } else { /* else check for a spurious third arg */ - pb[end++] = '\0'; - while (end < len && (pb[end] == ' ' || pb[end] == '\t')) - end++; - giveupif(end == len || pb[end] != '\n'); - } - } - } - *av = path; - if (!noarg) - *--av = pb + snd; - *--av = pb + fst; - execve(*av, av, ev); - return -1; -fail: errno = ENOEXEC; - return -1; -} diff --git a/fn.c b/fn.c @@ -1,257 +0,0 @@ -/* - fn.c: functions for adding and deleting functions from the symbol table. - Support for signal handlers is also found here. -*/ - -#include <signal.h> -#include <errno.h> -#include "rc.h" -#include "sigmsgs.h" - -static void fn_handler(int), dud_handler(int); - -static bool runexit = FALSE; -static Node *handlers[NUMOFSIGNALS], null; -static void (*def_sigint)(int) = SIG_DFL; -static void (*def_sigquit)(int) = SIG_DFL; -static void (*def_sigterm)(int) = SIG_DFL; - -/* - Set signals to default values for rc. This means that interactive - shells ignore SIGTERM, etc. -*/ - -extern void inithandler() { - int i; - null.type = nBody; - null.u[0].p = null.u[1].p = NULL; - for (i = 1; i < NUMOFSIGNALS; i++) -#ifndef HAVE_RESTARTABLE_SYSCALLS - if (i != SIGCLD) -#endif - if (sighandlers[i] == SIG_IGN) - fnassign(signals[i].name, NULL); /* ignore incoming ignored signals */ - if (interactive || sighandlers[SIGINT] != SIG_IGN) { - def_sigint = sigint; - fnrm("sigint"); /* installs SIGINT catcher if not inherited ignored */ - } - if (!dashdee) { - if (interactive || sighandlers[SIGQUIT] != SIG_IGN) { - def_sigquit = dud_handler; - fnrm("sigquit"); /* "ignores" SIGQUIT unless inherited ignored */ - } - if (interactive) { - def_sigterm = dud_handler; - fnrm("sigterm"); /* ditto for SIGTERM */ - } - } -} - -/* only run this in a child process! resets signals to their default values */ - -extern void setsigdefaults(bool sysvbackground) { - int i; - /* - General housekeeping: setsigdefaults happens after fork(), - so it's a convenient place to clean up open file descriptors. - (history file, scripts, etc.) - */ - closefds(); - /* - Restore signals to SIG_DFL, paying close attention to - a few quirks: SIGINT, SIGQUIT and are treated specially - depending on whether we are doing v7-style backgrounding - or not; the default action for SIGINT, SIGQUIT and SIGTERM - must be set to the appropriate action; finally, care must - be taken not to set to SIG_DFL any signals which are being - ignored. - */ - for (i = 1; i < NUMOFSIGNALS; i++) - if (sighandlers[i] != SIG_IGN) { - handlers[i] = NULL; - switch (i) { - case SIGINT: - if (sysvbackground) { - def_sigint = SIG_IGN; - fnassign("sigint", NULL); /* ignore */ - } else { - def_sigint = SIG_DFL; - goto sigcommon; - } - break; - case SIGQUIT: - if (sysvbackground) { - def_sigquit = SIG_IGN; - fnassign("sigquit", NULL); /* ignore */ - } else { - def_sigquit = SIG_DFL; - goto sigcommon; - } - break; - case SIGTERM: - def_sigterm = SIG_DFL; - /* FALLTHROUGH */ - sigcommon: - default: - if (sighandlers[i] != SIG_DFL) { - rc_signal(i, SIG_DFL); - delete_fn(signals[i].name); - } - } - } - delete_fn("sigexit"); - runexit = FALSE; /* No sigexit on subshells */ -} - -/* rc's exit. if runexit is set, run the sigexit function. */ - -extern void rc_exit(int stat) { - if (runexit) { - char *sig[2]; - sig[0] = "sigexit"; - sig[1] = NULL; - runexit = FALSE; - funcall(sig); - stat = getstatus(); - } - exit(stat); -} - -/* The signal handler for all functions. calls walk() */ - -static void fn_handler(int s) { - char *sig[2]; - int olderrno; - if (s < 1 || s >= NUMOFSIGNALS) - panic("unknown signal"); - olderrno = errno; - sig[0] = signals[s].name; - sig[1] = NULL; - funcall(sig); - errno = olderrno; -} - -/* A dud signal handler for SIGQUIT and SIGTERM */ - -static void dud_handler(int s) { -} - -/* - Assign a function in Node form. Check to see if the function is also - a signal, and set the signal vectors appropriately. -*/ - -extern void fnassign(char *name, Node *def) { - Node *newdef = treecpy(def == NULL ? &null : def, ealloc); /* important to do the treecopy first */ - Function *new = get_fn_place(name); - int i; - new->def = newdef; - new->extdef = NULL; - if (strncmp(name, "sig", conststrlen("sig")) == 0) { /* slight optimization */ -#ifndef HAVE_RESTARTABLE_SYSCALLS /* System V machines treat SIGCLD very specially */ - if (streq(name, "sigcld")) - rc_error("can't trap SIGCLD"); -#endif - if (streq(name, "sigexit")) - runexit = TRUE; - for (i = 1; i < NUMOFSIGNALS; i++) /* zero is a bogus signal */ - if (streq(signals[i].name, name)) { - handlers[i] = newdef; - if (def == NULL) - rc_signal(i, SIG_IGN); - else - rc_signal(i, fn_handler); - break; - } - } -} - -/* Assign a function from the environment. Store just the external representation */ - -extern void fnassign_string(char *extdef) { - char *name = get_name(extdef+3); /* +3 to skip over "fn_" */ - Function *new; - if (name == NULL) - return; - new = get_fn_place(name); - new->def = NULL; - new->extdef = ecpy(extdef); -} - -/* Return a function in Node form, evaluating an entry from the environment if necessary */ - -extern Node *fnlookup(char *name) { - Function *look = lookup_fn(name); - Node *ret; - if (look == NULL) - return NULL; /* not found */ - if (look->def != NULL) - return look->def; - if (look->extdef == NULL) /* function was set to null, e.g., fn foo {} */ - return &null; - ret = parse_fn(name, look->extdef); - if (ret == NULL) { - efree(look->extdef); - look->extdef = NULL; - return &null; - } else { - return look->def = treecpy(ret, ealloc); /* Need to take it out of nalloc space */ - } -} - -/* Return a function in string form (used by makeenv) */ - -extern char *fnlookup_string(char *name) { - Function *look = lookup_fn(name); - - if (look == NULL) - return NULL; - if (look->extdef != NULL) - return look->extdef; - return look->extdef = mprint("fn_%F={%T}", name, look->def); -} - -/* - Remove a function from the symbol table. If it also defines a signal - handler, restore the signal handler to its default value. -*/ - -extern void fnrm(char *name) { - int i; - for (i = 1; i < NUMOFSIGNALS; i++) - if (streq(signals[i].name, name)) { - handlers[i] = NULL; - switch (i) { - case SIGINT: - rc_signal(i, def_sigint); - break; - case SIGQUIT: - rc_signal(i, def_sigquit); - break; - case SIGTERM: - rc_signal(i, def_sigterm); - break; - default: - rc_signal(i, SIG_DFL); - } - } - if (streq(name, "sigexit")) - runexit = FALSE; - delete_fn(name); -} - -extern void whatare_all_signals() { - int i; - for (i = 1; i < NUMOFSIGNALS; i++) - if (*signals[i].name != '\0') - if (sighandlers[i] == SIG_IGN) - fprint(1, "fn %s {}\n", signals[i].name); - else if (sighandlers[i] == fn_handler) - fprint(1, "fn %S {%T}\n", signals[i].name, handlers[i]); - else - fprint(1, "fn %s\n", signals[i].name); -} - -extern void prettyprint_fn(int fd, char *name, Node *n) { - fprint(fd, "fn %S {%T}\n", name, n); -} diff --git a/footobar.c b/footobar.c @@ -1,337 +0,0 @@ -/* - footobar.c: a collection of functions to convert internal representations of - variables and functions to external representations, and vice versa -*/ - -#include "rc.h" - -/* protect an exported name from brain-dead shells */ - -#if PROTECT_ENV -static bool Fconv(Format *f, int ignore) { - unsigned const char *s = va_arg(f->args, unsigned const char *); - int c; - - while ((c = *s++) != '\0') - if (dnw[c] || c == '*' || (c == '_' && *s == '_')) - fmtprint(f, "__%02x", c); - else - fmtputc(f, c); - return FALSE; -} -#endif - -/* convert a redirection to a printable form */ - -static bool Dconv(Format *f, int ignore) { - const char *name = "?"; - int n = va_arg(f->args, int); - switch (n) { - case rCreate: name = ">"; break; - case rAppend: name = ">>"; break; - case rFrom: name = "<"; break; - case rHeredoc: name = "<<"; break; - case rHerestring: name = "<<<"; break; - } - fmtcat(f, name); - return FALSE; -} - -/* defaultfd -- return the default fd for a given redirection operation */ - -extern int defaultfd(int op) { - return (op == rCreate || op == rAppend) ? 1 : 0; -} - -/* convert a function in Node * form into something rc can parse (and humans can read?) */ - -static bool Tconv(Format *f, int ignore) { - Node *n = va_arg(f->args, Node *); - if (n == NULL) { - fmtprint(f, "()"); - return FALSE; - } - switch (n->type) { - case nWord: fmtprint(f, "%S", n->u[0].s); break; - case nQword: fmtprint(f, "%#S", n->u[0].s); break; - case nBang: fmtprint(f, "!%T", n->u[0].p); break; - case nCase: fmtprint(f, "case %T", n->u[0].p); break; - case nNowait: fmtprint(f, "%T&", n->u[0].p); break; - case nRmfn: fmtprint(f, "fn %T", n->u[0].p); break; - case nSubshell: fmtprint(f, "@ %T", n->u[0].p); break; - case nAndalso: fmtprint(f, "%T&&%T", n->u[0].p, n->u[1].p); break; - case nAssign: fmtprint(f, "%T=%T", n->u[0].p, n->u[1].p); break; - case nConcat: fmtprint(f, "%T^%T", n->u[0].p, n->u[1].p); break; - case nElse: fmtprint(f, "{%T}else %T", n->u[0].p, n->u[1].p); break; - case nNewfn: fmtprint(f, "fn %T {%T}", n->u[0].p, n->u[1].p); break; - case nIf: fmtprint(f, "if(%T)%T", n->u[0].p, n->u[1].p); break; - case nOrelse: fmtprint(f, "%T||%T", n->u[0].p, n->u[1].p); break; - case nArgs: fmtprint(f, "%T %T", n->u[0].p, n->u[1].p); break; - case nSwitch: fmtprint(f, "switch(%T){%T}", n->u[0].p, n->u[1].p); break; - case nMatch: fmtprint(f, "~ %T %T", n->u[0].p, n->u[1].p); break; - case nWhile: fmtprint(f, "while(%T)%T", n->u[0].p, n->u[1].p); break; - case nLappend: fmtprint(f, "(%T %T)", n->u[0].p, n->u[1].p); break; - case nForin: fmtprint(f, "for(%T in %T)%T", n->u[0].p, n->u[1].p, n->u[2].p); break; - case nVarsub: fmtprint(f, "$%T(%T)", n->u[0].p, n->u[1].p); break; - case nCount: case nFlat: case nVar: { - char *lp = "", *rp = ""; - Node *n0 = n->u[0].p; - - if (n0->type != nWord && n0->type != nQword) - lp = "(", rp = ")"; - - switch (n->type) { - default: panic("this can't happen"); break; - case nCount: fmtprint(f, "$#%s%T%s", lp, n0, rp); break; - case nFlat: fmtprint(f, "$^%s%T%s", lp, n0, rp); break; - case nVar: fmtprint(f, "$%s%T%s", lp, n0, rp); break; - } - break; - } - case nDup: - if (n->u[2].i != -1) - fmtprint(f, "%D[%d=%d]", n->u[0].i, n->u[1].i, n->u[2].i); - else - fmtprint(f, "%D[%d=]", n->u[0].i, n->u[1].i); - break; - case nBackq: { - Node *n0 = n->u[0].p, *n00; - if (n0 != NULL && n0->type == nVar - && (n00 = n0->u[0].p) != NULL && n00->type == nWord && streq(n00->u[0].s, "ifs")) - fmtprint(f, "`"); - else - fmtprint(f, "``%T", n0); - fmtprint(f, "{%T}", n->u[1].p); - break; - } - case nCbody: - case nBody: { - Node *n0 = n->u[0].p; - if (n0 != NULL) - fmtprint(f, "%T", n->u[0].p); - if (n->u[1].p != NULL) { - if (n0 != NULL && n0->type != nNowait) - fmtprint(f, ";"); - fmtprint(f, "%T", n->u[1].p); - } - break; - } - case nBrace: - fmtprint(f, "{%T}", n->u[0].p); - if (n->u[1].p != NULL) - fmtprint(f, "%T", n->u[1].p); - break; - case nEpilog: - case nPre: - fmtprint(f, "%T", n->u[0].p); - if (n->u[1].p != NULL) - fmtprint(f, " %T", n->u[1].p); - break; - case nPipe: { - int ofd = n->u[0].i, ifd = n->u[1].i; - fmtprint(f, "%T|", n->u[2].p); - if (ifd != 0) - fmtprint(f, "[%d=%d]", ofd, ifd); - else if (ofd != 1) - fmtprint(f, "[%d]", ofd); - fmtprint(f, "%T", n->u[3].p); - break; - } - case nRedir: { - int op = n->u[0].i; - fmtprint(f, "%D", op); - if (n->u[1].i != defaultfd(op)) - fmtprint(f, "[%d]", n->u[1].i); - fmtprint(f, "%T", n->u[2].p); - break; - } - case nNmpipe: { - int op = n->u[0].i; - fmtprint(f, "%D", op); - if (n->u[1].i != defaultfd(op)) - fmtprint(f, "[%d]", n->u[1].i); - fmtprint(f, "{%T}", n->u[2].p); - break; - } - } - return FALSE; -} - -/* convert a List to an array, for execve() */ - -extern char **list2array(List *s, bool print) { - char **argv, **av; - - if (print) - fprint(2, "%L\n", s, " "); - /* - Allocate 3 extra spots (2 for the fake execve & 1 for defaulting to - sh) and hide these from exec(). - */ - argv = av = (char **) nalloc((listnel(s) + 4) * sizeof *av) + 3; - while (s != NULL) { - *av++ = s->w; - s = s->n; - } - *av = NULL; - return argv; -} - -/* figure out the name of a variable given an environment string. */ - -extern char *get_name(char *s) { - char *eq = strchr(s, '='); - char *r, *result; - int c; - - if (eq == NULL) - return NULL; - r = result = nalloc(eq - s + 1); - while (1) - switch (c = *s++) { - case '=': - *r++ = '\0'; - return result; -#if PROTECT_ENV - case '_': - if (*s == '_') { - static const char hexchar[] = "0123456789abcdef"; - char *h1 = strchr(hexchar, s[1]); - char *h2 = strchr(hexchar, s[2]); - if (h1 != NULL && h2 != NULL) { - *r++ = ((h1 - hexchar) << 4) | (h2 - hexchar); - s += 3; - break; - } - } - /* FALLTHROUGH */ -#endif - default: - *r++ = c; - break; - } -} - -/* - Hacky routine to split a ^A-separated environment variable. Scans - backwards. Be VERY CAREFUL with the loop boundary conditions. e.g., - notice what happens when there is no ^A in the extdef. (It does - the right thing, of course :-) -*/ - -#define skipleft(p) do --p; while (*p != '\0' && *p != '\001'); - -extern List *parse_var(char *name, char *extdef) { - char *endp, *realend, *sepp; - List *tailp, *new; - - extdef = strchr(extdef, '='); - *extdef++ = '\0'; /* null "initiate" the string for rtol scanning */ - - sepp = realend = strchr(extdef, '\0'); - tailp = NULL; - - while (1) { - endp = sepp; /* set endp to end of current mebmer */ - skipleft(sepp); /* advance sepp to the previous \1, */ - *endp = '\0'; /* and null terminate the member. */ - - new = enew(List); - new->w = ecpy(sepp+1); - new->m = NULL; - new->n = tailp; - tailp = new; - - if (sepp < extdef) /* break when sepp hits the null "initiator" */ - break; - if (endp != realend) /* else restore the \1 in between members */ - *endp = '\001'; - } - if (endp != realend) - *endp = '\001'; - *--extdef = '='; /* restore extdef '=' */ - return tailp; -} - -/* get an environment entry for a function and have rc parse it. */ - -#define PREFIX "fn x" -#define PRELEN conststrlen(PREFIX) -extern Node *parse_fn(char *name, char *extdef) { - Node *def; - char *s, old[PRELEN]; - if ((s = strchr(extdef, '=')) == NULL) - return NULL; - memcpy(old, s -= (PRELEN-1), PRELEN); - memcpy(s, PREFIX, PRELEN); - def = parseline(s); - memcpy(s, old, PRELEN); - return (def == NULL || def->type != nNewfn) ? NULL : def->u[1].p; -} - -static bool Aconv(Format *f, int c) { - char **a = va_arg(f->args, char **); - if (*a != NULL) { - fmtcat(f, *a); - while (*++a != NULL) - fmtprint(f, " %s", *a); - } - return FALSE; -} - -static bool Lconv(Format *f, int c) { - List *l = va_arg(f->args, List *); - char *sep = va_arg(f->args, char *); - char *fmt = (f->flags & FMT_leftside) ? "%s%s" : "%-S%s"; - if (l == NULL && (f->flags & FMT_leftside) == 0) - fmtprint(f, "()"); - else { - List *s; - for (s = l; s != NULL; s = s->n) - fmtprint(f, fmt, s->w, s->n == NULL ? "" : sep); - } - return FALSE; -} - -#define ISMETA(c) (c == '*' || c == '?' || c == '[') - -static bool Sconv(Format *f, int ignore) { - int c; - unsigned char *s = va_arg(f->args, unsigned char *), *t = s; - bool quoted = (f->flags & FMT_altform) != 0; /* '#' */ - bool metaquote = (f->flags & FMT_leftside) != 0; /* '-' */ - if (*s == '\0') { - fmtprint(f, "''"); - return FALSE; - } - if (!quoted) { - while ((c = *t++) != '\0') - if (nw[c] == 1 || (metaquote && ISMETA(c))) - goto quoteit; - fmtprint(f, "%s", s); - return FALSE; - } -quoteit: - fmtputc(f, '\''); - while ((c = *s++) != '\0') { - fmtputc(f, c); - if (c == '\'') - fmtputc(f, '\''); - - } - fmtputc(f, '\''); - return FALSE; -} - -void initprint(void) { - fmtinstall('A', Aconv); - fmtinstall('L', Lconv); - fmtinstall('S', Sconv); - fmtinstall('T', Tconv); - fmtinstall('D', Dconv); -#if PROTECT_ENV - fmtinstall('F', Fconv); -#else - fmtinstall('F', fmtinstall('s', NULL)); -#endif -} diff --git a/getopt.c b/getopt.c @@ -1,50 +0,0 @@ -#include "rc.h" - -int rc_opterr = 1; -int rc_optind = 1; -int rc_optopt; -char *rc_optarg; - -/* getopt routine courtesy of David Sanderson */ - -extern int rc_getopt(int argc, char **argv, char *opts) { - static int sp = 1; - int c; - char *cp; - if (rc_optind == 0) /* reset rc_getopt() */ - rc_optind = sp = 1; - if (sp == 1) - if (rc_optind >= argc || argv[rc_optind][0] != '-' || argv[rc_optind][1] == '\0') { - return -1; - } else if (strcmp(argv[rc_optind], "--") == 0) { - rc_optind++; - return -1; - } - rc_optopt = c = argv[rc_optind][sp]; - if (c == ':' || (cp=strchr(opts, c)) == 0) { - fprint(2, "%s: bad option: -%c\n", argv[0], c); - if (argv[rc_optind][++sp] == '\0') { - rc_optind++; - sp = 1; - } - return '?'; - } - if (*++cp == ':') { - if (argv[rc_optind][sp+1] != '\0') { - rc_optarg = &argv[rc_optind++][sp+1]; - } else if (++rc_optind >= argc) { - fprint(2, "%s: option requires an argument -- %c\n", argv[0], c); - sp = 1; - return '?'; - } else - rc_optarg = argv[rc_optind++]; - sp = 1; - } else { - if (argv[rc_optind][++sp] == '\0') { - sp = 1; - rc_optind++; - } - rc_optarg = NULL; - } - return c; -} diff --git a/glob.c b/glob.c @@ -1,278 +0,0 @@ -/* glob.c: rc's (ugly) globber. This code is not elegant, but it works */ - -#include <sys/types.h> -#include <sys/stat.h> -#include "rc.h" - -/* Lifted from autoconf documentation.*/ -#if HAVE_DIRENT_H -# include <dirent.h> -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include <sys/ndir.h> -# endif -# if HAVE_SYS_DIR_H -# include <sys/dir.h> -# endif -# if HAVE_NDIR_H -# include <ndir.h> -# endif -#endif - -static List *dmatch(char *, char *, char *); -static List *doglob(char *, char *); -static List *lglob(List *, char *, char *, size_t); -static List *sort(List *); - -/* - Matches a list of words s against a list of patterns p. Returns true iff - a pattern in p matches a word in s. () matches (), but otherwise null - patterns match nothing. -*/ - -extern bool lmatch(List *s, List *p) { - List *q; - int i; - bool okay; - if (s == NULL) { - if (p == NULL) /* null matches null */ - return TRUE; - for (; p != NULL; p = p->n) { /* one or more stars match null */ - if (*p->w != '\0') { /* the null string is a special case; it does *not* match () */ - okay = TRUE; - for (i = 0; p->w[i] != '\0'; i++) - if (p->w[i] != '*' || p->m[i] != 1) { - okay = FALSE; - break; - } - if (okay) - return TRUE; - } - } - return FALSE; - } - for (; s != NULL; s = s->n) - for (q = p; q != NULL; q = q->n) - if (match(q->w, q->m, s->w)) - return TRUE; - return FALSE; -} - -/* - Globs a list; checks to see if each element in the list has a metacharacter. If it - does, it is globbed, and the output is sorted. -*/ - -extern List *glob(List *s) { - List *top, *r; - bool meta; - for (r = s, meta = FALSE; r != NULL; r = r->n) - if (r->m != NULL) - meta = TRUE; - if (!meta) - return s; /* don't copy lists with no metacharacters in them */ - for (top = r = NULL; s != NULL; s = s->n) { - if (s->m == NULL) { /* no metacharacters; just tack on to the return list */ - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = s->w; - } else { - if (top == NULL) - top = r = sort(doglob(s->w, s->m)); - else - r->n = sort(doglob(s->w, s->m)); - while (r->n != NULL) - r = r->n; - } - } - r->n = NULL; - return top; -} - -/* Matches a pattern p against the contents of directory d */ - -static List *dmatch(char *d, char *p, char *m) { - bool matched = FALSE; - List *top, *r; - static DIR *dirp; - static struct dirent *dp; - static struct stat s; - int i; - - /* - return a match if there are no metacharacters; allows globbing through - directories with no read permission. make sure the file exists, though. - */ - matched = TRUE; - if (m != NULL) - for (i = 0; p[i] != '\0'; i++) - if (m[i]) { - matched = FALSE; - break; - } - - if (matched) { - char *path = nprint("%s/%s", d, p); - if (stat(path, &s) < 0) - return NULL; - r = nnew(List); - r->w = ncpy(p); - r->m = NULL; - r->n = NULL; - return r; - } - - top = r = NULL; - if ((dirp = opendir(d)) == NULL) - return NULL; - /* opendir succeeds on regular files on some systems, so the stat() call is necessary (sigh) */ - if (stat(d, &s) < 0 || (s.st_mode & S_IFMT) != S_IFDIR) { - closedir(dirp); - return NULL; - } - while ((dp = readdir(dirp)) != NULL) - if ((*dp->d_name != '.' || *p == '.') && match(p, m, dp->d_name)) { /* match ^. explicitly */ - matched = TRUE; - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = ncpy(dp->d_name); - r->m = NULL; - } - closedir(dirp); - if (!matched) - return NULL; - r->n = NULL; - return top; -} - -/* - lglob() globs a pattern agains a list of directory roots. e.g., (/tmp /usr /bin) "*" - will return a list with all the files in /tmp, /usr, and /bin. NULL on no match. - slashcount indicates the number of slashes to stick between the directory and the - matched name. e.g., for matching ////tmp/////foo* -*/ - -static List *lglob(List *s, char *p, char *m, size_t slashcount) { - List *q, *r, *top, foo; - static struct { - List l; - size_t size; - } slash; - if (slashcount+1 > slash.size) { - slash.size = 2*(slashcount+1); - slash.l.w = erealloc(slash.l.w, slash.size); - } - slash.l.w[slashcount] = '\0'; - while (slashcount > 0) - slash.l.w[--slashcount] = '/'; - for (top = r = NULL; s != NULL; s = s->n) { - q = dmatch(s->w, p, m); - if (q != NULL) { - foo.w = s->w; - foo.m = NULL; - foo.n = NULL; - if (!(s->w[0] == '/' && s->w[1] == '\0')) /* need to separate */ - q = concat(&slash.l, q); /* dir/name with slash */ - q = concat(&foo, q); - if (r == NULL) - top = r = q; - else - r->n = q; - while (r->n != NULL) - r = r->n; - } - } - return top; -} - -/* - Doglob globs a pathname in pattern form against a unix path. Returns the original - pattern (cleaned of metacharacters) on failure, or the globbed string(s). -*/ - -static List *doglob(char *w, char *m) { - static char *dir = NULL, *pattern = NULL, *metadir = NULL, *metapattern = NULL; - static size_t dsize = 0; - char *d, *p, *md, *mp; - size_t psize; - char *s = w; - List firstdir; - List *matched; - if ((psize = strlen(w) + 1) > dsize || dir == NULL) { - efree(dir); efree(pattern); efree(metadir); efree(metapattern); - dir = ealloc(psize); - pattern = ealloc(psize); - metadir = ealloc(psize); - metapattern = ealloc(psize); - dsize = psize; - } - d = dir; - p = pattern; - md = metadir; - mp = metapattern; - if (*s == '/') - while (*s == '/') - *d++ = *s++, *md++ = *m++; - else - while (*s != '/' && *s != '\0') - *d++ = *s++, *md++ = *m++; /* get first directory component */ - *d = '\0'; - /* - Special case: no slashes in the pattern, i.e., open the current directory. - Remember that w cannot consist of slashes alone (the other way *s could be - zero) since doglob gets called iff there's a metacharacter to be matched - */ - if (*s == '\0') { - matched = dmatch(".", dir, metadir); - goto end; - } - if (*w == '/') { - firstdir.w = dir; - firstdir.m = metadir; - firstdir.n = NULL; - matched = &firstdir; - } else { - /* - we must glob against current directory, - since the first character is not a slash. - */ - matched = dmatch(".", dir, metadir); - } - do { - size_t slashcount; - sigchk(); - for (slashcount = 0; *s == '/'; s++, m++) - slashcount++; /* skip slashes */ - while (*s != '/' && *s != '\0') - *p++ = *s++, *mp++ = *m++; /* get pattern */ - *p = '\0'; - matched = lglob(matched, pattern, metapattern, slashcount); - p = pattern, mp = metapattern; - } while (*s != '\0'); -end: if (matched == NULL) { - matched = nnew(List); - matched->w = w; - matched->m = NULL; - matched->n = NULL; - } - return matched; -} - -static List *sort(List *s) { - size_t nel = listnel(s); - if (nel > 1) { - char **a; - List *t; - qsort(a = list2array(s, FALSE), nel, sizeof(char *), starstrcmp); - for (t = s; t != NULL; t = t->n) - t->w = *a++; - } - return s; -} diff --git a/glom.c b/glom.c @@ -1,433 +0,0 @@ -/* glom.c: builds an argument list out of words, variables, etc. */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include <errno.h> -#include "rc.h" - -static List *backq(Node *, Node *); -static List *bqinput(List *, int); -static List *count(List *); -static List *mkcmdarg(Node *); - -Rq *redirq = NULL; - -extern List *word(char *w, char *m) { - List *s = NULL; - if (w != NULL) { - s = nnew(List); - s->w = w; - s->m = m; - s->n = NULL; - } - return s; -} - -/* - Append list s2 to list s1 by copying s1 and making the new copy - point at s2. -*/ - -extern List *append(List *s1, List *s2) { - List *r, *top; - if (s1 == NULL) - return s2; - if (s2 == NULL) - return s1; - for (r = top = nnew(List); 1; r = r->n = nnew(List)) { - r->w = s1->w; - r->m = s1->m; - if ((s1 = s1->n) == NULL) - break; - } - r->n = s2; - return top; -} - -extern List *concat(List *s1, List *s2) { - int n1, n2; - List *r, *top; - if (s1 == NULL) - return s2; - if (s2 == NULL) - return s1; - if ((n1 = listnel(s1)) != (n2 = listnel(s2)) && n1 != 1 && n2 != 1) - rc_error("bad concatenation"); - for (r = top = nnew(List); 1; r = r->n = nnew(List)) { - size_t x = strlen(s1->w); - size_t y = strlen(s2->w); - size_t z = x + y + 1; - r->w = nalloc(z); - strcpy(r->w, s1->w); - strcat(r->w, s2->w); - if (s1->m == NULL && s2->m == NULL) { - r->m = NULL; - } else { - r->m = nalloc(z); - if (s1->m == NULL) - memzero(r->m, x); - else - memcpy(r->m, s1->m, x); - if (s2->m == NULL) - memzero(&r->m[x], y); - else - memcpy(&r->m[x], s2->m, y); - r->m[z] = 0; - } - if (n1 > 1) - s1 = s1->n; - if (n2 > 1) - s2 = s2->n; - if (s1 == NULL || s2 == NULL || (n1 == 1 && n2 == 1)) - break; - } - r->n = NULL; - return top; -} - -extern List *varsub(List *var, List *subs) { - List *r, *top; - int n = listnel(var); - for (top = r = NULL; subs != NULL; subs = subs->n) { - int i = a2u(subs->w); - if (i < 1) - rc_error("bad subscript"); - if (i <= n) { - List *sub = var; - while (--i) - sub = sub->n; /* loop until sub == var(i) */ - if (top == NULL) - top = r = nnew(List); - else - r = r->n = nnew(List); - r->w = sub->w; - r->m = sub->m; - } - } - if (top != NULL) - r->n = NULL; - return top; -} - -extern List *flatten(List *s) { - List *r; - size_t step; - char *f; - if (s == NULL || s->n == NULL) - return s; - r = nnew(List); - f = r->w = nalloc(listlen(s) + 1); - r->m = NULL; /* flattened lists come from variables, so no meta */ - r->n = NULL; - strcpy(f, s->w); - f += strlen(s->w); - do { - *f++ = ' '; - s = s->n; - step = strlen(s->w); - memcpy(f, s->w, step); - f += step; - } while (s->n != NULL); - *f = '\0'; - return r; -} - -static List *count(List *l) { - List *s = nnew(List); - s->w = nprint("%d", listnel(l)); - s->n = NULL; - s->m = NULL; - return s; -} - -extern void assign(List *s1, List *s2, bool stack) { - List *val = s2; - if (s1 == NULL) - rc_error("null variable name"); - if (s1->n != NULL) - rc_error("multi-word variable name"); - if (*s1->w == '\0') - rc_error("zero-length variable name"); - if (a2u(s1->w) != -1) - rc_error("numeric variable name"); - if (strchr(s1->w, '=') != NULL) - rc_error("'=' in variable name"); - if (*s1->w == '*' && s1->w[1] == '\0') - val = append(varlookup("0"), s2); /* preserve $0 when * is assigned explicitly */ - if (s2 != NULL || stack) { - if (dashex) - prettyprint_var(2, s1->w, val); - varassign(s1->w, val, stack); - alias(s1->w, varlookup(s1->w), stack); - } else { - if (dashex) - prettyprint_var(2, s1->w, NULL); - varrm(s1->w, stack); - } -} - -/* - The following two functions are by the courtesy of Paul Haahr, - who could not stand the incompetence of my own backquote implementation. -*/ - -#define BUFSIZE ((size_t) 1000) - -static List *bqinput(List *ifs, int fd) { - char *end, *bufend, *s; - List *r, *top, *prev; - size_t remain, bufsize; - char isifs[256]; - int n, state; /* a simple FSA is used to read in data */ - - memzero(isifs, sizeof isifs); - for (isifs['\0'] = TRUE; ifs != NULL; ifs = ifs->n) - for (s = ifs->w; *s != '\0'; s++) - isifs[*(unsigned char *)s] = TRUE; - remain = bufsize = BUFSIZE; - top = r = nnew(List); - r->w = end = nalloc(bufsize + 1); - r->m = NULL; - state = 0; - prev = NULL; - - while (1) { - if (remain == 0) { /* is the string bigger than the buffer? */ - size_t m = end - r->w; - char *buf; - while (bufsize < m + BUFSIZE) - bufsize *= 2; - buf = nalloc(bufsize + 1); - memcpy(buf, r->w, m); - r->w = buf; - end = &buf[m]; - remain = bufsize - m; - } - if ((n = rc_read(fd, end, remain)) <= 0) { - if (n == 0) - /* break */ break; - else if (errno == EINTR) - return NULL; /* interrupted, wait for subproc */ - else { - uerror("backquote read"); - rc_error(NULL); - } - } - remain -= n; - for (bufend = &end[n]; end < bufend; end++) - if (state == 0) { - if (!isifs[*(unsigned char *)end]) { - state = 1; - r->w = end; - r->m = NULL; - } - } else { - if (isifs[*(unsigned char *)end]) { - state = 0; - *end = '\0'; - prev = r; - r = r->n = nnew(List); - r->w = end+1; - r->m = NULL; - } - } - } - if (state == 1) { /* terminate last string */ - *end = '\0'; - r->n = NULL; - } else { - if (prev == NULL) /* no input at all? */ - top = NULL; - else - prev->n = NULL; /* else terminate list */ - } - return top; -} - -static List *backq(Node *ifs, Node *n) { - int p[2], sp; - pid_t pid; - List *bq; - if (n == NULL) - return NULL; - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if ((pid = rc_fork()) == 0) { - mvfd(p[1], 1); - close(p[0]); - redirq = NULL; - walk(n, FALSE); - exit(getstatus()); - } - close(p[1]); - bq = bqinput(glom(ifs), p[0]); - close(p[0]); - rc_wait4(pid, &sp, TRUE); - statprint(-1, sp); - varassign("bqstatus", word(strstatus(sp), NULL), FALSE); - sigchk(); - return bq; -} - -extern void qredir(Node *n) { - Rq *next; - if (redirq == NULL) { - next = redirq = nnew(Rq); - } else { - for (next = redirq; next->n != NULL; next = next->n) - ; - next->n = nnew(Rq); - next = next->n; - } - next->r = n; - next->n = NULL; -} - -#if HAVE_DEV_FD || HAVE_PROC_SELF_FD -static List *mkcmdarg(Node *n) { - char *name; - List *ret = nnew(List); - Estack *e = nnew(Estack); - Edata efd; - int p[2]; - if (pipe(p) < 0) { - uerror("pipe"); - return NULL; - } - if (rc_fork() == 0) { - setsigdefaults(FALSE); - if (mvfd(p[n->u[0].i == rFrom], n->u[0].i == rFrom) < 0) /* stupid hack */ - exit(1); - close(p[n->u[0].i != rFrom]); - redirq = NULL; - walk(n->u[2].p, FALSE); - exit(getstatus()); - } - -#if HAVE_DEV_FD - name = nprint("/dev/fd/%d", p[n->u[0].i != rFrom]); -#else - name = nprint("/proc/self/fd/%d", p[n->u[0].i != rFrom]); -#endif - - efd.fd = p[n->u[0].i != rFrom]; - except(eFd, efd, e); - close(p[n->u[0].i == rFrom]); - ret->w = name; - ret->m = NULL; - ret->n = NULL; - return ret; -} - -#elif HAVE_FIFO - -static List *mkcmdarg(Node *n) { - int fd; - char *name; - Edata efifo; - Estack *e = enew(Estack); - List *ret = nnew(List); - static int fifonumber = 0; - name = nprint("/tmp/rc%d.%d", getpid(), fifonumber++); - if (mknod(name, S_IFIFO | 0666, 0) < 0) { - uerror("mknod"); - return NULL; - } - if (rc_fork() == 0) { - setsigdefaults(FALSE); - fd = rc_open(name, (n->u[0].i != rFrom) ? rFrom : rCreate); /* stupid hack */ - if (fd < 0) { - uerror("open"); - exit(1); - } - if (mvfd(fd, (n->u[0].i == rFrom)) < 0) /* same stupid hack */ - exit(1); - redirq = NULL; - walk(n->u[2].p, FALSE); - exit(getstatus()); - } - efifo.name = name; - except(eFifo, efifo, e); - ret->w = name; - ret->m = NULL; - ret->n = NULL; - return ret; -} - -#else - -static List *mkcmdarg(Node *n) { - rc_error("named pipes are not supported"); - return NULL; -} - -#endif - -extern List *glom(Node *n) { - List *v, *head, *tail; - Node *words; - if (n == NULL) - return NULL; - switch (n->type) { - case nArgs: - case nLappend: - words = n->u[0].p; - tail = NULL; - while (words != NULL && (words->type == nArgs || words->type == nLappend)) { - if (words->u[1].p != NULL && words->u[1].p->type != nWord && words->u[1].p->type != nQword) - break; - head = glom(words->u[1].p); - if (head != NULL) { - head->n = tail; - tail = head; - } - words = words->u[0].p; - } - v = append(glom(words), tail); /* force left to right evaluation */ - return append(v, glom(n->u[1].p)); - case nBackq: - return backq(n->u[0].p, n->u[1].p); - case nConcat: - head = glom(n->u[0].p); /* force left-to-right evaluation */ - return concat(head, glom(n->u[1].p)); - case nDup: - case nRedir: - qredir(n); - return NULL; - case nWord: - case nQword: - return word(n->u[0].s, n->u[1].s); - case nNmpipe: - return mkcmdarg(n); - default: - /* - The next four operations depend on the left-child of glom - to be a variable name. Therefore the variable is looked up - here. - */ - if ((v = glom(n->u[0].p)) == NULL) - rc_error("null variable name"); - if (v->n != NULL) - rc_error("multi-word variable name"); - if (*v->w == '\0') - rc_error("zero-length variable name"); - v = (*v->w == '*' && v->w[1] == '\0') ? varlookup(v->w)->n : varlookup(v->w); - switch (n->type) { - default: - panic("unexpected node in glom"); - exit(1); - /* NOTREACHED */ - case nCount: - return count(v); - case nFlat: - return flatten(v); - case nVar: - return v; - case nVarsub: - return varsub(v, glom(n->u[1].p)); - } - } -} diff --git a/group.h b/group.h @@ -1,9 +0,0 @@ -/* Solaris / `gcc -ansi' only defines NGROUPS_MAX in <limits.h> if -_POSIX_C_SOURCE is defined. */ -#define _POSIX_C_SOURCE 1 -#include <limits.h> -#undef _POSIX_C_SOURCE - -#if defined(NGROUPS) && !defined(NGROUPS_MAX) -#define NGROUPS_MAX NGROUPS -#endif diff --git a/hash.c b/hash.c @@ -1,304 +0,0 @@ -/* hash.c: hash table support for functions and variables. */ - -/* - Functions and variables are cached in both internal and external - form for performance. Thus a variable which is never "dereferenced" - with a $ is passed on to rc's children untouched. This is not so - important for variables, but is a big win for functions, where a call - to yyparse() is involved. -*/ - -#include "rc.h" -#include "sigmsgs.h" - -static bool var_exportable(char *); -static bool fn_exportable(char *); -static int hash(char *, int); -static int find(char *, Htab *, int); -static void free_fn(Function *); - -Htab *fp; -Htab *vp; -static int fused, fsize, vused, vsize; -static char **env; -static int bozosize; -static int envsize; -static bool env_dirty = TRUE; -static char *dead = ""; - -#define HASHSIZE 64 /* rc was debugged with HASHSIZE == 2; 64 is about right for normal use */ - -extern void inithash() { - Htab *fpp, *vpp; - int i; - fp = ealloc(sizeof(Htab) * HASHSIZE); - vp = ealloc(sizeof(Htab) * HASHSIZE); - fused = vused = 0; - fsize = vsize = HASHSIZE; - for (vpp = vp, fpp = fp, i = 0; i < HASHSIZE; i++, vpp++, fpp++) - vpp->name = fpp->name = NULL; -} - -#define ADV() {if ((c = *s++) == '\0') break;} - -/* hash function courtesy of paul haahr */ - -static int hash(char *s, int size) { - int c, n = 0; - while (1) { - ADV(); - n += (c << 17) ^ (c << 11) ^ (c << 5) ^ (c >> 1); - ADV(); - n ^= (c << 14) + (c << 7) + (c << 4) + c; - ADV(); - n ^= (~c << 11) | ((c << 3) ^ (c >> 1)); - ADV(); - n -= (c << 16) | (c << 9) | (c << 2) | (c & 3); - } - if (n < 0) - n = ~n; - return n & (size - 1); /* need power of 2 size */ -} - -static bool rehash(Htab *ht) { - int i, j, size; - int newsize, newused; - Htab *newhtab; - if (ht == fp) { - if (fsize > 2 * fused) - return FALSE; - size = fsize; - } else { - if (vsize > 2 * vused) - return FALSE; - size = vsize; - } - newsize = 2 * size; - newhtab = ealloc(newsize * sizeof(Htab)); - for (i = 0; i < newsize; i++) - newhtab[i].name = NULL; - for (i = newused = 0; i < size; i++) - if (ht[i].name != NULL && ht[i].name != dead) { - newused++; - j = hash(ht[i].name, newsize); - while (newhtab[j].name != NULL) { - j++; - j &= (newsize - 1); - } - newhtab[j].name = ht[i].name; - newhtab[j].p = ht[i].p; - } - if (ht == fp) { - fused = newused; - fp = newhtab; - fsize = newsize; - } else { - vused = newused; - vp = newhtab; - vsize = newsize; - } - efree(ht); - return TRUE; -} - -#define varfind(s) find(s, vp, vsize) -#define fnfind(s) find(s, fp, fsize) - -static int find(char *s, Htab *ht, int size) { - int h = hash(s, size); - while (ht[h].name != NULL && !streq(ht[h].name, s)) { - h++; - h &= size - 1; - } - return h; -} - -extern void *lookup(char *s, Htab *ht) { - int h = find(s, ht, ht == fp ? fsize : vsize); - return (ht[h].name == NULL) ? NULL : ht[h].p; -} - -extern Function *get_fn_place(char *s) { - int h = fnfind(s); - env_dirty = TRUE; - if (fp[h].name == NULL) { - if (rehash(fp)) - h = fnfind(s); - fused++; - fp[h].name = ecpy(s); - fp[h].p = enew(Function); - } else - free_fn(fp[h].p); - return fp[h].p; -} - -extern Variable *get_var_place(char *s, bool stack) { - Variable *new; - int h = varfind(s); - - env_dirty = TRUE; - - if (vp[h].name == NULL) { - if (rehash(vp)) - h = varfind(s); - vused++; - vp[h].name = ecpy(s); - vp[h].p = enew(Variable); - ((Variable *)vp[h].p)->n = NULL; - return vp[h].p; - } else { - if (stack) { /* increase the stack by 1 */ - new = enew(Variable); - new->n = vp[h].p; - return vp[h].p = new; - } else { /* trample the top of the stack */ - new = vp[h].p; - efree(new->extdef); - listfree(new->def); - return new; - } - } -} - -extern void delete_fn(char *s) { - int h = fnfind(s); - if (fp[h].name == NULL) - return; /* not found */ - env_dirty = TRUE; - free_fn(fp[h].p); - efree(fp[h].p); - efree(fp[h].name); - if (fp[(h+1)&(fsize-1)].name == NULL) { - --fused; - fp[h].name = NULL; - } else { - fp[h].name = dead; - } -} - -extern void delete_var(char *s, bool stack) { - int h = varfind(s); - Variable *v; - if (vp[h].name == NULL) - return; /* not found */ - env_dirty = TRUE; - v = vp[h].p; - efree(v->extdef); - listfree(v->def); - if (v->n != NULL) { /* This is the top of a stack */ - if (stack) { /* pop */ - vp[h].p = v->n; - efree(v); - } else { /* else just empty */ - v->extdef = NULL; - v->def = NULL; - } - } else { /* needs to be removed from the hash table */ - efree(v); - efree(vp[h].name); - if (vp[(h+1)&(vsize-1)].name == NULL) { - --vused; - vp[h].name = NULL; - } else { - vp[h].name = dead; - } - } -} - -static void free_fn(Function *f) { - treefree(f->def); - efree(f->extdef); -} - -extern void initenv(char **envp) { - int n; - for (n = 0; envp[n] != NULL; n++) - ; - n++; /* one for the null terminator */ - if (n < HASHSIZE) - n = HASHSIZE; - env = ealloc((envsize = 2 * n) * sizeof (char *)); - for (; *envp != NULL; envp++) - if (strncmp(*envp, "fn_", conststrlen("fn_")) == 0) { - if (!dashpee) - fnassign_string(*envp); - } else { - if (!varassign_string(*envp)) /* add to bozo env */ - env[bozosize++] = *envp; - } -} - -static bool var_exportable(char *s) { - static char *notforexport[] = { - "apid", "pid", "apids", "*", "ifs" - }; - int i; - for (i = 0; i < arraysize(notforexport); i++) - if (streq(s, notforexport[i])) - return FALSE; - return TRUE; -} - -static bool fn_exportable(char *s) { - int i; - if (strncmp(s, "sig", conststrlen("sig")) == 0) { /* small speed hack */ - for (i = 0; i < NUMOFSIGNALS; i++) - if (streq(s, signals[i].name)) - return FALSE; - if (streq(s, "sigexit")) - return FALSE; - } - return TRUE; -} - -extern char **makeenv() { - int ep, i; - char *v; - if (!env_dirty) - return env; - env_dirty = FALSE; - ep = bozosize; - if (vsize + fsize + 1 + bozosize > envsize) { - envsize = 2 * (bozosize + vsize + fsize + 1); - env = erealloc(env, envsize * sizeof(char *)); - } - for (i = 0; i < vsize; i++) { - if (vp[i].name == NULL || vp[i].name == dead || !var_exportable(vp[i].name)) - continue; - v = varlookup_string(vp[i].name); - if (v != NULL) - env[ep++] = v; - } - for (i = 0; i < fsize; i++) { - if (fp[i].name == NULL || fp[i].name == dead || !fn_exportable(fp[i].name)) - continue; - env[ep++] = fnlookup_string(fp[i].name); - } - env[ep] = NULL; - qsort(env, (size_t) ep, sizeof(char *), starstrcmp); - return env; -} - -extern void whatare_all_vars(bool showfn, bool showvar) { - int i; - List *s; - if (showvar) - for (i = 0; i < vsize; i++) - if (vp[i].name != NULL && (s = varlookup(vp[i].name)) != NULL) - prettyprint_var(1, vp[i].name, s); - if (showfn) - for (i = 0; i < fsize; i++) - if (fp[i].name != NULL && fp[i].name != dead) - prettyprint_fn(1, fp[i].name, fnlookup(fp[i].name)); -} - -/* fake getenv() for readline() follows: */ - -#if READLINE -extern char *getenv(const char *name) { - List *s; - if (name == NULL || vp == NULL || (s = varlookup((char *) name)) == NULL) - return NULL; - return s->w; -} -#endif diff --git a/heredoc.c b/heredoc.c @@ -1,156 +0,0 @@ -/* heredoc.c: heredoc slurping is done here */ - -#include "rc.h" - -struct Hq { - Node *doc; - char *name; - Hq *n; - bool quoted; -} *hq; - -static bool dead = FALSE; - -/* - * read in a heredocument. A clever trick: skip over any partially matched end-of-file - * marker storing only the number of characters matched. If the whole marker is matched, - * return from readheredoc(). If only part of the marker is matched, copy that part into - * the heredocument. - * - * BUG: if the eof string contains a newline, the state can get confused, and the - * heredoc may continue past where it should. on the other hand, /bin/sh seems to - * never get out of its readheredoc() when the heredoc string contains a newline - */ - -static char *readheredoc(char *eof) { - int c; - char *t, *buf, *bufend; - unsigned char *s; - size_t bufsize; - t = buf = nalloc(bufsize = 512); - bufend = &buf[bufsize]; - dead = FALSE; -#define RESIZE(extra) { \ - char *nbuf; \ - bufsize = bufsize * 2 + extra; \ - nbuf = nalloc(bufsize); \ - memcpy(nbuf, buf, (size_t) (t - buf)); \ - t = nbuf + (t - buf); \ - buf = nbuf; \ - bufend = &buf[bufsize]; \ - } - for (;;) { - print_prompt2(); - for (s = (unsigned char *) eof; (c = gchar()) == *s; s++) - ; - if (*s == '\0' && (c == '\n' || c == EOF)) { - *t++ = '\0'; - return buf; - } - if (s != (unsigned char *) eof) { - size_t len = s - (unsigned char *) eof; - if (t + len >= bufend) - RESIZE(len); - memcpy(t, eof, len); - t += len; - } - for (;; c = gchar()) { - if (c == EOF) { - yyerror("heredoc incomplete"); - dead = TRUE; - return NULL; - } - if (t + 1 >= bufend) - RESIZE(0); - *t++ = c; - if (c == '\n') - break; - } - } -} - -/* parseheredoc -- turn a heredoc with variable references into a node chain */ - -static Node *parseheredoc(char *s) { - int c = *s; - Node *result = NULL; - while (TRUE) { - Node *node; - switch (c) { - default: { - char *begin = s; - while ((c = *s++) != '\0' && c != '$') - ; - *--s = '\0'; - node = mk(nQword, begin, NULL); - break; - } - case '$': { - char *begin = ++s, *var; - c = *s++; - if (c == '$') { - node = mk(nQword, "$", NULL); - c = *s; - } else { - size_t len = 0; - do - len++; - while (!dnw[c = *(unsigned char *) s++]); - if (c == '^') - c = *s; - else - s--; - var = nalloc(len + 1); - var[len] = '\0'; - memcpy(var, begin, len); - node = mk(nFlat, mk(nWord, var, NULL)); - } - break; - } - case '\0': - return result; - } - result = (result == NULL) ? node : mk(nConcat, result, node); - } -} - -/* read in heredocs when yyparse hits a newline. called from yyparse */ - -extern int heredoc(int end) { - Hq *here; - if ((here = hq) != NULL) { - hq = NULL; - if (end) { - yyerror("heredoc incomplete"); - return FALSE; - } - do { - Node *n = here->doc; - char *s = readheredoc(here->name); - if (dead) - return FALSE; - n->u[2].p = here->quoted ? mk(nQword, s, NULL) : parseheredoc(s); - n->u[0].i = rHerestring; - } while ((here = here->n) != NULL); - } - return TRUE; -} - -/* queue pending heredocs into a queue. called from yyparse */ - -extern int qdoc(Node *name, Node *n) { - Hq *new, **prev; - if (name->type != nWord && name->type != nQword) { - yyerror("eof-marker not a single literal word"); - flushu(); - return FALSE; - } - for (prev = &hq; (new = *prev) != NULL; prev = &new->n) - ; - *prev = new = nnew(Hq); - new->name = name->u[0].s; - new->quoted = (name->type == nQword); - new->doc = n; - new->n = NULL; - return TRUE; -} diff --git a/history/history.1 b/history/history.1 @@ -1,234 +0,0 @@ -.\" history.1 -.\"------- -.\" See rc.1 for man page portability notes. -.\"------- -.\" Dd distance to space vertically before a "display" -.\" These are what n/troff use for interparagraph distance -.\"------- -.if t .nr Dd .4v -.if n .nr Dd 1v -.\"------- -.\" Ds begin a display, indented .5 inches from the surrounding text. -.\" -.\" Note that uses of Ds and De may NOT be nested. -.\"------- -.de Ds -.\" .RS \\$1 -.sp \\n(Ddu -.in +0.5i -.nf -.. -.\"------- -.\" De end a display (no trailing vertical spacing) -.\"------- -.de De -.fi -.in -.\" .RE -.. -.\"------- -.\" I stole the Xf macro from the -man macros on my machine (originally -.\" "}S", I renamed it so that it won't conflict). -.\"------- -.\" Set Cf to the name of the constant width font. -.\" It will be "C" or "(CW", typically. -.\" NOTEZ BIEN the lines defining Cf must have no trailing white space: -.\"------- -.if t .ds Cf C -.if n .ds Cf R -.\"------- -.\" Rc - Alternate Roman and Courier -.\"------- -.de Rc -.Xf R \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ic - Alternate Italic and Courier -.\"------- -.de Ic -.Xf I \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Bc - Alternate Bold and Courier -.\"------- -.de Bc -.Xf B \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cr - Alternate Courier and Roman -.\"------- -.de Cr -.Xf \\*(Cf R \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ci - Alternate Courier and Italic -.\"------- -.de Ci -.Xf \\*(Cf I \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cb - Alternate Courier and Bold -.\"------- -.de Cb -.Xf \\*(Cf B \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Xf - Alternate fonts -.\" -.\" \$1 - first font -.\" \$2 - second font -.\" \$3 - desired word with embedded font changes, built up by recursion -.\" \$4 - text for first font -.\" \$5 - \$9 - remaining args -.\" -.\" Every time we are called: -.\" -.\" If there is something in \$4 -.\" then Call ourself with the fonts switched, -.\" with a new word made of the current word (\$3) and \$4 -.\" rendered in the first font, -.\" and with the remaining args following \$4. -.\" else We are done recursing. \$3 holds the desired output -.\" word. We emit \$3, change to Roman font, and restore -.\" the point size to the default. -.\" fi -.\" -.\" Use Xi to add a little bit of space after italic text. -.\"------- -.de Xf -.ds Xi -.\"------- -.\" I used to test for the italic font both by its font position -.\" and its name. Now just test by its name. -.\" -.\" .if "\\$1"2" .if !"\\$5"" .ds Xi \^ -.\"------- -.if "\\$1"I" .if !"\\$5"" .ds Xi \^ -.\"------- -.\" This is my original code to deal with the recursion. -.\" Evidently some nroffs can't deal with it. -.\"------- -.\" .ie !"\\$4"" \{\ -.\" . Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.\" .\} -.\" .el \{\\$3 -.\" . ft R \" Restore the default font, since we don't know -.\" . \" what the last font change was. -.\" . ps 10 \" Restore the default point size, since it might -.\" . \" have been changed by an argument to this macro. -.\" .\} -.\"------- -.\" Here is more portable (though less pretty) code to deal with -.\" the recursion. -.\"------- -.if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.if "\\$4"" \\$3\fR\s10 -.. -.TH HISTORY 1 "30 July 1991" -.SH NAME -\-, \-\|\-, \-p, \-\|\-p \- shell history programs -.SH SYNOPSIS -.B \- -.RI [ pattern ...] -.RI [ substitution ...] -.SH DESCRIPTION -This set of programs provides a crude history mechanism for the shell -.IR rc (1). -It is based on the v8 UNIX programs -.IR = , -.IR == , -etc. -.PP -The program -.RI `` \- '' -runs the shell on the command it is requested to find. -The program -.RI `` \-\|\- '' -edits that command first. -The programs -.RI `` \-p '' -and -.RI `` \-\|\-p '' -are similar, except that they print the final command on their standard -output instead of running the shell. -.PP -The commands work by looking for a file -named by the environment variable -.Cr $history , -and by searching for previous commands in this file. -Old commands can be edited, -or simply re-executed according to the rules below: -.PP -A command is searched for by examining the lines in -.Cr $history -in reverse order. -Lines which contain a previous invocation of the history -program itself are ignored. -If one or more -.I pattern -is supplied on the command line, -then the patterns are used as a means of -limiting the search. -Patterns match any substring of a previous command, -and if more than one pattern is present then all patterns must be -matched before a command is selected. -.PP -Substitutions may also be specified on the command line. -These have the syntax: -.Ds -.Ic old : new -.De -.PP -(Note that the -.I old -pattern is used as a search-limiting pattern also.) -Substitutions happen on the first match. -.PP -Finally, a command may be edited in a crude line-mode fashion: -The line to be edited is printed out, and below it the user -supplies modifications to the command: -.TP -.B any character -Replaces the character above. -.TP -.B space or tab -Skips over the above character(s). -.TP -.B # -Deletes one character. -.TP -.B % -Replaces one character with a space. -.TP -.B ^ -Inserts the rest of the typed line just before the character. -.TP -.B $ -Deletes the rest of the line from that character on, and replaces -it with the rest of the typed line. -.TP -.B + -Appends the rest of the typed line. -.TP -.B \- -Backs up to a previous command satisfying the same matching -constraints. -.TP -.B end of file -If an end-of-file is read from the keyboard by the editor, -it aborts with exit status 1 and does not produce any output. -.SH EXAMPLES -The history programs work best when their output is reinterpreted by -the shell using an -.Cr eval -command. -This can be achieved by writing a shell function to perform the -reinterpretation: -.Ds -.Cr "fn - -- {" -.Cr " comm = \`{$0^p $*}" -.Cr " if (! ~ $#comm 0) {" -.Cr " echo $comm >[1=2]" -.Cr " eval $comm" -.Cr " }" -.Cr "}" diff --git a/history/history.c b/history/history.c @@ -1,341 +0,0 @@ -/* - history.c -- primitive history mechanism - - Paul Haahr & Byron Rakitzis, July 1991. - - This program mimics the att v8 = and == history programs. - The edit() algorithm was adapted from a similar program - that Boyd Roberts wrote, but otherwise all the code has - been written from scratch. - - edit() was subsequently redone by Hugh Redelmeier in order - to correctly deal with tab characters in the source line. - - BUGS: - There is an implicit assumption that commands are no - more than 1k characters long. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static char *id = "@(#) history.c 8/91"; - -#undef FALSE -#undef TRUE -typedef enum { FALSE, TRUE } bool; - -#define CHUNKSIZE 65536 - -static struct { - char *old, *new; -} *replace; - -static char **search, *progname, *history; -static char me; /* typically ':' or '-' */ -static bool editit = FALSE, printit = FALSE; -static int nreplace = 0, nsearch = 0; -static FILE *fp; - -static void *ealloc(size_t n) { - void *p = (void *) malloc(n); - if (p == NULL) { - perror("malloc"); - exit(1); - } - return p; -} - -static void *erealloc(void *p, size_t n) { - p = (void *) realloc(p, n); - if (p == NULL) { - perror("realloc"); - exit(1); - } - return p; -} - -static char *newstr() { - return ealloc((size_t)1024); -} - -static char *basename(char *s) { - char *t = strrchr(s, '/'); - return (t == NULL) ? s : t + 1; -} - -/* stupid O(n^2) substring matching routine */ - -static char *isin(char *target, char *pattern) { - size_t plen = strlen(pattern); - size_t tlen = strlen(target); - for (; tlen >= plen; target++, --tlen) - if (strncmp(target, pattern, plen) == 0) - return target; - return NULL; -} - -/* replace the first match in the string with "new" */ -static char *sub(char *s, char *old, char *new) { - char *t, *u; - - t = isin(s, old); - u = newstr(); - - *t = '\0'; - while (*old != '\0') - old++, t++; - strcpy(u, s); - strcat(u, new); - strcat(u, t); - return u; -} - -static char *edit(char *s) { - char *final, *f, *end; - int col; - bool ins; - -start: - fprintf(stderr, "%s\n", s); - f = final = newstr(); - end = s + strlen(s); - col = 0; - ins = FALSE; - - for (;; col++) { - int c = getchar(); - - if (c == me && col == 0) { - int peekc = getchar(); - if (peekc == '\n') - return NULL; - ungetc(peekc, stdin); - } - if (c == '\n') { - if (col == 0) - return s; - - while (s < end) /* copy remainder of string */ - *f++ = *s++; - *f = '\0'; - s = final; - goto start; - } else if (ins || s>=end) { - /* col need not be accurate -- tabs need not be interpreted */ - *f++ = c; - } else { - switch (c) { - case '+': - while (s < end) - *f++ = *s++; - *f = '\0'; - continue; - case '%': - c = ' '; - /* FALLTHROUGH */ - default: - *f++ = c; - break; - case EOF: - exit(1); - /* NOTREACHED */ - case ' ': - if (*s == '\t') { - int oldcol = col; - - for (;; col++) { - int peekc; - - if ((col&07) == 07) { - *f++ = '\t'; /* we spaced past a tab */ - break; - } - peekc = getchar(); - if (peekc != ' ') { - ungetc(peekc, stdin); - if (peekc != '\n') { - /* we spaced partially into a tab */ - do { - *f++ = ' '; - oldcol++; - } while (oldcol <= col); - } - break; - } - } - } else { - *f++ = *s; - } - break; - case '#': - break; - case '$': - end = s; /* truncate s */ - continue; /* skip incrementing s */ - case '^': - ins = TRUE; - continue; /* skip incrementing s */ - case '\t': - for (;; col++) { - if ((*f++ = s<end? *s++ : '\t') == '\t') { - col = col | 07; /* advance to before next tabstop */ - } - if ((col&07) == 07) /* stop before tabstop */ - break; - } - continue; /* skip incrementing s */ - } - if (s<end && (*s!='\t' || (col&07)==07)) - s++; - } - } -} - -static char *readhistoryfile(char **last) { - char *buf; - size_t count, size; - long nread; - - if ((history = getenv("history")) == NULL) { - fprintf(stderr, "$history not set\n"); - exit(1); - } - fp = fopen(history, "r+"); - if (fp == NULL) { - perror(history); - exit(1); - } - - size = 0; - count = 0; - buf = ealloc(size = CHUNKSIZE); - while ((nread = fread(buf + count, sizeof (char), size - count, fp)) > 0) { - count += nread; - if (size - count == 0) - buf = erealloc(buf, size *= 4); - } - if (nread == -1) { - perror(history); - exit(1); - } - *last = buf + count; - return buf; -} - -static char *getcommand() { - char *s, *t; - static char *hist = NULL, *last; - - if (hist == NULL) { - hist = readhistoryfile(&last); - *--last = '\0'; /* trim final newline */ - } - -again: s = last; - if (s < hist) - return NULL; - while (*--s != '\n') - if (s <= hist) { - last = hist - 1; - return hist; - } - *s = '\0'; - last = s++; - - /* - * if the command contains the "me" character at the start of the line - * or after any of [`{|()@] then try again - */ - - for (t = s; *t != '\0'; t++) - if (*t == me) { - char *u = t - 1; - while (u >= s && (*u == ' ' || *u == '\t')) - --u; - if (u < s) - goto again; - switch (*u) { - case '`': case '@': - case '(': case ')': - case '{': case '|': - goto again; - default: - break; - } - } - return s; -} - -int main(int argc, char **argv) { - int i; - char *s; - - s = progname = basename(argv[0]); - me = *s++; - if (*s == me) { - s++; - editit = TRUE; - } - if (*s == 'p') { - s++; - printit = TRUE; - } -/* Nahh... - if (*s != '\0') { - fprintf(stderr, "\"%s\": bad name for history program\n", progname); - exit(1); - } -*/ - - if (argc > 1) { - replace = ealloc((argc - 1) * sizeof *replace); - search = ealloc((argc - 1) * sizeof *search); - } - for (i = 1; i < argc; i++) - if ((s = strchr(argv[i], ':')) == NULL) - search[nsearch++] = argv[i]; - else { - *(char *)s = '\0'; /* do we confuse ps too much? */ - replace[nreplace].old = argv[i]; - replace[nreplace].new = s + 1; - nreplace++; - } - -next: s = getcommand(); - if (s == NULL) { - fprintf(stderr, "command not matched\n"); - return 1; - } - for (i = 0; i < nsearch; i++) - if (!isin(s, search[i])) - goto next; - for (i = 0; i < nreplace; i++) - if (!isin(s, replace[i].old)) - goto next; - else - s = sub(s, replace[i].old, replace[i].new); - if (editit) { - s = edit(s); - if (s == NULL) - goto next; - } - fseek(fp, 0, 2); /* 2 == end of file. i.e., append command to $history */ - fprintf(fp, "%s\n", s); - fclose(fp); - if (printit) - printf("%s\n", s); - else { - char *shell = getenv("SHELL"); - - if (!editit) - fprintf(stderr, "%s\n", s); - if (shell == NULL) - shell = "/bin/sh"; - execl(shell, basename(shell), "-c", s, NULL); - perror(shell); - exit(1); - } - return 0; -} diff --git a/input.c b/input.c @@ -1,363 +0,0 @@ -/* input.c: i/o routines for files and pseudo-files (strings) */ - -#include <errno.h> -#include <setjmp.h> -#include "rc.h" -#include "jbwrap.h" - -/* - NB: character unget is supported for up to two characters, but NOT - in the case of EOF. Since EOF does not fit in a char, it is easiest - to support only one unget of EOF. -*/ - -typedef struct Input { - inputtype t; - char *ibuf; - int fd, index, read, lineno, last; - bool saved, eofread; -} Input; - -#define BUFSIZE ((size_t) 256) - -#if READLINE -extern char *readline(char *); -extern void add_history(char *); -static char *rlinebuf; -#endif - -char *prompt, *prompt2; -bool rcrc; - -static int dead(void); -static int fdgchar(void); -static int stringgchar(void); -static void history(void); -static void ugdead(int); -static void pushcommon(void); - -static char *inbuf; -static size_t istacksize, chars_out, chars_in; -static bool eofread = FALSE, save_lineno = TRUE; -static Input *istack, *itop; - -static int (*realgchar)(void); -static void (*realugchar)(int); - -int last; - -extern int gchar() { - int c; - - if (eofread) { - eofread = FALSE; - return last = EOF; - } - - while ((c = (*realgchar)()) == '\0') - pr_error("warning: null character ignored"); - - return c; -} - -extern void ugchar(int c) { - (*realugchar)(c); -} - -static int dead() { - return last = EOF; -} - -static void ugdead(int c) { - return; -} - -static void ugalive(int c) { - if (c == EOF) - eofread = TRUE; - else - inbuf[--chars_out] = c; -} - -/* get the next character from a string. */ - -static int stringgchar() { - return last = (inbuf[chars_out] == '\0' ? EOF : inbuf[chars_out++]); -} - -/* signal-safe readline wrapper */ - -#if READLINE -#ifndef HAVE_RESTARTABLE_SYSCALLS -static char *rc_readline(char *prompt) { - char *r; - interrupt_happened = FALSE; - if (!setjmp(slowbuf.j)) { - slow = TRUE; - if (!interrupt_happened) - r = readline(prompt); - else - r = NULL; - } else - r = NULL; - slow = FALSE; - if (r == NULL) - errno = EINTR; - sigchk(); - return r; -} -#else -#define rc_readline readline -#endif /* HAVE_RESTARTABLE_SYSCALLS */ -#endif /* READLINE */ - -/* - read a character from a file-descriptor. If GNU readline is defined, add a newline and doctor - the buffer to look like a regular fdgchar buffer. -*/ - -static int fdgchar() { - if (chars_out >= chars_in + 2) { /* has the buffer been exhausted? if so, replenish it */ - while (1) { -#if READLINE - if (interactive && istack->fd == 0) { - rlinebuf = rc_readline(prompt); - if (rlinebuf == NULL) { - chars_in = 0; - } else { - if (*rlinebuf != '\0') - add_history(rlinebuf); - chars_in = strlen(rlinebuf) + 1; - efree(inbuf); - inbuf = ealloc(chars_in + 3); - strcpy(inbuf+2, rlinebuf); - strcat(inbuf+2, "\n"); - efree(rlinebuf); - } - } else -#endif - { - long /*ssize_t*/ r = rc_read(istack->fd, inbuf + 2, BUFSIZE); - sigchk(); - if (r < 0) { - uerror("read"); - rc_exit(1); - } - chars_in = (size_t) r; - } - break; - } - if (chars_in == 0) - return last = EOF; - chars_out = 2; - if (dashvee) - writeall(2, inbuf + 2, chars_in); - history(); - } - return last = inbuf[chars_out++]; -} - -/* set up the input stack, and put a "dead" input at the bottom, so that yyparse will always read eof */ - -extern void initinput() { - istack = itop = ealloc(istacksize = 256 * sizeof (Input)); - istack->t = iFd; - istack->fd = -1; - realugchar = ugalive; -} - -/* push an input source onto the stack. set up a new input buffer, and set gchar() */ - -static void pushcommon() { - size_t idiff; - istack->index = chars_out; - istack->read = chars_in; - istack->ibuf = inbuf; - istack->lineno = lineno; - istack->saved = save_lineno; - istack->last = last; - istack->eofread = eofread; - istack++; - idiff = istack - itop; - if (idiff >= istacksize / sizeof (Input)) { - itop = erealloc(itop, istacksize *= 2); - istack = itop + idiff; - } - realugchar = ugalive; - chars_out = 2; - chars_in = 0; -} - -extern void pushfd(int fd) { - pushcommon(); - istack->t = iFd; - save_lineno = TRUE; - istack->fd = fd; - realgchar = fdgchar; - inbuf = ealloc(BUFSIZE + 2); - lineno = 1; -} - -extern void pushstring(char **a, bool save) { - pushcommon(); - istack->t = iString; - save_lineno = save; - inbuf = mprint("..%A", a); - realgchar = stringgchar; - if (save_lineno) - lineno = 1; - else - --lineno; -} - -/* remove an input source from the stack. restore the right kind of getchar (string,fd) etc. */ - -extern void popinput() { - if (istack->t == iFd) - close(istack->fd); - efree(inbuf); - --istack; - realgchar = (istack->t == iString ? stringgchar : fdgchar); - if (istack->t == iFd && istack->fd == -1) { /* top of input stack */ - realgchar = dead; - realugchar = ugdead; - } - last = istack->last; - eofread = istack->eofread; - inbuf = istack->ibuf; - chars_out = istack->index; - chars_in = istack->read; - if (save_lineno) - lineno = istack->lineno; - else - lineno++; - save_lineno = istack->saved; -} - -/* flush input characters upto newline. Used by scanerror() */ - -extern void flushu() { - int c; - if (last == '\n' || last == EOF) - return; - while ((c = gchar()) != '\n' && c != EOF) - ; /* skip to newline */ - if (c == EOF) - ugchar(c); -} - -/* the wrapper loop in rc: prompt for commands until EOF, calling yyparse and walk() */ - -extern Node *doit(bool execit) { - bool eof; - Jbwrap j; - Estack e1, e2; - Edata jerror; - - if (dashen) - execit = FALSE; - setjmp(j.j); - jerror.jb = &j; - except(eError, jerror, &e1); - for (eof = FALSE; !eof;) { - Edata block; - block.b = newblock(); - except(eArena, block, &e2); - sigchk(); - if (dashell) { - char *fname[3]; - fname[1] = concat(varlookup("home"), word("/.rcrc", NULL))->w; - fname[2] = NULL; - rcrc = TRUE; - dashell = FALSE; - b_dot(fname); - } - if (interactive) { - List *s; - if (!dashen && fnlookup("prompt") != NULL) { - static char *arglist[] = { "prompt", NULL }; - funcall(arglist); - } - if ((s = varlookup("prompt")) != NULL) { -#if READLINE - prompt = s->w; -#else - fprint(2, "%s", s->w); -#endif - prompt2 = (s->n == NULL ? "" : s->n->w); - } - } - inityy(); - if (yyparse() == 1 && execit) - rc_raise(eError); - eof = (last == EOF); /* "last" can be clobbered during a walk() */ - if (parsetree != NULL) { - if (execit) - walk(parsetree, TRUE); - else if (dashex && dashen) - fprint(2, "%T\n", parsetree); - } - unexcept(); /* eArena */ - } - popinput(); - unexcept(); /* eError */ - return parsetree; -} - -/* parse a function imported from the environment */ - -extern Node *parseline(char *extdef) { - int i = interactive; - char *in[2]; - Node *fun; - in[0] = extdef; - in[1] = NULL; - interactive = FALSE; - pushstring(in, TRUE); - fun = doit(FALSE); - interactive = i; - return fun; -} - -/* write last command out to a file if interactive && $history is set */ - -static void history() { - List *hist; - size_t a; - - if (!interactive || (hist = varlookup("history")) == NULL) - return; - - for (a = 0; a < chars_in; a++) { - char c = inbuf[a+2]; - - /* skip empty lines and comments */ - if (c == '#' || c == '\n') - break; - - /* line matches [ \t]*[^#\n] so it's ok to write out */ - if (c != ' ' && c != '\t') { - char *name = hist->w; - int fd = rc_open(name, rAppend); - if (fd < 0) { - uerror(name); - varrm(name, TRUE); - } else { - writeall(fd, inbuf + 2, chars_in); - close(fd); - } - break; - } - } -} - -/* close file descriptors after a fork() */ - -extern void closefds() { - Input *i; - for (i = istack; i != itop; --i) /* close open scripts */ - if (i->t == iFd && i->fd > 2) { - close(i->fd); - i->fd = -1; - } -} diff --git a/install-sh b/install-sh @@ -1,250 +0,0 @@ -#! /bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/jbwrap.h b/jbwrap.h @@ -1,9 +0,0 @@ -#include <setjmp.h> - -/* certain braindamaged environments don't define jmp_buf as an array, so... */ - -struct Jbwrap { - jmp_buf j; -}; - -extern Jbwrap slowbuf; /* for getting out of interrupts while performing slow i/o on BSD */ diff --git a/lex.c b/lex.c @@ -1,395 +0,0 @@ -/* lex.c: rc's lexical analyzer */ - -#include "rc.h" -#include "y.tab.h" - -/* - Special characters (i.e., "non-word") in rc: - \t \n # ; & | ^ $ = ~ ` ' { } @ ! ( ) < > \ - - The lexical analyzer is fairly straightforward. The only really - unclean part concerns backslash continuation and "double - backslashes". A backslash followed by a newline is treated as a - space, otherwise backslash is not a special character (i.e., - it can be part of a word). This introduces a host of unwanted - special cases. In our case, \ cannot be a word character, since - we wish to read in all word characters in a tight loop. - - Note: to save the trouble of declaring these arrays with TRUEs - and FALSEs, I am assuming that FALSE = 0, TRUE = 1. (and so is - it declared in rc.h) -*/ - -#define BUFSIZE ((size_t) 1000) /* malloc hates power of 2 buffers? */ -#define BUFMAX (8 * BUFSIZE) /* How big the buffer can get before we re-allocate the - space at BUFSIZE again. Premature optimization? Maybe. - */ - -typedef enum wordstates { - NW, RW, KW /* "nonword", "realword", "keyword" */ -} wordstates; - -static void getpair(int); - -int lineno; - -const char nw[] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -const char dnw[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - -static size_t bufsize = BUFSIZE; -static char *realbuf = NULL; -static bool newline = FALSE; -static bool errset = FALSE; -static bool prerror = FALSE; -static wordstates w = NW; -static int fd_left, fd_right; - -#define checkfreecaret {if (w != NW) { w = NW; ugchar(c); return '^'; }} - -enum filedescriptors { - UNSET = -9, CLOSED = -1 -}; - -extern int yylex() { - static bool dollar = FALSE; - bool saw_meta = FALSE; - int c; - size_t i; /* The purpose of all these local assignments is to */ - const char *meta; /* allow optimizing compilers like gcc to load these */ - char *buf = realbuf; /* values into registers. On a sparc this is a */ - YYSTYPE *y = &yylval; /* win, in code size *and* execution time */ - if (errset) { - errset = FALSE; - return '\n'; - } - /* rc variable-names may contain only alnum, '*' and '_', so use dnw if we are scanning one. */ - meta = (dollar ? dnw : nw); - dollar = FALSE; - if (newline) { - --lineno; /* slight space optimization; print_prompt2() always increments lineno */ - print_prompt2(); - newline = FALSE; - } -top: while ((c = gchar()) == ' ' || c == '\t') - w = NW; - if (c == EOF) - return END; - if (!meta[(unsigned char) c]) { /* it's a word or keyword. */ - checkfreecaret; - w = RW; - i = 0; - read: do { - buf[i++] = c; - if (c == '?' || c == '[' || c == '*') - saw_meta = TRUE; - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - } while ((c = gchar()) != EOF && !meta[(unsigned char) c]); - while (c == '\\') { - if ((c = gchar()) == '\n') { - print_prompt2(); - c = ' '; /* Pretend a space was read */ - break; - } else { - bs: if (meta != dnw) { /* all words but varnames may have a bslash */ - buf[i++] = '\\'; - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - if (!meta[(unsigned char) c]) - goto read; - } else { - ugchar(c); - c = '\\'; - break; - } - } - } - ugchar(c); - buf[i] = '\0'; - w = KW; - if (i == 2) { - if (*buf == 'i' && buf[1] == 'f') return IF; - if (*buf == 'f' && buf[1] == 'n') return FN; - if (*buf == 'i' && buf[1] == 'n') return IN; - } - if (streq(buf, "for")) return FOR; - if (streq(buf, "else")) return ELSE; - if (streq(buf, "switch")) return SWITCH; - if (streq(buf, "while")) return WHILE; - if (streq(buf, "case")) return CASE; - w = RW; - y->word.w = ncpy(buf); - if (saw_meta) { - char *r, *s; - - y->word.m = nalloc(strlen(buf) + 1); - for (r = buf, s = y->word.m; *r != '\0'; r++, s++) - *s = (*r == '?' || *r == '[' || *r == '*'); - } else { - y->word.m = NULL; - } - return WORD; - } - if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'') { - checkfreecaret; - if (c == '!' || c == '@' || c == '~') - w = KW; - } - switch (c) { - case '!': - return BANG; - case '@': - return SUBSHELL; - case '~': - return TWIDDLE; - case '`': - c = gchar(); - if (c == '`') - return BACKBACK; - ugchar(c); - return '`'; - case '$': - dollar = TRUE; - c = gchar(); - if (c == '#') - return COUNT; - if (c == '^') - return FLAT; - ugchar(c); - return '$'; - case '\'': - w = RW; - i = 0; - do { - buf[i++] = c; - if (c == '\n') - print_prompt2(); - if (c == EOF) { - w = NW; - scanerror("eof in quoted string"); - return HUH; - } - if (i >= bufsize) - buf = realbuf = erealloc(buf, bufsize *= 2); - } while ((c = gchar()) != '\'' || (c = gchar()) == '\''); /* quote "'" thus: 'how''s it going?' */ - ugchar(c); - buf[i] = '\0'; - y->word.w = ncpy(buf); - y->word.m = NULL; - return WORD; - case '\\': - if ((c = gchar()) == '\n') { - print_prompt2(); - goto top; /* Pretend it was just another space. */ - } - ugchar(c); - c = '\\'; - checkfreecaret; - c = gchar(); - i = 0; - goto bs; - case '(': - if (w == RW) /* SUB's happen only after real words, not keyowrds, so if () and while () work */ - c = SUB; - w = NW; - return c; - case '#': - while ((c = gchar()) != '\n') /* skip comment until newline */ - if (c == EOF) - return END; - /* FALLTHROUGH */ - case '\n': - lineno++; - newline = TRUE; - /* FALLTHROUGH */ - case ';': - case '^': - case ')': - case '=': - case '{': case '}': - w = NW; - return c; - case '&': - w = NW; - c = gchar(); - if (c == '&') - return ANDAND; - ugchar(c); - return '&'; - case '|': - w = NW; - c = gchar(); - if (c == '|') - return OROR; - getpair(c); - if (errset) - return HUH; - if ((y->pipe.left = fd_left) == UNSET) - y->pipe.left = 1; /* default to fd 1 */ - if ((y->pipe.right = fd_right) == UNSET) - y->pipe.right = 0; /* default to fd 0 */ - if (y->pipe.right == CLOSED) { - scanerror("expected digit after '='"); /* can't close a pipe */ - return HUH; - } - return PIPE; - case '>': - c = gchar(); - if (c == '>') { - c = gchar(); - y->redir.type = rAppend; - } else - y->redir.type = rCreate; - y->redir.fd = 1; - goto common; - case '<': - c = gchar(); - if (c == '<') { - c = gchar(); - if (c == '<') { - c = gchar(); - y->redir.type = rHerestring; - } else { - y->redir.type = rHeredoc; - } - } else - y->redir.type = rFrom; - y->redir.fd = 0; - common: - w = NW; - getpair(c); - if (errset) - return HUH; - if (fd_right == UNSET) { /* redirection, not dup */ - if (fd_left != UNSET) { - y->redir.fd = fd_left; - return SREDIR; - } - return (y->redir.type == rFrom || y->redir.type == rCreate) ? REDIR : SREDIR; - } else { /* dup; recast yylval */ - y->dup.type = y->redir.type; - y->dup.left = fd_left; - y->dup.right = fd_right; - return DUP; - } - default: - w = NW; - return c; /* don't know what it is, let yacc barf on it */ - } -} - -extern void yyerror(const char *s) { - char *tok; - if (prerror) { /* don't print "syntax error" if there's a more informative scanerror */ - prerror = FALSE; - return; - } - if (!interactive) { - if (w != NW) - tok = realbuf; - else if (last == EOF) - tok = "eof"; - else if (last == '\n') - tok = "end of line"; - else - tok = nprint((last < 32 || last > 126) ? "(decimal %d)" : "'%c'", last); - fprint(2, "line %d: %s near %s\n", lineno - (last == '\n'), s, tok); - } else - fprint(2, "%s\n", s); -} - -extern void scanerror(char *s) { - flushu(); /* flush upto newline */ - yyerror(s); - errset = prerror = TRUE; -} - -extern void inityy() { - newline = FALSE; - w = NW; - hq = NULL; - /* return memory to the system if the buffer got too large */ - if (bufsize > BUFMAX && realbuf != NULL) { - efree(realbuf); - bufsize = BUFSIZE; - realbuf = ealloc(bufsize); - } else if (realbuf == NULL) - realbuf = ealloc(bufsize); -} - -extern void print_prompt2() { - lineno++; -#if READLINE - prompt = prompt2; -#else - if (interactive) - fprint(2, "%s", prompt2); -#endif -} - -/* - Scan in a pair of integers for redirections like >[2=1]. CLOSED represents a closed file - descriptor (i.e., >[2=]) and UNSET represents an undesignated file descriptor (e.g., - >[2] is represented as (2,UNSET). - - This function makes use of unsigned compares to make range tests in one compare operation. -*/ - -static void getpair(int c) { - int n; - fd_left = fd_right = UNSET; - if (c != '[') { - ugchar(c); - return; - } - if ((unsigned int) (n = gchar() - '0') > 9) { - scanerror("expected digit after '['"); - return; - } - while ((unsigned int) (c = gchar() - '0') <= 9) - n = n * 10 + c; - fd_left = n; - c += '0'; - switch (c) { - default: - scanerror("expected '=' or ']' after digit"); - return; - case ']': - return; - case '=': - if ((unsigned int) (n = gchar() - '0') > 9) { - if (n != ']' - '0') { - scanerror("expected digit or ']' after '='"); - return; - } - fd_right = CLOSED; - } else { - while ((unsigned int) (c = gchar() - '0') <= 9) - n = n * 10 + c; - if (c != ']' - '0') { - scanerror("expected ']' after digit"); - return; - } - fd_right = n; - } - } -} diff --git a/list.c b/list.c @@ -1,57 +0,0 @@ -/* list.c: routines for manipulating the List type */ - -#include "rc.h" - -/* - These list routines assign meta values of null to the resulting lists; - it is impossible to glob with the value of a variable unless this value - is rescanned with eval---therefore it is safe to throw away the meta-ness - of the list. -*/ - -/* free a list from malloc space */ - -extern void listfree(List *p) { - while (p != NULL) { - List *n = p->n; - efree(p->w); - efree(p); - p = n; - } -} - -/* Copy list into malloc space (for storing a variable) */ - -extern List *listcpy(List *s, void *(*alloc)(size_t)) { - List *top, *r; - for (top = r = NULL; s != NULL; s = s->n) { - if (top == NULL) - r = top = (*alloc)(sizeof (List)); - else - r = r->n = (*alloc)(sizeof (List)); - r->w = (*alloc)(strlen(s->w) + 1); - strcpy(r->w, s->w); - r->m = NULL; - } - if (r != NULL) - r->n = NULL; - return top; -} - -/* Length of list */ - -extern size_t listlen(List *s) { - size_t size; - for (size = 0; s != NULL; s = s->n) - size += strlen(s->w) + 1; - return size; -} - -/* Number of elements in list */ - -extern int listnel(List *s) { - int nel; - for (nel = 0; s != NULL; s = s->n) - nel++; - return nel; -} diff --git a/main.c b/main.c @@ -1,121 +0,0 @@ -/* main.c: handles initialization of rc and command line options */ - -#include "rc.h" - -bool dashdee, dashee, dashvee, dashex, dashell, dasheye, - dashen, dashpee, dashess, interactive; -pid_t rc_pid; - -static bool dashoh; - -static void assigndefault(char *,...); -static void checkfd(int, enum redirtype); - -extern void main(int argc, char *argv[], char *envp[]) { - char *dashsee[2], *dollarzero, *null[1]; - int c; - initprint(); - dashsee[0] = dashsee[1] = NULL; - dollarzero = argv[0]; - rc_pid = getpid(); - dashell = (*argv[0] == '-'); /* Unix tradition */ - while ((c = rc_getopt(argc, argv, "nolpeivdxsc:")) != -1) - switch (c) { - case 'l': - dashell = TRUE; - break; - case 'e': - dashee = TRUE; - break; - case 'i': - dasheye = interactive = TRUE; - break; - case 'v': - dashvee = TRUE; - break; - case 'x': - dashex = TRUE; - break; - case 'd': - dashdee = TRUE; - break; - case 's': - dashess = dasheye = interactive = TRUE; - break; - case 'c': - dashsee[0] = rc_optarg; - goto quitopts; - case 'n': - dashen = TRUE; - break; - case 'p': - dashpee = TRUE; - break; - case 'o': - dashoh = TRUE; - break; - case '?': - exit(1); - } -quitopts: - argv += rc_optind; - /* use isatty() iff -i is not set, and iff the input is not from a script or -c or -s flags */ - if (!dasheye && !dashess && dashsee[0] == NULL && *argv == NULL) - interactive = isatty(0); - if (!dashoh) { - checkfd(0, rFrom); - checkfd(1, rCreate); - checkfd(2, rCreate); - } - initsignal(); - inithash(); - initparse(); - assigndefault("prompt", "; ", "", (void *)0); -#ifdef DEFAULTPATH - assigndefault("path", DEFAULTPATH, (void *)0); -#endif - assigndefault("ifs", " ", "\t", "\n", (void *)0); - assigndefault("pid", nprint("%d", rc_pid), (void *)0); - initenv(envp); - initinput(); - null[0] = NULL; - starassign(dollarzero, null, FALSE); /* assign $0 to $* */ - inithandler(); - if (dashsee[0] != NULL || dashess) { /* input from -c or -s? */ - if (*argv != NULL) - starassign(dollarzero, argv, FALSE); - if (dashess) - pushfd(0); - else - pushstring(dashsee, TRUE); - } else if (*argv != NULL) { /* else from a file? */ - b_dot(--argv); - rc_exit(getstatus()); - } else { /* else stdin */ - pushfd(0); - } - dasheye = FALSE; - doit(TRUE); - rc_exit(getstatus()); -} - -static void assigndefault(char *name,...) { - va_list ap; - List *l; - char *v; - va_start(ap, name); - for (l = NULL; (v = va_arg(ap, char *)) != NULL;) - l = append(l, word(v, NULL)); - varassign(name, l, FALSE); - if (streq(name, "path")) - alias(name, l, FALSE); - va_end(ap); -} - -/* open an fd on /dev/null if it is inherited closed */ - -static void checkfd(int fd, enum redirtype r) { - int new = rc_open("/dev/null", r); - if (new != fd && new != -1) - close(new); -} diff --git a/match.c b/match.c @@ -1,99 +0,0 @@ -/* match.c: pattern matching routines */ - -#include "rc.h" - -static int rangematch(char *, char); - -enum { RANGE_FAIL = -1, RANGE_ERROR = -2 }; - -/* match() matches a single pattern against a single string. */ - -extern bool match(char *p, char *m, char *s) { - int i, j; - if (m == NULL) - return streq(p, s); - i = 0; - while (1) { - if (p[i] == '\0') - return *s == '\0'; - else if (m[i]) { - switch (p[i++]) { - case '?': - if (*s++ == '\0') - return FALSE; - break; - case '*': - while (p[i] == '*' && m[i] == 1) /* collapse multiple stars */ - i++; - if (p[i] == '\0') /* star at end of pattern? */ - return TRUE; - while (*s != '\0') - if (match(p + i, m + i, s++)) - return TRUE; - return FALSE; - case '[': - if (*s == '\0') - return FALSE; - switch (j = rangematch(p + i, *s)) { - default: - i += j; - break; - case RANGE_FAIL: - return FALSE; - case RANGE_ERROR: - if (*s != '[') - return FALSE; - } - s++; - break; - default: - panic("bad metacharacter in match"); - /* NOTREACHED */ - return FALSE; /* hush up gcc -Wall */ - } - } else if (p[i++] != *s++) - return FALSE; - } -} - -/* - From the ed(1) man pages (on ranges): - - The `-' is treated as an ordinary character if it occurs first - (or first after an initial ^) or last in the string. - - The right square bracket does not terminate the enclosed string - if it is the first character (after an initial `^', if any), in - the bracketed string. - - rangematch() matches a single character against a class, and returns - an integer offset to the end of the range on success, or -1 on - failure. -*/ - -static int rangematch(char *p, char c) { - char *orig = p; - bool neg = (*p == '~'); - bool matched = FALSE; - if (neg) - p++; - if (*p == ']') { - p++; - matched = (c == ']'); - } - for (; *p != ']'; p++) { - if (*p == '\0') - return RANGE_ERROR; /* bad syntax */ - if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */ - if (c >= *p) - matched |= (c <= p[2]); - p += 2; - } else { - matched |= (*p == c); - } - } - if (matched ^ neg) - return p - orig + 1; /* skip the right-bracket */ - else - return RANGE_FAIL; -} diff --git a/mksignal b/mksignal @@ -1,76 +0,0 @@ -#!/bin/sh -# generate rc's internal signal table from signal.h - -exec > sigmsgs.c - -echo '#include "sigmsgs.h"' -echo -echo 'Sigmsgs signals[] = {' - -sed ' s/\/\*[ ]*// - s/[ ]*\*\/// - s/([@*+!]) // - s/[ ]*([a-zA-Z,->& ]*)[ ]*// - s/^[ ]*\#[ ]*define/\#define/ - s/[ ]*signal$// - s/_SIG/SIG/g' $1 | -awk ' - BEGIN { - # assign to nomesg["SIGNAME"] to suppress a long message - nomesg["SIGINT"] = 1 - nomesg["SIGPIPE"] = 1 - # assign to mesg["SIGNAME"] to override a message - mesg["SIGHUP"] = "hangup" - mesg["SIGKILL"] = "killed" - mesg["SIGQUIT"] = "quit" - mesg["SIGTERM"] = "terminated" - mesg["SIGURG"] = "urgent condition on i/o channel" - mesg["SIGSTOP"] = "stop signal not from tty" - mesg["SIGTSTP"] = "stopped" - mesg["SIGCONT"] = "continue" - mesg["SIGCHLD"] = "child stop or exit" - mesg["SIGTTIN"] = "background tty read" - mesg["SIGTTOU"] = "background tty write" - # assign to ignore["SIGNAME"] to explicitly ignore a named signal - ignore["SIGMAX"] = 1 - } - $1 == "#define" && $2 == "NSIG" && $3 ~ /^[0-9]+$/ { nsig = $3 } - $1 == "#define" && $2 ~ /^SIG/ && $3 ~ /^[0-9]+$/ && sig[$3] == "" && ignore[$2] == 0 { - sig[$3] = $2 - if ($3 > max) - max = $3 - if (mesg[$2] == "" && nomesg[$2] == 0) { - str = $4 - for (i = 5; i <= NF; i++) - str = str " " $i - mesg[$2] = str - } - } - END { - if (nsig == 0) - nsig = max + 1 - printf " {!!, !!},\n" - for (i = 1; i < nsig; i++) { - if (sig[i] == "") - printf " {!!, !!},\n" - else - printf " {!%s!, !%s!},\n", sig[i], mesg[sig[i]] - } - } -' | -tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ!' 'abcdefghijklmnopqrstuvwxyz"' - -echo '};' - -exec > sigmsgs.h - -echo 'typedef struct {' -echo ' char *name, *msg;' -echo '} Sigmsgs;' -echo 'extern Sigmsgs signals[];' - -grep '^ ' sigmsgs.c | # the thing in quotes is ^<tab> -awk ' - { sum = sum + 1; } - END { print "#define NUMOFSIGNALS", sum } -' diff --git a/nalloc.c b/nalloc.c @@ -1,139 +0,0 @@ -/* nalloc.c: a simple single-arena allocator for command-line-lifetime allocation */ -#include "rc.h" - -static struct Block { - size_t used, size; - char *mem; - Block *n; -} *fl, *ul; - -/* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */ -#define alignto(m, n) ((m + n - 1) & ~(n - 1)) -#define BLOCKSIZE ((size_t) 4096) - -/* Allocate a block from the free list or malloc one if none in the fl fit */ - -static void getblock(size_t n) { - Block *r, *p; - for (r = fl, p = NULL; r != NULL; p = r, r = r->n) - if (n <= r->size) - break; /* look for a block which fits the request */ - if (r != NULL) { /* if one is found, take it off the free list */ - if (p != NULL) - p->n = r->n; - else - fl = r->n; - } else { /* else allocate a new block */ - r = enew(Block); - r->mem = ealloc(r->size = alignto(n, BLOCKSIZE)); - } - r->used = 0; - r->n = ul; - ul = r; -} - -/* - A fast single-arena allocator. Looks at the current block, and if - there is not enough room, it goes to getblock() for more. "ul" - stands for "used list", and the head of the list is the current - block. "ulp" is a register cache for "ul"; this routine is hacked - for speed. (sigh, optimizing RISC compilers still can't cache the - address of a global in a register) -*/ - -extern void *nalloc(size_t n) { - size_t base; - Block *ulp; - n = alignto(n, sizeof(align_t)); - ulp = ul; - if (ulp != NULL && n + (base = ulp->used) < ulp->size) { - ulp->used = base + n; - return &ulp->mem[base]; - } else { - getblock(n); /* assert(ul->used) == 0 */ - (ulp = ul)->used = n; - return &ulp->mem[0]; - } -} - -/* - Frees memory from nalloc space by putting it on the free list. - Returns free blocks to the system, retaining at least MAXMEM bytes - worth of blocks for nalloc. -*/ - -#define MAXMEM 500000 - -extern void nfree() { - size_t count; - Block *r; - if (ul == NULL) - return; - for (r = ul; r->n != NULL; r = r->n) - ; /* get to end of used list */ - r->n = fl; /* tack free list onto it */ - fl = ul; /* and make it the free list */ - ul = NULL; /* finally, zero out the used list */ - for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) { - if (count >= MAXMEM) { - Block *tmp = r; - r = r->n; - tmp->n = NULL; /* terminate the free list */ - while (r != NULL) { /* free memory off the tail of the free list */ - tmp = r->n; - efree(r->mem); - efree(r); - r = tmp; - } - return; - } - } -} - -/* - "Allocates" a new arena by zeroing out the old one. Up to the - calling routine to keep the old value of the block around. -*/ - -extern Block *newblock() { - Block *old = ul; - ul = NULL; - return old; -} - -/* "Restores" an arena to its saved value. */ - -extern void restoreblock(Block *old) { - nfree(); - ul = old; -} - -/* generic memory allocation functions */ - -extern void *ealloc(size_t n) { - extern void *malloc(size_t); - void *p = malloc(n); - if (p == NULL) { - uerror("malloc"); - rc_exit(1); - } - return p; -} - -extern void *erealloc(void *p, size_t n) { - extern void *realloc(void *, size_t); - if (p == NULL) /* convenience feature */ - return ealloc(n); - if ((p = realloc(p, n)) == NULL) { - uerror("realloc"); - rc_exit(1); - } - return p; -} - -extern void efree(void *p) { - extern void free(void *); - if (p != NULL) - free(p); -} - diff --git a/open.c b/open.c @@ -1,25 +0,0 @@ -/* open.c: to insulate <fcntl.h> from the rest of rc. */ - -#include <fcntl.h> -#include "rc.h" - -/* - Opens a file with the necessary flags. Assumes the following - declaration for redirtype: - - enum redirtype { - rFrom, rCreate, rAppend, rHeredoc, rHerestring - }; -*/ - -static const int mode_masks[] = { - /* rFrom */ O_RDONLY, - /* rCreate */ O_TRUNC | O_CREAT | O_WRONLY, - /* rAppend */ O_APPEND | O_CREAT | O_WRONLY -}; - -extern int rc_open(const char *name, redirtype m) { - if ((unsigned) m >= arraysize(mode_masks)) - panic("bad mode passed to rc_open"); - return open(name, mode_masks[m], 0666); -} diff --git a/parse.y b/parse.y @@ -1,174 +0,0 @@ -/* parse.y */ - -/* - * Adapted from rc grammar, v10 manuals, volume 2. - */ - -%{ -#include "rc.h" -#ifndef lint -#define lint /* hush up gcc -Wall, leave out the dumb sccsid's. */ -#endif -static Node *star, *nolist; -Node *parsetree; /* not using yylval because bison declares it as an auto */ -%} - -%token ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN -%token OROR PIPE REDIR SREDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH - -%left WHILE ')' ELSE -%left ANDAND OROR '\n' -%left BANG SUBSHELL -%left PIPE -%right '$' -%left SUB -/* -*/ - -%union { - struct Node *node; - struct Redir redir; - struct Pipe pipe; - struct Dup dup; - struct Word word; - char *keyword; -} - -%type <redir> REDIR SREDIR -%type <pipe> PIPE -%type <dup> DUP -%type <word> WORD -%type <keyword> keyword -%type <node> assign body brace case cbody cmd cmdsa cmdsan comword epilog - first line nlwords paren redir sword simple iftail word words - -%start rc - -%% - -rc : line end { parsetree = $1; YYACCEPT; } - | error end { yyerrok; parsetree = NULL; YYABORT; } - -/* an rc line may end in end-of-file as well as newline, e.g., rc -c 'ls' */ -end : END /* EOF */ { if (!heredoc(1)) YYABORT; } /* flag error if there is a heredoc in the queue */ - | '\n' { if (!heredoc(0)) YYABORT; } /* get heredoc on \n */ - -/* a cmdsa is a command followed by ampersand or newline (used in "line" and "body") */ -cmdsa : cmd ';' - | cmd '&' { $$ = ($1 != NULL ? mk(nNowait,$1) : $1); } - -/* a line is a single command, or a command terminated by ; or & followed by a line (recursive) */ -line : cmd - | cmdsa line { $$ = ($1 != NULL ? mk(nBody,$1,$2) : $2); } - -/* a body is like a line, only commands may also be terminated by newline */ -body : cmd - | cmdsan body { $$ = ($1 == NULL ? $2 : $2 == NULL ? $1 : mk(nBody,$1,$2)); } - -cmdsan : cmdsa - | cmd '\n' { $$ = $1; if (!heredoc(0)) YYABORT; } /* get h.d. on \n */ - -brace : '{' body '}' { $$ = $2; } - -paren : '(' body ')' { $$ = $2; } - -assign : first '=' word { $$ = mk(nAssign,$1,$3); } - -epilog : { $$ = NULL; } - | redir epilog { $$ = mk(nEpilog,$1,$2); } - -/* a redirection is a dup (e.g., >[1=2]) or a file redirection. (e.g., > /dev/null) */ -redir : DUP { $$ = mk(nDup,$1.type,$1.left,$1.right); } - | REDIR word { $$ = mk(nRedir,$1.type,$1.fd,$2); - if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */ - } - | SREDIR word { $$ = mk(nRedir,$1.type,$1.fd,$2); - if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */ - } - -case : CASE words ';' { $$ = mk(nCase, $2); } - | CASE words '\n' { $$ = mk(nCase, $2); } - -cbody : cmd { $$ = mk(nCbody, $1, NULL); } - | case cbody { $$ = mk(nCbody, $1, $2); } - | cmdsan cbody { $$ = mk(nCbody, $1, $2); } - -iftail : cmd %prec ELSE - | brace ELSE optnl cmd { $$ = mk(nElse,$1,$4); } - -cmd : /* empty */ %prec WHILE { $$ = NULL; } - | simple - | brace epilog { $$ = mk(nBrace,$1,$2); } - | IF paren optnl iftail { $$ = mk(nIf,$2,$4); } - | FOR '(' word IN words ')' optnl cmd { $$ = mk(nForin,$3,$5,$8); } - | FOR '(' word ')' optnl cmd { $$ = mk(nForin,$3,star,$6); } - | WHILE paren optnl cmd { $$ = mk(nWhile,$2,$4); } - | SWITCH '(' word ')' optnl '{' cbody '}' { $$ = mk(nSwitch,$3,$7); } - | TWIDDLE optcaret word words { $$ = mk(nMatch,$3,$4); } - | cmd ANDAND optnl cmd { $$ = mk(nAndalso,$1,$4); } - | cmd OROR optnl cmd { $$ = mk(nOrelse,$1,$4); } - | cmd PIPE optnl cmd { $$ = mk(nPipe,$2.left,$2.right,$1,$4); } - | redir cmd %prec BANG { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); } - | assign cmd %prec BANG { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); } - | BANG optcaret cmd { $$ = mk(nBang,$3); } - | SUBSHELL optcaret cmd { $$ = mk(nSubshell,$3); } - | FN words brace { $$ = mk(nNewfn,$2,$3); } - | FN words { $$ = mk(nRmfn,$2); } - -optcaret : /* empty */ - | '^' - -simple : first - | simple word { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); } - | simple redir { $$ = mk(nArgs,$1,$2); } - -first : comword - | first '^' sword { $$ = mk(nConcat,$1,$3); } - -sword : comword - | keyword { $$ = mk(nWord,$1, NULL); } - -word : sword - | word '^' sword { $$ = mk(nConcat,$1,$3); } - -comword : '$' sword { $$ = mk(nVar,$2); } - | '$' sword SUB words ')' { $$ = mk(nVarsub,$2,$4); } - | COUNT sword { $$ = mk(nCount,$2); } - | FLAT sword { $$ = mk(nFlat, $2); } - | '`' sword { $$ = mk(nBackq,nolist,$2); } - | '`' brace { $$ = mk(nBackq,nolist,$2); } - | BACKBACK word brace { $$ = mk(nBackq,$2,$3); } - | BACKBACK word sword { $$ = mk(nBackq,$2,$3); } - | '(' nlwords ')' { $$ = $2; } - | REDIR brace { $$ = mk(nNmpipe,$1.type,$1.fd,$2); } - | WORD { $$ = ($1.w[0] == '\'') ? mk(nQword, $1.w+1, NULL) : mk(nWord,$1.w, $1.m); } - -keyword : FOR { $$ = "for"; } - | IN { $$ = "in"; } - | WHILE { $$ = "while"; } - | IF { $$ = "if"; } - | SWITCH { $$ = "switch"; } - | FN { $$ = "fn"; } - | ELSE { $$ = "else"; } - | CASE { $$ = "case"; } - | TWIDDLE { $$ = "~"; } - | BANG { $$ = "!"; } - | SUBSHELL { $$ = "@"; } - -words : { $$ = NULL; } - | words word { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); } - -nlwords : { $$ = NULL; } - | nlwords '\n' - | nlwords word { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); } - -optnl : /* empty */ - | optnl '\n' - -%% - -void initparse() { - star = treecpy(mk(nVar,mk(nWord,"*",NULL)), ealloc); - nolist = treecpy(mk(nVar,mk(nWord,"ifs",NULL)), ealloc); -} - diff --git a/print.c b/print.c @@ -1,482 +0,0 @@ -/* print.c -- formatted printing routines (Paul Haahr, 12/91) */ - -#include "rc.h" -#include <setjmp.h> - -#define PRINT_ALLOCSIZE ((size_t)64) -#define SPRINT_BUFSIZ ((size_t)1024) - -#define MAXCONV 256 - -/* - * conversion functions - * true return -> flag changes only, not a conversion - */ - -#define Flag(name, flag) \ -static bool name(Format *format, int c) { \ - format->flags |= flag; \ - return TRUE; \ -} - -Flag(uconv, FMT_unsigned) -Flag(hconv, FMT_short) -Flag(lconv, FMT_long) - -#if HAVE_QUAD_T -Flag(qconv, FMT_quad) -#endif - -Flag(altconv, FMT_altform) -Flag(leftconv, FMT_leftside) -Flag(dotconv, FMT_f2set) - -static bool digitconv(Format *format, int c) { - if (format->flags & FMT_f2set) - format->f2 = 10 * format->f2 + c - '0'; - else { - format->flags |= FMT_f1set; - format->f1 = 10 * format->f1 + c - '0'; - } - return TRUE; -} - -static bool zeroconv(Format *format, int c) { - if (format->flags & (FMT_f1set | FMT_f2set)) - return digitconv(format, '0'); - format->flags |= FMT_zeropad; - return TRUE; -} - -static void pad(Format *format, size_t len, int c) { - while (len-- != 0) - fmtputc(format, c); -} - -static bool sconv(Format *format, int c) { - char *s = va_arg(format->args, char *); - if ((format->flags & FMT_f1set) == 0) - fmtcat(format, s); - else { - size_t len = strlen(s), width = format->f1 - len; - if (format->flags & FMT_leftside) { - fmtappend(format, s, len); - pad(format, width, ' '); - } else { - pad(format, width, ' '); - fmtappend(format, s, len); - } - } - return FALSE; -} - -static char *utoa(unsigned long u, char *t, unsigned int radix, const char *digit) { - if (u >= radix) { - t = utoa(u / radix, t, radix, digit); - u %= radix; - } - *t++ = digit[u]; - return t; -} - -static void intconv(Format *format, unsigned int radix, int upper, const char *altform) { - static const char * const table[] = { - "0123456789abcdefghijklmnopqrstuvwxyz", - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", - }; - char padchar; - size_t len, pre, zeroes, padding, width; - long n, flags; - unsigned long u; - char number[64], prefix[20]; - - if (radix > 36) - return; - - flags = format->flags; - -#if HAVE_QUAD_T - if (flags & FMT_quad) - n = va_arg(format->args, quad_t); - else -#endif - - if (flags & FMT_long) - n = va_arg(format->args, long); - else if (flags & FMT_short) - n = va_arg(format->args, short); - else - n = va_arg(format->args, int); - - pre = 0; - if ((flags & FMT_unsigned) || n >= 0) - u = n; - else { - prefix[pre++] = '-'; - u = -n; - } - - if (flags & FMT_altform) - while (*altform != '\0') - prefix[pre++] = *altform++; - - len = utoa(u, number, radix, table[upper]) - number; - if ((flags & FMT_f2set) && (size_t) format->f2 > len) - zeroes = format->f2 - len; - else - zeroes = 0; - - width = pre + zeroes + len; - if ((flags & FMT_f1set) && (size_t) format->f1 > width) { - padding = format->f1 - width; - } else - padding = 0; - - padchar = ' '; - if (padding > 0 && flags & FMT_zeropad) { - padchar = '0'; - if ((flags & FMT_leftside) == 0) { - zeroes += padding; - padding = 0; - } - } - - - if ((flags & FMT_leftside) == 0) - pad(format, padding, padchar); - fmtappend(format, prefix, pre); - pad(format, zeroes, '0'); - fmtappend(format, number, len); - if (flags & FMT_leftside) - pad(format, padding, padchar); -} - -static bool cconv(Format *format, int c) { - fmtputc(format, va_arg(format->args, int)); - return FALSE; -} - -static bool dconv(Format *format, int c) { - intconv(format, 10, 0, ""); - return FALSE; -} - -static bool oconv(Format *format, int c) { - intconv(format, 8, 0, "0"); - return FALSE; -} - -static bool xconv(Format *format, int c) { - intconv(format, 16, 0, "0x"); - return FALSE; -} - -static bool pctconv(Format *format, int c) { - fmtputc(format, '%'); - return FALSE; -} - -static bool badconv(Format *format, int c) { - panic("bad conversion character in printfmt"); - /* NOTREACHED */ - return FALSE; /* hush up gcc -Wall */ -} - - -/* - * conversion table management - */ - -static Conv fmttab[MAXCONV]; - -static void inittab(void) { - int i; - for (i = 0; i < MAXCONV; i++) - fmttab[i] = badconv; - - fmttab['s'] = sconv; - fmttab['c'] = cconv; - fmttab['d'] = dconv; - fmttab['o'] = oconv; - fmttab['x'] = xconv; - fmttab['%'] = pctconv; - - fmttab['u'] = uconv; - fmttab['h'] = hconv; - fmttab['l'] = lconv; - fmttab['#'] = altconv; - fmttab['-'] = leftconv; - fmttab['.'] = dotconv; - -#if HAVE_QUAD_T - fmttab['q'] = qconv; -#endif - - fmttab['0'] = zeroconv; - for (i = '1'; i <= '9'; i++) - fmttab[i] = digitconv; -} - -extern bool (*fmtinstall(int c, bool (*f)(Format *, int)))(Format *, int) { -/*Conv fmtinstall(int c, Conv f) {*/ - Conv oldf; - if (fmttab[0] == NULL) - inittab(); - c &= MAXCONV - 1; - oldf = fmttab[c]; - if (f != NULL) - fmttab[c] = f; - return oldf; -} - - -/* - * functions for inserting strings in the format buffer - */ - -extern void fmtappend(Format *format, const char *s, size_t len) { - while (format->buf + len > format->bufend) { - size_t split = format->bufend - format->buf; - memcpy(format->buf, s, split); - format->buf += split; - s += split; - len -= split; - (*format->grow)(format, len); - } - memcpy(format->buf, s, len); - format->buf += len; -} - -extern void fmtcat(Format *format, const char *s) { - fmtappend(format, s, strlen(s)); -} - -/* - * printfmt -- the driver routine - */ - -extern int printfmt(Format *format, const char *fmt) { - unsigned const char *s = (unsigned const char *) fmt; - - if (fmttab[0] == NULL) - inittab(); - - for (;;) { - int c = *s++; - switch (c) { - case '%': - format->flags = format->f1 = format->f2 = 0; - do - c = *s++; - while ((*fmttab[c])(format, c)); - break; - case '\0': - return format->buf - format->bufbegin + format->flushed; - default: - fmtputc(format, c); - break; - } - } -} - - -/* - * the public entry points - */ - -extern int fmtprint(Format *format, const char *fmt,...) { - int n = -format->flushed; - va_list ap, saveargs; - - va_start(ap, fmt); - saveargs = format->args; - format->args = ap; - n += printfmt(format, fmt); - va_end(format->args); - format->args = saveargs; - - return n + format->flushed; -} - -static void fprint_flush(Format *format, size_t more) { - size_t n = format->buf - format->bufbegin; - char *buf = format->bufbegin; - - format->flushed += n; - format->buf = format->bufbegin; - writeall(format->u.n, buf, n); -} - -extern int fprint(int fd, const char *fmt,...) { - char buf[1024]; - Format format; - va_list ap; - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + sizeof buf; - format.grow = fprint_flush; - format.flushed = 0; - format.u.n = fd; - - va_start(ap, fmt); - format.args = ap; - printfmt(&format, fmt); - va_end(format.args); - - fprint_flush(&format, 0); - return format.flushed; -} - -static void memprint_grow(Format *format, size_t more) { - char *buf; - size_t len = format->bufend - format->bufbegin + 1; - len = (len >= more) - ? len * 2 - : ((len + more) + PRINT_ALLOCSIZE) &~ (PRINT_ALLOCSIZE - 1); - if (format->u.n) - buf = erealloc(format->bufbegin, len); - else { - size_t used = format->buf - format->bufbegin; - buf = nalloc(len); - memcpy(buf, format->bufbegin, used); - } - format->buf = buf + (format->buf - format->bufbegin); - format->bufbegin = buf; - format->bufend = buf + len - 1; -} - -static char *memprint(Format *format, const char *fmt, char *buf, size_t len) { - format->buf = buf; - format->bufbegin = buf; - format->bufend = buf + len - 1; - format->grow = memprint_grow; - format->flushed = 0; - printfmt(format, fmt); - *format->buf = '\0'; - return format->bufbegin; -} - -extern char *mprint(const char *fmt,...) { - Format format; - char *result; - va_list ap; - - format.u.n = 1; - va_start(ap, fmt); - format.args = ap; - result = memprint(&format, fmt, ealloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); - va_end(format.args); - return result; -} - -extern char *nprint(const char *fmt,...) { - Format format; - char *result; - va_list ap; - - format.u.n = 0; - va_start(ap, fmt); - format.args = ap; - result = memprint(&format, fmt, nalloc(PRINT_ALLOCSIZE), PRINT_ALLOCSIZE); - va_end(format.args); - return result; -} - - -/* THESE ARE UNUSED IN rc */ - -#if 0 - -extern int print(const char *fmt,...) { - char buf[1024]; - Format format; - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + sizeof buf; - format.grow = fprint_flush; - format.flushed = 0; - format.u.n = 1; - - va_start(format.args, fmt); - printfmt(&format, fmt); - va_end(format.args); - - fprint_flush(&format, 0); - return format.flushed; -} - -extern int eprint(const char *fmt,...) { - char buf[1024]; - Format format; - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + sizeof buf; - format.grow = fprint_flush; - format.flushed = 0; - format.u.n = 2; - - va_start(format.args, fmt); - printfmt(&format, fmt); - va_end(format.args); - - fprint_flush(&format, 0); - return format.flushed; -} - -static void snprint_grow(Format *format, size_t more) { - longjmp(format->u.p, 1); -} - -extern int snprint(char *buf, int buflen, const char *fmt,...) { - int n; - jmp_buf jbuf; - Format format; - - if (setjmp(jbuf)) { - *format.buf = '\0'; - return format.buf - format.bufbegin; - } - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + buflen - 1; - format.grow = snprint_grow; - format.flushed = 0; - format.u.p = jbuf; - - va_start(format.args, fmt); - n = printfmt(&format, fmt); - va_end(format.args); - - *format.buf = '\0'; - return n; -} - -extern int sprint(char *buf, const char *fmt,...) { - int n; - jmp_buf jbuf; - Format format; - - if (setjmp(jbuf)) { - *format.buf = '\0'; - return format.buf - format.bufbegin; - } - - format.buf = buf; - format.bufbegin = buf; - format.bufend = buf + SPRINT_BUFSIZ - 1; - format.grow = snprint_grow; - format.flushed = 0; - format.u.p = jbuf; - - va_start(format.args, fmt); - n = printfmt(&format, fmt); - va_end(format.args); - - *format.buf = '\0'; - return n; -} -#endif diff --git a/proto.h b/proto.h @@ -1,40 +0,0 @@ -#if HAVE_QUAD_T -typedef quad_t align_t; -#else -typedef long align_t; -#endif - -/* If you need to change this, please let the maintainer know. */ -#ifndef SIG_ATOMIC_T -typedef int SIG_ATOMIC_T; -#endif - -#if STDC_HEADERS -#include <stdlib.h> -#else -/* fake stdlib.h */ -extern void exit(int); -extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); -#endif - -#if STDC_HEADERS -#include <string.h> -#else -/* fake string.h */ -extern int strncmp(const char *, const char *, size_t); -extern int strcmp(const char *, const char *); -extern size_t strlen(const char *); -extern char *strchr(const char *, int); -extern char *strrchr(const char *, int); -extern char *strcpy(char *, const char *); -extern char *strncpy(char *, const char *, size_t); -extern char *strcat(char *, const char *); -extern char *strncat(char *, const char *, size_t); -extern void *memcpy(void *, const void *, size_t); -extern void *memset(void *, int, size_t); -#endif - -/* fake errno.h for mips (which doesn't declare errno in errno.h!?!?) */ -#ifdef host_mips -extern int errno; -#endif diff --git a/rc.1 b/rc.1 @@ -1,1881 +0,0 @@ -.\" rc.1 -.\"------- -.\" Man page portability notes -.\" -.\" These are some notes on conventions to maintain for greatest -.\" portability of this man page to various other versions of -.\" nroff. -.\" -.\" When you want a \ to appear in the output, use \e in the man page. -.\" (NOTE this comes up in the rc grammar, where to print out '\n' the -.\" man page must contain '\en'.) -.\" -.\" Evidently not all versions of nroff allow the omission of the -.\" terminal " on a macro argument. Thus what could be written -.\" -.\" .Cr "exec >[2] err.out -.\" -.\" in true nroffs must be written -.\" -.\" .Cr "exec >[2] err.out" -.\" -.\" instead. -.\" -.\" Use symbolic font names (e.g. R, I, B) instead of the standard -.\" font positions 1, 2, 3. Note that for Xf to work the standard -.\" font names must be single characters. -.\" -.\" Not all man macros have the RS and RE requests (I altered the Ds -.\" and De macros and the calls to Ds accordingly). -.\" -.\" Thanks to Michael Haardt (u31b3hs@cip-s01.informatik.rwth-aachen.de) -.\" for pointing out these problems. -.\" -.\" Note that sentences should end at the end of a line. nroff and -.\" troff will supply the correct intersentence spacing, but only if -.\" the sentences end at the end of a line. Explicit spaces, if given, -.\" are apparently honored and the normal intersentence spacing is -.\" supressed. -.\" -.\" DaviD W. Sanderson -.\"------- -.\" Dd distance to space vertically before a "display" -.\" These are what n/troff use for interparagraph distance -.\"------- -.if t .nr Dd .4v -.if n .nr Dd 1v -.\"------- -.\" Ds begin a display, indented .5 inches from the surrounding text. -.\" -.\" Note that uses of Ds and De may NOT be nested. -.\"------- -.de Ds -.\" .RS \\$1 -.sp \\n(Ddu -.in +0.5i -.nf -.. -.\"------- -.\" De end a display (no trailing vertical spacing) -.\"------- -.de De -.fi -.in -.\" .RE -.. -.\"------- -.\" I stole the Xf macro from the -man macros on my machine (originally -.\" "}S", I renamed it so that it won't conflict). -.\"------- -.\" Set Cf to the name of the constant width font. -.\" It will be "C" or "(CW", typically. -.\" NOTEZ BIEN the lines defining Cf must have no trailing white space: -.\"------- -.if t .ds Cf C -.if n .ds Cf R -.\"------- -.\" Rc - Alternate Roman and Courier -.\"------- -.de Rc -.Xf R \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ic - Alternate Italic and Courier -.\"------- -.de Ic -.Xf I \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Bc - Alternate Bold and Courier -.\"------- -.de Bc -.Xf B \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cr - Alternate Courier and Roman -.\"------- -.de Cr -.Xf \\*(Cf R \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ci - Alternate Courier and Italic -.\"------- -.de Ci -.Xf \\*(Cf I \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cb - Alternate Courier and Bold -.\"------- -.de Cb -.Xf \\*(Cf B \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Xf - Alternate fonts -.\" -.\" \$1 - first font -.\" \$2 - second font -.\" \$3 - desired word with embedded font changes, built up by recursion -.\" \$4 - text for first font -.\" \$5 - \$9 - remaining args -.\" -.\" Every time we are called: -.\" -.\" If there is something in \$4 -.\" then Call ourself with the fonts switched, -.\" with a new word made of the current word (\$3) and \$4 -.\" rendered in the first font, -.\" and with the remaining args following \$4. -.\" else We are done recursing. \$3 holds the desired output -.\" word. We emit \$3, change to Roman font, and restore -.\" the point size to the default. -.\" fi -.\" -.\" Use Xi to add a little bit of space after italic text. -.\"------- -.de Xf -.ds Xi -.\"------- -.\" I used to test for the italic font both by its font position -.\" and its name. Now just test by its name. -.\" -.\" .if "\\$1"2" .if !"\\$5"" .ds Xi \^ -.\"------- -.if "\\$1"I" .if !"\\$5"" .ds Xi \^ -.\"------- -.\" This is my original code to deal with the recursion. -.\" Evidently some nroffs can't deal with it. -.\"------- -.\" .ie !"\\$4"" \{\ -.\" . Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.\" .\} -.\" .el \{\\$3 -.\" . ft R \" Restore the default font, since we don't know -.\" . \" what the last font change was. -.\" . ps 10 \" Restore the default point size, since it might -.\" . \" have been changed by an argument to this macro. -.\" .\} -.\"------- -.\" Here is more portable (though less pretty) code to deal with -.\" the recursion. -.\"------- -.if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.if "\\$4"" \\$3\fR\s10 -.. -.TH RC 1 "28 April 1991" -.SH NAME -rc \- shell -.SH SYNOPSIS -.B rc -.RB [ \-eixvldnpo ] -.RB [ \-c -.IR command ] -.RI [ arguments ] -.SH DESCRIPTION -.I rc -is a command interpreter and programming language similar to -.IR sh (1). -It is based on the AT&T Plan 9 shell of the same name. -The shell offers a C-like syntax (much more so than the C shell), -and a powerful mechanism for manipulating variables. -It is reasonably small and reasonably fast, -especially when compared to contemporary shells. -Its use is intended to be interactive, -but the language lends itself well to scripts. -.SH OPTIONS -.TP -.Cr \-e -If the -.Cr \-e -option is present, then -.I rc -will exit if the exit status of a command is false (nonzero). -.I rc -will not exit, however, if a conditional fails, e.g., an -.Cr if() -command. -.TP -.Cr \-i -If the -.Cr \-i -option is present or if the input to -.I rc -is from a terminal (as determined by -.IR isatty (3)) -then -.I rc -will be in -.I interactive -mode. -That is, a prompt (from -.Cr $prompt(1)\^ ) -will be printed before an -input line is taken, and -.I rc -will ignore the signals -.Cr SIGINT -and -.Cr SIGQUIT . -.TP -.Cr \-x -This option will make -.I rc -print every command on standard error before it is executed. -It can be useful for debugging -.I rc -scripts. -.TP -.Cr \-v -This option will echo input to -.I rc -on standard error as it is read. -.TP -.Cr \-l -If the -.Cr \-l -option is present, or if -.IR rc 's -.Cr argv[0][0] -is a dash -.Rc ( \- ), -then -.I rc -will behave as a login shell. -That is, it will try to run commands present in -.Cr $home/.rcrc , -if this file exists, before reading any other input. -.TP -.Cr \-d -This flag causes -.I rc -not to ignore -.Cr SIGQUIT -or -.Cr SIGTERM . -Thus -.I rc -can be made to dump core if sent -.Cr SIGQUIT . -This option is only useful for debugging -.IR rc . -.TP -.Cr \-n -This flag causes -.I rc -to read its input and parse it, but not to execute any commands. -This is useful for syntax checking on scripts. -If used in combination with the -.Cr \-x -option, -.I rc -will print each command as it is parsed in a form similar to the one -used for exporting functions into the environment. -.TP -.Cr \-p -This flag prevents -.I rc -from initializing shell functions from the environment. -This allows -.I rc -to run in a protected mode, whereby it becomes more difficult for -an -.I rc -script to be subverted by placing false commands in the environment. -(Note that this presence of this option does NOT mean that it is safe to -run setuid -.I rc -scripts; the usual caveats about the setuid bit still apply.) -.TP -.Cr \-o -This flag prevents the usual practice of trying to open -.Cr /dev/null -on file descriptors 0, 1, and 2, if any of those descriptors -are inherited closed. -.TP -.Cr \-c -If -.Cr \-c -is present, commands are executed from the immediately following -argument. -Any further arguments to -.I rc -are placed in -.Cr $* . -.PP -.SH COMMANDS -A simple command is a sequence of words, separated by white space -(space and tab) characters that ends with a newline, semicolon -.Rc ( ; ), -or ampersand -.Rc ( & ). -The first word of a command is the name of that command. -If the name begins with -.Cr / , -.Cr ./ , -or -.Cr ../ , -then the name is used as an absolute path -name referring to an executable file. -Otherwise, the name of the command is looked up in a table -of shell functions, builtin commands, -or as a file in the directories named by -.Cr $path . -.SS "Background Tasks" -A command ending with a -.Cr & -is run in the background; that is, -the shell returns immediately rather than waiting for the command to -complete. -Background commands have -.Cr /dev/null -connected to their standard input unless an explicit redirection for -standard input is used. -.SS "Subshells" -A command prefixed with an at-sign -.Rc ( @ ) -is executed in a subshell. -This insulates the parent shell from the effects -of state changing operations such as a -.B cd -or a variable assignment. -For example: -.Ds -.Cr "@ {cd ..; make}" -.De -.PP -will run -.IR make (1) -in the parent directory -.Rc ( .. ), -but leaves the shell running in the current directory. -.SS "Line continuation" -A long logical line may be continued over several physical lines by -terminating each line (except the last) with a backslash -.Rc ( \e ). -The backslash-newline sequence is treated as a space. -A backslash is not otherwise special to -.IR rc . -(In addition, -inside quotes a backslash loses its special meaning -even when it is followed by a newline.) -.SS Quoting -.IR rc -interprets several characters specially; special characters -automatically terminate words. -The following characters are special: -.Ds -.Cr "# ; & | ^ $ = \` ' { } ( ) < >" -.De -.PP -The single quote -.Rc ( ' ) -prevents special treatment of any character other than itself. -All characters, including control characters, newlines, -and backslashes between two quote characters are treated as an -uninterpreted string. -A quote character itself may be quoted by placing two quotes in a row. -The minimal sequence needed to enter the quote character is -.Cr '''' . -The empty string is represented by -.Cr '' . -Thus: -.Ds -.Cr "echo 'What''s the plan, Stan?'" -.De -.PP -prints out -.Ds -.Cr "What's the plan, Stan?" -.De -.PP -The number sign -.Rc ( # ) -begins a comment in -.IR rc . -All characters up to but not including the next newline are ignored. -Note that backslash continuation does not work inside a comment, -i.e., -the backslash is ignored along with everything else. -.SS Grouping -Zero or more commands may be grouped within braces -.Rc (`` { '' -and -.Rc `` } ''), -and are then treated as one command. -Braces do not otherwise define scope; -they are used only for command grouping. -In particular, be wary of the command: -.Ds -.Cr "for (i) {" -.Cr " command" -.Cr "} | command" -.De -.PP -Since pipe binds tighter than -.Cr for , -this command does not perform what the user expects it to. -Instead, enclose the whole -.Cr for -statement in braces: -.Ds -.Cr "{for (i) command} | command" -.De -.PP -Fortunately, -.IR rc 's -grammar is simple enough that a (confident) user can -understand it by examining the skeletal -.IR yacc (1) -grammar -at the end of this man page (see the section entitled -.BR GRAMMAR ). -.SS "Input and output" -.PP -The standard output may be redirected to a file with -.Ds -.Cr "command > file" -.De -.PP -and the standard input may be taken from a file with -.Ds -.Cr "command < file" -.De -.PP -File descriptors other than 0 and 1 may be specified also. -For example, to redirect standard error to a file, use: -.Ds -.Cr "command >[2] file" -.De -.PP -In order to duplicate a file descriptor, use -.Ci >[ n = m ]\fR. -Thus to redirect both standard output and standard error -to the same file, use -.Ds -.Cr "command > file >[2=1]" -.De -.PP -To close a file descriptor that may be open, use -.Ci >[ n =]\fR. -For example, to -close file descriptor 7: -.Ds -.Cr "command >[7=]" -.De -.PP -In order to place the output of a command at the end of an already -existing file, use: -.Ds -.Cr "command >> file" -.De -.PP -If the file does not exist, then it is created. -.PP -``Here documents'' are supported as in -.I sh -with the use of -.Ds -.Cr "command << 'eof-marker'" -.De -.PP -If the end-of-file marker is enclosed in quotes, -then no variable substitution occurs inside the here document. -Otherwise, every variable is substituted -by its space-separated-list value (see -.BR "Flat Lists" , -below), -and if a -.Cr ^ -character follows a variable name, it is deleted. -This allows the unambiguous use of variables adjacent to text, as in -.Ds -.Cr $variable^follow -.De -.PP -To include a literal -.Cr $ -in a here document when an unquoted end-of-file marker is being used, -enter it as -.Cr $$ . -.PP -Additionally, -.I rc -supports ``here strings'', which are like here documents, -except that input is taken directly from a string on the command line. -Its use is illustrated here: -.Ds -.Cr "cat <<< 'this is a here string' | wc" -.De -.PP -(This feature enables -.I rc -to export functions using here documents into the environment; -the author does not expect users to find this feature useful.) -.SS Pipes -Two or more commands may be combined in a pipeline by placing the -vertical bar -.Rc ( \||\| ) -between them. -The standard output (file descriptor 1) -of the command on the left is tied to the standard input (file -descriptor 0) of the command on the right. -The notation -.Ci |[ n = m ] -indicates that file descriptor -.I n -of the left process is connected to -file descriptor -.I m -of the right process. -.Ci |[ n ] -is a shorthand for -.Ci |[ n =0]\fR. -As an example, to pipe the standard error of a command to -.IR wc (1), -use: -.Ds -.Cr "command |[2] wc" -.De -.PP -The exit status of a pipeline is considered true if and only if every -command in the pipeline exits true. -.SS "Commands as Arguments" -Some commands, like -.IR cmp (1) -or -.IR diff (1), -take their arguments on the command -line, and do not read input from standard input. -It is convenient -sometimes to build nonlinear pipelines so that a command like -.I cmp -can read the output of two other commands at once. -.I rc -does it like this: -.Ds -.Cr "cmp <{command} <{command}" -.De -.PP -compares the output of the two commands in braces. -A note: since this form of -redirection is implemented with some kind of pipe, and since one cannot -.IR lseek (2) -on a pipe, commands that use -.IR lseek (2) -will hang. -For example, -most versions of -.IR diff (1) -use -.IR lseek (2) -on their inputs. -.PP -Data can be sent down a pipe to several commands using -.IR tee (1) -and the output version of this notation: -.Ds -.Cr "echo hi there | tee >{sed 's/^/p1 /'} >{sed 's/^/p2 /'}" -.De -.SH "CONTROL STRUCTURES" -The following may be used for control flow in -.IR rc : -.SS "If-else Statements" -.PD 0 -.sp -.Ci "if (" test ") {" -.br -.I " cmd" -.br -.TP -.Ci "} else " cmd -The -.I test -is executed, and if its return status is zero, the first -command is executed, otherwise the second is. -Braces are not mandatory around the commands. -However, an -.Cr else -statement is valid only if it -follows a close-brace on the same line. -Otherwise, the -.Cr if -is taken to be a simple-if: -.Ds -.Cr "if (test)" -.Cr " command" -.De -.PD -.SS "While and For Loops" -.TP -.Ci "while (" test ) " cmd" -.I rc -executes the -.I test -and performs the command as long as the -.I test -is true. -.TP -.Ci "for (" var " in" " list" ) " cmd" -.I rc -sets -.I var -to each element of -.I list -(which may contain variables and backquote substitutions) and runs -.IR cmd . -If -.Rc `` in -.IR list '' -is omitted, then -.I rc -will set -.I var -to each element of -.Cr $* -(excluding -.Cr $0 ). -For example: -.Ds -.Cr "for (i in \`{ls -F | grep '\e*$' | sed 's/\e*$//'}) { commands }" -.De -.TP -\& -will set -.Cr $i -to the name of each file in the current directory that is -executable. -.SS "Switch" -.TP -.Ci "switch (" list ") { case" " ..." " }" -.I rc -looks inside the braces after a -.Cr switch -for statements beginning with the word -.Cr case . -If any of the patterns following -.Cr case -match the list supplied to -.Cr switch , -then the commands up until the next -.Cr case -statement are executed. -The metacharacters -.Cr "*" , -.Cr [ -or -.Cr ? -should not be quoted; -matching is performed only against the strings in -.IR list , -not against file names. -(Matching for case statements is the same as for the -.Cr ~ -command.) -.SS "Logical Operators" -There are a number of operators in -.I rc -which depend on the exit status of a command. -.Ds -.Cr "command && command" -.De -.PP -executes the first command and then executes the second command if and only if -the first command exits with a zero exit status (``true'' in Unix). -.Ds -.Cr "command || command" -.De -.PP -executes the first command and then executes the second command if and only if -the first command exits with a nonzero exit status (``false'' in Unix). -.Ds -.Cr "! command" -.De -.PP -negates the exit status of a command. -.SH "PATTERN MATCHING" -There are two forms of pattern matching in -.IR rc . -One is traditional shell globbing. -This occurs in matching for file names in argument lists: -.Ds -.Cr "command argument argument ..." -.De -.PP -When the characters -.Cr "*" , -.Cr [ -or -.Cr ? -occur in an argument or command, -.I rc -looks at the -argument as a pattern for matching against files. -(Contrary to the behavior other shells exhibit, -.I rc -will only perform pattern matching if a metacharacter occurs unquoted and -literally in the input. -Thus, -.Ds -.Cr "foo='*'" -.Cr "echo $foo" -.De -.PP -will always echo just a star. -In order for non-literal metacharacters to be expanded, an -.Cr eval -statement must be used in order to rescan the input.) -Pattern matching occurs according to the following rules: a -.Cr * -matches any number (including zero) of -characters. -A -.Cr ? -matches any single character, and a -.Cr [ -followed by a -number of characters followed by a -.Cr ] -matches a single character in that -class. -The rules for character class matching are the same as those for -.IR ed (1), -with the exception that character class negation is achieved -with the tilde -.Rc ( ~ ), -not the caret -.Rc ( ^ ), -since the caret already means -something else in -.IR rc . -.PP -.I rc -also matches patterns against strings with the -.Cr ~ -command: -.Ds -.Cr "~ subject pattern pattern ..." -.De -.PP -.Cr ~ -sets -.Cr $status -to zero if and only if a supplied pattern matches any -single element of the subject list. -Thus -.Ds -.Cr "~ foo f*" -.De -.PP -sets status to zero, while -.Ds -.Cr "~ (bar baz) f*" -.De -.PP -sets status to one. -The null list is matched by the null list, so -.Ds -.Cr "~ $foo ()" -.De -.PP -checks to see whether -.Cr $foo -is empty or not. -This may also be achieved -by the test -.Ds -.Cr "~ $#foo 0" -.De -.PP -Note that inside a -.Cr ~ -command -.I rc -does not match patterns against file -names, so it is not necessary to quote the characters -.Cr "*" , -.Cr [ -and -.Cr "?" . -However, -.I rc -does expand the glob the subject against filenames if it contains -metacharacters. -Thus, the command -.Ds -.Cr "~ * ?" -.De -.PP -returns true if any of the files in the current directory have a -single-character name. -(Note that if the -.Cr ~ -command is given a list as its first -argument, then a successful match against any of the elements of that -list will cause -.Cr ~ -to return true. -For example: -.Ds -.Cr "~ (foo goo zoo) z*" -.De -.PP -is true.) -.SH "LISTS AND VARIABLES" -The primary data structure in -.IR rc -is the list, which is a sequence of words. -Parentheses are used to group lists. -The empty list is represented by -.Cr "()" . -Lists have no hierarchical structure; -a list inside another list is expanded so the -outer list contains all the elements of the inner list. -Thus, the following are all equivalent -.Ds -.Cr "one two three" - -.Cr "(one two three)" - -.Cr "((one) () ((two three)))" -.De -.PP -Note that the null string, -.Cr "''" , -and the null list, -.Cr "()" , -are two very -different things. -Assigning the null string to variable is a valid -operation, but it does not remove its definition. -For example, -if -.Cr $a -is set to -.Cr "''" , -then -.Cr "$#a" , -returns a 1. -.SS "List Concatenation" -Two lists may be joined by the concatenation operator -.Rc ( ^ ). -A single word is treated as a list of length one, so -.Ds -.Cr "echo foo^bar" -.De -.PP -produces the output -.Ds -.Cr foobar -.De -.PP -For lists of more than one element, -concatenation works according to the following rules: -if the two lists have the same number of elements, -then concatenation is pairwise: -.Ds -.Cr "echo (a\- b\- c\-)^(1 2 3)" -.De -.PP -produces the output -.Ds -.Cr "a\-1 b\-2 c\-3" -.De -.PP -Otherwise, one of the lists must have a single element, -and then the concatenation is distributive: -.Ds -.Cr "cc \-^(O g c) (malloc alloca)^.c" -.De -.PP -has the effect of performing the command -.Ds -.Cr "cc \-O \-g \-c malloc.c alloca.c" -.De -.SS "Free Carets" -.I rc -inserts carets (concatenation operators) for free in certain situations, -in order to save some typing on the user's behalf. -For -example, the above example could also be typed in as: -.Ds -.Cr "opts=(O g c) files=(malloc alloca) cc \-$opts $files.c" -.De -.PP -.I rc -takes care to insert a free-caret between the -.Rc `` \- '' -and -.Cr "$opts" , -as well -as between -.Cr $files -and -.Cr ".c" . -The rule for free carets is as follows: if -a word or keyword is immediately -followed by another word, keyword, dollar-sign or -backquote, then -.I rc -inserts a caret between them. -.SS "Variables" -A list may be assigned to a variable, using the notation: -.Ds -.Ic var " = " list -.De -.PP -Any sequence of non-special characters, except a sequence including -only digits, may be used as a variable name. -All user-defined variables are exported into the environment. -.PP -The value of a variable is referenced with the notation: -.Ds -.Ci $ var -.De -.PP -Any variable which has not been assigned a value returns the null list, -.Cr "()" , -when referenced. -In addition, multiple references are allowed: -.Ds -.Cr a=foo -.Cr b=a -.Cr "echo $$b" -.De -.PP -prints -.Ds -.Cr foo -.De -.PP -A variable's definition may also be removed by -assigning the null list to a variable: -.Ds -.Ic var =() -.De -.PP -For ``free careting'' to work correctly, -.I rc -must make certain assumptions -about what characters may appear in a variable name. -.I rc -assumes that a variable name consists only of alphanumeric characters, -underscore -.Rc ( \|_\| ) -and star -.Rc ( * ). -To reference a variable with other -characters in its name, quote the variable name. -Thus: -.Ds -.Cr "echo $'we$Ird\Variab!le'" -.De -.SS "Local Variables" -Any number of variable assignments may be made local to a single -command by typing: -.Ds -.Cr "a=foo b=bar ... command" -.De -.PP -The command may be a compound command, so for example: -.Ds -.Cr "path=. ifs=() {" -.Cr " " ... -.Cr } -.De -.PP -sets -.Cr path -to -.Cr . -and removes -.Cr ifs -for the duration of one long compound command. -.SS "Variable Subscripts" -Variables may be subscripted with the notation -.Ds -.Ci $var( n ) -.De -.PP -where -.I n -is a list of integers (origin 1). -The list of subscripts need -not be in order or even unique. -Thus, if -.Ds -.Cr "a=(one two three)" -.De -.PP -then -.Ds -.Cr "echo $a(3 3 3)" -.De -.PP -prints -.Ds -.Cr "three three three" -.De -.PP -If -.I n -references a nonexistent element, then -.Ci $var( n ) -returns the null list. -The notation -.Ci "$" n\fR, -where -.I n -is an integer, is a shorthand for -.Ci $*( n )\fR. -Thus, -.IR rc 's -arguments may be referred to as -.Cr "$1" , -.Cr "$2" , -and so on. -.PP -Note also that the list of subscripts may be given by any of -.IR rc 's -list operations: -.Ds -.Cr "$var(\`{awk 'BEGIN{for(i=1;i<=10;i++)print i;exit; }'})" -.De -.PP -returns the first 10 elements of -.Cr $var . -.PP -To count the number of elements in a variable, use -.Ds -.Cr $#var -.De -.PP -This returns a single-element list, with the number of elements in -.Cr $var . -.SS "Flat Lists" -In order to create a single-element list from a multi-element list, -with the components space-separated, use -.Ds -.Cr $^var -.De -.PP -This is useful when the normal list concatenation rules need to be -bypassed. -For example, to append a single period at the end of -.Cr $path , -use: -.Ds -.Cr "echo $^path." -.De -.SS "Backquote Substitution" -A list may be formed from the output of a command by using backquote -substitution: -.Ds -.Cr "\`{ command }" -.De -.PP -returns a list formed from the standard output of the command in braces. -.Cr $ifs -is used to split the output into list elements. -By default, -.Cr $ifs -has the value space-tab-newline. -The braces may be omitted if the command is a single word. -Thus -.Cr \`ls -may be used instead of -.Cr "\`{ls}" . -This last feature is useful when defining functions that expand -to useful argument lists. -A frequent use is: -.Ds -.Cr "fn src { echo *.[chy] }" -.De -.PP -followed by -.Ds -.Cr "wc \`src" -.De -.PP -(This will print out a word-count of all C source files in the current -directory.) -.PP -In order to override the value of -.Cr $ifs -for a single backquote -substitution, use: -.Ds -.Cr "\`\` (ifs-list) { command }" -.De -.PP -.Cr $ifs -will be temporarily ignored and the command's output will be split as specified by -the list following the double backquote. -For example: -.Ds -.Cr "\`\` ($nl :) {cat /etc/passwd}" -.De -.PP -splits up -.Cr /etc/passwd -into fields, assuming that -.Cr $nl -contains a newline -as its value. -.SH "SPECIAL VARIABLES" -Several variables are known to -.I rc -and are treated specially. -.TP -.Cr * -The argument list of -.IR rc . -.Cr "$1, $2," -etc. are the same as -.Cr $*(1) , -.Cr $*(2) , -etc. -The variable -.Cr $0 -holds the value of -.Cr argv[0] -with which -.I rc -was invoked. -Additionally, -.Cr $0 -is set to the name of a function for the duration of -the execution of that function, and -.Cr $0 -is also set to the name of the -file being interpreted for the duration of a -.Cr . -command. -.TP -.Cr apid -The process ID of the last process started in the background. -.TP -.Cr apids -The process IDs of any background processes which are outstanding -or which have died and have not been waited for yet. -.TP -.Cr cdpath -A list of directories to search for the target of a -.B cd -command. -The empty string stands for the current directory. -Note that if the -.Cr $cdpath -variable does not contain the current directory, then the current -directory will not be searched; this allows directory searching to -begin in a directory other than the current directory. -Note also that an assignment to -.Cr $cdpath -causes an automatic assignment to -.Cr $CDPATH , -and vice-versa. -.TP -.Cr history -.Cr $history -contains the name of a file to which commands are appended as -.I rc -reads them. -This facilitates the use of a stand-alone history program -(such as -.IR history (1)) -which parses the contents of the history file and presents them to -.I rc -for reinterpretation. -If -.Cr $history -is not set, then -.I rc -does not append commands to any file. -.TP -.Cr home -The default directory for the builtin -.B cd -command and is the directory -in which -.I rc -looks to find its initialization file, -.Cr .rcrc , -if -.I rc -has been started up as a login shell. -Like -.Cr $cdpath -and -.Cr $CDPATH , -.Cr $home -and -.Cr $HOME -are aliased to each other. -.TP -.Cr ifs -The internal field separator, used for splitting up the output of -backquote commands for digestion as a list. -.TP -.Cr path -This is a list of directories to search in for commands. -The empty string stands for the current directory. -Note that like -.Cr $cdpath -and -.Cr $CDPATH , -.Cr $path -and -.Cr $PATH -are aliased to each other. -If -.Cr $path -or -.Cr $PATH -is not set at startup time, -.Cr $path -assumes a default value suitable for your system. -This is typically -.Cr "(/usr/ucb /usr/bin /bin .)" -.TP -.Cr pid -The process ID of the currently running -.IR rc . -.TP -.Cr prompt -This variable holds the two prompts (in list form, of course) that -.I rc -prints. -.Cr $prompt(1) -is printed before each command is read, and -.Cr $prompt(2) -is printed when input is expected to continue on the next -line. -.I rc -sets -.Cr $prompt -to -.Cr "('; ' '')" -by default. -The reason for this is that it enables an -.I rc -user to grab commands from previous lines using a -mouse, and to present them to -.I rc -for re-interpretation; the semicolon -prompt is simply ignored by -.IR rc . -The null -.Cr $prompt(2) -also has its -justification: an -.I rc -script, when typed interactively, will not leave -.Cr $prompt(2) 's -on the screen, -and can therefore be grabbed by a mouse and placed -directly into a file for use as a shell script, without further editing -being necessary. -.TP -.Cr prompt " (function)" -If this function is set, then it gets executed every time -.I rc -is about to print -.Cr "$prompt(1)" . -.TP -.Cr status -The exit status of the last command. -If the command exited with a numeric value, -that number is the status. -If the died with a signal, -the status is the name of that signal; if a core file -was created, the string -.Rc `` +core '' -is appended. -The value of -.Cr $status -for a pipeline is a list, with one entry, -as above, for each process in the pipeline. -For example, the command -.Ds -.Cr "ls | wc" -.De -.TP -\& -usually sets -.Cr $status -to -.Cr "(0 0)" . -.PP -The values of -.Cr "$path" , -.Cr "$cdpath" , -and -.Cr $home -are derived from the environment -values of -.Cr "$PATH" , -.Cr "$CDPATH" , -and -.Cr "$HOME" . -Otherwise, they are derived from -the environment values of -.Cr $path , -.Cr $cdpath -and -.Cr $home . -This is for compatibility with other Unix programs, like -.IR sh (1). -.Cr $PATH -and -.Cr $CDPATH -are assumed to be colon-separated lists. -.SH FUNCTIONS -.I rc -functions are identical to -.I rc -scripts, except that they are stored -in memory and are automatically exported into the environment. -A shell function is declared as: -.Ds -.Cr "fn name { commands }" -.De -.PP -.I rc -scans the definition until the close-brace, so the function can -span more than one line. -The function definition may be removed by typing -.Ds -.Cr "fn name" -.De -.PP -(One or more names may be specified. -With an accompanying definition, all names receive the same definition. -This is sometimes useful -for assigning the same signal handler to many signals. -Without a definition, all named functions are deleted.) -When a function is executed, -.Cr $* -is set to the arguments to that -function for the duration of the command. -Thus a reasonable definition for -.Cr "l" , -a shorthand for -.IR ls (1), -could be: -.Ds -.Cr "fn l { ls -FC $* }" -.De -.PP -but not -.Ds -.Cr "fn l { ls -FC }" -.De -.SH "INTERRUPTS AND SIGNALS" -.I rc -recognizes a number of signals, and allows the user to define shell -functions which act as signal handlers. -.I rc -by default traps -.Cr SIGINT -when it is in interactive mode. -.Cr SIGQUIT -and -.Cr SIGTERM -are ignored, unless -.I rc -has been invoked with the -.Cr \-d -flag. -However, user-defined signal handlers may be written for these and -all other signals. -The way to define a signal handler is to -write a function by the name of the signal in lower case. -Thus: -.Ds -.Cr "fn sighup { echo hangup; rm /tmp/rc$pid.*; exit }" -.De -.PP -In addition to Unix signals, -.I rc -recognizes the artificial signal -.Cr SIGEXIT -which occurs as -.I rc -is about to exit. -.PP -In order to remove a signal handler's definition, -remove it as though it were a regular function. -For example: -.Ds -.Cr "fn sigint" -.De -.PP -returns the handler of -.Cr SIGINT -to the default value. -In order to ignore a signal, set the signal handler's value to -.Cr "{}" . -Thus: -.Ds -.Cr "fn sigint {}" -.De -.PP -causes SIGINT to be ignored by the shell. -Only signals that are being ignored are passed on to programs run by -.IR rc ; -signal functions are not exported. -.PP -On System V-based Unix systems, -.I rc -will not allow you to trap -.Cr SIGCLD . -.SH "BUILTIN COMMANDS" -Builtin commands execute in the context of the shell, but otherwise -behave exactly like other commands. -Although -.BR ! , -.B ~ -and -.B @ -are not strictly speaking builtin commands, -they can usually be used as such. -.TP -\&\fB.\fR [\fB\-i\fR] \fIfile \fR[\fIarg ...\fR] -Reads -.I file -as input to -.IR rc -and executes its contents. -With a -.Cr \-i -flag, input is interactive. -Thus from within a shell script, -.Ds -.Cr ". \-i /dev/tty" -.De -.TP -\& -does the ``right'' thing. -.TP -.B break -Breaks from the innermost -.Cr for -or -.Cr while , -as in C. -It is an error to invoke -.B break -outside of a loop. -(Note that there is no -.B break -keyword between commands in -.Cr switch -statements, unlike C.) -.TP -\fBbuiltin \fIcommand \fR[\fIarg ...\fR] -Executes the command ignoring any function definition of the -same name. -This command is present to allow functions with the -same names as builtins to use the underlying builtin or binary. -.TP -\fBcd \fR[\fIdirectory\fR] -Changes the current directory to -.IR directory . -The variable -.Cr $cdpath -is searched for possible locations of -.IR directory , -analogous to the searching of -.Cr $path -for executable files. -With no argument, -.B cd -changes the current directory to -.Cr "$home" . -.TP -\fBecho \fR[\fB\-n\fR] [\fB\-\|\-\fR] [\fIarg ...\fR] -Prints its arguments to standard output, terminated by a newline. -Arguments are separated by spaces. -If the first argument is -.Cr "\-n" -no final newline is printed. -If the first argument is -.Cr "\-\|\-" , -then all other arguments are echoed literally. -This is used for echoing a literal -.Cr "\-n" . -.TP -\fBeval \fR[\fIlist\fR] -Concatenates the elements of -.I list -with spaces and feeds the resulting string to -.I rc -for re-scanning. -This is the only time input is rescanned in -.IR rc . -.TP -\fBexec \fR[\fIarg ...\fR] -Replaces -.I rc -with the given command. -If the exec contains only redirections, -then these redirections apply to the current shell -and the shell does not exit. -For example, -.Ds -.Cr "exec >[2] err.out" -.De -.TP -\& -places further output to standard error in the file -.IR err.out . -.TP -\fBexit \fR[\fIstatus\fR] -Cause the current shell to exit with the given exit -.IR status . -If no argument is given, the current value of -.Cr $status -is used. -.TP -\fBlimit \fR[\fB\-h\fR] [\fIresource \fR[\fIvalue\fR]] -Similar to the -.IR csh (1) -.B limit -builtin, this command operates upon the -BSD-style limits of a process. -The -.Cr \-h -flag displays/alters the hard -limits. -The resources which can be shown or altered are -.BR cputime , -.BR filesize , -.BR datasize , -.BR stacksize , -.B coredumpsize -and -.BR memoryuse . -For -example: -.Ds -.Cr "limit coredumpsize 0" -.De -.TP -\& -disables core dumps. -.TP -.B newpgrp -Puts -.I rc -into a new process group. -This builtin is useful for making -.I rc -behave like a job-control shell in a hostile environment. -One example is the NeXT Terminal program, which implicitly assumes -that each shell it forks will put itself into a new process group. -.TP -\fBreturn \fR[\fIn\fR] -Returns from the current function, with status -.IR n , -where -.IR n -is a single value or a list of possible exit statuses. -Thus it is legal to have -.Ds -.Cr "return (sigpipe 1 2 3)" -.De -.TP -\& -(This is commonly used to allow a function to return with the exit status -of a previously executed pipeline of commands.) -If -.IR n -is omitted, then -.Cr $status -is left unchanged. -It is an error to invoke -.B return -when not inside a function. -.TP -\fBshift \fR[\fIn\fR] -Deletes -.I n -elements from the beginning of -.Cr $* -and shifts the other -elements down by -.IR n . -.I n -defaults to 1. -(Note that -.Cr $0 -is not affected by -.BR shift .) -.TP -\fBumask \fR[\fImask\fR] -Sets the current umask (see -.IR umask (2)) -to the octal -.IR mask . -If no argument is present, the current mask value is printed. -.TP -\fBwait \fR[\fIpid\fR] -Waits for the specified -.IR pid , -which must have been started by -.IR rc . -If no -.I pid -is specified, -.I rc -waits for all child processes to exit. -.TP -\fBwhatis \fR[\fB\-s\fR] [\fB\-\|\-\fR] [\fIname ...\fR] -Prints a definition of the named objects. -For variables, their values -are printed; for functions, their definitions are; and for executable -files, path names are printed. -Without arguments, -.B whatis -prints the values of all shell variables and functions. -With a -.Cr \-s -argument, -.B whatis -also prints out a list of available signals and their handlers (if any). -Note that -.B whatis -output is suitable for input to -.IR rc ; -by saving the output of -.B whatis -in a file, it should be possible to recreate the state of -.I rc -by sourcing this file with a -.Cr . -command. -Another note: -.Cr "whatis -s > file" -cannot be used to store the state of -.IR rc 's -signal handlers in a file, because builtins with redirections -are run in a subshell, and -.I rc -always restores signal handlers to their default value after a -.Cr fork() . -.TP -\& -Since -.B whatis -uses -.IR getopt (3) -to parse its arguments, you can use the special argument -.Cr "\-\|\-" -to terminate its options. -This allows you to use names beginning with a dash, such as -the -.IR history (1) -commands. -For example, -.Ds -.Cr "whatis \-\|\- \-p" -.De -.SH GRAMMAR -Here is -.IR rc 's -grammar, edited to remove semantic actions. -.Ds -.ft \*(Cf -%term ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN -%term OROR PIPE REDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH - -%left WHILE ')' ELSE -%left ANDAND OROR '\en' -%left BANG SUBSHELL -%left PIPE -%right '$' -%left SUB - -%start rc - -%% - -rc: line end - | error end - -end: END /* EOF */ | '\en' - -cmdsa: cmd ';' | cmd '&' - -line: cmd | cmdsa line - -body: cmd | cmdsan body - -cmdsan: cmdsa | cmd '\en' - -brace: '{' body '}' - -paren: '(' body ')' - -assign: first '=' word - -epilog: /* empty */ | redir epilog - -redir: DUP | REDIR word - -case: CASE words ';' | CASE words '\en' - -cbody: cmd | case cbody | cmdsan cbody - -iftail: cmd %prec ELSE - | brace ELSE optnl cmd - -cmd : /* empty */ %prec WHILE - | simple - | brace epilog - | IF paren optnl iftail - | FOR '(' word IN words ')' optnl cmd - | FOR '(' word ')' optnl cmd - | WHILE paren optnl cmd - | SWITCH '(' word ')' optnl '{' cbody '}' - | TWIDDLE optcaret word words - | cmd ANDAND optnl cmd - | cmd OROR optnl cmd - | cmd PIPE optnl cmd - | redir cmd %prec BANG - | assign cmd %prec BANG - | BANG optcaret cmd - | SUBSHELL optcaret cmd - | FN words brace - | FN words - -optcaret: /* empty */ | '^' - -simple: first | simple word | simple redir - -first: comword | first '^' sword - -sword: comword | keyword - -word: sword | word '^' sword - -comword: '$' sword - | '$' sword SUB words ')' - | COUNT sword - | FLAT sword - | '`' sword - | '`' brace - | BACKBACK word brace | BACKBACK word sword - | '(' words ')' - | REDIR brace - | WORD - -keyword: FOR | IN | WHILE | IF | SWITCH - | FN | ELSE | CASE | TWIDDLE | BANG | SUBSHELL - -words: /* empty */ | words word - -optnl: /* empty */ | optnl '\en' -.ft R -.De -.SH FILES -.Cr $HOME/.rcrc , -.Cr /tmp/rc* , -.Cr /dev/null -.SH CREDITS -.I rc -was written by Byron Rakitzis, with valuable help -from Paul Haahr, Hugh Redelmeier and David Sanderson. -The design of this shell has been copied from the -.I rc -that Tom Duff wrote at Bell Labs. -.SH BUGS -On systems that support -.Cr /dev/fd , -.Cr <{foo} -style redirection is implemented that way. -However, on other systems it is implemented with named pipes, -and it is sometimes -possible to foil -.I rc -into removing the FIFO it places in -.Cr /tmp -prematurely, or it is even possible to cause -.I rc -to hang. -.PP -The functionality of -.B shift -should be available for variables other than -.Cr "$*" . -.PP -.B echo -is built in only for performance reasons, which is a bad idea. -.PP -There should be a way to avoid exporting a variable. -.PP -The -.Cr $^var -notation for flattening should allow for using an arbitrary -separating character, not just space. -.PP -Bug reports should be mailed to -.Cr "byron@archone.tamu.edu" . -.SH INCOMPATIBILITIES -Here is a list of features which distinguish this incarnation of -.I rc -from the one described in the Bell Labs manual pages: -.PP -The treatment of -.Cr if - else -is different in the v10 -.IR rc : -that version uses an -.Cr "if not" -clause which gets executed -if the preceding -.Cr if -test does not succeed. -.PP -Backquotes are slightly different in v10 -.IR rc : -a backquote must always be followed by a left-brace. -This restriction is not present for single-word commands in this -.IR rc . -.PP -The following are all new with this version of -.IR rc : -The -.Cr \-n -option, -the list flattening operator, -here strings (they facilitate exporting of functions -with here documents into the environment), -the -.B return -and -.B break -keywords, -the -.B echo -builtin, -the support for the GNU -.IR readline (3) -library and -the support for the -.Cr prompt -function. -This -.I rc -also sets -.Cr $0 -to the name of a function being executed/file -being sourced. -.SH "SEE ALSO" -``rc \(em A Shell for Plan 9 and UNIX Systems'', -Unix Research System, -10th Edition, -vol. 2. (Saunders College Publishing) -(This paper is also distributed with this -.I rc -in PostScript form.) -.PP -.IR history (1) diff --git a/rc.h b/rc.h @@ -1,406 +0,0 @@ -#include "config.h" - -#if HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#if HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include "proto.h" - -/* datatypes */ - -/* braindamaged IBM header files #define true and false */ -#undef FALSE -#undef TRUE - -#include <stdarg.h> - -#if HAVE_SETPGRP - -#if SETPGRP_VOID -/* Smells like POSIX: should all be ok. */ -#else -/* BSD: fake it. */ -#define setpgid(pid, pgrp) setpgrp(pid, pgrp) -#define tcsetpgrp(fd, pgrp) ioctl((fd), TIOCSPGRP, &(pgrp)) -#endif - -#else /* HAVE_SETPGRP */ - -/* Nothing doing. */ -#define setpgid -#define tcsetpgrp - -#endif /*HAVE_SETPGRP */ - -typedef void builtin_t(char **); -typedef struct Block Block; -typedef struct Dup Dup; -typedef struct Estack Estack; -typedef struct Function Function; -typedef struct Hq Hq; -typedef struct Htab Htab; -typedef struct Jbwrap Jbwrap; -typedef struct List List; -typedef struct Node Node; -typedef struct Pipe Pipe; -typedef struct Redir Redir; -typedef struct Rq Rq; -typedef struct Variable Variable; -typedef struct Word Word; -typedef struct Format Format; -typedef union Edata Edata; - -typedef enum nodetype { - nAndalso, nAssign, nBackq, nBang, nBody, nCbody, nNowait, nBrace, nConcat, - nCount, nElse, nFlat, nDup, nEpilog, nNewfn, nForin, nIf, nQword, - nOrelse, nPipe, nPre, nRedir, nRmfn, nArgs, nSubshell, nCase, - nSwitch, nMatch, nVar, nVarsub, nWhile, nWord, nLappend, nNmpipe -} nodetype; - -typedef enum ecodes { - eError, eBreak, eReturn, eVarstack, eArena, eFifo, eFd -} ecodes; - -typedef enum bool { - FALSE, TRUE -} bool; - -typedef enum inputtype { - iFd, iString -} inputtype; - -typedef enum redirtype { - rFrom, rCreate, rAppend, rHeredoc, rHerestring -} redirtype; - -typedef bool (*Conv)(Format *, int); - -union Edata { - Jbwrap *jb; - Block *b; - char *name; - int fd; -}; - -struct Estack { - ecodes e; - bool interactive; - Edata data; - Estack *prev; -}; - -struct List { - char *w, *m; - List *n; -}; - -struct Node { - nodetype type; - union { - char *s; - int i; - Node *p; - } u[4]; -}; - -struct Pipe { - int left, right; -}; - -struct Dup { - redirtype type; - int left, right; -}; - -struct Redir { - redirtype type; - int fd; -}; - -struct Word { - char *w, *m; -}; - -struct Rq { - Node *r; - struct Rq *n; -}; - -struct Function { - Node *def; - char *extdef; -}; - -struct Variable { - List *def; - char *extdef; - Variable *n; -}; - -struct Htab { - char *name; - void *p; -}; - -struct Format { - /* for the formatting routines */ - va_list args; - long flags, f1, f2; - /* for the buffer maintainence routines */ - char *buf, *bufbegin, *bufend; - int flushed; - void (*grow)(Format *, size_t); - union { int n; void *p; } u; -}; - -/* Format->flags values */ -enum { - FMT_quad = 1, /* %q */ - FMT_long = 2, /* %l */ - FMT_short = 4, /* %h */ - FMT_unsigned = 8, /* %u */ - FMT_zeropad = 16, /* %0 */ - FMT_leftside = 32, /* %- */ - FMT_altform = 64, /* %# */ - FMT_f1set = 128, /* %<n> */ - FMT_f2set = 256 /* %.<n> */ -}; - -/* macros */ -#define EOF (-1) -#ifndef NULL -#define NULL 0 -#endif -#define a2u(x) n2u(x, 10) -#define o2u(x) n2u(x, 8) -#define arraysize(a) ((int)(sizeof(a)/sizeof(*a))) -#define memzero(s, n) memset(s, 0, n) -#define enew(x) ((x *) ealloc(sizeof(x))) -#define ecpy(x) strcpy((char *) ealloc(strlen(x) + 1), x) -#define lookup_fn(s) ((Function *) lookup(s, fp)) -#define lookup_var(s) ((Variable *) lookup(s, vp)) -#define nnew(x) ((x *) nalloc(sizeof(x))) -#define ncpy(x) (strcpy((char *) nalloc(strlen(x) + 1), x)) -#ifndef offsetof -#define offsetof(t, m) ((size_t) (((char *) &((t *) 0)->m) - (char *)0)) -#endif -#define streq(x, y) (*(x) == *(y) && strcmp(x, y) == 0) -#define conststrlen(x) (sizeof (x) - 1) - -/* rc prototypes */ - -/* main.c */ -extern char *prompt, *prompt2; -extern Rq *redirq; -extern bool dashdee, dashee, dashvee, dashex, dashell, - dasheye, dashen, dashpee, interactive; -extern pid_t rc_pid; -extern int lineno; - -/* builtins.c */ -extern builtin_t *isbuiltin(char *); -extern void b_exec(char **), funcall(char **), b_dot(char **), b_builtin(char **); -extern char *which(char *, bool); - -/* except.c */ -extern bool nl_on_intr; -extern bool outstanding_cmdarg(void); -extern void pop_cmdarg(bool); -extern void rc_raise(ecodes); -extern void except(ecodes, Edata, Estack *); -extern void unexcept(void); -extern void rc_error(char *); -extern void sigint(int); - -/* exec.c */ -extern void exec(List *, bool); -extern void doredirs(void); - -/* footobar.c */ -extern char **list2array(List *, bool); -extern char *get_name(char *); -extern List *parse_var(char *, char *); -extern Node *parse_fn(char *, char *); -extern void initprint(void); -extern void rc_exit(int); /* here for odd reasons; user-defined signal handlers are kept in fn.c */ - -/* getopt.c */ -extern int rc_getopt(int, char **, char *); - -extern int rc_optind, rc_opterr, rc_optopt; -extern char *rc_optarg; - -/* glob.c */ -extern bool lmatch(List *, List *); -extern List *glob(List *); - -/* glom.c */ -extern void assign(List *, List *, bool); -extern void qredir(Node *); -extern List *append(List *, List*); -extern List *flatten(List *); -extern List *glom(Node *); -extern List *concat(List *, List *); -extern List *varsub(List *, List *); -extern List *word(char *, char *); - -/* hash.c */ -extern Htab *fp, *vp; -extern void *lookup(char *, Htab *); -extern Function *get_fn_place(char *); -extern List *varlookup(char *); -extern Node *fnlookup(char *); -extern Variable *get_var_place(char *, bool); -extern bool varassign_string(char *); -extern char **makeenv(void); -extern char *fnlookup_string(char *); -extern char *varlookup_string(char *); -extern void alias(char *, List *, bool); -extern void starassign(char *, char **, bool); -extern void delete_fn(char *); -extern void delete_var(char *, bool); -extern void fnassign(char *, Node *); -extern void fnassign_string(char *); -extern void fnrm(char *); -extern void initenv(char **); -extern void inithash(void); -extern void setsigdefaults(bool); -extern void inithandler(void); -extern void varassign(char *, List *, bool); -extern void varrm(char *, bool); -extern void whatare_all_vars(bool, bool); -extern void whatare_all_signals(void); -extern void prettyprint_var(int, char *, List *); -extern void prettyprint_fn(int, char *, Node *); - -/* heredoc.c */ -extern int heredoc(int); -extern int qdoc(Node *, Node *); -extern Hq *hq; - -/* input.c */ -extern void initinput(void); -extern Node *parseline(char *); -extern int gchar(void); -extern void ugchar(int); -extern Node *doit(bool); -extern void flushu(void); -extern void pushfd(int); -extern void pushstring(char **, bool); -extern void popinput(void); -extern void closefds(void); -extern int last; -extern bool rcrc; - -/* lex.c */ -extern int yylex(void); -extern void inityy(void); -extern void yyerror(const char *); -extern void scanerror(char *); -extern void print_prompt2(void); -extern const char nw[], dnw[]; - -/* list.c */ -extern void listfree(List *); -extern List *listcpy(List *, void *(*)(size_t)); -extern size_t listlen(List *); -extern int listnel(List *); - -/* match.c */ -extern bool match(char *, char *, char *); - -/* alloc.c */ -extern void *ealloc(size_t); -extern void *erealloc(void *, size_t); -extern void efree(void *); -extern Block *newblock(void); -extern void *nalloc(size_t); -extern void nfree(void); -extern void restoreblock(Block *); - -/* open.c */ -extern int rc_open(const char *, redirtype); - -/* print.c */ -/* - The following prototype should be: -extern Conv fmtinstall(int, Conv); - but this freaks out SGI's compiler under IRIX3.3.2 -*/ -extern bool (*fmtinstall(int, bool (*)(Format *, int)))(Format *, int); -extern int printfmt(Format *, const char *); -extern int fmtprint(Format *, const char *,...); -extern void fmtappend(Format *, const char *, size_t); -extern void fmtcat(Format *, const char *); -extern int fprint(int fd, const char *fmt,...); -extern char *mprint(const char *fmt,...); -extern char *nprint(const char *fmt,...); -/* - the following macro should by rights be coded as an expression, not - a statement, but certain compilers (notably DEC) have trouble with - void expressions inside the ?: operator. (sheesh, give me a break!) -*/ -#define fmtputc(f, c) {\ - if ((f)->buf >= (f)->bufend)\ - (*(f)->grow)((f), (size_t)1);\ - *(f)->buf++ = (c);\ -} - -/* y.tab.c (parse.y) */ -extern Node *parsetree; -extern int yyparse(void); -extern void initparse(void); - -/* redir.c */ -extern void doredirs(void); - -/* signal.c */ -extern void initsignal(void); -extern void catcher(int); -extern void sigchk(void); -extern void (*rc_signal(int, void (*)(int)))(int); -extern void (*sighandlers[])(int); -extern volatile SIG_ATOMIC_T slow, interrupt_happened; - -/* status.c */ -extern int istrue(void); -extern int getstatus(void); -extern void set(bool); -extern void setstatus(pid_t, int); -extern List *sgetstatus(void); -extern void setpipestatus(int [], int); -extern void statprint(pid_t, int); -extern void ssetstatus(char **); -extern char *strstatus(int s); - -/* tree.c */ -extern Node *mk(int /*nodetype*/,...); -extern Node *treecpy(Node *, void *(*)(size_t)); -extern void treefree(Node *); - -/* utils.c */ -extern bool isabsolute(char *); -extern int n2u(char *, unsigned int); -extern int rc_read(int, char *, size_t); -extern int mvfd(int, int); -extern int starstrcmp(const void *, const void *); -extern void pr_error(char *); -extern void panic(char *); -extern void uerror(char *); -extern void writeall(int, char *, size_t); - -/* wait.c */ -extern pid_t rc_fork(void); -extern pid_t rc_wait4(pid_t, int *, bool); -extern List *sgetapids(void); -extern void waitforall(void); -extern bool forked; - -/* walk.c */ -extern bool walk(Node *, bool); -extern bool cond; - diff --git a/redir.c b/redir.c @@ -1,77 +0,0 @@ -/* redir.c: code for opening files and piping heredocs after fork but before exec. */ - -#include "rc.h" - -/* - Walk the redirection queue, and open files and dup2 to them. Also, - here-documents are treated here by dumping them down a pipe. (this - should make here-documents fast on systems with lots of memory which - do pipes right. Under sh, a file is copied to /tmp, and then read - out of /tmp again. I'm interested in knowing how much faster, say, - shar runs when unpacking when invoked with rc instead of sh. On my - sun4/280, it runs in about 60-75% of the time of sh for unpacking - the rc source distribution.) -*/ - -extern void doredirs() { - List *fname; - int fd, p[2]; - Rq *r; - for (r = redirq; r != NULL; r = r->n) { - switch(r->r->type) { - default: - panic("unexpected node in doredirs"); - /* NOTREACHED */ - case nRedir: - if (r->r->u[0].i == rHerestring) { - fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */ - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if (rc_fork() == 0) { /* child writes to pipe */ - setsigdefaults(FALSE); - close(p[0]); - if (fname != NULL) - writeall(p[1], fname->w, strlen(fname->w)); - exit(0); - } else { - close(p[1]); - if (mvfd(p[0], r->r->u[1].i) < 0) - rc_error(NULL); - } - } else { - fname = glob(glom(r->r->u[2].p)); - if (fname == NULL) - rc_error("null filename in redirection"); - if (fname->n != NULL) - rc_error("multi-word filename in redirection"); - switch (r->r->u[0].i) { - default: - panic("unexpected node in doredirs"); - /* NOTREACHED */ - case rCreate: case rAppend: case rFrom: - fd = rc_open(fname->w, r->r->u[0].i); - break; - } - if (fd < 0) { - uerror(fname->w); - rc_error(NULL); - } - if (mvfd(fd, r->r->u[1].i) < 0) - rc_error(NULL); - } - break; - case nDup: - if (r->r->u[2].i == -1) - close(r->r->u[1].i); - else if (r->r->u[2].i != r->r->u[1].i) { - if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) { - uerror("dup2"); - rc_error(NULL); - } - } - } - } - redirq = NULL; -} diff --git a/rlimit.h b/rlimit.h @@ -1,42 +0,0 @@ -/* What a mess. This file attempts to straighten everything out. */ - -#if HAVE_SETRLIMIT - -#if HAVE_SYS_RESOURCE_H -# include <sys/time.h> -# if RLIMIT_NEEDS_KERNEL -# define _KERNEL -# endif -# include <sys/resource.h> -# if RLIMIT_NEEDS_KERNEL -# undef _KERNEL -# endif -#else -# include <sys/times.h> -#endif - -#if HAVE_LIMITS_H -# include <limits.h> -#endif - -#ifndef HAVE_RLIM_T -# if RLIM_T_IS_QUAD_T -typedef quad_t rlim_t; -# else -typedef long rlim_t; -# endif -#endif - -#if HAVE_QUAD_T -# define RLIM_CONV quad_t -# define RLIM_FMT "%s \t%qd%s\n" -#else -# define RLIM_CONV long -# define RLIM_FMT "%s \t%ld%s\n" -#endif - -#if defined(RLIMIT_OFILE) && !defined (RLIMIT_NOFILE) -# define RLIMIT_NOFILE RLIMIT_OFILE -#endif - -#endif /* HAVE_SETRLIMIT */ diff --git a/signal.c b/signal.c @@ -1,80 +0,0 @@ -/* signal.c: a Hugh-approved signal handler. */ - -#include <signal.h> -#include <setjmp.h> -#include "rc.h" -#include "sigmsgs.h" -#include "jbwrap.h" - -Jbwrap slowbuf; -volatile SIG_ATOMIC_T slow, interrupt_happened; -void (*sighandlers[NUMOFSIGNALS])(int); - -static volatile SIG_ATOMIC_T sigcount, caught[NUMOFSIGNALS]; - -extern void catcher(int s) { - if (caught[s] == 0) { - sigcount++; - caught[s] = 1; - } - signal(s, catcher); - interrupt_happened = TRUE; -#ifndef HAVE_RESTARTABLE_SYSCALLS - if (slow) - longjmp(slowbuf.j, 1); -#endif -} - -extern void sigchk() { - void (*h)(int); - int s, i; - if (sigcount == 0) - return; /* ho hum; life as usual */ - if (forked) - exit(1); /* exit unconditionally on a signal in a child process */ - for (i = 0, s = -1; i < NUMOFSIGNALS; i++) - if (caught[i] != 0) { - s = i; - --sigcount; - caught[s] = 0; - break; - } - if (s == -1) - panic("all-zero sig vector with nonzero sigcount"); - if ((h = sighandlers[s]) == SIG_DFL) - panic("caught signal set to SIG_DFL"); - if (h == SIG_IGN) - panic("caught signal set to SIG_IGN"); - (*h)(s); -} - -extern void (*rc_signal(int s, void (*h)(int)))(int) { - void (*old)(int); - sigchk(); - old = sighandlers[s]; - if (h == SIG_DFL || h == SIG_IGN) { - signal(s, h); - sighandlers[s] = h; - } else { - sighandlers[s] = h; - signal(s, catcher); - } - return old; -} - -extern void initsignal() { - void (*h)(int); - int i; - for (i = 1; i < NUMOFSIGNALS; i++) { - if ((h = signal(i, SIG_DFL)) != SIG_DFL) - signal(i, h); - sighandlers[i] = h; - } - -#ifdef SIGCLD - /* Ensure that SIGCLD is not SIG_IGN. Solaris's rshd does this. :-( */ - h = signal(SIGCLD, SIG_DFL); - if (h != SIG_IGN) - signal(SIGCLD, h); -#endif -} diff --git a/status.c b/status.c @@ -1,147 +0,0 @@ -/* status.c: functions for printing fancy status messages in rc */ - -#include "rc.h" -#include "sigmsgs.h" - -/* status == the wait() value of the last command in the pipeline, or the last command */ - -static int statuses[512]; -static int pipelength = 1; - -/* - Test to see if rc's status is true. According to td, status is true - if and only if every pipe-member has an exit status of zero. -*/ - -extern int istrue() { - int i; - for (i = 0; i < pipelength; i++) - if (statuses[i] != 0) - return FALSE; - return TRUE; -} - -/* - Return the status as an integer. A status which has low-bits set is - a signal number, whereas a status with high bits set is a value set - from exit(). The presence of a signal just sets status to 1. Also, - a pipeline with nonzero exit statuses in it just sets status to 1. -*/ - -extern int getstatus() { - int s; - if (pipelength > 1) - return !istrue(); - s = statuses[0]; - return (s&0xff) ? 1 : (s >> 8) & 0xff; -} - -extern void set(bool code) { - setstatus(-1, (!code) << 8); /* exit status 1 == 0x100 */ -} - -/* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */ - -extern void setpipestatus(int stats[], int num) { - int i; - for (i = 0; i < (pipelength = num); i++) { - statprint(-1, stats[i]); - statuses[i] = stats[i]; - } -} - -/* set a simple status, as opposed to a pipeline */ - -extern void setstatus(pid_t pid, int i) { - pipelength = 1; - statuses[0] = i; - statprint(pid, i); -} - -/* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */ - -extern void statprint(pid_t pid, int i) { - if (i & 0xff) { - char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f].msg : ""); - if (pid != -1) - fprint(2, "%ld: ", (long)pid); - if (i & 0x80) { - if (*msg == '\0') - fprint(2, "core dumped\n"); - else - fprint(2, "%s--core dumped\n", msg); - } else if (*msg != '\0') - fprint(2, "%s\n", msg); - } - if (i != 0 && dashee && !cond) - rc_exit(getstatus()); -} - -/* prepare a list to be passed back. Used whenever $status is dereferenced */ - -extern List *sgetstatus() { - List *r = NULL; - int i; - - for (i = 0; i < pipelength; i++) { - List *q = nnew(List); - q->w = strstatus(statuses[i]); - q->m = NULL; - q->n = r; - r = q; - } - - return r; -} - -/* return status as a string (used above and for bqstatus) */ - -extern char *strstatus(int s) { - int t = s & 0x7f; - - if (t != 0) { - const char *core = (s & 0x80) ? "+core" : ""; - if (t < NUMOFSIGNALS && *signals[t].name != '\0') - return nprint("%s%s", signals[t].name, core); - else - return nprint("-%d%s", t, core); /* unknown signals are negated */ - } else - return nprint("%d", (s >> 8) & 0xff); -} - -extern void ssetstatus(char **av) { - int i, j, k, l; - bool found; - for (l = 0; av[l] != NULL; l++) - ; /* count up array length */ - --l; - for (i = 0; av[i] != NULL; i++) { - j = a2u(av[i]); - if (j >= 0) { - statuses[l - i] = j << 8; - continue; - } - found = FALSE; - for (k = 0; k < NUMOFSIGNALS; k++) { - if (streq(signals[k].name, av[i])) { - statuses[l - i] = k; - found = TRUE; - break; - } - else { - size_t len = strlen(signals[k].name); - if (strncmp(signals[k].name, av[i], len) == 0 && streq(av[i] + len, "+core")) { - statuses[l - i] = k + 0x80; - found = TRUE; - break; - } - } - } - if (!found) { - fprint(2, "bad status\n"); - set(FALSE); - return; - } - } - pipelength = i; -} diff --git a/tree.c b/tree.c @@ -1,172 +0,0 @@ -/* tree.c: functions for manipulating parse-trees. (create, copy, delete) */ - -#include "rc.h" - -/* make a new node, pass it back to yyparse. Used to generate the parsetree. */ - -extern Node *mk(int /*nodetype*/ t,...) { - va_list ap; - Node *n; - va_start(ap, t); - switch (t) { - default: - panic("unexpected node in mk"); - /* NOTREACHED */ - case nDup: - n = nalloc(offsetof(Node, u[3])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].i = va_arg(ap, int); - break; - case nWord: case nQword: - n = nalloc(offsetof(Node, u[2])); - n->u[0].s = va_arg(ap, char *); - n->u[1].s = va_arg(ap, char *); - break; - case nBang: case nNowait: - case nCount: case nFlat: case nRmfn: case nSubshell: - case nVar: case nCase: - n = nalloc(offsetof(Node, u[1])); - n->u[0].p = va_arg(ap, Node *); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: - case nOrelse: case nPre: case nArgs: case nSwitch: - case nMatch: case nVarsub: case nWhile: case nLappend: - n = nalloc(offsetof(Node, u[2])); - n->u[0].p = va_arg(ap, Node *); - n->u[1].p = va_arg(ap, Node *); - break; - case nForin: - n = nalloc(offsetof(Node, u[3])); - n->u[0].p = va_arg(ap, Node *); - n->u[1].p = va_arg(ap, Node *); - n->u[2].p = va_arg(ap, Node *); - break; - case nPipe: - n = nalloc(offsetof(Node, u[4])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].p = va_arg(ap, Node *); - n->u[3].p = va_arg(ap, Node *); - break; - case nRedir: - case nNmpipe: - n = nalloc(offsetof(Node, u[3])); - n->u[0].i = va_arg(ap, int); - n->u[1].i = va_arg(ap, int); - n->u[2].p = va_arg(ap, Node *); - break; - } - n->type = t; - va_end(ap); - return n; -} - -/* copy a tree to malloc space. Used when storing the definition of a function */ - -extern Node *treecpy(Node *s, void *(*alloc)(size_t)) { - Node *n; - if (s == NULL) - return NULL; - switch (s->type) { - default: - panic("unexpected node in treecpy"); - /* NOTREACHED */ - case nDup: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].i = s->u[2].i; - break; - case nWord: case nQword: - n = (*alloc)(offsetof(Node, u[2])); - n->u[0].s = strcpy((char *) (*alloc)(strlen(s->u[0].s) + 1), s->u[0].s); - if (s->u[1].s != NULL) { - size_t i = strlen(s->u[0].s); - n->u[1].s = (*alloc)(i); - memcpy(n->u[1].s, s->u[1].s, i); - } else - n->u[1].s = NULL; - break; - case nBang: case nNowait: case nCase: - case nCount: case nFlat: case nRmfn: case nSubshell: case nVar: - n = (*alloc)(offsetof(Node, u[1])); - n->u[0].p = treecpy(s->u[0].p, alloc); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: case nCbody: - case nOrelse: case nPre: case nArgs: case nSwitch: - case nMatch: case nVarsub: case nWhile: case nLappend: - n = (*alloc)(offsetof(Node, u[2])); - n->u[0].p = treecpy(s->u[0].p, alloc); - n->u[1].p = treecpy(s->u[1].p, alloc); - break; - case nForin: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].p = treecpy(s->u[0].p, alloc); - n->u[1].p = treecpy(s->u[1].p, alloc); - n->u[2].p = treecpy(s->u[2].p, alloc); - break; - case nPipe: - n = (*alloc)(offsetof(Node, u[4])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].p = treecpy(s->u[2].p, alloc); - n->u[3].p = treecpy(s->u[3].p, alloc); - break; - case nRedir: - case nNmpipe: - n = (*alloc)(offsetof(Node, u[3])); - n->u[0].i = s->u[0].i; - n->u[1].i = s->u[1].i; - n->u[2].p = treecpy(s->u[2].p, alloc); - break; - } - n->type = s->type; - return n; -} - -/* free a function definition that is no longer needed */ - -extern void treefree(Node *s) { - if (s == NULL) - return; - switch (s->type) { - default: - panic("unexpected node in treefree"); - /* NOTREACHED */ - case nDup: - break; - case nWord: case nQword: - efree(s->u[0].s); - efree(s->u[1].s); - break; - case nBang: case nNowait: - case nCount: case nFlat: case nRmfn: - case nSubshell: case nVar: case nCase: - treefree(s->u[0].p); - break; - case nAndalso: case nAssign: case nBackq: case nBody: case nBrace: case nConcat: - case nElse: case nEpilog: case nIf: case nNewfn: - case nOrelse: case nPre: case nArgs: case nCbody: - case nSwitch: case nMatch: case nVarsub: case nWhile: - case nLappend: - treefree(s->u[1].p); - treefree(s->u[0].p); - break; - case nForin: - treefree(s->u[2].p); - treefree(s->u[1].p); - treefree(s->u[0].p); - break; - case nPipe: - treefree(s->u[2].p); - treefree(s->u[3].p); - break; - case nRedir: - case nNmpipe: - treefree(s->u[2].p); - } - efree(s); -} diff --git a/trip.rc b/trip.rc Binary files differ. diff --git a/utils.c b/utils.c @@ -1,116 +0,0 @@ -/* utils.c: functions of general utility */ - -#include <errno.h> -#include <setjmp.h> -#include "rc.h" -#include "jbwrap.h" - -/* print error with line number on noninteractive shells (i.e., scripts) */ - -extern void pr_error(char *s) { - if (s != NULL) { - if (interactive) - fprint(2, "%s\n", s); - else - fprint(2, "line %d: %s\n", lineno - 1, s); - } -} - -/* our perror */ - -extern void uerror(char *s) { - extern int sys_nerr; - extern char *sys_errlist[]; - if (errno > sys_nerr) - return; - if (s != NULL) - fprint(2, "%s: %s\n", s, sys_errlist[errno]); - else - fprint(2, "%s\n", sys_errlist[errno]); -} - -/* Die horribly. This should never get called. Please let me know if it does. */ - -#define PANICMSG "rc panic: " - -extern void panic(char *s) { - write(2, PANICMSG, conststrlen(PANICMSG)); - write(2, s, strlen(s)); - write(2, "!\n", 2); - exit(1); -} - -/* ascii -> unsigned conversion routines. -1 indicates conversion error. */ - -extern int n2u(char *s, unsigned int base) { - unsigned int i; - for (i = 0; *s != '\0'; s++) { - unsigned int j = (unsigned int) *s - '0'; - if (j >= base) /* small hack with unsigned ints -- one compare for range test */ - return -1; - i = i * base + j; - } - return (int) i; -} - -/* The last word in portable ANSI: a strcmp wrapper for qsort */ - -extern int starstrcmp(const void *s1, const void *s2) { - return strcmp(*(char **)s1, *(char **)s2); -} - -/* tests to see if pathname begins with "/", "./", or "../" */ - -extern bool isabsolute(char *path) { - return path[0] == '/' || (path[0] == '.' && (path[1] == '/' || (path[1] == '.' && path[2] == '/'))); -} - -/* signal-safe read and write (for BSD slow devices). writeall also allows partial writes */ - -extern void writeall(int fd, char *buf, size_t remain) { - int i; - for (i = 0; remain > 0; buf += i, remain -= i) { - interrupt_happened = FALSE; - if (!setjmp(slowbuf.j)) { - slow = TRUE; - if (interrupt_happened) - break; - else if ((i = write(fd, buf, remain)) <= 0) - break; /* abort silently on errors in write() */ - } else - break; - slow = FALSE; - } - slow = FALSE; - sigchk(); -} - -extern int rc_read(int fd, char *buf, size_t n) { - long /*ssize_t*/ r; - interrupt_happened = FALSE; - if (!setjmp(slowbuf.j)) { - slow = TRUE; - if (!interrupt_happened) - r = read(fd, buf, n); - else - r = -2; - } else - r = -2; - slow = FALSE; - if (r == -2) { - errno = EINTR; - r = -1; - } - return r; -} - -/* duplicate a fd and close the old one only if necessary */ - -extern int mvfd(int i, int j) { - if (i != j) { - int s = dup2(i, j); - close(i); - return s; - } - return 0; -} diff --git a/var.c b/var.c @@ -1,225 +0,0 @@ -/* var.c: provide "public" functions for adding and removing variables from the symbol table */ - -#include "rc.h" - -static void colonassign(char *, List *, bool); -static void listassign(char *, List *, bool); -static int hasalias(char *); - -static char *const aliases[] = { - "home", "HOME", "path", "PATH", "cdpath", "CDPATH" -}; - -/* assign a variable in List form to a name, stacking if appropriate */ - -extern void varassign(char *name, List *def, bool stack) { - Variable *new; - List *newdef = listcpy(def, ealloc); /* important to do the listcpy first; get_var_place() frees old values */ - new = get_var_place(name, stack); - new->def = newdef; - new->extdef = NULL; -#if READLINE /* need to reset readline() every time TERM or TERMCAP changes */ - if (interactive && (streq(name, "TERM") || streq(name, "TERMCAP"))) { - extern void rl_reset_terminal(char *); - rl_reset_terminal(NULL); - } -#endif -} - -/* assign a variable in string form. Check to see if it is aliased (e.g., PATH and path) */ - -extern bool varassign_string(char *extdef) { - static bool aliasset[arraysize(aliases)] = { - FALSE, FALSE, FALSE, FALSE, FALSE, FALSE - }; - char *name = get_name(extdef); - Variable *new; - int i; - if (name == NULL) - return FALSE; /* add it to bozo env */ - if ((i = hasalias(name)) != -1) { - aliasset[i] = TRUE; - i ^= 1; /* set i to the "opposite" case subscript and */ - if (i&1 && aliasset[i]) /* don't alias variables that are already set in upper case */ - return TRUE; - } - new = get_var_place(name, FALSE); - new->def = NULL; - new->extdef = ealloc(strlen(extdef) + 1); - strcpy(new->extdef, extdef); - if (i != -1) - alias(name, varlookup(name), FALSE); - return TRUE; -} - -/* - Return a List based on a name lookup. If the list is in external (string) form, - convert it to internal (List) form. Treat $n (n is an integer) specially as $*(n). - Also check to see if $status is being dereferenced. (we lazily evaluate the List - associated with $status) -*/ - -extern List *varlookup(char *name) { - Variable *look; - List *ret, *l; - int sub; - if (streq(name, "status")) - return sgetstatus(); - if (streq(name, "apids")) - return sgetapids(); - if (*name != '\0' && (sub = a2u(name)) != -1) { /* handle $1, $2, etc. */ - for (l = varlookup("*"); l != NULL && sub != 0; --sub) - l = l->n; - if (l == NULL) - return NULL; - ret = nnew(List); - ret->w = l->w; - ret->m = NULL; - ret->n = NULL; - return ret; - } - look = lookup_var(name); - if (look == NULL) - return NULL; /* not found */ - if (look->def != NULL) - return look->def; - if (look->extdef == NULL) - return NULL; /* variable was set to null, e.g., a=() echo foo */ - ret = parse_var(name, look->extdef); - if (ret == NULL) { - look->extdef = NULL; - return NULL; - } - return look->def = ret; -} - -/* lookup a variable in external (string) form, converting if necessary. Used by makeenv() */ - -extern char *varlookup_string(char *name) { - Variable *look; - look = lookup_var(name); - if (look == NULL) - return NULL; - if (look->extdef != NULL) - return look->extdef; - if (look->def == NULL) - return NULL; - return look->extdef = mprint("%F=%-L", name, look->def, "\001"); -} - -/* remove a variable from the symtab. "stack" determines whether a level of scoping is popped or not */ - -extern void varrm(char *name, bool stack) { - int i = hasalias(name); - if (streq(name, "*") && !stack) { /* when assigning () to $*, we want to preserve $0 */ - varassign("*", varlookup("0"), FALSE); - return; - } - delete_var(name, stack); - if (i != -1) - delete_var(aliases[i^1], stack); -} - -/* assign a value (List) to a variable, using array "a" as input. Used to assign $* */ - -extern void starassign(char *dollarzero, char **a, bool stack) { - List *s, *var; - var = nnew(List); - var->w = dollarzero; - if (*a == NULL) { - var->n = NULL; - varassign("*", var, stack); - return; - } - var->n = s = nnew(List); - while (1) { - s->w = *a++; - if (*a == NULL) { - s->n = NULL; - break; - } else - s = s->n = nnew(List); - } - varassign("*", var, stack); -} - -/* (ugly name, huh?) assign a colon-separated value to a variable (e.g., PATH) from a List (e.g., path) */ - -static void colonassign(char *name, List *def, bool stack) { - List dud; - if (def == NULL) { - varassign(name, NULL, stack); - return; - } - dud.w = nprint("%-L", def, ":"); - dud.n = NULL; - varassign(name, &dud, stack); -} - -/* assign a List variable (e.g., path) from a colon-separated string (e.g., PATH) */ - -static void listassign(char *name, List *def, bool stack) { - List *val, *r; - char *v, *w; - if (def == NULL) { - varassign(name, NULL, stack); - return; - } - v = def->w; - r = val = nnew(List); - while ((w = strchr(v, ':')) != NULL) { - *w = '\0'; - r->w = ncpy(v); - *w = ':'; - v = w + 1; - r = r->n = nnew(List); - } - r->w = ncpy(v); - r->n = NULL; - varassign(name, val, stack); -} - -/* check to see if a particular variable is aliased; return -1 on failure, or the index */ - -static int hasalias(char *name) { - int i; - for (i = 0; i < arraysize(aliases); i++) - if (streq(name, aliases[i])) - return i; - return -1; -} - -/* alias a variable to its lowercase equivalent. function pointers are used to specify the conversion function */ - -extern void alias(char *name, List *s, bool stack) { - static void (*vectors[])(char *, List *, bool) = { - varassign, varassign, colonassign, listassign, colonassign, listassign - }; - int i = hasalias(name); - if (i != -1) - (*vectors[i])(aliases[i^1], s, stack); /* xor hack to reverse case of alias entry */ -} - -extern void prettyprint_var(int fd, char *name, List *s) { - int i; - static const char * const keywords[] = { - "if", "in", "fn", "for", "else", "switch", "while", "case" - }; - if (s == NULL) { - fprint(fd, "%S=()\n", name); - return; - } - if (streq(name, "*")) { - s = s->n; - if (s == NULL) - return; /* Don't print $0, and if $* is not set, skip it */ - } - for (i = 0; i < arraysize(keywords); i++) - if (streq(keywords[i], name)) { - fprint(fd, "%#S=", name); - goto value; - } - fprint(fd, "%S=", name); -value: - fprint(fd, s->n == NULL ? "%L\n" : "(%L)\n", s, " "); -} diff --git a/version.c b/version.c @@ -1 +0,0 @@ -const char id[] = "@(#)rc version 1.5b2, 1997-07-01."; diff --git a/wait.c b/wait.c @@ -1,129 +0,0 @@ -#include "rc.h" - -#include <errno.h> -#include <setjmp.h> -#include <sys/wait.h> - -#include "jbwrap.h" - -bool forked = FALSE; - -static pid_t rc_wait(int *); - -typedef struct Pid Pid; - -static struct Pid { - pid_t pid; - int stat; - bool alive; - Pid *n; -} *plist = NULL; - -extern pid_t rc_fork() { - Pid *new; - pid_t pid = fork(); - switch (pid) { - case -1: - uerror("fork"); - rc_error(NULL); - /* NOTREACHED */ - case 0: - forked = TRUE; - sigchk(); - return 0; - default: - new = enew(Pid); - new->pid = pid; - new->alive = TRUE; - new->n = plist; - plist = new; - return pid; - } -} - -extern pid_t rc_wait4(pid_t pid, int *stat, bool nointr) { - Pid *r, *prev; - int ret; - /* first look for a child which may already have exited */ -again: for (r = plist, prev = NULL; r != NULL; prev = r, r = r->n) - if (r->pid == pid) - break; - if (r == NULL) { - errno = ECHILD; /* no children */ - uerror("wait"); - *stat = 0x100; /* exit(1) */ - return -1; - } - if (r->alive) { - while (pid != (ret = rc_wait(stat))) { - Pid *q; - if (ret < 0) { - if (nointr) - goto again; - return ret; - } - for (q = plist; q != NULL; q = q->n) - if (q->pid == ret) { - q->alive = FALSE; - q->stat = *stat; - break; - } - } - } else - *stat = r->stat; - if (prev == NULL) - plist = r->n; /* remove element from head of list */ - else - prev->n = r->n; - efree(r); - return pid; -} - -extern List *sgetapids() { - List *r; - Pid *p; - for (r = NULL, p = plist; p != NULL; p = p->n) { - List *q; - if (!p->alive) - continue; - q = nnew(List); - q->w = nprint("%d", p->pid); - q->m = NULL; - q->n = r; - r = q; - } - return r; -} - -extern void waitforall() { - int stat; - while (plist != NULL) { - int pid = rc_wait4(plist->pid, &stat, FALSE); - if (pid > 0) - setstatus(pid, stat); - else - set(FALSE); - sigchk(); - } -} - -/* - rc_wait: a wait() wrapper that interfaces wait() w/rc signals. - Note that the signal queue is not checked in this fn; someone - may want to resume the wait() without delivering any signals. -*/ - -static pid_t rc_wait(int *stat) { - int r; - interrupt_happened = FALSE; - if (!setjmp(slowbuf.j)) { - slow = TRUE; - if (!interrupt_happened) - r = wait(stat); - else - r = -1; - } else - r = -1; - slow = FALSE; - return r; -} diff --git a/walk.c b/walk.c @@ -1,358 +0,0 @@ -/* walk.c: walks the parse tree. */ - -#include <signal.h> -#include <setjmp.h> -#include "rc.h" -#include "jbwrap.h" - -/* - global which indicates whether rc is executing a test; - used by rc -e so that if (false) does not exit. -*/ -bool cond = FALSE; - -static bool haspreredir(Node *); -static bool isallpre(Node *); -static bool dofork(bool); -static void dopipe(Node *); - -/* Tail-recursive version of walk() */ - -#define WALK(x, y) { n = x; parent = y; goto top; } - -/* walk the parse-tree. "obvious". */ - -extern bool walk(Node *n, bool parent) { -top: sigchk(); - if (n == NULL) { - if (!parent) - exit(0); - set(TRUE); - return TRUE; - } - switch (n->type) { - case nArgs: case nBackq: case nConcat: case nCount: - case nFlat: case nLappend: case nRedir: case nVar: - case nVarsub: case nWord: case nQword: - exec(glob(glom(n)), parent); /* simple command */ - break; - case nBody: - walk(n->u[0].p, TRUE); - WALK(n->u[1].p, parent); - /* WALK doesn't fall through */ - case nNowait: { - int pid; - if ((pid = rc_fork()) == 0) { -#if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP) - setsigdefaults(FALSE); - rc_signal(SIGTTOU, SIG_IGN); /* Berkeleyized version: put it in a new pgroup. */ - rc_signal(SIGTTIN, SIG_IGN); - rc_signal(SIGTSTP, SIG_IGN); - setpgid(0, getpid()); -#else - setsigdefaults(TRUE); /* ignore SIGINT, SIGQUIT, SIGTERM */ -#endif - mvfd(rc_open("/dev/null", rFrom), 0); - walk(n->u[0].p, FALSE); - exit(getstatus()); - } - if (interactive) - fprint(2, "%d\n", pid); - varassign("apid", word(nprint("%d", pid), NULL), FALSE); - redirq = NULL; /* kill pre-redir queue */ - break; - } - case nAndalso: { - bool oldcond = cond; - cond = TRUE; - if (walk(n->u[0].p, TRUE)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nOrelse: { - bool oldcond = cond; - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) { - cond = oldcond; - WALK(n->u[1].p, parent); - } else - cond = oldcond; - break; - } - case nBang: - set(!walk(n->u[0].p, TRUE)); - break; - case nIf: { - bool oldcond = cond; - Node *true_cmd = n->u[1].p, *false_cmd = NULL; - if (true_cmd != NULL && true_cmd->type == nElse) { - false_cmd = true_cmd->u[1].p; - true_cmd = true_cmd->u[0].p; - } - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) - true_cmd = false_cmd; /* run the else clause */ - cond = oldcond; - WALK(true_cmd, parent); - } - case nWhile: { - Jbwrap j; - Edata jbreak; - Estack e1, e2; - bool testtrue, oldcond = cond; - cond = TRUE; - if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */ - cond = oldcond; - break; - } - if (setjmp(j.j)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - do { - Edata block; - block.b = newblock(); - cond = oldcond; - except(eArena, block, &e2); - walk(n->u[1].p, TRUE); - testtrue = walk(n->u[0].p, TRUE); - unexcept(); /* eArena */ - cond = TRUE; - } while (testtrue); - cond = oldcond; - unexcept(); /* eBreak */ - break; - } - case nForin: { - List *l, *var = glom(n->u[0].p); - Jbwrap j; - Estack e1, e2; - Edata jbreak; - if (setjmp(j.j)) - break; - jbreak.jb = &j; - except(eBreak, jbreak, &e1); - for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) { - Edata block; - assign(var, word(l->w, NULL), FALSE); - block.b = newblock(); - except(eArena, block, &e2); - walk(n->u[2].p, TRUE); - unexcept(); /* eArena */ - } - unexcept(); /* eBreak */ - break; - } - case nSubshell: - if (dofork(TRUE)) { - walk(n->u[0].p, FALSE); - rc_exit(getstatus()); - } - break; - case nAssign: - if (n->u[0].p == NULL) - rc_error("null variable name"); - assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE); - set(TRUE); - break; - case nPipe: - dopipe(n); - break; - case nNewfn: { - List *l = glom(n->u[0].p); - if (l == NULL) - rc_error("null function name"); - while (l != NULL) { - if (dashex) - prettyprint_fn(2, l->w, n->u[1].p); - fnassign(l->w, n->u[1].p); - l = l->n; - } - set(TRUE); - break; - } - case nRmfn: { - List *l = glom(n->u[0].p); - while (l != NULL) { - if (dashex) - fprint(2, "fn %S\n", l->w); - fnrm(l->w); - l = l->n; - } - set(TRUE); - break; - } - case nDup: - redirq = NULL; - break; /* Null command */ - case nMatch: { - List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p); - if (dashex) - fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " "); - set(lmatch(a, b)); - break; - } - case nSwitch: { - List *v = glom(n->u[0].p); - while (1) { - do { - n = n->u[1].p; - if (n == NULL) - return istrue(); - } while (n->u[0].p == NULL || n->u[0].p->type != nCase); - if (lmatch(v, glom(n->u[0].p->u[0].p))) { - for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p) - walk(n->u[0].p, TRUE); - break; - } - } - break; - } - case nPre: { - List *v; - if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) { - if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */ - break; - qredir(n->u[0].p); - if (!haspreredir(n->u[1].p)) - doredirs(); /* no more preredirs, empty queue */ - walk(n->u[1].p, FALSE); - rc_exit(getstatus()); - /* NOTREACHED */ - } else if (n->u[0].p->type == nAssign) { - if (isallpre(n->u[1].p)) { - walk(n->u[0].p, TRUE); - WALK(n->u[1].p, parent); - } else { - Estack e; - Edata var; - v = glom(n->u[0].p->u[0].p); - assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE); - var.name = v->w; - except(eVarstack, var, &e); - walk(n->u[1].p, parent); - varrm(v->w, TRUE); - unexcept(); /* eVarstack */ - } - } else - panic("unexpected node in preredir section of walk"); - break; - } - case nBrace: - if (n->u[1].p == NULL) { - WALK(n->u[0].p, parent); - } else if (dofork(parent)) { - walk(n->u[1].p, TRUE); /* Do redirections */ - redirq = NULL; /* Reset redirection queue */ - walk(n->u[0].p, FALSE); /* Do commands */ - rc_exit(getstatus()); - /* NOTREACHED */ - } - break; - case nEpilog: - qredir(n->u[0].p); - if (n->u[1].p != NULL) { - WALK(n->u[1].p, parent); /* Do more redirections. */ - } else { - doredirs(); /* Okay, we hit the bottom. */ - } - break; - case nNmpipe: - rc_error("named pipes cannot be executed as commands"); - /* NOTREACHED */ - default: - panic("unknown node in walk"); - /* NOTREACHED */ - } - return istrue(); -} - -/* checks to see whether there are any pre-redirections left in the tree */ - -static bool haspreredir(Node *n) { - while (n != NULL && n->type == nPre) { - if (n->u[0].p->type == nDup || n->u[0].p->type == nRedir) - return TRUE; - n = n->u[1].p; - } - return FALSE; -} - -/* checks to see whether a subtree is all pre-command directives, i.e., assignments and redirs only */ - -static bool isallpre(Node *n) { - while (n != NULL && n->type == nPre) - n = n->u[1].p; - return n == NULL || n->type == nRedir || n->type == nAssign || n->type == nDup; -} - -/* - A code-saver. Forks, child returns (for further processing in walk()), and the parent - waits for the child to finish, setting $status appropriately. -*/ - -static bool dofork(bool parent) { - int pid, sp; - - if (!parent || (pid = rc_fork()) == 0) - return TRUE; - redirq = NULL; /* clear out the pre-redirection queue in the parent */ - rc_wait4(pid, &sp, TRUE); - setstatus(-1, sp); - sigchk(); - return FALSE; -} - -static void dopipe(Node *n) { - int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2]; - bool intr; - Node *r; - - fd_prev = fd_out = 1; - for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) { - if (i > 500) /* the only hard-wired limit in rc? */ - rc_error("pipe too long"); - if (pipe(p) < 0) { - uerror("pipe"); - rc_error(NULL); - } - if ((pid = rc_fork()) == 0) { - redirq = NULL; /* clear preredir queue */ - mvfd(p[0], r->u[1].i); - if (fd_prev != 1) - mvfd(fd_prev, fd_out); - close(p[1]); - walk(r->u[3].p, FALSE); - exit(getstatus()); - } - if (fd_prev != 1) - close(fd_prev); /* parent must close all pipe fd's */ - pids[i] = pid; - fd_prev = p[1]; - fd_out = r->u[0].i; - close(p[0]); - } - if ((pid = rc_fork()) == 0) { - mvfd(fd_prev, fd_out); - walk(r, FALSE); - exit(getstatus()); - /* NOTREACHED */ - } - redirq = NULL; /* clear preredir queue */ - close(fd_prev); - pids[i++] = pid; - - /* collect statuses */ - - intr = FALSE; - for (j = 0; j < i; j++) { - rc_wait4(pids[j], &sp, TRUE); - stats[j] = sp; - intr |= (sp == SIGINT); - } - setpipestatus(stats, i); - sigchk(); -} diff --git a/which.c b/which.c @@ -1,121 +0,0 @@ -/* which.c: check to see if a file is executable. - - This function was originally written with Maarten Litmaath's which.c as - a template, but was changed in order to accomodate the possibility of - rc's running setuid or the possibility of executing files not in the - primary group. Much of this file has been re-vamped by Paul Haahr. - I re-re-vamped the functions that Paul supplied to correct minor bugs - and to strip out unneeded functionality. -*/ - -#include "rc.h" -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#define X_USR 0100 -#define X_GRP 0010 -#define X_OTH 0001 -#define X_ALL (X_USR|X_GRP|X_OTH) - -extern int stat(const char *, struct stat *); - -static bool initialized = FALSE; -static uid_t uid; -static gid_t gid; - -#if HAVE_GETGROUPS -static int ngroups; -static GETGROUPS_T *gidset; - -/* determine whether gid lies in gidset */ - -static int ingidset(gid_t g) { - gid_t i; - for (i = 0; i < ngroups; ++i) - if (g == gidset[i]) - return 1; - return 0; -} -#endif - -/* - A home-grown access/stat. Does the right thing for group-executable files. - Returns a bool instead of this -1 nonsense. -*/ - -static bool rc_access(char *path, bool verbose) { - struct stat st; - int mask; - if (stat(path, &st) != 0) { - if (verbose) /* verbose flag only set for absolute pathname */ - uerror(path); - return FALSE; - } - if (uid == 0) - mask = X_ALL; - else if (uid == st.st_uid) - mask = X_USR; -#if HAVE_GETGROUPS - else if (gid == st.st_gid || ingidset(st.st_gid)) -#else - else if (gid == st.st_gid) -#endif - mask = X_GRP; - else - mask = X_OTH; - if (((st.st_mode & S_IFMT) == S_IFREG) && (st.st_mode & mask)) - return TRUE; - errno = EACCES; - if (verbose) - uerror(path); - return FALSE; -} - -/* return a full pathname by searching $path, and by checking the status of the file */ - -extern char *which(char *name, bool verbose) { - static char *test = NULL; - static size_t testlen = 0; - List *path; - int len; - if (name == NULL) /* no filename? can happen with "> foo" as a command */ - return NULL; - if (!initialized) { - initialized = TRUE; - uid = geteuid(); - gid = getegid(); -#if HAVE_GETGROUPS - ngroups = getgroups(0, (gid_t *)0); - gidset = malloc(ngroups * sizeof(gid_t)); - if (!gidset) - uerror("malloc"); - else - getgroups(ngroups, gidset); -#endif - } - if (isabsolute(name)) /* absolute pathname? */ - return rc_access(name, verbose) ? name : NULL; - len = strlen(name); - for (path = varlookup("path"); path != NULL; path = path->n) { - size_t need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */ - if (testlen < need) { - efree(test); - test = ealloc(testlen = need); - } - if (*path->w == '\0') { - strcpy(test, name); - } else { - strcpy(test, path->w); - if (!streq(test, "/")) /* "//" is special to POSIX */ - strcat(test, "/"); - strcat(test, name); - } - if (rc_access(test, FALSE)) - return test; - } - if (verbose) - fprint(2, "%s not found\n", name); - return NULL; -} diff --git a/y.tab.c b/y.tab.c @@ -1,1070 +0,0 @@ -#ifndef lint -static char const yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; -#endif -#define YYBYACC 1 -#define YYMAJOR 1 -#define YYMINOR 9 -#define YYLEX yylex() -#define YYEMPTY -1 -#define yyclearin (yychar=(YYEMPTY)) -#define yyerrok (yyerrflag=0) -#define YYRECOVERING (yyerrflag!=0) -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif -#endif -#ifdef __cplusplus -extern "C" { char *getenv(const char *); } -#else -extern char *getenv(); -extern int yylex(); -extern int yyparse(); -#endif -#define YYPREFIX "yy" -#line 8 "parse.y" -#include "rc.h" -#ifndef lint -#define lint /* hush up gcc -Wall, leave out the dumb sccsid's. */ -#endif -static Node *star, *nolist; -Node *parsetree; /* not using yylval because bison declares it as an auto */ -#line 28 "parse.y" -typedef union { - struct Node *node; - struct Redir redir; - struct Pipe pipe; - struct Dup dup; - struct Word word; - char *keyword; -} YYSTYPE; -#line 43 "y.tab.c" -#define ANDAND 257 -#define BACKBACK 258 -#define BANG 259 -#define CASE 260 -#define COUNT 261 -#define DUP 262 -#define ELSE 263 -#define END 264 -#define FLAT 265 -#define FN 266 -#define FOR 267 -#define IF 268 -#define IN 269 -#define OROR 270 -#define PIPE 271 -#define REDIR 272 -#define SREDIR 273 -#define SUB 274 -#define SUBSHELL 275 -#define SWITCH 276 -#define TWIDDLE 277 -#define WHILE 278 -#define WORD 279 -#define HUH 280 -#define YYERRCODE 256 -const short yylhs[] = { -1, - 0, 0, 22, 22, 8, 8, 13, 13, 3, 3, - 9, 9, 4, 15, 2, 11, 11, 16, 16, 16, - 5, 5, 6, 6, 6, 19, 19, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 24, 24, 18, 18, 18, - 12, 12, 17, 17, 20, 20, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 21, 21, - 14, 14, 14, 23, 23, -}; -const short yylen[] = { 2, - 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, - 1, 2, 3, 3, 3, 0, 2, 1, 2, 2, - 3, 3, 1, 2, 2, 1, 4, 0, 1, 2, - 4, 8, 6, 4, 8, 4, 4, 4, 4, 2, - 2, 3, 3, 3, 2, 0, 1, 1, 2, 2, - 1, 3, 1, 1, 1, 3, 2, 5, 2, 2, - 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, - 0, 2, 2, 0, 2, -}; -const short yydefred[] = { 0, - 0, 0, 0, 0, 18, 0, 79, 0, 0, 0, - 0, 0, 0, 0, 0, 67, 0, 0, 81, 0, - 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, - 3, 4, 2, 77, 75, 74, 73, 68, 71, 69, - 0, 78, 72, 76, 70, 54, 53, 55, 0, 47, - 0, 59, 60, 0, 0, 0, 84, 66, 0, 0, - 0, 0, 0, 84, 0, 0, 0, 11, 0, 0, - 62, 61, 0, 0, 30, 0, 84, 84, 84, 5, - 6, 8, 0, 0, 1, 0, 50, 0, 0, 63, - 64, 0, 44, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 13, 12, 10, 65, 82, 0, 17, 0, - 0, 0, 0, 52, 56, 79, 84, 14, 85, 0, - 0, 31, 84, 0, 0, 0, 0, 0, 39, 0, - 0, 84, 0, 58, 84, 0, 0, 0, 0, 0, - 79, 0, 0, 0, 0, 0, 0, 24, 35, 25, - 22, 21, -}; -const short yydgoto[] = { 21, - 46, 22, 66, 23, 142, 143, 67, 68, 69, 47, - 75, 27, 28, 70, 57, 29, 48, 30, 122, 94, - 54, 33, 97, 51, -}; -const short yysindex[] = { 874, - 24, 1001, -82, 1001, 0, 1001, 0, -27, -26, 900, - 1001, -82, -20, -82, -26, 0, 1001, 1134, 0, 900, - 0, 1134, -203, -30, 1134, 0, -55, 24, 1134, 826, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -66, 0, 0, 0, 0, 0, 0, 0, 849, 0, - 1134, 0, 0, 900, 1001, 1134, 0, 0, -52, -52, - 1134, 1001, 1001, 0, -212, -58, 154, 0, 1134, 426, - 0, 0, -196, 1001, 0, -203, 0, 0, 0, 0, - 0, 0, 1001, 1001, 0, -196, 0, -52, 1001, 0, - 0, -196, 0, -52, -38, 36, 502, -196, -36, -52, - 502, 0, 0, 0, 0, 0, 0, -52, 0, 502, - 502, 502, -52, 0, 0, 0, 0, 0, 0, -97, - -234, 0, 0, 1001, -234, 922, -196, -196, 0, 944, - 502, 0, -9, 0, 0, -234, 502, 967, 502, -234, - 0, 967, -45, 154, 967, -234, 448, 0, 0, 0, - 0, 0, -}; -const short yyrindex[] = { 134, - 0, 0, 356, 0, 0, 0, 0, 0, 0, 0, - 0, 356, 0, 1024, 0, 0, 0, 571, 0, 0, - 0, 487, 529, 54, 134, 0, 62, 0, 487, 548, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 487, 0, 0, 712, 0, 142, 0, 0, 14, 38, - 487, 0, 0, 0, -10, 0, -32, 0, 744, 0, - 0, 0, 749, 0, 0, 529, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 763, 0, 86, 0, 0, - 0, 779, 0, 110, 0, 0, -34, 788, 0, 380, - -34, 0, 0, 0, 0, 0, 0, 470, 0, -34, - -34, -34, 404, 0, 0, 0, 0, 0, 0, 529, - 6, 0, 0, 724, 30, 0, 805, 813, 0, 0, - -34, 0, 0, 0, 0, 119, -34, 571, -34, 187, - 0, 571, 0, -44, 571, 396, 0, 0, 0, 0, - 0, 0, -}; -const short yygindex[] = { 0, - 0, 0, -23, 12, 0, -104, 1319, 2, -127, 1307, - 7, 0, 57, 0, 70, -13, 84, 0, 0, 420, - -81, 59, 369, 31, -}; -#define YYTABLESIZE 1464 -const short yytable[] = { 57, - 119, 25, 117, 28, 123, 83, 28, 81, 9, 76, - 145, 50, 55, 56, 145, 26, 87, 145, 124, 62, - 126, 58, 77, 19, 28, 57, 25, 57, 80, 57, - 57, 71, 96, 32, 130, 78, 79, 148, 84, 34, - 150, 89, 61, 26, 63, 105, 26, 20, 57, 19, - 57, 19, 58, 19, 19, 89, 18, 89, 5, 147, - 90, 102, 76, 7, 26, 93, 103, 34, 74, 11, - 34, 48, 19, 20, 79, 20, 118, 20, 20, 149, - 23, 82, 109, 57, 64, 57, 85, 52, 34, 53, - 28, 0, 9, 0, 0, 49, 20, 48, 0, 48, - 65, 48, 48, 72, 0, 0, 76, 0, 120, 19, - 0, 0, 57, 138, 57, 0, 0, 0, 0, 80, - 48, 49, 0, 49, 0, 49, 49, 0, 33, 0, - 26, 0, 91, 20, 0, 0, 19, 0, 19, 0, - 0, 0, 0, 28, 49, 80, 0, 80, 0, 80, - 80, 28, 0, 0, 34, 0, 33, 48, 0, 33, - 20, 0, 20, 104, 5, 132, 0, 114, 80, 0, - 0, 28, 115, 0, 74, 11, 0, 33, 0, 28, - 0, 49, 28, 0, 0, 0, 48, 0, 0, 0, - 0, 81, 28, 0, 0, 0, 27, 0, 0, 0, - 28, 0, 0, 0, 0, 80, 0, 0, 0, 0, - 49, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 28, 0, 27, 0, 77, 27, 0, 28, - 116, 0, 80, 0, 80, 28, 28, 0, 0, 78, - 79, 0, 0, 33, 0, 27, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 0, 57, 57, 57, 57, 57, 26, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 31, 19, 19, - 19, 19, 19, 34, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 27, 20, 20, 20, 20, 20, 7, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, - 48, 0, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, - 49, 49, 49, 49, 49, 46, 80, 80, 80, 80, - 80, 0, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 33, 0, 80, 80, 80, 80, 80, 79, - 28, 46, 0, 46, 0, 46, 46, 28, 28, 0, - 0, 0, 0, 28, 28, 32, 0, 0, 0, 0, - 77, 28, 28, 15, 46, 79, 0, 79, 0, 79, - 79, 49, 0, 78, 79, 0, 0, 0, 0, 59, - 60, 0, 101, 32, 0, 107, 32, 0, 79, 15, - 0, 15, 0, 15, 15, 110, 111, 112, 0, 88, - 27, 46, 0, 0, 32, 0, 0, 151, 0, 0, - 0, 17, 15, 0, 0, 19, 106, 0, 0, 0, - 0, 0, 0, 0, 95, 79, 0, 0, 46, 83, - 46, 99, 100, 17, 0, 131, 0, 19, 0, 108, - 0, 133, 0, 59, 0, 0, 28, 0, 0, 15, - 137, 0, 113, 139, 79, 83, 152, 0, 0, 83, - 83, 119, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 20, 0, 0, 28, 0, 15, 28, 15, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 16, 0, - 0, 19, 0, 20, 0, 28, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, - 0, 0, 0, 0, 0, 83, 16, 0, 0, 16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 28, 0, 0, 0, 0, 29, 0, 16, 29, 0, - 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, - 0, 0, 0, 0, 0, 0, 29, 0, 28, 0, - 0, 28, 46, 46, 46, 0, 46, 46, 0, 46, - 46, 46, 46, 46, 18, 46, 46, 46, 46, 28, - 46, 46, 46, 46, 46, 0, 79, 79, 79, 79, - 79, 0, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 0, 16, 79, 79, 79, 79, 79, 32, - 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, - 15, 15, 29, 15, 15, 15, 15, 0, 15, 15, - 15, 15, 15, 2, 34, 35, 4, 0, 36, 0, - 6, 37, 38, 39, 40, 28, 0, 41, 0, 0, - 42, 43, 44, 45, 16, 2, 34, 35, 4, 0, - 36, 0, 6, 37, 38, 39, 40, 0, 0, 41, - 0, 45, 42, 43, 44, 45, 16, 83, 83, 83, - 83, 0, 83, 36, 83, 83, 83, 83, 83, 0, - 0, 83, 0, 28, 83, 83, 83, 83, 83, 45, - 28, 0, 45, 28, 0, 0, 28, 28, 41, 2, - 3, 36, 4, 5, 36, 0, 6, 7, 8, 9, - 45, 0, 40, 10, 11, 0, 12, 13, 14, 15, - 16, 28, 36, 0, 28, 16, 41, 0, 42, 41, - 0, 0, 16, 0, 0, 0, 0, 43, 16, 16, - 40, 0, 28, 40, 29, 0, 0, 41, 0, 0, - 0, 29, 0, 0, 37, 0, 42, 29, 29, 42, - 0, 40, 38, 0, 0, 43, 0, 28, 43, 0, - 0, 0, 0, 0, 0, 0, 45, 42, 0, 0, - 28, 28, 37, 0, 0, 37, 43, 0, 36, 0, - 38, 0, 0, 38, 0, 0, 0, 0, 0, 0, - 0, 17, 0, 37, 0, 19, 0, 0, 28, 0, - 0, 38, 0, 41, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 40, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 42, 0, 0, 0, 0, 0, 17, - 0, 0, 43, 19, 0, 0, 0, 0, 0, 0, - 0, 20, 0, 0, 0, 0, 0, 0, 0, 37, - 0, 0, 0, 0, 0, 17, 0, 38, 0, 19, - 0, 0, 89, 0, 20, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, - 0, 19, 134, 0, 0, 0, 0, 0, 45, 20, - 0, 18, 0, 0, 0, 45, 0, 0, 0, 17, - 36, 45, 45, 19, 135, 0, 0, 36, 0, 0, - 0, 0, 0, 36, 36, 20, 18, 0, 0, 0, - 28, 0, 17, 0, 0, 41, 19, 0, 0, 0, - 0, 0, 41, 28, 28, 0, 0, 20, 41, 40, - 0, 0, 18, 0, 0, 0, 40, 0, 0, 0, - 0, 0, 40, 0, 0, 42, 17, 0, 0, 20, - 19, 0, 42, 0, 43, 0, 0, 0, 42, 0, - 0, 43, 0, 0, 0, 0, 0, 43, 0, 46, - 0, 37, 20, 46, 0, 0, 0, 0, 37, 38, - 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, - 0, 0, 38, 2, 34, 35, 4, 5, 36, 18, - 6, 37, 38, 39, 40, 0, 20, 10, 11, 0, - 42, 43, 44, 45, 16, 0, 2, 34, 35, 4, - 0, 36, 0, 6, 37, 38, 39, 40, 0, 46, - 41, 0, 0, 42, 43, 44, 45, 16, 0, 1, - 0, 2, 3, 0, 4, 5, 0, 0, 6, 7, - 8, 9, 0, 0, 0, 10, 11, 0, 12, 13, - 14, 15, 16, 0, 0, 0, 0, 2, 34, 35, - 4, 0, 36, 0, 6, 37, 38, 39, 40, 17, - 0, 41, 0, 19, 42, 43, 44, 45, 16, 2, - 34, 35, 4, 0, 36, 0, 6, 37, 38, 39, - 40, 0, 0, 41, 0, 0, 42, 43, 44, 45, - 16, 2, 34, 35, 4, 0, 36, 0, 6, 37, - 38, 39, 40, 0, 0, 41, 0, 0, 42, 43, - 44, 45, 16, 0, 2, 3, 141, 4, 5, 20, - 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, - 0, 12, 13, 14, 15, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 18, 0, 2, 34, - 35, 4, 0, 36, 0, 6, 37, 38, 39, 40, - 0, 0, 41, 0, 0, 42, 43, 44, 45, 16, - 0, 46, 46, 46, 46, 0, 46, 0, 46, 46, - 46, 46, 46, 0, 0, 46, 0, 0, 46, 46, - 46, 46, 46, 0, 0, 0, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, - 0, 0, 0, 0, 26, 0, 0, 0, 26, 0, - 0, 26, 0, 0, 0, 26, 0, 0, 0, 0, - 73, 0, 0, 24, 0, 0, 0, 86, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, - 0, 0, 26, 0, 0, 0, 0, 26, 0, 92, - 0, 0, 0, 0, 0, 26, 0, 0, 0, 98, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 3, 0, 4, 5, 0, 0, 6, 7, - 8, 9, 0, 26, 0, 10, 11, 26, 12, 13, - 14, 15, 16, 0, 0, 121, 26, 26, 26, 125, - 0, 0, 0, 0, 0, 0, 0, 0, 127, 128, - 129, 0, 0, 0, 0, 0, 0, 26, 0, 0, - 0, 0, 0, 26, 26, 26, 0, 0, 26, 136, - 0, 26, 0, 0, 0, 140, 144, 146, 0, 0, - 144, 0, 0, 144, -}; -const short yycheck[] = { 10, - 10, 0, 41, 38, 41, 61, 41, 38, 41, 23, - 138, 94, 40, 40, 142, 10, 30, 145, 100, 40, - 102, 10, 257, 10, 59, 36, 25, 38, 59, 40, - 41, 20, 56, 10, 116, 270, 271, 142, 94, 10, - 145, 94, 12, 38, 14, 69, 41, 10, 59, 36, - 61, 38, 41, 40, 41, 94, 123, 94, 262, 141, - 49, 274, 76, 10, 59, 54, 125, 38, 272, 273, - 41, 10, 59, 36, 271, 38, 41, 40, 41, 125, - 125, 25, 76, 94, 15, 96, 28, 4, 59, 6, - 125, -1, 125, -1, -1, 10, 59, 36, -1, 38, - 17, 40, 41, 20, -1, -1, 120, -1, 97, 96, - -1, -1, 123, 123, 125, -1, -1, -1, -1, 10, - 59, 36, -1, 38, -1, 40, 41, -1, 10, -1, - 125, -1, 49, 96, -1, -1, 123, -1, 125, -1, - -1, -1, -1, 10, 59, 36, -1, 38, -1, 40, - 41, 10, -1, -1, 125, -1, 38, 96, -1, 41, - 123, -1, 125, 10, 262, 263, -1, 84, 59, -1, - -1, 38, 89, -1, 272, 273, -1, 59, -1, 38, - -1, 96, 41, -1, -1, -1, 125, -1, -1, -1, - -1, 38, 59, -1, -1, -1, 10, -1, -1, -1, - 59, -1, -1, -1, -1, 96, -1, -1, -1, -1, - 125, -1, 59, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 257, -1, 38, -1, 257, 41, -1, 264, - 269, -1, 123, -1, 125, 270, 271, -1, -1, 270, - 271, -1, -1, 125, -1, 59, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, -1, 275, 276, 277, 278, 279, 264, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 264, 275, 276, - 277, 278, 279, 264, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 125, 275, 276, 277, 278, 279, 264, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - 279, -1, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, -1, - 275, 276, 277, 278, 279, 10, 257, 258, 259, 260, - 261, -1, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 264, -1, 275, 276, 277, 278, 279, 10, - 257, 36, -1, 38, -1, 40, 41, 264, 257, -1, - -1, -1, -1, 270, 271, 10, -1, -1, -1, -1, - 257, 270, 271, 10, 59, 36, -1, 38, -1, 40, - 41, 2, -1, 270, 271, -1, -1, -1, -1, 10, - 11, -1, 64, 38, -1, 10, 41, -1, 59, 36, - -1, 38, -1, 40, 41, 77, 78, 79, -1, 30, - 264, 96, -1, -1, 59, -1, -1, 10, -1, -1, - -1, 36, 59, -1, -1, 40, 41, -1, -1, -1, - -1, -1, -1, -1, 55, 96, -1, -1, 123, 10, - 125, 62, 63, 36, -1, 117, -1, 40, -1, 70, - -1, 123, -1, 74, -1, -1, 10, -1, -1, 96, - 132, -1, 83, 135, 125, 36, 59, -1, -1, 40, - 41, 10, -1, -1, -1, -1, -1, -1, -1, -1, - 125, 96, -1, -1, 38, -1, 123, 41, 125, -1, - -1, -1, -1, -1, -1, -1, -1, 36, 10, -1, - -1, 40, -1, 96, -1, 59, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, - -1, -1, -1, -1, -1, 96, 38, -1, -1, 41, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 10, -1, -1, -1, -1, 38, -1, 59, 41, -1, - -1, -1, -1, -1, -1, -1, -1, 96, -1, -1, - -1, -1, -1, -1, -1, -1, 59, -1, 38, -1, - -1, 125, 257, 258, 259, -1, 261, 262, -1, 264, - 265, 266, 267, 268, 123, 270, 271, 272, 273, 59, - 275, 276, 277, 278, 279, -1, 257, 258, 259, 260, - 261, -1, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, -1, 125, 275, 276, 277, 278, 279, 264, - 257, 258, 259, -1, 261, 262, -1, 264, 265, 266, - 267, 268, 125, 270, 271, 272, 273, -1, 275, 276, - 277, 278, 279, 258, 259, 260, 261, -1, 263, -1, - 265, 266, 267, 268, 269, 125, -1, 272, -1, -1, - 275, 276, 277, 278, 279, 258, 259, 260, 261, -1, - 263, -1, 265, 266, 267, 268, 269, -1, -1, 272, - -1, 10, 275, 276, 277, 278, 279, 258, 259, 260, - 261, -1, 263, 10, 265, 266, 267, 268, 269, -1, - -1, 272, -1, 257, 275, 276, 277, 278, 279, 38, - 264, -1, 41, 10, -1, -1, 270, 271, 10, 258, - 259, 38, 261, 262, 41, -1, 265, 266, 267, 268, - 59, -1, 10, 272, 273, -1, 275, 276, 277, 278, - 279, 38, 59, -1, 41, 257, 38, -1, 10, 41, - -1, -1, 264, -1, -1, -1, -1, 10, 270, 271, - 38, -1, 59, 41, 257, -1, -1, 59, -1, -1, - -1, 264, -1, -1, 10, -1, 38, 270, 271, 41, - -1, 59, 10, -1, -1, 38, -1, 257, 41, -1, - -1, -1, -1, -1, -1, -1, 125, 59, -1, -1, - 270, 271, 38, -1, -1, 41, 59, -1, 125, -1, - 38, -1, -1, 41, -1, -1, -1, -1, -1, -1, - -1, 36, -1, 59, -1, 40, -1, -1, 125, -1, - -1, 59, -1, 125, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 36, -1, -1, 125, 40, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 125, -1, -1, -1, -1, -1, 36, - -1, -1, 125, 40, -1, -1, -1, -1, -1, -1, - -1, 96, -1, -1, -1, -1, -1, -1, -1, 125, - -1, -1, -1, -1, -1, 36, -1, 125, -1, 40, - -1, -1, 94, -1, 96, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, - -1, 40, 41, -1, -1, -1, -1, -1, 257, 96, - -1, 123, -1, -1, -1, 264, -1, -1, -1, 36, - 257, 270, 271, 40, 41, -1, -1, 264, -1, -1, - -1, -1, -1, 270, 271, 96, 123, -1, -1, -1, - 257, -1, 36, -1, -1, 257, 40, -1, -1, -1, - -1, -1, 264, 270, 271, -1, -1, 96, 270, 257, - -1, -1, 123, -1, -1, -1, 264, -1, -1, -1, - -1, -1, 270, -1, -1, 257, 36, -1, -1, 96, - 40, -1, 264, -1, 257, -1, -1, -1, 270, -1, - -1, 264, -1, -1, -1, -1, -1, 270, -1, 36, - -1, 257, 96, 40, -1, -1, -1, -1, 264, 257, - -1, -1, -1, -1, 270, -1, 264, -1, -1, -1, - -1, -1, 270, 258, 259, 260, 261, 262, 263, 123, - 265, 266, 267, 268, 269, -1, 96, 272, 273, -1, - 275, 276, 277, 278, 279, -1, 258, 259, 260, 261, - -1, 263, -1, 265, 266, 267, 268, 269, -1, 96, - 272, -1, -1, 275, 276, 277, 278, 279, -1, 256, - -1, 258, 259, -1, 261, 262, -1, -1, 265, 266, - 267, 268, -1, -1, -1, 272, 273, -1, 275, 276, - 277, 278, 279, -1, -1, -1, -1, 258, 259, 260, - 261, -1, 263, -1, 265, 266, 267, 268, 269, 36, - -1, 272, -1, 40, 275, 276, 277, 278, 279, 258, - 259, 260, 261, -1, 263, -1, 265, 266, 267, 268, - 269, -1, -1, 272, -1, -1, 275, 276, 277, 278, - 279, 258, 259, 260, 261, -1, 263, -1, 265, 266, - 267, 268, 269, -1, -1, 272, -1, -1, 275, 276, - 277, 278, 279, -1, 258, 259, 260, 261, 262, 96, - -1, 265, 266, 267, 268, -1, -1, -1, 272, 273, - -1, 275, 276, 277, 278, 279, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 123, -1, 258, 259, - 260, 261, -1, 263, -1, 265, 266, 267, 268, 269, - -1, -1, 272, -1, -1, 275, 276, 277, 278, 279, - -1, 258, 259, 260, 261, -1, 263, -1, 265, 266, - 267, 268, 269, -1, -1, 272, -1, -1, 275, 276, - 277, 278, 279, -1, -1, -1, 0, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, - -1, -1, -1, -1, 18, -1, -1, -1, 22, -1, - -1, 25, -1, -1, -1, 29, -1, -1, -1, -1, - 22, -1, -1, 25, -1, -1, -1, 29, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, - -1, -1, 56, -1, -1, -1, -1, 61, -1, 51, - -1, -1, -1, -1, -1, 69, -1, -1, -1, 61, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 258, 259, -1, 261, 262, -1, -1, 265, 266, - 267, 268, -1, 97, -1, 272, 273, 101, 275, 276, - 277, 278, 279, -1, -1, 97, 110, 111, 112, 101, - -1, -1, -1, -1, -1, -1, -1, -1, 110, 111, - 112, -1, -1, -1, -1, -1, -1, 131, -1, -1, - -1, -1, -1, 137, 138, 139, -1, -1, 142, 131, - -1, 145, -1, -1, -1, 137, 138, 139, -1, -1, - 142, -1, -1, 145, -}; -#define YYFINAL 21 -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif -#define YYMAXTOKEN 280 -#if YYDEBUG -char *yyname[] = { -"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,"'$'",0,"'&'",0,"'('","')'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"';'",0, -"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'^'",0, -"'`'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,"ANDAND","BACKBACK","BANG","CASE","COUNT","DUP","ELSE","END", -"FLAT","FN","FOR","IF","IN","OROR","PIPE","REDIR","SREDIR","SUB","SUBSHELL", -"SWITCH","TWIDDLE","WHILE","WORD","HUH", -}; -const char * const yyrule[] = { -"$accept : rc", -"rc : line end", -"rc : error end", -"end : END", -"end : '\\n'", -"cmdsa : cmd ';'", -"cmdsa : cmd '&'", -"line : cmd", -"line : cmdsa line", -"body : cmd", -"body : cmdsan body", -"cmdsan : cmdsa", -"cmdsan : cmd '\\n'", -"brace : '{' body '}'", -"paren : '(' body ')'", -"assign : first '=' word", -"epilog :", -"epilog : redir epilog", -"redir : DUP", -"redir : REDIR word", -"redir : SREDIR word", -"case : CASE words ';'", -"case : CASE words '\\n'", -"cbody : cmd", -"cbody : case cbody", -"cbody : cmdsan cbody", -"iftail : cmd", -"iftail : brace ELSE optnl cmd", -"cmd :", -"cmd : simple", -"cmd : brace epilog", -"cmd : IF paren optnl iftail", -"cmd : FOR '(' word IN words ')' optnl cmd", -"cmd : FOR '(' word ')' optnl cmd", -"cmd : WHILE paren optnl cmd", -"cmd : SWITCH '(' word ')' optnl '{' cbody '}'", -"cmd : TWIDDLE optcaret word words", -"cmd : cmd ANDAND optnl cmd", -"cmd : cmd OROR optnl cmd", -"cmd : cmd PIPE optnl cmd", -"cmd : redir cmd", -"cmd : assign cmd", -"cmd : BANG optcaret cmd", -"cmd : SUBSHELL optcaret cmd", -"cmd : FN words brace", -"cmd : FN words", -"optcaret :", -"optcaret : '^'", -"simple : first", -"simple : simple word", -"simple : simple redir", -"first : comword", -"first : first '^' sword", -"sword : comword", -"sword : keyword", -"word : sword", -"word : word '^' sword", -"comword : '$' sword", -"comword : '$' sword SUB words ')'", -"comword : COUNT sword", -"comword : FLAT sword", -"comword : '`' sword", -"comword : '`' brace", -"comword : BACKBACK word brace", -"comword : BACKBACK word sword", -"comword : '(' nlwords ')'", -"comword : REDIR brace", -"comword : WORD", -"keyword : FOR", -"keyword : IN", -"keyword : WHILE", -"keyword : IF", -"keyword : SWITCH", -"keyword : FN", -"keyword : ELSE", -"keyword : CASE", -"keyword : TWIDDLE", -"keyword : BANG", -"keyword : SUBSHELL", -"words :", -"words : words word", -"nlwords :", -"nlwords : nlwords '\\n'", -"nlwords : nlwords word", -"optnl :", -"optnl : optnl '\\n'", -}; -#endif -#ifdef YYSTACKSIZE -#undef YYMAXDEPTH -#define YYMAXDEPTH YYSTACKSIZE -#else -#ifdef YYMAXDEPTH -#define YYSTACKSIZE YYMAXDEPTH -#else -#define YYSTACKSIZE 500 -#define YYMAXDEPTH 500 -#endif -#endif -int yydebug; -int yynerrs; -int yyerrflag; -int yychar; -short *yyssp; -YYSTYPE *yyvsp; -YYSTYPE yyval; -YYSTYPE yylval; -short yyss[YYSTACKSIZE]; -YYSTYPE yyvs[YYSTACKSIZE]; -#define yystacksize YYSTACKSIZE -#line 169 "parse.y" - -void initparse() { - star = treecpy(mk(nVar,mk(nWord,"*",NULL)), ealloc); - nolist = treecpy(mk(nVar,mk(nWord,"ifs",NULL)), ealloc); -} - -#line 590 "y.tab.c" -#define YYABORT goto yyabort -#define YYREJECT goto yyabort -#define YYACCEPT goto yyaccept -#define YYERROR goto yyerrlab - -int -yyparse() -{ - register int yym, yyn, yystate; -#if YYDEBUG - register char *yys; - - if ((yys = getenv("YYDEBUG"))) - { - yyn = *yys; - if (yyn >= '0' && yyn <= '9') - yydebug = yyn - '0'; - } -#endif - - yynerrs = 0; - yyerrflag = 0; - yychar = (-1); - - yyssp = yyss; - yyvsp = yyvs; - *yyssp = yystate = 0; - -yyloop: - if ((yyn = yydefred[yystate])) goto yyreduce; - if (yychar < 0) - { - if ((yychar = yylex()) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - } - if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, shifting to state %d\n", - YYPREFIX, yystate, yytable[yyn]); -#endif - if (yyssp >= yyss + yystacksize - 1) - { - goto yyoverflow; - } - *++yyssp = yystate = yytable[yyn]; - *++yyvsp = yylval; - yychar = (-1); - if (yyerrflag > 0) --yyerrflag; - goto yyloop; - } - if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { - yyn = yytable[yyn]; - goto yyreduce; - } - if (yyerrflag) goto yyinrecovery; -#if defined(lint) || defined(__GNUC__) - goto yynewerror; -#endif -yynewerror: - yyerror("syntax error"); -#if defined(lint) || defined(__GNUC__) - goto yyerrlab; -#endif -yyerrlab: - ++yynerrs; -yyinrecovery: - if (yyerrflag < 3) - { - yyerrflag = 3; - for (;;) - { - if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, error recovery shifting\ - to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); -#endif - if (yyssp >= yyss + yystacksize - 1) - { - goto yyoverflow; - } - *++yyssp = yystate = yytable[yyn]; - *++yyvsp = yylval; - goto yyloop; - } - else - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: error recovery discarding state %d\n", - YYPREFIX, *yyssp); -#endif - if (yyssp <= yyss) goto yyabort; - --yyssp; - --yyvsp; - } - } - } - else - { - if (yychar == 0) goto yyabort; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, error recovery discards token %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - yychar = (-1); - goto yyloop; - } -yyreduce: -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, reducing by rule %d (%s)\n", - YYPREFIX, yystate, yyn, yyrule[yyn]); -#endif - yym = yylen[yyn]; - yyval = yyvsp[1-yym]; - switch (yyn) - { -case 1: -#line 49 "parse.y" -{ parsetree = yyvsp[-1].node; YYACCEPT; } -break; -case 2: -#line 50 "parse.y" -{ yyerrok; parsetree = NULL; YYABORT; } -break; -case 3: -#line 53 "parse.y" -{ if (!heredoc(1)) YYABORT; } -break; -case 4: -#line 54 "parse.y" -{ if (!heredoc(0)) YYABORT; } -break; -case 6: -#line 58 "parse.y" -{ yyval.node = (yyvsp[-1].node != NULL ? mk(nNowait,yyvsp[-1].node) : yyvsp[-1].node); } -break; -case 8: -#line 62 "parse.y" -{ yyval.node = (yyvsp[-1].node != NULL ? mk(nBody,yyvsp[-1].node,yyvsp[0].node) : yyvsp[0].node); } -break; -case 10: -#line 66 "parse.y" -{ yyval.node = (yyvsp[-1].node == NULL ? yyvsp[0].node : yyvsp[0].node == NULL ? yyvsp[-1].node : mk(nBody,yyvsp[-1].node,yyvsp[0].node)); } -break; -case 12: -#line 69 "parse.y" -{ yyval.node = yyvsp[-1].node; if (!heredoc(0)) YYABORT; } -break; -case 13: -#line 71 "parse.y" -{ yyval.node = yyvsp[-1].node; } -break; -case 14: -#line 73 "parse.y" -{ yyval.node = yyvsp[-1].node; } -break; -case 15: -#line 75 "parse.y" -{ yyval.node = mk(nAssign,yyvsp[-2].node,yyvsp[0].node); } -break; -case 16: -#line 77 "parse.y" -{ yyval.node = NULL; } -break; -case 17: -#line 78 "parse.y" -{ yyval.node = mk(nEpilog,yyvsp[-1].node,yyvsp[0].node); } -break; -case 18: -#line 81 "parse.y" -{ yyval.node = mk(nDup,yyvsp[0].dup.type,yyvsp[0].dup.left,yyvsp[0].dup.right); } -break; -case 19: -#line 82 "parse.y" -{ yyval.node = mk(nRedir,yyvsp[-1].redir.type,yyvsp[-1].redir.fd,yyvsp[0].node); - if (yyvsp[-1].redir.type == rHeredoc && !qdoc(yyvsp[0].node, yyval.node)) YYABORT; /* queue heredocs up */ - } -break; -case 20: -#line 85 "parse.y" -{ yyval.node = mk(nRedir,yyvsp[-1].redir.type,yyvsp[-1].redir.fd,yyvsp[0].node); - if (yyvsp[-1].redir.type == rHeredoc && !qdoc(yyvsp[0].node, yyval.node)) YYABORT; /* queue heredocs up */ - } -break; -case 21: -#line 89 "parse.y" -{ yyval.node = mk(nCase, yyvsp[-1].node); } -break; -case 22: -#line 90 "parse.y" -{ yyval.node = mk(nCase, yyvsp[-1].node); } -break; -case 23: -#line 92 "parse.y" -{ yyval.node = mk(nCbody, yyvsp[0].node, NULL); } -break; -case 24: -#line 93 "parse.y" -{ yyval.node = mk(nCbody, yyvsp[-1].node, yyvsp[0].node); } -break; -case 25: -#line 94 "parse.y" -{ yyval.node = mk(nCbody, yyvsp[-1].node, yyvsp[0].node); } -break; -case 27: -#line 97 "parse.y" -{ yyval.node = mk(nElse,yyvsp[-3].node,yyvsp[0].node); } -break; -case 28: -#line 99 "parse.y" -{ yyval.node = NULL; } -break; -case 30: -#line 101 "parse.y" -{ yyval.node = mk(nBrace,yyvsp[-1].node,yyvsp[0].node); } -break; -case 31: -#line 102 "parse.y" -{ yyval.node = mk(nIf,yyvsp[-2].node,yyvsp[0].node); } -break; -case 32: -#line 103 "parse.y" -{ yyval.node = mk(nForin,yyvsp[-5].node,yyvsp[-3].node,yyvsp[0].node); } -break; -case 33: -#line 104 "parse.y" -{ yyval.node = mk(nForin,yyvsp[-3].node,star,yyvsp[0].node); } -break; -case 34: -#line 105 "parse.y" -{ yyval.node = mk(nWhile,yyvsp[-2].node,yyvsp[0].node); } -break; -case 35: -#line 106 "parse.y" -{ yyval.node = mk(nSwitch,yyvsp[-5].node,yyvsp[-1].node); } -break; -case 36: -#line 107 "parse.y" -{ yyval.node = mk(nMatch,yyvsp[-1].node,yyvsp[0].node); } -break; -case 37: -#line 108 "parse.y" -{ yyval.node = mk(nAndalso,yyvsp[-3].node,yyvsp[0].node); } -break; -case 38: -#line 109 "parse.y" -{ yyval.node = mk(nOrelse,yyvsp[-3].node,yyvsp[0].node); } -break; -case 39: -#line 110 "parse.y" -{ yyval.node = mk(nPipe,yyvsp[-2].pipe.left,yyvsp[-2].pipe.right,yyvsp[-3].node,yyvsp[0].node); } -break; -case 40: -#line 111 "parse.y" -{ yyval.node = (yyvsp[0].node != NULL ? mk(nPre,yyvsp[-1].node,yyvsp[0].node) : yyvsp[-1].node); } -break; -case 41: -#line 112 "parse.y" -{ yyval.node = (yyvsp[0].node != NULL ? mk(nPre,yyvsp[-1].node,yyvsp[0].node) : yyvsp[-1].node); } -break; -case 42: -#line 113 "parse.y" -{ yyval.node = mk(nBang,yyvsp[0].node); } -break; -case 43: -#line 114 "parse.y" -{ yyval.node = mk(nSubshell,yyvsp[0].node); } -break; -case 44: -#line 115 "parse.y" -{ yyval.node = mk(nNewfn,yyvsp[-1].node,yyvsp[0].node); } -break; -case 45: -#line 116 "parse.y" -{ yyval.node = mk(nRmfn,yyvsp[0].node); } -break; -case 49: -#line 122 "parse.y" -{ yyval.node = (yyvsp[0].node != NULL ? mk(nArgs,yyvsp[-1].node,yyvsp[0].node) : yyvsp[-1].node); } -break; -case 50: -#line 123 "parse.y" -{ yyval.node = mk(nArgs,yyvsp[-1].node,yyvsp[0].node); } -break; -case 52: -#line 126 "parse.y" -{ yyval.node = mk(nConcat,yyvsp[-2].node,yyvsp[0].node); } -break; -case 54: -#line 129 "parse.y" -{ yyval.node = mk(nWord,yyvsp[0].keyword, NULL); } -break; -case 56: -#line 132 "parse.y" -{ yyval.node = mk(nConcat,yyvsp[-2].node,yyvsp[0].node); } -break; -case 57: -#line 134 "parse.y" -{ yyval.node = mk(nVar,yyvsp[0].node); } -break; -case 58: -#line 135 "parse.y" -{ yyval.node = mk(nVarsub,yyvsp[-3].node,yyvsp[-1].node); } -break; -case 59: -#line 136 "parse.y" -{ yyval.node = mk(nCount,yyvsp[0].node); } -break; -case 60: -#line 137 "parse.y" -{ yyval.node = mk(nFlat, yyvsp[0].node); } -break; -case 61: -#line 138 "parse.y" -{ yyval.node = mk(nBackq,nolist,yyvsp[0].node); } -break; -case 62: -#line 139 "parse.y" -{ yyval.node = mk(nBackq,nolist,yyvsp[0].node); } -break; -case 63: -#line 140 "parse.y" -{ yyval.node = mk(nBackq,yyvsp[-1].node,yyvsp[0].node); } -break; -case 64: -#line 141 "parse.y" -{ yyval.node = mk(nBackq,yyvsp[-1].node,yyvsp[0].node); } -break; -case 65: -#line 142 "parse.y" -{ yyval.node = yyvsp[-1].node; } -break; -case 66: -#line 143 "parse.y" -{ yyval.node = mk(nNmpipe,yyvsp[-1].redir.type,yyvsp[-1].redir.fd,yyvsp[0].node); } -break; -case 67: -#line 144 "parse.y" -{ yyval.node = (yyvsp[0].word.w[0] == '\'') ? mk(nQword, yyvsp[0].word.w+1, NULL) : mk(nWord,yyvsp[0].word.w, yyvsp[0].word.m); } -break; -case 68: -#line 146 "parse.y" -{ yyval.keyword = "for"; } -break; -case 69: -#line 147 "parse.y" -{ yyval.keyword = "in"; } -break; -case 70: -#line 148 "parse.y" -{ yyval.keyword = "while"; } -break; -case 71: -#line 149 "parse.y" -{ yyval.keyword = "if"; } -break; -case 72: -#line 150 "parse.y" -{ yyval.keyword = "switch"; } -break; -case 73: -#line 151 "parse.y" -{ yyval.keyword = "fn"; } -break; -case 74: -#line 152 "parse.y" -{ yyval.keyword = "else"; } -break; -case 75: -#line 153 "parse.y" -{ yyval.keyword = "case"; } -break; -case 76: -#line 154 "parse.y" -{ yyval.keyword = "~"; } -break; -case 77: -#line 155 "parse.y" -{ yyval.keyword = "!"; } -break; -case 78: -#line 156 "parse.y" -{ yyval.keyword = "@"; } -break; -case 79: -#line 158 "parse.y" -{ yyval.node = NULL; } -break; -case 80: -#line 159 "parse.y" -{ yyval.node = (yyvsp[-1].node != NULL ? (yyvsp[0].node != NULL ? mk(nLappend,yyvsp[-1].node,yyvsp[0].node) : yyvsp[-1].node) : yyvsp[0].node); } -break; -case 81: -#line 161 "parse.y" -{ yyval.node = NULL; } -break; -case 83: -#line 163 "parse.y" -{ yyval.node = (yyvsp[-1].node != NULL ? (yyvsp[0].node != NULL ? mk(nLappend,yyvsp[-1].node,yyvsp[0].node) : yyvsp[-1].node) : yyvsp[0].node); } -break; -#line 1015 "y.tab.c" - } - yyssp -= yym; - yystate = *yyssp; - yyvsp -= yym; - yym = yylhs[yyn]; - if (yystate == 0 && yym == 0) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state 0 to\ - state %d\n", YYPREFIX, YYFINAL); -#endif - yystate = YYFINAL; - *++yyssp = YYFINAL; - *++yyvsp = yyval; - if (yychar < 0) - { - if ((yychar = yylex()) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, YYFINAL, yychar, yys); - } -#endif - } - if (yychar == 0) goto yyaccept; - goto yyloop; - } - if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yystate) - yystate = yytable[yyn]; - else - yystate = yydgoto[yym]; -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state %d \ -to state %d\n", YYPREFIX, *yyssp, yystate); -#endif - if (yyssp >= yyss + yystacksize - 1) - { - goto yyoverflow; - } - *++yyssp = yystate; - *++yyvsp = yyval; - goto yyloop; -yyoverflow: - yyerror("yacc stack overflow"); -yyabort: - return (1); -yyaccept: - return (0); -} diff --git a/y.tab.h b/y.tab.h @@ -1,33 +0,0 @@ -#define ANDAND 257 -#define BACKBACK 258 -#define BANG 259 -#define CASE 260 -#define COUNT 261 -#define DUP 262 -#define ELSE 263 -#define END 264 -#define FLAT 265 -#define FN 266 -#define FOR 267 -#define IF 268 -#define IN 269 -#define OROR 270 -#define PIPE 271 -#define REDIR 272 -#define SREDIR 273 -#define SUB 274 -#define SUBSHELL 275 -#define SWITCH 276 -#define TWIDDLE 277 -#define WHILE 278 -#define WORD 279 -#define HUH 280 -typedef union { - struct Node *node; - struct Redir redir; - struct Pipe pipe; - struct Dup dup; - struct Word word; - char *keyword; -} YYSTYPE; -extern YYSTYPE yylval;