home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume35
/
zsh
/
part17
< prev
next >
Wrap
Text File
|
1993-02-20
|
56KB
|
2,300 lines
Newsgroups: comp.sources.misc
From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Subject: v35i067: zsh - The Z Shell, version 2.3.1, Part17/22
Message-ID: <1993Feb20.212754.29286@sparky.imd.sterling.com>
X-Md4-Signature: ceaaa9f6e26a57c085f8974ff8feb0c1
Date: Sat, 20 Feb 1993 21:27:54 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
Posting-number: Volume 35, Issue 67
Archive-name: zsh/part17
Environment: UNIX
Supersedes: zsh2.2: Volume 29, Issue 97-113
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: help/popd man/man1/zsh.1.03 src/builtin.c.02 src/subst.c
# Wrapped by mattson@odin on Sat Feb 6 14:41:55 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 17 (of 22)."'
if test -f 'help/popd' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'help/popd'\"
else
echo shar: Extracting \"'help/popd'\" \(609 characters\)
sed "s/^X//" >'help/popd' <<'END_OF_FILE'
X popd [ +-n ]
X Removes entries from the directory stack. With no
X arguments, removes the top directory from the stack,
X and performs a cd to the new top directory. With an
X argument of the form +n, remove the nth entry counting
X from the left of the list shown by the dirs command,
X starting with zero, and change to that directory. With
X an argument of the form -n, remove the nth entry count-
X ing from the right. If the PUSHD_MINUS option is set,
X the meanings of + and - in this context are swapped.
END_OF_FILE
if test 609 -ne `wc -c <'help/popd'`; then
echo shar: \"'help/popd'\" unpacked with wrong size!
fi
# end of 'help/popd'
fi
if test -f 'man/man1/zsh.1.03' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'man/man1/zsh.1.03'\"
else
echo shar: Extracting \"'man/man1/zsh.1.03'\" \(17067 characters\)
sed "s/^X//" >'man/man1/zsh.1.03' <<'END_OF_FILE'
X\fBlet\fP \fIarg\fP ...
XEvaluate each \fIarg\fP as an arithmetic expression.
XSee \fBARITHMETIC EVALUATION\fP above for a description
Xof arithmetic expressions. The exit status is 0 if the
Xvalue of the last expression is nonzero, and 1 otherwise.
X.TP
X.PD 0
X\fBlimit\fP [ \-\fBh\fP ] [ \fIresource\fP [ \fIlimit\fP ] ] ...
X.TP
X\fBlimit\fP \-\fBs\fP
X.PD
XLimit the resource consumption of children of the current shell.
XIf \fIlimit\fP is not specified, print the current limit placed
Xon \fIresource\fP; otherwise
Xset the limit to the specified value. If the \-\fBh\fP flag
Xis given, use hard limits instead of soft limits.
XIf no \fIresource\fP is given, print all limits.
X.RS
X.PP
X\fIresource\fP is one of:
X.PP
X.PD 0
X.TP
X.B cputime
XMaximum CPU seconds per process.
X.TP
X.B filesize
XLargest single file allowed.
X.TP
X.B datasize
XMaximum data size (including stack) for each process.
X.TP
X.B stacksize
XMaximum stack size for each process.
X.TP
X.B coredumpsize
XMaximum size of a core dump.
X.TP
X.B resident
XMaximum resident set size.
X.TP
X.B descriptors
XMaximum value for a file descriptor.
X.PD
X.PP
X\fIlimit\fP is a number, with an optional scaling factor, as follows:
X.PP
X.PD 0
X.TP
X\fIn\fPh
Xhours.
X.TP
X\fIn\fPk
Xkilobytes.
XThis is the default for all but cputime.
X.TP
X\fIn\fPm
Xmegabytes or minutes.
X.TP
X\fImm\fP:\fBss\fP
Xminutes and seconds.
X.PD
X.RE
X.TP
X\fBlocal\fP
XSame as \fBtypeset\fP.
X.TP
X\fBlog\fP
XList all users currently logged in who are affected by
Xthe current setting of the \fBwatch\fP parameter.
X.TP
X\fBlogout\fP
XExit the shell, if this is a login shell.
X.TP
X\fBpopd\fP [ \(+-\fIn\fP ]
XRemoves entries from the directory stack. With no arguments,
Xremoves the top directory from the stack, and performs a \fBcd\fP
Xto the new top directory. With an argument of the form +\fIn\fP,
Xremove the \fIn\fPth entry counting from the left of the list
Xshown by the \fBdirs\fP command, starting with zero, and change
Xto that directory. With an argument of the form \-\fIn\fP,
Xremove the \fIn\fPth entry counting from the right.
XIf the \fBPUSHD_MINUS\fP option is set, the meanings of +
Xand \- in this context are swapped.
X.TP
X\fBprint\fP [ \-\fBRnrslzpNDP\fP ] [ \-\fBu\fP\fIn\fP ] [ \fIarg\fP ... ]
XWith no flags or with flag \-, the arguments are printed on
Xthe standard output as described by \fBecho\fP.
X.RS
X.PD 0
X.TP
X\-\fBR\fP, \-\fBr\fP
Xignore the escape conventions of \fBecho\fP.
XThe \-\fBR\fP option will print all subsequent
Xarguments and options.
X.TP
X\-\fBs\fP
Xplace the results in the history list instead of on the standard output.
X.TP
X\-\fBn\fP
Xdo not add a newline to the output.
X.TP
X\-\fBl\fP
Xprint the arguments separated by newlines instead of spaces.
X.TP
X\-\fBN\fP
Xprint the arguments separated and terminated by nulls.
X.TP
X\-\fBu\fP\fIn\fP
Xprint the arguments to file descriptor \fIn\fP.
X.TP
X\-\fBp\fP
Xprint the arguments to the input of the coprocess.
X.TP
X\-\fBz\fP
Xpush the arguments onto the editing buffer stack, separated by spaces;
Xno escape sequences are recognized.
X.TP
X\-\fBD\fP
Xtreat the arguments as directory names, replacing prefixes with ~
Xexpressions, as appropriate.
X.TP
X\-\fBP\fP
Xrecognize the same escape sequences as in the \fBPROMPT\fP parameter.
X.PD
X.RE
X.TP
X.PD 0
X\fBpushd\fP [ \fIarg\fP ]
X.TP
X\fBpushd\fP \fIold\fP \fInew\fP
X.TP
X\fBpushd\fP \(+-\fBn\fP
X.PD
XChange the current directory, and push the old current directory
Xonto the directory stack. In the first form, change the
Xcurrent directory to \fIarg\fP.
XIf \fIarg\fP is not specified, change to the second directory
Xon the stack (that is, exchange the top two entries), or
Xchange to the value of \fBHOME\fP if the \fBPUSHD_TO_HOME\fP
Xoption is set or if there is only one entry on the stack.
XIf \fIarg\fP is \-, change to the
Xvalue of \fBOLDPWD\fP, the previous directory.
XIf a directory named \fIarg\fP is not found in the current directory
Xand \fIarg\fP does not contain a slash,
Xsearch each component of the shell parameter \fBcdpath\fP.
XIf the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP
Xexists whose value begins with a slash, treat its value as
Xthe directory.
XIf the option \fBPUSHD_SILENT\fP is not set, the directory
Xstack will be printed after a \fBpushd\fP is performed.
X.RS
X.PP
XThe second form of \fBpushd\fP substitutes the string \fInew\fP
Xfor the string \fIold\fP in the name of the current directory,
Xand tries to change to this new directory.
X.PP
XThe third form of \fBpushd\fP is equivalent to \fBpopd\fP.
X.RE
X.TP
X\fBpwd\fP
XEquivalent to \fBprint \-R $PWD\fP.
X.TP
X\fBr\fP
XEquivalent to \fBfc \-e \-\fP.
X.TP
X\fBread\fP [ \-\fBrzp\fP ] [ \-\fBu\fIn\fR ] [ \fIname\fP?\fIprompt\fP ] [ \fIname\fP ... ]
XRead one line and break it into fields using the characters
Xin \fBIFS\fP as separators. In raw mode, \-\fBr\fP, a \e
Xat the end of a line does not signify line continuation.
XIf the \-\fBz\fP flag is set, read from the editor buffer stack.
XThe first field is assigned to the first \fIname\fP, the second field
Xto the second \fIname\fP, etc., with leftover
Xfields assigned to the last \fIname\fP.
XIf \fIname\fP is omitted then \fBREPLY\fP is used.
XIf \-\fBu\fIn\fR is specified, then input is read from file
Xdescriptor \fIn\fP; if \-\fBp\fP is specified, then input is
Xread from the coprocess.
XThe exit status is 0 unless end-of-file is encountered.
XIf the first argument contains a \fB?\fP, the remainder of this
Xword is used as a \fIprompt\fP on standard error when the shell
Xis interactive. The exit status is 0 unless an end-of-file
Xis encountered.
X.TP
X\fBreadonly\fP [ \fIname\fP[=\fIvalue\fP] ] ...
XThe given \fInames\fP are marked readonly; these names
Xcannot be changed by subsequent assignment.
X.TP
X\fBrehash\fP [ \-\fBf\fP ]
XThrow out the command hash table and start over.
XIf the \-\fBf\fP option is set, rescan the command path
Ximmediately, instead of rebuilding the hash table incrementally.
X.TP
X\fBreturn\fP [ \fIn\fP ]
XCauses a shell function or \fB\&.\fP script to return to
Xthe invoking script
Xwith the return status specified by \fIn\fP. If \fIn\fP
Xis omitted then the return status is that of the last command
Xexecuted.
X.TP
X.PD 0
X\fBsched\fP [+]\fIhh\fP:\fImm\fP \fIcommand\fP ...
X.TP
X\fBsched\fP [ \-\fIitem\fP ]
X.PD
XMake an entry in the scheduled list of commands to execute.
XThe time may be specified in either absolute or relative time.
XWith no arguments, prints the list of scheduled commands.
XWith the argument \-\fIitem\fP, removes the given item
Xfrom the list.
X.TP
X\fBset\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption name\fP ] ... [ \-\fBA\fP \fIname\fP ] [ \fIarg\fP ] ...
XSet the options for the shell and/or set the positional parameters, or
Xdeclare an array. For the meaning of the flags, see
X\fBOPTIONS\fP above.
XFlags may be specified by name using the \-\fBo\fP option.
XIf the \-\fBA\fP flag is specified, \fIname\fP is set to an
Xarray containing the given \fIarg\fPs.
XOtherwise the positional parameters are set.
XIf no arguments are given, then the names and values
Xof all parameters are printed on the standard output.
XIf the only argument is +, the names of all parameters are printed.
X.TP
X\fBsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
XSet the options for the shell. All options specified either
Xwith flags or by name are set. If no arguments are supplied,
Xthe names of all options currently set are printed.
XIn option names, case is insignificant, and all underscore
Xcharacters are ignored.
X.TP
X\fBshift\fP [ \fIn\fP ]
XThe positional parameters from $\fIn\fP+\fB1\fP ... are renamed
X$\fB1\fP, where \fIn\fP is an arithmetic expression that
Xdefaults to 1.
X.TP
X\fBsource\fP
XSame as \fB.\fP.
X.TP
X\fBsuspend\fP [ \-\fBf\fP ]
XSuspend the execution of the shell (send it a \fBSIGTSTP\fP)
Xuntil it receives a \fBSIGCONT\fP.
XIf the \-\fBf\fP option is not given, complain if this is a login shell.
X.TP
X.PD 0
X\fBtest\fP \fIarg\fP ...
X.TP
X\fB[\fP \fIarg\fP ... \fB]\fP
X.PD
XLike the system version of \fBtest\fP. Added for compatibility;
Xuse conditional expressions instead.
X.TP
X\fBtimes\fP
XPrint the accumulated user and system times for the shell
Xand for processes run from the shell.
X.TP
X\fBtrap\fP [ \fIarg\fP ] [ \fIsig\fP ] ...
X\fIarg\fP is a command to be read and executed when the shell
Xreceives \fIsig\fP. Each \fIsig\fP can be given as a number
Xor as the name of a signal.
XIf \fIarg\fP is \-, then all traps \fIsig\fP are reset to their
Xdefault values. If \fIarg\fP is the null string, then this signal
Xis ignored by the shell and by the commands it invokes.
XIf \fIsig\fP is \fBERR\fP then \fIarg\fP will be executed
Xafter each command.
XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
Xand the \fBtrap\fP statement is executed inside the body of a function,
Xthen the command \fIarg\fP is executed after the function completes.
XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
Xand the \fBtrap\fP statement is not executed inside the body of a function,
Xthen the command \fIarg\fP is executed when the shell terminates.
XThe \fBtrap\fP command with no arguments prints a list of commands
Xassociated with each signal.
X.TP
X\fBtrue\fP
XDo nothing and return an exit code of 0.
X.TP
X\fBttyctl\fP \-\fBfu\fP
XThe \-\fBf\fP option freezes the tty, and \-\fBu\fP unfreezes it.
XWhen the tty is frozen, no changes made to the tty settings by
Xexternal programs will be honored by the shell; the shell will
Xsimply reset the settings to their previous values as soon as each
Xcommand exits. Thus, \fBstty\fP and similar programs have no
Xeffect when the tty is frozen.
X.TP
X\fBtype\fP
XSame as \fBwhence\fP \-\fBv\fP.
X.TP
X\fBtypeset\fP [ \(+-\fBLRZfilrtux [\fIn\fP]] [ \fIname\fP[=\fIvalue\fP] ] ...
XSet attributes and values for shell parameters.
XWhen invoked inside a function, if \fIname\fP is not already
Xdefined, a new parameter is created which will be unset when the
Xfunction completes.
XThe following attributes are valid:
X.RS
X.PD 0
X.TP
X\-\fBL\fP
XLeft justify and remove leading blanks from \fIvalue\fP.
XIf \fIn\fP is nonzero, it defines the width of the field;
Xotherwise it is determined by the width of the value of the first
Xassignment.
XWhen the parameter is printed, it is filled on the right with
Xblanks or truncated if necessary to fit the field.
XLeading zeros are removed if the \-\fBZ\fP flag is also set.
X.TP
X\-\fBR\fP
XRight justify and fill with leading blanks. If \fIn\fP is nonzero
Xif defines the width of the field;
Xotherwise it is determined by the width of the value of the first
Xassignment.
XWhen the parameter is printed, the field is left filled with
Xblanks or truncated from the end.
X.TP
X\-\fBZ\fP
XRight justify and fill with leading zeros if the first non-blank
Xcharacter is a digit and the \-\fBL\fP flag has not been set.
XIf \fIn\fP is nonzero it defines the width of the field;
Xotherwise it is determined by the width of the value of the
Xfirst assignment.
X.TP
X\-\fBf\fP
XThe names refer to functions rather than parameters. No assignments
Xcan be made, and the only other valid flags are \-\fBt\fP
Xand \-\fBu\fP. The flag \-\fBt\fP turns on execution tracing for this
Xfunction. The flag \-\fBu\fP causes this function to be marked
Xfor autoloading. The \fBfpath\fP parameter will be searched to find the
Xfunction definition when the function is first referenced.
X.TP
X\-\fBi\fP
XUse an internal integer representation. If \fBi\fP is nonzero
Xit defines the output arithmetic base, otherwise it is determined by the first
Xassignment.
X.TP
X\-\fBl\fP
XConvert to lower case.
X.TP
X\-\fBr\fP
XThe given \fIname\fPs are marked readonly.
X.TP
X\-\fBt\fP
XTags the named parameters. Tags have no special meaning to the shell.
X.TP
X\-\fBu\fP
XConvert to upper case.
X.TP
X\-\fBx\fP
XMark for automatic export to the environment of subsequently
Xexecuted commands.
X.RE
X.PD
X.PP
XUsing + rather than \- causes these flags to be turned off.
XIf no arguments are given but flags are specified,
Xa list of named parameters which have these flags set is printed.
XUsing + instead of \- keeps their values from being printed.
XIf no arguments or options are given, the names and attributes
Xof all parameters are printed.
X.TP
X\fBulimit\fP [ \-\fBHSacdfmnt\fP ] [ \fIlimit\fP ]
XSet or display a resource limit. The value of limit can be a number
Xin the unit specified below or the value \fBunlimited\fP.
XThe \fBH\fP and \fBS\fP flags specify whether the hard limit
Xor the soft limit for the given resource is set.
X.RS
X.PD 0
X.TP
X\-\fBa\fP
XLists all of the current resource limits.
X.TP
X\-\fBc\fP
XThe number of 512-byte blocks on the size of core dumps.
X.TP
X\-\fBd\fP
XThe number of K-bytes on the size of the data segment.
X.TP
X\-\fBf\fP
XThe number of 512-byte blocks on the size of files written.
X.TP
X\-\fBm\fP
XThe number of K-bytes on the size of physical memory.
X.TP
X\-\fBn\fP
XThe number of file descriptors.
X.TP
X\-\fBs\fP
XThe number of K-bytes on the size of the stack.
X.TP
X\-\fBt\fP
XThe number of CPU seconds to be used.
X.RE
X.PD
X.TP
X\fBumask\fP [ \fImask\fP ]
XThe umask is set to \fImask\fP. \fImask\fP can be either
Xan octal number or a symbolic value as described in \fBchmod\fP(1).
XIf \fImask\fP is omitted, the current value is printed.
X.TP
X\fBunalias\fP \fIname\fP ...
XThe alias definition, if any, for each \fIname\fP is removed.
X.TP
X\fBunfunction\fP \fIname\fP ...
XThe function definition, if any, for each \fIname\fP is removed.
X.TP
X\fBunhash\fP \fIname\fP ...
XThe entry in the command hash table, if any, for each \fIname\fP
Xis removed.
X.TP
X\fBunlimit\fP [ \-\fBh\fP ] \fIresource\fP ...
XThe resource limit for each \fIresource\fP is set to the hard limit.
XIf the \-\fBh\fP flag is given and the shell is running as root,
Xthe hard resource limit for each \fIresource\fP is removed.
X.TP
X\fBunset\fP \fIname\fP ...
XEach named parameter is unset.
X.TP
X\fBunsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
XUnset the options for the shell. All options specified either
Xwith flags or by name are unset.
X.TP
X\fBvared\fP \fIname\fP
XThe value of the parameter \fIname\fP is loaded into the edit
Xbuffer, and the line editor is invoked. When the editor exits,
X\fIname\fP is set to the string value returned by the editor.
X.TP
X\fBwait\fP [ \fIjob\fP ... ]
XWait for the specified jobs or processes. If \fIjob\fP is not given
Xthen all currently active child processes are waited for.
XEach \fIjob\fP can be either a job specification or the process-id
Xof a job in the job table.
XThe exit status from this command is that of the job waited for.
X.TP
X\fBwhence\fP [ \-\fBacpv\fP ] \fIname\fP ...
XFor each name, indicate how it would be interpreted if used
Xas a command name. The \-\fBv\fP flag produces a more verbose
Xreport. The \-\fBp\fP flag does a path search for \fIname\fP
Xeven if it is a shell function, alias, or reserved word.
XThe \-\fBc\fP flag prints the results in a csh-like format.
XThe \-\fBa\fP flag does a search for all occurences of \fIname\fP
Xthroughout the command path.
X.TP
X\fBwhich\fP
XSame as \fBwhence \-c\fP.
X.RE
X.SH INVOCATION
XCommands are first read from /etc/zshenv.
XThen, if the \fBNO_RCS\fP option is unset, commands are read
Xfrom $ZDOTDIR/.zshenv.
X(If \fBZDOTDIR\fP is unset, \fBHOME\fP is used instead).
XIf the first character of argument zero passed to the shell
Xis \-, or if the \-\fBl\fP flag is present, then the shell is
Xassumed to be a login shell, and commands
Xare read from /etc/zprofile and then $ZDOTDIR/.zprofile.
XThen, if the shell is interactive and the \fBNO_RCS\fP option is unset,
Xcommands are read from /etc/zshrc and then $ZDOTDIR/.zshrc.
XFinally, if the shell is a login shell, /etc/zlogin and $ZDOTDIR/.zlogin
Xare read.
X.PP
XIf the \fBNO_RCS\fP option is set within /etc/zshenv, then only /etc/zprofile,
X/etc/zshrc, and /etc/zlogin are read, and the $ZDOTDIR files are skipped.
XIf the \-\fBf\fP flag is present, only /etc/zshenv is read, and all other
Xinitialization files are skipped.
X.PP
XIf the \-\fBs\fP flag is not present and an argument is given,
Xthe first argument is taken to be the pathname of a script to
Xexecute. The remaining arguments are assigned to the positional
Xparameters. The following flags are interpreted by the shell
Xwhen invoked:
X.TP
X.PD 0
X\-\fBc\fP \fIstring\fP
XRead commands from \fIstring\fP.
X.TP
X\-\fBs\fP
XRead command from the standard input.
X.TP
X\-\fBi\fP
XIf this flag is present or the shell input and output
Xare attached to a terminal, this shell is interactive.
X.PD
X.SH "SEE ALSO"
Xsh(1),
Xcsh(1),
Xtcsh(1),
Xitcsh(1),
Xrc(1),
Xbash(1),
Xash(1),
Xksh(1),
Xclam(1),
Xstrftime(3).
X.SH FILES
X$ZDOTDIR/.zshenv
X.br
X$ZDOTDIR/.zprofile
X.br
X$ZDOTDIR/.zshrc
X.br
X$ZDOTDIR/.zlogin
X.br
X$ZDOTDIR/.zlogout
X.br
X/tmp/zsh*
X.br
X/etc/zshenv
X.br
X/etc/zprofile
X.br
X/etc/zshrc
X.br
X/etc/zlogin
X.SH AUTHOR
XPaul Falstad (pf@ttisms.com)
X.SH AVAILABILITY
XThe latest official release of zsh is available via anonymous ftp from
Xcs.ucsd.edu (132.239.51.3), in the directory pub/zsh. The beta release
Xof zsh 2.4 is available from carlo.phys.uva.nl (145.18.220.25), in the
Xdirectory pub/bas/zsh. This man page is current to zsh 2.3.1.
X.SH "UNDOCUMENTED FEATURES"
XKnown only to the recipients of the zsh mailing list, zsh-list@cs.uow.edu.au.
XIf you run into problems, please send your questions and patches to the
Xmailing list. To join the list, send email to zsh-request@cs.uow.edu.au.
END_OF_FILE
if test 17067 -ne `wc -c <'man/man1/zsh.1.03'`; then
echo shar: \"'man/man1/zsh.1.03'\" unpacked with wrong size!
fi
# end of 'man/man1/zsh.1.03'
fi
if test -f 'src/builtin.c.02' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/builtin.c.02'\"
else
echo shar: Extracting \"'src/builtin.c.02'\" \(16952 characters\)
sed "s/^X//" >'src/builtin.c.02' <<'END_OF_FILE'
Xchar *s;char *t;
Xstruct param *pm;
X
X if (!(s = getsparam(args[0]))) {
X zerrnam(name,"no such variable: %s",args[0],0);
X return 1;
X }
X permalloc();
X pushnode(bufstack,ztrdup(s));
X heapalloc();
X t = (char *) zleread((unsigned char *)"> ",NULL,2);
X if (!t || errflag)
X return 1;
X if (t[strlen(t)-1] == '\n')
X t[strlen(t)-1] = '\0';
X pm = gethnode(args[0],paramtab);
X if (pmtype(pm) == PMFLAG_A)
X setaparam(args[0],spacesplit(t));
X else
X setsparam(args[0],t);
X return 0;
X}
X
X#define fset(X) (flags & X)
X
X/* execute a builtin handler function after parsing the arguments */
X
Xint execbin(args,cnode) /**/
XLklist args;Cmdnam cnode;
X{
Xstruct bincmd *b;
Xchar ops[128],*arg,*pp,*name,**argv,**oargv,*optstr;
Xint t0,flags,sense,argc = 0,op;
XLknode n;
X
X auxdata = NULL;
X auxlen = 0;
X for (t0 = 0; t0 != 128; t0++)
X ops[t0] = 0;
X name = ugetnode(args);
X b = builtins+cnode->u.binnum;
X
X/* the 'builtin' builtin is handled specially */
X
X if (b->funcid == BIN_BUILTIN)
X {
X if (!(name = ugetnode(args)))
X {
X zerrnam("builtin","command name expected",NULL,0);
X return 1;
X }
X for (b = builtins; b->name; b++)
X if (!strcmp(name,b->name))
X break;
X if (!b->name)
X {
X zerrnam("builtin","no such builtin: %s",name,0);
X return 1;
X }
X }
X flags = b->flags;
X arg = ugetnode(args);
X optstr = b->optstr;
X if (flags & BINF_ECHOPTS && arg && strcmp(arg,"-n"))
X optstr = NULL;
X if (optstr)
X while (arg &&
X ((sense = *arg == '-') || (fset(BINF_PLUSOPTS) && *arg == '+')) &&
X (fset(BINF_PLUSOPTS) || !atoi(arg)))
X {
X if (arg[1] == '-')
X arg++;
X if (!arg[1])
X {
X ops['-'] = 1;
X if (!sense)
X ops['+'] = 1;
X }
X else
X ops['@'] = 1;
X op = -1;
X while (*++arg)
X if (strchr(b->optstr,op = *arg))
X ops[(int)*arg] = (sense) ? 1 : 2;
X else
X break;
X if (*arg)
X {
X zerr("bad option: %c",NULL,*arg);
X return 1;
X }
X arg = ugetnode(args);
X if (fset(BINF_SETOPTS) && op == 'o')
X {
X int c;
X
X if (!arg)
X prtopt();
X else
X {
X c = optlookup(arg);
X if (c == -1)
X {
X zerr("bad option: %s",arg,0);
X return 1;
X }
X else
X {
X if (c == INTERACTIVE)
X zerr("can't change option: %s",arg,0);
X else
X ops[c] = ops['o'];
X arg = ugetnode(args);
X }
X }
X }
X if ((fset(BINF_PRINTOPTS) && ops['R']) || ops['-'])
X break;
X if (fset(BINF_SETOPTS) && ops['A'])
X {
X auxdata = arg;
X arg = ugetnode(args);
X break;
X }
X if (fset(BINF_FCOPTS) && op == 'e')
X {
X auxdata = arg;
X arg = ugetnode(args);
X }
X if (fset(BINF_TYPEOPT) && (op == 'L' || op == 'R' ||
X op == 'Z' || op == 'i') && arg && idigit(*arg))
X {
X auxlen = atoi(arg);
X arg = ugetnode(args);
X }
X }
X if (fset(BINF_R))
X auxdata = "-";
X if (pp = b->defopts)
X while (*pp)
X ops[(int)*pp++] = 1;
X if (arg)
X {
X argc = 1;
X n = firstnode(args);
X while (n)
X argc++,incnode(n);
X }
X oargv = argv = (char **) ncalloc(sizeof(char **) * (argc+1));
X if (*argv++ = arg)
X while (*argv++ = ugetnode(args));
X argv = oargv;
X if (errflag)
X return 1;
X if (argc < b->minargs || (argc > b->maxargs && b->maxargs != -1)) {
X zerrnam(name,(argc < b->minargs)
X ? "not enough arguments" : "too many arguments",NULL,0);
X return 1;
X }
X if (isset(XTRACE)) {
X char **pp = argv;
X fprintf(stderr,"%s%s",(prompt4) ? prompt4 : "",name);
X while (*pp) fprintf(stderr," %s",*pp++);
X fputc('\n',stderr);
X fflush(stderr);
X }
X return (*(b->handlerfunc))(name,argv,ops,b->funcid);
X}
X
Xstruct asgment *getasg(s) /**/
Xchar *s;
X{
Xstatic struct asgment asg;
X
X if (!s)
X return NULL;
X if (*s == '=')
X {
X zerr("bad assignment",NULL,0);
X return NULL;
X }
X asg.name = s;
X for (; *s && *s != '='; s++);
X if (*s)
X {
X *s = '\0';
X asg.value = s+1;
X }
X else
X asg.value = NULL;
X return &asg;
X}
X
X/* ., source */
X
Xint bin_dot(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xchar **old,*old0;
Xint ret;
Xchar buf[MAXPATHLEN];
Xchar *s,**t,*enam;
X
X if (!*argv)
X return 0;
X old = pparams;
X old0 = argzero;
X if (argv[1]) {
X permalloc();
X pparams = arrdup(argv+1);
X heapalloc();
X }
X enam = argzero = ztrdup(*argv);
X errno = ENOENT;
X ret = 1;
X for (s = argzero; *s; s++)
X if (*s == '/') {
X ret = source(argzero);
X break;
X }
X if (!*s) {
X for (t = path; *t; t++)
X if ((*t)[0] == '.' && !(*t)[1]) {
X ret = source(argzero);
X break;
X } else {
X sprintf(buf,"%s/%s",*t,argzero);
X if (access(buf,F_OK) == 0) {
X ret = source(enam = buf);
X break;
X }
X }
X if (!*t && access(argzero,F_OK) == 0)
X ret = source(enam = argzero);
X }
X if (argv[1]) {
X freearray(pparams);
X pparams = old;
X }
X if (ret) zerrnam(name,"%e: %s",enam,errno);
X free(argzero);
X argzero = old0;
X return ret;
X}
X
Xint bin_set(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xstruct option *opp;
Xchar **x;
X
X if (((ops['+'] && ops['-']) || !ops['-']) && !ops['@'] && !*argv)
X {
X showflag = ~0;
X showflag2 = ops['+'];
X listhtable(paramtab,(HFunc) printparam);
X }
X for (opp = optns; opp->name; opp++)
X if (ops[(int)opp->id] == 1)
X opts[(int)opp->id] = OPT_SET;
X else if (ops[(int)opp->id] == 2)
X opts[(int)opp->id] = OPT_UNSET;
X if (!*argv && !ops['-'])
X return 0;
X permalloc();
X x = arrdup(argv);
X heapalloc();
X if (ops['A'])
X setaparam(auxdata,x);
X else {
X freearray(pparams);
X pparams = x;
X }
X return 0;
X}
X
X#define pttime(X) printf("%dm%ds",(X)/3600,(X)/60%60)
X
Xint bin_times(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xstruct tms buf;
X
X if (times(&buf) == -1)
X return 1;
X pttime(buf.tms_utime);
X putchar(' ');
X pttime(buf.tms_stime);
X putchar('\n');
X pttime(buf.tms_cutime);
X putchar(' ');
X pttime(buf.tms_cstime);
X putchar('\n');
X return 0;
X}
X
Xint bin_getopts(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xchar *optstr = *argv++,*var = *argv++;
Xchar **args = (*argv) ? argv : pparams;
Xstatic int optcind = 1,quiet;
Xchar *str,optbuf[3],*opch = optbuf+1;
X
X if (zoptind < 1) zoptind = 1;
X optbuf[0] = '+'; optbuf[1] = optbuf[2] = '\0';
X if (optarg) free(optarg);
X optarg = ztrdup("");
X setsparam(var,ztrdup(""));
X if (*optstr == ':') {
X quiet = 1;
X optstr++;
X }
X if (zoptind > arrlen(args)) return 1;
X str = args[zoptind-1];
X if ((*str != '+' && *str != '-') || optcind >= strlen(str) ||
X !strcmp("--",str)) {
X if (*str == '+' || *str == '-')
X zoptind++;
X optcind = 0;
X return 1;
X }
X if (!optcind)
X optcind = 1;
X *opch = str[optcind++];
X if (!args[zoptind-1][optcind]) {
X zoptind++;
X optcind = 0;
X }
X for (; *optstr; optstr++)
X if (*opch == *optstr)
X break;
X if (!*optstr) {
X setsparam(var,ztrdup("?"));
X if (quiet) {
X free(optarg); optarg = ztrdup(opch);
X return 0;
X }
X zerr("bad option: %c",NULL,*opch); errflag = 0;
X return 0;
X }
X setsparam(var,ztrdup(opch-(*str == '+')));
X if (optstr[1] == ':') {
X if (!args[zoptind-1]) {
X if (quiet) {
X free(optarg); optarg = ztrdup(opch);
X setsparam(var,ztrdup(":"));
X return 0;
X }
X setsparam(var,ztrdup("?"));
X zerr("argument expected after %c option",NULL,*opch); errflag = 0;
X return 0;
X }
X free(optarg);
X optarg = ztrdup(args[zoptind-1]+optcind);
X zoptind++;
X optcind = 0;
X }
X return 0;
X}
X
X/* get a signal number from a string */
X
Xint getsignum(s) /**/
Xchar *s;
X{
Xint x = atoi(s),t0;
X
X if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
X return x;
X for (t0 = 0; t0 != VSIGCOUNT; t0++)
X if (!strcmp(s,sigs[t0]))
X return t0;
X return -1;
X}
X
Xint bin_trap(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
XList l;
Xchar *arg;
X
X if (!*argv) {
X int t0;
X
X for (t0 = 0; t0 != VSIGCOUNT; t0++)
X if (sigtrapped[t0])
X if (!sigfuncs[t0])
X printf("TRAP%s () {}\n",sigs[t0]);
X else {
X char *s = getpermtext((vptr) sigfuncs[t0]);
X printf("TRAP%s () {\n\t%s\n}\n",sigs[t0],s);
X free(s);
X }
X return 0;
X }
X if (!strcmp(*argv,"-")) {
X int t0;
X
X argv++;
X if (!*argv)
X for (t0 = 0; t0 != VSIGCOUNT; t0++) unsettrap(t0);
X else
X while (*argv) unsettrap(getsignum(*argv++));
X return 0;
X }
X arg = *argv++;
X if (!*arg) l = NULL;
X else if (!(l = parselstring(arg))) {
X zerrnam(name,"couldn't parse trap command",NULL,0);
X popheap();
X return 1;
X }
X for (; *argv; argv++) {
X int sg = getsignum(*argv);
X if (sg == -1) {
X zerrnam(name,"undefined signal: %s",*argv,0);
X break;
X }
X settrap(sg,l);
X }
X if (l) popheap();
X return errflag;
X}
X
Xvoid printulimit(lim,hard) /**/
Xint lim;int hard;
X{
Xlong t0;
X
X#ifdef RLIM_INFINITY
X t0 = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
X switch (lim)
X {
X case RLIMIT_CPU: printf("cpu time (seconds) "); break;
X case RLIMIT_FSIZE: printf("file size (blocks) "); t0 /= 512; break;
X case RLIMIT_DATA: printf("data seg size (kbytes) "); t0 /= 1024; break;
X case RLIMIT_STACK: printf("stack size (kbytes) "); t0 /= 1024; break;
X case RLIMIT_CORE: printf("core file size (blocks) "); t0 /= 512; break;
X#ifdef RLIMIT_RSS
X case RLIMIT_RSS: printf("resident set size (kbytes) "); t0 /= 1024; break;
X#endif
X#ifdef RLIMIT_MEMLOCK
X case RLIMIT_MEMLOCK: printf("locked-in-memory size (kb) "); t0 /= 1024; break;
X#endif
X#ifdef RLIMIT_NPROC
X case RLIMIT_NPROC: printf("processes "); break;
X#endif
X#ifdef RLIMIT_OFILE
X case RLIMIT_OFILE: printf("open files "); break;
X#endif
X#ifdef RLIMIT_NOFILE
X case RLIMIT_NOFILE: printf("file descriptors "); break;
X#endif
X }
X printf("%ld\n",t0);
X#endif
X}
X
Xint bin_ulimit(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint res,hard;
X
X#ifndef RLIM_INFINITY
X zerrnam(name,"not available on this system",NULL,0);
X return 1;
X#else
X hard = ops['H'];
X if (ops['a'] || !ops['@'])
X res = -1;
X else if (ops['t'])
X res = RLIMIT_CPU;
X else if (ops['f'])
X res = RLIMIT_FSIZE;
X else if (ops['d'])
X res = RLIMIT_DATA;
X else if (ops['s'])
X res = RLIMIT_STACK;
X else if (ops['c'])
X res = RLIMIT_CORE;
X#ifdef RLIMIT_RSS
X else if (ops['m'])
X res = RLIMIT_RSS;
X#endif
X#ifdef RLIMIT_MEMLOCK
X else if (ops['l'])
X res = RLIMIT_MEMLOCK;
X#endif
X#ifdef RLIMIT_NPROC
X else if (ops['p'])
X res = RLIMIT_NPROC;
X#endif
X#ifdef RLIMIT_OFILE
X else if (ops['o'])
X res = RLIMIT_OFILE;
X#endif
X#ifdef RLIMIT_NOFILE
X else if (ops['n'])
X res = RLIMIT_NOFILE;
X#endif
X else
X {
X zerrnam(name,"no such limit",NULL,0);
X return 1;
X }
X if (res == -1)
X if (*argv)
X {
X zerrnam(name,"no arguments required after -a",NULL,0);
X return 1;
X }
X else
X {
X int t0;
X
X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
X printulimit(t0,hard);
X return 0;
X }
X if (!*argv)
X printulimit(res,hard);
X else if (strcmp(*argv,"unlimited"))
X {
X long t0;
X
X t0 = atol(*argv);
X switch(res)
X {
X case RLIMIT_FSIZE: case RLIMIT_CORE: t0 *= 512; break;
X case RLIMIT_DATA: case RLIMIT_STACK:
X#ifdef RLIMIT_RSS
X case RLIMIT_RSS:
X#endif
X#ifdef RLIMIT_MEMLOCK
X case RLIMIT_MEMLOCK:
X#endif
X t0 *= 1024; break;
X }
X if (hard)
X {
X if (t0 > limits[res].rlim_max && geteuid())
X {
X zerrnam(name,"can't raise hard limits",NULL,0);
X return 1;
X }
X limits[res].rlim_max = t0;
X }
X else
X {
X if (t0 > limits[res].rlim_max)
X {
X if (geteuid())
X {
X zerrnam(name,"value exceeds hard limit",NULL,0);
X return 1;
X }
X limits[res].rlim_max = limits[res].rlim_cur = t0;
X }
X else
X limits[res].rlim_cur = t0;
X }
X }
X else
X {
X if (hard)
X {
X if (geteuid())
X {
X zerrnam(name,"can't remove hard limits",NULL,0);
X return 1;
X }
X limits[res].rlim_max = RLIM_INFINITY;
X }
X else
X limits[res].rlim_cur = limits[res].rlim_max;
X }
X return 0;
X#endif
X}
X
Xint putraw(c) /**/
Xint c;
X{
X putchar(c);
X return 0;
X}
X
Xint bin_echotc(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xchar *s,buf[2048],*t,*u;
Xint num,argct,t0;
X
X s = *argv++;
X if (!termok)
X return 1;
X if ((num = tgetnum(s)) != -1)
X {
X printf("%d\n",num);
X return 0;
X }
X u = buf;
X t = tgetstr(s,&u);
X if (!t || !*t)
X {
X zerrnam(name,"no such capability: %s",s,0);
X return 1;
X }
X for (argct = 0, u = t; *u; u++)
X if (*u == '%')
X {
X if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' ||
X *u == '+'))
X argct++;
X }
X if (arrlen(argv) != argct)
X {
X zerrnam(name,(arrlen(argv) < argct) ? "not enough arguments" :
X "too many arguments",NULL,0);
X return 1;
X }
X if (!argct)
X tputs(t,1,putraw);
X else
X {
X t0 = (argv[1]) ? atoi(argv[1]) : atoi(*argv);
X tputs(tgoto(t,atoi(*argv),t0),t0,putraw);
X }
X return 0;
X}
X
Xint bin_pwd(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
X printf("%s\n",pwd);
X return 0;
X}
X
X#define TEST_END 0
X#define TEST_INPAR 1
X#define TEST_OUTPAR 2
X#define TEST_STR 3
X#define TEST_AND 4
X#define TEST_OR 5
X#define TEST_NOT 6
X
Xstatic char **tsp;
Xstatic int *tip;
X
Xint bin_test(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xchar **s;
Xint cnt,*arr,*ap;
XCond c;
X
X if (func == BIN_BRACKET)
X {
X for (s = argv; *s; s++);
X if (s == argv || strcmp(s[-1],"]"))
X {
X zerrnam(name,"']' expected",NULL,0);
X return 1;
X }
X s[-1] = NULL;
X }
X for (s = argv, cnt = 0; *s; s++,cnt++);
X ap = arr = alloc((cnt+1)*sizeof *arr);
X for (s = argv; *s; s++,ap++)
X if (!strcmp(*s,"("))
X *ap = TEST_INPAR;
X else if (!strcmp(*s,")"))
X *ap = TEST_OUTPAR;
X else if (!strcmp(*s,"-a"))
X *ap = TEST_AND;
X else if (!strcmp(*s,"-o"))
X *ap = TEST_OR;
X else if (!strcmp(*s,"!"))
X *ap = TEST_NOT;
X else
X *ap = TEST_STR;
X *ap = TEST_END;
X tsp = argv;
X tip = arr;
X c = partest(0);
X if (*tip != TEST_END || errflag)
X {
X zerrnam(name,"parse error",NULL,0);
X return 1;
X }
X return (c) ? !evalcond(c) : 1;
X}
X
XCond partest(level) /**/
Xint level;
X{
XCond a,b;
X
X switch (level)
X {
X case 0:
X a = partest(1);
X if (*tip == TEST_OR)
X {
X tip++,tsp++;
X b = makecond();
X b->left = a;
X b->right = partest(0);
X b->type = COND_OR;
X return b;
X }
X return a;
X case 1:
X a = partest(2);
X if (*tip == TEST_AND)
X {
X tip++,tsp++;
X b = makecond();
X b->left = a;
X b->right = partest(1);
X b->type = COND_AND;
X return b;
X }
X return a;
X case 2:
X if (*tip == TEST_NOT)
X {
X tip++,tsp++;
X b = makecond();
X b->left = partest(2);
X b->type = COND_NOT;
X return b;
X }
X case 3:
X if (*tip == TEST_INPAR)
X {
X tip++,tsp++;
X b = partest(0);
X if (*tip != TEST_OUTPAR)
X {
X zerrnam("test","parse error",NULL,0);
X return NULL;
X }
X tip++,tsp++;
X return b;
X }
X if (tip[0] != TEST_STR)
X {
X zerrnam("test","parse error",NULL,0);
X return NULL;
X }
X else if (tip[1] != TEST_STR)
X {
X b = makecond();
X if (!strcmp(*tsp,"-t"))
X {
X b->left = strdup("1");
X b->type = 't';
X }
X else
X {
X b->left = tsp[0];
X b->type = 'n';
X }
X tip++,tsp++;
X return b;
X }
X else if (tip[2] != TEST_STR)
X {
X b = par_cond_double(tsp[0],tsp[1]);
X tip += 2,tsp += 2;
X return b;
X }
X else
X {
X b = par_cond_triple(tsp[0],tsp[1],tsp[2]);
X tip += 3,tsp += 3;
X return b;
X }
X }
X return NULL;
X}
X
Xint bin_compctl(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint flags = 0;
XCompctl cc = NULL;
Xchar *usrkeys = NULL;
X
X for (; *argv && **argv == '-'; argv++)
X while (*++(*argv)) switch(**argv) {
X case 'c': flags |= CC_COMMPATH; break;
X case 'f': flags |= CC_FILES; break;
X case 'h': flags |= CC_HOSTS; break;
X case 'o': flags |= CC_OPTIONS; break;
X case 'v': flags |= CC_VARS; break;
X case 'b': flags |= CC_BINDINGS; break;
X case 'k':
X flags |= CC_USRKEYS;
X if ((*argv)[1]) { usrkeys = (*argv)+1; *argv = "\0"; }
X else if (!argv[1]) {
X zerrnam(name,"variable name expected after -k",NULL,0);
X return 1;
X } else { usrkeys = *++argv; *argv = "\0"; }
X break;
X case 'C': cc = &cc_compos; break;
X case 'D': cc = &cc_default; break;
X default: zerrnam(name,"bad option: %c",NULL,**argv); return 1;
X }
X if (cc) {
X cc->mask = flags;
X if (cc->keyvar) free(cc->keyvar);
X cc->keyvar = ztrdup(usrkeys);
X }
X if (!*argv) {
X if (!cc) {
X showflag = flags;
X listhtable(compctltab,(HFunc) printcompctl);
X printcompctl("COMMAND",&cc_compos);
X printcompctl("DEFAULT",&cc_default);
X }
X return 0;
X }
X compctl_process(argv,flags,usrkeys);
X return 0;
X}
X
Xvoid printcompctl(s,cc) /**/
Xchar *s;Compctl cc;
X{
Xchar *css = "fchovb";
X
X if (cc->mask & showflag) {
X puts(s);
X } else if (!showflag) {
X int flags = cc->mask;
X printf("%s -",s);
X while (*css) {
X if (flags & 1) putchar(*css);
X css++; flags >>= 1;
X }
X if (flags & 1) printf("k %s",cc->keyvar);
X putchar('\n');
X }
X}
X
Xvoid compctl_process(s,mask,uk) /**/
Xchar **s;int mask;char *uk;
X{
XCompctl cc;
X
X for (;*s;s++) {
X cc = zalloc(sizeof *cc);
X cc->mask = mask; cc->keyvar = ztrdup(uk);
X addhnode(ztrdup(*s),cc,compctltab,freecompctl);
X }
X}
X
Xint bin_ttyctl(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
X if (ops['f'] || !ops['@']) ttyfrozen = 1;
X else if (ops['u']) ttyfrozen = 0;
X return 0;
X}
END_OF_FILE
if test 16952 -ne `wc -c <'src/builtin.c.02'`; then
echo shar: \"'src/builtin.c.02'\" unpacked with wrong size!
fi
# end of 'src/builtin.c.02'
fi
if test -f 'src/subst.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/subst.c'\"
else
echo shar: Extracting \"'src/subst.c'\" \(16309 characters\)
sed "s/^X//" >'src/subst.c' <<'END_OF_FILE'
X/*
X *
X * subst.c - various substitutions
X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X#include <pwd.h>
X
X/* do substitutions before fork */
X
Xvoid prefork(list) /**/
XLklist list;
X{
XLknode node = firstnode(list);
Xint qt;
X
X while (node)
X {
X char *str,*str3;
X
X str = str3 = getdata(node);
X if ((*str == Inang || *str == Outang || *str == Equals) &&
X str[1] == Inpar)
X {
X if (*str == Inang)
X setdata(node,getoutproc(str+2)); /* <(...) */
X else if (*str == Equals)
X setdata(node,getoutputfile(str+2)); /* =(...) */
X else
X setdata(node,getinproc(str+2)); /* >(...) */
X if (!getdata(node))
X {
X zerr("parse error in process substitution",NULL,0);
X return;
X }
X }
X else while (*str)
X {
X if ((qt = *str == Qstring) || *str == String)
X if (str[1] != Inpar)
X if (str[1] == Inbrack)
X {
X arithsubst((vptr*) &str,&str3); /* $[...] */
X setdata(node,str3);
X str = str3;
X continue;
X }
X else
X {
X paramsubst(list,node,str,str3,qt);
X if (errflag)
X return;
X str3 = str = getdata(node);
X continue;
X }
X str++;
X if (errflag)
X return;
X }
X if (*(char *) getdata(node))
X remnulargs(getdata(node));
X if (unset(IGNOREBRACES))
X while (hasbraces(getdata(node)))
X xpandbraces(list,&node);
X filesub((char **) getaddrdata(node));
X if (errflag)
X return;
X incnode(node);
X }
X}
X
Xvoid postfork(list,doglob) /**/
XLklist list;int doglob;
X{
XLknode node = firstnode(list);
Xint glb = 1;
X
X badcshglob = 0;
X if (isset(NOGLOBOPT) || !doglob)
X glb = 0;
X while (node)
X {
X char *str3,*str;
X
X str = str3 = getdata(node);
X while (*str)
X {
X if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
X *str == Tick || *str == Qtick)
X {
X Lknode n = prevnode(node);
X
X commsubst(list,node,str,str3,
X (*str == Qstring || *str == Qtick)); /* `...`,$(...) */
X if (errflag)
X return;
X str = str3 = getdata(node = nextnode(n));
X continue;
X }
X str++;
X }
X if (glb)
X {
X if (haswilds(getdata(node)))
X glob(list,&node);
X if (errflag)
X return;
X }
X incnode(node);
X }
X if (badcshglob == 1) zerr("no match",NULL,0);
X}
X
X/* perform substitution on a single word */
X
Xvoid singsub(s) /**/
Xchar **s;
X{
XLklist foo;
Xchar *t;
X
X for (t = *s; *t; t++)
X if (*t == String)
X *t = Qstring;
X else if (*t == Tick)
X *t = Qtick;
X foo = newlist();
X addnode(foo,*s);
X prefork(foo);
X if (errflag)
X return;
X postfork(foo,0);
X if (errflag)
X return;
X *s = ugetnode(foo);
X if (firstnode(foo))
X zerr("ambiguous: %s",*s,0);
X}
X
X/* strdup, but returns "Nularg" if this is a null string */
X
Xvptr nstrdup(s) /**/
Xvptr s;
X{
Xchar *t = s;
X
X if (!*t)
X return strdup(nulstring);
X return strdup(t);
X}
X
Xchar *dynread(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X
X ptr = buf;
X while ((c = hgetc()) != stop)
X {
X *ptr++ = c;
X if (++ct == bsiz)
X {
X buf = realloc(buf,bsiz *= 2);
X ptr = buf+ct;
X }
X }
X *ptr = 0;
X return buf;
X}
X
Xint filesub(namptr) /**/
Xchar **namptr;
X{
Xchar *str = *namptr,*cnam;
X
X if (*str == Tilde && str[1] != '=')
X {
X if (str[1] == '+' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo = strdup(pwd); /* ~+ */
X
X str+=2;
X modify(&foo,&str);
X *namptr = dyncat(pwd,str);
X return 1;
X }
X else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo; /* ~- */
X
X if (cnam = oldpwd)
X foo = cnam;
X else
X foo = pwd;
X str += 2;
X foo = strdup(foo);
X modify(&foo,&str);
X *namptr = dyncat(foo,str);
X return 1;
X }
X if (ialpha(str[1])) /* ~foo */
X {
X char *ptr,*hom;
X
X for (ptr = ++str; *ptr && iuser(*ptr); ptr++)
X if (*ptr == '-')
X *ptr = '-';
X if (*ptr && *ptr != '/') return 0;
X if (!(hom = gethome(str,ptr-str)))
X {
X zerr("user not found: %l",str,ptr-str);
X return 0;
X }
X modify(&hom,&ptr);
X *namptr = dyncat(hom,ptr);
X return 1;
X }
X else if (str[1] == '/') /* ~/foo */
X {
X *namptr = dyncat(home,str+1);
X return 1;
X }
X else if (!str[1]) /* ~ by itself */
X {
X *namptr = strdup(home);
X return 1;
X }
X }
X if (*str == Equals && iuser(str[1]) && unset(NOEQUALS))
X {
X char *ptr,*s,*ds;
X int val;
X
X if (ialpha(str[1])) /* =foo */
X {
X char sav,*pp;
X
X for (pp = str+1; *pp && *pp != ':'; pp++);
X sav = *pp;
X *pp = '\0';
X if (!(cnam = findcmd(str+1)))
X {
X zerr("%s not found",str+1,0);
X return 0;
X }
X *namptr = strdup(cnam);
X free(cnam);
X if ((*pp = sav) == ':')
X {
X modify(namptr,&pp);
X s = *namptr;
X *namptr = dyncat(*namptr,pp);
X }
X return 1;
X }
X if (str[1] == '-') /* =- */
X {
X val = -1;
X ptr = str+2;
X }
X else
X val = zstrtol(str+1,&ptr,10); /* =# */
X ds = dstackent(val);
X if (!ds)
X return 1;
X s = strdup(ds);
X modify(&s,&ptr);
X *namptr = dyncat(s,ptr);
X return 1;
X }
X return 0;
X}
X
X/* get a named directory */
X
Xchar *gethome(user,len) /**/
Xchar *user;int len;
X{
Xchar sav,*str,*ret_val;
Xstruct passwd *pw;
X
X if (len == 0)
X return strdup(home);
X sav = user[len];
X user[len] = '\0';
X if ((getparamtype(user,len) == PMFLAG_s) &&
X (str = getsparamval(user,len)) && *str == '/')
X {
X str = strdup(str);
X adduserdir(user,str);
X user[len] = sav;
X return str;
X }
X permalloc(); /* fixes iris bug--getpwnam calls strdup! */
X pw = getpwnam(user);
X lastalloc();
X if (!pw) {
X user[len] = sav;
X return NULL;
X }
X str = xsymlink(pw->pw_dir);
X adduserdir(user,str);
X user[len] = sav;
X ret_val = strdup(str);
X free(str);
X return ret_val;
X}
X
X/* `...`, $(...) */
X
Xvoid commsubst(l,n,str3,str,qt) /**/
XLklist l;Lknode n;char *str3;char *str;int qt;
X{
Xchar *str2;
XLknode where = prevnode(n);
XLklist pl;
X
X if (*str3 == Tick || *str3 == Qtick)
X {
X *str3 = '\0';
X for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
X *str3++ = '\0';
X }
X else
X {
X *str3++ = '\0';
X for (str2 = ++str3; *str3 != Outpar; str3++);
X *str3++ = '\0';
X }
X uremnode(l,n);
X if (!(pl = getoutput(str2,qt)))
X {
X if (!errflag)
X zerr("parse error in command substitution",NULL,0);
X return;
X }
X if (full(pl))
X {
X setdata(firstnode(pl),dyncat(str,peekfirst(pl)));
X setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3));
X inslist(pl,where,l);
X }
X else
X insnode(l,where,dyncat(str,str3));
X}
X
X/* parameter substitution */
X
X#define isstring(c) (c == '$' || c == String || c == Qstring)
X#define isbrace(c) (c == '{' || c == Inbrace)
X
Xvoid paramsubst(l,n,aptr,bptr,qt) /**/
XLklist l;Lknode n;char *aptr;char *bptr;int qt;
X{
Xchar *s = aptr,*u,*idbeg,*idend,*ostr = bptr;
Xint brs; /* != 0 means ${...}, otherwise $... */
Xint colf; /* != 0 means we found a colon after the name */
Xint doub = 0; /* != 0 means we have %%, not %, or ##, not # */
Xint isarr = 0;
Xint plan9 = isset(RCEXPANDPARAM);
Xint getlen = 0;
Xint vunset = 0;
Xint spbreak = isset(SHWORDSPLIT) && !qt;
Xchar *val = NULL,**aval = NULL;
Xint vlen;
Xint fwidth = 0;
XValue v;
X
X *s++ = '\0';
X if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
X *s != '!' && *s != '$' && *s != String && *s != Qstring &&
X *s != '?' && *s != Quest && *s != '_' &&
X *s != '*' && *s != Star && *s != '@' && *s != '{' &&
X *s != Inbrace && *s != '=' && *s != Hat && *s != '^') {
X s[-1] = '$';
X return;
X }
X if (brs = (*s == '{' || *s == Inbrace)) s++;
X for (;;) {
X if (*s == '^' || *s == Hat)
X plan9 ^= 1,s++;
X else if (*s == '=')
X spbreak ^= 1,s++;
X else if ((*s == '#' || *s == Pound) && (iident(s[1])
X || s[1] == '*' || s[1] == Star || s[1] == '@'
X || (isstring(s[1]) && isbrace(s[2]) && iident(s[3]))))
X getlen = 1,s++;
X else
X break;
X }
X
X idbeg = s;
X if (isstring(*s) && isbrace(s[1])) {
X int bct, sav;
X
X val = s;
X for (bct = 1, s += 2; *s && bct; ++s)
X if (*s == Inbrace || *s == '{')
X ++bct;
X else if (*s == Outbrace || *s == '}')
X --bct;
X sav = *s;
X *s = 0;
X singsub(&val);
X *s = sav;
X isarr = 0;
X v = (Value) NULL;
X } else if (!(v = getvalue(&s,1))) {
X vunset = 1;
X } else
X if (isarr = v->isarr) {
X aval = getarrvalue(v);
X if (qt && isarr > 0) {
X val = spacejoin(aval);
X isarr = 0;
X }
X }
X else {
X val = getstrvalue(v);
X fwidth = v->pm->ct;
X switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z)) {
X char *t;
X int t0;
X
X case PMFLAG_L:
X case PMFLAG_L|PMFLAG_Z:
X t = val;
X if (v->pm->flags & PMFLAG_Z)
X while (*t == '0') t++;
X else
X while (isep(*t)) t++;
X val = ncalloc(fwidth+1);
X val[fwidth] = '\0';
X if ((t0 = strlen(t)) > fwidth)
X t0 = fwidth;
X memset(val,' ',fwidth);
X strncpy(val,t,t0);
X break;
X case PMFLAG_R:
X case PMFLAG_Z:
X case PMFLAG_Z|PMFLAG_R:
X if (strlen(val) < fwidth) {
X t = ncalloc(fwidth+1);
X memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth);
X if ((t0 = strlen(val)) > fwidth)
X t0 = fwidth;
X strcpy(t+(fwidth-t0),val);
X val = t;
X } else {
X t = ncalloc(fwidth+1);
X t[fwidth] = '\0';
X strncpy(t,val+strlen(val)-fwidth,fwidth);
X val = t;
X }
X break;
X }
X switch (v->pm->flags & (PMFLAG_l | PMFLAG_u)) {
X char *t;
X
X case PMFLAG_l:
X t = val;
X for (;*t;t++)
X *t = tulower(*t);
X break;
X case PMFLAG_u:
X t = val;
X for (;*t;t++)
X *t = tuupper(*t);
X break;
X }
X }
X idend = s;
X if (colf = *s == ':') s++;
X
X /* check for ${..?...} or ${..=..} or one of those. Only works
X if the name is in braces. */
X
X if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
X *s == '%' || *s == Quest || *s == Pound)) {
X if (v && isarr && (*s == '%' || *s == '#' || *s == Pound)) {
X zerr("operator requires a scalar",NULL,0);
X return;
X }
X if (*s == s[1]) {
X s++;
X doub = 1;
X }
X u = ++s;
X if (brs) {
X int bct = 1;
X
X for (;;) {
X if (*s == '{' || *s == Inbrace)
X bct++;
X else if (*s == '}' || *s == Outbrace)
X bct--;
X if (!bct || !*s)
X break;
X s++;
X }
X } else {
X while (*s++);
X s--;
X }
X if (*s) *s++ = '\0';
X if (colf && !vunset)
X vunset = (isarr) ? !*aval : !*val;
X switch ((int)(unsigned char)u[-1]) {
X case '-':
X if (vunset)
X val = strdup(u), isarr = 0;
X break;
X case '=':
X if (vunset) {
X char sav = *idend;
X
X *idend = '\0';
X setsparam(idbeg,ztrdup(val = strdup(u)));
X *idend = sav;
X isarr = 0;
X }
X break;
X case '?':
X case (int)STOUC(Quest):
X if (vunset) {
X zerr("%s",(*u) ? u : "parameter not set",0);
X if (!interact)
X exit(1);
X return;
X }
X break;
X case '+':
X if (vunset)
X val = strdup("");
X else
X val = strdup(u);
X isarr = 0;
X break;
X case '#':
X case (int)STOUC(Pound):
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub);
X break;
X case '%':
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub+2);
X break;
X }
X } else { /* no ${...=...} or anything, but possible modifiers. */
X if (vunset) {
X if (isset(NOUNSET)) {
X zerr("parameter not set",NULL,0);
X return;
X }
X val = strdup("");
X }
X if (colf) {
X s--;
X if (!isarr) modify(&val,&s);
X else {
X char *ss = s;
X char **ap = aval;
X char **pp = aval = (char **)ncalloc(sizeof(char *)*(arrlen(aval)+1));
X while (*pp = *ap++) {
X ss = s;
X modify(pp++,&ss);
X }
X s = ss;
X }
X }
X if (brs) {
X if (*s != '}' && *s != Outbrace) {
X zerr("closing brace expected",NULL,0);
X return;
X }
X s++;
X }
X }
X if (errflag)
X return;
X if (getlen) {
X long len = 0;
X char buf[14];
X
X if (isarr) {
X char **ctr;
X for (ctr = aval; *ctr; ctr++,len++);
X } else
X len = strlen(val);
X sprintf(buf,"%ld",len);
X val = strdup(buf);
X isarr = 0;
X }
X if (isarr)
X if (!aval || !aval[0]) {
X val = strdup("");
X isarr = 0;
X } else if (!aval[1]) {
X val = aval[0];
X isarr = 0;
X }
X if (!qt && spbreak) {
X if (isarr)
X val = spacejoin(aval);
X isarr = 1;
X aval = spacesplit(val);
X if (!aval || !aval[0]) {
X val = strdup("");
X isarr = 0;
X } else if (!aval[1]) {
X val = aval[0];
X isarr = 0;
X }
X /* if only one member, not really an array */
X if (!aval[1])
X isarr = 0;
X }
X if (isarr)
X if (plan9) {
X int dlen;
X char *y;
X char *x;
X
X vlen = strlen(aval[0]);
X if (qt && vlen == 0)
X y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+nulstrlen);
X else
X y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+vlen);
X setdata(n,y);
X strcpy(y,ostr);
X strcat(y, (qt && vlen == 0) ? nulstring : aval[0]);
X strcat(y,s);
X while (*++aval) {
X vlen = strlen(*aval);
X if (qt && vlen == 0)
X x = ncalloc(dlen+nulstrlen);
X else
X x = ncalloc(dlen+vlen);
X strcpy(x,ostr);
X strcat(x, (qt && vlen == 0) ? nulstring : *aval);
X strcat(x,s);
X insnode(l,n,x), incnode(n);
X }
X } else {
X char *zz;
X
X vlen = strlen(aval[0]);
X if (qt && vlen == 0)
X zz = ncalloc((char *) aptr-(bptr)+nulstrlen+1);
X else
X zz = ncalloc((char *) aptr-(bptr)+vlen+1);
X setdata(n,zz);
X strcpy(zz,ostr);
X strcat(zz, (qt && vlen == 0) ? nulstring : *aval);
X aval++;
X while (aval[1]) {
X insnode(l,n,
X (qt && strlen(*aval) == 0) ? strdup(nulstring) : *aval);
X incnode(n);
X aval++;
X }
X vlen = strlen(*aval);
X if (qt && vlen == 0) {
X zz = ncalloc(nulstrlen+strlen(s)+1);
X strcpy(zz,nulstring);
X }
X else {
X zz = ncalloc(vlen+strlen(s)+1);
X strcpy(zz,*aval);
X }
X strcat(zz,s);
X insnode(l,n,zz);
X }
X else {
X vlen = strlen(val);
X if (qt && vlen == 0)
X bptr = ncalloc((char *) aptr-bptr+nulstrlen+strlen(s)+1);
X else
X bptr = ncalloc((char *) aptr-bptr+vlen+strlen(s)+1);
X setdata(n,bptr);
X strcpy(bptr,ostr);
X strcat(bptr, (qt && vlen == 0) ? nulstring : val);
X strcat(bptr,s);
X }
X}
X
X/* arithmetic substitution */
X
Xvoid arithsubst(aptr,bptr) /**/
Xvptr *aptr;char **bptr;
X{
Xchar *s = *aptr,*t,buf[16];
Xlong v;
X
X *s = '\0';
X for (; *s != Outbrack; s++);
X *s++ = '\0';
X v = matheval((char *) *aptr+2);
X sprintf(buf,"%ld",v);
X t = ncalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
X strcpy(t,*bptr);
X strcat(t,buf);
X strcat(t,s);
X *bptr = t;
X}
X
Xvoid modify(str,ptr) /**/
Xchar **str;char **ptr;
X{
Xchar *ptr1,*ptr2,*ptr3,del,*lptr, sav;
Xint gbal;
X
X if (**ptr == ':')
X *str = strdup(*str);
X while (**ptr == ':')
X {
X lptr = *ptr;
X (*ptr)++;
X gbal = 0;
Xhere:
X switch(*(*ptr)++)
X {
X case 'h': remtpath(str); break;
X case 'r': remtext(str); break;
X case 'e': rembutext(str); break;
X case 't': remlpaths(str); break;
X case 'l': downcase(str); break;
X case 'u': upcase(str); break;
X case 's':
X if (hsubl)
X free(hsubl);
X if (hsubr)
X free(hsubr);
X ptr1 = *ptr;
X del = *ptr1++;
X for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
X if (!*ptr2)
X {
X zerr("bad subtitution",NULL,0);
X return;
X }
X *ptr2++ = '\0';
X for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
X if (sav = *ptr3)
X *ptr3++ = '\0';
X hsubl = ztrdup(ptr1);
X hsubr = ztrdup(ptr2);
X ptr2[-1] = del;
X if (sav)
X ptr3[-1] = sav;
X *ptr = ptr3;
X case '&':
X if (hsubl && hsubr)
X subst(str,hsubl,hsubr,gbal);
X break;
X case 'g': gbal = 1; goto here;
X default: *ptr = lptr; return;
X }
X }
X}
X
X/* get a directory stack entry */
X
Xchar *dstackent(val) /**/
Xint val;
X{
XLknode node;
X
X if ((val < 0 && !firstnode(dirstack)) || !val--)
X return pwd;
X if (val < 0)
X node = lastnode(dirstack);
X else
X for (node = firstnode(dirstack); node && val; val--,incnode(node));
X if (!node)
X {
X zerr("not enough dir stack entries.",NULL,0);
X return NULL;
X }
X return getdata(node);
X}
X
X/* make an alias hash table node */
X
Xstruct alias *mkanode(txt,cmflag) /**/
Xchar *txt;int cmflag;
X{
Xstruct alias *ptr = (Alias) zcalloc(sizeof *ptr);
X
X ptr->text = txt;
X ptr->cmd = cmflag;
X ptr->inuse = 0;
X return ptr;
X}
END_OF_FILE
if test 16309 -ne `wc -c <'src/subst.c'`; then
echo shar: \"'src/subst.c'\" unpacked with wrong size!
fi
# end of 'src/subst.c'
fi
echo shar: End of archive 17 \(of 22\).
cp /dev/null ark17isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 22 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...