MFS: No longer needed in PicoBSD 0.44
This commit is contained in:
parent
008e15781e
commit
1252b4b671
@ -1,80 +0,0 @@
|
||||
#!/bin/sh -
|
||||
# $Id: rc.network.pl,v 1.1.1.1 1998/08/27 17:38:42 abial Exp $
|
||||
network_pass1() {
|
||||
echo -n 'Wstepna konfiguracja sieci:'
|
||||
# Set the host name if it is not already set
|
||||
if [ -z "`hostname -s`" ] ; then
|
||||
hostname $hostname
|
||||
echo ' hostname'
|
||||
fi
|
||||
# Set up all the network interfaces, calling startup scripts if needed
|
||||
for ifn in ${network_interfaces}; do
|
||||
if [ -e /etc/start_if.${ifn} ]; then
|
||||
. /etc/start_if.${ifn}
|
||||
fi
|
||||
# Do the primary ifconfig if specified
|
||||
eval ifconfig_args=\$ifconfig_${ifn}
|
||||
if [ -n "${ifconfig_args}" ] ; then
|
||||
ifconfig ${ifn} ${ifconfig_args}
|
||||
fi
|
||||
# Check to see if aliases need to be added
|
||||
alias=0
|
||||
while :
|
||||
do
|
||||
eval ifconfig_args=\$ifconfig_${ifn}_alias${alias}
|
||||
if [ -n "${ifconfig_args}" ]; then
|
||||
ifconfig ${ifn} ${ifconfig_args} alias
|
||||
alias=`expr ${alias} + 1`
|
||||
else
|
||||
break;
|
||||
fi
|
||||
done
|
||||
ifconfig ${ifn}
|
||||
done
|
||||
# Load the filters if required
|
||||
if [ -n "$firewall_enable" -a -f /etc/rc.firewall -a \
|
||||
"x$firewall_enable" = "xYES" ] ; then
|
||||
. /etc/rc.firewall
|
||||
echo "Zaladowano reguly filtrujace do firewalla."
|
||||
else
|
||||
echo "UWAGA: system posiada wbudowany modul firewalla, ale zadne reguly"
|
||||
echo " filtrujace nie zostaly zaladowane."
|
||||
echo " Wszystkie rodzaje ruchu IP sa dozwolone."
|
||||
fi
|
||||
# Configure routing
|
||||
if [ "x$defaultrouter" != "xNO" ] ; then
|
||||
static_routes="default ${static_routes}"
|
||||
route_default="default ${defaultrouter}"
|
||||
fi
|
||||
# Set up any static routes. This should be done before router discovery.
|
||||
if [ "x${static_routes}" != "x" ]; then
|
||||
for i in ${static_routes}; do
|
||||
eval route_args=\$route_${i}
|
||||
route add ${route_args}
|
||||
done
|
||||
fi
|
||||
echo -n 'Dodatkowe opcje routingu:'
|
||||
if [ -n "$tcp_extensions" -a "x$tcp_extensions" != "xYES" ] ; then
|
||||
echo -n ' tcp_extensions=NO'
|
||||
sysctl -w net.inet.tcp.rfc1323=0 >/dev/null 2>&1
|
||||
sysctl -w net.inet.tcp.rfc1644=0 >/dev/null 2>&1
|
||||
fi
|
||||
if [ "X$gateway_enable" = X"YES" ]; then
|
||||
echo -n ' IP_gateway=YES'
|
||||
sysctl -w net.inet.ip.forwarding=1 >/dev/null 2>&1
|
||||
fi
|
||||
if [ "X$arpproxy_all" = X"YES" ]; then
|
||||
echo -n ' wlaczam ARP_PROXY_ALL: '
|
||||
sysctl -w net.link.ether.inet.proxyall=1 2>&1
|
||||
fi
|
||||
echo '.'
|
||||
network_pass1_done=YES # Let future generations know we made it.
|
||||
}
|
||||
|
||||
network_pass2() {
|
||||
network_pass2_done=YES
|
||||
}
|
||||
|
||||
network_pass3() {
|
||||
network_pass3_done=YES
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.33 1997/07/04 21:40:55 christos Exp $
|
||||
# @(#)Makefile 8.4 (Berkeley) 5/5/95
|
||||
|
||||
WARNS= 1
|
||||
PROG= sh
|
||||
SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \
|
||||
histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
|
||||
mystring.c options.c parser.c redir.c show.c trap.c output.c var.c
|
||||
GENSRCS=arith.c arith_lex.c builtins.c builtins.h init.c nodes.c nodes.h \
|
||||
syntax.c syntax.h token.h
|
||||
SRCS= ${SHSRCS} ${GENSRCS}
|
||||
|
||||
LDADD+= -ll -ledit -ltermcap
|
||||
DPADD+= ${LIBL} ${LIBEDIT} ${LIBTERMCAP}
|
||||
|
||||
LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
||||
|
||||
CFLAGS+=-DSHELL -I. -I${.CURDIR}
|
||||
|
||||
|
||||
.PATH: ${.CURDIR}/bltin ${.CURDIR}/../../usr.bin/printf
|
||||
|
||||
CLEANFILES+= mkinit mknodes mksyntax
|
||||
CLEANFILES+= mkinit.o mknodes.o mksyntax.o
|
||||
CLEANFILES+= ${GENSRCS} y.tab.h
|
||||
|
||||
token.h: mktokens
|
||||
sh ${.CURDIR}/mktokens
|
||||
|
||||
builtins.c builtins.h: mkbuiltins builtins.def
|
||||
cd ${.CURDIR}; sh mkbuiltins ${.OBJDIR}
|
||||
|
||||
init.c: mkinit ${SHSRCS}
|
||||
./mkinit ${.ALLSRC:S/^mkinit$//}
|
||||
|
||||
nodes.c nodes.h: mknodes nodetypes nodes.c.pat
|
||||
./mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat
|
||||
|
||||
syntax.c syntax.h: mksyntax
|
||||
./mksyntax
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
${OBJS}: builtins.h nodes.h syntax.h token.h
|
@ -1,357 +0,0 @@
|
||||
# $NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
|
||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||
|
||||
NOTE -- This is the original TOUR paper distributed with ash and
|
||||
does not represent the current state of the shell. It is provided anyway
|
||||
since it provides helpful information for how the shell is structured,
|
||||
but be warned that things have changed -- the current shell is
|
||||
still under development.
|
||||
|
||||
================================================================
|
||||
|
||||
A Tour through Ash
|
||||
|
||||
Copyright 1989 by Kenneth Almquist.
|
||||
|
||||
|
||||
DIRECTORIES: The subdirectory bltin contains commands which can
|
||||
be compiled stand-alone. The rest of the source is in the main
|
||||
ash directory.
|
||||
|
||||
SOURCE CODE GENERATORS: Files whose names begin with "mk" are
|
||||
programs that generate source code. A complete list of these
|
||||
programs is:
|
||||
|
||||
program intput files generates
|
||||
------- ------------ ---------
|
||||
mkbuiltins builtins builtins.h builtins.c
|
||||
mkinit *.c init.c
|
||||
mknodes nodetypes nodes.h nodes.c
|
||||
mksignames - signames.h signames.c
|
||||
mksyntax - syntax.h syntax.c
|
||||
mktokens - token.h
|
||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
||||
|
||||
There are undoubtedly too many of these. Mkinit searches all the
|
||||
C source files for entries looking like:
|
||||
|
||||
INIT {
|
||||
x = 1; /* executed during initialization */
|
||||
}
|
||||
|
||||
RESET {
|
||||
x = 2; /* executed when the shell does a longjmp
|
||||
back to the main command loop */
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
x = 3; /* executed when the shell runs a shell procedure */
|
||||
}
|
||||
|
||||
It pulls this code out into routines which are when particular
|
||||
events occur. The intent is to improve modularity by isolating
|
||||
the information about which modules need to be explicitly
|
||||
initialized/reset within the modules themselves.
|
||||
|
||||
Mkinit recognizes several constructs for placing declarations in
|
||||
the init.c file.
|
||||
INCLUDE "file.h"
|
||||
includes a file. The storage class MKINIT makes a declaration
|
||||
available in the init.c file, for example:
|
||||
MKINIT int funcnest; /* depth of function calls */
|
||||
MKINIT alone on a line introduces a structure or union declara-
|
||||
tion:
|
||||
MKINIT
|
||||
struct redirtab {
|
||||
short renamed[10];
|
||||
};
|
||||
Preprocessor #define statements are copied to init.c without any
|
||||
special action to request this.
|
||||
|
||||
INDENTATION: The ash source is indented in multiples of six
|
||||
spaces. The only study that I have heard of on the subject con-
|
||||
cluded that the optimal amount to indent is in the range of four
|
||||
to six spaces. I use six spaces since it is not too big a jump
|
||||
from the widely used eight spaces. If you really hate six space
|
||||
indentation, use the adjind (source included) program to change
|
||||
it to something else.
|
||||
|
||||
EXCEPTIONS: Code for dealing with exceptions appears in
|
||||
exceptions.c. The C language doesn't include exception handling,
|
||||
so I implement it using setjmp and longjmp. The global variable
|
||||
exception contains the type of exception. EXERROR is raised by
|
||||
calling error. EXINT is an interrupt. EXSHELLPROC is an excep-
|
||||
tion which is raised when a shell procedure is invoked. The pur-
|
||||
pose of EXSHELLPROC is to perform the cleanup actions associated
|
||||
with other exceptions. After these cleanup actions, the shell
|
||||
can interpret a shell procedure itself without exec'ing a new
|
||||
copy of the shell.
|
||||
|
||||
INTERRUPTS: In an interactive shell, an interrupt will cause an
|
||||
EXINT exception to return to the main command loop. (Exception:
|
||||
EXINT is not raised if the user traps interrupts using the trap
|
||||
command.) The INTOFF and INTON macros (defined in exception.h)
|
||||
provide uninterruptable critical sections. Between the execution
|
||||
of INTOFF and the execution of INTON, interrupt signals will be
|
||||
held for later delivery. INTOFF and INTON can be nested.
|
||||
|
||||
MEMALLOC.C: Memalloc.c defines versions of malloc and realloc
|
||||
which call error when there is no memory left. It also defines a
|
||||
stack oriented memory allocation scheme. Allocating off a stack
|
||||
is probably more efficient than allocation using malloc, but the
|
||||
big advantage is that when an exception occurs all we have to do
|
||||
to free up the memory in use at the time of the exception is to
|
||||
restore the stack pointer. The stack is implemented using a
|
||||
linked list of blocks.
|
||||
|
||||
STPUTC: If the stack were contiguous, it would be easy to store
|
||||
strings on the stack without knowing in advance how long the
|
||||
string was going to be:
|
||||
p = stackptr;
|
||||
*p++ = c; /* repeated as many times as needed */
|
||||
stackptr = p;
|
||||
The folloing three macros (defined in memalloc.h) perform these
|
||||
operations, but grow the stack if you run off the end:
|
||||
STARTSTACKSTR(p);
|
||||
STPUTC(c, p); /* repeated as many times as needed */
|
||||
grabstackstr(p);
|
||||
|
||||
We now start a top-down look at the code:
|
||||
|
||||
MAIN.C: The main routine performs some initialization, executes
|
||||
the user's profile if necessary, and calls cmdloop. Cmdloop is
|
||||
repeatedly parses and executes commands.
|
||||
|
||||
OPTIONS.C: This file contains the option processing code. It is
|
||||
called from main to parse the shell arguments when the shell is
|
||||
invoked, and it also contains the set builtin. The -i and -j op-
|
||||
tions (the latter turns on job control) require changes in signal
|
||||
handling. The routines setjobctl (in jobs.c) and setinteractive
|
||||
(in trap.c) are called to handle changes to these options.
|
||||
|
||||
PARSING: The parser code is all in parser.c. A recursive des-
|
||||
cent parser is used. Syntax tables (generated by mksyntax) are
|
||||
used to classify characters during lexical analysis. There are
|
||||
three tables: one for normal use, one for use when inside single
|
||||
quotes, and one for use when inside double quotes. The tables
|
||||
are machine dependent because they are indexed by character vari-
|
||||
ables and the range of a char varies from machine to machine.
|
||||
|
||||
PARSE OUTPUT: The output of the parser consists of a tree of
|
||||
nodes. The various types of nodes are defined in the file node-
|
||||
types.
|
||||
|
||||
Nodes of type NARG are used to represent both words and the con-
|
||||
tents of here documents. An early version of ash kept the con-
|
||||
tents of here documents in temporary files, but keeping here do-
|
||||
cuments in memory typically results in significantly better per-
|
||||
formance. It would have been nice to make it an option to use
|
||||
temporary files for here documents, for the benefit of small
|
||||
machines, but the code to keep track of when to delete the tem-
|
||||
porary files was complex and I never fixed all the bugs in it.
|
||||
(AT&T has been maintaining the Bourne shell for more than ten
|
||||
years, and to the best of my knowledge they still haven't gotten
|
||||
it to handle temporary files correctly in obscure cases.)
|
||||
|
||||
The text field of a NARG structure points to the text of the
|
||||
word. The text consists of ordinary characters and a number of
|
||||
special codes defined in parser.h. The special codes are:
|
||||
|
||||
CTLVAR Variable substitution
|
||||
CTLENDVAR End of variable substitution
|
||||
CTLBACKQ Command substitution
|
||||
CTLBACKQ|CTLQUOTE Command substitution inside double quotes
|
||||
CTLESC Escape next character
|
||||
|
||||
A variable substitution contains the following elements:
|
||||
|
||||
CTLVAR type name '=' [ alternative-text CTLENDVAR ]
|
||||
|
||||
The type field is a single character specifying the type of sub-
|
||||
stitution. The possible types are:
|
||||
|
||||
VSNORMAL $var
|
||||
VSMINUS ${var-text}
|
||||
VSMINUS|VSNUL ${var:-text}
|
||||
VSPLUS ${var+text}
|
||||
VSPLUS|VSNUL ${var:+text}
|
||||
VSQUESTION ${var?text}
|
||||
VSQUESTION|VSNUL ${var:?text}
|
||||
VSASSIGN ${var=text}
|
||||
VSASSIGN|VSNUL ${var=text}
|
||||
|
||||
In addition, the type field will have the VSQUOTE flag set if the
|
||||
variable is enclosed in double quotes. The name of the variable
|
||||
comes next, terminated by an equals sign. If the type is not
|
||||
VSNORMAL, then the text field in the substitution follows, ter-
|
||||
minated by a CTLENDVAR byte.
|
||||
|
||||
Commands in back quotes are parsed and stored in a linked list.
|
||||
The locations of these commands in the string are indicated by
|
||||
CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
|
||||
the back quotes were enclosed in double quotes.
|
||||
|
||||
The character CTLESC escapes the next character, so that in case
|
||||
any of the CTL characters mentioned above appear in the input,
|
||||
they can be passed through transparently. CTLESC is also used to
|
||||
escape '*', '?', '[', and '!' characters which were quoted by the
|
||||
user and thus should not be used for file name generation.
|
||||
|
||||
CTLESC characters have proved to be particularly tricky to get
|
||||
right. In the case of here documents which are not subject to
|
||||
variable and command substitution, the parser doesn't insert any
|
||||
CTLESC characters to begin with (so the contents of the text
|
||||
field can be written without any processing). Other here docu-
|
||||
ments, and words which are not subject to splitting and file name
|
||||
generation, have the CTLESC characters removed during the vari-
|
||||
able and command substitution phase. Words which are subject
|
||||
splitting and file name generation have the CTLESC characters re-
|
||||
moved as part of the file name phase.
|
||||
|
||||
EXECUTION: Command execution is handled by the following files:
|
||||
eval.c The top level routines.
|
||||
redir.c Code to handle redirection of input and output.
|
||||
jobs.c Code to handle forking, waiting, and job control.
|
||||
exec.c Code to to path searches and the actual exec sys call.
|
||||
expand.c Code to evaluate arguments.
|
||||
var.c Maintains the variable symbol table. Called from expand.c.
|
||||
|
||||
EVAL.C: Evaltree recursively executes a parse tree. The exit
|
||||
status is returned in the global variable exitstatus. The alter-
|
||||
native entry evalbackcmd is called to evaluate commands in back
|
||||
quotes. It saves the result in memory if the command is a buil-
|
||||
tin; otherwise it forks off a child to execute the command and
|
||||
connects the standard output of the child to a pipe.
|
||||
|
||||
JOBS.C: To create a process, you call makejob to return a job
|
||||
structure, and then call forkshell (passing the job structure as
|
||||
an argument) to create the process. Waitforjob waits for a job
|
||||
to complete. These routines take care of process groups if job
|
||||
control is defined.
|
||||
|
||||
REDIR.C: Ash allows file descriptors to be redirected and then
|
||||
restored without forking off a child process. This is accom-
|
||||
plished by duplicating the original file descriptors. The redir-
|
||||
tab structure records where the file descriptors have be dupli-
|
||||
cated to.
|
||||
|
||||
EXEC.C: The routine find_command locates a command, and enters
|
||||
the command in the hash table if it is not already there. The
|
||||
third argument specifies whether it is to print an error message
|
||||
if the command is not found. (When a pipeline is set up,
|
||||
find_command is called for all the commands in the pipeline be-
|
||||
fore any forking is done, so to get the commands into the hash
|
||||
table of the parent process. But to make command hashing as
|
||||
transparent as possible, we silently ignore errors at that point
|
||||
and only print error messages if the command cannot be found
|
||||
later.)
|
||||
|
||||
The routine shellexec is the interface to the exec system call.
|
||||
|
||||
EXPAND.C: Arguments are processed in three passes. The first
|
||||
(performed by the routine argstr) performs variable and command
|
||||
substitution. The second (ifsbreakup) performs word splitting
|
||||
and the third (expandmeta) performs file name generation. If the
|
||||
"/u" directory is simulated, then when "/u/username" is replaced
|
||||
by the user's home directory, the flag "didudir" is set. This
|
||||
tells the cd command that it should print out the directory name,
|
||||
just as it would if the "/u" directory were implemented using
|
||||
symbolic links.
|
||||
|
||||
VAR.C: Variables are stored in a hash table. Probably we should
|
||||
switch to extensible hashing. The variable name is stored in the
|
||||
same string as the value (using the format "name=value") so that
|
||||
no string copying is needed to create the environment of a com-
|
||||
mand. Variables which the shell references internally are preal-
|
||||
located so that the shell can reference the values of these vari-
|
||||
ables without doing a lookup.
|
||||
|
||||
When a program is run, the code in eval.c sticks any environment
|
||||
variables which precede the command (as in "PATH=xxx command") in
|
||||
the variable table as the simplest way to strip duplicates, and
|
||||
then calls "environment" to get the value of the environment.
|
||||
There are two consequences of this. First, if an assignment to
|
||||
PATH precedes the command, the value of PATH before the assign-
|
||||
ment must be remembered and passed to shellexec. Second, if the
|
||||
program turns out to be a shell procedure, the strings from the
|
||||
environment variables which preceded the command must be pulled
|
||||
out of the table and replaced with strings obtained from malloc,
|
||||
since the former will automatically be freed when the stack (see
|
||||
the entry on memalloc.c) is emptied.
|
||||
|
||||
BUILTIN COMMANDS: The procedures for handling these are scat-
|
||||
tered throughout the code, depending on which location appears
|
||||
most appropriate. They can be recognized because their names al-
|
||||
ways end in "cmd". The mapping from names to procedures is
|
||||
specified in the file builtins, which is processed by the mkbuil-
|
||||
tins command.
|
||||
|
||||
A builtin command is invoked with argc and argv set up like a
|
||||
normal program. A builtin command is allowed to overwrite its
|
||||
arguments. Builtin routines can call nextopt to do option pars-
|
||||
ing. This is kind of like getopt, but you don't pass argc and
|
||||
argv to it. Builtin routines can also call error. This routine
|
||||
normally terminates the shell (or returns to the main command
|
||||
loop if the shell is interactive), but when called from a builtin
|
||||
command it causes the builtin command to terminate with an exit
|
||||
status of 2.
|
||||
|
||||
The directory bltins contains commands which can be compiled in-
|
||||
dependently but can also be built into the shell for efficiency
|
||||
reasons. The makefile in this directory compiles these programs
|
||||
in the normal fashion (so that they can be run regardless of
|
||||
whether the invoker is ash), but also creates a library named
|
||||
bltinlib.a which can be linked with ash. The header file bltin.h
|
||||
takes care of most of the differences between the ash and the
|
||||
stand-alone environment. The user should call the main routine
|
||||
"main", and #define main to be the name of the routine to use
|
||||
when the program is linked into ash. This #define should appear
|
||||
before bltin.h is included; bltin.h will #undef main if the pro-
|
||||
gram is to be compiled stand-alone.
|
||||
|
||||
CD.C: This file defines the cd and pwd builtins. The pwd com-
|
||||
mand runs /bin/pwd the first time it is invoked (unless the user
|
||||
has already done a cd to an absolute pathname), but then
|
||||
remembers the current directory and updates it when the cd com-
|
||||
mand is run, so subsequent pwd commands run very fast. The main
|
||||
complication in the cd command is in the docd command, which
|
||||
resolves symbolic links into actual names and informs the user
|
||||
where the user ended up if he crossed a symbolic link.
|
||||
|
||||
SIGNALS: Trap.c implements the trap command. The routine set-
|
||||
signal figures out what action should be taken when a signal is
|
||||
received and invokes the signal system call to set the signal ac-
|
||||
tion appropriately. When a signal that a user has set a trap for
|
||||
is caught, the routine "onsig" sets a flag. The routine dotrap
|
||||
is called at appropriate points to actually handle the signal.
|
||||
When an interrupt is caught and no trap has been set for that
|
||||
signal, the routine "onint" in error.c is called.
|
||||
|
||||
OUTPUT: Ash uses it's own output routines. There are three out-
|
||||
put structures allocated. "Output" represents the standard out-
|
||||
put, "errout" the standard error, and "memout" contains output
|
||||
which is to be stored in memory. This last is used when a buil-
|
||||
tin command appears in backquotes, to allow its output to be col-
|
||||
lected without doing any I/O through the UNIX operating system.
|
||||
The variables out1 and out2 normally point to output and errout,
|
||||
respectively, but they are set to point to memout when appropri-
|
||||
ate inside backquotes.
|
||||
|
||||
INPUT: The basic input routine is pgetc, which reads from the
|
||||
current input file. There is a stack of input files; the current
|
||||
input file is the top file on this stack. The code allows the
|
||||
input to come from a string rather than a file. (This is for the
|
||||
-c option and the "." and eval builtin commands.) The global
|
||||
variable plinno is saved and restored when files are pushed and
|
||||
popped from the stack. The parser routines store the number of
|
||||
the current line in this variable.
|
||||
|
||||
DEBUGGING: If DEBUG is defined in shell.h, then the shell will
|
||||
write debugging information to the file $HOME/trace. Most of
|
||||
this is done using the TRACE macro, which takes a set of printf
|
||||
arguments inside two sets of parenthesis. Example:
|
||||
"TRACE(("n=%d0, n))". The double parenthesis are necessary be-
|
||||
cause the preprocessor can't handle functions with a variable
|
||||
number of arguments. Defining DEBUG also causes the shell to
|
||||
generate a core dump if it is sent a quit signal. The tracing
|
||||
code is in show.c.
|
@ -1,267 +0,0 @@
|
||||
/* $NetBSD: alias.c,v 1.9 1997/07/04 21:01:48 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: alias.c,v 1.9 1997/07/04 21:01:48 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "mystring.h"
|
||||
#include "alias.h"
|
||||
#include "options.h" /* XXX for argptr (should remove?) */
|
||||
|
||||
#define ATABSIZE 39
|
||||
|
||||
struct alias *atab[ATABSIZE];
|
||||
|
||||
STATIC void setalias __P((char *, char *));
|
||||
STATIC int unalias __P((char *));
|
||||
STATIC struct alias **hashalias __P((char *));
|
||||
|
||||
STATIC
|
||||
void
|
||||
setalias(name, val)
|
||||
char *name, *val;
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
for (ap = *app; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
INTOFF;
|
||||
ckfree(ap->val);
|
||||
ap->val = savestr(val);
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
INTOFF;
|
||||
ap = ckmalloc(sizeof (struct alias));
|
||||
ap->name = savestr(name);
|
||||
/*
|
||||
* XXX - HACK: in order that the parser will not finish reading the
|
||||
* alias value off the input before processing the next alias, we
|
||||
* dummy up an extra space at the end of the alias. This is a crock
|
||||
* and should be re-thought. The idea (if you feel inclined to help)
|
||||
* is to avoid alias recursions. The mechanism used is: when
|
||||
* expanding an alias, the value of the alias is pushed back on the
|
||||
* input as a string and a pointer to the alias is stored with the
|
||||
* string. The alias is marked as being in use. When the input
|
||||
* routine finishes reading the string, it markes the alias not
|
||||
* in use. The problem is synchronization with the parser. Since
|
||||
* it reads ahead, the alias is marked not in use before the
|
||||
* resulting token(s) is next checked for further alias sub. The
|
||||
* H A C K is that we add a little fluff after the alias value
|
||||
* so that the string will not be exhausted. This is a good
|
||||
* idea ------- ***NOT***
|
||||
*/
|
||||
#ifdef notyet
|
||||
ap->val = savestr(val);
|
||||
#else /* hack */
|
||||
{
|
||||
int len = strlen(val);
|
||||
ap->val = ckmalloc(len + 2);
|
||||
memcpy(ap->val, val, len);
|
||||
ap->val[len] = ' '; /* fluff */
|
||||
ap->val[len+1] = '\0';
|
||||
}
|
||||
#endif
|
||||
ap->next = *app;
|
||||
*app = ap;
|
||||
INTON;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
unalias(name)
|
||||
char *name;
|
||||
{
|
||||
struct alias *ap, **app;
|
||||
|
||||
app = hashalias(name);
|
||||
|
||||
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
/*
|
||||
* if the alias is currently in use (i.e. its
|
||||
* buffer is being used by the input routine) we
|
||||
* just null out the name instead of freeing it.
|
||||
* We could clear it out later, but this situation
|
||||
* is so rare that it hardly seems worth it.
|
||||
*/
|
||||
if (ap->flag & ALIASINUSE)
|
||||
*ap->name = '\0';
|
||||
else {
|
||||
INTOFF;
|
||||
*app = ap->next;
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
ckfree(ap);
|
||||
INTON;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void rmaliases __P((void));
|
||||
|
||||
SHELLPROC {
|
||||
rmaliases();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
rmaliases() {
|
||||
struct alias *ap, *tmp;
|
||||
int i;
|
||||
|
||||
INTOFF;
|
||||
for (i = 0; i < ATABSIZE; i++) {
|
||||
ap = atab[i];
|
||||
atab[i] = NULL;
|
||||
while (ap) {
|
||||
ckfree(ap->name);
|
||||
ckfree(ap->val);
|
||||
tmp = ap;
|
||||
ap = ap->next;
|
||||
ckfree(tmp);
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
struct alias *
|
||||
lookupalias(name, check)
|
||||
char *name;
|
||||
int check;
|
||||
{
|
||||
struct alias *ap = *hashalias(name);
|
||||
|
||||
for (; ap; ap = ap->next) {
|
||||
if (equal(name, ap->name)) {
|
||||
if (check && (ap->flag & ALIASINUSE))
|
||||
return (NULL);
|
||||
return (ap);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - sort output
|
||||
*/
|
||||
int
|
||||
aliascmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *n, *v;
|
||||
int ret = 0;
|
||||
struct alias *ap;
|
||||
|
||||
if (argc == 1) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATABSIZE; i++)
|
||||
for (ap = atab[i]; ap; ap = ap->next) {
|
||||
if (*ap->name != '\0')
|
||||
out1fmt("alias %s=%s\n", ap->name, ap->val);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
while ((n = *++argv) != NULL) {
|
||||
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
|
||||
if ((ap = lookupalias(n, 0)) == NULL) {
|
||||
outfmt(out2, "alias: %s not found\n", n);
|
||||
ret = 1;
|
||||
} else
|
||||
out1fmt("alias %s=%s\n", n, ap->val);
|
||||
else {
|
||||
*v++ = '\0';
|
||||
setalias(n, v);
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
unaliascmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = nextopt("a")) != '\0') {
|
||||
if (i == 'a') {
|
||||
rmaliases();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
for (i = 0; *argptr; argptr++)
|
||||
i = unalias(*argptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
STATIC struct alias **
|
||||
hashalias(p)
|
||||
char *p;
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = *p << 4;
|
||||
while (*p)
|
||||
hashval+= *p++;
|
||||
return &atab[hashval % ATABSIZE];
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/* $NetBSD: alias.h,v 1.4 1995/05/11 21:28:42 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#define ALIASINUSE 1
|
||||
|
||||
struct alias {
|
||||
struct alias *next;
|
||||
char *name;
|
||||
char *val;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct alias *lookupalias __P((char *, int));
|
||||
int aliascmd __P((int, char **));
|
||||
int unaliascmd __P((int, char **));
|
||||
void rmaliases __P((void));
|
@ -1,41 +0,0 @@
|
||||
/* $NetBSD: arith.h,v 1.2 1997/07/04 21:01:49 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)arith.h 1.1 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
int arith __P((char *));
|
||||
int expcmd __P((int , char **));
|
||||
void arith_lex_reset __P((void));
|
||||
int yylex __P((void));
|
@ -1,201 +0,0 @@
|
||||
%{
|
||||
/* $NetBSD: arith.y,v 1.8 1997/07/04 21:01:50 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: arith.y,v 1.8 1997/07/04 21:01:50 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "arith.h"
|
||||
#include "shell.h"
|
||||
#include "error.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
char *arith_buf, *arith_startbuf;
|
||||
|
||||
void yyerror __P((char *));
|
||||
int yyparse __P((void));
|
||||
#ifdef TESTARITH
|
||||
int main __P((int , char *[]));
|
||||
int error __P((char *));
|
||||
#endif
|
||||
|
||||
int
|
||||
arith(s)
|
||||
char *s;
|
||||
{
|
||||
long result;
|
||||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
INTOFF;
|
||||
result = yyparse();
|
||||
arith_lex_reset(); /* reprime lex */
|
||||
INTON;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
char *concat;
|
||||
char **ap;
|
||||
long i;
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[1];
|
||||
if (argc > 2) {
|
||||
/*
|
||||
* concatenate arguments
|
||||
*/
|
||||
STARTSTACKSTR(concat);
|
||||
ap = argv + 2;
|
||||
for (;;) {
|
||||
while (*p)
|
||||
STPUTC(*p++, concat);
|
||||
if ((p = *ap++) == NULL)
|
||||
break;
|
||||
STPUTC(' ', concat);
|
||||
}
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
} else
|
||||
p = "";
|
||||
|
||||
i = arith(p);
|
||||
|
||||
out1fmt("%d\n", i);
|
||||
return (! i);
|
||||
}
|
||||
|
||||
/*************************/
|
||||
#ifdef TEST_ARITH
|
||||
#include <stdio.h>
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
printf("%d\n", exp(argv[1]));
|
||||
}
|
||||
error(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr, "exp: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
%}
|
||||
%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||
|
||||
%left ARITH_OR
|
||||
%left ARITH_AND
|
||||
%left ARITH_BOR
|
||||
%left ARITH_BXOR
|
||||
%left ARITH_BAND
|
||||
%left ARITH_EQ ARITH_NE
|
||||
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
||||
%left ARITH_LSHIFT ARITH_RSHIFT
|
||||
%left ARITH_ADD ARITH_SUB
|
||||
%left ARITH_MUL ARITH_DIV ARITH_REM
|
||||
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
||||
%%
|
||||
|
||||
exp: expr = {
|
||||
return ($1);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
|
||||
| expr ARITH_OR expr = { $$ = $1 ? $1 : $3 ? $3 : 0; }
|
||||
| expr ARITH_AND expr = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
|
||||
| expr ARITH_BOR expr = { $$ = $1 | $3; }
|
||||
| expr ARITH_BXOR expr = { $$ = $1 ^ $3; }
|
||||
| expr ARITH_BAND expr = { $$ = $1 & $3; }
|
||||
| expr ARITH_EQ expr = { $$ = $1 == $3; }
|
||||
| expr ARITH_GT expr = { $$ = $1 > $3; }
|
||||
| expr ARITH_GE expr = { $$ = $1 >= $3; }
|
||||
| expr ARITH_LT expr = { $$ = $1 < $3; }
|
||||
| expr ARITH_LE expr = { $$ = $1 <= $3; }
|
||||
| expr ARITH_NE expr = { $$ = $1 != $3; }
|
||||
| expr ARITH_LSHIFT expr = { $$ = $1 << $3; }
|
||||
| expr ARITH_RSHIFT expr = { $$ = $1 >> $3; }
|
||||
| expr ARITH_ADD expr = { $$ = $1 + $3; }
|
||||
| expr ARITH_SUB expr = { $$ = $1 - $3; }
|
||||
| expr ARITH_MUL expr = { $$ = $1 * $3; }
|
||||
| expr ARITH_DIV expr = {
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| expr ARITH_REM expr = {
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| ARITH_NOT expr = { $$ = !($2); }
|
||||
| ARITH_BNOT expr = { $$ = ~($2); }
|
||||
| ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
|
||||
| ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
|
||||
| ARITH_NUM
|
||||
;
|
||||
%%
|
||||
void
|
||||
yyerror(s)
|
||||
char *s;
|
||||
{
|
||||
|
||||
yyerrok;
|
||||
yyclearin;
|
||||
arith_lex_reset(); /* reprime lex */
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
%{
|
||||
/* $NetBSD: arith_lex.l,v 1.7 1997/07/04 21:01:51 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: arith_lex.l,v 1.7 1997/07/04 21:01:51 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <unistd.h>
|
||||
#include "y.tab.h"
|
||||
#include "error.h"
|
||||
#include "arith.h"
|
||||
|
||||
extern yylval;
|
||||
extern char *arith_buf, *arith_startbuf;
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||
#define YY_NO_UNPUT
|
||||
%}
|
||||
|
||||
%%
|
||||
[ \t\n] { ; }
|
||||
[0-9]+ { yylval = atol(yytext); return(ARITH_NUM); }
|
||||
"(" { return(ARITH_LPAREN); }
|
||||
")" { return(ARITH_RPAREN); }
|
||||
"||" { return(ARITH_OR); }
|
||||
"&&" { return(ARITH_AND); }
|
||||
"|" { return(ARITH_BOR); }
|
||||
"^" { return(ARITH_BXOR); }
|
||||
"&" { return(ARITH_BAND); }
|
||||
"==" { return(ARITH_EQ); }
|
||||
"!=" { return(ARITH_NE); }
|
||||
">" { return(ARITH_GT); }
|
||||
">=" { return(ARITH_GE); }
|
||||
"<" { return(ARITH_LT); }
|
||||
"<=" { return(ARITH_LE); }
|
||||
"<<" { return(ARITH_LSHIFT); }
|
||||
">>" { return(ARITH_RSHIFT); }
|
||||
"*" { return(ARITH_MUL); }
|
||||
"/" { return(ARITH_DIV); }
|
||||
"%" { return(ARITH_REM); }
|
||||
"+" { return(ARITH_ADD); }
|
||||
"-" { return(ARITH_SUB); }
|
||||
"~" { return(ARITH_BNOT); }
|
||||
"!" { return(ARITH_NOT); }
|
||||
. { error("arith: syntax error: \"%s\"\n", arith_startbuf); }
|
||||
%%
|
||||
|
||||
void
|
||||
arith_lex_reset() {
|
||||
YY_NEW_FILE;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/* $NetBSD: bltin.h,v 1.9 1997/07/04 21:02:29 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bltin.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is included by programs which are optionally built into the
|
||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
||||
* routines to ash routines using defines.
|
||||
*/
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../mystring.h"
|
||||
#ifdef SHELL
|
||||
#include "../output.h"
|
||||
#define stdout out1
|
||||
#define stderr out2
|
||||
#define printf out1fmt
|
||||
#define putc(c, file) outc(c, file)
|
||||
#define putchar(c) out1c(c)
|
||||
#define fprintf outfmt
|
||||
#define fputs outstr
|
||||
#define fflush flushout
|
||||
#define INITARGS(argv)
|
||||
#define warnx(a, b, c) { \
|
||||
char buf[64]; \
|
||||
(void)snprintf(buf, sizeof(buf), a, b, c); \
|
||||
error("%s", buf); \
|
||||
}
|
||||
|
||||
#else
|
||||
#undef NULL
|
||||
#include <stdio.h>
|
||||
#undef main
|
||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||
#endif
|
||||
|
||||
pointer stalloc __P((int));
|
||||
void error __P((char *, ...));
|
||||
int echocmd __P((int, char **));
|
||||
|
||||
|
||||
extern char *commandname;
|
@ -1,113 +0,0 @@
|
||||
.\" $NetBSD: echo.1,v 1.8 1996/10/16 15:27:03 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Kenneth Almquist.
|
||||
.\" Copyright 1989 by Kenneth Almquist
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)echo.1 8.1 (Berkeley) 5/31/93
|
||||
.\"
|
||||
.Dd May 31, 1993
|
||||
.Dt ECHO 1
|
||||
.Os BSD 4.4
|
||||
.Sh NAME
|
||||
.Nm echo
|
||||
.Nd produce message in a shell script
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n | Fl e
|
||||
.Ar args...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
prints its arguments on the standard output, separated by spaces.
|
||||
Unless the
|
||||
.Fl n
|
||||
option is present, a newline is output following the arguments.
|
||||
The
|
||||
.Fl e
|
||||
option causes
|
||||
.Nm
|
||||
to treat the escape sequences specially, as described in the following
|
||||
paragraph.
|
||||
The
|
||||
.Fl e
|
||||
option is the default, and is provided solely for compatibility with
|
||||
other systems.
|
||||
Only one of the options
|
||||
.Fl n
|
||||
and
|
||||
.Fl e
|
||||
may be given.
|
||||
.Pp
|
||||
If any of the following sequences of characters is encountered during
|
||||
output, the sequence is not output. Instead, the specified action is
|
||||
performed:
|
||||
.Bl -tag -width indent
|
||||
.It Li \eb
|
||||
A backspace character is output.
|
||||
.It Li \ec
|
||||
Subsequent output is suppressed. This is normally used at the end of the
|
||||
last argument to suppress the trailing newline that
|
||||
.Nm
|
||||
would otherwise output.
|
||||
.It Li \ef
|
||||
Output a form feed.
|
||||
.It Li \en
|
||||
Output a newline character.
|
||||
.It Li \er
|
||||
Output a carriage return.
|
||||
.It Li \et
|
||||
Output a (horizontal) tab character.
|
||||
.It Li \ev
|
||||
Output a vertical tab.
|
||||
.It Li \e0 Ns Ar digits
|
||||
Output the character whose value is given by zero to three digits.
|
||||
If there are zero digits, a nul character is output.
|
||||
.It Li \e\e
|
||||
Output a backslash.
|
||||
.El
|
||||
.Sh HINTS
|
||||
Remember that backslash is special to the shell and needs to be escaped.
|
||||
To output a message to standard error, say
|
||||
.Pp
|
||||
.D1 echo message >&2
|
||||
.Sh BUGS
|
||||
The octal character escape mechanism
|
||||
.Pq Li \e0 Ns Ar digits
|
||||
differs from the
|
||||
C language mechanism.
|
||||
.Pp
|
||||
There is no way to force
|
||||
.Nm
|
||||
to treat its arguments literally, rather than interpreting them as
|
||||
options and escape sequences.
|
@ -1,107 +0,0 @@
|
||||
/* $NetBSD: echo.c,v 1.8 1996/11/02 18:26:06 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)echo.c 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Echo command.
|
||||
*/
|
||||
|
||||
#define main echocmd
|
||||
|
||||
#include "bltin.h"
|
||||
|
||||
/* #define eflag 1 */
|
||||
|
||||
int
|
||||
main(argc, argv) char **argv; {
|
||||
register char **ap;
|
||||
register char *p;
|
||||
register char c;
|
||||
int count;
|
||||
int nflag = 0;
|
||||
#ifndef eflag
|
||||
int eflag = 0;
|
||||
#endif
|
||||
|
||||
ap = argv;
|
||||
if (argc)
|
||||
ap++;
|
||||
if ((p = *ap) != NULL) {
|
||||
if (equal(p, "-n")) {
|
||||
nflag++;
|
||||
ap++;
|
||||
} else if (equal(p, "-e")) {
|
||||
#ifndef eflag
|
||||
eflag++;
|
||||
#endif
|
||||
ap++;
|
||||
}
|
||||
}
|
||||
while ((p = *ap++) != NULL) {
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && eflag) {
|
||||
switch (*p++) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 'c': return 0; /* exit */
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
case '\\': break; /* c = '\\' */
|
||||
case '0':
|
||||
c = 0;
|
||||
count = 3;
|
||||
while (--count >= 0 && (unsigned)(*p - '0') < 8)
|
||||
c = (c << 3) + (*p++ - '0');
|
||||
break;
|
||||
default:
|
||||
p--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
if (*ap)
|
||||
putchar(' ');
|
||||
}
|
||||
if (! nflag)
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: builtins.def,v 1.14 1997/03/14 01:42:18 christos Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
# of a C routine. The -j flag, if present, specifies that this command
|
||||
# is to be excluded from systems without job control, and the -h flag,
|
||||
# if present specifies that this command is to be excluded from systems
|
||||
# based on the SMALL compile-time symbol. The rest of the line
|
||||
# specifies the command name or names used to run the command. The entry
|
||||
# for bltincmd, which is run when the user does not specify a command, must
|
||||
# come first.
|
||||
#
|
||||
# NOTE: bltincmd must come first!
|
||||
|
||||
bltincmd command
|
||||
#alloccmd alloc
|
||||
bgcmd -j bg
|
||||
breakcmd break continue
|
||||
#catfcmd catf
|
||||
cdcmd cd chdir
|
||||
dotcmd .
|
||||
echocmd echo
|
||||
evalcmd eval
|
||||
execcmd exec
|
||||
exitcmd exit
|
||||
expcmd exp let
|
||||
exportcmd export readonly
|
||||
#exprcmd expr test [
|
||||
falsecmd false
|
||||
histcmd -h fc
|
||||
fgcmd -j fg
|
||||
getoptscmd getopts
|
||||
hashcmd hash
|
||||
jobidcmd jobid
|
||||
jobscmd jobs
|
||||
#linecmd line
|
||||
localcmd local
|
||||
#nlechocmd nlecho
|
||||
#printfcmd printf
|
||||
pwdcmd pwd
|
||||
readcmd read
|
||||
returncmd return
|
||||
setcmd set
|
||||
setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true
|
||||
typecmd type
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
waitcmd wait
|
||||
#foocmd foo
|
||||
aliascmd alias
|
||||
ulimitcmd ulimit
|
@ -1,383 +0,0 @@
|
||||
/* $NetBSD: cd.c,v 1.23 1997/07/04 20:59:40 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: cd.c,v 1.23 1997/07/04 20:59:40 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* The cd and pwd commands.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "var.h"
|
||||
#include "nodes.h" /* for jobs.h */
|
||||
#include "jobs.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "exec.h"
|
||||
#include "redir.h"
|
||||
#include "mystring.h"
|
||||
#include "show.h"
|
||||
#include "cd.h"
|
||||
|
||||
STATIC int docd __P((char *, int));
|
||||
STATIC char *getcomponent __P((void));
|
||||
STATIC void updatepwd __P((char *));
|
||||
|
||||
char *curdir = NULL; /* current working directory */
|
||||
char *prevdir; /* previous working directory */
|
||||
STATIC char *cdcomppath;
|
||||
|
||||
int
|
||||
cdcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *dest;
|
||||
char *path;
|
||||
char *p;
|
||||
struct stat statb;
|
||||
int print = 0;
|
||||
|
||||
nextopt(nullstr);
|
||||
if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
||||
error("HOME not set");
|
||||
if (*dest == '\0')
|
||||
dest = ".";
|
||||
if (dest[0] == '-' && dest[1] == '\0') {
|
||||
dest = prevdir ? prevdir : curdir;
|
||||
print = 1;
|
||||
if (dest)
|
||||
print = 1;
|
||||
else
|
||||
dest = ".";
|
||||
}
|
||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||
path = nullstr;
|
||||
while ((p = padvance(&path, dest)) != NULL) {
|
||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||
if (!print) {
|
||||
/*
|
||||
* XXX - rethink
|
||||
*/
|
||||
if (p[0] == '.' && p[1] == '/')
|
||||
p += 2;
|
||||
print = strcmp(p, dest);
|
||||
}
|
||||
if (docd(p, print) >= 0)
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
error("can't cd to %s", dest);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actually do the chdir. In an interactive shell, print the
|
||||
* directory name if "print" is nonzero.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
docd(dest, print)
|
||||
char *dest;
|
||||
int print;
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
char *component;
|
||||
struct stat statb;
|
||||
int first;
|
||||
int badstat;
|
||||
|
||||
TRACE(("docd(\"%s\", %d) called\n", dest, print));
|
||||
|
||||
/*
|
||||
* Check each component of the path. If we find a symlink or
|
||||
* something we can't stat, clear curdir to force a getcwd()
|
||||
* next time we get the value of the current directory.
|
||||
*/
|
||||
badstat = 0;
|
||||
cdcomppath = stalloc(strlen(dest) + 1);
|
||||
scopy(dest, cdcomppath);
|
||||
STARTSTACKSTR(p);
|
||||
if (*dest == '/') {
|
||||
STPUTC('/', p);
|
||||
cdcomppath++;
|
||||
}
|
||||
first = 1;
|
||||
while ((q = getcomponent()) != NULL) {
|
||||
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
||||
continue;
|
||||
if (! first)
|
||||
STPUTC('/', p);
|
||||
first = 0;
|
||||
component = q;
|
||||
while (*q)
|
||||
STPUTC(*q++, p);
|
||||
if (equal(component, ".."))
|
||||
continue;
|
||||
STACKSTRNUL(p);
|
||||
if ((lstat(stackblock(), &statb) < 0)
|
||||
|| (S_ISLNK(statb.st_mode))) {
|
||||
/* print = 1; */
|
||||
badstat = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INTOFF;
|
||||
if (chdir(dest) < 0) {
|
||||
INTON;
|
||||
return -1;
|
||||
}
|
||||
updatepwd(badstat ? NULL : dest);
|
||||
INTON;
|
||||
if (print && iflag && curdir)
|
||||
out1fmt("%s\n", curdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the next component of the path name pointed to by cdcomppath.
|
||||
* This routine overwrites the string pointed to by cdcomppath.
|
||||
*/
|
||||
|
||||
STATIC char *
|
||||
getcomponent() {
|
||||
char *p;
|
||||
char *start;
|
||||
|
||||
if ((p = cdcomppath) == NULL)
|
||||
return NULL;
|
||||
start = cdcomppath;
|
||||
while (*p != '/' && *p != '\0')
|
||||
p++;
|
||||
if (*p == '\0') {
|
||||
cdcomppath = NULL;
|
||||
} else {
|
||||
*p++ = '\0';
|
||||
cdcomppath = p;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Update curdir (the name of the current directory) in response to a
|
||||
* cd command. We also call hashcd to let the routines in exec.c know
|
||||
* that the current directory has changed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
updatepwd(dir)
|
||||
char *dir;
|
||||
{
|
||||
char *new;
|
||||
char *p;
|
||||
|
||||
hashcd(); /* update command hash table */
|
||||
|
||||
/*
|
||||
* If our argument is NULL, we don't know the current directory
|
||||
* any more because we traversed a symbolic link or something
|
||||
* we couldn't stat().
|
||||
*/
|
||||
if (dir == NULL) {
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
INTOFF;
|
||||
prevdir = curdir;
|
||||
curdir = NULL;
|
||||
getpwd();
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
|
||||
cdcomppath = stalloc(strlen(dir) + 1);
|
||||
scopy(dir, cdcomppath);
|
||||
STARTSTACKSTR(new);
|
||||
if (*dir != '/') {
|
||||
if (curdir == NULL)
|
||||
return;
|
||||
p = curdir;
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
if (p[-1] == '/')
|
||||
STUNPUTC(new);
|
||||
}
|
||||
while ((p = getcomponent()) != NULL) {
|
||||
if (equal(p, "..")) {
|
||||
while (new > stackblock() && (STUNPUTC(new), *new) != '/');
|
||||
} else if (*p != '\0' && ! equal(p, ".")) {
|
||||
STPUTC('/', new);
|
||||
while (*p)
|
||||
STPUTC(*p++, new);
|
||||
}
|
||||
}
|
||||
if (new == stackblock())
|
||||
STPUTC('/', new);
|
||||
STACKSTRNUL(new);
|
||||
INTOFF;
|
||||
if (prevdir)
|
||||
ckfree(prevdir);
|
||||
prevdir = curdir;
|
||||
curdir = savestr(stackblock());
|
||||
setvar("PWD", curdir, VEXPORT|VTEXTFIXED);
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
pwdcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
getpwd();
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
/*
|
||||
* Find out what the current directory is. If we already know the current
|
||||
* directory, this routine returns immediately.
|
||||
*/
|
||||
void
|
||||
getpwd()
|
||||
{
|
||||
char buf[MAXPWD];
|
||||
|
||||
if (curdir)
|
||||
return;
|
||||
/*
|
||||
* Things are a bit complicated here; we could have just used
|
||||
* getcwd, but traditionally getcwd is implemented using popen
|
||||
* to /bin/pwd. This creates a problem for us, since we cannot
|
||||
* keep track of the job if it is being ran behind our backs.
|
||||
* So we re-implement getcwd(), and we suppress interrupts
|
||||
* throughout the process. This is not completely safe, since
|
||||
* the user can still break out of it by killing the pwd program.
|
||||
* We still try to use getcwd for systems that we know have a
|
||||
* c implementation of getcwd, that does not open a pipe to
|
||||
* /bin/pwd.
|
||||
*/
|
||||
#if defined(__NetBSD__) || defined(__SVR4)
|
||||
|
||||
if (getcwd(buf, sizeof(buf)) == NULL) {
|
||||
char *pwd = getenv("PWD");
|
||||
struct stat stdot, stpwd;
|
||||
|
||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||
stat(pwd, &stpwd) != -1 &&
|
||||
stdot.st_dev == stpwd.st_dev &&
|
||||
stdot.st_ino == stpwd.st_ino) {
|
||||
curdir = savestr(pwd);
|
||||
return;
|
||||
}
|
||||
error("getcwd() failed: %s", strerror(errno));
|
||||
}
|
||||
curdir = savestr(buf);
|
||||
#else
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
int status;
|
||||
struct job *jp;
|
||||
int pip[2];
|
||||
|
||||
INTOFF;
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
jp = makejob((union node *)NULL, 1);
|
||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
(void) close(pip[0]);
|
||||
if (pip[1] != 1) {
|
||||
close(1);
|
||||
copyfd(pip[1], 1);
|
||||
close(pip[1]);
|
||||
}
|
||||
(void) execl("/bin/pwd", "pwd", (char *)0);
|
||||
error("Cannot exec /bin/pwd");
|
||||
}
|
||||
(void) close(pip[1]);
|
||||
pip[1] = -1;
|
||||
p = buf;
|
||||
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
|
||||
|| (i == -1 && errno == EINTR)) {
|
||||
if (i > 0)
|
||||
p += i;
|
||||
}
|
||||
(void) close(pip[0]);
|
||||
pip[0] = -1;
|
||||
status = waitforjob(jp);
|
||||
if (status != 0)
|
||||
error((char *)0);
|
||||
if (i < 0 || p == buf || p[-1] != '\n')
|
||||
error("pwd command failed");
|
||||
p[-1] = '\0';
|
||||
}
|
||||
curdir = savestr(buf);
|
||||
INTON;
|
||||
#endif
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/* $NetBSD: cd.h,v 1.2 1997/07/04 21:01:52 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
void getpwd __P((void));
|
||||
int cdcmd __P((int, char **));
|
||||
int pwdcmd __P((int, char **));
|
@ -1,291 +0,0 @@
|
||||
/* $NetBSD: error.c,v 1.17 1997/07/04 21:01:54 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: error.c,v 1.17 1997/07/04 21:01:54 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Errors and exceptions.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "error.h"
|
||||
#include "show.h"
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
* Code to handle exceptions in C.
|
||||
*/
|
||||
|
||||
struct jmploc *handler;
|
||||
int exception;
|
||||
volatile int suppressint;
|
||||
volatile int intpending;
|
||||
char *commandname;
|
||||
|
||||
|
||||
static void exverror __P((int, char *, va_list)) __attribute__((__noreturn__));
|
||||
|
||||
/*
|
||||
* Called to raise an exception. Since C doesn't include exceptions, we
|
||||
* just do a longjmp to the exception handler. The type of exception is
|
||||
* stored in the global variable "exception".
|
||||
*/
|
||||
|
||||
void
|
||||
exraise(e)
|
||||
int e;
|
||||
{
|
||||
if (handler == NULL)
|
||||
abort();
|
||||
exception = e;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
||||
* there is a short period after a fork before the signal handlers are
|
||||
* set to the appropriate value for the child. (The test for iflag is
|
||||
* just defensive programming.)
|
||||
*/
|
||||
|
||||
void
|
||||
onint() {
|
||||
sigset_t sigset;
|
||||
|
||||
if (suppressint) {
|
||||
intpending++;
|
||||
return;
|
||||
}
|
||||
intpending = 0;
|
||||
sigemptyset(&sigset);
|
||||
sigprocmask(SIG_SETMASK, &sigset, NULL);
|
||||
if (rootshell && iflag)
|
||||
exraise(EXINT);
|
||||
else
|
||||
_exit(128 + SIGINT);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Exverror is called to raise the error exception. If the first argument
|
||||
* is not NULL then error prints an error message using printf style
|
||||
* formatting. It then raises the error exception.
|
||||
*/
|
||||
static void
|
||||
exverror(cond, msg, ap)
|
||||
int cond;
|
||||
char *msg;
|
||||
va_list ap;
|
||||
{
|
||||
CLEAR_PENDING_INT;
|
||||
INTOFF;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (msg)
|
||||
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
|
||||
else
|
||||
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||
#endif
|
||||
if (msg) {
|
||||
if (commandname)
|
||||
outfmt(&errout, "%s: ", commandname);
|
||||
doformat(&errout, msg, ap);
|
||||
out2c('\n');
|
||||
}
|
||||
flushall();
|
||||
exraise(cond);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
error(char *msg, ...)
|
||||
#else
|
||||
void
|
||||
error(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char *msg;
|
||||
#endif
|
||||
va_list ap;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, msg);
|
||||
#else
|
||||
va_start(ap);
|
||||
msg = va_arg(ap, char *);
|
||||
#endif
|
||||
exverror(EXERROR, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
exerror(int cond, char *msg, ...)
|
||||
#else
|
||||
void
|
||||
exerror(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifndef __STDC__
|
||||
int cond;
|
||||
char *msg;
|
||||
#endif
|
||||
va_list ap;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, msg);
|
||||
#else
|
||||
va_start(ap);
|
||||
cond = va_arg(ap, int);
|
||||
msg = va_arg(ap, char *);
|
||||
#endif
|
||||
exverror(cond, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Table of error messages.
|
||||
*/
|
||||
|
||||
struct errname {
|
||||
short errcode; /* error number */
|
||||
short action; /* operation which encountered the error */
|
||||
char *msg; /* text describing the error */
|
||||
};
|
||||
|
||||
|
||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||
|
||||
STATIC const struct errname errormsg[] = {
|
||||
{ EINTR, ALL, "interrupted" },
|
||||
{ EACCES, ALL, "permission denied" },
|
||||
{ EIO, ALL, "I/O error" },
|
||||
{ ENOENT, E_OPEN, "no such file" },
|
||||
{ ENOENT, E_CREAT,"directory nonexistent" },
|
||||
{ ENOENT, E_EXEC, "not found" },
|
||||
{ ENOTDIR, E_OPEN, "no such file" },
|
||||
{ ENOTDIR, E_CREAT,"directory nonexistent" },
|
||||
{ ENOTDIR, E_EXEC, "not found" },
|
||||
{ EISDIR, ALL, "is a directory" },
|
||||
#ifdef notdef
|
||||
{ EMFILE, ALL, "too many open files" },
|
||||
#endif
|
||||
{ ENFILE, ALL, "file table overflow" },
|
||||
{ ENOSPC, ALL, "file system full" },
|
||||
#ifdef EDQUOT
|
||||
{ EDQUOT, ALL, "disk quota exceeded" },
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
{ ENOSR, ALL, "no streams resources" },
|
||||
#endif
|
||||
{ ENXIO, ALL, "no such device or address" },
|
||||
{ EROFS, ALL, "read-only file system" },
|
||||
{ ETXTBSY, ALL, "text busy" },
|
||||
#ifdef SYSV
|
||||
{ EAGAIN, E_EXEC, "not enough memory" },
|
||||
#endif
|
||||
{ ENOMEM, ALL, "not enough memory" },
|
||||
#ifdef ENOLINK
|
||||
{ ENOLINK, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
{ EMULTIHOP, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ECOMM
|
||||
{ ECOMM, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
{ ESTALE, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
{ ETIMEDOUT, ALL, "remote access failed" },
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
{ ELOOP, ALL, "symbolic link loop" },
|
||||
#endif
|
||||
{ E2BIG, E_EXEC, "argument list too long" },
|
||||
#ifdef ELIBACC
|
||||
{ ELIBACC, E_EXEC, "shared library missing" },
|
||||
#endif
|
||||
{ 0, 0, NULL },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Return a string describing an error. The returned string may be a
|
||||
* pointer to a static buffer that will be overwritten on the next call.
|
||||
* Action describes the operation that got the error.
|
||||
*/
|
||||
|
||||
char *
|
||||
errmsg(e, action)
|
||||
int e;
|
||||
int action;
|
||||
{
|
||||
struct errname const *ep;
|
||||
static char buf[12];
|
||||
|
||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
||||
if (ep->errcode == e && (ep->action & action) != 0)
|
||||
return ep->msg;
|
||||
}
|
||||
fmtstr(buf, sizeof buf, "error %d", e);
|
||||
return buf;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/* $NetBSD: error.h,v 1.10 1997/07/04 21:01:55 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Types of operations (passed to the errmsg routine).
|
||||
*/
|
||||
|
||||
#define E_OPEN 01 /* opening a file */
|
||||
#define E_CREAT 02 /* creating a file */
|
||||
#define E_EXEC 04 /* executing a program */
|
||||
|
||||
|
||||
/*
|
||||
* We enclose jmp_buf in a structure so that we can declare pointers to
|
||||
* jump locations. The global variable handler contains the location to
|
||||
* jump to when an exception occurs, and the global variable exception
|
||||
* contains a code identifying the exeception. To implement nested
|
||||
* exception handlers, the user should save the value of handler on entry
|
||||
* to an inner scope, set handler to point to a jmploc structure for the
|
||||
* inner scope, and restore handler on exit from the scope.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct jmploc {
|
||||
jmp_buf loc;
|
||||
};
|
||||
|
||||
extern struct jmploc *handler;
|
||||
extern int exception;
|
||||
|
||||
/* exceptions */
|
||||
#define EXINT 0 /* SIGINT received */
|
||||
#define EXERROR 1 /* a generic error */
|
||||
#define EXSHELLPROC 2 /* execute a shell procedure */
|
||||
#define EXEXEC 3 /* command execution failed */
|
||||
|
||||
|
||||
/*
|
||||
* These macros allow the user to suspend the handling of interrupt signals
|
||||
* over a period of time. This is similar to SIGHOLD to or sigblock, but
|
||||
* much more efficient and portable. (But hacking the kernel is so much
|
||||
* more fun than worrying about efficiency and portability. :-))
|
||||
*/
|
||||
|
||||
extern volatile int suppressint;
|
||||
extern volatile int intpending;
|
||||
extern char *commandname; /* name of command--printed on error */
|
||||
|
||||
#define INTOFF suppressint++
|
||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
||||
#define CLEAR_PENDING_INT intpending = 0
|
||||
#define int_pending() intpending
|
||||
|
||||
void exraise __P((int)) __attribute__((__noreturn__));
|
||||
void onint __P((void));
|
||||
void error __P((char *, ...)) __attribute__((__noreturn__));
|
||||
void exerror __P((int, char *, ...));
|
||||
char *errmsg __P((int, int));
|
||||
|
||||
|
||||
/*
|
||||
* BSD setjmp saves the signal mask, which violates ANSI C and takes time,
|
||||
* so we use _setjmp instead.
|
||||
*/
|
||||
|
||||
#ifdef BSD
|
||||
#define setjmp(jmploc) _setjmp(jmploc)
|
||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,74 +0,0 @@
|
||||
/* $NetBSD: eval.h,v 1.9 1995/09/11 17:05:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
extern char *commandname; /* currently executing command */
|
||||
extern int exitstatus; /* exit status of last command */
|
||||
extern struct strlist *cmdenviron; /* environment for builtin command */
|
||||
|
||||
|
||||
struct backcmd { /* result of evalbackcmd */
|
||||
int fd; /* file descriptor to read from */
|
||||
char *buf; /* buffer */
|
||||
int nleft; /* number of chars in buffer */
|
||||
struct job *jp; /* job structure for command */
|
||||
};
|
||||
|
||||
int evalcmd __P((int, char **));
|
||||
void evalstring __P((char *));
|
||||
union node; /* BLETCH for ansi C */
|
||||
void evaltree __P((union node *, int));
|
||||
void evalbackcmd __P((union node *, struct backcmd *));
|
||||
int bltincmd __P((int, char **));
|
||||
int breakcmd __P((int, char **));
|
||||
int returncmd __P((int, char **));
|
||||
int falsecmd __P((int, char **));
|
||||
int truecmd __P((int, char **));
|
||||
int execcmd __P((int, char **));
|
||||
|
||||
/* in_function returns nonzero if we are currently evaluating a function */
|
||||
#define in_function() funcnest
|
||||
extern int funcnest;
|
||||
extern int evalskip;
|
||||
|
||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||
#define SKIPBREAK 1
|
||||
#define SKIPCONT 2
|
||||
#define SKIPFUNC 3
|
||||
#define SKIPFILE 4
|
@ -1,921 +0,0 @@
|
||||
/* $NetBSD: exec.c,v 1.23 1997/07/04 21:01:59 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: exec.c,v 1.23 1997/07/04 21:01:59 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* When commands are first encountered, they are entered in a hash table.
|
||||
* This ensures that a full path search will not have to be done for them
|
||||
* on each invocation.
|
||||
*
|
||||
* We should investigate converting to a linear search, even though that
|
||||
* would make the command name "hash" a misnomer.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "nodes.h"
|
||||
#include "parser.h"
|
||||
#include "redir.h"
|
||||
#include "eval.h"
|
||||
#include "exec.h"
|
||||
#include "builtins.h"
|
||||
#include "var.h"
|
||||
#include "options.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "syntax.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
#include "show.h"
|
||||
#include "jobs.h"
|
||||
#include "alias.h"
|
||||
|
||||
|
||||
#define CMDTABLESIZE 31 /* should be prime */
|
||||
#define ARB 1 /* actual size determined at run time */
|
||||
|
||||
|
||||
|
||||
struct tblentry {
|
||||
struct tblentry *next; /* next entry in hash chain */
|
||||
union param param; /* definition of builtin function */
|
||||
short cmdtype; /* index identifying command */
|
||||
char rehash; /* if set, cd done since entry created */
|
||||
char cmdname[ARB]; /* name of command */
|
||||
};
|
||||
|
||||
|
||||
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
|
||||
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
||||
int exerrno = 0; /* Last exec error */
|
||||
|
||||
|
||||
STATIC void tryexec __P((char *, char **, char **));
|
||||
STATIC void execinterp __P((char **, char **));
|
||||
STATIC void printentry __P((struct tblentry *, int));
|
||||
STATIC void clearcmdentry __P((int));
|
||||
STATIC struct tblentry *cmdlookup __P((char *, int));
|
||||
STATIC void delete_cmd_entry __P((void));
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Exec a program. Never returns. If you change this routine, you may
|
||||
* have to change the find_command routine as well.
|
||||
*/
|
||||
|
||||
void
|
||||
shellexec(argv, envp, path, index)
|
||||
char **argv, **envp;
|
||||
char *path;
|
||||
int index;
|
||||
{
|
||||
char *cmdname;
|
||||
int e;
|
||||
|
||||
if (strchr(argv[0], '/') != NULL) {
|
||||
tryexec(argv[0], argv, envp);
|
||||
e = errno;
|
||||
} else {
|
||||
e = ENOENT;
|
||||
while ((cmdname = padvance(&path, argv[0])) != NULL) {
|
||||
if (--index < 0 && pathopt == NULL) {
|
||||
tryexec(cmdname, argv, envp);
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
e = errno;
|
||||
}
|
||||
stunalloc(cmdname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Map to POSIX errors */
|
||||
switch (e) {
|
||||
case EACCES:
|
||||
exerrno = 126;
|
||||
break;
|
||||
case ENOENT:
|
||||
exerrno = 127;
|
||||
break;
|
||||
default:
|
||||
exerrno = 2;
|
||||
break;
|
||||
}
|
||||
exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
tryexec(cmd, argv, envp)
|
||||
char *cmd;
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
int e;
|
||||
#ifndef BSD
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
#ifdef SYSV
|
||||
do {
|
||||
execve(cmd, argv, envp);
|
||||
} while (errno == EINTR);
|
||||
#else
|
||||
execve(cmd, argv, envp);
|
||||
#endif
|
||||
e = errno;
|
||||
if (e == ENOEXEC) {
|
||||
initshellproc();
|
||||
setinputfile(cmd, 0);
|
||||
commandname = arg0 = savestr(argv[0]);
|
||||
#ifndef BSD
|
||||
pgetc(); pungetc(); /* fill up input buffer */
|
||||
p = parsenextc;
|
||||
if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
|
||||
argv[0] = cmd;
|
||||
execinterp(argv, envp);
|
||||
}
|
||||
#endif
|
||||
setparam(argv + 1);
|
||||
exraise(EXSHELLPROC);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
errno = e;
|
||||
}
|
||||
|
||||
|
||||
#ifndef BSD
|
||||
/*
|
||||
* Execute an interpreter introduced by "#!", for systems where this
|
||||
* feature has not been built into the kernel. If the interpreter is
|
||||
* the shell, return (effectively ignoring the "#!"). If the execution
|
||||
* of the interpreter fails, exit.
|
||||
*
|
||||
* This code peeks inside the input buffer in order to avoid actually
|
||||
* reading any input. It would benefit from a rewrite.
|
||||
*/
|
||||
|
||||
#define NEWARGS 5
|
||||
|
||||
STATIC void
|
||||
execinterp(argv, envp)
|
||||
char **argv, **envp;
|
||||
{
|
||||
int n;
|
||||
char *inp;
|
||||
char *outp;
|
||||
char c;
|
||||
char *p;
|
||||
char **ap;
|
||||
char *newargs[NEWARGS];
|
||||
int i;
|
||||
char **ap2;
|
||||
char **new;
|
||||
|
||||
n = parsenleft - 2;
|
||||
inp = parsenextc + 2;
|
||||
ap = newargs;
|
||||
for (;;) {
|
||||
while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
|
||||
inp++;
|
||||
if (n < 0)
|
||||
goto bad;
|
||||
if ((c = *inp++) == '\n')
|
||||
break;
|
||||
if (ap == &newargs[NEWARGS])
|
||||
bad: error("Bad #! line");
|
||||
STARTSTACKSTR(outp);
|
||||
do {
|
||||
STPUTC(c, outp);
|
||||
} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
|
||||
STPUTC('\0', outp);
|
||||
n++, inp--;
|
||||
*ap++ = grabstackstr(outp);
|
||||
}
|
||||
if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
|
||||
p = newargs[0];
|
||||
for (;;) {
|
||||
if (equal(p, "sh") || equal(p, "ash")) {
|
||||
return;
|
||||
}
|
||||
while (*p != '/') {
|
||||
if (*p == '\0')
|
||||
goto break2;
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
break2:;
|
||||
}
|
||||
i = (char *)ap - (char *)newargs; /* size in bytes */
|
||||
if (i == 0)
|
||||
error("Bad #! line");
|
||||
for (ap2 = argv ; *ap2++ != NULL ; );
|
||||
new = ckmalloc(i + ((char *)ap2 - (char *)argv));
|
||||
ap = newargs, ap2 = new;
|
||||
while ((i -= sizeof (char **)) >= 0)
|
||||
*ap2++ = *ap++;
|
||||
ap = argv;
|
||||
while (*ap2++ = *ap++);
|
||||
shellexec(new, envp, pathval(), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Do a path search. The variable path (passed by reference) should be
|
||||
* set to the start of the path before the first call; padvance will update
|
||||
* this value as it proceeds. Successive calls to padvance will return
|
||||
* the possible path expansions in sequence. If an option (indicated by
|
||||
* a percent sign) appears in the path entry then the global variable
|
||||
* pathopt will be set to point to it; otherwise pathopt will be set to
|
||||
* NULL.
|
||||
*/
|
||||
|
||||
char *pathopt;
|
||||
|
||||
char *
|
||||
padvance(path, name)
|
||||
char **path;
|
||||
char *name;
|
||||
{
|
||||
char *p, *q;
|
||||
char *start;
|
||||
int len;
|
||||
|
||||
if (*path == NULL)
|
||||
return NULL;
|
||||
start = *path;
|
||||
for (p = start ; *p && *p != ':' && *p != '%' ; p++);
|
||||
len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
|
||||
while (stackblocksize() < len)
|
||||
growstackblock();
|
||||
q = stackblock();
|
||||
if (p != start) {
|
||||
memcpy(q, start, p - start);
|
||||
q += p - start;
|
||||
*q++ = '/';
|
||||
}
|
||||
strcpy(q, name);
|
||||
pathopt = NULL;
|
||||
if (*p == '%') {
|
||||
pathopt = ++p;
|
||||
while (*p && *p != ':') p++;
|
||||
}
|
||||
if (*p == ':')
|
||||
*path = p + 1;
|
||||
else
|
||||
*path = NULL;
|
||||
return stalloc(len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** Command hashing code ***/
|
||||
|
||||
|
||||
int
|
||||
hashcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
int c;
|
||||
int verbose;
|
||||
struct cmdentry entry;
|
||||
char *name;
|
||||
|
||||
verbose = 0;
|
||||
while ((c = nextopt("rv")) != '\0') {
|
||||
if (c == 'r') {
|
||||
clearcmdentry(0);
|
||||
} else if (c == 'v') {
|
||||
verbose++;
|
||||
}
|
||||
}
|
||||
if (*argptr == NULL) {
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
printentry(cmdp, verbose);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
while ((name = *argptr) != NULL) {
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL
|
||||
&& (cmdp->cmdtype == CMDNORMAL
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
||||
delete_cmd_entry();
|
||||
find_command(name, &entry, 1, pathval());
|
||||
if (verbose) {
|
||||
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
||||
cmdp = cmdlookup(name, 0);
|
||||
printentry(cmdp, verbose);
|
||||
}
|
||||
flushall();
|
||||
}
|
||||
argptr++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
printentry(cmdp, verbose)
|
||||
struct tblentry *cmdp;
|
||||
int verbose;
|
||||
{
|
||||
int index;
|
||||
char *path;
|
||||
char *name;
|
||||
|
||||
if (cmdp->cmdtype == CMDNORMAL) {
|
||||
index = cmdp->param.index;
|
||||
path = pathval();
|
||||
do {
|
||||
name = padvance(&path, cmdp->cmdname);
|
||||
stunalloc(name);
|
||||
} while (--index >= 0);
|
||||
out1str(name);
|
||||
} else if (cmdp->cmdtype == CMDBUILTIN) {
|
||||
out1fmt("builtin %s", cmdp->cmdname);
|
||||
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
out1fmt("function %s", cmdp->cmdname);
|
||||
if (verbose) {
|
||||
INTOFF;
|
||||
name = commandtext(cmdp->param.func);
|
||||
out1c(' ');
|
||||
out1str(name);
|
||||
ckfree(name);
|
||||
INTON;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
} else {
|
||||
error("internal error: cmdtype %d", cmdp->cmdtype);
|
||||
#endif
|
||||
}
|
||||
if (cmdp->rehash)
|
||||
out1c('*');
|
||||
out1c('\n');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Resolve a command name. If you change this routine, you may have to
|
||||
* change the shellexec routine as well.
|
||||
*/
|
||||
|
||||
void
|
||||
find_command(name, entry, printerr, path)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
int printerr;
|
||||
char *path;
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
int index;
|
||||
int prev;
|
||||
char *fullname;
|
||||
struct stat statb;
|
||||
int e;
|
||||
int i;
|
||||
|
||||
/* If name contains a slash, don't use the hash table */
|
||||
if (strchr(name, '/') != NULL) {
|
||||
entry->cmdtype = CMDNORMAL;
|
||||
entry->u.index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If name is in the table, and not invalidated by cd, we're done */
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
|
||||
goto success;
|
||||
|
||||
/* If %builtin not in path, check for builtin next */
|
||||
if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
cmdp->cmdtype = CMDBUILTIN;
|
||||
cmdp->param.index = i;
|
||||
INTON;
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* We have to search path. */
|
||||
prev = -1; /* where to start */
|
||||
if (cmdp) { /* doing a rehash */
|
||||
if (cmdp->cmdtype == CMDBUILTIN)
|
||||
prev = builtinloc;
|
||||
else
|
||||
prev = cmdp->param.index;
|
||||
}
|
||||
|
||||
e = ENOENT;
|
||||
index = -1;
|
||||
loop:
|
||||
while ((fullname = padvance(&path, name)) != NULL) {
|
||||
stunalloc(fullname);
|
||||
index++;
|
||||
if (pathopt) {
|
||||
if (prefix("builtin", pathopt)) {
|
||||
if ((i = find_builtin(name)) < 0)
|
||||
goto loop;
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
cmdp->cmdtype = CMDBUILTIN;
|
||||
cmdp->param.index = i;
|
||||
INTON;
|
||||
goto success;
|
||||
} else if (prefix("func", pathopt)) {
|
||||
/* handled below */
|
||||
} else {
|
||||
goto loop; /* ignore unimplemented options */
|
||||
}
|
||||
}
|
||||
/* if rehash, don't redo absolute path names */
|
||||
if (fullname[0] == '/' && index <= prev) {
|
||||
if (index < prev)
|
||||
goto loop;
|
||||
TRACE(("searchexec \"%s\": no change\n", name));
|
||||
goto success;
|
||||
}
|
||||
while (stat(fullname, &statb) < 0) {
|
||||
#ifdef SYSV
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
if (errno != ENOENT && errno != ENOTDIR)
|
||||
e = errno;
|
||||
goto loop;
|
||||
}
|
||||
e = EACCES; /* if we fail, this will be the error */
|
||||
if (!S_ISREG(statb.st_mode))
|
||||
goto loop;
|
||||
if (pathopt) { /* this is a %func directory */
|
||||
stalloc(strlen(fullname) + 1);
|
||||
readcmdfile(fullname);
|
||||
if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
|
||||
error("%s not defined in %s", name, fullname);
|
||||
stunalloc(fullname);
|
||||
goto success;
|
||||
}
|
||||
#ifdef notdef
|
||||
if (statb.st_uid == geteuid()) {
|
||||
if ((statb.st_mode & 0100) == 0)
|
||||
goto loop;
|
||||
} else if (statb.st_gid == getegid()) {
|
||||
if ((statb.st_mode & 010) == 0)
|
||||
goto loop;
|
||||
} else {
|
||||
if ((statb.st_mode & 01) == 0)
|
||||
goto loop;
|
||||
}
|
||||
#endif
|
||||
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
cmdp->cmdtype = CMDNORMAL;
|
||||
cmdp->param.index = index;
|
||||
INTON;
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* We failed. If there was an entry for this command, delete it */
|
||||
if (cmdp)
|
||||
delete_cmd_entry();
|
||||
if (printerr)
|
||||
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
return;
|
||||
|
||||
success:
|
||||
cmdp->rehash = 0;
|
||||
entry->cmdtype = cmdp->cmdtype;
|
||||
entry->u = cmdp->param;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Search the table of builtin commands.
|
||||
*/
|
||||
|
||||
int
|
||||
find_builtin(name)
|
||||
char *name;
|
||||
{
|
||||
const struct builtincmd *bp;
|
||||
|
||||
for (bp = builtincmd ; bp->name ; bp++) {
|
||||
if (*bp->name == *name && equal(bp->name, name))
|
||||
return bp->code;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called when a cd is done. Marks all commands so the next time they
|
||||
* are executed they will be rehashed.
|
||||
*/
|
||||
|
||||
void
|
||||
hashcd() {
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype == CMDNORMAL
|
||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||
cmdp->rehash = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called before PATH is changed. The argument is the new value of PATH;
|
||||
* pathval() still returns the old value at this point. Called with
|
||||
* interrupts off.
|
||||
*/
|
||||
|
||||
void
|
||||
changepath(newval)
|
||||
const char *newval;
|
||||
{
|
||||
const char *old, *new;
|
||||
int index;
|
||||
int firstchange;
|
||||
int bltin;
|
||||
|
||||
old = pathval();
|
||||
new = newval;
|
||||
firstchange = 9999; /* assume no change */
|
||||
index = 0;
|
||||
bltin = -1;
|
||||
for (;;) {
|
||||
if (*old != *new) {
|
||||
firstchange = index;
|
||||
if ((*old == '\0' && *new == ':')
|
||||
|| (*old == ':' && *new == '\0'))
|
||||
firstchange++;
|
||||
old = new; /* ignore subsequent differences */
|
||||
}
|
||||
if (*new == '\0')
|
||||
break;
|
||||
if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
|
||||
bltin = index;
|
||||
if (*new == ':') {
|
||||
index++;
|
||||
}
|
||||
new++, old++;
|
||||
}
|
||||
if (builtinloc < 0 && bltin >= 0)
|
||||
builtinloc = bltin; /* zap builtins */
|
||||
if (builtinloc >= 0 && bltin < 0)
|
||||
firstchange = 0;
|
||||
clearcmdentry(firstchange);
|
||||
builtinloc = bltin;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear out command entries. The argument specifies the first entry in
|
||||
* PATH which has changed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
clearcmdentry(firstchange)
|
||||
int firstchange;
|
||||
{
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
||||
pp = tblp;
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if ((cmdp->cmdtype == CMDNORMAL &&
|
||||
cmdp->param.index >= firstchange)
|
||||
|| (cmdp->cmdtype == CMDBUILTIN &&
|
||||
builtinloc >= firstchange)) {
|
||||
*pp = cmdp->next;
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
pp = &cmdp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete all functions.
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void deletefuncs __P((void));
|
||||
|
||||
SHELLPROC {
|
||||
deletefuncs();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
deletefuncs() {
|
||||
struct tblentry **tblp;
|
||||
struct tblentry **pp;
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
||||
pp = tblp;
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
*pp = cmdp->next;
|
||||
freefunc(cmdp->param.func);
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
pp = &cmdp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Locate a command in the command hash table. If "add" is nonzero,
|
||||
* add the command to the table if it is not already present. The
|
||||
* variable "lastcmdentry" is set to point to the address of the link
|
||||
* pointing to the entry, so that delete_cmd_entry can delete the
|
||||
* entry.
|
||||
*/
|
||||
|
||||
struct tblentry **lastcmdentry;
|
||||
|
||||
|
||||
STATIC struct tblentry *
|
||||
cmdlookup(name, add)
|
||||
char *name;
|
||||
int add;
|
||||
{
|
||||
int hashval;
|
||||
char *p;
|
||||
struct tblentry *cmdp;
|
||||
struct tblentry **pp;
|
||||
|
||||
p = name;
|
||||
hashval = *p << 4;
|
||||
while (*p)
|
||||
hashval += *p++;
|
||||
hashval &= 0x7FFF;
|
||||
pp = &cmdtable[hashval % CMDTABLESIZE];
|
||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||
if (equal(cmdp->cmdname, name))
|
||||
break;
|
||||
pp = &cmdp->next;
|
||||
}
|
||||
if (add && cmdp == NULL) {
|
||||
INTOFF;
|
||||
cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
|
||||
+ strlen(name) + 1);
|
||||
cmdp->next = NULL;
|
||||
cmdp->cmdtype = CMDUNKNOWN;
|
||||
cmdp->rehash = 0;
|
||||
strcpy(cmdp->cmdname, name);
|
||||
INTON;
|
||||
}
|
||||
lastcmdentry = pp;
|
||||
return cmdp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the command entry returned on the last lookup.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
delete_cmd_entry() {
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
cmdp = *lastcmdentry;
|
||||
*lastcmdentry = cmdp->next;
|
||||
ckfree(cmdp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
void
|
||||
getcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
struct tblentry *cmdp = cmdlookup(name, 0);
|
||||
|
||||
if (cmdp) {
|
||||
entry->u = cmdp->param;
|
||||
entry->cmdtype = cmdp->cmdtype;
|
||||
} else {
|
||||
entry->cmdtype = CMDUNKNOWN;
|
||||
entry->u.index = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Add a new command entry, replacing any existing command entry for
|
||||
* the same name.
|
||||
*/
|
||||
|
||||
void
|
||||
addcmdentry(name, entry)
|
||||
char *name;
|
||||
struct cmdentry *entry;
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
freefunc(cmdp->param.func);
|
||||
}
|
||||
cmdp->cmdtype = entry->cmdtype;
|
||||
cmdp->param = entry->u;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Define a shell function.
|
||||
*/
|
||||
|
||||
void
|
||||
defun(name, func)
|
||||
char *name;
|
||||
union node *func;
|
||||
{
|
||||
struct cmdentry entry;
|
||||
|
||||
INTOFF;
|
||||
entry.cmdtype = CMDFUNCTION;
|
||||
entry.u.func = copyfunc(func);
|
||||
addcmdentry(name, &entry);
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete a function if it exists.
|
||||
*/
|
||||
|
||||
int
|
||||
unsetfunc(name)
|
||||
char *name;
|
||||
{
|
||||
struct tblentry *cmdp;
|
||||
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||
freefunc(cmdp->param.func);
|
||||
delete_cmd_entry();
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate and print what a word is...
|
||||
*/
|
||||
|
||||
int
|
||||
typecmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct cmdentry entry;
|
||||
struct tblentry *cmdp;
|
||||
char **pp;
|
||||
struct alias *ap;
|
||||
int i;
|
||||
int error = 0;
|
||||
extern char *const parsekwd[];
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
out1str(argv[i]);
|
||||
/* First look at the keywords */
|
||||
for (pp = (char **)parsekwd; *pp; pp++)
|
||||
if (**pp == *argv[i] && equal(*pp, argv[i]))
|
||||
break;
|
||||
|
||||
if (*pp) {
|
||||
out1str(" is a shell keyword\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then look at the aliases */
|
||||
if ((ap = lookupalias(argv[i], 1)) != NULL) {
|
||||
out1fmt(" is an alias for %s\n", ap->val);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then check if it is a tracked alias */
|
||||
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
|
||||
entry.cmdtype = cmdp->cmdtype;
|
||||
entry.u = cmdp->param;
|
||||
}
|
||||
else {
|
||||
/* Finally use brute force */
|
||||
find_command(argv[i], &entry, 0, pathval());
|
||||
}
|
||||
|
||||
switch (entry.cmdtype) {
|
||||
case CMDNORMAL: {
|
||||
int j = entry.u.index;
|
||||
char *path = pathval(), *name;
|
||||
do {
|
||||
name = padvance(&path, argv[i]);
|
||||
stunalloc(name);
|
||||
} while (--j >= 0);
|
||||
out1fmt(" is%s %s\n",
|
||||
cmdp ? " a tracked alias for" : "", name);
|
||||
break;
|
||||
}
|
||||
case CMDFUNCTION:
|
||||
out1str(" is a shell function\n");
|
||||
break;
|
||||
|
||||
case CMDBUILTIN:
|
||||
out1str(" is a shell builtin\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
out1str(" not found\n");
|
||||
error |= 127;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/* $NetBSD: exec.h,v 1.12 1997/02/06 23:24:53 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||
*/
|
||||
|
||||
/* values of cmdtype */
|
||||
#define CMDUNKNOWN -1 /* no entry in table for command */
|
||||
#define CMDNORMAL 0 /* command is an executable program */
|
||||
#define CMDBUILTIN 1 /* command is a shell builtin */
|
||||
#define CMDFUNCTION 2 /* command is a shell function */
|
||||
|
||||
|
||||
struct cmdentry {
|
||||
int cmdtype;
|
||||
union param {
|
||||
int index;
|
||||
union node *func;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
extern char *pathopt; /* set by padvance */
|
||||
extern int exerrno; /* last exec error */
|
||||
|
||||
void shellexec __P((char **, char **, char *, int));
|
||||
char *padvance __P((char **, char *));
|
||||
int hashcmd __P((int, char **));
|
||||
void find_command __P((char *, struct cmdentry *, int, char *));
|
||||
int find_builtin __P((char *));
|
||||
void hashcd __P((void));
|
||||
void changepath __P((const char *));
|
||||
void deletefuncs __P((void));
|
||||
void getcmdentry __P((char *, struct cmdentry *));
|
||||
void addcmdentry __P((char *, struct cmdentry *));
|
||||
void defun __P((char *, union node *));
|
||||
int unsetfunc __P((char *));
|
||||
int typecmd __P((int, char **));
|
File diff suppressed because it is too large
Load Diff
@ -1,68 +0,0 @@
|
||||
/* $NetBSD: expand.h,v 1.8 1995/05/11 21:29:08 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct strlist {
|
||||
struct strlist *next;
|
||||
char *text;
|
||||
};
|
||||
|
||||
|
||||
struct arglist {
|
||||
struct strlist *list;
|
||||
struct strlist **lastp;
|
||||
};
|
||||
|
||||
/*
|
||||
* expandarg() flags
|
||||
*/
|
||||
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
|
||||
#define EXP_TILDE 0x2 /* do normal tilde expansion */
|
||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||
|
||||
|
||||
union node;
|
||||
void expandhere __P((union node *, int));
|
||||
void expandarg __P((union node *, struct arglist *, int));
|
||||
void expari __P((int));
|
||||
int patmatch __P((char *, char *));
|
||||
void rmescapes __P((char *));
|
||||
int casematch __P((union node *, char *));
|
@ -1,50 +0,0 @@
|
||||
# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# Conditional move--don't replace an existing file.
|
||||
|
||||
cmv() {
|
||||
if test $# != 2
|
||||
then echo "cmv: arg count"
|
||||
return 2
|
||||
fi
|
||||
if test -f "$2" -o -w "$2"
|
||||
then echo "$2 exists"
|
||||
return 2
|
||||
fi
|
||||
/bin/mv "$1" "$2"
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# Convert job names to process ids and then run /bin/kill.
|
||||
|
||||
kill() {
|
||||
local args x
|
||||
args=
|
||||
for x in "$@"
|
||||
do case $x in
|
||||
%*) x=`jobid "$x"` ;;
|
||||
esac
|
||||
args="$args $x"
|
||||
done
|
||||
/bin/kill $args
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# replaces the login builtin in the BSD shell
|
||||
login () exec login "$@"
|
@ -1,38 +0,0 @@
|
||||
# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||
|
||||
newgrp() exec newgrp "$@"
|
@ -1,74 +0,0 @@
|
||||
# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# pushd, popd, and dirs --- written by Chris Bertin
|
||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||
# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
|
||||
|
||||
pushd () {
|
||||
SAVE=`pwd`
|
||||
if [ "$1" = "" ]
|
||||
then if [ "$DSTACK" = "" ]
|
||||
then echo "pushd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1 || return
|
||||
shift 1
|
||||
DSTACK="$*"
|
||||
else cd $1 > /dev/null || return
|
||||
fi
|
||||
DSTACK="$SAVE $DSTACK"
|
||||
dirs
|
||||
}
|
||||
|
||||
popd () {
|
||||
if [ "$DSTACK" = "" ]
|
||||
then echo "popd: directory stack empty."
|
||||
return 1
|
||||
fi
|
||||
set $DSTACK
|
||||
cd $1
|
||||
shift
|
||||
DSTACK=$*
|
||||
dirs
|
||||
}
|
||||
|
||||
dirs () {
|
||||
echo "`pwd` $DSTACK"
|
||||
return 0
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||
|
||||
suspend() {
|
||||
local -
|
||||
set +j
|
||||
kill -TSTP 0
|
||||
}
|
@ -1,501 +0,0 @@
|
||||
/* $NetBSD: histedit.c,v 1.14 1997/07/04 21:02:02 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: histedit.c,v 1.14 1997/07/04 21:02:02 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
/*
|
||||
* Editline and history functions (and glue).
|
||||
*/
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "var.h"
|
||||
#include "options.h"
|
||||
#include "main.h"
|
||||
#include "output.h"
|
||||
#include "mystring.h"
|
||||
#ifndef SMALL
|
||||
#include "myhistedit.h"
|
||||
#include "error.h"
|
||||
#include "eval.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
#define MAXHISTLOOPS 4 /* max recursions through fc */
|
||||
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
|
||||
|
||||
History *hist; /* history cookie */
|
||||
EditLine *el; /* editline cookie */
|
||||
int displayhist;
|
||||
static FILE *el_in, *el_out;
|
||||
|
||||
STATIC char *fc_replace __P((const char *, char *, char *));
|
||||
|
||||
/*
|
||||
* Set history and editing status. Called whenever the status may
|
||||
* have changed (figures out what to do).
|
||||
*/
|
||||
void
|
||||
histedit()
|
||||
{
|
||||
|
||||
#define editing (Eflag || Vflag)
|
||||
|
||||
if (iflag) {
|
||||
if (!hist) {
|
||||
/*
|
||||
* turn history on
|
||||
*/
|
||||
INTOFF;
|
||||
hist = history_init();
|
||||
INTON;
|
||||
|
||||
if (hist != NULL)
|
||||
sethistsize(histsizeval());
|
||||
else
|
||||
out2str("sh: can't initialize history\n");
|
||||
}
|
||||
if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
|
||||
/*
|
||||
* turn editing on
|
||||
*/
|
||||
INTOFF;
|
||||
if (el_in == NULL)
|
||||
el_in = fdopen(0, "r");
|
||||
if (el_out == NULL)
|
||||
el_out = fdopen(2, "w");
|
||||
if (el_in == NULL || el_out == NULL)
|
||||
goto bad;
|
||||
el = el_init(arg0, el_in, el_out);
|
||||
if (el != NULL) {
|
||||
if (hist)
|
||||
el_set(el, EL_HIST, history, hist);
|
||||
el_set(el, EL_PROMPT, getprompt);
|
||||
} else {
|
||||
bad:
|
||||
out2str("sh: can't initialize editing\n");
|
||||
}
|
||||
INTON;
|
||||
} else if (!editing && el) {
|
||||
INTOFF;
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
INTON;
|
||||
}
|
||||
if (el) {
|
||||
if (Vflag)
|
||||
el_set(el, EL_EDITOR, "vi");
|
||||
else if (Eflag)
|
||||
el_set(el, EL_EDITOR, "emacs");
|
||||
}
|
||||
} else {
|
||||
INTOFF;
|
||||
if (el) { /* no editing if not interactive */
|
||||
el_end(el);
|
||||
el = NULL;
|
||||
}
|
||||
if (hist) {
|
||||
history_end(hist);
|
||||
hist = NULL;
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sethistsize(hs)
|
||||
const char *hs;
|
||||
{
|
||||
int histsize;
|
||||
|
||||
if (hist != NULL) {
|
||||
if (hs == NULL || *hs == '\0' ||
|
||||
(histsize = atoi(hs)) < 0)
|
||||
histsize = 100;
|
||||
history(hist, H_EVENT, histsize);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setterm(term)
|
||||
const char *term;
|
||||
{
|
||||
if (el != NULL && term != NULL)
|
||||
if (el_set(el, EL_TERMINAL, term) != 0) {
|
||||
outfmt(out2, "sh: Can't set terminal type %s\n", term);
|
||||
outfmt(out2, "sh: Using dumb terminal settings.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This command is provided since POSIX decided to standardize
|
||||
* the Korn shell fc command. Oh well...
|
||||
*/
|
||||
int
|
||||
histcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind, optopt, optreset;
|
||||
int ch;
|
||||
char *editor = NULL;
|
||||
const HistEvent *he;
|
||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
||||
int i;
|
||||
char *firststr, *laststr;
|
||||
int first, last, direction;
|
||||
char *pat = NULL, *repl; /* ksh "fc old=new" crap */
|
||||
static int active = 0;
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler;
|
||||
char editfile[MAXPATHLEN + 1];
|
||||
FILE *efp;
|
||||
#ifdef __GNUC__
|
||||
/* Avoid longjmp clobbering */
|
||||
(void) &editor;
|
||||
(void) &lflg;
|
||||
(void) &nflg;
|
||||
(void) &rflg;
|
||||
(void) &sflg;
|
||||
(void) &firststr;
|
||||
(void) &laststr;
|
||||
(void) &pat;
|
||||
(void) &repl;
|
||||
(void) &efp;
|
||||
(void) &argc;
|
||||
(void) &argv;
|
||||
#endif
|
||||
|
||||
if (hist == NULL)
|
||||
error("history not active");
|
||||
|
||||
if (argc == 1)
|
||||
error("missing history argument");
|
||||
|
||||
optreset = 1; optind = 1; /* initialize getopt */
|
||||
while (not_fcnumber(argv[optind]) &&
|
||||
(ch = getopt(argc, argv, ":e:lnrs")) != EOF)
|
||||
switch ((char)ch) {
|
||||
case 'e':
|
||||
editor = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
lflg = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflg = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflg = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflg = 1;
|
||||
break;
|
||||
case ':':
|
||||
error("option -%c expects argument", optopt);
|
||||
case '?':
|
||||
default:
|
||||
error("unknown option: -%c", optopt);
|
||||
}
|
||||
argc -= optind, argv += optind;
|
||||
|
||||
/*
|
||||
* If executing...
|
||||
*/
|
||||
if (lflg == 0 || editor || sflg) {
|
||||
lflg = 0; /* ignore */
|
||||
editfile[0] = '\0';
|
||||
/*
|
||||
* Catch interrupts to reset active counter and
|
||||
* cleanup temp files.
|
||||
*/
|
||||
if (setjmp(jmploc.loc)) {
|
||||
active = 0;
|
||||
if (*editfile)
|
||||
unlink(editfile);
|
||||
handler = savehandler;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
savehandler = handler;
|
||||
handler = &jmploc;
|
||||
if (++active > MAXHISTLOOPS) {
|
||||
active = 0;
|
||||
displayhist = 0;
|
||||
error("called recursively too many times");
|
||||
}
|
||||
/*
|
||||
* Set editor.
|
||||
*/
|
||||
if (sflg == 0) {
|
||||
if (editor == NULL &&
|
||||
(editor = bltinlookup("FCEDIT", 1)) == NULL &&
|
||||
(editor = bltinlookup("EDITOR", 1)) == NULL)
|
||||
editor = DEFEDITOR;
|
||||
if (editor[0] == '-' && editor[1] == '\0') {
|
||||
sflg = 1; /* no edit */
|
||||
editor = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If executing, parse [old=new] now
|
||||
*/
|
||||
if (lflg == 0 && argc > 0 &&
|
||||
((repl = strchr(argv[0], '=')) != NULL)) {
|
||||
pat = argv[0];
|
||||
*repl++ = '\0';
|
||||
argc--, argv++;
|
||||
}
|
||||
/*
|
||||
* determine [first] and [last]
|
||||
*/
|
||||
switch (argc) {
|
||||
case 0:
|
||||
firststr = lflg ? "-16" : "-1";
|
||||
laststr = "-1";
|
||||
break;
|
||||
case 1:
|
||||
firststr = argv[0];
|
||||
laststr = lflg ? "-1" : argv[0];
|
||||
break;
|
||||
case 2:
|
||||
firststr = argv[0];
|
||||
laststr = argv[1];
|
||||
break;
|
||||
default:
|
||||
error("too many args");
|
||||
}
|
||||
/*
|
||||
* Turn into event numbers.
|
||||
*/
|
||||
first = str_to_event(firststr, 0);
|
||||
last = str_to_event(laststr, 1);
|
||||
|
||||
if (rflg) {
|
||||
i = last;
|
||||
last = first;
|
||||
first = i;
|
||||
}
|
||||
/*
|
||||
* XXX - this should not depend on the event numbers
|
||||
* always increasing. Add sequence numbers or offset
|
||||
* to the history element in next (diskbased) release.
|
||||
*/
|
||||
direction = first < last ? H_PREV : H_NEXT;
|
||||
|
||||
/*
|
||||
* If editing, grab a temp file.
|
||||
*/
|
||||
if (editor) {
|
||||
int fd;
|
||||
INTOFF; /* easier */
|
||||
sprintf(editfile, "%s/_shXXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(editfile)) < 0)
|
||||
error("can't create temporary file %s", editfile);
|
||||
if ((efp = fdopen(fd, "w")) == NULL) {
|
||||
close(fd);
|
||||
error("can't allocate stdio buffer for temp");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through selected history events. If listing or executing,
|
||||
* do it now. Otherwise, put into temp file and call the editor
|
||||
* after.
|
||||
*
|
||||
* The history interface needs rethinking, as the following
|
||||
* convolutions will demonstrate.
|
||||
*/
|
||||
history(hist, H_FIRST);
|
||||
he = history(hist, H_NEXT_EVENT, first);
|
||||
for (;he != NULL; he = history(hist, direction)) {
|
||||
if (lflg) {
|
||||
if (!nflg)
|
||||
out1fmt("%5d ", he->num);
|
||||
out1str(he->str);
|
||||
} else {
|
||||
char *s = pat ?
|
||||
fc_replace(he->str, pat, repl) : (char *)he->str;
|
||||
|
||||
if (sflg) {
|
||||
if (displayhist) {
|
||||
out2str(s);
|
||||
}
|
||||
evalstring(s);
|
||||
if (displayhist && hist) {
|
||||
/*
|
||||
* XXX what about recursive and
|
||||
* relative histnums.
|
||||
*/
|
||||
history(hist, H_ENTER, s);
|
||||
}
|
||||
} else
|
||||
fputs(s, efp);
|
||||
}
|
||||
/*
|
||||
* At end? (if we were to loose last, we'd sure be
|
||||
* messed up).
|
||||
*/
|
||||
if (he->num == last)
|
||||
break;
|
||||
}
|
||||
if (editor) {
|
||||
char *editcmd;
|
||||
|
||||
fclose(efp);
|
||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||
sprintf(editcmd, "%s %s", editor, editfile);
|
||||
evalstring(editcmd); /* XXX - should use no JC command */
|
||||
INTON;
|
||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||
unlink(editfile);
|
||||
}
|
||||
|
||||
if (lflg == 0 && active > 0)
|
||||
--active;
|
||||
if (displayhist)
|
||||
displayhist = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC char *
|
||||
fc_replace(s, p, r)
|
||||
const char *s;
|
||||
char *p, *r;
|
||||
{
|
||||
char *dest;
|
||||
int plen = strlen(p);
|
||||
|
||||
STARTSTACKSTR(dest);
|
||||
while (*s) {
|
||||
if (*s == *p && strncmp(s, p, plen) == 0) {
|
||||
while (*r)
|
||||
STPUTC(*r++, dest);
|
||||
s += plen;
|
||||
*p = '\0'; /* so no more matches */
|
||||
} else
|
||||
STPUTC(*s++, dest);
|
||||
}
|
||||
STACKSTRNUL(dest);
|
||||
dest = grabstackstr(dest);
|
||||
|
||||
return (dest);
|
||||
}
|
||||
|
||||
int
|
||||
not_fcnumber(s)
|
||||
char *s;
|
||||
{
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
if (*s == '-')
|
||||
s++;
|
||||
return (!is_number(s));
|
||||
}
|
||||
|
||||
int
|
||||
str_to_event(str, last)
|
||||
char *str;
|
||||
int last;
|
||||
{
|
||||
const HistEvent *he;
|
||||
char *s = str;
|
||||
int relative = 0;
|
||||
int i;
|
||||
|
||||
he = history(hist, H_FIRST);
|
||||
switch (*s) {
|
||||
case '-':
|
||||
relative = 1;
|
||||
/*FALLTHROUGH*/
|
||||
case '+':
|
||||
s++;
|
||||
}
|
||||
if (is_number(s)) {
|
||||
i = atoi(s);
|
||||
if (relative) {
|
||||
while (he != NULL && i--) {
|
||||
he = history(hist, H_NEXT);
|
||||
}
|
||||
if (he == NULL)
|
||||
he = history(hist, H_LAST);
|
||||
} else {
|
||||
he = history(hist, H_NEXT_EVENT, i);
|
||||
if (he == NULL) {
|
||||
/*
|
||||
* the notion of first and last is
|
||||
* backwards to that of the history package
|
||||
*/
|
||||
he = history(hist, last ? H_FIRST : H_LAST);
|
||||
}
|
||||
}
|
||||
if (he == NULL)
|
||||
error("history number %s not found (internal error)",
|
||||
str);
|
||||
} else {
|
||||
/*
|
||||
* pattern
|
||||
*/
|
||||
he = history(hist, H_PREV_STR, str);
|
||||
if (he == NULL)
|
||||
error("history pattern not found: %s", str);
|
||||
}
|
||||
return (he->num);
|
||||
}
|
||||
#else
|
||||
int
|
||||
histcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
error("not compiled with history support");
|
||||
}
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
/* $NetBSD: init.h,v 1.8 1995/05/11 21:29:14 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
void init __P((void));
|
||||
void reset __P((void));
|
||||
void initshellproc __P((void));
|
@ -1,516 +0,0 @@
|
||||
/* $NetBSD: input.c,v 1.27 1997/07/04 21:02:03 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: input.c,v 1.27 1997/07/04 21:02:03 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* This file implements the input routines used by the parser.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "redir.h"
|
||||
#include "syntax.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "options.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "alias.h"
|
||||
#include "parser.h"
|
||||
#include "myhistedit.h"
|
||||
|
||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
||||
|
||||
MKINIT
|
||||
struct strpush {
|
||||
struct strpush *prev; /* preceding string on stack */
|
||||
char *prevstring;
|
||||
int prevnleft;
|
||||
int prevlleft;
|
||||
struct alias *ap; /* if push was associated with an alias */
|
||||
};
|
||||
|
||||
/*
|
||||
* The parsefile structure pointed to by the global variable parsefile
|
||||
* contains information about the current file being read.
|
||||
*/
|
||||
|
||||
MKINIT
|
||||
struct parsefile {
|
||||
struct parsefile *prev; /* preceding file on stack */
|
||||
int linno; /* current line */
|
||||
int fd; /* file descriptor (or -1 if string) */
|
||||
int nleft; /* number of chars left in this line */
|
||||
int lleft; /* number of chars left in this buffer */
|
||||
char *nextc; /* next char in buffer */
|
||||
char *buf; /* input buffer */
|
||||
struct strpush *strpush; /* for pushing strings at this level */
|
||||
struct strpush basestrpush; /* so pushing one is fast */
|
||||
};
|
||||
|
||||
|
||||
int plinno = 1; /* input line number */
|
||||
MKINIT int parsenleft; /* copy of parsefile->nleft */
|
||||
MKINIT int parselleft; /* copy of parsefile->lleft */
|
||||
char *parsenextc; /* copy of parsefile->nextc */
|
||||
MKINIT struct parsefile basepf; /* top level input file */
|
||||
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||
struct parsefile *parsefile = &basepf; /* current input file */
|
||||
int init_editline = 0; /* editline library initialized? */
|
||||
int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
EditLine *el; /* cookie for editline package */
|
||||
|
||||
STATIC void pushfile __P((void));
|
||||
static int preadfd __P((void));
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "input.h"
|
||||
INCLUDE "error.h"
|
||||
|
||||
INIT {
|
||||
extern char basebuf[];
|
||||
|
||||
basepf.nextc = basepf.buf = basebuf;
|
||||
}
|
||||
|
||||
RESET {
|
||||
if (exception != EXSHELLPROC)
|
||||
parselleft = parsenleft = 0; /* clear input buffer */
|
||||
popallfiles();
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
popallfiles();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Read a line from the script.
|
||||
*/
|
||||
|
||||
char *
|
||||
pfgets(line, len)
|
||||
char *line;
|
||||
int len;
|
||||
{
|
||||
char *p = line;
|
||||
int nleft = len;
|
||||
int c;
|
||||
|
||||
while (--nleft > 0) {
|
||||
c = pgetc_macro();
|
||||
if (c == PEOF) {
|
||||
if (p == line)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = '\0';
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a character from the script, returning PEOF on end of file.
|
||||
* Nul characters in the input are silently discarded.
|
||||
*/
|
||||
|
||||
int
|
||||
pgetc()
|
||||
{
|
||||
return pgetc_macro();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
preadfd()
|
||||
{
|
||||
int nr;
|
||||
parsenextc = parsefile->buf;
|
||||
|
||||
retry:
|
||||
#ifndef SMALL
|
||||
if (parsefile->fd == 0 && el) {
|
||||
const char *rl_cp;
|
||||
|
||||
rl_cp = el_gets(el, &nr);
|
||||
if (rl_cp == NULL)
|
||||
nr = 0;
|
||||
else {
|
||||
/* XXX - BUFSIZE should redesign so not necessary */
|
||||
(void) strcpy(parsenextc, rl_cp);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
|
||||
|
||||
|
||||
if (nr <= 0) {
|
||||
if (nr < 0) {
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
|
||||
int flags = fcntl(0, F_GETFL, 0);
|
||||
if (flags >= 0 && flags & O_NONBLOCK) {
|
||||
flags &=~ O_NONBLOCK;
|
||||
if (fcntl(0, F_SETFL, flags) >= 0) {
|
||||
out2str("sh: turning off NDELAY mode\n");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nr = -1;
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refill the input buffer and return the next input character:
|
||||
*
|
||||
* 1) If a string was pushed back on the input, pop it;
|
||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
||||
* from a string so we can't refill the buffer, return EOF.
|
||||
* 3) If the is more stuff in this buffer, use it else call read to fill it.
|
||||
* 4) Process input up to the next newline, deleting nul characters.
|
||||
*/
|
||||
|
||||
int
|
||||
preadbuffer()
|
||||
{
|
||||
char *p, *q;
|
||||
int more;
|
||||
int something;
|
||||
extern EditLine *el;
|
||||
char savec;
|
||||
|
||||
if (parsefile->strpush) {
|
||||
popstring();
|
||||
if (--parsenleft >= 0)
|
||||
return (*parsenextc++);
|
||||
}
|
||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||
return PEOF;
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
|
||||
again:
|
||||
if (parselleft <= 0) {
|
||||
if ((parselleft = preadfd()) == -1) {
|
||||
parselleft = parsenleft = EOF_NLEFT;
|
||||
return PEOF;
|
||||
}
|
||||
}
|
||||
|
||||
q = p = parsenextc;
|
||||
|
||||
/* delete nul characters */
|
||||
something = 0;
|
||||
for (more = 1; more;) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
p++; /* Skip nul */
|
||||
goto check;
|
||||
|
||||
case '\t':
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
parsenleft = q - parsenextc;
|
||||
more = 0; /* Stop processing here */
|
||||
break;
|
||||
|
||||
default:
|
||||
something = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
*q++ = *p++;
|
||||
check:
|
||||
if (--parselleft <= 0) {
|
||||
parsenleft = q - parsenextc - 1;
|
||||
if (parsenleft < 0)
|
||||
goto again;
|
||||
*q = '\0';
|
||||
more = 0;
|
||||
}
|
||||
}
|
||||
|
||||
savec = *q;
|
||||
*q = '\0';
|
||||
|
||||
#ifndef SMALL
|
||||
if (parsefile->fd == 0 && hist && something) {
|
||||
INTOFF;
|
||||
history(hist, whichprompt == 1 ? H_ENTER : H_ADD, parsenextc);
|
||||
INTON;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vflag) {
|
||||
out2str(parsenextc);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
*q = savec;
|
||||
|
||||
return *parsenextc++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the last call to pgetc. Only one character may be pushed back.
|
||||
* PEOF may be pushed back.
|
||||
*/
|
||||
|
||||
void
|
||||
pungetc() {
|
||||
parsenleft++;
|
||||
parsenextc--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a string back onto the input at this current parsefile level.
|
||||
* We handle aliases this way.
|
||||
*/
|
||||
void
|
||||
pushstring(s, len, ap)
|
||||
char *s;
|
||||
int len;
|
||||
void *ap;
|
||||
{
|
||||
struct strpush *sp;
|
||||
|
||||
INTOFF;
|
||||
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
||||
if (parsefile->strpush) {
|
||||
sp = ckmalloc(sizeof (struct strpush));
|
||||
sp->prev = parsefile->strpush;
|
||||
parsefile->strpush = sp;
|
||||
} else
|
||||
sp = parsefile->strpush = &(parsefile->basestrpush);
|
||||
sp->prevstring = parsenextc;
|
||||
sp->prevnleft = parsenleft;
|
||||
sp->prevlleft = parselleft;
|
||||
sp->ap = (struct alias *)ap;
|
||||
if (ap)
|
||||
((struct alias *)ap)->flag |= ALIASINUSE;
|
||||
parsenextc = s;
|
||||
parsenleft = len;
|
||||
INTON;
|
||||
}
|
||||
|
||||
void
|
||||
popstring()
|
||||
{
|
||||
struct strpush *sp = parsefile->strpush;
|
||||
|
||||
INTOFF;
|
||||
parsenextc = sp->prevstring;
|
||||
parsenleft = sp->prevnleft;
|
||||
parselleft = sp->prevlleft;
|
||||
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
||||
if (sp->ap)
|
||||
sp->ap->flag &= ~ALIASINUSE;
|
||||
parsefile->strpush = sp->prev;
|
||||
if (sp != &(parsefile->basestrpush))
|
||||
ckfree(sp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the input to take input from a file. If push is set, push the
|
||||
* old input onto the stack first.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfile(fname, push)
|
||||
char *fname;
|
||||
int push;
|
||||
{
|
||||
int fd;
|
||||
int fd2;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||
error("Can't open %s", fname);
|
||||
if (fd < 10) {
|
||||
fd2 = copyfd(fd, 10);
|
||||
close(fd);
|
||||
if (fd2 < 0)
|
||||
error("Out of file descriptors");
|
||||
fd = fd2;
|
||||
}
|
||||
setinputfd(fd, push);
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Like setinputfile, but takes an open file descriptor. Call this with
|
||||
* interrupts off.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputfd(fd, push)
|
||||
int fd, push;
|
||||
{
|
||||
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
if (push) {
|
||||
pushfile();
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
}
|
||||
if (parsefile->fd > 0)
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = fd;
|
||||
if (parsefile->buf == NULL)
|
||||
parsefile->buf = ckmalloc(BUFSIZ);
|
||||
parselleft = parsenleft = 0;
|
||||
plinno = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Like setinputfile, but takes input from a string.
|
||||
*/
|
||||
|
||||
void
|
||||
setinputstring(string, push)
|
||||
char *string;
|
||||
int push;
|
||||
{
|
||||
INTOFF;
|
||||
if (push)
|
||||
pushfile();
|
||||
parsenextc = string;
|
||||
parselleft = parsenleft = strlen(string);
|
||||
parsefile->buf = NULL;
|
||||
plinno = 1;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* To handle the "." command, a stack of input files is used. Pushfile
|
||||
* adds a new entry to the stack and popfile restores the previous level.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
pushfile() {
|
||||
struct parsefile *pf;
|
||||
|
||||
parsefile->nleft = parsenleft;
|
||||
parsefile->lleft = parselleft;
|
||||
parsefile->nextc = parsenextc;
|
||||
parsefile->linno = plinno;
|
||||
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
||||
pf->prev = parsefile;
|
||||
pf->fd = -1;
|
||||
pf->strpush = NULL;
|
||||
pf->basestrpush.prev = NULL;
|
||||
parsefile = pf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popfile() {
|
||||
struct parsefile *pf = parsefile;
|
||||
|
||||
INTOFF;
|
||||
if (pf->fd >= 0)
|
||||
close(pf->fd);
|
||||
if (pf->buf)
|
||||
ckfree(pf->buf);
|
||||
while (pf->strpush)
|
||||
popstring();
|
||||
parsefile = pf->prev;
|
||||
ckfree(pf);
|
||||
parsenleft = parsefile->nleft;
|
||||
parselleft = parsefile->lleft;
|
||||
parsenextc = parsefile->nextc;
|
||||
plinno = parsefile->linno;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return to top level.
|
||||
*/
|
||||
|
||||
void
|
||||
popallfiles() {
|
||||
while (parsefile != &basepf)
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Close the file(s) that the shell is reading commands from. Called
|
||||
* after a fork is done.
|
||||
*/
|
||||
|
||||
void
|
||||
closescript() {
|
||||
popallfiles();
|
||||
if (parsefile->fd > 0) {
|
||||
close(parsefile->fd);
|
||||
parsefile->fd = 0;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/* $NetBSD: input.h,v 1.9 1996/10/16 15:45:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||
|
||||
/*
|
||||
* The input line number. Input.c just defines this variable, and saves
|
||||
* and restores it when files are pushed and popped. The user of this
|
||||
* package must set its value.
|
||||
*/
|
||||
extern int plinno;
|
||||
extern int parsenleft; /* number of characters left in input buffer */
|
||||
extern char *parsenextc; /* next character in input buffer */
|
||||
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
|
||||
|
||||
char *pfgets __P((char *, int));
|
||||
int pgetc __P((void));
|
||||
int preadbuffer __P((void));
|
||||
void pungetc __P((void));
|
||||
void pushstring __P((char *, int, void *));
|
||||
void popstring __P((void));
|
||||
void setinputfile __P((char *, int));
|
||||
void setinputfd __P((int, int));
|
||||
void setinputstring __P((char *, int));
|
||||
void popfile __P((void));
|
||||
void popallfiles __P((void));
|
||||
void closescript __P((void));
|
||||
|
||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
File diff suppressed because it is too large
Load Diff
@ -1,97 +0,0 @@
|
||||
/* $NetBSD: jobs.h,v 1.8 1995/05/11 21:29:19 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||
#define FORK_FG 0
|
||||
#define FORK_BG 1
|
||||
#define FORK_NOJOB 2
|
||||
|
||||
|
||||
/*
|
||||
* A job structure contains information about a job. A job is either a
|
||||
* single process or a set of processes contained in a pipeline. In the
|
||||
* latter case, pidlist will be non-NULL, and will point to a -1 terminated
|
||||
* array of pids.
|
||||
*/
|
||||
|
||||
struct procstat {
|
||||
short pid; /* process id */
|
||||
short status; /* status flags (defined above) */
|
||||
char *cmd; /* text of command being run */
|
||||
};
|
||||
|
||||
|
||||
/* states */
|
||||
#define JOBSTOPPED 1 /* all procs are stopped */
|
||||
#define JOBDONE 2 /* all procs are completed */
|
||||
|
||||
|
||||
struct job {
|
||||
struct procstat ps0; /* status of process */
|
||||
struct procstat *ps; /* status or processes when more than one */
|
||||
short nprocs; /* number of processes */
|
||||
short pgrp; /* process group of this job */
|
||||
char state; /* true if job is finished */
|
||||
char used; /* true if this entry is in used */
|
||||
char changed; /* true if status has changed */
|
||||
#if JOBS
|
||||
char jobctl; /* job running under job control */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern short backgndpid; /* pid of last background process */
|
||||
extern int job_warning; /* user was warned about stopped jobs */
|
||||
|
||||
void setjobctl __P((int));
|
||||
int fgcmd __P((int, char **));
|
||||
int bgcmd __P((int, char **));
|
||||
int jobscmd __P((int, char **));
|
||||
void showjobs __P((int));
|
||||
int waitcmd __P((int, char **));
|
||||
int jobidcmd __P((int, char **));
|
||||
struct job *makejob __P((union node *, int));
|
||||
int forkshell __P((struct job *, union node *, int));
|
||||
int waitforjob __P((struct job *));
|
||||
int stoppedjobs __P((void));
|
||||
char *commandtext __P((union node *));
|
||||
|
||||
#if ! JOBS
|
||||
#define setjobctl(on) /* do nothing */
|
||||
#endif
|
@ -1,53 +0,0 @@
|
||||
/* $NetBSD: machdep.h,v 1.8 1995/05/11 21:29:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Most machines require the value returned from malloc to be aligned
|
||||
* in some way. The following macro will get this right on many machines.
|
||||
*/
|
||||
|
||||
#ifndef ALIGN
|
||||
union align {
|
||||
int i;
|
||||
char *cp;
|
||||
};
|
||||
|
||||
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
|
||||
#endif
|
@ -1,124 +0,0 @@
|
||||
/* $NetBSD: mail.c,v 1.11 1997/07/04 21:02:06 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mail.c,v 1.11 1997/07/04 21:02:06 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines to check for mail. (Perhaps make part of main.c?)
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "exec.h" /* defines padvance() */
|
||||
#include "var.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#define MAXMBOXES 10
|
||||
|
||||
|
||||
STATIC int nmboxes; /* number of mailboxes */
|
||||
STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Print appropriate message(s) if mail has arrived. If the argument is
|
||||
* nozero, then the value of MAIL has changed, so we just update the
|
||||
* values.
|
||||
*/
|
||||
|
||||
void
|
||||
chkmail(silent)
|
||||
int silent;
|
||||
{
|
||||
int i;
|
||||
char *mpath;
|
||||
char *p;
|
||||
char *q;
|
||||
struct stackmark smark;
|
||||
struct stat statb;
|
||||
|
||||
if (silent)
|
||||
nmboxes = 10;
|
||||
if (nmboxes == 0)
|
||||
return;
|
||||
setstackmark(&smark);
|
||||
mpath = mpathset()? mpathval() : mailval();
|
||||
for (i = 0 ; i < nmboxes ; i++) {
|
||||
p = padvance(&mpath, nullstr);
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (*p == '\0')
|
||||
continue;
|
||||
for (q = p ; *q ; q++);
|
||||
if (q[-1] != '/')
|
||||
abort();
|
||||
q[-1] = '\0'; /* delete trailing '/' */
|
||||
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_mtime = 0;
|
||||
if (statb.st_mtime > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_mtime;
|
||||
#else /* this is what it should do */
|
||||
if (stat(p, &statb) < 0)
|
||||
statb.st_size = 0;
|
||||
if (statb.st_size > mailtime[i] && ! silent) {
|
||||
out2str(pathopt? pathopt : "you have mail");
|
||||
out2c('\n');
|
||||
}
|
||||
mailtime[i] = statb.st_size;
|
||||
#endif
|
||||
}
|
||||
nmboxes = i;
|
||||
popstackmark(&smark);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/* $NetBSD: mail.h,v 1.8 1995/05/11 21:29:23 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
void chkmail __P((int));
|
@ -1,388 +0,0 @@
|
||||
/* $NetBSD: main.c,v 1.26 1997/07/04 21:02:07 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.26 1997/07/04 21:02:07 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "mail.h"
|
||||
#include "options.h"
|
||||
#include "output.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "expand.h"
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "trap.h"
|
||||
#include "var.h"
|
||||
#include "show.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "mystring.h"
|
||||
#include "exec.h"
|
||||
#include "cd.h"
|
||||
|
||||
#define PROFILE 0
|
||||
|
||||
int rootpid;
|
||||
int rootshell;
|
||||
STATIC union node *curcmd;
|
||||
STATIC union node *prevcmd;
|
||||
extern int errno;
|
||||
#if PROFILE
|
||||
short profile_buf[16384];
|
||||
extern int etext();
|
||||
#endif
|
||||
|
||||
STATIC void read_profile __P((char *));
|
||||
STATIC char *find_dot_file __P((char *));
|
||||
int main __P((int, char **));
|
||||
|
||||
/*
|
||||
* Main routine. We initialize things, parse the arguments, execute
|
||||
* profiles if we're a login shell, and then call cmdloop to execute
|
||||
* commands. The setjmp call sets up the location to jump to when an
|
||||
* exception occurs. When an exception occurs the variable "state"
|
||||
* is used to figure out how far we had gotten.
|
||||
*/
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct stackmark smark;
|
||||
volatile int state;
|
||||
char *shinit;
|
||||
|
||||
#if PROFILE
|
||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
||||
#endif
|
||||
state = 0;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
/*
|
||||
* When a shell procedure is executed, we raise the
|
||||
* exception EXSHELLPROC to clean up before executing
|
||||
* the shell procedure.
|
||||
*/
|
||||
switch (exception) {
|
||||
case EXSHELLPROC:
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
minusc = NULL;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case EXEXEC:
|
||||
exitstatus = exerrno;
|
||||
break;
|
||||
|
||||
case EXERROR:
|
||||
exitstatus = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (exception != EXSHELLPROC) {
|
||||
if (state == 0 || iflag == 0 || ! rootshell)
|
||||
exitshell(exitstatus);
|
||||
}
|
||||
reset();
|
||||
if (exception == EXINT
|
||||
#if ATTY
|
||||
&& (! attyset() || equal(termval(), "emacs"))
|
||||
#endif
|
||||
) {
|
||||
out2c('\n');
|
||||
flushout(&errout);
|
||||
}
|
||||
popstackmark(&smark);
|
||||
FORCEINTON; /* enable interrupts */
|
||||
if (state == 1)
|
||||
goto state1;
|
||||
else if (state == 2)
|
||||
goto state2;
|
||||
else if (state == 3)
|
||||
goto state3;
|
||||
else
|
||||
goto state4;
|
||||
}
|
||||
handler = &jmploc;
|
||||
#ifdef DEBUG
|
||||
opentrace();
|
||||
trputs("Shell args: "); trargs(argv);
|
||||
#endif
|
||||
rootpid = getpid();
|
||||
rootshell = 1;
|
||||
init();
|
||||
setstackmark(&smark);
|
||||
procargs(argc, argv);
|
||||
if (argv[0] && argv[0][0] == '-') {
|
||||
state = 1;
|
||||
read_profile("/etc/profile");
|
||||
state1:
|
||||
state = 2;
|
||||
read_profile(".profile");
|
||||
}
|
||||
state2:
|
||||
state = 3;
|
||||
if (getuid() == geteuid() && getgid() == getegid()) {
|
||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
state3:
|
||||
state = 4;
|
||||
if (minusc) {
|
||||
evalstring(minusc);
|
||||
}
|
||||
if (sflag || minusc == NULL) {
|
||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||
cmdloop(1);
|
||||
}
|
||||
#if PROFILE
|
||||
monitor(0);
|
||||
#endif
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read and execute commands. "Top" is nonzero for the top level command
|
||||
* loop; it turns on prompting if the shell is interactive.
|
||||
*/
|
||||
|
||||
void
|
||||
cmdloop(top)
|
||||
int top;
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
int inter;
|
||||
int numeof = 0;
|
||||
|
||||
TRACE(("cmdloop(%d) called\n", top));
|
||||
setstackmark(&smark);
|
||||
for (;;) {
|
||||
if (pendingsigs)
|
||||
dotrap();
|
||||
inter = 0;
|
||||
if (iflag && top) {
|
||||
inter++;
|
||||
showjobs(1);
|
||||
chkmail(0);
|
||||
flushout(&output);
|
||||
}
|
||||
n = parsecmd(inter);
|
||||
/* showtree(n); DEBUG */
|
||||
if (n == NEOF) {
|
||||
if (!top || numeof >= 50)
|
||||
break;
|
||||
if (!stoppedjobs()) {
|
||||
if (!Iflag)
|
||||
break;
|
||||
out2str("\nUse \"exit\" to leave shell.\n");
|
||||
}
|
||||
numeof++;
|
||||
} else if (n != NULL && nflag == 0) {
|
||||
job_warning = (job_warning == 2) ? 1 : 0;
|
||||
numeof = 0;
|
||||
evaltree(n, 0);
|
||||
}
|
||||
popstackmark(&smark);
|
||||
if (evalskip == SKIPFILE) {
|
||||
evalskip = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
popstackmark(&smark); /* unnecessary */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read /etc/profile or .profile. Return on error.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
read_profile(name)
|
||||
char *name;
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
INTON;
|
||||
if (fd < 0)
|
||||
return;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a file containing shell functions.
|
||||
*/
|
||||
|
||||
void
|
||||
readcmdfile(name)
|
||||
char *name;
|
||||
{
|
||||
int fd;
|
||||
|
||||
INTOFF;
|
||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||
setinputfd(fd, 1);
|
||||
else
|
||||
error("Can't open %s", name);
|
||||
INTON;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Take commands from a file. To be compatable we should do a path
|
||||
* search for the file, which is necessary to find sub-commands.
|
||||
*/
|
||||
|
||||
|
||||
STATIC char *
|
||||
find_dot_file(basename)
|
||||
char *basename;
|
||||
{
|
||||
static char localname[FILENAME_MAX+1];
|
||||
char *fullname;
|
||||
char *path = pathval();
|
||||
struct stat statb;
|
||||
|
||||
/* don't try this for absolute or relative paths */
|
||||
if( strchr(basename, '/'))
|
||||
return basename;
|
||||
|
||||
while ((fullname = padvance(&path, basename)) != NULL) {
|
||||
strcpy(localname, fullname);
|
||||
stunalloc(fullname);
|
||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
|
||||
return localname;
|
||||
}
|
||||
return basename;
|
||||
}
|
||||
|
||||
int
|
||||
dotcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct strlist *sp;
|
||||
exitstatus = 0;
|
||||
|
||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
|
||||
|
||||
if (argc >= 2) { /* That's what SVR2 does */
|
||||
char *fullname = find_dot_file(argv[1]);
|
||||
|
||||
setinputfile(fullname, 1);
|
||||
commandname = fullname;
|
||||
cmdloop(0);
|
||||
popfile();
|
||||
}
|
||||
return exitstatus;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
exitcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern int oexitstatus;
|
||||
|
||||
if (stoppedjobs())
|
||||
return 0;
|
||||
if (argc > 1)
|
||||
exitstatus = number(argv[1]);
|
||||
else
|
||||
exitstatus = oexitstatus;
|
||||
exitshell(exitstatus);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* Should never be called.
|
||||
*/
|
||||
|
||||
void
|
||||
exit(exitstatus) {
|
||||
_exit(exitstatus);
|
||||
}
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
/* $NetBSD: main.h,v 1.8 1995/05/11 21:29:27 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
extern int rootpid; /* pid of main shell */
|
||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
||||
|
||||
void readcmdfile __P((char *));
|
||||
void cmdloop __P((int));
|
||||
int dotcmd __P((int, char **));
|
||||
int exitcmd __P((int, char **));
|
@ -1,306 +0,0 @@
|
||||
/* $NetBSD: memalloc.c,v 1.20 1997/07/04 21:02:08 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: memalloc.c,v 1.20 1997/07/04 21:02:08 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Like malloc, but returns an error when out of space.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckmalloc(nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
pointer p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Same for realloc.
|
||||
*/
|
||||
|
||||
pointer
|
||||
ckrealloc(p, nbytes)
|
||||
pointer p;
|
||||
int nbytes;
|
||||
{
|
||||
|
||||
if ((p = realloc(p, nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make a copy of a string in safe storage.
|
||||
*/
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
scopy(s, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse trees for commands are allocated in lifo order, so we use a stack
|
||||
* to make this more efficient, and also to avoid all sorts of exception
|
||||
* handling code to handle interrupts in the middle of a parse.
|
||||
*
|
||||
* The size 504 was chosen because the Ultrix malloc handles that size
|
||||
* well.
|
||||
*/
|
||||
|
||||
#define MINSIZE 504 /* minimum size of a block */
|
||||
|
||||
|
||||
struct stack_block {
|
||||
struct stack_block *prev;
|
||||
char space[MINSIZE];
|
||||
};
|
||||
|
||||
struct stack_block stackbase;
|
||||
struct stack_block *stackp = &stackbase;
|
||||
char *stacknxt = stackbase.space;
|
||||
int stacknleft = MINSIZE;
|
||||
int sstrnleft;
|
||||
int herefd = -1;
|
||||
|
||||
|
||||
|
||||
pointer
|
||||
stalloc(nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *p;
|
||||
|
||||
nbytes = ALIGN(nbytes);
|
||||
if (nbytes > stacknleft) {
|
||||
int blocksize;
|
||||
struct stack_block *sp;
|
||||
|
||||
blocksize = nbytes;
|
||||
if (blocksize < MINSIZE)
|
||||
blocksize = MINSIZE;
|
||||
INTOFF;
|
||||
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
|
||||
sp->prev = stackp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = blocksize;
|
||||
stackp = sp;
|
||||
INTON;
|
||||
}
|
||||
p = stacknxt;
|
||||
stacknxt += nbytes;
|
||||
stacknleft -= nbytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
stunalloc(p)
|
||||
pointer p;
|
||||
{
|
||||
if (p == NULL) { /*DEBUG */
|
||||
write(2, "stunalloc\n", 10);
|
||||
abort();
|
||||
}
|
||||
stacknleft += stacknxt - (char *)p;
|
||||
stacknxt = p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
setstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
mark->stackp = stackp;
|
||||
mark->stacknxt = stacknxt;
|
||||
mark->stacknleft = stacknleft;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
popstackmark(mark)
|
||||
struct stackmark *mark;
|
||||
{
|
||||
struct stack_block *sp;
|
||||
|
||||
INTOFF;
|
||||
while (stackp != mark->stackp) {
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
ckfree(sp);
|
||||
}
|
||||
stacknxt = mark->stacknxt;
|
||||
stacknleft = mark->stacknleft;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When the parser reads in a string, it wants to stick the string on the
|
||||
* stack and only adjust the stack pointer when it knows how big the
|
||||
* string is. Stackblock (defined in stack.h) returns a pointer to a block
|
||||
* of space on top of the stack and stackblocklen returns the length of
|
||||
* this block. Growstackblock will grow this space by at least one byte,
|
||||
* possibly moving it (like realloc). Grabstackblock actually allocates the
|
||||
* part of the block that has been used.
|
||||
*/
|
||||
|
||||
void
|
||||
growstackblock() {
|
||||
char *p;
|
||||
int newlen = ALIGN(stacknleft * 2 + 100);
|
||||
char *oldspace = stacknxt;
|
||||
int oldlen = stacknleft;
|
||||
struct stack_block *sp;
|
||||
|
||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
||||
INTOFF;
|
||||
sp = stackp;
|
||||
stackp = sp->prev;
|
||||
sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
|
||||
sp->prev = stackp;
|
||||
stackp = sp;
|
||||
stacknxt = sp->space;
|
||||
stacknleft = newlen;
|
||||
INTON;
|
||||
} else {
|
||||
p = stalloc(newlen);
|
||||
memcpy(p, oldspace, oldlen);
|
||||
stacknxt = p; /* free the space */
|
||||
stacknleft += newlen; /* we just allocated */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
grabstackblock(len)
|
||||
int len;
|
||||
{
|
||||
len = ALIGN(len);
|
||||
stacknxt += len;
|
||||
stacknleft -= len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following routines are somewhat easier to use that the above.
|
||||
* The user declares a variable of type STACKSTR, which may be declared
|
||||
* to be a register. The macro STARTSTACKSTR initializes things. Then
|
||||
* the user uses the macro STPUTC to add characters to the string. In
|
||||
* effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
|
||||
* grown as necessary. When the user is done, she can just leave the
|
||||
* string there and refer to it using stackblock(). Or she can allocate
|
||||
* the space for it using grabstackstr(). If it is necessary to allow
|
||||
* someone else to use the stack temporarily and then continue to grow
|
||||
* the string, the user should use grabstack to allocate the space, and
|
||||
* then call ungrabstr(p) to return to the previous mode of operation.
|
||||
*
|
||||
* USTPUTC is like STPUTC except that it doesn't check for overflow.
|
||||
* CHECKSTACKSPACE can be called before USTPUTC to ensure that there
|
||||
* is space for at least one character.
|
||||
*/
|
||||
|
||||
|
||||
char *
|
||||
growstackstr() {
|
||||
int len = stackblocksize();
|
||||
if (herefd >= 0 && len >= 1024) {
|
||||
xwrite(herefd, stackblock(), len);
|
||||
sstrnleft = len - 1;
|
||||
return stackblock();
|
||||
}
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len - 1;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called from CHECKSTRSPACE.
|
||||
*/
|
||||
|
||||
char *
|
||||
makestrspace() {
|
||||
int len = stackblocksize() - sstrnleft;
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ungrabstackstr(s, p)
|
||||
char *s;
|
||||
char *p;
|
||||
{
|
||||
stacknleft += stacknxt - s;
|
||||
stacknxt = s;
|
||||
sstrnleft = stacknleft - (p - s);
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/* $NetBSD: memalloc.h,v 1.10 1995/05/11 21:29:31 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct stackmark {
|
||||
struct stack_block *stackp;
|
||||
char *stacknxt;
|
||||
int stacknleft;
|
||||
};
|
||||
|
||||
|
||||
extern char *stacknxt;
|
||||
extern int stacknleft;
|
||||
extern int sstrnleft;
|
||||
extern int herefd;
|
||||
|
||||
pointer ckmalloc __P((int));
|
||||
pointer ckrealloc __P((pointer, int));
|
||||
char *savestr __P((char *));
|
||||
pointer stalloc __P((int));
|
||||
void stunalloc __P((pointer));
|
||||
void setstackmark __P((struct stackmark *));
|
||||
void popstackmark __P((struct stackmark *));
|
||||
void growstackblock __P((void));
|
||||
void grabstackblock __P((int));
|
||||
char *growstackstr __P((void));
|
||||
char *makestrspace __P((void));
|
||||
void ungrabstackstr __P((char *, char *));
|
||||
|
||||
|
||||
|
||||
#define stackblock() stacknxt
|
||||
#define stackblocksize() stacknleft
|
||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
||||
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
||||
#define STTOPC(p) p[-1]
|
||||
#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
|
||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||
|
||||
#define ckfree(p) free((pointer)(p))
|
@ -1,402 +0,0 @@
|
||||
/* $NetBSD: miscbltin.c,v 1.19 1997/07/04 21:02:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: miscbltin.c,v 1.19 1997/07/04 21:02:09 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Miscelaneous builtins.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "miscbltin.h"
|
||||
#include "mystring.h"
|
||||
|
||||
#undef eflag
|
||||
|
||||
extern char **argptr; /* argument list for builtin command */
|
||||
|
||||
|
||||
/*
|
||||
* The read builtin. The -e option causes backslashes to escape the
|
||||
* following character.
|
||||
*
|
||||
* This uses unbuffered input, which may be avoidable in some cases.
|
||||
*/
|
||||
|
||||
int
|
||||
readcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **ap;
|
||||
int backslash;
|
||||
char c;
|
||||
int eflag;
|
||||
char *prompt;
|
||||
char *ifs;
|
||||
char *p;
|
||||
int startword;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
eflag = 0;
|
||||
prompt = NULL;
|
||||
while ((i = nextopt("ep:")) != '\0') {
|
||||
if (i == 'p')
|
||||
prompt = optarg;
|
||||
else
|
||||
eflag = 1;
|
||||
}
|
||||
if (prompt && isatty(0)) {
|
||||
out2str(prompt);
|
||||
flushall();
|
||||
}
|
||||
if (*(ap = argptr) == NULL)
|
||||
error("arg count");
|
||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||
ifs = nullstr;
|
||||
status = 0;
|
||||
startword = 1;
|
||||
backslash = 0;
|
||||
STARTSTACKSTR(p);
|
||||
for (;;) {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
if (c == '\0')
|
||||
continue;
|
||||
if (backslash) {
|
||||
backslash = 0;
|
||||
if (c != '\n')
|
||||
STPUTC(c, p);
|
||||
continue;
|
||||
}
|
||||
if (eflag && c == '\\') {
|
||||
backslash++;
|
||||
continue;
|
||||
}
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (startword && *ifs == ' ' && strchr(ifs, c)) {
|
||||
continue;
|
||||
}
|
||||
startword = 0;
|
||||
if (backslash && c == '\\') {
|
||||
if (read(0, &c, 1) != 1) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
STPUTC(c, p);
|
||||
} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
|
||||
STACKSTRNUL(p);
|
||||
setvar(*ap, stackblock(), 0);
|
||||
ap++;
|
||||
startword = 1;
|
||||
STARTSTACKSTR(p);
|
||||
} else {
|
||||
STPUTC(c, p);
|
||||
}
|
||||
}
|
||||
STACKSTRNUL(p);
|
||||
setvar(*ap, stackblock(), 0);
|
||||
while (*++ap != NULL)
|
||||
setvar(*ap, nullstr, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
umaskcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *ap;
|
||||
int mask;
|
||||
int i;
|
||||
int symbolic_mode = 0;
|
||||
|
||||
while ((i = nextopt("S")) != '\0') {
|
||||
symbolic_mode = 1;
|
||||
}
|
||||
|
||||
INTOFF;
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
INTON;
|
||||
|
||||
if ((ap = *argptr) == NULL) {
|
||||
if (symbolic_mode) {
|
||||
char u[4], g[4], o[4];
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRUSR) == 0)
|
||||
u[i++] = 'r';
|
||||
if ((mask & S_IWUSR) == 0)
|
||||
u[i++] = 'w';
|
||||
if ((mask & S_IXUSR) == 0)
|
||||
u[i++] = 'x';
|
||||
u[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IRGRP) == 0)
|
||||
g[i++] = 'r';
|
||||
if ((mask & S_IWGRP) == 0)
|
||||
g[i++] = 'w';
|
||||
if ((mask & S_IXGRP) == 0)
|
||||
g[i++] = 'x';
|
||||
g[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if ((mask & S_IROTH) == 0)
|
||||
o[i++] = 'r';
|
||||
if ((mask & S_IWOTH) == 0)
|
||||
o[i++] = 'w';
|
||||
if ((mask & S_IXOTH) == 0)
|
||||
o[i++] = 'x';
|
||||
o[i] = '\0';
|
||||
|
||||
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
|
||||
} else {
|
||||
out1fmt("%.4o\n", mask);
|
||||
}
|
||||
} else {
|
||||
if (isdigit(*ap)) {
|
||||
mask = 0;
|
||||
do {
|
||||
if (*ap >= '8' || *ap < '0')
|
||||
error("Illegal number: %s", argv[1]);
|
||||
mask = (mask << 3) + (*ap - '0');
|
||||
} while (*++ap != '\0');
|
||||
umask(mask);
|
||||
} else {
|
||||
void *set;
|
||||
if ((set = setmode (ap)) == 0)
|
||||
error("Illegal number: %s", ap);
|
||||
|
||||
mask = getmode (set, ~mask & 0777);
|
||||
umask(~mask & 0777);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ulimit builtin
|
||||
*
|
||||
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
|
||||
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
|
||||
* ash by J.T. Conklin.
|
||||
*
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
struct limits {
|
||||
const char *name;
|
||||
int cmd;
|
||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||
char option;
|
||||
};
|
||||
|
||||
static const struct limits limits[] = {
|
||||
#ifdef RLIMIT_CPU
|
||||
{ "time(seconds)", RLIMIT_CPU, 1, 't' },
|
||||
#endif
|
||||
#ifdef RLIMIT_FSIZE
|
||||
{ "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
|
||||
#endif
|
||||
#ifdef RLIMIT_RSS
|
||||
{ "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK
|
||||
{ "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC
|
||||
{ "process(processes)", RLIMIT_NPROC, 1, 'p' },
|
||||
#endif
|
||||
#ifdef RLIMIT_NOFILE
|
||||
{ "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
|
||||
#endif
|
||||
#ifdef RLIMIT_VMEM
|
||||
{ "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
|
||||
#endif
|
||||
#ifdef RLIMIT_SWAP
|
||||
{ "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
|
||||
#endif
|
||||
{ (char *) 0, 0, 0, '\0' }
|
||||
};
|
||||
|
||||
int
|
||||
ulimitcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
rlim_t val = 0;
|
||||
enum { SOFT = 0x1, HARD = 0x2 }
|
||||
how = SOFT | HARD;
|
||||
const struct limits *l;
|
||||
int set, all = 0;
|
||||
int optc, what;
|
||||
struct rlimit limit;
|
||||
|
||||
what = 'f';
|
||||
while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
|
||||
switch (optc) {
|
||||
case 'H':
|
||||
how = HARD;
|
||||
break;
|
||||
case 'S':
|
||||
how = SOFT;
|
||||
break;
|
||||
case 'a':
|
||||
all = 1;
|
||||
break;
|
||||
default:
|
||||
what = optc;
|
||||
}
|
||||
|
||||
for (l = limits; l->name && l->option != what; l++)
|
||||
;
|
||||
if (!l->name)
|
||||
error("ulimit: internal error (%c)\n", what);
|
||||
|
||||
set = *argptr ? 1 : 0;
|
||||
if (set) {
|
||||
char *p = *argptr;
|
||||
|
||||
if (all || argptr[1])
|
||||
error("ulimit: too many arguments\n");
|
||||
if (strcmp(p, "unlimited") == 0)
|
||||
val = RLIM_INFINITY;
|
||||
else {
|
||||
val = (rlim_t) 0;
|
||||
|
||||
while ((c = *p++) >= '0' && c <= '9')
|
||||
{
|
||||
val = (val * 10) + (long)(c - '0');
|
||||
if (val < (rlim_t) 0)
|
||||
break;
|
||||
}
|
||||
if (c)
|
||||
error("ulimit: bad number\n");
|
||||
val *= l->factor;
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
for (l = limits; l->name; l++) {
|
||||
getrlimit(l->cmd, &limit);
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
out1fmt("%-20s ", l->name);
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
#ifdef BSD4_4
|
||||
out1fmt("%qd\n", (quad_t) val);
|
||||
#else
|
||||
out1fmt("%ld\n", (long) val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
getrlimit(l->cmd, &limit);
|
||||
if (set) {
|
||||
if (how & SOFT)
|
||||
limit.rlim_cur = val;
|
||||
if (how & HARD)
|
||||
limit.rlim_max = val;
|
||||
if (setrlimit(l->cmd, &limit) < 0)
|
||||
error("ulimit: bad limit\n");
|
||||
} else {
|
||||
if (how & SOFT)
|
||||
val = limit.rlim_cur;
|
||||
else if (how & HARD)
|
||||
val = limit.rlim_max;
|
||||
|
||||
if (val == RLIM_INFINITY)
|
||||
out1fmt("unlimited\n");
|
||||
else
|
||||
{
|
||||
val /= l->factor;
|
||||
#ifdef BSD4_4
|
||||
out1fmt("%qd\n", (quad_t) val);
|
||||
#else
|
||||
out1fmt("%ld\n", (long) val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/* $NetBSD: miscbltin.h,v 1.1 1997/07/04 21:02:10 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
int readcmd __P((int, char **));
|
||||
int umaskcmd __P((int, char **));
|
||||
int ulimitcmd __P((int, char **));
|
@ -1,94 +0,0 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: mkbuiltins,v 1.13 1997/07/04 21:02:10 christos Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||
|
||||
temp=/tmp/ka$$
|
||||
havejobs=0
|
||||
if grep '^#define JOBS[ ]*1' shell.h > /dev/null
|
||||
then havejobs=1
|
||||
fi
|
||||
havehist=1
|
||||
if [ "X$1" = "X-h" ]; then
|
||||
havehist=0
|
||||
shift
|
||||
fi
|
||||
objdir=$1
|
||||
exec > ${objdir}/builtins.c
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
!
|
||||
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
|
||||
print $0}' builtins.def | sed 's/-j//' > $temp
|
||||
awk '{ printf "int %s __P((int, char **));\n", $1}' $temp
|
||||
echo '
|
||||
int (*const builtinfunc[]) __P((int, char **)) = {'
|
||||
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
|
||||
echo '};
|
||||
|
||||
const struct builtincmd builtincmd[] = {'
|
||||
awk '{ for (i = 2 ; i <= NF ; i++) {
|
||||
printf "\t{ \"%s\", %d },\n", $i, NR-1
|
||||
}}' $temp
|
||||
echo ' { NULL, 0 }
|
||||
};'
|
||||
|
||||
exec > ${objdir}/builtins.h
|
||||
cat <<\!
|
||||
/*
|
||||
* This file was generated by the mkbuiltins program.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
!
|
||||
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
|
||||
awk '{ printf "#define %s %d\n", $1, NR-1}'
|
||||
echo '
|
||||
struct builtincmd {
|
||||
char *name;
|
||||
int code;
|
||||
};
|
||||
|
||||
extern int (*const builtinfunc[]) __P((int, char **));
|
||||
extern const struct builtincmd builtincmd[];'
|
||||
rm -f $temp
|
@ -1,523 +0,0 @@
|
||||
/* $NetBSD: mkinit.c,v 1.17 1997/07/04 21:02:11 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mkinit.c,v 1.17 1997/07/04 21:02:11 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This program scans all the source files for code to handle various
|
||||
* special events and combines this code into one file. This (allegedly)
|
||||
* improves the structure of the program since there is no need for
|
||||
* anyone outside of a module to know that that module performs special
|
||||
* operations on particular events.
|
||||
*
|
||||
* Usage: mkinit sourcefile...
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/*
|
||||
* OUTFILE is the name of the output file. Output is initially written
|
||||
* to the file OUTTEMP, which is then moved to OUTFILE.
|
||||
*/
|
||||
|
||||
#define OUTFILE "init.c"
|
||||
#define OUTTEMP "init.c.new"
|
||||
|
||||
|
||||
/*
|
||||
* A text structure is basicly just a string that grows as more characters
|
||||
* are added onto the end of it. It is implemented as a linked list of
|
||||
* blocks of characters. The routines addstr and addchar append a string
|
||||
* or a single character, respectively, to a text structure. Writetext
|
||||
* writes the contents of a text structure to a file.
|
||||
*/
|
||||
|
||||
#define BLOCKSIZE 512
|
||||
|
||||
struct text {
|
||||
char *nextc;
|
||||
int nleft;
|
||||
struct block *start;
|
||||
struct block *last;
|
||||
};
|
||||
|
||||
struct block {
|
||||
struct block *next;
|
||||
char text[BLOCKSIZE];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* There is one event structure for each event that mkinit handles.
|
||||
*/
|
||||
|
||||
struct event {
|
||||
char *name; /* name of event (e.g. INIT) */
|
||||
char *routine; /* name of routine called on event */
|
||||
char *comment; /* comment describing routine */
|
||||
struct text code; /* code for handling event */
|
||||
};
|
||||
|
||||
|
||||
char writer[] = "\
|
||||
/*\n\
|
||||
* This file was generated by the mkinit program.\n\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
char init[] = "\
|
||||
/*\n\
|
||||
* Initialization code.\n\
|
||||
*/\n";
|
||||
|
||||
char reset[] = "\
|
||||
/*\n\
|
||||
* This routine is called when an error or an interrupt occurs in an\n\
|
||||
* interactive shell and control is returned to the main command loop.\n\
|
||||
*/\n";
|
||||
|
||||
char shellproc[] = "\
|
||||
/*\n\
|
||||
* This routine is called to initialize the shell to run a shell procedure.\n\
|
||||
*/\n";
|
||||
|
||||
|
||||
struct event event[] = {
|
||||
{"INIT", "init", init},
|
||||
{"RESET", "reset", reset},
|
||||
{"SHELLPROC", "initshellproc", shellproc},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
char *curfile; /* current file */
|
||||
int linno; /* current line */
|
||||
char *header_files[200]; /* list of header files */
|
||||
struct text defines; /* #define statements */
|
||||
struct text decls; /* declarations */
|
||||
int amiddecls; /* for formatting */
|
||||
|
||||
|
||||
void readfile __P((char *));
|
||||
int match __P((char *, char *));
|
||||
int gooddefine __P((char *));
|
||||
void doevent __P((struct event *, FILE *, char *));
|
||||
void doinclude __P((char *));
|
||||
void dodecl __P((char *, FILE *));
|
||||
void output __P((void));
|
||||
void addstr __P((char *, struct text *));
|
||||
void addchar __P((int, struct text *));
|
||||
void writetext __P((struct text *, FILE *));
|
||||
FILE *ckfopen __P((char *, char *));
|
||||
void *ckmalloc __P((int));
|
||||
char *savestr __P((char *));
|
||||
void error __P((char *));
|
||||
int main __P((int, char **));
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **ap;
|
||||
|
||||
header_files[0] = "\"shell.h\"";
|
||||
header_files[1] = "\"mystring.h\"";
|
||||
header_files[2] = "\"init.h\"";
|
||||
for (ap = argv + 1 ; *ap ; ap++)
|
||||
readfile(*ap);
|
||||
output();
|
||||
rename(OUTTEMP, OUTFILE);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse an input file.
|
||||
*/
|
||||
|
||||
void
|
||||
readfile(fname)
|
||||
char *fname;
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1024];
|
||||
struct event *ep;
|
||||
|
||||
fp = ckfopen(fname, "r");
|
||||
curfile = fname;
|
||||
linno = 0;
|
||||
amiddecls = 0;
|
||||
while (fgets(line, sizeof line, fp) != NULL) {
|
||||
linno++;
|
||||
for (ep = event ; ep->name ; ep++) {
|
||||
if (line[0] == ep->name[0] && match(ep->name, line)) {
|
||||
doevent(ep, fp, fname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (line[0] == 'I' && match("INCLUDE", line))
|
||||
doinclude(line);
|
||||
if (line[0] == 'M' && match("MKINIT", line))
|
||||
dodecl(line, fp);
|
||||
if (line[0] == '#' && gooddefine(line))
|
||||
addstr(line, &defines);
|
||||
if (line[0] == '#' && gooddefine(line)) {
|
||||
char *cp;
|
||||
char line2[1024];
|
||||
static const char undef[] = "#undef ";
|
||||
|
||||
strcpy(line2, line);
|
||||
memcpy(line2, undef, sizeof(undef) - 1);
|
||||
cp = line2 + sizeof(undef) - 1;
|
||||
while(*cp && (*cp == ' ' || *cp == '\t'))
|
||||
cp++;
|
||||
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
*cp++ = '\n'; *cp = '\0';
|
||||
addstr(line2, &defines);
|
||||
addstr(line, &defines);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
match(name, line)
|
||||
char *name;
|
||||
char *line;
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = name, q = line;
|
||||
while (*p) {
|
||||
if (*p++ != *q++)
|
||||
return 0;
|
||||
}
|
||||
if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
gooddefine(line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (! match("#define", line))
|
||||
return 0; /* not a define */
|
||||
p = line + 7;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
while (*p != ' ' && *p != '\t') {
|
||||
if (*p == '(')
|
||||
return 0; /* macro definition */
|
||||
p++;
|
||||
}
|
||||
while (*p != '\n' && *p != '\0')
|
||||
p++;
|
||||
if (p[-1] == '\\')
|
||||
return 0; /* multi-line definition */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
doevent(ep, fp, fname)
|
||||
struct event *ep;
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
char line[1024];
|
||||
int indent;
|
||||
char *p;
|
||||
|
||||
sprintf(line, "\n /* from %s: */\n", fname);
|
||||
addstr(line, &ep->code);
|
||||
addstr(" {\n", &ep->code);
|
||||
for (;;) {
|
||||
linno++;
|
||||
if (fgets(line, sizeof line, fp) == NULL)
|
||||
error("Unexpected EOF");
|
||||
if (equal(line, "}\n"))
|
||||
break;
|
||||
indent = 6;
|
||||
for (p = line ; *p == '\t' ; p++)
|
||||
indent += 8;
|
||||
for ( ; *p == ' ' ; p++)
|
||||
indent++;
|
||||
if (*p == '\n' || *p == '#')
|
||||
indent = 0;
|
||||
while (indent >= 8) {
|
||||
addchar('\t', &ep->code);
|
||||
indent -= 8;
|
||||
}
|
||||
while (indent > 0) {
|
||||
addchar(' ', &ep->code);
|
||||
indent--;
|
||||
}
|
||||
addstr(p, &ep->code);
|
||||
}
|
||||
addstr(" }\n", &ep->code);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
doinclude(line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
char *name;
|
||||
char **pp;
|
||||
|
||||
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
|
||||
if (*p == '\0')
|
||||
error("Expecting '\"' or '<'");
|
||||
name = p;
|
||||
while (*p != ' ' && *p != '\t' && *p != '\n')
|
||||
p++;
|
||||
if (p[-1] != '"' && p[-1] != '>')
|
||||
error("Missing terminator");
|
||||
*p = '\0';
|
||||
|
||||
/* name now contains the name of the include file */
|
||||
for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
|
||||
if (*pp == NULL)
|
||||
*pp = savestr(name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dodecl(line1, fp)
|
||||
char *line1;
|
||||
FILE *fp;
|
||||
{
|
||||
char line[1024];
|
||||
char *p, *q;
|
||||
|
||||
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
|
||||
addchar('\n', &decls);
|
||||
do {
|
||||
linno++;
|
||||
if (fgets(line, sizeof line, fp) == NULL)
|
||||
error("Unterminated structure declaration");
|
||||
addstr(line, &decls);
|
||||
} while (line[0] != '}');
|
||||
amiddecls = 0;
|
||||
} else {
|
||||
if (! amiddecls)
|
||||
addchar('\n', &decls);
|
||||
q = NULL;
|
||||
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
|
||||
continue;
|
||||
if (*p == '=') { /* eliminate initialization */
|
||||
for (q = p ; *q && *q != ';' ; q++);
|
||||
if (*q == '\0')
|
||||
q = NULL;
|
||||
else {
|
||||
while (p[-1] == ' ')
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
addstr("extern", &decls);
|
||||
addstr(line1 + 6, &decls);
|
||||
if (q != NULL)
|
||||
addstr(q, &decls);
|
||||
amiddecls = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Write the output to the file OUTTEMP.
|
||||
*/
|
||||
|
||||
void
|
||||
output() {
|
||||
FILE *fp;
|
||||
char **pp;
|
||||
struct event *ep;
|
||||
|
||||
fp = ckfopen(OUTTEMP, "w");
|
||||
fputs(writer, fp);
|
||||
for (pp = header_files ; *pp ; pp++)
|
||||
fprintf(fp, "#include %s\n", *pp);
|
||||
fputs("\n\n\n", fp);
|
||||
writetext(&defines, fp);
|
||||
fputs("\n\n", fp);
|
||||
writetext(&decls, fp);
|
||||
for (ep = event ; ep->name ; ep++) {
|
||||
fputs("\n\n\n", fp);
|
||||
fputs(ep->comment, fp);
|
||||
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
|
||||
writetext(&ep->code, fp);
|
||||
fprintf(fp, "}\n");
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A text structure is simply a block of text that is kept in memory.
|
||||
* Addstr appends a string to the text struct, and addchar appends a single
|
||||
* character.
|
||||
*/
|
||||
|
||||
void
|
||||
addstr(s, text)
|
||||
char *s;
|
||||
struct text *text;
|
||||
{
|
||||
while (*s) {
|
||||
if (--text->nleft < 0)
|
||||
addchar(*s++, text);
|
||||
else
|
||||
*text->nextc++ = *s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
addchar(c, text)
|
||||
int c;
|
||||
struct text *text;
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (--text->nleft < 0) {
|
||||
bp = ckmalloc(sizeof *bp);
|
||||
if (text->start == NULL)
|
||||
text->start = bp;
|
||||
else
|
||||
text->last->next = bp;
|
||||
text->last = bp;
|
||||
text->nextc = bp->text;
|
||||
text->nleft = BLOCKSIZE - 1;
|
||||
}
|
||||
*text->nextc++ = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the contents of a text structure to a file.
|
||||
*/
|
||||
void
|
||||
writetext(text, fp)
|
||||
struct text *text;
|
||||
FILE *fp;
|
||||
{
|
||||
struct block *bp;
|
||||
|
||||
if (text->start != NULL) {
|
||||
for (bp = text->start ; bp != text->last ; bp = bp->next)
|
||||
fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
|
||||
fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
ckfopen(file, mode)
|
||||
char *file;
|
||||
char *mode;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(file, mode)) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", file);
|
||||
exit(2);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
void *
|
||||
ckmalloc(nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(nbytes)) == NULL)
|
||||
error("Out of space");
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
char *s;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = ckmalloc(strlen(s) + 1);
|
||||
strcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
error(msg)
|
||||
char *msg;
|
||||
{
|
||||
if (curfile != NULL)
|
||||
fprintf(stderr, "%s:%d: ", curfile, linno);
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(2);
|
||||
}
|
@ -1,482 +0,0 @@
|
||||
/* $NetBSD: mknodes.c,v 1.15 1997/07/04 21:02:12 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mknodes.c,v 1.15 1997/07/04 21:02:12 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This program reads the nodetypes file and nodes.c.pat file. It generates
|
||||
* the files nodes.h and nodes.c.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define MAXTYPES 50 /* max number of node types */
|
||||
#define MAXFIELDS 20 /* max fields in a structure */
|
||||
#define BUFLEN 100 /* size of character buffers */
|
||||
|
||||
/* field types */
|
||||
#define T_NODE 1 /* union node *field */
|
||||
#define T_NODELIST 2 /* struct nodelist *field */
|
||||
#define T_STRING 3
|
||||
#define T_INT 4 /* int field */
|
||||
#define T_OTHER 5 /* other */
|
||||
#define T_TEMP 6 /* don't copy this field */
|
||||
|
||||
|
||||
struct field { /* a structure field */
|
||||
char *name; /* name of field */
|
||||
int type; /* type of field */
|
||||
char *decl; /* declaration of field */
|
||||
};
|
||||
|
||||
|
||||
struct str { /* struct representing a node structure */
|
||||
char *tag; /* structure tag */
|
||||
int nfields; /* number of fields in the structure */
|
||||
struct field field[MAXFIELDS]; /* the fields of the structure */
|
||||
int done; /* set if fully parsed */
|
||||
};
|
||||
|
||||
|
||||
static int ntypes; /* number of node types */
|
||||
static char *nodename[MAXTYPES]; /* names of the nodes */
|
||||
static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||
static int nstr; /* number of structures */
|
||||
static struct str str[MAXTYPES]; /* the structures */
|
||||
static struct str *curstr; /* current structure */
|
||||
static FILE *infp = stdin;
|
||||
static char line[1024];
|
||||
static int linno;
|
||||
static char *linep;
|
||||
|
||||
static void parsenode __P((void));
|
||||
static void parsefield __P((void));
|
||||
static void output __P((char *));
|
||||
static void outsizes __P((FILE *));
|
||||
static void outfunc __P((FILE *, int));
|
||||
static void indent __P((int, FILE *));
|
||||
static int nextfield __P((char *));
|
||||
static void skipbl __P((void));
|
||||
static int readline __P((void));
|
||||
static void error __P((const char *, ...));
|
||||
static char *savestr __P((const char *));
|
||||
int main __P((int, char **));
|
||||
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
if (argc != 3)
|
||||
error("usage: mknodes file");
|
||||
if ((infp = fopen(argv[1], "r")) == NULL)
|
||||
error("Can't open %s", argv[1]);
|
||||
while (readline()) {
|
||||
if (line[0] == ' ' || line[0] == '\t')
|
||||
parsefield();
|
||||
else if (line[0] != '\0')
|
||||
parsenode();
|
||||
}
|
||||
output(argv[2]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
parsenode()
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char tag[BUFLEN];
|
||||
struct str *sp;
|
||||
|
||||
if (curstr && curstr->nfields > 0)
|
||||
curstr->done = 1;
|
||||
nextfield(name);
|
||||
if (! nextfield(tag))
|
||||
error("Tag expected");
|
||||
if (*linep != '\0')
|
||||
error("Garbage at end of line");
|
||||
nodename[ntypes] = savestr(name);
|
||||
for (sp = str ; sp < str + nstr ; sp++) {
|
||||
if (strcmp(sp->tag, tag) == 0)
|
||||
break;
|
||||
}
|
||||
if (sp >= str + nstr) {
|
||||
sp->tag = savestr(tag);
|
||||
sp->nfields = 0;
|
||||
curstr = sp;
|
||||
nstr++;
|
||||
}
|
||||
nodestr[ntypes] = sp;
|
||||
ntypes++;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parsefield()
|
||||
{
|
||||
char name[BUFLEN];
|
||||
char type[BUFLEN];
|
||||
char decl[2 * BUFLEN];
|
||||
struct field *fp;
|
||||
|
||||
if (curstr == NULL || curstr->done)
|
||||
error("No current structure to add field to");
|
||||
if (! nextfield(name))
|
||||
error("No field name");
|
||||
if (! nextfield(type))
|
||||
error("No field type");
|
||||
fp = &curstr->field[curstr->nfields];
|
||||
fp->name = savestr(name);
|
||||
if (strcmp(type, "nodeptr") == 0) {
|
||||
fp->type = T_NODE;
|
||||
sprintf(decl, "union node *%s", name);
|
||||
} else if (strcmp(type, "nodelist") == 0) {
|
||||
fp->type = T_NODELIST;
|
||||
sprintf(decl, "struct nodelist *%s", name);
|
||||
} else if (strcmp(type, "string") == 0) {
|
||||
fp->type = T_STRING;
|
||||
sprintf(decl, "char *%s", name);
|
||||
} else if (strcmp(type, "int") == 0) {
|
||||
fp->type = T_INT;
|
||||
sprintf(decl, "int %s", name);
|
||||
} else if (strcmp(type, "other") == 0) {
|
||||
fp->type = T_OTHER;
|
||||
} else if (strcmp(type, "temp") == 0) {
|
||||
fp->type = T_TEMP;
|
||||
} else {
|
||||
error("Unknown type %s", type);
|
||||
}
|
||||
if (fp->type == T_OTHER || fp->type == T_TEMP) {
|
||||
skipbl();
|
||||
fp->decl = savestr(linep);
|
||||
} else {
|
||||
if (*linep)
|
||||
error("Garbage at end of line");
|
||||
fp->decl = savestr(decl);
|
||||
}
|
||||
curstr->nfields++;
|
||||
}
|
||||
|
||||
|
||||
char writer[] = "\
|
||||
/*\n\
|
||||
* This file was generated by the mknodes program.\n\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
static void
|
||||
output(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *hfile;
|
||||
FILE *cfile;
|
||||
FILE *patfile;
|
||||
int i;
|
||||
struct str *sp;
|
||||
struct field *fp;
|
||||
char *p;
|
||||
|
||||
if ((patfile = fopen(file, "r")) == NULL)
|
||||
error("Can't open %s", file);
|
||||
if ((hfile = fopen("nodes.h", "w")) == NULL)
|
||||
error("Can't create nodes.h");
|
||||
if ((cfile = fopen("nodes.c", "w")) == NULL)
|
||||
error("Can't create nodes.c");
|
||||
fputs(writer, hfile);
|
||||
for (i = 0 ; i < ntypes ; i++)
|
||||
fprintf(hfile, "#define %s %d\n", nodename[i], i);
|
||||
fputs("\n\n\n", hfile);
|
||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||
fprintf(hfile, "struct %s {\n", sp->tag);
|
||||
for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
|
||||
fprintf(hfile, " %s;\n", fp->decl);
|
||||
}
|
||||
fputs("};\n\n\n", hfile);
|
||||
}
|
||||
fputs("union node {\n", hfile);
|
||||
fprintf(hfile, " int type;\n");
|
||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||
fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag);
|
||||
}
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("struct nodelist {\n", hfile);
|
||||
fputs("\tstruct nodelist *next;\n", hfile);
|
||||
fputs("\tunion node *n;\n", hfile);
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("#ifdef __STDC__\n", hfile);
|
||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||
fputs("void freefunc(union node *);\n", hfile);
|
||||
fputs("#else\n", hfile);
|
||||
fputs("union node *copyfunc();\n", hfile);
|
||||
fputs("void freefunc();\n", hfile);
|
||||
fputs("#endif\n", hfile);
|
||||
|
||||
fputs(writer, cfile);
|
||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||
for (p = line ; *p == ' ' || *p == '\t' ; p++);
|
||||
if (strcmp(p, "%SIZES\n") == 0)
|
||||
outsizes(cfile);
|
||||
else if (strcmp(p, "%CALCSIZE\n") == 0)
|
||||
outfunc(cfile, 1);
|
||||
else if (strcmp(p, "%COPY\n") == 0)
|
||||
outfunc(cfile, 0);
|
||||
else
|
||||
fputs(line, cfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
outsizes(cfile)
|
||||
FILE *cfile;
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
|
||||
for (i = 0 ; i < ntypes ; i++) {
|
||||
fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
|
||||
}
|
||||
fprintf(cfile, "};\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
outfunc(cfile, calcsize)
|
||||
FILE *cfile;
|
||||
int calcsize;
|
||||
{
|
||||
struct str *sp;
|
||||
struct field *fp;
|
||||
int i;
|
||||
|
||||
fputs(" if (n == NULL)\n", cfile);
|
||||
if (calcsize)
|
||||
fputs(" return;\n", cfile);
|
||||
else
|
||||
fputs(" return NULL;\n", cfile);
|
||||
if (calcsize)
|
||||
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
|
||||
else {
|
||||
fputs(" new = funcblock;\n", cfile);
|
||||
fputs(" funcblock = (char *) funcblock + nodesize[n->type];\n", cfile);
|
||||
}
|
||||
fputs(" switch (n->type) {\n", cfile);
|
||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||
for (i = 0 ; i < ntypes ; i++) {
|
||||
if (nodestr[i] == sp)
|
||||
fprintf(cfile, " case %s:\n", nodename[i]);
|
||||
}
|
||||
for (i = sp->nfields ; --i >= 1 ; ) {
|
||||
fp = &sp->field[i];
|
||||
switch (fp->type) {
|
||||
case T_NODE:
|
||||
if (calcsize) {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "calcsize(n->%s.%s);\n",
|
||||
sp->tag, fp->name);
|
||||
} else {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
|
||||
sp->tag, fp->name, sp->tag, fp->name);
|
||||
}
|
||||
break;
|
||||
case T_NODELIST:
|
||||
if (calcsize) {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "sizenodelist(n->%s.%s);\n",
|
||||
sp->tag, fp->name);
|
||||
} else {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
|
||||
sp->tag, fp->name, sp->tag, fp->name);
|
||||
}
|
||||
break;
|
||||
case T_STRING:
|
||||
if (calcsize) {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
|
||||
sp->tag, fp->name);
|
||||
} else {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
|
||||
sp->tag, fp->name, sp->tag, fp->name);
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
case T_OTHER:
|
||||
if (! calcsize) {
|
||||
indent(12, cfile);
|
||||
fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
|
||||
sp->tag, fp->name, sp->tag, fp->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
indent(12, cfile);
|
||||
fputs("break;\n", cfile);
|
||||
}
|
||||
fputs(" };\n", cfile);
|
||||
if (! calcsize)
|
||||
fputs(" new->type = n->type;\n", cfile);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
indent(amount, fp)
|
||||
int amount;
|
||||
FILE *fp;
|
||||
{
|
||||
while (amount >= 8) {
|
||||
putc('\t', fp);
|
||||
amount -= 8;
|
||||
}
|
||||
while (--amount >= 0) {
|
||||
putc(' ', fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nextfield(buf)
|
||||
char *buf;
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
p = linep;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
q = buf;
|
||||
while (*p != ' ' && *p != '\t' && *p != '\0')
|
||||
*q++ = *p++;
|
||||
*q = '\0';
|
||||
linep = p;
|
||||
return (q > buf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
skipbl()
|
||||
{
|
||||
while (*linep == ' ' || *linep == '\t')
|
||||
linep++;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
readline()
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (fgets(line, 1024, infp) == NULL)
|
||||
return 0;
|
||||
for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
|
||||
while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
|
||||
p--;
|
||||
*p = '\0';
|
||||
linep = line;
|
||||
linno++;
|
||||
if (p - line > BUFLEN)
|
||||
error("Line too long");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
error(const char *msg, ...)
|
||||
#else
|
||||
error(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list va;
|
||||
#ifdef __STDC__
|
||||
va_start(va, msg);
|
||||
#else
|
||||
char *msg;
|
||||
va_start(va);
|
||||
msg = va_arg(va, char *);
|
||||
#endif
|
||||
|
||||
(void) fprintf(stderr, "line %d: ", linno);
|
||||
(void) vfprintf(stderr, msg, va);
|
||||
(void) fputc('\n', stderr);
|
||||
|
||||
va_end(va);
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *
|
||||
savestr(s)
|
||||
const char *s;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = malloc(strlen(s) + 1)) == NULL)
|
||||
error("Out of space");
|
||||
(void) strcpy(p, s);
|
||||
return p;
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
/* $NetBSD: mksyntax.c,v 1.15 1997/07/05 21:25:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mksyntax.c,v 1.15 1997/07/05 21:25:09 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This program creates syntax.h and syntax.c.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
struct synclass {
|
||||
char *name;
|
||||
char *comment;
|
||||
};
|
||||
|
||||
/* Syntax classes */
|
||||
struct synclass synclass[] = {
|
||||
{ "CWORD", "character is nothing special" },
|
||||
{ "CNL", "newline character" },
|
||||
{ "CBACK", "a backslash character" },
|
||||
{ "CSQUOTE", "single quote" },
|
||||
{ "CDQUOTE", "double quote" },
|
||||
{ "CENDQUOTE", "a terminating quote" },
|
||||
{ "CBQUOTE", "backwards single quote" },
|
||||
{ "CVAR", "a dollar sign" },
|
||||
{ "CENDVAR", "a '}' character" },
|
||||
{ "CLP", "a left paren in arithmetic" },
|
||||
{ "CRP", "a right paren in arithmetic" },
|
||||
{ "CEOF", "end of file" },
|
||||
{ "CCTL", "like CWORD, except it must be escaped" },
|
||||
{ "CSPCL", "these terminate a word" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Syntax classes for is_ functions. Warning: if you add new classes
|
||||
* you may have to change the definition of the is_in_name macro.
|
||||
*/
|
||||
struct synclass is_entry[] = {
|
||||
{ "ISDIGIT", "a digit" },
|
||||
{ "ISUPPER", "an upper case letter" },
|
||||
{ "ISLOWER", "a lower case letter" },
|
||||
{ "ISUNDER", "an underscore" },
|
||||
{ "ISSPECL", "the name of a special parameter" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static char writer[] = "\
|
||||
/*\n\
|
||||
* This file was generated by the mksyntax program.\n\
|
||||
*/\n\
|
||||
\n";
|
||||
|
||||
|
||||
static FILE *cfile;
|
||||
static FILE *hfile;
|
||||
static char *syntax[513];
|
||||
static int base;
|
||||
static int size; /* number of values which a char variable can have */
|
||||
static int nbits; /* number of bits in a character */
|
||||
static int digit_contig;/* true if digits are contiguous */
|
||||
|
||||
static void filltable __P((char *));
|
||||
static void init __P((void));
|
||||
static void add __P((char *, char *));
|
||||
static void print __P((char *));
|
||||
static void output_type_macros __P((void));
|
||||
static void digit_convert __P((void));
|
||||
int main __P((int, char **));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char c;
|
||||
char d;
|
||||
int sign;
|
||||
int i;
|
||||
char buf[80];
|
||||
int pos;
|
||||
static char digit[] = "0123456789";
|
||||
|
||||
/* Create output files */
|
||||
if ((cfile = fopen("syntax.c", "w")) == NULL) {
|
||||
perror("syntax.c");
|
||||
exit(2);
|
||||
}
|
||||
if ((hfile = fopen("syntax.h", "w")) == NULL) {
|
||||
perror("syntax.h");
|
||||
exit(2);
|
||||
}
|
||||
fputs(writer, hfile);
|
||||
fputs(writer, cfile);
|
||||
|
||||
/* Determine the characteristics of chars. */
|
||||
c = -1;
|
||||
if (c <= 0)
|
||||
sign = 1;
|
||||
else
|
||||
sign = 0;
|
||||
for (nbits = 1 ; ; nbits++) {
|
||||
d = (1 << nbits) - 1;
|
||||
if (d == c)
|
||||
break;
|
||||
}
|
||||
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
|
||||
if (nbits > 9) {
|
||||
fputs("Characters can't have more than 9 bits\n", stderr);
|
||||
exit(2);
|
||||
}
|
||||
size = (1 << nbits) + 1;
|
||||
base = 1;
|
||||
if (sign)
|
||||
base += 1 << (nbits - 1);
|
||||
digit_contig = 1;
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (digit[i] != '0' + i)
|
||||
digit_contig = 0;
|
||||
}
|
||||
|
||||
fputs("#include <sys/cdefs.h>\n", hfile);
|
||||
fputs("#include <ctype.h>\n", hfile);
|
||||
|
||||
/* Generate the #define statements in the header file */
|
||||
fputs("/* Syntax classes */\n", hfile);
|
||||
for (i = 0 ; synclass[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %d", synclass[i].name, i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", synclass[i].comment);
|
||||
}
|
||||
putc('\n', hfile);
|
||||
fputs("/* Syntax classes for is_ functions */\n", hfile);
|
||||
for (i = 0 ; is_entry[i].name ; i++) {
|
||||
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
|
||||
fputs(buf, hfile);
|
||||
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||
putc('\t', hfile);
|
||||
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
|
||||
}
|
||||
putc('\n', hfile);
|
||||
fprintf(hfile, "#define SYNBASE %d\n", base);
|
||||
fprintf(hfile, "#define PEOF %d\n\n", -base);
|
||||
if (sign)
|
||||
fprintf(hfile, "#define UPEOF %d\n\n", -base);
|
||||
else
|
||||
fprintf(hfile, "#define UPEOF ((unsigned char) %d)\n\n", -base);
|
||||
putc('\n', hfile);
|
||||
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
|
||||
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
|
||||
putc('\n', hfile);
|
||||
output_type_macros(); /* is_digit, etc. */
|
||||
putc('\n', hfile);
|
||||
|
||||
/* Generate the syntax tables. */
|
||||
fputs("#include \"shell.h\"\n", cfile);
|
||||
fputs("#include \"syntax.h\"\n\n", cfile);
|
||||
init();
|
||||
fputs("/* syntax table used when not in quotes */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("\\", "CBACK");
|
||||
add("'", "CSQUOTE");
|
||||
add("\"", "CDQUOTE");
|
||||
add("`", "CBQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("<>();&| \t", "CSPCL");
|
||||
print("basesyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in double quotes */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("\\", "CBACK");
|
||||
add("\"", "CENDQUOTE");
|
||||
add("`", "CBQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("dqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in single quotes */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("'", "CENDQUOTE");
|
||||
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||
add("!*?[=~:/-", "CCTL");
|
||||
print("sqsyntax");
|
||||
init();
|
||||
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
|
||||
add("\n", "CNL");
|
||||
add("\\", "CBACK");
|
||||
add("`", "CBQUOTE");
|
||||
add("'", "CSQUOTE");
|
||||
add("\"", "CDQUOTE");
|
||||
add("$", "CVAR");
|
||||
add("}", "CENDVAR");
|
||||
add("(", "CLP");
|
||||
add(")", "CRP");
|
||||
print("arisyntax");
|
||||
filltable("0");
|
||||
fputs("\n/* character classification table */\n", cfile);
|
||||
add("0123456789", "ISDIGIT");
|
||||
add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
|
||||
add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
|
||||
add("_", "ISUNDER");
|
||||
add("#?$!-*@", "ISSPECL");
|
||||
print("is_type");
|
||||
if (! digit_contig)
|
||||
digit_convert();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clear the syntax table.
|
||||
*/
|
||||
|
||||
static void
|
||||
filltable(dftval)
|
||||
char *dftval;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < size ; i++)
|
||||
syntax[i] = dftval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the syntax table with default values.
|
||||
*/
|
||||
|
||||
static void
|
||||
init()
|
||||
{
|
||||
filltable("CWORD");
|
||||
syntax[0] = "CEOF";
|
||||
syntax[base + CTLESC] = "CCTL";
|
||||
syntax[base + CTLVAR] = "CCTL";
|
||||
syntax[base + CTLENDVAR] = "CCTL";
|
||||
syntax[base + CTLBACKQ] = "CCTL";
|
||||
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
|
||||
syntax[base + CTLARI] = "CCTL";
|
||||
syntax[base + CTLENDARI] = "CCTL";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add entries to the syntax table.
|
||||
*/
|
||||
|
||||
static void
|
||||
add(p, type)
|
||||
char *p, *type;
|
||||
{
|
||||
while (*p)
|
||||
syntax[*p++ + base] = type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Output the syntax table.
|
||||
*/
|
||||
|
||||
static void
|
||||
print(name)
|
||||
char *name;
|
||||
{
|
||||
int i;
|
||||
int col;
|
||||
|
||||
fprintf(hfile, "extern const char %s[];\n", name);
|
||||
fprintf(cfile, "const char %s[%d] = {\n", name, size);
|
||||
col = 0;
|
||||
for (i = 0 ; i < size ; i++) {
|
||||
if (i == 0) {
|
||||
fputs(" ", cfile);
|
||||
} else if ((i & 03) == 0) {
|
||||
fputs(",\n ", cfile);
|
||||
col = 0;
|
||||
} else {
|
||||
putc(',', cfile);
|
||||
while (++col < 9 * (i & 03))
|
||||
putc(' ', cfile);
|
||||
}
|
||||
fputs(syntax[i], cfile);
|
||||
col += strlen(syntax[i]);
|
||||
}
|
||||
fputs("\n};\n", cfile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Output character classification macros (e.g. is_digit). If digits are
|
||||
* contiguous, we can test for them quickly.
|
||||
*/
|
||||
|
||||
static char *macro[] = {
|
||||
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
|
||||
"#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
|
||||
"#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
|
||||
"#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
|
||||
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
output_type_macros()
|
||||
{
|
||||
char **pp;
|
||||
|
||||
if (digit_contig)
|
||||
macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
|
||||
for (pp = macro ; *pp ; pp++)
|
||||
fprintf(hfile, "%s\n", *pp);
|
||||
if (digit_contig)
|
||||
fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
|
||||
else
|
||||
fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Output digit conversion table (if digits are not contiguous).
|
||||
*/
|
||||
|
||||
static void
|
||||
digit_convert()
|
||||
{
|
||||
int maxdigit;
|
||||
static char digit[] = "0123456789";
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
maxdigit = 0;
|
||||
for (p = digit ; *p ; p++)
|
||||
if (*p > maxdigit)
|
||||
maxdigit = *p;
|
||||
fputs("extern const char digit_value[];\n", hfile);
|
||||
fputs("\n\nconst char digit_value[] = {\n", cfile);
|
||||
for (i = 0 ; i <= maxdigit ; i++) {
|
||||
for (p = digit ; *p && *p != i ; p++);
|
||||
if (*p == '\0')
|
||||
p = digit;
|
||||
fprintf(cfile, " %d,\n", p - digit);
|
||||
}
|
||||
fputs("};\n", cfile);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: mktokens,v 1.8 1996/10/16 14:47:49 christos Exp $
|
||||
#
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||
|
||||
# The following is a list of tokens. The second column is nonzero if the
|
||||
# token marks the end of a list. The third column is the name to print in
|
||||
# error messages.
|
||||
|
||||
cat > /tmp/ka$$ <<\!
|
||||
TEOF 1 end of file
|
||||
TNL 0 newline
|
||||
TSEMI 0 ";"
|
||||
TBACKGND 0 "&"
|
||||
TAND 0 "&&"
|
||||
TOR 0 "||"
|
||||
TPIPE 0 "|"
|
||||
TLP 0 "("
|
||||
TRP 1 ")"
|
||||
TENDCASE 1 ";;"
|
||||
TENDBQUOTE 1 "`"
|
||||
TREDIR 0 redirection
|
||||
TWORD 0 word
|
||||
TIF 0 "if"
|
||||
TTHEN 1 "then"
|
||||
TELSE 1 "else"
|
||||
TELIF 1 "elif"
|
||||
TFI 1 "fi"
|
||||
TWHILE 0 "while"
|
||||
TUNTIL 0 "until"
|
||||
TFOR 0 "for"
|
||||
TDO 1 "do"
|
||||
TDONE 1 "done"
|
||||
TBEGIN 0 "{"
|
||||
TEND 1 "}"
|
||||
TCASE 0 "case"
|
||||
TESAC 1 "esac"
|
||||
TNOT 0 "!"
|
||||
!
|
||||
nl=`wc -l /tmp/ka$$`
|
||||
exec > token.h
|
||||
awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
|
||||
echo '
|
||||
/* Array indicating which tokens mark the end of a list */
|
||||
const char tokendlist[] = {'
|
||||
awk '{print "\t" $2 ","}' /tmp/ka$$
|
||||
echo '};
|
||||
|
||||
char *const tokname[] = {'
|
||||
sed -e 's/"/\\"/g' \
|
||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||
/tmp/ka$$
|
||||
echo '};
|
||||
'
|
||||
sed 's/"//g' /tmp/ka$$ | awk '
|
||||
/TIF/{print "#define KWDOFFSET " NR-1; print ""; print "char *const parsekwd[] = {"}
|
||||
/TIF/,/neverfound/{print " \"" $3 "\","}'
|
||||
echo ' 0
|
||||
};'
|
||||
|
||||
rm /tmp/ka$$
|
@ -1,50 +0,0 @@
|
||||
/* $NetBSD: myhistedit.h,v 1.6 1997/04/11 22:45:40 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <histedit.h>
|
||||
|
||||
extern History *hist;
|
||||
extern EditLine *el;
|
||||
extern int displayhist;
|
||||
|
||||
void histedit __P((void));
|
||||
void sethistsize __P((const char *));
|
||||
void setterm __P((const char *));
|
||||
int histcmd __P((int, char **));
|
||||
int not_fcnumber __P((char *));
|
||||
int str_to_event __P((char *, int));
|
||||
|
@ -1,144 +0,0 @@
|
||||
/* $NetBSD: mystring.c,v 1.13 1997/07/04 21:02:15 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: mystring.c,v 1.13 1997/07/04 21:02:15 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* String functions.
|
||||
*
|
||||
* equal(s1, s2) Return true if strings are equal.
|
||||
* scopy(from, to) Copy a string.
|
||||
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
||||
* number(s) Convert a string of digits to an integer.
|
||||
* is_number(s) Return true if s is a string of digits.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
char nullstr[1]; /* zero length string */
|
||||
|
||||
/*
|
||||
* equal - #defined in mystring.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* scopy - #defined in mystring.h
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* scopyn - copy a string from "from" to "to", truncating the string
|
||||
* if necessary. "To" is always nul terminated, even if
|
||||
* truncation is performed. "Size" is the size of "to".
|
||||
*/
|
||||
|
||||
void
|
||||
scopyn(from, to, size)
|
||||
char const *from;
|
||||
char *to;
|
||||
int size;
|
||||
{
|
||||
|
||||
while (--size > 0) {
|
||||
if ((*to++ = *from++) == '\0')
|
||||
return;
|
||||
}
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* prefix -- see if pfx is a prefix of string.
|
||||
*/
|
||||
|
||||
int
|
||||
prefix(pfx, string)
|
||||
char const *pfx;
|
||||
char const *string;
|
||||
{
|
||||
while (*pfx) {
|
||||
if (*pfx++ != *string++)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a string of digits to an integer, printing an error message on
|
||||
* failure.
|
||||
*/
|
||||
|
||||
int
|
||||
number(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
if (! is_number(s))
|
||||
error("Illegal number: %s", (char *)s);
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Check for a valid number. This should be elsewhere.
|
||||
*/
|
||||
|
||||
int
|
||||
is_number(p)
|
||||
const char *p;
|
||||
{
|
||||
do {
|
||||
if (! is_digit(*p))
|
||||
return 0;
|
||||
} while (*++p != '\0');
|
||||
return 1;
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/* $NetBSD: mystring.h,v 1.9 1995/05/11 21:29:42 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void scopyn __P((const char *, char *, int));
|
||||
int prefix __P((const char *, const char *));
|
||||
int number __P((const char *));
|
||||
int is_number __P((const char *));
|
||||
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
@ -1,169 +0,0 @@
|
||||
/* $NetBSD: nodes.c.pat,v 1.8 1997/04/11 23:03:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "memalloc.h"
|
||||
#include "machdep.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
int funcblocksize; /* size of structures in function */
|
||||
int funcstringsize; /* size of strings in node */
|
||||
pointer funcblock; /* block to allocate function from */
|
||||
char *funcstring; /* block to allocate strings from */
|
||||
|
||||
%SIZES
|
||||
|
||||
|
||||
STATIC void calcsize __P((union node *));
|
||||
STATIC void sizenodelist __P((struct nodelist *));
|
||||
STATIC union node *copynode __P((union node *));
|
||||
STATIC struct nodelist *copynodelist __P((struct nodelist *));
|
||||
STATIC char *nodesavestr __P((char *));
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Make a copy of a parse tree.
|
||||
*/
|
||||
|
||||
union node *
|
||||
copyfunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *) funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(n)
|
||||
union node *n;
|
||||
{
|
||||
%CALCSIZE
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC void
|
||||
sizenodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
while (lp) {
|
||||
funcblocksize += ALIGN(sizeof(struct nodelist));
|
||||
calcsize(lp->n);
|
||||
lp = lp->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC union node *
|
||||
copynode(n)
|
||||
union node *n;
|
||||
{
|
||||
union node *new;
|
||||
|
||||
%COPY
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
STATIC struct nodelist *
|
||||
copynodelist(lp)
|
||||
struct nodelist *lp;
|
||||
{
|
||||
struct nodelist *start;
|
||||
struct nodelist **lpp;
|
||||
|
||||
lpp = &start;
|
||||
while (lp) {
|
||||
*lpp = funcblock;
|
||||
funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
|
||||
(*lpp)->n = copynode(lp->n);
|
||||
lp = lp->next;
|
||||
lpp = &(*lpp)->next;
|
||||
}
|
||||
*lpp = NULL;
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC char *
|
||||
nodesavestr(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p = s;
|
||||
register char *q = funcstring;
|
||||
char *rtn = funcstring;
|
||||
|
||||
while ((*q++ = *p++) != '\0')
|
||||
continue;
|
||||
funcstring = q;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Free a parse tree.
|
||||
*/
|
||||
|
||||
void
|
||||
freefunc(n)
|
||||
union node *n;
|
||||
{
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
# $NetBSD: nodetypes,v 1.8 1995/05/11 21:29:44 christos Exp $
|
||||
# Copyright (c) 1991, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||
|
||||
# This file describes the nodes used in parse trees. Unindented lines
|
||||
# contain a node type followed by a structure tag. Subsequent indented
|
||||
# lines specify the fields of the structure. Several node types can share
|
||||
# the same structure, in which case the fields of the structure should be
|
||||
# specified only once.
|
||||
#
|
||||
# A field of a structure is described by the name of the field followed
|
||||
# by a type. The currently implemented types are:
|
||||
# nodeptr - a pointer to a node
|
||||
# nodelist - a pointer to a list of nodes
|
||||
# string - a pointer to a nul terminated string
|
||||
# int - an integer
|
||||
# other - any type that can be copied by assignment
|
||||
# temp - a field that doesn't have to be copied when the node is copied
|
||||
# The last two types should be followed by the text of a C declaration for
|
||||
# the field.
|
||||
|
||||
NSEMI nbinary # two commands separated by a semicolon
|
||||
type int
|
||||
ch1 nodeptr # the first child
|
||||
ch2 nodeptr # the second child
|
||||
|
||||
NCMD ncmd # a simple command
|
||||
type int
|
||||
backgnd int # set to run command in background
|
||||
args nodeptr # the arguments
|
||||
redirect nodeptr # list of file redirections
|
||||
|
||||
NPIPE npipe # a pipeline
|
||||
type int
|
||||
backgnd int # set to run pipeline in background
|
||||
cmdlist nodelist # the commands in the pipeline
|
||||
|
||||
NREDIR nredir # redirection (of a compex command)
|
||||
type int
|
||||
n nodeptr # the command
|
||||
redirect nodeptr # list of file redirections
|
||||
|
||||
NBACKGND nredir # run command in background
|
||||
NSUBSHELL nredir # run command in a subshell
|
||||
|
||||
NAND nbinary # the && operator
|
||||
NOR nbinary # the || operator
|
||||
|
||||
NIF nif # the if statement. Elif clauses are handled
|
||||
type int # using multiple if nodes.
|
||||
test nodeptr # if test
|
||||
ifpart nodeptr # then ifpart
|
||||
elsepart nodeptr # else elsepart
|
||||
|
||||
NWHILE nbinary # the while statement. First child is the test
|
||||
NUNTIL nbinary # the until statement
|
||||
|
||||
NFOR nfor # the for statement
|
||||
type int
|
||||
args nodeptr # for var in args
|
||||
body nodeptr # do body; done
|
||||
var string # the for variable
|
||||
|
||||
NCASE ncase # a case statement
|
||||
type int
|
||||
expr nodeptr # the word to switch on
|
||||
cases nodeptr # the list of cases (NCLIST nodes)
|
||||
|
||||
NCLIST nclist # a case
|
||||
type int
|
||||
next nodeptr # the next case in list
|
||||
pattern nodeptr # list of patterns for this case
|
||||
body nodeptr # code to execute for this case
|
||||
|
||||
|
||||
NDEFUN narg # define a function. The "next" field contains
|
||||
# the body of the function.
|
||||
|
||||
NARG narg # represents a word
|
||||
type int
|
||||
next nodeptr # next word in list
|
||||
text string # the text of the word
|
||||
backquote nodelist # list of commands in back quotes
|
||||
|
||||
NTO nfile # fd> fname
|
||||
NFROM nfile # fd< fname
|
||||
NAPPEND nfile # fd>> fname
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
fname nodeptr # file name, in a NARG node
|
||||
expfname temp char *expfname # actual file name
|
||||
|
||||
NTOFD ndup # fd<&dupfd
|
||||
NFROMFD ndup # fd>&dupfd
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
dupfd int # file descriptor to duplicate
|
||||
vname nodeptr # file name if fd>&$var
|
||||
|
||||
|
||||
NHERE nhere # fd<<\!
|
||||
NXHERE nhere # fd<<!
|
||||
type int
|
||||
next nodeptr # next redirection in list
|
||||
fd int # file descriptor being redirected
|
||||
doc nodeptr # input to command (NARG node)
|
||||
|
||||
NNOT nnot # ! command (actually pipeline)
|
||||
type int
|
||||
com nodeptr
|
@ -1,541 +0,0 @@
|
||||
/* $NetBSD: options.c,v 1.25 1997/07/04 21:02:16 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: options.c,v 1.25 1997/07/04 21:02:16 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#define DEFINE_OPTIONS
|
||||
#include "options.h"
|
||||
#undef DEFINE_OPTIONS
|
||||
#include "nodes.h" /* for other header files */
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "trap.h"
|
||||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#ifndef SMALL
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
char *arg0; /* value of $0 */
|
||||
struct shparam shellparam; /* current positional parameters */
|
||||
char **argptr; /* argument list for builtin commands */
|
||||
char *optarg; /* set by nextopt (like getopt) */
|
||||
char *optptr; /* used by nextopt */
|
||||
|
||||
char *minusc; /* argument to -c option */
|
||||
|
||||
|
||||
STATIC void options __P((int));
|
||||
STATIC void minus_o __P((char *, int));
|
||||
STATIC void setoption __P((int, int));
|
||||
STATIC int getopts __P((char *, char *, char **, char ***, char **));
|
||||
|
||||
|
||||
/*
|
||||
* Process the shell command line arguments.
|
||||
*/
|
||||
|
||||
void
|
||||
procargs(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
|
||||
argptr = argv;
|
||||
if (argc > 0)
|
||||
argptr++;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 2;
|
||||
options(1);
|
||||
if (*argptr == NULL && minusc == NULL)
|
||||
sflag = 1;
|
||||
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
||||
iflag = 1;
|
||||
if (mflag == 2)
|
||||
mflag = iflag;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].val == 2)
|
||||
optlist[i].val = 0;
|
||||
arg0 = argv[0];
|
||||
if (sflag == 0 && minusc == NULL) {
|
||||
commandname = arg0 = *argptr++;
|
||||
setinputfile(commandname, 0);
|
||||
}
|
||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||
if (argptr && minusc && *argptr)
|
||||
arg0 = *argptr++;
|
||||
|
||||
shellparam.p = argptr;
|
||||
shellparam.reset = 1;
|
||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
||||
while (*argptr) {
|
||||
shellparam.nparam++;
|
||||
argptr++;
|
||||
}
|
||||
optschanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
optschanged()
|
||||
{
|
||||
setinteractive(iflag);
|
||||
#ifndef SMALL
|
||||
histedit();
|
||||
#endif
|
||||
setjobctl(mflag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process shell options. The global variable argptr contains a pointer
|
||||
* to the argument list; we advance it past the options.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
options(cmdline)
|
||||
int cmdline;
|
||||
{
|
||||
char *p;
|
||||
int val;
|
||||
int c;
|
||||
|
||||
if (cmdline)
|
||||
minusc = NULL;
|
||||
while ((p = *argptr) != NULL) {
|
||||
argptr++;
|
||||
if ((c = *p++) == '-') {
|
||||
val = 1;
|
||||
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
|
||||
if (!cmdline) {
|
||||
/* "-" means turn off -x and -v */
|
||||
if (p[0] == '\0')
|
||||
xflag = vflag = 0;
|
||||
/* "--" means reset params */
|
||||
else if (*argptr == NULL)
|
||||
setparam(argptr);
|
||||
}
|
||||
break; /* "-" or "--" terminates options */
|
||||
}
|
||||
} else if (c == '+') {
|
||||
val = 0;
|
||||
} else {
|
||||
argptr--;
|
||||
break;
|
||||
}
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == 'c' && cmdline) {
|
||||
char *q;
|
||||
#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
|
||||
if (*p == '\0')
|
||||
#endif
|
||||
q = *argptr++;
|
||||
if (q == NULL || minusc != NULL)
|
||||
error("Bad -c option");
|
||||
minusc = q;
|
||||
#ifdef NOHACK
|
||||
break;
|
||||
#endif
|
||||
} else if (c == 'o') {
|
||||
minus_o(*argptr, val);
|
||||
if (*argptr)
|
||||
argptr++;
|
||||
} else {
|
||||
setoption(c, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void
|
||||
minus_o(name, val)
|
||||
char *name;
|
||||
int val;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (name == NULL) {
|
||||
out1str("Current option settings\n");
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
out1fmt("%-16s%s\n", optlist[i].name,
|
||||
optlist[i].val ? "on" : "off");
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
setoption(optlist[i].letter, val);
|
||||
return;
|
||||
}
|
||||
error("Illegal option -o %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
setoption(flag, val)
|
||||
char flag;
|
||||
int val;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (optlist[i].letter == flag) {
|
||||
optlist[i].val = val;
|
||||
if (val) {
|
||||
/* #%$ hack for ksh semantics */
|
||||
if (flag == 'V')
|
||||
Eflag = 0;
|
||||
else if (flag == 'E')
|
||||
Vflag = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
error("Illegal option -%c", flag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "options.h"
|
||||
|
||||
SHELLPROC {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 0;
|
||||
optschanged();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Set the shell parameters.
|
||||
*/
|
||||
|
||||
void
|
||||
setparam(argv)
|
||||
char **argv;
|
||||
{
|
||||
char **newparam;
|
||||
char **ap;
|
||||
int nparam;
|
||||
|
||||
for (nparam = 0 ; argv[nparam] ; nparam++);
|
||||
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
||||
while (*argv) {
|
||||
*ap++ = savestr(*argv++);
|
||||
}
|
||||
*ap = NULL;
|
||||
freeparam(&shellparam);
|
||||
shellparam.malloc = 1;
|
||||
shellparam.nparam = nparam;
|
||||
shellparam.p = newparam;
|
||||
shellparam.optnext = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free the list of positional parameters.
|
||||
*/
|
||||
|
||||
void
|
||||
freeparam(param)
|
||||
struct shparam *param;
|
||||
{
|
||||
char **ap;
|
||||
|
||||
if (param->malloc) {
|
||||
for (ap = param->p ; *ap ; ap++)
|
||||
ckfree(*ap);
|
||||
ckfree(param->p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The shift builtin command.
|
||||
*/
|
||||
|
||||
int
|
||||
shiftcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int n;
|
||||
char **ap1, **ap2;
|
||||
|
||||
n = 1;
|
||||
if (argc > 1)
|
||||
n = number(argv[1]);
|
||||
if (n > shellparam.nparam)
|
||||
error("can't shift that many");
|
||||
INTOFF;
|
||||
shellparam.nparam -= n;
|
||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
||||
if (shellparam.malloc)
|
||||
ckfree(*ap1);
|
||||
}
|
||||
ap2 = shellparam.p;
|
||||
while ((*ap2++ = *ap1++) != NULL);
|
||||
shellparam.optnext = NULL;
|
||||
INTON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The set command builtin.
|
||||
*/
|
||||
|
||||
int
|
||||
setcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
if (argc == 1)
|
||||
return showvarscmd(argc, argv);
|
||||
INTOFF;
|
||||
options(0);
|
||||
optschanged();
|
||||
if (*argptr != NULL) {
|
||||
setparam(argptr);
|
||||
}
|
||||
INTON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
getoptsreset(value)
|
||||
const char *value;
|
||||
{
|
||||
if (number(value) == 1) {
|
||||
shellparam.optnext = NULL;
|
||||
shellparam.reset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The getopts builtin. Shellparam.optnext points to the next argument
|
||||
* to be processed. Shellparam.optptr points to the next character to
|
||||
* be processed in the current argument. If shellparam.optnext is NULL,
|
||||
* then it's the first time getopts has been called.
|
||||
*/
|
||||
|
||||
int
|
||||
getoptscmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **optbase;
|
||||
|
||||
if (argc < 3)
|
||||
error("Usage: getopts optstring var [arg]");
|
||||
else if (argc == 3)
|
||||
optbase = shellparam.p;
|
||||
else
|
||||
optbase = &argv[3];
|
||||
|
||||
if (shellparam.reset == 1) {
|
||||
shellparam.optnext = optbase;
|
||||
shellparam.optptr = NULL;
|
||||
shellparam.reset = 0;
|
||||
}
|
||||
|
||||
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
||||
&shellparam.optptr);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
getopts(optstr, optvar, optfirst, optnext, optptr)
|
||||
char *optstr;
|
||||
char *optvar;
|
||||
char **optfirst;
|
||||
char ***optnext;
|
||||
char **optptr;
|
||||
{
|
||||
char *p, *q;
|
||||
char c = '?';
|
||||
int done = 0;
|
||||
int ind = 0;
|
||||
int err = 0;
|
||||
char s[10];
|
||||
|
||||
if ((p = *optptr) == NULL || *p == '\0') {
|
||||
/* Current word is done, advance */
|
||||
if (*optnext == NULL)
|
||||
return 1;
|
||||
p = **optnext;
|
||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||
atend:
|
||||
ind = *optnext - optfirst + 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
(*optnext)++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
goto atend;
|
||||
}
|
||||
|
||||
c = *p++;
|
||||
for (q = optstr; *q != c; ) {
|
||||
if (*q == '\0') {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
}
|
||||
else {
|
||||
out1fmt("Illegal option -%c\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
}
|
||||
c = '?';
|
||||
goto bad;
|
||||
}
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||
if (optstr[0] == ':') {
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe("OPTARG", s, 0);
|
||||
c = ':';
|
||||
}
|
||||
else {
|
||||
out1fmt("No arg for -%c option\n", c);
|
||||
(void) unsetvar("OPTARG");
|
||||
c = '?';
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (p == **optnext)
|
||||
(*optnext)++;
|
||||
setvarsafe("OPTARG", p, 0);
|
||||
p = NULL;
|
||||
}
|
||||
else
|
||||
setvarsafe("OPTARG", "", 0);
|
||||
ind = *optnext - optfirst + 1;
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
ind = 1;
|
||||
*optnext = NULL;
|
||||
p = NULL;
|
||||
out:
|
||||
*optptr = p;
|
||||
fmtstr(s, sizeof(s), "%d", ind);
|
||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||
s[0] = c;
|
||||
s[1] = '\0';
|
||||
err |= setvarsafe(optvar, s, 0);
|
||||
if (err) {
|
||||
*optnext = NULL;
|
||||
*optptr = NULL;
|
||||
flushall();
|
||||
exraise(EXERROR);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - should get rid of. have all builtins use getopt(3). the
|
||||
* library getopt must have the BSD extension static variable "optreset"
|
||||
* otherwise it can't be used within the shell safely.
|
||||
*
|
||||
* Standard option processing (a la getopt) for builtin routines. The
|
||||
* only argument that is passed to nextopt is the option string; the
|
||||
* other arguments are unnecessary. It return the character, or '\0' on
|
||||
* end of input.
|
||||
*/
|
||||
|
||||
int
|
||||
nextopt(optstring)
|
||||
char *optstring;
|
||||
{
|
||||
char *p, *q;
|
||||
char c;
|
||||
|
||||
if ((p = optptr) == NULL || *p == '\0') {
|
||||
p = *argptr;
|
||||
if (p == NULL || *p != '-' || *++p == '\0')
|
||||
return '\0';
|
||||
argptr++;
|
||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||
return '\0';
|
||||
}
|
||||
c = *p++;
|
||||
for (q = optstring ; *q != c ; ) {
|
||||
if (*q == '\0')
|
||||
error("Illegal option -%c", c);
|
||||
if (*++q == ':')
|
||||
q++;
|
||||
}
|
||||
if (*++q == ':') {
|
||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||
error("No arg for -%c option", c);
|
||||
optarg = p;
|
||||
p = NULL;
|
||||
}
|
||||
optptr = p;
|
||||
return c;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/* $NetBSD: options.h,v 1.11 1996/11/06 01:17:12 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
struct shparam {
|
||||
int nparam; /* # of positional parameters (without $0) */
|
||||
unsigned char malloc; /* if parameter list dynamically allocated */
|
||||
unsigned char reset; /* if getopts has been reset */
|
||||
char **p; /* parameter list */
|
||||
char **optnext; /* next parameter to be processed by getopts */
|
||||
char *optptr; /* used by getopts */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define eflag optlist[0].val
|
||||
#define fflag optlist[1].val
|
||||
#define Iflag optlist[2].val
|
||||
#define iflag optlist[3].val
|
||||
#define mflag optlist[4].val
|
||||
#define nflag optlist[5].val
|
||||
#define sflag optlist[6].val
|
||||
#define xflag optlist[7].val
|
||||
#define vflag optlist[8].val
|
||||
#define Vflag optlist[9].val
|
||||
#define Eflag optlist[10].val
|
||||
#define Cflag optlist[11].val
|
||||
#define aflag optlist[12].val
|
||||
#define bflag optlist[13].val
|
||||
#define uflag optlist[14].val
|
||||
|
||||
#define NOPTS 15
|
||||
|
||||
struct optent {
|
||||
const char *name;
|
||||
const char letter;
|
||||
char val;
|
||||
};
|
||||
|
||||
#ifdef DEFINE_OPTIONS
|
||||
struct optent optlist[NOPTS] = {
|
||||
{ "errexit", 'e', 0 },
|
||||
{ "noglob", 'f', 0 },
|
||||
{ "ignoreeof", 'I', 0 },
|
||||
{ "interactive",'i', 0 },
|
||||
{ "monitor", 'm', 0 },
|
||||
{ "noexec", 'n', 0 },
|
||||
{ "stdin", 's', 0 },
|
||||
{ "xtrace", 'x', 0 },
|
||||
{ "verbose", 'v', 0 },
|
||||
{ "vi", 'V', 0 },
|
||||
{ "emacs", 'E', 0 },
|
||||
{ "noclobber", 'C', 0 },
|
||||
{ "allexport", 'a', 0 },
|
||||
{ "notify", 'b', 0 },
|
||||
{ "nounset", 'u', 0 },
|
||||
};
|
||||
#else
|
||||
extern struct optent optlist[NOPTS];
|
||||
#endif
|
||||
|
||||
|
||||
extern char *minusc; /* argument to -c option */
|
||||
extern char *arg0; /* $0 */
|
||||
extern struct shparam shellparam; /* $@ */
|
||||
extern char **argptr; /* argument list for builtin commands */
|
||||
extern char *optarg; /* set by nextopt */
|
||||
extern char *optptr; /* used by nextopt */
|
||||
|
||||
void procargs __P((int, char **));
|
||||
void optschanged __P((void));
|
||||
void setparam __P((char **));
|
||||
void freeparam __P((struct shparam *));
|
||||
int shiftcmd __P((int, char **));
|
||||
int setcmd __P((int, char **));
|
||||
int getoptscmd __P((int, char **));
|
||||
int nextopt __P((char *));
|
||||
void getoptsreset __P((const char *));
|
@ -1,584 +0,0 @@
|
||||
/* $NetBSD: output.c,v 1.19 1997/07/04 21:02:18 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: output.c,v 1.19 1997/07/04 21:02:18 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Shell output routines. We use our own output routines because:
|
||||
* When a builtin command is interrupted we have to discard
|
||||
* any pending output.
|
||||
* When a builtin command appears in back quotes, we want to
|
||||
* save the output of the command in a region obtained
|
||||
* via malloc, rather than doing a fork and reading the
|
||||
* output of the command via a pipe.
|
||||
* Our output routines may be smaller than the stdio routines.
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* quad_t */
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <stdio.h> /* defines BUFSIZ */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "syntax.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
#define OUTBUFSIZ BUFSIZ
|
||||
#define BLOCK_OUT -2 /* output to a fixed block of memory */
|
||||
#define MEM_OUT -3 /* output to dynamically allocated memory */
|
||||
#define OUTPUT_ERR 01 /* error occurred on output */
|
||||
|
||||
|
||||
struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
|
||||
struct output errout = {NULL, 0, NULL, 100, 2, 0};
|
||||
struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
|
||||
struct output *out1 = &output;
|
||||
struct output *out2 = &errout;
|
||||
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
|
||||
INCLUDE "output.h"
|
||||
INCLUDE "memalloc.h"
|
||||
|
||||
RESET {
|
||||
out1 = &output;
|
||||
out2 = &errout;
|
||||
if (memout.buf != NULL) {
|
||||
ckfree(memout.buf);
|
||||
memout.buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef notdef /* no longer used */
|
||||
/*
|
||||
* Set up an output file to write to memory rather than a file.
|
||||
*/
|
||||
|
||||
void
|
||||
open_mem(block, length, file)
|
||||
char *block;
|
||||
int length;
|
||||
struct output *file;
|
||||
{
|
||||
file->nextc = block;
|
||||
file->nleft = --length;
|
||||
file->fd = BLOCK_OUT;
|
||||
file->flags = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
out1str(p)
|
||||
const char *p;
|
||||
{
|
||||
outstr(p, out1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out2str(p)
|
||||
const char *p;
|
||||
{
|
||||
outstr(p, out2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outstr(p, file)
|
||||
const char *p;
|
||||
struct output *file;
|
||||
{
|
||||
while (*p)
|
||||
outc(*p++, file);
|
||||
if (file == out2)
|
||||
flushout(file);
|
||||
}
|
||||
|
||||
|
||||
char out_junk[16];
|
||||
|
||||
|
||||
void
|
||||
emptyoutbuf(dest)
|
||||
struct output *dest;
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (dest->fd == BLOCK_OUT) {
|
||||
dest->nextc = out_junk;
|
||||
dest->nleft = sizeof out_junk;
|
||||
dest->flags |= OUTPUT_ERR;
|
||||
} else if (dest->buf == NULL) {
|
||||
INTOFF;
|
||||
dest->buf = ckmalloc(dest->bufsize);
|
||||
dest->nextc = dest->buf;
|
||||
dest->nleft = dest->bufsize;
|
||||
INTON;
|
||||
} else if (dest->fd == MEM_OUT) {
|
||||
offset = dest->bufsize;
|
||||
INTOFF;
|
||||
dest->bufsize <<= 1;
|
||||
dest->buf = ckrealloc(dest->buf, dest->bufsize);
|
||||
dest->nleft = dest->bufsize - offset;
|
||||
dest->nextc = dest->buf + offset;
|
||||
INTON;
|
||||
} else {
|
||||
flushout(dest);
|
||||
}
|
||||
dest->nleft--;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flushall() {
|
||||
flushout(&output);
|
||||
flushout(&errout);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flushout(dest)
|
||||
struct output *dest;
|
||||
{
|
||||
|
||||
if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
|
||||
return;
|
||||
if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
|
||||
dest->flags |= OUTPUT_ERR;
|
||||
dest->nextc = dest->buf;
|
||||
dest->nleft = dest->bufsize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
freestdout() {
|
||||
INTOFF;
|
||||
if (output.buf) {
|
||||
ckfree(output.buf);
|
||||
output.buf = NULL;
|
||||
output.nleft = 0;
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
outfmt(struct output *file, char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(file, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out1fmt(char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(out1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(char *outbuf, int length, char *fmt, ...) {
|
||||
va_list ap;
|
||||
struct output strout;
|
||||
|
||||
va_start(ap, fmt);
|
||||
strout.nextc = outbuf;
|
||||
strout.nleft = length;
|
||||
strout.fd = BLOCK_OUT;
|
||||
strout.flags = 0;
|
||||
doformat(&strout, fmt, ap);
|
||||
outc('\0', &strout);
|
||||
if (strout.flags & OUTPUT_ERR)
|
||||
outbuf[length - 1] = '\0';
|
||||
}
|
||||
|
||||
#else /* not __STDC__ */
|
||||
|
||||
void
|
||||
outfmt(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
struct output *file;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
file = va_arg(ap, struct output *);
|
||||
fmt = va_arg(ap, char *);
|
||||
doformat(file, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
out1fmt(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
doformat(out1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
dprintf(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
doformat(out2, fmt, ap);
|
||||
va_end(ap);
|
||||
flushout(out2);
|
||||
}
|
||||
|
||||
void
|
||||
fmtstr(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
struct output strout;
|
||||
char *outbuf;
|
||||
int length;
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
outbuf = va_arg(ap, char *);
|
||||
length = va_arg(ap, int);
|
||||
fmt = va_arg(ap, char *);
|
||||
strout.nextc = outbuf;
|
||||
strout.nleft = length;
|
||||
strout.fd = BLOCK_OUT;
|
||||
strout.flags = 0;
|
||||
doformat(&strout, fmt, ap);
|
||||
outc('\0', &strout);
|
||||
if (strout.flags & OUTPUT_ERR)
|
||||
outbuf[length - 1] = '\0';
|
||||
}
|
||||
#endif /* __STDC__ */
|
||||
|
||||
|
||||
/*
|
||||
* Formatted output. This routine handles a subset of the printf formats:
|
||||
* - Formats supported: d, u, o, X, s, and c.
|
||||
* - The x format is also accepted but is treated like X.
|
||||
* - The l and q modifiers are accepted.
|
||||
* - The - and # flags are accepted; # only works with the o format.
|
||||
* - Width and precision may be specified with any format except c.
|
||||
* - An * may be given for the width or precision.
|
||||
* - The obsolete practice of preceding the width with a zero to get
|
||||
* zero padding is not supported; use the precision field.
|
||||
* - A % may be printed by writing %% in the format string.
|
||||
*/
|
||||
|
||||
#define TEMPSIZE 24
|
||||
|
||||
static const char digit[] = "0123456789ABCDEF";
|
||||
|
||||
|
||||
void
|
||||
doformat(dest, f, ap)
|
||||
struct output *dest;
|
||||
char *f; /* format string */
|
||||
va_list ap;
|
||||
{
|
||||
char c;
|
||||
char temp[TEMPSIZE];
|
||||
int flushleft;
|
||||
int sharp;
|
||||
int width;
|
||||
int prec;
|
||||
int islong;
|
||||
int isquad;
|
||||
char *p;
|
||||
int sign;
|
||||
#ifdef BSD4_4
|
||||
quad_t l;
|
||||
u_quad_t num;
|
||||
#else
|
||||
long l;
|
||||
u_long num;
|
||||
#endif
|
||||
unsigned base;
|
||||
int len;
|
||||
int size;
|
||||
int pad;
|
||||
|
||||
while ((c = *f++) != '\0') {
|
||||
if (c != '%') {
|
||||
outc(c, dest);
|
||||
continue;
|
||||
}
|
||||
flushleft = 0;
|
||||
sharp = 0;
|
||||
width = 0;
|
||||
prec = -1;
|
||||
islong = 0;
|
||||
isquad = 0;
|
||||
for (;;) {
|
||||
if (*f == '-')
|
||||
flushleft++;
|
||||
else if (*f == '#')
|
||||
sharp++;
|
||||
else
|
||||
break;
|
||||
f++;
|
||||
}
|
||||
if (*f == '*') {
|
||||
width = va_arg(ap, int);
|
||||
f++;
|
||||
} else {
|
||||
while (is_digit(*f)) {
|
||||
width = 10 * width + digit_val(*f++);
|
||||
}
|
||||
}
|
||||
if (*f == '.') {
|
||||
if (*++f == '*') {
|
||||
prec = va_arg(ap, int);
|
||||
f++;
|
||||
} else {
|
||||
prec = 0;
|
||||
while (is_digit(*f)) {
|
||||
prec = 10 * prec + digit_val(*f++);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*f == 'l') {
|
||||
islong++;
|
||||
f++;
|
||||
} else if (*f == 'q') {
|
||||
isquad++;
|
||||
f++;
|
||||
}
|
||||
switch (*f) {
|
||||
case 'd':
|
||||
#ifdef BSD4_4
|
||||
if (isquad)
|
||||
l = va_arg(ap, quad_t);
|
||||
else
|
||||
#endif
|
||||
if (islong)
|
||||
l = va_arg(ap, long);
|
||||
else
|
||||
l = va_arg(ap, int);
|
||||
sign = 0;
|
||||
num = l;
|
||||
if (l < 0) {
|
||||
num = -l;
|
||||
sign = 1;
|
||||
}
|
||||
base = 10;
|
||||
goto number;
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto uns_number;
|
||||
case 'o':
|
||||
base = 8;
|
||||
goto uns_number;
|
||||
case 'x':
|
||||
/* we don't implement 'x'; treat like 'X' */
|
||||
case 'X':
|
||||
base = 16;
|
||||
uns_number: /* an unsigned number */
|
||||
sign = 0;
|
||||
#ifdef BSD4_4
|
||||
if (isquad)
|
||||
num = va_arg(ap, u_quad_t);
|
||||
else
|
||||
#endif
|
||||
if (islong)
|
||||
num = va_arg(ap, unsigned long);
|
||||
else
|
||||
num = va_arg(ap, unsigned int);
|
||||
number: /* process a number */
|
||||
p = temp + TEMPSIZE - 1;
|
||||
*p = '\0';
|
||||
while (num) {
|
||||
*--p = digit[num % base];
|
||||
num /= base;
|
||||
}
|
||||
len = (temp + TEMPSIZE - 1) - p;
|
||||
if (prec < 0)
|
||||
prec = 1;
|
||||
if (sharp && *f == 'o' && prec <= len)
|
||||
prec = len + 1;
|
||||
pad = 0;
|
||||
if (width) {
|
||||
size = len;
|
||||
if (size < prec)
|
||||
size = prec;
|
||||
size += sign;
|
||||
pad = width - size;
|
||||
if (flushleft == 0) {
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
}
|
||||
}
|
||||
if (sign)
|
||||
outc('-', dest);
|
||||
prec -= len;
|
||||
while (--prec >= 0)
|
||||
outc('0', dest);
|
||||
while (*p)
|
||||
outc(*p++, dest);
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
break;
|
||||
case 's':
|
||||
p = va_arg(ap, char *);
|
||||
pad = 0;
|
||||
if (width) {
|
||||
len = strlen(p);
|
||||
if (prec >= 0 && len > prec)
|
||||
len = prec;
|
||||
pad = width - len;
|
||||
if (flushleft == 0) {
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
}
|
||||
}
|
||||
prec++;
|
||||
while (--prec != 0 && *p)
|
||||
outc(*p++, dest);
|
||||
while (--pad >= 0)
|
||||
outc(' ', dest);
|
||||
break;
|
||||
case 'c':
|
||||
c = va_arg(ap, int);
|
||||
outc(c, dest);
|
||||
break;
|
||||
default:
|
||||
outc(*f, dest);
|
||||
break;
|
||||
}
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Version of write which resumes after a signal is caught.
|
||||
*/
|
||||
|
||||
int
|
||||
xwrite(fd, buf, nbytes)
|
||||
int fd;
|
||||
char *buf;
|
||||
int nbytes;
|
||||
{
|
||||
int ntry;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
n = nbytes;
|
||||
ntry = 0;
|
||||
for (;;) {
|
||||
i = write(fd, buf, n);
|
||||
if (i > 0) {
|
||||
if ((n -= i) <= 0)
|
||||
return nbytes;
|
||||
buf += i;
|
||||
ntry = 0;
|
||||
} else if (i == 0) {
|
||||
if (++ntry > 10)
|
||||
return nbytes - n;
|
||||
} else if (errno != EINTR) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Version of ioctl that retries after a signal is caught.
|
||||
* XXX unused function
|
||||
*/
|
||||
|
||||
int
|
||||
xioctl(fd, request, arg)
|
||||
int fd;
|
||||
unsigned long request;
|
||||
char * arg;
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||
return i;
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/* $NetBSD: output.h,v 1.13 1997/04/11 23:08:40 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
#ifndef OUTPUT_INCL
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
struct output {
|
||||
char *nextc;
|
||||
int nleft;
|
||||
char *buf;
|
||||
int bufsize;
|
||||
short fd;
|
||||
short flags;
|
||||
};
|
||||
|
||||
extern struct output output;
|
||||
extern struct output errout;
|
||||
extern struct output memout;
|
||||
extern struct output *out1;
|
||||
extern struct output *out2;
|
||||
|
||||
void open_mem __P((char *, int, struct output *));
|
||||
void out1str __P((const char *));
|
||||
void out2str __P((const char *));
|
||||
void outstr __P((const char *, struct output *));
|
||||
void emptyoutbuf __P((struct output *));
|
||||
void flushall __P((void));
|
||||
void flushout __P((struct output *));
|
||||
void freestdout __P((void));
|
||||
void outfmt __P((struct output *, char *, ...));
|
||||
void out1fmt __P((char *, ...));
|
||||
void dprintf __P((char *, ...));
|
||||
void fmtstr __P((char *, int, char *, ...));
|
||||
void doformat __P((struct output *, char *, va_list));
|
||||
int xwrite __P((int, char *, int));
|
||||
int xioctl __P((int, unsigned long, char *));
|
||||
|
||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||
#define out1c(c) outc(c, out1);
|
||||
#define out2c(c) outc(c, out2);
|
||||
|
||||
#define OUTPUT_INCL
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
/* $NetBSD: parser.h,v 1.11 1996/10/16 15:45:15 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* control characters in argument strings */
|
||||
#define CTLESC '\201'
|
||||
#define CTLVAR '\202'
|
||||
#define CTLENDVAR '\203'
|
||||
#define CTLBACKQ '\204'
|
||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||
#define CTLARI '\206'
|
||||
#define CTLENDARI '\207'
|
||||
|
||||
/* variable substitution byte (follows CTLVAR) */
|
||||
#define VSTYPE 0x0f /* type of variable substitution */
|
||||
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
||||
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
||||
|
||||
/* values of VSTYPE field */
|
||||
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
||||
#define VSMINUS 0x2 /* ${var-text} */
|
||||
#define VSPLUS 0x3 /* ${var+text} */
|
||||
#define VSQUESTION 0x4 /* ${var?message} */
|
||||
#define VSASSIGN 0x5 /* ${var=text} */
|
||||
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
|
||||
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
|
||||
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
|
||||
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
|
||||
#define VSLENGTH 0xa /* ${#var} */
|
||||
|
||||
|
||||
/*
|
||||
* NEOF is returned by parsecmd when it encounters an end of file. It
|
||||
* must be distinct from NULL, so we use the address of a variable that
|
||||
* happens to be handy.
|
||||
*/
|
||||
extern int tokpushback;
|
||||
#define NEOF ((union node *)&tokpushback)
|
||||
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||
|
||||
|
||||
union node *parsecmd __P((int));
|
||||
void fixredir __P((union node *, const char *, int));
|
||||
int goodname __P((char *));
|
||||
char *getprompt __P((void *));
|
@ -1,375 +0,0 @@
|
||||
/* $NetBSD: redir.c,v 1.16 1997/07/04 21:02:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: redir.c,v 1.16 1997/07/04 21:02:21 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Code for dealing with input/output redirection.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "nodes.h"
|
||||
#include "jobs.h"
|
||||
#include "expand.h"
|
||||
#include "redir.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||
#define PIPESIZE 4096 /* amount of buffering in a pipe */
|
||||
|
||||
|
||||
MKINIT
|
||||
struct redirtab {
|
||||
struct redirtab *next;
|
||||
short renamed[10];
|
||||
};
|
||||
|
||||
|
||||
MKINIT struct redirtab *redirlist;
|
||||
|
||||
/*
|
||||
* We keep track of whether or not fd0 has been redirected. This is for
|
||||
* background commands, where we want to redirect fd0 to /dev/null only
|
||||
* if it hasn't already been redirected.
|
||||
*/
|
||||
int fd0_redirected = 0;
|
||||
|
||||
STATIC void openredirect __P((union node *, char[10 ]));
|
||||
STATIC int openhere __P((union node *));
|
||||
|
||||
|
||||
/*
|
||||
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
|
||||
* old file descriptors are stashed away so that the redirection can be
|
||||
* undone by calling popredir. If the REDIR_BACKQ flag is set, then the
|
||||
* standard output, and the standard error if it becomes a duplicate of
|
||||
* stdout, is saved in memory.
|
||||
*/
|
||||
|
||||
void
|
||||
redirect(redir, flags)
|
||||
union node *redir;
|
||||
int flags;
|
||||
{
|
||||
union node *n;
|
||||
struct redirtab *sv = NULL;
|
||||
int i;
|
||||
int fd;
|
||||
int try;
|
||||
char memory[10]; /* file descriptors to write to memory */
|
||||
|
||||
for (i = 10 ; --i >= 0 ; )
|
||||
memory[i] = 0;
|
||||
memory[1] = flags & REDIR_BACKQ;
|
||||
if (flags & REDIR_PUSH) {
|
||||
sv = ckmalloc(sizeof (struct redirtab));
|
||||
for (i = 0 ; i < 10 ; i++)
|
||||
sv->renamed[i] = EMPTY;
|
||||
sv->next = redirlist;
|
||||
redirlist = sv;
|
||||
}
|
||||
for (n = redir ; n ; n = n->nfile.next) {
|
||||
fd = n->nfile.fd;
|
||||
try = 0;
|
||||
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
||||
n->ndup.dupfd == fd)
|
||||
continue; /* redirect from/to same file descriptor */
|
||||
|
||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
||||
INTOFF;
|
||||
again:
|
||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
if (!try) {
|
||||
openredirect(n, memory);
|
||||
try++;
|
||||
goto again;
|
||||
}
|
||||
/* FALLTHROUGH*/
|
||||
default:
|
||||
INTON;
|
||||
error("%d: %s", fd, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!try) {
|
||||
sv->renamed[fd] = i;
|
||||
close(fd);
|
||||
}
|
||||
INTON;
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
if (fd == 0)
|
||||
fd0_redirected++;
|
||||
if (!try)
|
||||
openredirect(n, memory);
|
||||
}
|
||||
if (memory[1])
|
||||
out1 = &memout;
|
||||
if (memory[2])
|
||||
out2 = &memout;
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
openredirect(redir, memory)
|
||||
union node *redir;
|
||||
char memory[10];
|
||||
{
|
||||
int fd = redir->nfile.fd;
|
||||
char *fname;
|
||||
int f;
|
||||
|
||||
/*
|
||||
* We suppress interrupts so that we won't leave open file
|
||||
* descriptors around. This may not be such a good idea because
|
||||
* an open of a device or a fifo can block indefinitely.
|
||||
*/
|
||||
INTOFF;
|
||||
memory[fd] = 0;
|
||||
switch (redir->nfile.type) {
|
||||
case NFROM:
|
||||
fname = redir->nfile.expfname;
|
||||
if ((f = open(fname, O_RDONLY)) < 0)
|
||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
||||
movefd:
|
||||
if (f != fd) {
|
||||
copyfd(f, fd);
|
||||
close(f);
|
||||
}
|
||||
break;
|
||||
case NTO:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_CREAT
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#endif
|
||||
goto movefd;
|
||||
case NAPPEND:
|
||||
fname = redir->nfile.expfname;
|
||||
#ifdef O_APPEND
|
||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
#else
|
||||
if ((f = open(fname, O_WRONLY)) < 0
|
||||
&& (f = creat(fname, 0666)) < 0)
|
||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||
lseek(f, (off_t)0, 2);
|
||||
#endif
|
||||
goto movefd;
|
||||
case NTOFD:
|
||||
case NFROMFD:
|
||||
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
|
||||
if (memory[redir->ndup.dupfd])
|
||||
memory[fd] = 1;
|
||||
else
|
||||
copyfd(redir->ndup.dupfd, fd);
|
||||
}
|
||||
break;
|
||||
case NHERE:
|
||||
case NXHERE:
|
||||
f = openhere(redir);
|
||||
goto movefd;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle here documents. Normally we fork off a process to write the
|
||||
* data to a pipe. If the document is short, we can stuff the data in
|
||||
* the pipe without forking.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
openhere(redir)
|
||||
union node *redir;
|
||||
{
|
||||
int pip[2];
|
||||
int len = 0;
|
||||
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed");
|
||||
if (redir->type == NHERE) {
|
||||
len = strlen(redir->nhere.doc->narg.text);
|
||||
if (len <= PIPESIZE) {
|
||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
|
||||
close(pip[0]);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
if (redir->type == NHERE)
|
||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||
else
|
||||
expandhere(redir->nhere.doc, pip[1]);
|
||||
_exit(0);
|
||||
}
|
||||
out:
|
||||
close(pip[1]);
|
||||
return pip[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Undo the effects of the last redirection.
|
||||
*/
|
||||
|
||||
void
|
||||
popredir() {
|
||||
struct redirtab *rp = redirlist;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (rp->renamed[i] != EMPTY) {
|
||||
if (i == 0)
|
||||
fd0_redirected--;
|
||||
close(i);
|
||||
if (rp->renamed[i] >= 0) {
|
||||
copyfd(rp->renamed[i], i);
|
||||
close(rp->renamed[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
INTOFF;
|
||||
redirlist = rp->next;
|
||||
ckfree(rp);
|
||||
INTON;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo all redirections. Called on error or interrupt.
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
|
||||
INCLUDE "redir.h"
|
||||
|
||||
RESET {
|
||||
while (redirlist)
|
||||
popredir();
|
||||
}
|
||||
|
||||
SHELLPROC {
|
||||
clearredir();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Return true if fd 0 has already been redirected at least once. */
|
||||
int
|
||||
fd0_redirected_p () {
|
||||
return fd0_redirected != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard all saved file descriptors.
|
||||
*/
|
||||
|
||||
void
|
||||
clearredir() {
|
||||
struct redirtab *rp;
|
||||
int i;
|
||||
|
||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
if (rp->renamed[i] >= 0) {
|
||||
close(rp->renamed[i]);
|
||||
}
|
||||
rp->renamed[i] = EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy a file descriptor to be >= to. Returns -1
|
||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
||||
* file descriptors left.
|
||||
*/
|
||||
|
||||
int
|
||||
copyfd(from, to)
|
||||
int from;
|
||||
int to;
|
||||
{
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(from, F_DUPFD, to);
|
||||
if (newfd < 0) {
|
||||
if (errno == EMFILE)
|
||||
return EMPTY;
|
||||
else
|
||||
error("%d: %s", from, strerror(errno));
|
||||
}
|
||||
return newfd;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/* $NetBSD: redir.h,v 1.10 1996/10/16 15:45:18 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/* flags passed to redirect */
|
||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||
|
||||
union node;
|
||||
void redirect __P((union node *, int));
|
||||
void popredir __P((void));
|
||||
int fd0_redirected_p __P((void));
|
||||
void clearredir __P((void));
|
||||
int copyfd __P((int, int));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,83 +0,0 @@
|
||||
/* $NetBSD: shell.h,v 1.10 1996/10/16 15:21:49 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* The follow should be set to reflect the type of system you have:
|
||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
||||
* define BSD if you are running 4.2 BSD or later.
|
||||
* define SYSV if you are running under System V.
|
||||
* define DEBUG=1 to compile in debugging (set global "debug" to turn on)
|
||||
* define DEBUG=2 to compile in and turn on debugging.
|
||||
*
|
||||
* When debugging is on, debugging info will be written to $HOME/trace and
|
||||
* a quit signal will generate a core dump.
|
||||
*/
|
||||
|
||||
|
||||
#define JOBS 1
|
||||
#ifndef BSD
|
||||
#define BSD 1
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
#else /* not __STDC__ */
|
||||
typedef char *pointer;
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif /* not __STDC__ */
|
||||
#define STATIC /* empty */
|
||||
#define MKINIT /* empty */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACE(param) trace param
|
||||
#else
|
||||
#define TRACE(param)
|
||||
#endif
|
@ -1,446 +0,0 @@
|
||||
/* $NetBSD: show.c,v 1.15 1997/07/04 21:02:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: show.c,v 1.15 1997/07/04 21:02:22 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
#include "parser.h"
|
||||
#include "nodes.h"
|
||||
#include "mystring.h"
|
||||
#include "show.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static void shtree __P((union node *, int, char *, FILE*));
|
||||
static void shcmd __P((union node *, FILE *));
|
||||
static void sharg __P((union node *, FILE *));
|
||||
static void indent __P((int, char *, FILE *));
|
||||
static void trstring __P((char *));
|
||||
|
||||
|
||||
void
|
||||
showtree(n)
|
||||
union node *n;
|
||||
{
|
||||
trputs("showtree called\n");
|
||||
shtree(n, 1, NULL, stdout);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
shtree(n, ind, pfx, fp)
|
||||
union node *n;
|
||||
int ind;
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
struct nodelist *lp;
|
||||
char *s;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
indent(ind, pfx, fp);
|
||||
switch(n->type) {
|
||||
case NSEMI:
|
||||
s = "; ";
|
||||
goto binop;
|
||||
case NAND:
|
||||
s = " && ";
|
||||
goto binop;
|
||||
case NOR:
|
||||
s = " || ";
|
||||
binop:
|
||||
shtree(n->nbinary.ch1, ind, NULL, fp);
|
||||
/* if (ind < 0) */
|
||||
fputs(s, fp);
|
||||
shtree(n->nbinary.ch2, ind, NULL, fp);
|
||||
break;
|
||||
case NCMD:
|
||||
shcmd(n, fp);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case NPIPE:
|
||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
|
||||
shcmd(lp->n, fp);
|
||||
if (lp->next)
|
||||
fputs(" | ", fp);
|
||||
}
|
||||
if (n->npipe.backgnd)
|
||||
fputs(" &", fp);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "<node type %d>", n->type);
|
||||
if (ind >= 0)
|
||||
putc('\n', fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
shcmd(cmd, fp)
|
||||
union node *cmd;
|
||||
FILE *fp;
|
||||
{
|
||||
union node *np;
|
||||
int first;
|
||||
char *s;
|
||||
int dftfd;
|
||||
|
||||
first = 1;
|
||||
for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
|
||||
if (! first)
|
||||
putchar(' ');
|
||||
sharg(np, fp);
|
||||
first = 0;
|
||||
}
|
||||
for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
|
||||
if (! first)
|
||||
putchar(' ');
|
||||
switch (np->nfile.type) {
|
||||
case NTO: s = ">"; dftfd = 1; break;
|
||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||
case NFROM: s = "<"; dftfd = 0; break;
|
||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
||||
default: s = "*error*"; dftfd = 0; break;
|
||||
}
|
||||
if (np->nfile.fd != dftfd)
|
||||
fprintf(fp, "%d", np->nfile.fd);
|
||||
fputs(s, fp);
|
||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
||||
fprintf(fp, "%d", np->ndup.dupfd);
|
||||
} else {
|
||||
sharg(np->nfile.fname, fp);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sharg(arg, fp)
|
||||
union node *arg;
|
||||
FILE *fp;
|
||||
{
|
||||
char *p;
|
||||
struct nodelist *bqlist;
|
||||
int subtype;
|
||||
|
||||
if (arg->type != NARG) {
|
||||
printf("<node type %d>\n", arg->type);
|
||||
fflush(stdout);
|
||||
abort();
|
||||
}
|
||||
bqlist = arg->narg.backquote;
|
||||
for (p = arg->narg.text ; *p ; p++) {
|
||||
switch (*p) {
|
||||
case CTLESC:
|
||||
putc(*++p, fp);
|
||||
break;
|
||||
case CTLVAR:
|
||||
putc('$', fp);
|
||||
putc('{', fp);
|
||||
subtype = *++p;
|
||||
if (subtype == VSLENGTH)
|
||||
putc('#', fp);
|
||||
|
||||
while (*p != '=')
|
||||
putc(*p++, fp);
|
||||
|
||||
if (subtype & VSNUL)
|
||||
putc(':', fp);
|
||||
|
||||
switch (subtype & VSTYPE) {
|
||||
case VSNORMAL:
|
||||
putc('}', fp);
|
||||
break;
|
||||
case VSMINUS:
|
||||
putc('-', fp);
|
||||
break;
|
||||
case VSPLUS:
|
||||
putc('+', fp);
|
||||
break;
|
||||
case VSQUESTION:
|
||||
putc('?', fp);
|
||||
break;
|
||||
case VSASSIGN:
|
||||
putc('=', fp);
|
||||
break;
|
||||
case VSTRIMLEFT:
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMLEFTMAX:
|
||||
putc('#', fp);
|
||||
putc('#', fp);
|
||||
break;
|
||||
case VSTRIMRIGHT:
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSTRIMRIGHTMAX:
|
||||
putc('%', fp);
|
||||
putc('%', fp);
|
||||
break;
|
||||
case VSLENGTH:
|
||||
break;
|
||||
default:
|
||||
printf("<subtype %d>", subtype);
|
||||
}
|
||||
break;
|
||||
case CTLENDVAR:
|
||||
putc('}', fp);
|
||||
break;
|
||||
case CTLBACKQ:
|
||||
case CTLBACKQ|CTLQUOTE:
|
||||
putc('$', fp);
|
||||
putc('(', fp);
|
||||
shtree(bqlist->n, -1, NULL, fp);
|
||||
putc(')', fp);
|
||||
break;
|
||||
default:
|
||||
putc(*p, fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
indent(amount, pfx, fp)
|
||||
int amount;
|
||||
char *pfx;
|
||||
FILE *fp;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < amount ; i++) {
|
||||
if (pfx && i == amount - 1)
|
||||
fputs(pfx, fp);
|
||||
putc('\t', fp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Debugging stuff.
|
||||
*/
|
||||
|
||||
|
||||
FILE *tracefile;
|
||||
|
||||
#if DEBUG == 2
|
||||
int debug = 1;
|
||||
#else
|
||||
int debug = 0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
trputc(c)
|
||||
int c;
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc(c, tracefile);
|
||||
if (c == '\n')
|
||||
fflush(tracefile);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
trace(const char *fmt, ...)
|
||||
#else
|
||||
trace(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG
|
||||
va_list va;
|
||||
#ifdef __STDC__
|
||||
va_start(va, fmt);
|
||||
#else
|
||||
char *fmt;
|
||||
va_start(va);
|
||||
fmt = va_arg(va, char *);
|
||||
#endif
|
||||
if (tracefile != NULL) {
|
||||
(void) vfprintf(tracefile, fmt, va);
|
||||
if (strchr(fmt, '\n'))
|
||||
(void) fflush(tracefile);
|
||||
}
|
||||
va_end(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
trputs(s)
|
||||
char *s;
|
||||
{
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
fputs(s, tracefile);
|
||||
if (strchr(s, '\n'))
|
||||
fflush(tracefile);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
trstring(s)
|
||||
char *s;
|
||||
{
|
||||
char *p;
|
||||
char c;
|
||||
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
putc('"', tracefile);
|
||||
for (p = s ; *p ; p++) {
|
||||
switch (*p) {
|
||||
case '\n': c = 'n'; goto backslash;
|
||||
case '\t': c = 't'; goto backslash;
|
||||
case '\r': c = 'r'; goto backslash;
|
||||
case '"': c = '"'; goto backslash;
|
||||
case '\\': c = '\\'; goto backslash;
|
||||
case CTLESC: c = 'e'; goto backslash;
|
||||
case CTLVAR: c = 'v'; goto backslash;
|
||||
case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
|
||||
case CTLBACKQ: c = 'q'; goto backslash;
|
||||
case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
|
||||
backslash: putc('\\', tracefile);
|
||||
putc(c, tracefile);
|
||||
break;
|
||||
default:
|
||||
if (*p >= ' ' && *p <= '~')
|
||||
putc(*p, tracefile);
|
||||
else {
|
||||
putc('\\', tracefile);
|
||||
putc(*p >> 6 & 03, tracefile);
|
||||
putc(*p >> 3 & 07, tracefile);
|
||||
putc(*p & 07, tracefile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc('"', tracefile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
trargs(ap)
|
||||
char **ap;
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (tracefile == NULL)
|
||||
return;
|
||||
while (*ap) {
|
||||
trstring(*ap++);
|
||||
if (*ap)
|
||||
putc(' ', tracefile);
|
||||
else
|
||||
putc('\n', tracefile);
|
||||
}
|
||||
fflush(tracefile);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
opentrace() {
|
||||
char s[100];
|
||||
char *getenv();
|
||||
#ifdef O_APPEND
|
||||
int flags;
|
||||
#endif
|
||||
|
||||
if (!debug)
|
||||
return;
|
||||
#ifdef not_this_way
|
||||
{
|
||||
char *p;
|
||||
if ((p = getenv("HOME")) == NULL) {
|
||||
if (geteuid() == 0)
|
||||
p = "/";
|
||||
else
|
||||
p = "/tmp";
|
||||
}
|
||||
scopy(p, s);
|
||||
strcat(s, "/trace");
|
||||
}
|
||||
#else
|
||||
scopy("./trace", s);
|
||||
#endif /* not_this_way */
|
||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", s);
|
||||
return;
|
||||
}
|
||||
#ifdef O_APPEND
|
||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||
#endif
|
||||
fputs("\nTracing started.\n", tracefile);
|
||||
fflush(tracefile);
|
||||
}
|
||||
#endif /* DEBUG */
|
@ -1,46 +0,0 @@
|
||||
/* $NetBSD: show.h,v 1.3 1997/04/11 22:58:40 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
union node;
|
||||
void showtree __P((union node *));
|
||||
void trace __P((const char *, ...));
|
||||
void trargs __P((char **));
|
||||
#ifdef DEBUG
|
||||
void trputc __P((int));
|
||||
void trputs __P((char *));
|
||||
void opentrace __P((void));
|
||||
#endif
|
@ -1,383 +0,0 @@
|
||||
/* $NetBSD: trap.c,v 1.17 1997/07/04 21:02:24 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: trap.c,v 1.17 1997/07/04 21:02:24 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "main.h"
|
||||
#include "nodes.h" /* for other headers */
|
||||
#include "eval.h"
|
||||
#include "jobs.h"
|
||||
#include "show.h"
|
||||
#include "options.h"
|
||||
#include "syntax.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "trap.h"
|
||||
#include "mystring.h"
|
||||
|
||||
|
||||
/*
|
||||
* Sigmode records the current value of the signal handlers for the various
|
||||
* modes. A value of zero means that the current handler is not known.
|
||||
* S_HARD_IGN indicates that the signal was ignored on entry to the shell,
|
||||
*/
|
||||
|
||||
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
||||
#define S_CATCH 2 /* signal is caught */
|
||||
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
||||
#define S_HARD_IGN 4 /* signal is ignored permenantly */
|
||||
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
||||
|
||||
|
||||
extern char nullstr[1]; /* null string */
|
||||
|
||||
char *trap[NSIG+1]; /* trap handler commands */
|
||||
MKINIT char sigmode[NSIG]; /* current value of signal */
|
||||
char gotsig[NSIG]; /* indicates specified signal received */
|
||||
int pendingsigs; /* indicates some signal received */
|
||||
|
||||
static int getsigaction __P((int, sig_t *));
|
||||
|
||||
/*
|
||||
* The trap builtin.
|
||||
*/
|
||||
|
||||
int
|
||||
trapcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *action;
|
||||
char **ap;
|
||||
int signo;
|
||||
|
||||
if (argc <= 1) {
|
||||
for (signo = 0 ; signo <= NSIG ; signo++) {
|
||||
if (trap[signo] != NULL)
|
||||
out1fmt("%d: %s\n", signo, trap[signo]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ap = argv + 1;
|
||||
if (is_number(*ap))
|
||||
action = NULL;
|
||||
else
|
||||
action = *ap++;
|
||||
while (*ap) {
|
||||
if ((signo = number(*ap)) < 0 || signo > NSIG)
|
||||
error("%s: bad trap", *ap);
|
||||
INTOFF;
|
||||
if (action)
|
||||
action = savestr(action);
|
||||
if (trap[signo])
|
||||
ckfree(trap[signo]);
|
||||
trap[signo] = action;
|
||||
if (signo != 0)
|
||||
setsignal(signo);
|
||||
INTON;
|
||||
ap++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Clear traps on a fork.
|
||||
*/
|
||||
|
||||
void
|
||||
clear_traps() {
|
||||
char **tp;
|
||||
|
||||
for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
|
||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||
INTOFF;
|
||||
ckfree(*tp);
|
||||
*tp = NULL;
|
||||
if (tp != &trap[0])
|
||||
setsignal(tp - trap);
|
||||
INTON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set the signal handler for the specified signal. The routine figures
|
||||
* out what it should be set to.
|
||||
*/
|
||||
|
||||
long
|
||||
setsignal(signo)
|
||||
int signo;
|
||||
{
|
||||
int action;
|
||||
sig_t sigact = SIG_DFL;
|
||||
char *t;
|
||||
|
||||
if ((t = trap[signo]) == NULL)
|
||||
action = S_DFL;
|
||||
else if (*t != '\0')
|
||||
action = S_CATCH;
|
||||
else
|
||||
action = S_IGN;
|
||||
if (rootshell && action == S_DFL) {
|
||||
switch (signo) {
|
||||
case SIGINT:
|
||||
if (iflag)
|
||||
action = S_CATCH;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#ifdef DEBUG
|
||||
{
|
||||
extern int debug;
|
||||
|
||||
if (debug)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
case SIGTERM:
|
||||
if (iflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#if JOBS
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
if (mflag)
|
||||
action = S_IGN;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
t = &sigmode[signo - 1];
|
||||
if (*t == 0) {
|
||||
/*
|
||||
* current setting unknown
|
||||
*/
|
||||
if (!getsigaction(signo, &sigact)) {
|
||||
/*
|
||||
* Pretend it worked; maybe we should give a warning
|
||||
* here, but other shells don't. We don't alter
|
||||
* sigmode, so that we retry every time.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (sigact == SIG_IGN) {
|
||||
if (mflag && (signo == SIGTSTP ||
|
||||
signo == SIGTTIN || signo == SIGTTOU)) {
|
||||
*t = S_IGN; /* don't hard ignore these */
|
||||
} else
|
||||
*t = S_HARD_IGN;
|
||||
} else {
|
||||
*t = S_RESET; /* force to be set */
|
||||
}
|
||||
}
|
||||
if (*t == S_HARD_IGN || *t == action)
|
||||
return 0;
|
||||
switch (action) {
|
||||
case S_DFL: sigact = SIG_DFL; break;
|
||||
case S_CATCH: sigact = onsig; break;
|
||||
case S_IGN: sigact = SIG_IGN; break;
|
||||
}
|
||||
*t = action;
|
||||
return (long)signal(signo, sigact);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current setting for sig w/o changing it.
|
||||
*/
|
||||
static int
|
||||
getsigaction(signo, sigact)
|
||||
int signo;
|
||||
sig_t *sigact;
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
|
||||
return 0;
|
||||
*sigact = (sig_t) sa.sa_handler;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore a signal.
|
||||
*/
|
||||
|
||||
void
|
||||
ignoresig(signo)
|
||||
int signo;
|
||||
{
|
||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
|
||||
signal(signo, SIG_IGN);
|
||||
}
|
||||
sigmode[signo - 1] = S_HARD_IGN;
|
||||
}
|
||||
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE <signal.h>
|
||||
INCLUDE "trap.h"
|
||||
|
||||
SHELLPROC {
|
||||
char *sm;
|
||||
|
||||
clear_traps();
|
||||
for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
|
||||
if (*sm == S_IGN)
|
||||
*sm = S_HARD_IGN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Signal handler.
|
||||
*/
|
||||
|
||||
void
|
||||
onsig(signo)
|
||||
int signo;
|
||||
{
|
||||
signal(signo, onsig);
|
||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
||||
onint();
|
||||
return;
|
||||
}
|
||||
gotsig[signo - 1] = 1;
|
||||
pendingsigs++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
||||
* handlers while we are executing a trap handler.
|
||||
*/
|
||||
|
||||
void
|
||||
dotrap() {
|
||||
int i;
|
||||
int savestatus;
|
||||
|
||||
for (;;) {
|
||||
for (i = 1 ; ; i++) {
|
||||
if (gotsig[i - 1])
|
||||
break;
|
||||
if (i >= NSIG)
|
||||
goto done;
|
||||
}
|
||||
gotsig[i - 1] = 0;
|
||||
savestatus=exitstatus;
|
||||
evalstring(trap[i]);
|
||||
exitstatus=savestatus;
|
||||
}
|
||||
done:
|
||||
pendingsigs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Controls whether the shell is interactive or not.
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
setinteractive(on)
|
||||
int on;
|
||||
{
|
||||
static int is_interactive;
|
||||
|
||||
if (on == is_interactive)
|
||||
return;
|
||||
setsignal(SIGINT);
|
||||
setsignal(SIGQUIT);
|
||||
setsignal(SIGTERM);
|
||||
is_interactive = on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called to exit the shell.
|
||||
*/
|
||||
|
||||
void
|
||||
exitshell(status)
|
||||
int status;
|
||||
{
|
||||
struct jmploc loc1, loc2;
|
||||
char *p;
|
||||
|
||||
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
|
||||
if (setjmp(loc1.loc)) {
|
||||
goto l1;
|
||||
}
|
||||
if (setjmp(loc2.loc)) {
|
||||
goto l2;
|
||||
}
|
||||
handler = &loc1;
|
||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||
trap[0] = NULL;
|
||||
evalstring(p);
|
||||
}
|
||||
l1: handler = &loc2; /* probably unnecessary */
|
||||
flushall();
|
||||
#if JOBS
|
||||
setjobctl(0);
|
||||
#endif
|
||||
l2: _exit(status);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/* $NetBSD: trap.h,v 1.11 1996/10/16 15:45:20 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||
*/
|
||||
|
||||
extern int pendingsigs;
|
||||
|
||||
int trapcmd __P((int, char **));
|
||||
void clear_traps __P((void));
|
||||
long setsignal __P((int));
|
||||
void ignoresig __P((int));
|
||||
void onsig __P((int));
|
||||
void dotrap __P((void));
|
||||
void setinteractive __P((int));
|
||||
void exitshell __P((int));
|
@ -1,754 +0,0 @@
|
||||
/* $NetBSD: var.c,v 1.19 1997/07/04 21:02:25 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: var.c,v 1.19 1997/07/04 21:02:25 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
#include "shell.h"
|
||||
#include "output.h"
|
||||
#include "expand.h"
|
||||
#include "nodes.h" /* for other headers */
|
||||
#include "eval.h" /* defines cmdenviron */
|
||||
#include "exec.h"
|
||||
#include "syntax.h"
|
||||
#include "options.h"
|
||||
#include "mail.h"
|
||||
#include "var.h"
|
||||
#include "memalloc.h"
|
||||
#include "error.h"
|
||||
#include "mystring.h"
|
||||
#include "parser.h"
|
||||
#ifndef SMALL
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define VTABSIZE 39
|
||||
|
||||
|
||||
struct varinit {
|
||||
struct var *var;
|
||||
int flags;
|
||||
char *text;
|
||||
void (*func) __P((const char *));
|
||||
};
|
||||
|
||||
|
||||
#if ATTY
|
||||
struct var vatty;
|
||||
#endif
|
||||
#ifndef SMALL
|
||||
struct var vhistsize;
|
||||
struct var vterm;
|
||||
#endif
|
||||
struct var vifs;
|
||||
struct var vmail;
|
||||
struct var vmpath;
|
||||
struct var vpath;
|
||||
struct var vps1;
|
||||
struct var vps2;
|
||||
struct var vvers;
|
||||
struct var voptind;
|
||||
|
||||
const struct varinit varinit[] = {
|
||||
#if ATTY
|
||||
{ &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
|
||||
NULL },
|
||||
#endif
|
||||
#ifndef SMALL
|
||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||
sethistsize },
|
||||
#endif
|
||||
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
||||
NULL },
|
||||
{ &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
|
||||
NULL },
|
||||
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
||||
NULL },
|
||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=/bin:/usr/bin",
|
||||
changepath },
|
||||
/*
|
||||
* vps1 depends on uid
|
||||
*/
|
||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||
NULL },
|
||||
#ifndef SMALL
|
||||
{ &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=",
|
||||
setterm },
|
||||
#endif
|
||||
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
|
||||
getoptsreset },
|
||||
{ NULL, 0, NULL,
|
||||
NULL }
|
||||
};
|
||||
|
||||
struct var *vartab[VTABSIZE];
|
||||
|
||||
STATIC struct var **hashvar __P((char *));
|
||||
STATIC int varequal __P((char *, char *));
|
||||
|
||||
/*
|
||||
* Initialize the varable symbol tables and import the environment
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
INCLUDE "var.h"
|
||||
INIT {
|
||||
char **envp;
|
||||
extern char **environ;
|
||||
|
||||
initvar();
|
||||
for (envp = environ ; *envp ; envp++) {
|
||||
if (strchr(*envp, '=')) {
|
||||
setvareq(*envp, VEXPORT|VTEXTFIXED);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This routine initializes the builtin variables. It is called when the
|
||||
* shell is initialized and again when a shell procedure is spawned.
|
||||
*/
|
||||
|
||||
void
|
||||
initvar() {
|
||||
const struct varinit *ip;
|
||||
struct var *vp;
|
||||
struct var **vpp;
|
||||
|
||||
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
|
||||
if ((vp->flags & VEXPORT) == 0) {
|
||||
vpp = hashvar(ip->text);
|
||||
vp->next = *vpp;
|
||||
*vpp = vp;
|
||||
vp->text = ip->text;
|
||||
vp->flags = ip->flags;
|
||||
vp->func = ip->func;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* PS1 depends on uid
|
||||
*/
|
||||
if ((vps1.flags & VEXPORT) == 0) {
|
||||
vpp = hashvar("PS1=");
|
||||
vps1.next = *vpp;
|
||||
*vpp = &vps1;
|
||||
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
|
||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe version of setvar, returns 1 on success 0 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
setvarsafe(name, val, flags)
|
||||
char *name, *val;
|
||||
int flags;
|
||||
{
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *volatile savehandler = handler;
|
||||
int err = 0;
|
||||
#ifdef __GNUC__
|
||||
(void) &err;
|
||||
#endif
|
||||
|
||||
if (setjmp(jmploc.loc))
|
||||
err = 1;
|
||||
else {
|
||||
handler = &jmploc;
|
||||
setvar(name, val, flags);
|
||||
}
|
||||
handler = savehandler;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the value of a variable. The flags argument is ored with the
|
||||
* flags of the variable. If val is NULL, the variable is unset.
|
||||
*/
|
||||
|
||||
void
|
||||
setvar(name, val, flags)
|
||||
char *name, *val;
|
||||
int flags;
|
||||
{
|
||||
char *p, *q;
|
||||
int len;
|
||||
int namelen;
|
||||
char *nameeq;
|
||||
int isbad;
|
||||
|
||||
isbad = 0;
|
||||
p = name;
|
||||
if (! is_name(*p))
|
||||
isbad = 1;
|
||||
p++;
|
||||
for (;;) {
|
||||
if (! is_in_name(*p)) {
|
||||
if (*p == '\0' || *p == '=')
|
||||
break;
|
||||
isbad = 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
namelen = p - name;
|
||||
if (isbad)
|
||||
error("%.*s: bad variable name", namelen, name);
|
||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
||||
if (val == NULL) {
|
||||
flags |= VUNSET;
|
||||
} else {
|
||||
len += strlen(val);
|
||||
}
|
||||
p = nameeq = ckmalloc(len);
|
||||
q = name;
|
||||
while (--namelen >= 0)
|
||||
*p++ = *q++;
|
||||
*p++ = '=';
|
||||
*p = '\0';
|
||||
if (val)
|
||||
scopy(val, p);
|
||||
setvareq(nameeq, flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Same as setvar except that the variable and value are passed in
|
||||
* the first argument as name=value. Since the first argument will
|
||||
* be actually stored in the table, it should not be a string that
|
||||
* will go away.
|
||||
*/
|
||||
|
||||
void
|
||||
setvareq(s, flags)
|
||||
char *s;
|
||||
int flags;
|
||||
{
|
||||
struct var *vp, **vpp;
|
||||
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(s, vp->text)) {
|
||||
if (vp->flags & VREADONLY) {
|
||||
size_t len = strchr(s, '=') - s;
|
||||
error("%.*s: is read only", len, s);
|
||||
}
|
||||
INTOFF;
|
||||
|
||||
if (vp->func && (flags & VNOFUNC) == 0)
|
||||
(*vp->func)(strchr(s, '=') + 1);
|
||||
|
||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||
ckfree(vp->text);
|
||||
|
||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||
vp->flags |= flags;
|
||||
vp->text = s;
|
||||
|
||||
/*
|
||||
* We could roll this to a function, to handle it as
|
||||
* a regular variable function callback, but why bother?
|
||||
*/
|
||||
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
||||
chkmail(1);
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
vp = ckmalloc(sizeof (*vp));
|
||||
vp->flags = flags;
|
||||
vp->text = s;
|
||||
vp->next = *vpp;
|
||||
vp->func = NULL;
|
||||
*vpp = vp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Process a linked list of variable assignments.
|
||||
*/
|
||||
|
||||
void
|
||||
listsetvar(list)
|
||||
struct strlist *list;
|
||||
{
|
||||
struct strlist *lp;
|
||||
|
||||
INTOFF;
|
||||
for (lp = list ; lp ; lp = lp->next) {
|
||||
setvareq(savestr(lp->text), 0);
|
||||
}
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Find the value of a variable. Returns NULL if not set.
|
||||
*/
|
||||
|
||||
char *
|
||||
lookupvar(name)
|
||||
char *name;
|
||||
{
|
||||
struct var *v;
|
||||
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
if (varequal(v->text, name)) {
|
||||
if (v->flags & VUNSET)
|
||||
return NULL;
|
||||
return strchr(v->text, '=') + 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Search the environment of a builtin command. If the second argument
|
||||
* is nonzero, return the value of a variable even if it hasn't been
|
||||
* exported.
|
||||
*/
|
||||
|
||||
char *
|
||||
bltinlookup(name, doall)
|
||||
char *name;
|
||||
int doall;
|
||||
{
|
||||
struct strlist *sp;
|
||||
struct var *v;
|
||||
|
||||
for (sp = cmdenviron ; sp ; sp = sp->next) {
|
||||
if (varequal(sp->text, name))
|
||||
return strchr(sp->text, '=') + 1;
|
||||
}
|
||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||
if (varequal(v->text, name)) {
|
||||
if ((v->flags & VUNSET)
|
||||
|| (!doall && (v->flags & VEXPORT) == 0))
|
||||
return NULL;
|
||||
return strchr(v->text, '=') + 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Generate a list of exported variables. This routine is used to construct
|
||||
* the third argument to execve when executing a program.
|
||||
*/
|
||||
|
||||
char **
|
||||
environment() {
|
||||
int nenv;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
char **env, **ep;
|
||||
|
||||
nenv = 0;
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next)
|
||||
if (vp->flags & VEXPORT)
|
||||
nenv++;
|
||||
}
|
||||
ep = env = stalloc((nenv + 1) * sizeof *env);
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next)
|
||||
if (vp->flags & VEXPORT)
|
||||
*ep++ = vp->text;
|
||||
}
|
||||
*ep = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when a shell procedure is invoked to clear out nonexported
|
||||
* variables. It is also necessary to reallocate variables of with
|
||||
* VSTACK set since these are currently allocated on the stack.
|
||||
*/
|
||||
|
||||
#ifdef mkinit
|
||||
MKINIT void shprocvar __P((void));
|
||||
|
||||
SHELLPROC {
|
||||
shprocvar();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
shprocvar() {
|
||||
struct var **vpp;
|
||||
struct var *vp, **prev;
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (prev = vpp ; (vp = *prev) != NULL ; ) {
|
||||
if ((vp->flags & VEXPORT) == 0) {
|
||||
*prev = vp->next;
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
if ((vp->flags & VSTRFIXED) == 0)
|
||||
ckfree(vp);
|
||||
} else {
|
||||
if (vp->flags & VSTACK) {
|
||||
vp->text = savestr(vp->text);
|
||||
vp->flags &=~ VSTACK;
|
||||
}
|
||||
prev = &vp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
initvar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Command to list all variables which are set. Currently this command
|
||||
* is invoked from the set command when the set command is called without
|
||||
* any variables.
|
||||
*/
|
||||
|
||||
int
|
||||
showvarscmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if ((vp->flags & VUNSET) == 0)
|
||||
out1fmt("%s\n", vp->text);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The export and readonly commands.
|
||||
*/
|
||||
|
||||
int
|
||||
exportcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
char *name;
|
||||
char *p;
|
||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||
|
||||
listsetvar(cmdenviron);
|
||||
if (argc > 1) {
|
||||
while ((name = *argptr++) != NULL) {
|
||||
if ((p = strchr(name, '=')) != NULL) {
|
||||
p++;
|
||||
} else {
|
||||
vpp = hashvar(name);
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (varequal(vp->text, name)) {
|
||||
vp->flags |= flag;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
setvar(name, p, flag);
|
||||
found:;
|
||||
}
|
||||
} else {
|
||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||
if (vp->flags & flag) {
|
||||
for (p = vp->text ; *p != '=' ; p++)
|
||||
out1c(*p);
|
||||
out1c('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The "local" command.
|
||||
*/
|
||||
|
||||
int
|
||||
localcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (! in_function())
|
||||
error("Not in a function");
|
||||
while ((name = *argptr++) != NULL) {
|
||||
mklocal(name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Make a variable a local variable. When a variable is made local, it's
|
||||
* value and flags are saved in a localvar structure. The saved values
|
||||
* will be restored when the shell function returns. We handle the name
|
||||
* "-" as a special case.
|
||||
*/
|
||||
|
||||
void
|
||||
mklocal(name)
|
||||
char *name;
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
INTOFF;
|
||||
lvp = ckmalloc(sizeof (struct localvar));
|
||||
if (name[0] == '-' && name[1] == '\0') {
|
||||
lvp->text = ckmalloc(sizeof optlist);
|
||||
memcpy(lvp->text, optlist, sizeof optlist);
|
||||
vp = NULL;
|
||||
} else {
|
||||
vpp = hashvar(name);
|
||||
for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
|
||||
if (vp == NULL) {
|
||||
if (strchr(name, '='))
|
||||
setvareq(savestr(name), VSTRFIXED);
|
||||
else
|
||||
setvar(name, NULL, VSTRFIXED);
|
||||
vp = *vpp; /* the new variable */
|
||||
lvp->text = NULL;
|
||||
lvp->flags = VUNSET;
|
||||
} else {
|
||||
lvp->text = vp->text;
|
||||
lvp->flags = vp->flags;
|
||||
vp->flags |= VSTRFIXED|VTEXTFIXED;
|
||||
if (strchr(name, '='))
|
||||
setvareq(savestr(name), 0);
|
||||
}
|
||||
}
|
||||
lvp->vp = vp;
|
||||
lvp->next = localvars;
|
||||
localvars = lvp;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called after a function returns.
|
||||
*/
|
||||
|
||||
void
|
||||
poplocalvars() {
|
||||
struct localvar *lvp;
|
||||
struct var *vp;
|
||||
|
||||
while ((lvp = localvars) != NULL) {
|
||||
localvars = lvp->next;
|
||||
vp = lvp->vp;
|
||||
if (vp == NULL) { /* $- saved */
|
||||
memcpy(optlist, lvp->text, sizeof optlist);
|
||||
ckfree(lvp->text);
|
||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||
(void)unsetvar(vp->text);
|
||||
} else {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
vp->flags = lvp->flags;
|
||||
vp->text = lvp->text;
|
||||
}
|
||||
ckfree(lvp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
setvarcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
if (argc <= 2)
|
||||
return unsetcmd(argc, argv);
|
||||
else if (argc == 3)
|
||||
setvar(argv[1], argv[2], 0);
|
||||
else
|
||||
error("List assignment not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The unset builtin command. We unset the function before we unset the
|
||||
* variable to allow a function to be unset when there is a readonly variable
|
||||
* with the same name.
|
||||
*/
|
||||
|
||||
int
|
||||
unsetcmd(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char **ap;
|
||||
int i;
|
||||
int flg_func = 0;
|
||||
int flg_var = 0;
|
||||
int ret = 0;
|
||||
|
||||
while ((i = nextopt("vf")) != '\0') {
|
||||
if (i == 'f')
|
||||
flg_func = 1;
|
||||
else
|
||||
flg_var = 1;
|
||||
}
|
||||
if (flg_func == 0 && flg_var == 0)
|
||||
flg_var = 1;
|
||||
|
||||
for (ap = argptr; *ap ; ap++) {
|
||||
if (flg_func)
|
||||
ret |= unsetfunc(*ap);
|
||||
if (flg_var)
|
||||
ret |= unsetvar(*ap);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unset the specified variable.
|
||||
*/
|
||||
|
||||
int
|
||||
unsetvar(s)
|
||||
char *s;
|
||||
{
|
||||
struct var **vpp;
|
||||
struct var *vp;
|
||||
|
||||
vpp = hashvar(s);
|
||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||
if (varequal(vp->text, s)) {
|
||||
if (vp->flags & VREADONLY)
|
||||
return (1);
|
||||
INTOFF;
|
||||
if (*(strchr(vp->text, '=') + 1) != '\0')
|
||||
setvar(s, nullstr, 0);
|
||||
vp->flags &= ~VEXPORT;
|
||||
vp->flags |= VUNSET;
|
||||
if ((vp->flags & VSTRFIXED) == 0) {
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
*vpp = vp->next;
|
||||
ckfree(vp);
|
||||
}
|
||||
INTON;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Find the appropriate entry in the hash table from the name.
|
||||
*/
|
||||
|
||||
STATIC struct var **
|
||||
hashvar(p)
|
||||
char *p;
|
||||
{
|
||||
unsigned int hashval;
|
||||
|
||||
hashval = ((unsigned char) *p) << 4;
|
||||
while (*p && *p != '=')
|
||||
hashval += (unsigned char) *p++;
|
||||
return &vartab[hashval % VTABSIZE];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the two strings specify the same varable. The first
|
||||
* variable name is terminated by '='; the second may be terminated by
|
||||
* either '=' or '\0'.
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
varequal(p, q)
|
||||
char *p, *q;
|
||||
{
|
||||
while (*p == *q++) {
|
||||
if (*p++ == '=')
|
||||
return 1;
|
||||
}
|
||||
if (*p == '=' && *(q - 1) == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
/* $NetBSD: var.h,v 1.14 1997/04/11 22:45:40 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Shell variables.
|
||||
*/
|
||||
|
||||
/* flags */
|
||||
#define VEXPORT 0x01 /* variable is exported */
|
||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||
#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
|
||||
#define VTEXTFIXED 0x08 /* text is staticly allocated */
|
||||
#define VSTACK 0x10 /* text is allocated on the stack */
|
||||
#define VUNSET 0x20 /* the variable is not set */
|
||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||
|
||||
|
||||
struct var {
|
||||
struct var *next; /* next entry in hash list */
|
||||
int flags; /* flags are defined above */
|
||||
char *text; /* name=value */
|
||||
void (*func) __P((const char *));
|
||||
/* function to be called when */
|
||||
/* the variable gets set/unset */
|
||||
};
|
||||
|
||||
|
||||
struct localvar {
|
||||
struct localvar *next; /* next local variable in list */
|
||||
struct var *vp; /* the variable that was made local */
|
||||
int flags; /* saved flags */
|
||||
char *text; /* saved text */
|
||||
};
|
||||
|
||||
|
||||
struct localvar *localvars;
|
||||
|
||||
#if ATTY
|
||||
extern struct var vatty;
|
||||
#endif
|
||||
extern struct var vifs;
|
||||
extern struct var vmail;
|
||||
extern struct var vmpath;
|
||||
extern struct var vpath;
|
||||
extern struct var vps1;
|
||||
extern struct var vps2;
|
||||
#ifndef SMALL
|
||||
extern struct var vterm;
|
||||
extern struct var vtermcap;
|
||||
extern struct var vhistsize;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following macros access the values of the above variables.
|
||||
* They have to skip over the name. They return the null string
|
||||
* for unset variables.
|
||||
*/
|
||||
|
||||
#define ifsval() (vifs.text + 4)
|
||||
#define mailval() (vmail.text + 5)
|
||||
#define mpathval() (vmpath.text + 9)
|
||||
#define pathval() (vpath.text + 5)
|
||||
#define ps1val() (vps1.text + 4)
|
||||
#define ps2val() (vps2.text + 4)
|
||||
#define optindval() (voptind.text + 7)
|
||||
#ifndef SMALL
|
||||
#define histsizeval() (vhistsize.text + 9)
|
||||
#define termval() (vterm.text + 5)
|
||||
#endif
|
||||
|
||||
#if ATTY
|
||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
||||
#endif
|
||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||
|
||||
void initvar __P((void));
|
||||
void setvar __P((char *, char *, int));
|
||||
void setvareq __P((char *, int));
|
||||
struct strlist;
|
||||
void listsetvar __P((struct strlist *));
|
||||
char *lookupvar __P((char *));
|
||||
char *bltinlookup __P((char *, int));
|
||||
char **environment __P((void));
|
||||
void shprocvar __P((void));
|
||||
int showvarscmd __P((int, char **));
|
||||
int exportcmd __P((int, char **));
|
||||
int localcmd __P((int, char **));
|
||||
void mklocal __P((char *));
|
||||
void poplocalvars __P((void));
|
||||
int setvarcmd __P((int, char **));
|
||||
int unsetcmd __P((int, char **));
|
||||
int unsetvar __P((char *));
|
||||
int setvarsafe __P((char *, char *, int));
|
Loading…
Reference in New Issue
Block a user