Importing bin/sh
/etc/profile enables by default tabcompletion, as well as emacs mode, in order to keep the old MINIX ash behavior. Note: The shell now refuses to source a script without a relative or absolute path. This means: - '. myscript.sh' fails, while - '. ./myscript.sh' succeeds Change-Id: I0be89b0747bd005e4c05cadb937af86883627dc6
This commit is contained in:
parent
2d64210c1d
commit
d90bee9749
117 changed files with 12265 additions and 10664 deletions
|
@ -2,7 +2,7 @@
|
||||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||||
|
|
||||||
SUBDIR= cat chmod cp date df echo ed expr hostname \
|
SUBDIR= cat chmod cp date df echo ed expr hostname \
|
||||||
kill ksh ln ls mkdir mv pax pwd rm rmdir \
|
kill ksh ln ls mkdir mv pax pwd rm rmdir sh \
|
||||||
sleep stty sync test
|
sleep stty sync test
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
|
88
bin/sh/Makefile
Normal file
88
bin/sh/Makefile
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
# $NetBSD: Makefile,v 1.99 2012/12/02 12:55:27 apb Exp $
|
||||||
|
# @(#)Makefile 8.4 (Berkeley) 5/5/95
|
||||||
|
|
||||||
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
|
YHEADER=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 \
|
||||||
|
test.c kill.c syntax.c
|
||||||
|
GENSRCS=arith.c arith_lex.c builtins.c init.c nodes.c
|
||||||
|
GENHDRS=arith.h builtins.h nodes.h token.h
|
||||||
|
SRCS= ${SHSRCS} ${GENSRCS}
|
||||||
|
|
||||||
|
DPSRCS+=${GENHDRS}
|
||||||
|
|
||||||
|
LDADD+= -ll -ledit -lterminfo
|
||||||
|
DPADD+= ${LIBL} ${LIBEDIT} ${LIBTERMINFO}
|
||||||
|
|
||||||
|
LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
||||||
|
|
||||||
|
# Environment for scripts executed during build.
|
||||||
|
SCRIPT_ENV= \
|
||||||
|
AWK=${TOOL_AWK:Q} \
|
||||||
|
SED=${TOOL_SED:Q}
|
||||||
|
|
||||||
|
# The .depend file can get references to these temporary files
|
||||||
|
.OPTIONAL: lex.yy.c y.tab.c
|
||||||
|
|
||||||
|
.ifdef CRUNCHEDPROG
|
||||||
|
LFLAGS+=-L
|
||||||
|
YFLAGS+=-l
|
||||||
|
.endif
|
||||||
|
|
||||||
|
CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
|
||||||
|
#XXX: For testing only.
|
||||||
|
#CPPFLAGS+=-DDEBUG=2
|
||||||
|
#COPTS+=-g
|
||||||
|
#CFLAGS+=-funsigned-char
|
||||||
|
#TARGET_CHARFLAG?= -DTARGET_CHAR="unsigned char" -funsigned-char
|
||||||
|
|
||||||
|
.ifdef SMALLPROG
|
||||||
|
CPPFLAGS+=-DSMALL
|
||||||
|
.else
|
||||||
|
SRCS+=printf.c
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test \
|
||||||
|
${NETBSDSRCDIR}/usr.bin/printf \
|
||||||
|
${NETBSDSRCDIR}/bin/kill
|
||||||
|
|
||||||
|
CLEANFILES+= ${GENSRCS} ${GENHDRS} y.tab.h
|
||||||
|
CLEANFILES+= trace
|
||||||
|
|
||||||
|
token.h: mktokens
|
||||||
|
${_MKTARGET_CREATE}
|
||||||
|
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC}
|
||||||
|
|
||||||
|
.ORDER: builtins.h builtins.c
|
||||||
|
builtins.h builtins.c: mkbuiltins shell.h builtins.def
|
||||||
|
${_MKTARGET_CREATE}
|
||||||
|
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} ${.OBJDIR}
|
||||||
|
[ -f builtins.h ]
|
||||||
|
|
||||||
|
init.c: mkinit.sh ${SHSRCS}
|
||||||
|
${_MKTARGET_CREATE}
|
||||||
|
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC}
|
||||||
|
|
||||||
|
.ORDER: nodes.h nodes.c
|
||||||
|
nodes.c nodes.h: mknodes.sh nodetypes nodes.c.pat
|
||||||
|
${_MKTARGET_CREATE}
|
||||||
|
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} ${.OBJDIR}
|
||||||
|
[ -f nodes.h ]
|
||||||
|
|
||||||
|
.if ${USETOOLS} == "yes"
|
||||||
|
NBCOMPATLIB= -L${TOOLDIR}/lib -lnbcompat
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if make(install)
|
||||||
|
SUBDIR+=USD.doc
|
||||||
|
.endif
|
||||||
|
|
||||||
|
COPTS.printf.c = -Wno-format-nonliteral
|
||||||
|
COPTS.jobs.c = -Wno-format-nonliteral
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
|
.include <bsd.subdir.mk>
|
|
@ -1,5 +1,5 @@
|
||||||
|
# $NetBSD: TOUR,v 1.10 2008/11/15 17:01:38 snj Exp $
|
||||||
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||||
# $FreeBSD: src/bin/sh/TOUR,v 1.6 1999/08/27 23:15:07 peter Exp $
|
|
||||||
|
|
||||||
NOTE -- This is the original TOUR paper distributed with ash and
|
NOTE -- This is the original TOUR paper distributed with ash and
|
||||||
does not represent the current state of the shell. It is provided anyway
|
does not represent the current state of the shell. It is provided anyway
|
||||||
|
@ -22,7 +22,7 @@ SOURCE CODE GENERATORS: Files whose names begin with "mk" are
|
||||||
programs that generate source code. A complete list of these
|
programs that generate source code. A complete list of these
|
||||||
programs is:
|
programs is:
|
||||||
|
|
||||||
program intput files generates
|
program input files generates
|
||||||
------- ------------ ---------
|
------- ------------ ---------
|
||||||
mkbuiltins builtins builtins.h builtins.c
|
mkbuiltins builtins builtins.h builtins.c
|
||||||
mkinit *.c init.c
|
mkinit *.c init.c
|
||||||
|
@ -91,7 +91,7 @@ INTERRUPTS: In an interactive shell, an interrupt will cause an
|
||||||
EXINT exception to return to the main command loop. (Exception:
|
EXINT exception to return to the main command loop. (Exception:
|
||||||
EXINT is not raised if the user traps interrupts using the trap
|
EXINT is not raised if the user traps interrupts using the trap
|
||||||
command.) The INTOFF and INTON macros (defined in exception.h)
|
command.) The INTOFF and INTON macros (defined in exception.h)
|
||||||
provide uninterruptable critical sections. Between the execution
|
provide uninterruptible critical sections. Between the execution
|
||||||
of INTOFF and the execution of INTON, interrupt signals will be
|
of INTOFF and the execution of INTON, interrupt signals will be
|
||||||
held for later delivery. INTOFF and INTON can be nested.
|
held for later delivery. INTOFF and INTON can be nested.
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ string was going to be:
|
||||||
p = stackptr;
|
p = stackptr;
|
||||||
*p++ = c; /* repeated as many times as needed */
|
*p++ = c; /* repeated as many times as needed */
|
||||||
stackptr = p;
|
stackptr = p;
|
||||||
The folloing three macros (defined in memalloc.h) perform these
|
The following three macros (defined in memalloc.h) perform these
|
||||||
operations, but grow the stack if you run off the end:
|
operations, but grow the stack if you run off the end:
|
||||||
STARTSTACKSTR(p);
|
STARTSTACKSTR(p);
|
||||||
STPUTC(c, p); /* repeated as many times as needed */
|
STPUTC(c, p); /* repeated as many times as needed */
|
||||||
|
@ -232,7 +232,7 @@ control is defined.
|
||||||
REDIR.C: Ash allows file descriptors to be redirected and then
|
REDIR.C: Ash allows file descriptors to be redirected and then
|
||||||
restored without forking off a child process. This is accom-
|
restored without forking off a child process. This is accom-
|
||||||
plished by duplicating the original file descriptors. The redir-
|
plished by duplicating the original file descriptors. The redir-
|
||||||
tab structure records where the file descriptors have be dupli-
|
tab structure records where the file descriptors have been dupli-
|
||||||
cated to.
|
cated to.
|
||||||
|
|
||||||
EXEC.C: The routine find_command locates a command, and enters
|
EXEC.C: The routine find_command locates a command, and enters
|
||||||
|
@ -327,7 +327,7 @@ is called at appropriate points to actually handle the signal.
|
||||||
When an interrupt is caught and no trap has been set for that
|
When an interrupt is caught and no trap has been set for that
|
||||||
signal, the routine "onint" in error.c is called.
|
signal, the routine "onint" in error.c is called.
|
||||||
|
|
||||||
OUTPUT: Ash uses it's own output routines. There are three out-
|
OUTPUT: Ash uses its own output routines. There are three out-
|
||||||
put structures allocated. "Output" represents the standard out-
|
put structures allocated. "Output" represents the standard out-
|
||||||
put, "errout" the standard error, and "memout" contains output
|
put, "errout" the standard error, and "memout" contains output
|
||||||
which is to be stored in memory. This last is used when a buil-
|
which is to be stored in memory. This last is used when a buil-
|
||||||
|
@ -355,6 +355,3 @@ cause the preprocessor can't handle functions with a variable
|
||||||
number of arguments. Defining DEBUG also causes the shell to
|
number of arguments. Defining DEBUG also causes the shell to
|
||||||
generate a core dump if it is sent a quit signal. The tracing
|
generate a core dump if it is sent a quit signal. The tracing
|
||||||
code is in show.c.
|
code is in show.c.
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: TOUR,v 1.3 2006/03/31 11:33:46 philip Exp $
|
|
12
bin/sh/USD.doc/Makefile
Normal file
12
bin/sh/USD.doc/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# $NetBSD: Makefile,v 1.1 2010/08/22 01:58:16 perry Exp $
|
||||||
|
# @(#)Makefile 8.1 (Berkeley) 8/14/93
|
||||||
|
|
||||||
|
DIR= usd/03.shell
|
||||||
|
SRCS= Rv7man t.mac t1 t2 t3 t4
|
||||||
|
MACROS= -ms
|
||||||
|
|
||||||
|
paper.ps: ${SRCS}
|
||||||
|
${TOOL_REFER} -e -p ${SRCS} | \
|
||||||
|
${TOOL_ROFF_PS} ${MACROS} > ${.TARGET}
|
||||||
|
|
||||||
|
.include <bsd.doc.mk>
|
405
bin/sh/USD.doc/Rv7man
Normal file
405
bin/sh/USD.doc/Rv7man
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
%A L. P. Deutsch
|
||||||
|
%A B. W. Lampson
|
||||||
|
%T An online editor
|
||||||
|
%J Comm. Assoc. Comp. Mach.
|
||||||
|
%V 10
|
||||||
|
%N 12
|
||||||
|
%D December 1967
|
||||||
|
%P 793-799, 803
|
||||||
|
%K qed
|
||||||
|
|
||||||
|
.[
|
||||||
|
%r 17
|
||||||
|
%K cstr
|
||||||
|
%R Comp. Sci. Tech. Rep. No. 17
|
||||||
|
%I Bell Laboratories
|
||||||
|
%C Murray Hill, New Jersey
|
||||||
|
%A B. W. Kernighan
|
||||||
|
%A L. L. Cherry
|
||||||
|
%T A System for Typesetting Mathematics
|
||||||
|
%d May 1974, revised April 1977
|
||||||
|
%J Comm. Assoc. Comp. Mach.
|
||||||
|
%K acm cacm
|
||||||
|
%V 18
|
||||||
|
%P 151-157
|
||||||
|
%D March 1975
|
||||||
|
.]
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Time-Sharing System: Document Preparation
|
||||||
|
%K unix bstj
|
||||||
|
%A B. W. Kernighan
|
||||||
|
%A M. E. Lesk
|
||||||
|
%A J. F. Ossanna
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 2115-2135
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%A T. A. Dolotta
|
||||||
|
%A J. R. Mashey
|
||||||
|
%T An Introduction to the Programmer's Workbench
|
||||||
|
%J Proc. 2nd Int. Conf. on Software Engineering
|
||||||
|
%D October 13-15, 1976
|
||||||
|
%P 164-168
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Time-Sharing System: The Programmer's Workbench
|
||||||
|
%A T. A. Dolotta
|
||||||
|
%A R. C. Haight
|
||||||
|
%A J. R. Mashey
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 2177-2200
|
||||||
|
%D 1978
|
||||||
|
%K unix bstj
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Time-Sharing System: U\s-2NIX\s0 on a Microprocessor
|
||||||
|
%K unix bstj
|
||||||
|
%A H. Lycklama
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 2087-2101
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%T The C Programming Language
|
||||||
|
%A B. W. Kernighan
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%I Prentice-Hall
|
||||||
|
%C Englewood Cliffs, New Jersey
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%T Computer Recreations
|
||||||
|
%A Aleph-null
|
||||||
|
%J Software Practice and Experience
|
||||||
|
%V 1
|
||||||
|
%N 2
|
||||||
|
%D April-June 1971
|
||||||
|
%P 201-204
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Time-Sharing System: The U\s-2NIX\s0 Shell
|
||||||
|
%A S. R. Bourne
|
||||||
|
%K unix bstj
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 1971-1990
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%A L. P. Deutsch
|
||||||
|
%A B. W. Lampson
|
||||||
|
%T \*sSDS\*n 930 time-sharing system preliminary reference manual
|
||||||
|
%R Doc. 30.10.10, Project \*sGENIE\*n
|
||||||
|
%C Univ. Cal. at Berkeley
|
||||||
|
%D April 1965
|
||||||
|
|
||||||
|
%A R. J. Feiertag
|
||||||
|
%A E. I. Organick
|
||||||
|
%T The Multics input-output system
|
||||||
|
%J Proc. Third Symposium on Operating Systems Principles
|
||||||
|
%D October 18-20, 1971
|
||||||
|
%P 35-41
|
||||||
|
|
||||||
|
%A D. G. Bobrow
|
||||||
|
%A J. D. Burchfiel
|
||||||
|
%A D. L. Murphy
|
||||||
|
%A R. S. Tomlinson
|
||||||
|
%T \*sTENEX\*n, a Paged Time Sharing System for the \*sPDP\*n-10
|
||||||
|
%J Comm. Assoc. Comp. Mach.
|
||||||
|
%V 15
|
||||||
|
%N 3
|
||||||
|
%D March 1972
|
||||||
|
%K tenex
|
||||||
|
%P 135-143
|
||||||
|
|
||||||
|
%A R. E. Griswold
|
||||||
|
%A D. R. Hanson
|
||||||
|
%T An Overview of SL5
|
||||||
|
%J SIGPLAN Notices
|
||||||
|
%V 12
|
||||||
|
%N 4
|
||||||
|
%D April 1977
|
||||||
|
%P 40-50
|
||||||
|
|
||||||
|
%A E. W. Dijkstra
|
||||||
|
%T Cooperating Sequential Processes
|
||||||
|
%B Programming Languages
|
||||||
|
%E F. Genuys
|
||||||
|
%I Academic Press
|
||||||
|
%C New York
|
||||||
|
%D 1968
|
||||||
|
%P 43-112
|
||||||
|
|
||||||
|
%A J. A. Hawley
|
||||||
|
%A W. B. Meyer
|
||||||
|
%T M\s-2UNIX\s0, A Multiprocessing Version of U\s-2NIX\s0
|
||||||
|
%K munix unix
|
||||||
|
%R M.S. Thesis
|
||||||
|
%I Naval Postgraduate School
|
||||||
|
%C Monterey, Cal.
|
||||||
|
%D 1975
|
||||||
|
|
||||||
|
%T The U\s-2NIX\s0 Time-Sharing System
|
||||||
|
%K unix bstj
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%A K. Thompson
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 1905-1929
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%A E. I. Organick
|
||||||
|
%T The M\s-2ULTICS\s0 System
|
||||||
|
%K multics
|
||||||
|
%I M.I.T. Press
|
||||||
|
%C Cambridge, Mass.
|
||||||
|
%D 1972
|
||||||
|
|
||||||
|
%T UNIX for Beginners
|
||||||
|
%A B. W. Kernighan
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Programmer's Man\&ual
|
||||||
|
%A K. Thompson
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%K unix
|
||||||
|
%I Bell Laboratories
|
||||||
|
%O Seventh Edition.
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%A K. Thompson
|
||||||
|
%T The U\s-2NIX\s0 Command Language
|
||||||
|
%B Structured Programming\(emInfotech State of the Art Report
|
||||||
|
%I Infotech International Ltd.
|
||||||
|
%C Nicholson House, Maidenhead, Berkshire, England
|
||||||
|
%D March 1975
|
||||||
|
%P 375-384
|
||||||
|
%K unix
|
||||||
|
%X pwb
|
||||||
|
Brief description of shell syntax and semantics, without much
|
||||||
|
detail on implementation.
|
||||||
|
Much on pipes and convenience of hooking programs together.
|
||||||
|
Includes SERMONETTE:
|
||||||
|
"Many familiar computing `concepts' are missing from UNIX.
|
||||||
|
Files have no records. There are no access methods.
|
||||||
|
There are no file types. These concepts fill a much-needed gap.
|
||||||
|
I sincerely hope that when future systems are designed by
|
||||||
|
manufacturers the value of some of these ingrained notions is re-examined.
|
||||||
|
Like the politician and his `common man', manufacturers have
|
||||||
|
their `average user'.
|
||||||
|
|
||||||
|
%A J. R. Mashey
|
||||||
|
%T PWB/UNIX Shell Tutorial
|
||||||
|
%D September 30, 1977
|
||||||
|
|
||||||
|
%A D. F. Hartley (Ed.)
|
||||||
|
%T The Cambridge Multiple Access System \- Users Reference Manual
|
||||||
|
%I University Mathematical Laboratory
|
||||||
|
%C Cambridge, England
|
||||||
|
%D 1968
|
||||||
|
|
||||||
|
%A P. A. Crisman (Ed.)
|
||||||
|
%T The Compatible Time-Sharing System
|
||||||
|
%I M.I.T. Press
|
||||||
|
%K whole ctss book
|
||||||
|
%C Cambridge, Mass.
|
||||||
|
%D 1965
|
||||||
|
|
||||||
|
%T LR Parsing
|
||||||
|
%A A. V. Aho
|
||||||
|
%A S. C. Johnson
|
||||||
|
%J Comp. Surveys
|
||||||
|
%V 6
|
||||||
|
%N 2
|
||||||
|
%P 99-124
|
||||||
|
%D June 1974
|
||||||
|
|
||||||
|
%T Deterministic Parsing of Ambiguous Grammars
|
||||||
|
%A A. V. Aho
|
||||||
|
%A S. C. Johnson
|
||||||
|
%A J. D. Ullman
|
||||||
|
%J Comm. Assoc. Comp. Mach.
|
||||||
|
%K acm cacm
|
||||||
|
%V 18
|
||||||
|
%N 8
|
||||||
|
%P 441-452
|
||||||
|
%D August 1975
|
||||||
|
|
||||||
|
%A A. V. Aho
|
||||||
|
%A J. D. Ullman
|
||||||
|
%T Principles of Compiler Design
|
||||||
|
%I Addison-Wesley
|
||||||
|
%C Reading, Mass.
|
||||||
|
%D 1977
|
||||||
|
|
||||||
|
.[
|
||||||
|
%r 65
|
||||||
|
%R Comp. Sci. Tech. Rep. No. 65
|
||||||
|
%K CSTR
|
||||||
|
%A S. C. Johnson
|
||||||
|
%T Lint, a C Program Checker
|
||||||
|
%D December 1977
|
||||||
|
%O updated version TM 78-1273-3
|
||||||
|
%D 1978
|
||||||
|
.]
|
||||||
|
|
||||||
|
%T A Portable Compiler: Theory and Practice
|
||||||
|
%A S. C. Johnson
|
||||||
|
%J Proc. 5th ACM Symp. on Principles of Programming Languages
|
||||||
|
%P 97-104
|
||||||
|
%D January 1978
|
||||||
|
|
||||||
|
.[
|
||||||
|
%r 39
|
||||||
|
%K CSTR
|
||||||
|
%R Comp. Sci. Tech. Rep. No. 39
|
||||||
|
%I Bell Laboratories
|
||||||
|
%C Murray Hill, New Jersey
|
||||||
|
%A M. E. Lesk
|
||||||
|
%T Lex \(em A Lexical Analyzer Generator
|
||||||
|
%D October 1975
|
||||||
|
.]
|
||||||
|
|
||||||
|
.[
|
||||||
|
%r 32
|
||||||
|
%K CSTR
|
||||||
|
%R Comp. Sci. Tech. Rep. No. 32
|
||||||
|
%I Bell Laboratories
|
||||||
|
%C Murray Hill, New Jersey
|
||||||
|
%A S. C. Johnson
|
||||||
|
%T Yacc \(em Yet Another Compiler-Compiler
|
||||||
|
%D July 1975
|
||||||
|
.]
|
||||||
|
|
||||||
|
%T U\s-2NIX\s0 Time-Sharing System: Portability of C Programs and the U\s-2NIX\s0 System
|
||||||
|
%K unix bstj
|
||||||
|
%A S. C. Johnson
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%J Bell Sys. Tech. J.
|
||||||
|
%V 57
|
||||||
|
%N 6
|
||||||
|
%P 2021-2048
|
||||||
|
%D 1978
|
||||||
|
|
||||||
|
%T Typing Documents on UNIX and GCOS: The -ms Macros for Troff
|
||||||
|
%A M. E. Lesk
|
||||||
|
%D 1977
|
||||||
|
|
||||||
|
%A K. Thompson
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%T U\s-2NIX\s0 Programmer's Manual
|
||||||
|
%K unix
|
||||||
|
%I Bell Laboratories
|
||||||
|
%O Sixth Edition
|
||||||
|
%D May 1975
|
||||||
|
|
||||||
|
%T The Network U\s-2NIX\s0 System
|
||||||
|
%K unix
|
||||||
|
%A G. L. Chesson
|
||||||
|
%J Operating Systems Review
|
||||||
|
%V 9
|
||||||
|
%N 5
|
||||||
|
%P 60-66
|
||||||
|
%D 1975
|
||||||
|
%O Also in \f2Proc. 5th Symp. on Operating Systems Principles.\f1
|
||||||
|
|
||||||
|
%T Spider \(em An Experimental Data Communications System
|
||||||
|
%Z ctr127
|
||||||
|
%A A. G. Fraser
|
||||||
|
%J Proc. IEEE Conf. on Communications
|
||||||
|
%P 21F
|
||||||
|
%O IEEE Cat. No. 74CH0859-9-CSCB.
|
||||||
|
%D June 1974
|
||||||
|
|
||||||
|
%T A Virtual Channel Network
|
||||||
|
%A A. G. Fraser
|
||||||
|
%J Datamation
|
||||||
|
%P 51-56
|
||||||
|
%D February 1975
|
||||||
|
|
||||||
|
.[
|
||||||
|
%r 41
|
||||||
|
%K CSTR
|
||||||
|
%R Comp. Sci. Tech. Rep. No. 41
|
||||||
|
%I Bell Laboratories
|
||||||
|
%C Murray Hill, New Jersey
|
||||||
|
%A J. W. Hunt
|
||||||
|
%A M. D. McIlroy
|
||||||
|
%T An Algorithm for Differential File Comparison
|
||||||
|
%D June 1976
|
||||||
|
.]
|
||||||
|
|
||||||
|
%A F. P. Brooks, Jr.
|
||||||
|
%T The Mythical Man-Month
|
||||||
|
%I Addison-Wesley
|
||||||
|
%C Reading, Mass.
|
||||||
|
%D 1975
|
||||||
|
%X pwb
|
||||||
|
Readable, classic reference on software engineering and
|
||||||
|
problems of large projects, from someone with experience in them.
|
||||||
|
Required reading for any software engineer, even if conclusions may not
|
||||||
|
always be agreed with.
|
||||||
|
%br
|
||||||
|
"The second is the most dangerous system a man every designs." p.55.
|
||||||
|
%br
|
||||||
|
"Hence plan to throw one away; you will, anyhow." p.116.
|
||||||
|
%br
|
||||||
|
"Cosgrove has perceptively pointed out that the programmer delivers
|
||||||
|
satisfaction of a user need rather than any tangible product.
|
||||||
|
And both the actual need and the user's perception of that need
|
||||||
|
will change as programs are built, tested, and used." p.117.
|
||||||
|
%br
|
||||||
|
"The total cost of maintaining a widely used program is typically 40 percent
|
||||||
|
or more of the cost of developing it." p.121.
|
||||||
|
%br
|
||||||
|
"As shown above, amalgamating prose and program reduces the total
|
||||||
|
number of characters to be stored." p.175.
|
||||||
|
|
||||||
|
%T A Portable Compiler for the Language C
|
||||||
|
%A A. Snyder
|
||||||
|
%I Master's Thesis, M.I.T.
|
||||||
|
%C Cambridge, Mass.
|
||||||
|
%D 1974
|
||||||
|
|
||||||
|
%T The C Language Calling Sequence
|
||||||
|
%A M. E. Lesk
|
||||||
|
%A S. C. Johnson
|
||||||
|
%A D. M. Ritchie
|
||||||
|
%D 1977
|
||||||
|
|
||||||
|
%T Optimal Code Generation for Expression Trees
|
||||||
|
%A A. V. Aho
|
||||||
|
%A S. C. Johnson
|
||||||
|
%D 1975
|
||||||
|
%J J. Assoc. Comp. Mach.
|
||||||
|
%K acm jacm
|
||||||
|
%V 23
|
||||||
|
%N 3
|
||||||
|
%P 488-501
|
||||||
|
%O Also in \f2Proc. ACM Symp. on Theory of Computing,\f1 pp. 207-217, 1975.
|
||||||
|
|
||||||
|
%A R. Sethi
|
||||||
|
%A J. D. Ullman
|
||||||
|
%T The Generation of Optimal Code for Arithmetic Expressions
|
||||||
|
%J J. Assoc. Comp. Mach.
|
||||||
|
%K acm jacm
|
||||||
|
%V 17
|
||||||
|
%N 4
|
||||||
|
%D October 1970
|
||||||
|
%P 715-728
|
||||||
|
%O Reprinted as pp. 229-247 in \fICompiler Techniques\fR, ed. B. W. Pollack, Auerbach, Princeton NJ (1972).
|
||||||
|
%X pwb
|
||||||
|
Optimal approach for straight-line, fixed
|
||||||
|
number of regs.
|
||||||
|
|
||||||
|
%T Code Generation for Machines with Multiregister
|
||||||
|
Operations
|
||||||
|
%A A. V. Aho
|
||||||
|
%A S. C. Johnson
|
||||||
|
%A J. D. Ullman
|
||||||
|
%J Proc. 4th ACM Symp. on Principles of Programming Languages
|
||||||
|
%P 21-28
|
||||||
|
%D January 1977
|
||||||
|
|
69
bin/sh/USD.doc/t.mac
Normal file
69
bin/sh/USD.doc/t.mac
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
.\" $NetBSD: t.mac,v 1.2 2010/08/22 02:19:07 perry Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions are
|
||||||
|
.\" met:
|
||||||
|
.\"
|
||||||
|
.\" Redistributions of source code and documentation must retain the above
|
||||||
|
.\" copyright notice, this list of conditions and the following
|
||||||
|
.\" disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.\" All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\"
|
||||||
|
.\" This product includes software developed or owned by Caldera
|
||||||
|
.\" International, Inc. Neither the name of Caldera International, Inc.
|
||||||
|
.\" nor the names of other contributors may be used to endorse or promote
|
||||||
|
.\" products derived from this software without specific prior written
|
||||||
|
.\" permission.
|
||||||
|
.\"
|
||||||
|
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||||
|
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)t.mac 8.1 (Berkeley) 8/14/93
|
||||||
|
.\"
|
||||||
|
.ds ZZ \fB.\|.\|.\fP
|
||||||
|
.ds ST \v'.3m'\s+2*\s0\v'-.3m'
|
||||||
|
.ds DO \h'\w'do 'u'
|
||||||
|
.ds Ca \h'\w'case 'u'
|
||||||
|
.ds WH \h'\w'while 'u'
|
||||||
|
.ds VT \|\fB\(or\fP\|
|
||||||
|
.ds TH \h'\w'then 'u'
|
||||||
|
.ds DC \*(DO\*(Ca
|
||||||
|
.ds AP >\h'-.2m'>
|
||||||
|
.ds HE <\h'-.2m'<
|
||||||
|
. \" macros for algol 68c reference manual
|
||||||
|
.ds DA 1977 November 1
|
||||||
|
.ds md \v'.25m'
|
||||||
|
.ds mu \v'-.25m'
|
||||||
|
.ds U \*(mu\s-3
|
||||||
|
.ds V \s0\*(md
|
||||||
|
.ds L \*(md\s-3
|
||||||
|
.ds M \s0\*(mu
|
||||||
|
.ds S \s-1
|
||||||
|
.ds T \s0
|
||||||
|
. \" small 1
|
||||||
|
.ds O \*S1\*T
|
||||||
|
.ds h \|
|
||||||
|
.ds s \|\|
|
||||||
|
. \" ellipsis
|
||||||
|
.ds e .\|.\|.
|
||||||
|
. \" subscripts
|
||||||
|
.ds 1 \*(md\s-41\s0\*(mu
|
||||||
|
.ds 2 \*(md\s-42\s0\*(mu
|
553
bin/sh/USD.doc/t1
Normal file
553
bin/sh/USD.doc/t1
Normal file
|
@ -0,0 +1,553 @@
|
||||||
|
.\" $NetBSD: t1,v 1.3 2010/08/22 02:19:07 perry Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions are
|
||||||
|
.\" met:
|
||||||
|
.\"
|
||||||
|
.\" Redistributions of source code and documentation must retain the above
|
||||||
|
.\" copyright notice, this list of conditions and the following
|
||||||
|
.\" disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.\" All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgment:
|
||||||
|
.\"
|
||||||
|
.\" This product includes software developed or owned by Caldera
|
||||||
|
.\" International, Inc. Neither the name of Caldera International, Inc.
|
||||||
|
.\" nor the names of other contributors may be used to endorse or promote
|
||||||
|
.\" products derived from this software without specific prior written
|
||||||
|
.\" permission.
|
||||||
|
.\"
|
||||||
|
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||||
|
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)t1 8.1 (Berkeley) 8/14/93
|
||||||
|
.\"
|
||||||
|
.EH 'USD:3-%''An Introduction to the UNIX Shell'
|
||||||
|
.OH 'An Introduction to the UNIX Shell''USD:3-%'
|
||||||
|
.\".RP
|
||||||
|
.TL
|
||||||
|
An Introduction to the UNIX Shell
|
||||||
|
.AU
|
||||||
|
S. R. Bourne
|
||||||
|
.AI
|
||||||
|
Murray Hill, NJ
|
||||||
|
.AU
|
||||||
|
(Updated for 4.3BSD by Mark Seiden)
|
||||||
|
.AU
|
||||||
|
(Further updated by Perry E. Metzger)\(dg
|
||||||
|
.AB
|
||||||
|
.FS
|
||||||
|
\(dg This paper was updated in 2010 to reflect most features of modern
|
||||||
|
POSIX shells, which all follow the design of S.R. Bourne's original v7
|
||||||
|
Unix shell.
|
||||||
|
Among these are ash, bash, ksh and others.
|
||||||
|
Typically one of these will be installed as /bin/sh on a modern system.
|
||||||
|
It does not describe the behavior of the c shell (csh).
|
||||||
|
If it's the c shell (csh) you're interested in, a good place to
|
||||||
|
begin is William Joy's paper "An Introduction to the C shell" (USD:4).
|
||||||
|
.FE
|
||||||
|
.LP
|
||||||
|
The
|
||||||
|
.ul
|
||||||
|
shell
|
||||||
|
is a command programming language that provides an interface
|
||||||
|
to the
|
||||||
|
.UX
|
||||||
|
operating system.
|
||||||
|
Its features include
|
||||||
|
control-flow primitives, parameter passing, variables and
|
||||||
|
string substitution.
|
||||||
|
Constructs such as
|
||||||
|
.ul
|
||||||
|
while, if then else, case
|
||||||
|
and
|
||||||
|
.ul
|
||||||
|
for
|
||||||
|
are available.
|
||||||
|
Two-way communication is possible between the
|
||||||
|
.ul
|
||||||
|
shell
|
||||||
|
and commands.
|
||||||
|
String-valued parameters, typically file names or flags, may be
|
||||||
|
passed to a command.
|
||||||
|
A return code is set by commands that may be used to determine control-flow,
|
||||||
|
and the standard output from a command may be used
|
||||||
|
as shell input.
|
||||||
|
.LP
|
||||||
|
The
|
||||||
|
.ul
|
||||||
|
shell
|
||||||
|
can modify the environment
|
||||||
|
in which commands run.
|
||||||
|
Input and output can be redirected
|
||||||
|
to files, and processes that communicate through `pipes'
|
||||||
|
can be invoked.
|
||||||
|
Commands are found by
|
||||||
|
searching directories
|
||||||
|
in the file system in a
|
||||||
|
sequence that can be defined by the user.
|
||||||
|
Commands can be read either from the terminal or from a file,
|
||||||
|
which allows command procedures to be
|
||||||
|
stored for later use.
|
||||||
|
.AE
|
||||||
|
.ds ST \v'.3m'\s+2*\s0\v'-.3m'
|
||||||
|
.SH
|
||||||
|
1.0\ Introduction
|
||||||
|
.LP
|
||||||
|
The shell is both a command language
|
||||||
|
and a programming language
|
||||||
|
that provides an interface to the UNIX
|
||||||
|
operating system.
|
||||||
|
This memorandum describes, with
|
||||||
|
examples, the UNIX shell.
|
||||||
|
The first section covers most of the
|
||||||
|
everyday requirements
|
||||||
|
of terminal users.
|
||||||
|
Some familiarity with UNIX
|
||||||
|
is an advantage when reading this section;
|
||||||
|
see, for example,
|
||||||
|
"UNIX for beginners".
|
||||||
|
.[
|
||||||
|
unix beginn kernigh 1978
|
||||||
|
.]
|
||||||
|
Section 2 describes those features
|
||||||
|
of the shell primarily intended
|
||||||
|
for use within shell procedures.
|
||||||
|
These include the control-flow
|
||||||
|
primitives and string-valued variables
|
||||||
|
provided by the shell.
|
||||||
|
A knowledge of a programming language
|
||||||
|
would be a help when reading this section.
|
||||||
|
The last section describes the more
|
||||||
|
advanced features of the shell.
|
||||||
|
References of the form "see \fIpipe\fP (2)"
|
||||||
|
are to a section of the UNIX manual.
|
||||||
|
.[
|
||||||
|
seventh 1978 ritchie thompson
|
||||||
|
.]
|
||||||
|
.SH
|
||||||
|
1.1\ Simple\ commands
|
||||||
|
.LP
|
||||||
|
Simple commands consist of one or more words
|
||||||
|
separated by blanks.
|
||||||
|
The first word is the name of the command
|
||||||
|
to be executed; any remaining words
|
||||||
|
are passed as arguments to the command.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
who
|
||||||
|
.DE
|
||||||
|
is a command that prints the names
|
||||||
|
of users logged in.
|
||||||
|
The command
|
||||||
|
.DS
|
||||||
|
ls \(mil
|
||||||
|
.DE
|
||||||
|
prints a list of files in the current
|
||||||
|
directory.
|
||||||
|
The argument \fI\(mil\fP tells \fIls\fP
|
||||||
|
to print status information, size and
|
||||||
|
the creation date for each file.
|
||||||
|
.SH
|
||||||
|
1.2\ Input\ output\ redirection
|
||||||
|
.LP
|
||||||
|
Most commands produce output on the standard output
|
||||||
|
that is initially connected to the terminal.
|
||||||
|
This output may be sent to a file
|
||||||
|
by writing, for example,
|
||||||
|
.DS
|
||||||
|
ls \(mil >file
|
||||||
|
.DE
|
||||||
|
The notation \fI>file\fP
|
||||||
|
is interpreted by the shell and is not passed
|
||||||
|
as an argument to \fIls.\fP
|
||||||
|
If \fIfile\fP does not exist then the
|
||||||
|
shell creates it;
|
||||||
|
otherwise the original contents of
|
||||||
|
\fIfile\fP are replaced with the output
|
||||||
|
from \fIls.\fP
|
||||||
|
Output may be appended to a file
|
||||||
|
using the notation
|
||||||
|
.DS
|
||||||
|
ls \(mil \*(APfile
|
||||||
|
.DE
|
||||||
|
In this case \fIfile\fP is also created if it does not already
|
||||||
|
exist.
|
||||||
|
.LP
|
||||||
|
The standard input of a command may be taken
|
||||||
|
from a file instead of the terminal by
|
||||||
|
writing, for example,
|
||||||
|
.DS
|
||||||
|
wc <file
|
||||||
|
.DE
|
||||||
|
The command \fIwc\fP reads its standard input
|
||||||
|
(in this case redirected from \fIfile\fP)
|
||||||
|
and prints the number of characters, words and
|
||||||
|
lines found.
|
||||||
|
If only the number of lines is required
|
||||||
|
then
|
||||||
|
.DS
|
||||||
|
wc \(mil <file
|
||||||
|
.DE
|
||||||
|
could be used.
|
||||||
|
.\" I considered adding the following, but have thought better of it
|
||||||
|
.\" for now.
|
||||||
|
.\" -- Perry Metzger
|
||||||
|
.\"
|
||||||
|
.\" .LP
|
||||||
|
.\" Error messages are typically printed by commands on a different
|
||||||
|
.\" channel, called standard error, which may also be redirected using the
|
||||||
|
.\" notation 2>\|.
|
||||||
|
.\" For example
|
||||||
|
.\" .DS
|
||||||
|
.\" command some args >out 2>errors
|
||||||
|
.\" .DE
|
||||||
|
.\" will redirect standard output to the file `out' but standard error
|
||||||
|
.\" (and thus all error messages) to `errors'.
|
||||||
|
.\" The notation 2>&1 sets standard error pointing to the same
|
||||||
|
.\" place as standard out.
|
||||||
|
.\" Thus:
|
||||||
|
.\" .DS
|
||||||
|
.\" command some args 2>&1 >everything
|
||||||
|
.\" .DE
|
||||||
|
.\" will put both standard out and standard error into the file `everything'.
|
||||||
|
.\" See section 3.7 below for more details.
|
||||||
|
.SH
|
||||||
|
1.3\ Pipelines\ and\ filters
|
||||||
|
.LP
|
||||||
|
The standard output of one command may be
|
||||||
|
connected to the standard input of another
|
||||||
|
by writing
|
||||||
|
the `pipe' operator,
|
||||||
|
indicated by \*(VT,
|
||||||
|
as in,
|
||||||
|
.DS
|
||||||
|
ls \(mil \*(VT wc
|
||||||
|
.DE
|
||||||
|
Two commands connected in this way constitute
|
||||||
|
a \fIpipeline\fP and
|
||||||
|
the overall effect is the same as
|
||||||
|
.DS
|
||||||
|
ls \(mil >file; wc <file
|
||||||
|
.DE
|
||||||
|
except that no \fIfile\fP is used.
|
||||||
|
Instead the two \fIprocesses\fP are connected
|
||||||
|
by a pipe (see \fIpipe\fP(2)) and are
|
||||||
|
run in parallel.
|
||||||
|
Pipes are unidirectional and
|
||||||
|
synchronization is achieved by
|
||||||
|
halting \fIwc\fP when there is
|
||||||
|
nothing to read and halting \fIls\fP
|
||||||
|
when the pipe is full.
|
||||||
|
.LP
|
||||||
|
A \fIfilter\fP is a command
|
||||||
|
that reads its standard input,
|
||||||
|
transforms it in some way,
|
||||||
|
and prints the result as output.
|
||||||
|
One such filter, \fIgrep,\fP
|
||||||
|
selects from its input those lines
|
||||||
|
that contain some specified string.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
ls \*(VT grep old
|
||||||
|
.DE
|
||||||
|
prints those lines, if any, of the output
|
||||||
|
from \fIls\fP that contain
|
||||||
|
the string \fIold.\fP
|
||||||
|
Another useful filter is \fIsort\fP.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
who \*(VT sort
|
||||||
|
.DE
|
||||||
|
will print an alphabetically sorted list
|
||||||
|
of logged in users.
|
||||||
|
.LP
|
||||||
|
A pipeline may consist of more than two commands,
|
||||||
|
for example,
|
||||||
|
.DS
|
||||||
|
ls \*(VT grep old \*(VT wc \(mil
|
||||||
|
.DE
|
||||||
|
prints the number of file names
|
||||||
|
in the current directory containing
|
||||||
|
the string \fIold.\fP
|
||||||
|
.SH
|
||||||
|
1.4\ Background\ commands
|
||||||
|
.LP
|
||||||
|
To execute a command (or pipeline) the shell normally
|
||||||
|
creates the new \fIprocesses\fP
|
||||||
|
and waits for them to finish.
|
||||||
|
A command may be run without waiting
|
||||||
|
for it to finish.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
cc pgm.c &
|
||||||
|
.DE
|
||||||
|
calls the C compiler to compile
|
||||||
|
the file \fIpgm.c\|.\fP
|
||||||
|
The trailing \fB&\fP is an operator that instructs the shell
|
||||||
|
not to wait for the command to finish.
|
||||||
|
To help keep track of such a process
|
||||||
|
the shell reports its job number (see below) and process
|
||||||
|
id following its creation.
|
||||||
|
Such a command is said to be running in the \fIbackground\fP.
|
||||||
|
By contrast, a command executed without the \fB&\fP is said to be
|
||||||
|
running in the \fIforeground\fP.\(dg
|
||||||
|
.FS
|
||||||
|
\(dg Even after execution, one may move commands from the foreground
|
||||||
|
to the background, or temporarily suspend their execution (which is
|
||||||
|
known as \fIstopping\fP a command.
|
||||||
|
This is described in detail in section 3.10 on \fIJob Control\fB.
|
||||||
|
.FE
|
||||||
|
.LP
|
||||||
|
A list of currently active processes, including ones not associated
|
||||||
|
with the current shell, may be obtained using the \fIps\fP(1) command.
|
||||||
|
.SH
|
||||||
|
1.5\ File\ name\ generation
|
||||||
|
.LP
|
||||||
|
Many commands accept arguments
|
||||||
|
which are file names.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
ls \(mil main.c
|
||||||
|
.DE
|
||||||
|
prints information relating to the file \fImain.c\fP\|.
|
||||||
|
.LP
|
||||||
|
The shell provides a mechanism
|
||||||
|
for generating a list of file names
|
||||||
|
that match a pattern.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
ls \(mil \*(ST.c
|
||||||
|
.DE
|
||||||
|
generates, as arguments to \fIls,\fP
|
||||||
|
all file names in the current directory that end in \fI.c\|.\fP
|
||||||
|
The character \*(ST is a pattern that will match any string
|
||||||
|
including the null string.
|
||||||
|
In general \fIpatterns\fP are specified
|
||||||
|
as follows.
|
||||||
|
.RS
|
||||||
|
.IP \fB\*(ST\fR 8
|
||||||
|
Matches any string of characters
|
||||||
|
including the null string.
|
||||||
|
.IP \fB?\fR 8
|
||||||
|
Matches any single character.
|
||||||
|
.IP \fB[\*(ZZ]\fR 8
|
||||||
|
Matches any one of the characters
|
||||||
|
enclosed.
|
||||||
|
A pair of characters separated by a minus will
|
||||||
|
match any character lexically between
|
||||||
|
the pair.
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
[a\(miz]\*(ST
|
||||||
|
.DE
|
||||||
|
matches all names in the current directory
|
||||||
|
beginning with
|
||||||
|
one of the letters \fIa\fP through \fIz.\fP
|
||||||
|
.DS
|
||||||
|
/usr/fred/test/?
|
||||||
|
.DE
|
||||||
|
matches all names in the directory
|
||||||
|
\fB/usr/fred/test\fP that consist of a single character.
|
||||||
|
If no file name is found that matches
|
||||||
|
the pattern then the pattern is passed,
|
||||||
|
unchanged, as an argument.
|
||||||
|
.LP
|
||||||
|
This mechanism is useful both to save typing
|
||||||
|
and to select names according to some pattern.
|
||||||
|
It may also be used to find files.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
echo /usr/fred/\*(ST/core
|
||||||
|
.DE
|
||||||
|
finds and prints the names of all \fIcore\fP files in sub-directories
|
||||||
|
of \fB/usr/fred\|.\fP
|
||||||
|
(\fIecho\fP is a standard UNIX command that prints
|
||||||
|
its arguments, separated by blanks.)
|
||||||
|
This last feature can be expensive,
|
||||||
|
requiring a scan of all
|
||||||
|
sub-directories of \fB/usr/fred\|.\fP
|
||||||
|
.LP
|
||||||
|
There is one exception to the general
|
||||||
|
rules given for patterns.
|
||||||
|
The character `\fB.\fP'
|
||||||
|
at the start of a file name must be explicitly
|
||||||
|
matched.
|
||||||
|
.DS
|
||||||
|
echo \*(ST
|
||||||
|
.DE
|
||||||
|
will therefore echo all file names in the current
|
||||||
|
directory not beginning
|
||||||
|
with `\fB.\fP'\|.
|
||||||
|
.DS
|
||||||
|
echo \fB.\fP\*(ST
|
||||||
|
.DE
|
||||||
|
will echo all those file names that begin with `\fB.\fP'\|.
|
||||||
|
This avoids inadvertent matching
|
||||||
|
of the names `\fB.\fP' and `\fB..\fP'
|
||||||
|
which mean `the current directory'
|
||||||
|
and `the parent directory'
|
||||||
|
respectively.
|
||||||
|
(Notice that \fIls\fP suppresses
|
||||||
|
information for the files `\fB.\fP' and `\fB..\fP'\|.)
|
||||||
|
.LP
|
||||||
|
Finally, the tilde character, `\fB\(ap\fP', may be used to indicate the
|
||||||
|
home directory of a user.
|
||||||
|
The `\fB\(ap\fP' at the beginning of a path name followed by a
|
||||||
|
non-alphabetic character expands to the current user's home
|
||||||
|
directory.
|
||||||
|
If the `\fB\(ap\fP' is followed by a login name, it expands to the named
|
||||||
|
user's home directory.
|
||||||
|
For example:
|
||||||
|
.DS
|
||||||
|
ls \(ap
|
||||||
|
cd \(apegbert/
|
||||||
|
.DE
|
||||||
|
will list the contents of the user's home directory and then change
|
||||||
|
to the home directory of the user ``egbert''.
|
||||||
|
.SH
|
||||||
|
1.6\ Quoting
|
||||||
|
.LP
|
||||||
|
Characters that have a special meaning
|
||||||
|
to the shell, such as \fB< > \*(ST ? \*(VT &\|,\fR
|
||||||
|
are called metacharacters.
|
||||||
|
A complete list of metacharacters is given
|
||||||
|
in appendix B.
|
||||||
|
Any character preceded by a \fB\\\fR is \fIquoted\fP
|
||||||
|
and loses its special meaning, if any.
|
||||||
|
The \fB\\\fP is elided so that
|
||||||
|
.DS
|
||||||
|
echo \\?
|
||||||
|
.DE
|
||||||
|
will echo a single \fB?\|,\fP
|
||||||
|
and
|
||||||
|
.DS
|
||||||
|
echo \\\\
|
||||||
|
.DE
|
||||||
|
will echo a single \fB\\\|.\fR
|
||||||
|
To allow long strings to be continued over
|
||||||
|
more than one line
|
||||||
|
the sequence \fB\\newline\fP
|
||||||
|
is ignored.
|
||||||
|
.LP
|
||||||
|
\fB\\\fP is convenient for quoting
|
||||||
|
single characters.
|
||||||
|
When more than one character needs
|
||||||
|
quoting the above mechanism is clumsy and
|
||||||
|
error prone.
|
||||||
|
A string of characters may be quoted
|
||||||
|
by enclosing the string between single quotes.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
echo xx\'\*(ST\*(ST\*(ST\*(ST\'xx
|
||||||
|
.DE
|
||||||
|
will echo
|
||||||
|
.DS
|
||||||
|
xx\*(ST\*(ST\*(ST\*(STxx
|
||||||
|
.DE
|
||||||
|
The quoted string may not contain
|
||||||
|
a single quote
|
||||||
|
but may contain newlines, which are preserved.
|
||||||
|
This quoting mechanism is the most
|
||||||
|
simple and is recommended
|
||||||
|
for casual use.
|
||||||
|
.LP
|
||||||
|
A third quoting mechanism using double quotes
|
||||||
|
is also available
|
||||||
|
that prevents interpretation of some but not all
|
||||||
|
metacharacters.
|
||||||
|
Discussion of the
|
||||||
|
details is deferred
|
||||||
|
to section 3.5\|.
|
||||||
|
.SH
|
||||||
|
1.7\ Prompting
|
||||||
|
.LP
|
||||||
|
When the shell is used from a terminal it will
|
||||||
|
issue a prompt before reading a command.
|
||||||
|
By default this prompt is `\fB$\ \fR'\|.
|
||||||
|
It may be changed by saying,
|
||||||
|
for example,
|
||||||
|
.DS
|
||||||
|
\s-1PS1\s0="yesdear$ "
|
||||||
|
.DE
|
||||||
|
that sets the prompt to be the string \fIyesdear$\|.\fP
|
||||||
|
If a newline is typed and further input is needed
|
||||||
|
then the shell will issue the prompt `\fB>\ \fR'\|.
|
||||||
|
Sometimes this can be caused by mistyping
|
||||||
|
a quote mark.
|
||||||
|
If it is unexpected then entering the interrupt character
|
||||||
|
(typically \s-1CONTROL-C\s0)
|
||||||
|
will return the shell to read another command.
|
||||||
|
This prompt may be changed by saying, for example,
|
||||||
|
.DS
|
||||||
|
\s-1PS2\s0=more
|
||||||
|
.DE
|
||||||
|
Entering the interrupt character may also be used to terminate most
|
||||||
|
programs running as the current foreground job.
|
||||||
|
.LP
|
||||||
|
(\s-1PS1\s0 and \s-1PS2\s0 are \fIshell variables\fP, which will be
|
||||||
|
described in section 2.4 below.)
|
||||||
|
.SH
|
||||||
|
1.8\ The\ shell\ and\ login
|
||||||
|
.LP
|
||||||
|
Following \fIlogin\fP(1)
|
||||||
|
the shell is called to read and execute
|
||||||
|
commands typed at the terminal.
|
||||||
|
If the user's login directory
|
||||||
|
contains the file \fB.profile\fP
|
||||||
|
then it is assumed to contain commands
|
||||||
|
and is read by the shell before reading
|
||||||
|
any commands from the terminal.
|
||||||
|
.LP
|
||||||
|
(Most versions of the shell also specify a file that is read and
|
||||||
|
executed on start-up whether or not the shell is invoked by login.
|
||||||
|
The \s-1ENV\s0 shell variable, described in section 2.4 below, can be
|
||||||
|
used to override the name of this file.
|
||||||
|
See the shell manual page for further information.)
|
||||||
|
.SH
|
||||||
|
1.9\ Summary
|
||||||
|
.sp
|
||||||
|
.RS
|
||||||
|
.IP \(bu
|
||||||
|
\fBls\fP
|
||||||
|
.br
|
||||||
|
Print the names of files in the current directory.
|
||||||
|
.IP \(bu
|
||||||
|
\fBls >file\fP
|
||||||
|
.br
|
||||||
|
Put the output from \fIls\fP into \fIfile.\fP
|
||||||
|
.IP \(bu
|
||||||
|
\fBls \*(VT wc \(mil\fR
|
||||||
|
.br
|
||||||
|
Print the number of files in the current directory.
|
||||||
|
.IP \(bu
|
||||||
|
\fBls \*(VT grep old\fR
|
||||||
|
.br
|
||||||
|
Print those file names containing the string \fIold.\fP
|
||||||
|
.IP \(bu
|
||||||
|
\fBls \*(VT grep old \*(VT wc \(mil\fR
|
||||||
|
.br
|
||||||
|
Print the number of files whose name contains the string \fIold.\fP
|
||||||
|
.IP \(bu
|
||||||
|
\fBcc pgm.c &\fR
|
||||||
|
.br
|
||||||
|
Run \fIcc\fP in the background.
|
||||||
|
.RE
|
971
bin/sh/USD.doc/t2
Normal file
971
bin/sh/USD.doc/t2
Normal file
|
@ -0,0 +1,971 @@
|
||||||
|
.\" $NetBSD: t2,v 1.3 2010/08/22 02:19:07 perry Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions are
|
||||||
|
.\" met:
|
||||||
|
.\"
|
||||||
|
.\" Redistributions of source code and documentation must retain the above
|
||||||
|
.\" copyright notice, this list of conditions and the following
|
||||||
|
.\" disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.\" All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgment:
|
||||||
|
.\"
|
||||||
|
.\" This product includes software developed or owned by Caldera
|
||||||
|
.\" International, Inc. Neither the name of Caldera International, Inc.
|
||||||
|
.\" nor the names of other contributors may be used to endorse or promote
|
||||||
|
.\" products derived from this software without specific prior written
|
||||||
|
.\" permission.
|
||||||
|
.\"
|
||||||
|
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||||
|
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)t2 8.1 (Berkeley) 6/8/93
|
||||||
|
.\"
|
||||||
|
.SH
|
||||||
|
2.0\ Shell\ scripts
|
||||||
|
.LP
|
||||||
|
The shell may be used to read and execute commands
|
||||||
|
contained in a file.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
sh file [ args \*(ZZ ]
|
||||||
|
.DE
|
||||||
|
calls the shell to read commands from \fIfile.\fP
|
||||||
|
Such a file is called a \fIshell script.\fP
|
||||||
|
Arguments may be supplied with the call
|
||||||
|
and are referred to in \fIfile\fP
|
||||||
|
using the positional parameters
|
||||||
|
\fB$1, $2, \*(ZZ\|.\fR
|
||||||
|
.LP
|
||||||
|
For example, if the file \fIwg\fP contains
|
||||||
|
.DS
|
||||||
|
who \*(VT grep $1
|
||||||
|
.DE
|
||||||
|
then
|
||||||
|
.DS
|
||||||
|
sh wg fred
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
who \*(VT grep fred
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
UNIX files have three independent attributes,
|
||||||
|
\fIread,\fP \fIwrite\fP and \fIexecute.\fP
|
||||||
|
The UNIX command \fIchmod\fP(1) may be used
|
||||||
|
to make a file executable.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
chmod +x wg
|
||||||
|
.DE
|
||||||
|
will ensure that the file \fIwg\fP has execute status.
|
||||||
|
Following this, the command
|
||||||
|
.DS
|
||||||
|
wg fred
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
sh wg fred
|
||||||
|
.DE
|
||||||
|
This allows shell scripts and other programs
|
||||||
|
to be used interchangeably.
|
||||||
|
In either case a new process is created to
|
||||||
|
run the command.
|
||||||
|
.LP
|
||||||
|
The `\fB#\fP' character is used as a comment character by the shell.
|
||||||
|
All characters following the `#' on a line are ignored.
|
||||||
|
.LP
|
||||||
|
A typical modern system has several different shells, some with differing
|
||||||
|
command syntax, and it is desirable to specify which one should be
|
||||||
|
invoked when an executable script is invoked.
|
||||||
|
If the special comment
|
||||||
|
.DS
|
||||||
|
#!/\fIpath\fP/\fIto\fP/\fIinterpreter\fP
|
||||||
|
.DE
|
||||||
|
appears as the first line in a script, it is used to specify the
|
||||||
|
absolute pathname of the shell (or other interpreter) that should be
|
||||||
|
used to execute the file.
|
||||||
|
(Without such a line, \fB/bin/sh\fP is assumed.)
|
||||||
|
It is best if a script explicitly states
|
||||||
|
what shell it is intended for in this manner.
|
||||||
|
.LP
|
||||||
|
As well as providing names for the positional
|
||||||
|
parameters,
|
||||||
|
the number of positional parameters to a script
|
||||||
|
is available as \fB$#\|.\fP
|
||||||
|
The name of the file being executed
|
||||||
|
is available as \fB$0\|.\fP
|
||||||
|
.LP
|
||||||
|
A special shell parameter \fB$\*(ST\fP
|
||||||
|
is used to substitute for all positional parameters
|
||||||
|
except \fB$0\|.\fP
|
||||||
|
A typical use of this is to provide
|
||||||
|
some default arguments,
|
||||||
|
as in,
|
||||||
|
.DS
|
||||||
|
nroff \(miT450 \(mims $\*(ST
|
||||||
|
.DE
|
||||||
|
which simply prepends some arguments
|
||||||
|
to those already given.
|
||||||
|
(The variable \fB$@\fP also expands to ``all positional
|
||||||
|
parameters'', but is subtly different when expanded inside quotes.
|
||||||
|
See section 3.5, below.)
|
||||||
|
.SH
|
||||||
|
2.1\ Control\ flow\ -\ for
|
||||||
|
.LP
|
||||||
|
A frequent use of shell scripts is to loop
|
||||||
|
through the arguments (\fB$1, $2, \*(ZZ\fR)
|
||||||
|
executing commands once for each argument.
|
||||||
|
An example of such a script is
|
||||||
|
\fItel\fP that searches the file
|
||||||
|
\fB/usr/share/telnos\fR
|
||||||
|
that contains lines of the form
|
||||||
|
.DS
|
||||||
|
\*(ZZ
|
||||||
|
fred mh0123
|
||||||
|
bert mh0789
|
||||||
|
\*(ZZ
|
||||||
|
.DE
|
||||||
|
The text of \fItel\fP is
|
||||||
|
.DS
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for i
|
||||||
|
do
|
||||||
|
grep $i /usr/share/telnos
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
The command
|
||||||
|
.DS
|
||||||
|
tel fred
|
||||||
|
.DE
|
||||||
|
prints those lines in \fB/usr/share/telnos\fR
|
||||||
|
that contain the string \fIfred\|.\fP
|
||||||
|
.DS
|
||||||
|
tel fred bert
|
||||||
|
.DE
|
||||||
|
prints those lines containing \fIfred\fP
|
||||||
|
followed by those for \fIbert.\fP
|
||||||
|
.LP
|
||||||
|
The \fBfor\fP loop notation is recognized by the shell
|
||||||
|
and has the general form
|
||||||
|
.DS
|
||||||
|
\fBfor\fR \fIname\fR \fBin\fR \fIw1 w2 \*(ZZ\fR
|
||||||
|
\fBdo\fR \fIcommand-list\fR
|
||||||
|
\fBdone\fR
|
||||||
|
.DE
|
||||||
|
A \fIcommand-list\fP is a sequence of one or more
|
||||||
|
simple commands separated or terminated by a newline or semicolon.
|
||||||
|
Furthermore, reserved words
|
||||||
|
like \fBdo\fP and \fBdone\fP are only
|
||||||
|
recognized following a newline or
|
||||||
|
semicolon.
|
||||||
|
\fIname\fP is a shell variable that is set
|
||||||
|
to the words \fIw1 w2 \*(ZZ\fR in turn each time the \fIcommand-list\fP
|
||||||
|
following \fBdo\fP
|
||||||
|
is executed.
|
||||||
|
If \fBin\fR \fIw1 w2 \*(ZZ\fR
|
||||||
|
is omitted then the loop
|
||||||
|
is executed once for each positional parameter;
|
||||||
|
that is, \fBin\fR \fI$\*(ST\fR is assumed.
|
||||||
|
.LP
|
||||||
|
Another example of the use of the \fBfor\fP
|
||||||
|
loop is the \fIcreate\fP command
|
||||||
|
whose text is
|
||||||
|
.DS
|
||||||
|
for i do >$i; done
|
||||||
|
.DE
|
||||||
|
The command
|
||||||
|
.DS
|
||||||
|
create alpha beta
|
||||||
|
.DE
|
||||||
|
ensures that two empty files
|
||||||
|
\fIalpha\fP and \fIbeta\fP exist
|
||||||
|
and are empty.
|
||||||
|
The notation \fI>file\fP may be used on its
|
||||||
|
own to create or clear the contents of a file.
|
||||||
|
Notice also that a semicolon (or newline) is required before \fBdone.\fP
|
||||||
|
.SH
|
||||||
|
2.2\ Control\ flow\ -\ case
|
||||||
|
.LP
|
||||||
|
A multiple way branch is provided for by the
|
||||||
|
\fBcase\fP notation.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
case $# in
|
||||||
|
\*(Ca1) cat \*(AP$1 ;;
|
||||||
|
\*(Ca2) cat \*(AP$2 <$1 ;;
|
||||||
|
\*(Ca\*(ST) echo \'usage: append [ from ] to\' ;;
|
||||||
|
esac
|
||||||
|
.DE
|
||||||
|
is an \fIappend\fP command.
|
||||||
|
When called
|
||||||
|
with one argument as
|
||||||
|
.DS
|
||||||
|
append file
|
||||||
|
.DE
|
||||||
|
\fB$#\fP is the string \fI1\fP and
|
||||||
|
the standard input is copied onto the
|
||||||
|
end of \fIfile\fP
|
||||||
|
using the \fIcat\fP command.
|
||||||
|
.DS
|
||||||
|
append file1 file2
|
||||||
|
.DE
|
||||||
|
appends the contents of \fIfile1\fP
|
||||||
|
onto \fIfile2.\fP
|
||||||
|
If the number of arguments supplied to
|
||||||
|
\fIappend\fP is other than 1 or 2
|
||||||
|
then a message is printed indicating
|
||||||
|
proper usage.
|
||||||
|
.LP
|
||||||
|
The general form of the \fBcase\fP command
|
||||||
|
is
|
||||||
|
.DS
|
||||||
|
\fBcase \fIword \fBin
|
||||||
|
\*(Ca\fIpattern\|\fB)\ \fIcommand-list\fB\|;;
|
||||||
|
\*(Ca\*(ZZ
|
||||||
|
\fBesac\fR
|
||||||
|
.DE
|
||||||
|
The shell attempts to match
|
||||||
|
\fIword\fR with each \fIpattern,\fR
|
||||||
|
in the order in which the patterns
|
||||||
|
appear.
|
||||||
|
If a match is found the
|
||||||
|
associated \fIcommand-list\fP is
|
||||||
|
executed and execution
|
||||||
|
of the \fBcase\fP is complete.
|
||||||
|
Since \*(ST is the pattern that matches any
|
||||||
|
string it can be used for the default case.
|
||||||
|
.LP
|
||||||
|
A word of caution:
|
||||||
|
no check is made to ensure that only
|
||||||
|
one pattern matches
|
||||||
|
the case argument.
|
||||||
|
The first match found defines the set of commands
|
||||||
|
to be executed.
|
||||||
|
In the example below the commands following
|
||||||
|
the second \*(ST will never be executed.
|
||||||
|
.DS
|
||||||
|
case $# in
|
||||||
|
\*(Ca\*(ST) \*(ZZ ;;
|
||||||
|
\*(Ca\*(ST) \*(ZZ ;;
|
||||||
|
esac
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
Another example of the use of the \fBcase\fP
|
||||||
|
construction is to distinguish
|
||||||
|
between different forms
|
||||||
|
of an argument.
|
||||||
|
The following example is a fragment of a \fIcc\fP command.
|
||||||
|
.DS
|
||||||
|
for i
|
||||||
|
do case $i in
|
||||||
|
\*(DC\(mi[ocs]) \*(ZZ ;;
|
||||||
|
\*(DC\(mi\*(ST) echo "unknown flag $i" ;;
|
||||||
|
\*(DC\*(ST.c) /lib/c0 $i \*(ZZ ;;
|
||||||
|
\*(DC\*(ST) echo "unexpected argument $i" ;;
|
||||||
|
\*(DOesac
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
To allow the same commands to be associated
|
||||||
|
with more than one pattern
|
||||||
|
the \fBcase\fP command provides
|
||||||
|
for alternative patterns
|
||||||
|
separated by a \*(VT\|.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
case $i in
|
||||||
|
\*(Ca\(mix\*(VT\(miy) \*(ZZ
|
||||||
|
esac
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
case $i in
|
||||||
|
\*(Ca\(mi[xy]) \*(ZZ
|
||||||
|
esac
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The usual quoting conventions apply
|
||||||
|
so that
|
||||||
|
.DS
|
||||||
|
case $i in
|
||||||
|
\*(Ca\\?) \*(ZZ
|
||||||
|
.DE
|
||||||
|
will match the character \fB?\|.\fP
|
||||||
|
.SH
|
||||||
|
2.3\ Here\ documents
|
||||||
|
.LP
|
||||||
|
The shell script \fItel\fP
|
||||||
|
in section 2.1 uses the file \fB/usr/share/telnos\fR
|
||||||
|
to supply the data
|
||||||
|
for \fIgrep.\fP
|
||||||
|
An alternative is to include this
|
||||||
|
data
|
||||||
|
within the shell script as a \fIhere\fP document, as in,
|
||||||
|
.DS
|
||||||
|
for i
|
||||||
|
do grep $i \*(HE!
|
||||||
|
\*(DO\*(ZZ
|
||||||
|
\*(DOfred mh0123
|
||||||
|
\*(DObert mh0789
|
||||||
|
\*(DO\*(ZZ
|
||||||
|
!
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
In this example
|
||||||
|
the shell takes the lines between \fB\*(HE!\fR and \fB!\fR
|
||||||
|
as the standard input for \fIgrep.\fP
|
||||||
|
The string \fB!\fR is arbitrary, the document
|
||||||
|
being terminated by a line that consists
|
||||||
|
of the string following \*(HE\|.
|
||||||
|
.LP
|
||||||
|
Parameters are substituted in the document
|
||||||
|
before it is made available to \fIgrep\fP
|
||||||
|
as illustrated by the following script
|
||||||
|
called \fIedg\|.\fP
|
||||||
|
.DS
|
||||||
|
ed $3 \*(HE%
|
||||||
|
g/$1/s//$2/g
|
||||||
|
w
|
||||||
|
%
|
||||||
|
.DE
|
||||||
|
The call
|
||||||
|
.DS
|
||||||
|
edg string1 string2 file
|
||||||
|
.DE
|
||||||
|
is then equivalent to the command
|
||||||
|
.DS
|
||||||
|
ed file \*(HE%
|
||||||
|
g/string1/s//string2/g
|
||||||
|
w
|
||||||
|
%
|
||||||
|
.DE
|
||||||
|
and changes all occurrences of \fIstring1\fP
|
||||||
|
in \fIfile\fP to \fIstring2\|.\fP
|
||||||
|
Substitution can be prevented using \\
|
||||||
|
to quote the special character \fB$\fP
|
||||||
|
as in
|
||||||
|
.DS
|
||||||
|
ed $3 \*(HE+
|
||||||
|
1,\\$s/$1/$2/g
|
||||||
|
w
|
||||||
|
+
|
||||||
|
.DE
|
||||||
|
(This version of \fIedg\fP is equivalent to
|
||||||
|
the first except that \fIed\fP will print
|
||||||
|
a \fB?\fR if there are no occurrences of
|
||||||
|
the string \fB$1\|.\fP)
|
||||||
|
Substitution within a \fIhere\fP document
|
||||||
|
may be prevented entirely by quoting
|
||||||
|
the terminating string,
|
||||||
|
for example,
|
||||||
|
.DS
|
||||||
|
grep $i \*(HE'end'
|
||||||
|
\*(ZZ
|
||||||
|
end
|
||||||
|
.DE
|
||||||
|
The document is presented
|
||||||
|
without modification to \fIgrep.\fP
|
||||||
|
If parameter substitution is not required
|
||||||
|
in a \fIhere\fP document this latter form
|
||||||
|
is more efficient.
|
||||||
|
.SH
|
||||||
|
2.4\ Shell\ variables\(dg
|
||||||
|
.LP
|
||||||
|
.FS
|
||||||
|
Also known as \fIenvironment variables\fB, see \fIenvironment\fB(7).
|
||||||
|
.FE
|
||||||
|
The shell
|
||||||
|
provides string-valued variables.
|
||||||
|
Variable names begin with a letter
|
||||||
|
and consist of letters, digits and
|
||||||
|
underscores.
|
||||||
|
Variables may be given values by writing, for example,
|
||||||
|
.DS
|
||||||
|
user=fred\ box=m000\ acct=mh0000
|
||||||
|
.DE
|
||||||
|
which assigns values to the variables
|
||||||
|
\fBuser, box\fP and \fBacct.\fP
|
||||||
|
A variable may be set to the null string
|
||||||
|
by saying, for example,
|
||||||
|
.DS
|
||||||
|
null=
|
||||||
|
.DE
|
||||||
|
The value of a variable is substituted
|
||||||
|
by preceding its name with \fB$\|\fP;
|
||||||
|
for example,
|
||||||
|
.DS
|
||||||
|
echo $user
|
||||||
|
.DE
|
||||||
|
will echo \fIfred.\fP
|
||||||
|
.LP
|
||||||
|
Variables may be used interactively
|
||||||
|
to provide abbreviations for frequently
|
||||||
|
used strings.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
b=/usr/fred/bin
|
||||||
|
mv pgm $b
|
||||||
|
.DE
|
||||||
|
will move the file \fIpgm\fP
|
||||||
|
from the current directory to the directory \fB/usr/fred/bin\|.\fR
|
||||||
|
A more general notation is available for parameter
|
||||||
|
(or variable)
|
||||||
|
substitution, as in,
|
||||||
|
.DS
|
||||||
|
echo ${user}
|
||||||
|
.DE
|
||||||
|
which is equivalent to
|
||||||
|
.DS
|
||||||
|
echo $user
|
||||||
|
.DE
|
||||||
|
and is used when the parameter name is
|
||||||
|
followed by a letter or digit.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
tmp=/tmp/ps
|
||||||
|
ps a >${tmp}a
|
||||||
|
.DE
|
||||||
|
will direct the output of \fIps\fR
|
||||||
|
to the file \fB/tmp/psa,\fR
|
||||||
|
whereas,
|
||||||
|
.DS
|
||||||
|
ps a >$tmpa
|
||||||
|
.DE
|
||||||
|
would cause the value of the variable \fBtmpa\fP
|
||||||
|
to be substituted.
|
||||||
|
.LP
|
||||||
|
Except for \fB$?\fP the following
|
||||||
|
are set initially by the shell.
|
||||||
|
\fB$?\fP is set after executing each command.
|
||||||
|
.RS
|
||||||
|
.IP \fB$?\fP 8
|
||||||
|
The exit status (return code)
|
||||||
|
of the last command executed
|
||||||
|
as a decimal string.
|
||||||
|
Most commands return a zero exit status
|
||||||
|
if they complete successfully,
|
||||||
|
otherwise a non-zero exit status is returned.
|
||||||
|
Testing the value of return codes is dealt with
|
||||||
|
later under \fBif\fP and \fBwhile\fP commands.
|
||||||
|
.IP \fB$#\fP 8
|
||||||
|
The number of positional parameters
|
||||||
|
(in decimal).
|
||||||
|
Used, for example, in the \fIappend\fP command
|
||||||
|
to check the number of parameters.
|
||||||
|
.IP \fB$$\fP 8
|
||||||
|
The process number of this shell (in decimal).
|
||||||
|
Since process numbers are unique among
|
||||||
|
all existing processes, this string is
|
||||||
|
frequently used to generate
|
||||||
|
unique
|
||||||
|
temporary file names.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
ps a >/tmp/ps$$
|
||||||
|
\*(ZZ
|
||||||
|
rm /tmp/ps$$
|
||||||
|
.DE
|
||||||
|
.IP \fB$\|!\fP 8
|
||||||
|
The process number of the last process
|
||||||
|
run in the background (in decimal).
|
||||||
|
.IP \fB$\(mi\fP 8
|
||||||
|
The current shell flags, such as
|
||||||
|
\fB\(mix\fR and \fB\(miv\|.\fR
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
Some variables have a special meaning to the
|
||||||
|
shell and should be avoided for general
|
||||||
|
use.
|
||||||
|
.RS
|
||||||
|
.IP \fB$\s-1MAIL\s0\fP 8
|
||||||
|
When used interactively
|
||||||
|
the shell looks at the file
|
||||||
|
specified by this variable
|
||||||
|
before it issues a prompt.
|
||||||
|
If the specified file has been modified
|
||||||
|
since it
|
||||||
|
was last looked at the shell
|
||||||
|
prints the message
|
||||||
|
\fIyou have mail\fP before prompting
|
||||||
|
for the next command.
|
||||||
|
This variable is typically set
|
||||||
|
in the file \fB.profile,\fP
|
||||||
|
in the user's login directory.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
\s-1MAIL\s0=/usr/spool/mail/fred
|
||||||
|
.DE
|
||||||
|
.IP \fB$\s-1HOME\s0\fP 8
|
||||||
|
The default argument
|
||||||
|
for the \fIcd\fP command.
|
||||||
|
The current directory is used to resolve
|
||||||
|
file name references that do not begin with
|
||||||
|
a \fB/\|,\fR
|
||||||
|
and is changed using the \fIcd\fP command.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
cd /usr/fred/bin
|
||||||
|
.DE
|
||||||
|
makes the current directory \fB/usr/fred/bin\|.\fR
|
||||||
|
.DS
|
||||||
|
cat wn
|
||||||
|
.DE
|
||||||
|
will print on the terminal the file \fIwn\fP
|
||||||
|
in this directory.
|
||||||
|
The command
|
||||||
|
\fIcd\fP with no argument
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
cd $\s-1HOME\s0
|
||||||
|
.DE
|
||||||
|
This variable is also typically set in the
|
||||||
|
the user's login profile.
|
||||||
|
.IP \fB$\s-1PWD\s0\fP 8
|
||||||
|
The current working directory. Set by the \fIcd\fB command.
|
||||||
|
.IP \fB$\s-1PATH\s0\fP 8
|
||||||
|
A list of directories that contain commands (the \fIsearch path\fR\|).
|
||||||
|
Each time a command is executed by the shell
|
||||||
|
a list of directories is searched
|
||||||
|
for an executable file.
|
||||||
|
.ne 5
|
||||||
|
If \fB$\s-1PATH\s0\fP is not set
|
||||||
|
then the current directory,
|
||||||
|
\fB/bin\fP, and \fB/usr/bin\fP are searched by default.
|
||||||
|
.ne 5
|
||||||
|
Otherwise \fB$\s-1PATH\s0\fP consists of directory
|
||||||
|
names separated by \fB:\|.\fP
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
\s-1PATH\s0=\fB:\fP/usr/fred/bin\fB:\fP/bin\fB:\fP/usr/bin
|
||||||
|
.DE
|
||||||
|
specifies that the current directory
|
||||||
|
(the null string before the first \fB:\fP\|),
|
||||||
|
\fB/usr/fred/bin, /bin \fRand\fP /usr/bin\fR
|
||||||
|
are to be searched in that order.
|
||||||
|
In this way individual users
|
||||||
|
can have their own `private' commands
|
||||||
|
that are accessible independently
|
||||||
|
of the current directory.
|
||||||
|
If the command name contains a \fB/\fR then this directory search
|
||||||
|
is not used; a single attempt
|
||||||
|
is made to execute the command.
|
||||||
|
.IP \fB$\s-1PS1\s0\fP 8
|
||||||
|
The primary shell prompt string, by default, `\fB$\ \fR'.
|
||||||
|
.IP \fB$\s-1PS2\s0\fP 8
|
||||||
|
The shell prompt when further input is needed,
|
||||||
|
by default, `\fB>\ \fR'.
|
||||||
|
.IP \fB$\s-1IFS\s0\fP 8
|
||||||
|
The set of characters used by \fIblank
|
||||||
|
interpretation\fR (see section 3.5).
|
||||||
|
.IP \fB$\s-1ENV\s0\fP 8
|
||||||
|
The shell reads and executes the commands in the file
|
||||||
|
specified by this variable when it is initially started.
|
||||||
|
Unlike the \fB.profile\fP file, these commands are executed by all
|
||||||
|
shells, not just the one started at login.
|
||||||
|
(Most versions of the shell specify a filename that is used if
|
||||||
|
\s-1ENV\s0 is not explicitly set. See the manual page for your shell.)
|
||||||
|
.RE
|
||||||
|
.SH
|
||||||
|
2.5\ The\ test\ command
|
||||||
|
.LP
|
||||||
|
The \fItest\fP command, although not part of the shell,
|
||||||
|
is intended for use by shell programs.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
test \(mif file
|
||||||
|
.DE
|
||||||
|
returns zero exit status if \fIfile\fP
|
||||||
|
exists and non-zero exit status otherwise.
|
||||||
|
In general \fItest\fP evaluates a predicate
|
||||||
|
and returns the result as its exit status.
|
||||||
|
Some of the more frequently used \fItest\fP
|
||||||
|
arguments are given here, see \fItest\fP(1)
|
||||||
|
for a complete specification.
|
||||||
|
.DS
|
||||||
|
test s true if the argument \fIs\fP is not the null string
|
||||||
|
test \(mif file true if \fIfile\fP exists
|
||||||
|
test \(mir file true if \fIfile\fP is readable
|
||||||
|
test \(miw file true if \fIfile\fP is writable
|
||||||
|
test \(mid file true if \fIfile\fP is a directory
|
||||||
|
.DE
|
||||||
|
The \fItest\fP command is known as `\fB[\fP' and may be invoked as
|
||||||
|
such.
|
||||||
|
For aesthetic reasons, the command ignores a close bracket `\fB]\fP' given
|
||||||
|
at the end of a command so
|
||||||
|
.DS
|
||||||
|
[ -f filename ]
|
||||||
|
.DE
|
||||||
|
and
|
||||||
|
.DS
|
||||||
|
test -f filename
|
||||||
|
.DE
|
||||||
|
are completely equivalent.
|
||||||
|
Typically, the bracket notation is used when \fItest\fP is invoked inside
|
||||||
|
shell control constructs.
|
||||||
|
.SH
|
||||||
|
2.6\ Control\ flow\ -\ while
|
||||||
|
.LP
|
||||||
|
The actions of
|
||||||
|
the \fBfor\fP loop and the \fBcase\fP
|
||||||
|
branch are determined by data available to the shell.
|
||||||
|
A \fBwhile\fP or \fBuntil\fP loop
|
||||||
|
and an \fBif then else\fP branch
|
||||||
|
are also provided whose
|
||||||
|
actions are determined by the exit status
|
||||||
|
returned by commands.
|
||||||
|
A \fBwhile\fP loop has the general form
|
||||||
|
.DS
|
||||||
|
\fBwhile\fP \fIcommand-list\*1\fP
|
||||||
|
\fBdo\fP \fIcommand-list\*2\fP
|
||||||
|
\fBdone\fP
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The value tested by the \fBwhile\fP command
|
||||||
|
is the exit status of the last simple command
|
||||||
|
following \fBwhile.\fP
|
||||||
|
Each time round the loop
|
||||||
|
\fIcommand-list\*1\fP is executed;
|
||||||
|
if a zero exit status is returned then
|
||||||
|
\fIcommand-list\*2\fP
|
||||||
|
is executed;
|
||||||
|
otherwise, the loop terminates.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
while [ $1 ]
|
||||||
|
do \*(ZZ
|
||||||
|
\*(DOshift
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
for i
|
||||||
|
do \*(ZZ
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
\fIshift\fP is a shell command that
|
||||||
|
renames the positional parameters
|
||||||
|
\fB$2, $3, \*(ZZ\fR as \fB$1, $2, \*(ZZ\fR
|
||||||
|
and loses \fB$1\|.\fP
|
||||||
|
.LP
|
||||||
|
Another kind of use for the \fBwhile/until\fP
|
||||||
|
loop is to wait until some
|
||||||
|
external event occurs and then run
|
||||||
|
some commands.
|
||||||
|
In an \fBuntil\fP loop
|
||||||
|
the termination condition is reversed.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
until [ \(mif file ]
|
||||||
|
do sleep 300; done
|
||||||
|
\fIcommands\fP
|
||||||
|
.DE
|
||||||
|
will loop until \fIfile\fP exists.
|
||||||
|
Each time round the loop it waits for
|
||||||
|
5 minutes before trying again.
|
||||||
|
(Presumably another process
|
||||||
|
will eventually create the file.)
|
||||||
|
.LP
|
||||||
|
The most recent enclosing loop may be exited with the \fBbreak\fP
|
||||||
|
command, or the rest of the body skipped and the next iteration begun
|
||||||
|
with the \fBcontinue\fP command.
|
||||||
|
.LP
|
||||||
|
The commands \fItrue\fP(1) and \fIfalse\fP(1) return 0 and non-zero
|
||||||
|
exit statuses respectively. They are sometimes of use in control flow,
|
||||||
|
e.g.:
|
||||||
|
.DS
|
||||||
|
while true
|
||||||
|
do date; sleep 5
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
is an infinite loop that prints the date and time every five seconds.
|
||||||
|
.SH
|
||||||
|
2.7\ Control\ flow\ -\ if
|
||||||
|
.LP
|
||||||
|
Also available is a
|
||||||
|
general conditional branch
|
||||||
|
of the form,
|
||||||
|
.DS
|
||||||
|
\fBif\fP \fIcommand-list
|
||||||
|
\fBthen \fIcommand-list
|
||||||
|
\fBelse \fIcommand-list
|
||||||
|
\fBfi\fR
|
||||||
|
.DE
|
||||||
|
that tests the value returned by the last simple command
|
||||||
|
following \fBif.\fP
|
||||||
|
.LP
|
||||||
|
The \fBif\fP command may be used
|
||||||
|
in conjunction with the \fItest\fP command
|
||||||
|
to test for the existence of a file as in
|
||||||
|
.DS
|
||||||
|
if [ \(mif file ]
|
||||||
|
then \fIprocess file\fP
|
||||||
|
else \fIdo something else\fP
|
||||||
|
fi
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
An example of the use of \fBif, case\fP
|
||||||
|
and \fBfor\fP constructions is given in
|
||||||
|
section 2.10\|.
|
||||||
|
.LP
|
||||||
|
A multiple test \fBif\fP command
|
||||||
|
of the form
|
||||||
|
.DS
|
||||||
|
if \*(ZZ
|
||||||
|
then \*(ZZ
|
||||||
|
else if \*(ZZ
|
||||||
|
then \*(ZZ
|
||||||
|
else if \*(ZZ
|
||||||
|
\*(ZZ
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
.DE
|
||||||
|
may be written using an extension of the \fBif\fP
|
||||||
|
notation as,
|
||||||
|
.DS
|
||||||
|
if \*(ZZ
|
||||||
|
then \*(ZZ
|
||||||
|
elif \*(ZZ
|
||||||
|
then \*(ZZ
|
||||||
|
elif \*(ZZ
|
||||||
|
\*(ZZ
|
||||||
|
fi
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The following example is an implementation of the \fItouch\fP command
|
||||||
|
which changes the `last modified' time for a list
|
||||||
|
of files.
|
||||||
|
The command may be used in conjunction
|
||||||
|
with \fImake\fP(1) to force recompilation of a list
|
||||||
|
of files.
|
||||||
|
.DS
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
flag=
|
||||||
|
for i
|
||||||
|
do case $i in
|
||||||
|
\*(DC\(mic) flag=N ;;
|
||||||
|
\*(DC\*(ST) if [ \(mif $i ]
|
||||||
|
\*(DC then cp $i junk$$; mv junk$$ $i
|
||||||
|
\*(DC elif [ $flag ]
|
||||||
|
\*(DC then echo file \\'$i\\' does not exist
|
||||||
|
\*(DC else >$i
|
||||||
|
\*(DC fi
|
||||||
|
\*(DO esac
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
The \fB\(mic\fP flag is used in this command to
|
||||||
|
force subsequent files to be created if they do not already exist.
|
||||||
|
Otherwise, if the file does not exist, an error message is printed.
|
||||||
|
The shell variable \fIflag\fP
|
||||||
|
is set to some non-null string if the \fB\(mic\fP
|
||||||
|
argument is encountered.
|
||||||
|
The commands
|
||||||
|
.DS
|
||||||
|
cp \*(ZZ; mv \*(ZZ
|
||||||
|
.DE
|
||||||
|
copy the file and then overwrite it with the copy,
|
||||||
|
thus causing the last modified date to be updated.
|
||||||
|
.LP
|
||||||
|
The sequence
|
||||||
|
.DS
|
||||||
|
if command1
|
||||||
|
then command2
|
||||||
|
fi
|
||||||
|
.DE
|
||||||
|
may be written
|
||||||
|
.DS
|
||||||
|
command1 && command2
|
||||||
|
.DE
|
||||||
|
Conversely,
|
||||||
|
.DS
|
||||||
|
command1 \*(VT\*(VT command2
|
||||||
|
.DE
|
||||||
|
executes \fIcommand2\fP only if \fIcommand1\fP
|
||||||
|
fails.
|
||||||
|
In each case the value returned
|
||||||
|
is that of the last simple command executed.
|
||||||
|
.LP
|
||||||
|
Placing a `\fB!\fP' in front of a pipeline inverts its exit
|
||||||
|
status, almost in the manner of the C operator of the same name.
|
||||||
|
Thus:
|
||||||
|
.DS
|
||||||
|
if ! [ -d $1 ]
|
||||||
|
then
|
||||||
|
echo $1 is not a directory
|
||||||
|
fi
|
||||||
|
.DE
|
||||||
|
will print a message only if $1 is not a directory.
|
||||||
|
.SH
|
||||||
|
2.8\ Command\ grouping
|
||||||
|
.LP
|
||||||
|
Commands may be grouped in two ways,
|
||||||
|
.DS
|
||||||
|
\fB{\fI command-list\fB ; }\fR
|
||||||
|
.DE
|
||||||
|
and
|
||||||
|
.DS
|
||||||
|
\fB(\fI command-list\fB )\fR
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
In the first \fIcommand-list\fP is simply executed.
|
||||||
|
The second form executes \fIcommand-list\fP
|
||||||
|
as a separate process.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
(cd x; rm junk )
|
||||||
|
.DE
|
||||||
|
executes \fIrm junk\fP in the directory
|
||||||
|
\fBx\fP without changing the current
|
||||||
|
directory of the invoking shell.
|
||||||
|
.LP
|
||||||
|
The commands
|
||||||
|
.DS
|
||||||
|
cd x; rm junk
|
||||||
|
.DE
|
||||||
|
have the same effect but leave the invoking
|
||||||
|
shell in the directory \fBx.\fP
|
||||||
|
.SH
|
||||||
|
2.9\ Shell\ Functions
|
||||||
|
.LP
|
||||||
|
A function may be defined by the syntax
|
||||||
|
.DS
|
||||||
|
\fIfuncname\fP() \fB{\fI command-list\fB ; }\fR
|
||||||
|
.DE
|
||||||
|
Functions are invoked within a script as though they were separate
|
||||||
|
commands of the same name.
|
||||||
|
While they are executed, the
|
||||||
|
positional parameters \fB$1, $2, \*(ZZ\fR are temporarily set to the
|
||||||
|
arguments passed to the function. For example:
|
||||||
|
.DS
|
||||||
|
count() {
|
||||||
|
echo $2 : $#
|
||||||
|
}
|
||||||
|
|
||||||
|
count a b c
|
||||||
|
.DE
|
||||||
|
would print `b : 3'.
|
||||||
|
.SH
|
||||||
|
2.10\ Debugging\ shell\ scripts
|
||||||
|
.LP
|
||||||
|
The shell provides two tracing mechanisms
|
||||||
|
to help when debugging shell scripts.
|
||||||
|
The first is invoked within the script
|
||||||
|
as
|
||||||
|
.DS
|
||||||
|
set \(miv
|
||||||
|
.DE
|
||||||
|
(\fBv\fP for verbose) and causes lines of the
|
||||||
|
script to be printed as they are read.
|
||||||
|
It is useful to help isolate syntax errors.
|
||||||
|
It may be invoked without modifying the script
|
||||||
|
by saying
|
||||||
|
.DS
|
||||||
|
sh \(miv \fIscript\fP \*(ZZ
|
||||||
|
.DE
|
||||||
|
where \fIscript\fP is the name of the shell script.
|
||||||
|
This flag may be used in conjunction
|
||||||
|
with the \fB\(min\fP flag which prevents
|
||||||
|
execution of subsequent commands.
|
||||||
|
(Note that saying \fIset \(min\fP at a terminal
|
||||||
|
will render the terminal useless
|
||||||
|
until an end-of-file is typed.)
|
||||||
|
.LP
|
||||||
|
The command
|
||||||
|
.DS
|
||||||
|
set \(mix
|
||||||
|
.DE
|
||||||
|
will produce an execution
|
||||||
|
trace.
|
||||||
|
Following parameter substitution
|
||||||
|
each command is printed as it is executed.
|
||||||
|
(Try these at the terminal to see
|
||||||
|
what effect they have.)
|
||||||
|
Both flags may be turned off by saying
|
||||||
|
.DS
|
||||||
|
set \(mi
|
||||||
|
.DE
|
||||||
|
and the current setting of the shell flags is available as \fB$\(mi\|\fR.
|
||||||
|
.SH
|
||||||
|
2.11\ The\ man\ command
|
||||||
|
.LP
|
||||||
|
The following is a simple implementation of the \fIman\fP command,
|
||||||
|
which is used to display sections of the UNIX manual on your terminal.
|
||||||
|
It is called, for example, as
|
||||||
|
.DS
|
||||||
|
man sh
|
||||||
|
man \(mit ed
|
||||||
|
man 2 fork
|
||||||
|
.DE
|
||||||
|
In the first the manual section for \fIsh\fP
|
||||||
|
is displayed..
|
||||||
|
Since no section is specified, section 1 is used.
|
||||||
|
The second example will typeset (\fB\(mit\fP option)
|
||||||
|
the manual section for \fIed.\fP
|
||||||
|
The last prints the \fIfork\fP manual page
|
||||||
|
from section 2, which covers system calls.
|
||||||
|
.sp 2
|
||||||
|
.DS
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd /usr/share/man
|
||||||
|
|
||||||
|
# "#" is the comment character
|
||||||
|
# default is nroff ($N), section 1 ($s)
|
||||||
|
N=n\ s=1
|
||||||
|
|
||||||
|
for i
|
||||||
|
do case $i in
|
||||||
|
.sp .5
|
||||||
|
\*(DC[1\(mi9]\*(ST) s=$i ;;
|
||||||
|
.sp .5
|
||||||
|
\*(DC\(mit) N=t ;;
|
||||||
|
.sp .5
|
||||||
|
\*(DC\(min) N=n ;;
|
||||||
|
.sp .5
|
||||||
|
\*(DC\(mi\*(ST) echo unknown flag \\'$i\\' ;;
|
||||||
|
.sp .5
|
||||||
|
\*(DC\*(ST) if [ \(mif man$s/$i.$s ]
|
||||||
|
\*(DC then
|
||||||
|
\*(DC ${N}roff \(miman man$s/$i.$s
|
||||||
|
\*(DC else # look through all manual sections
|
||||||
|
\*(DC found=no
|
||||||
|
\*(DC for j in 1 2 3 4 5 6 7 8 9
|
||||||
|
\*(DC do
|
||||||
|
\*(DC \*(DOif [ \(mif man$j/$i.$j ]
|
||||||
|
\*(DC \*(DOthen
|
||||||
|
\*(DC \*(DO\*(THman $j $i
|
||||||
|
\*(DC \*(DO\*(THfound=yes
|
||||||
|
\*(DC \*(DO\*(THbreak
|
||||||
|
\*(DC \*(DOfi
|
||||||
|
\*(DC done
|
||||||
|
\*(DC case $found in
|
||||||
|
\*(DC \*(Cano) echo \\'$i: manual page not found\\'
|
||||||
|
\*(DC esac
|
||||||
|
\*(DC fi
|
||||||
|
\*(DOesac
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
.ce
|
||||||
|
.ft B
|
||||||
|
Figure 1. A version of the man command
|
||||||
|
.ft R
|
976
bin/sh/USD.doc/t3
Normal file
976
bin/sh/USD.doc/t3
Normal file
|
@ -0,0 +1,976 @@
|
||||||
|
.\" $NetBSD: t3,v 1.3 2010/08/22 02:19:07 perry Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions are
|
||||||
|
.\" met:
|
||||||
|
.\"
|
||||||
|
.\" Redistributions of source code and documentation must retain the above
|
||||||
|
.\" copyright notice, this list of conditions and the following
|
||||||
|
.\" disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.\" All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\"
|
||||||
|
.\" This product includes software developed or owned by Caldera
|
||||||
|
.\" International, Inc. Neither the name of Caldera International, Inc.
|
||||||
|
.\" nor the names of other contributors may be used to endorse or promote
|
||||||
|
.\" products derived from this software without specific prior written
|
||||||
|
.\" permission.
|
||||||
|
.\"
|
||||||
|
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||||
|
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)t3 8.1 (Berkeley) 6/8/93
|
||||||
|
.\"
|
||||||
|
.SH
|
||||||
|
3.0\ Keyword\ parameters
|
||||||
|
.LP
|
||||||
|
Shell variables may be given values
|
||||||
|
by assignment
|
||||||
|
or when a shell script is invoked.
|
||||||
|
An argument to a command of the form
|
||||||
|
\fIname=value\fP
|
||||||
|
that precedes the command name
|
||||||
|
causes \fIvalue\fP
|
||||||
|
to be assigned to \fIname\fP
|
||||||
|
before execution of the command begins.
|
||||||
|
The value of \fIname\fP in the invoking
|
||||||
|
shell is not affected.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
user=fred\ command
|
||||||
|
.DE
|
||||||
|
will execute \fIcommand\fP with
|
||||||
|
\fBuser\fP set to \fIfred\fP.
|
||||||
|
.\" Removed by Perry Metzger because -k is not in POSIX
|
||||||
|
.\"
|
||||||
|
.\" The \fB\(mik\fR flag causes arguments of the form
|
||||||
|
.\" \fIname=value\fP to be interpreted in this way
|
||||||
|
.\" anywhere in the argument list.
|
||||||
|
.\" Such \fInames\fP are sometimes
|
||||||
|
.\" called keyword parameters.
|
||||||
|
.\" If any arguments remain they
|
||||||
|
.\" are available as positional
|
||||||
|
.\" parameters \fB$1, $2, \*(ZZ\|.\fP
|
||||||
|
.LP
|
||||||
|
The \fIset\fP command
|
||||||
|
may also be used to set positional parameters
|
||||||
|
from within a script.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
set\ \(mi\(mi\ \*(ST
|
||||||
|
.DE
|
||||||
|
will set \fB$1\fP to the first file name
|
||||||
|
in the current directory, \fB$2\fP to the next,
|
||||||
|
and so on.
|
||||||
|
Note that the first argument, \(mi\(mi, ensures correct treatment
|
||||||
|
when the first file name begins with a \(mi\|.
|
||||||
|
.LP
|
||||||
|
.SH
|
||||||
|
3.1\ Parameter\ transmission
|
||||||
|
.LP
|
||||||
|
When a command is executed both positional parameters
|
||||||
|
and shell variables may be set on invocation.
|
||||||
|
Variables are also made available implicitly
|
||||||
|
to a command
|
||||||
|
by specifying in advance that such parameters
|
||||||
|
are to be exported from the invoking shell.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
export\ user\ box=red
|
||||||
|
.DE
|
||||||
|
marks the variables \fBuser\fP and \fBbox\fP
|
||||||
|
for export (setting \fBbox\fP to ``red'' in the process).
|
||||||
|
When a command is invoked
|
||||||
|
copies are made of all exportable variables
|
||||||
|
(also known as \fIenvironment variables\fP)
|
||||||
|
for use within the invoked program.
|
||||||
|
Modification of such variables
|
||||||
|
within an invoked command does not
|
||||||
|
affect the values in the invoking shell.
|
||||||
|
It is generally true of
|
||||||
|
a shell script or other program
|
||||||
|
that it
|
||||||
|
cannot modify the state
|
||||||
|
of its caller without explicit
|
||||||
|
actions on the part of the caller.
|
||||||
|
.\" Removed by Perry Metzger because this is confusing to beginners.
|
||||||
|
.\"
|
||||||
|
.\" (Shared file descriptors are an
|
||||||
|
.\" exception to this rule.)
|
||||||
|
.LP
|
||||||
|
Names whose value is intended to remain
|
||||||
|
constant may be declared \fIreadonly\|.\fP
|
||||||
|
The form of this command is the same as that of the \fIexport\fP
|
||||||
|
command,
|
||||||
|
.DS
|
||||||
|
readonly name[=value] \*(ZZ
|
||||||
|
.DE
|
||||||
|
Subsequent attempts to set readonly variables
|
||||||
|
are illegal.
|
||||||
|
.SH
|
||||||
|
3.2\ Parameter\ substitution
|
||||||
|
.LP
|
||||||
|
If a shell parameter is not set
|
||||||
|
then the null string is substituted for it.
|
||||||
|
For example, if the variable \fBd\fP
|
||||||
|
is not set
|
||||||
|
.DS
|
||||||
|
echo $d
|
||||||
|
.DE
|
||||||
|
or
|
||||||
|
.DS
|
||||||
|
echo ${d}
|
||||||
|
.DE
|
||||||
|
will echo nothing.
|
||||||
|
A default string may be given
|
||||||
|
as in
|
||||||
|
.DS
|
||||||
|
echo ${d:\(mi\fB.\fR}
|
||||||
|
.DE
|
||||||
|
which will echo
|
||||||
|
the value of the variable \fBd\fP
|
||||||
|
if it is set and not null and `\fB.\fP' otherwise.
|
||||||
|
The default string is evaluated using the usual
|
||||||
|
quoting conventions so that
|
||||||
|
.DS
|
||||||
|
echo ${d:\(mi\'\*(ST\'}
|
||||||
|
.DE
|
||||||
|
will echo \fB\*(ST\fP if the variable \fBd\fP
|
||||||
|
is not set or null.
|
||||||
|
Similarly
|
||||||
|
.DS
|
||||||
|
echo ${d:\(mi$1}
|
||||||
|
.DE
|
||||||
|
will echo the value of \fBd\fP if it is set and not null
|
||||||
|
and the value (if any) of \fB$1\fP otherwise.
|
||||||
|
.LP
|
||||||
|
The notation ${d:+\fB.\fR} performs the inverse operation. It
|
||||||
|
substitutes `\fB.\fP' if \fBd\fP is set or not null, and otherwise
|
||||||
|
substitutes null.
|
||||||
|
.LP
|
||||||
|
A variable may be assigned a default value
|
||||||
|
using
|
||||||
|
the notation
|
||||||
|
.DS
|
||||||
|
echo ${d:=\fB.\fR}
|
||||||
|
.DE
|
||||||
|
which substitutes the same string as
|
||||||
|
.DS
|
||||||
|
echo ${d:\(mi\fB.\fR}
|
||||||
|
.DE
|
||||||
|
and if \fBd\fP were not previously set or null
|
||||||
|
then it will be set to the string `\fB.\fP'\|.
|
||||||
|
.LP
|
||||||
|
If there is no sensible default then
|
||||||
|
the notation
|
||||||
|
.DS
|
||||||
|
echo ${d:?\fImessage\fP}
|
||||||
|
.DE
|
||||||
|
will echo the value of the variable \fBd\fP if it is set and not null,
|
||||||
|
otherwise \fImessage\fP is printed by the shell and
|
||||||
|
execution of the shell script is abandoned.
|
||||||
|
If \fImessage\fP is absent then a standard message
|
||||||
|
is printed.
|
||||||
|
A shell script that requires some variables
|
||||||
|
to be set might start as follows:
|
||||||
|
.DS
|
||||||
|
:\ ${user:?}\ ${acct:?}\ ${bin:?}
|
||||||
|
\*(ZZ
|
||||||
|
.DE
|
||||||
|
Colon (\fB:\fP) is a command
|
||||||
|
that is
|
||||||
|
built in to the shell and does nothing
|
||||||
|
once its arguments have been evaluated.
|
||||||
|
If any of the variables \fBuser, acct\fP
|
||||||
|
or \fBbin\fP are not set then the shell
|
||||||
|
will abandon execution of the script.
|
||||||
|
.SH
|
||||||
|
3.3\ Command\ substitution
|
||||||
|
.LP
|
||||||
|
The standard output from a command can be
|
||||||
|
substituted in a similar way to parameters.
|
||||||
|
The command \fIpwd\fP prints on its standard
|
||||||
|
output the name of the current directory.
|
||||||
|
For example, if the current directory is
|
||||||
|
\fB/usr/fred/bin\fR
|
||||||
|
then the commands
|
||||||
|
.DS
|
||||||
|
d=$(pwd)
|
||||||
|
.DE
|
||||||
|
(or the older notation d=\`pwd\`)
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
d=/usr/fred/bin
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The entire string inside $(\*(ZZ)\| (or between grave accents \`\*(ZZ\`)
|
||||||
|
is taken as the command
|
||||||
|
to be executed
|
||||||
|
and is replaced with the output from
|
||||||
|
the command.
|
||||||
|
(The difference between the $(\*(ZZ) and \`\*(ZZ\` notations is that
|
||||||
|
the former may be nested, while the latter cannot be.)
|
||||||
|
.LP
|
||||||
|
The command is written using the usual quoting conventions,
|
||||||
|
except that inside \`\*(ZZ\`
|
||||||
|
a \fB\`\fR must be escaped using
|
||||||
|
a \fB\\\|\fR.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
ls $(echo "$HOME")
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
ls $HOME
|
||||||
|
.DE
|
||||||
|
Command substitution occurs in all contexts
|
||||||
|
where parameter substitution occurs (including \fIhere\fP documents) and the
|
||||||
|
treatment of the resulting text is the same
|
||||||
|
in both cases.
|
||||||
|
This mechanism allows string
|
||||||
|
processing commands to be used within
|
||||||
|
shell scripts.
|
||||||
|
An example of such a command is \fIbasename\fP
|
||||||
|
which removes a specified suffix from a string.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
basename main\fB.\fPc \fB.\fPc
|
||||||
|
.DE
|
||||||
|
will print the string \fImain\|.\fP
|
||||||
|
Its use is illustrated by the following
|
||||||
|
fragment from a \fIcc\fP command.
|
||||||
|
.DS
|
||||||
|
case $A in
|
||||||
|
\*(Ca\*(ZZ
|
||||||
|
\*(Ca\*(ST\fB.\fPc) B=$(basename $A \fB.\fPc)
|
||||||
|
\*(Ca\*(ZZ
|
||||||
|
esac
|
||||||
|
.DE
|
||||||
|
that sets \fBB\fP to the part of \fB$A\fP
|
||||||
|
with the suffix \fB.c\fP stripped.
|
||||||
|
.LP
|
||||||
|
Here are some composite examples.
|
||||||
|
.RS
|
||||||
|
.IP \(bu
|
||||||
|
.ft B
|
||||||
|
for i in \`ls \(mit\`; do \*(ZZ
|
||||||
|
.ft R
|
||||||
|
.br
|
||||||
|
The variable \fBi\fP is set
|
||||||
|
to the names of files in time order,
|
||||||
|
most recent first.
|
||||||
|
.IP \(bu
|
||||||
|
.ft B
|
||||||
|
set \(mi\(mi\| \`date\`; echo $6 $2 $3, $4
|
||||||
|
.ft R
|
||||||
|
.br
|
||||||
|
will print, e.g.,
|
||||||
|
.ft I
|
||||||
|
1977 Nov 1, 23:59:59
|
||||||
|
.ft R
|
||||||
|
.RE
|
||||||
|
.SH
|
||||||
|
3.4\ Arithmetic\ Expansion
|
||||||
|
.LP
|
||||||
|
Within a $((\*(ZZ)) construct, integer arithmetic operations are
|
||||||
|
evaluated.
|
||||||
|
(The $ in front of variable names is optional within $((\*(ZZ)).
|
||||||
|
For example:
|
||||||
|
.DS
|
||||||
|
x=5; y=1
|
||||||
|
echo $(($x+3*2))
|
||||||
|
echo $((y+=x))
|
||||||
|
echo $y
|
||||||
|
.DE
|
||||||
|
will print `11', then `6', then `6' again.
|
||||||
|
Most of the constructs permitted in C arithmetic operations are
|
||||||
|
permitted though some (like `++') are not universally supported \(em
|
||||||
|
see the shell manual page for details.
|
||||||
|
.SH
|
||||||
|
3.5\ Evaluation\ and\ quoting
|
||||||
|
.LP
|
||||||
|
The shell is a macro processor that
|
||||||
|
provides parameter substitution, command substitution and file
|
||||||
|
name generation for the arguments to commands.
|
||||||
|
This section discusses the order in which
|
||||||
|
these evaluations occur and the
|
||||||
|
effects of the various quoting mechanisms.
|
||||||
|
.LP
|
||||||
|
Commands are parsed initially according to the grammar
|
||||||
|
given in appendix A.
|
||||||
|
Before a command is executed
|
||||||
|
the following
|
||||||
|
substitutions occur.
|
||||||
|
.RS
|
||||||
|
.IP \(bu
|
||||||
|
parameter substitution, e.g. \fB$user\fP
|
||||||
|
.IP \(bu
|
||||||
|
command substitution, e.g. \fB$(pwd)\fP or \fB\`pwd\`\fP
|
||||||
|
.IP \(bu
|
||||||
|
arithmetic expansion, e.g. \fB$(($count+1))\fP
|
||||||
|
.RS
|
||||||
|
.LP
|
||||||
|
Only one evaluation occurs so that if, for example, the value of the variable
|
||||||
|
\fBX\fP
|
||||||
|
is the string \fI$y\fP
|
||||||
|
then
|
||||||
|
.DS
|
||||||
|
echo $X
|
||||||
|
.DE
|
||||||
|
will echo \fI$y\|.\fP
|
||||||
|
.RE
|
||||||
|
.IP \(bu
|
||||||
|
blank interpretation
|
||||||
|
.RS
|
||||||
|
.LP
|
||||||
|
Following the above substitutions
|
||||||
|
the resulting characters
|
||||||
|
are broken into non-blank words (\fIblank interpretation\fP).
|
||||||
|
For this purpose `blanks' are the characters of the string
|
||||||
|
\fB$\s-1IFS\s0\fP.
|
||||||
|
By default, this string consists of blank, tab and newline.
|
||||||
|
The null string
|
||||||
|
is not regarded as a word unless it is quoted.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
echo \'\'
|
||||||
|
.DE
|
||||||
|
will pass on the null string as the first argument to \fIecho\fP,
|
||||||
|
whereas
|
||||||
|
.DS
|
||||||
|
echo $null
|
||||||
|
.DE
|
||||||
|
will call \fIecho\fR with no arguments
|
||||||
|
if the variable \fBnull\fP is not set
|
||||||
|
or set to the null string.
|
||||||
|
.RE
|
||||||
|
.IP \(bu
|
||||||
|
file name generation
|
||||||
|
.RS
|
||||||
|
.LP
|
||||||
|
Each word
|
||||||
|
is then scanned for the file pattern characters
|
||||||
|
\fB\*(ST, ?\fR and \fB[\*(ZZ]\fR
|
||||||
|
and an alphabetical list of file names
|
||||||
|
is generated to replace the word.
|
||||||
|
Each such file name is a separate argument.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
The evaluations just described also occur
|
||||||
|
in the list of words associated with a \fBfor\fP
|
||||||
|
loop.
|
||||||
|
Only substitution occurs
|
||||||
|
in the \fIword\fP used
|
||||||
|
for a \fBcase\fP branch.
|
||||||
|
.LP
|
||||||
|
As well as the quoting mechanisms described
|
||||||
|
earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR
|
||||||
|
a third quoting mechanism is provided using double quotes.
|
||||||
|
Within double quotes parameter and command substitution
|
||||||
|
occurs but file name generation and the interpretation
|
||||||
|
of blanks does not.
|
||||||
|
The following characters
|
||||||
|
have a special meaning within double quotes
|
||||||
|
and may be quoted using \fB\\\|.\fP
|
||||||
|
.DS
|
||||||
|
\fB$ \fPparameter substitution
|
||||||
|
\fB$()\fP command substitution
|
||||||
|
\fB\`\fP command substitution
|
||||||
|
\fB"\fP ends the quoted string
|
||||||
|
\fB\e\fP quotes the special characters \fB$ \` " \e\fP
|
||||||
|
.DE
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
echo "$x"
|
||||||
|
.DE
|
||||||
|
will pass the value of the variable \fBx\fP as a
|
||||||
|
single argument to \fIecho.\fP
|
||||||
|
Similarly,
|
||||||
|
.DS
|
||||||
|
echo "$\*(ST"
|
||||||
|
.DE
|
||||||
|
will pass the positional parameters as a single
|
||||||
|
argument and is equivalent to
|
||||||
|
.DS
|
||||||
|
echo "$1 $2 \*(ZZ"
|
||||||
|
.DE
|
||||||
|
The notation \fB$@\fP
|
||||||
|
is the same as \fB$\*(ST\fR
|
||||||
|
except when it is quoted.
|
||||||
|
.DS
|
||||||
|
echo "$@"
|
||||||
|
.DE
|
||||||
|
will pass the positional parameters, unevaluated, to \fIecho\fR
|
||||||
|
and is equivalent to
|
||||||
|
.DS
|
||||||
|
echo "$1" "$2" \*(ZZ
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The following table gives, for each quoting mechanism,
|
||||||
|
the shell metacharacters that are evaluated.
|
||||||
|
.DS
|
||||||
|
.ce
|
||||||
|
.ft I
|
||||||
|
metacharacter
|
||||||
|
.ft
|
||||||
|
.in 1.5i
|
||||||
|
\e $ * \` " \'
|
||||||
|
\' n n n n n t
|
||||||
|
\` y n n t n n
|
||||||
|
" y y n y t n
|
||||||
|
|
||||||
|
t terminator
|
||||||
|
y interpreted
|
||||||
|
n not interpreted
|
||||||
|
|
||||||
|
.in
|
||||||
|
.ft B
|
||||||
|
.ce
|
||||||
|
Figure 2. Quoting mechanisms
|
||||||
|
.ft
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
In cases where more than one evaluation of a string
|
||||||
|
is required the built-in command \fIeval\fP
|
||||||
|
may be used.
|
||||||
|
For example,
|
||||||
|
if the variable \fBX\fP has the value
|
||||||
|
\fI$y\fP, and if \fBy\fP has the value \fIpqr\fP
|
||||||
|
then
|
||||||
|
.DS
|
||||||
|
eval echo $X
|
||||||
|
.DE
|
||||||
|
will echo the string \fIpqr\|.\fP
|
||||||
|
.LP
|
||||||
|
In general the \fIeval\fP command
|
||||||
|
evaluates its arguments (as do all commands)
|
||||||
|
and treats the result as input to the shell.
|
||||||
|
The input is read and the resulting command(s)
|
||||||
|
executed.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
wg=\'eval who\*(VTgrep\'
|
||||||
|
$wg fred
|
||||||
|
.DE
|
||||||
|
is equivalent to
|
||||||
|
.DS
|
||||||
|
who\*(VTgrep fred
|
||||||
|
.DE
|
||||||
|
In this example,
|
||||||
|
\fIeval\fP is required
|
||||||
|
since there is no interpretation
|
||||||
|
of metacharacters, such as \fB\*(VT\|\fR, following
|
||||||
|
substitution.
|
||||||
|
.SH
|
||||||
|
3.6\ Error\ handling
|
||||||
|
.LP
|
||||||
|
The treatment of errors detected by
|
||||||
|
the shell depends on the type of error
|
||||||
|
and on whether the shell is being
|
||||||
|
used interactively.
|
||||||
|
An interactive shell is one whose
|
||||||
|
input and output are connected
|
||||||
|
to a terminal.
|
||||||
|
.\" Removed by Perry Metzger, obsolete and excess detail
|
||||||
|
.\"
|
||||||
|
.\" (as determined by
|
||||||
|
.\" \fIgtty\fP (2)).
|
||||||
|
A shell invoked with the \fB\(mii\fP
|
||||||
|
flag is also interactive.
|
||||||
|
.LP
|
||||||
|
Execution of a command (see also 3.7) may fail
|
||||||
|
for any of the following reasons.
|
||||||
|
.IP \(bu
|
||||||
|
Input output redirection may fail.
|
||||||
|
For example, if a file does not exist
|
||||||
|
or cannot be created.
|
||||||
|
.IP \(bu
|
||||||
|
The command itself does not exist
|
||||||
|
or cannot be executed.
|
||||||
|
.IP \(bu
|
||||||
|
The command terminates abnormally,
|
||||||
|
for example, with a "bus error"
|
||||||
|
or "memory fault".
|
||||||
|
See Figure 2 below for a complete list
|
||||||
|
of UNIX signals.
|
||||||
|
.IP \(bu
|
||||||
|
The command terminates normally
|
||||||
|
but returns a non-zero exit status.
|
||||||
|
.LP
|
||||||
|
In all of these cases the shell
|
||||||
|
will go on to execute the next command.
|
||||||
|
Except for the last case an error
|
||||||
|
message will be printed by the shell.
|
||||||
|
All remaining errors cause the shell
|
||||||
|
to exit from a script.
|
||||||
|
An interactive shell will return
|
||||||
|
to read another command from the terminal.
|
||||||
|
Such errors include the following.
|
||||||
|
.IP \(bu
|
||||||
|
Syntax errors.
|
||||||
|
e.g., if \*(ZZ then \*(ZZ done
|
||||||
|
.IP \(bu
|
||||||
|
A signal such as interrupt.
|
||||||
|
The shell waits for the current
|
||||||
|
command, if any, to finish execution and
|
||||||
|
then either exits or returns to the terminal.
|
||||||
|
.IP \(bu
|
||||||
|
Failure of any of the built-in commands
|
||||||
|
such as \fIcd.\fP
|
||||||
|
.LP
|
||||||
|
The shell flag \fB\(mie\fP
|
||||||
|
causes the shell to terminate
|
||||||
|
if any error is detected.
|
||||||
|
.DS
|
||||||
|
1 hangup
|
||||||
|
2 interrupt
|
||||||
|
3* quit
|
||||||
|
4* illegal instruction
|
||||||
|
5* trace trap
|
||||||
|
6* IOT instruction
|
||||||
|
7* EMT instruction
|
||||||
|
8* floating point exception
|
||||||
|
9 kill (cannot be caught or ignored)
|
||||||
|
10* bus error
|
||||||
|
11* segmentation violation
|
||||||
|
12* bad argument to system call
|
||||||
|
13 write on a pipe with no one to read it
|
||||||
|
14 alarm clock
|
||||||
|
15 software termination (from \fIkill\fP (1))
|
||||||
|
|
||||||
|
.DE
|
||||||
|
.ft B
|
||||||
|
.ce
|
||||||
|
Figure 3. UNIX signals\(dg
|
||||||
|
.ft
|
||||||
|
.FS
|
||||||
|
\(dg Additional signals have been added in modern Unix.
|
||||||
|
See \fIsigvec\fP(2) or \fIsignal\fP(3) for an up-to-date list.
|
||||||
|
.FE
|
||||||
|
Those signals marked with an asterisk
|
||||||
|
produce a core dump
|
||||||
|
if not caught.
|
||||||
|
However,
|
||||||
|
the shell itself ignores quit which is the only
|
||||||
|
external signal that can cause a dump.
|
||||||
|
The signals in this list of potential interest
|
||||||
|
to shell programs are 1, 2, 3, 14 and 15.
|
||||||
|
.SH
|
||||||
|
3.7\ Fault\ handling
|
||||||
|
.LP
|
||||||
|
shell scripts normally terminate
|
||||||
|
when an interrupt is received from the
|
||||||
|
terminal.
|
||||||
|
The \fItrap\fP command is used
|
||||||
|
if some cleaning up is required, such
|
||||||
|
as removing temporary files.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
trap\ \'rm\ /tmp/ps$$; exit\'\ 2
|
||||||
|
.DE
|
||||||
|
sets a trap for signal 2 (terminal
|
||||||
|
interrupt), and if this signal is received
|
||||||
|
will execute the commands
|
||||||
|
.DS
|
||||||
|
rm /tmp/ps$$; exit
|
||||||
|
.DE
|
||||||
|
\fIexit\fP is
|
||||||
|
another built-in command
|
||||||
|
that terminates execution of a shell script.
|
||||||
|
The \fIexit\fP is required; otherwise,
|
||||||
|
after the trap has been taken,
|
||||||
|
the shell will resume executing
|
||||||
|
the script
|
||||||
|
at the place where it was interrupted.
|
||||||
|
.LP
|
||||||
|
UNIX signals can be handled in one of three ways.
|
||||||
|
They can be ignored, in which case
|
||||||
|
the signal is never sent to the process.
|
||||||
|
They can be caught, in which case the process
|
||||||
|
must decide what action to take when the
|
||||||
|
signal is received.
|
||||||
|
Lastly, they can be left to cause
|
||||||
|
termination of the process without
|
||||||
|
it having to take any further action.
|
||||||
|
If a signal is being ignored
|
||||||
|
on entry to the shell script, for example,
|
||||||
|
by invoking it in the background (see 3.7) then \fItrap\fP
|
||||||
|
commands (and the signal) are ignored.
|
||||||
|
.LP
|
||||||
|
The use of \fItrap\fP is illustrated
|
||||||
|
by this modified version of the \fItouch\fP
|
||||||
|
command (Figure 4).
|
||||||
|
The cleanup action is to remove the file \fBjunk$$\fR\|.
|
||||||
|
.DS
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
flag=
|
||||||
|
trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15
|
||||||
|
for i
|
||||||
|
do\ case\ $i\ in
|
||||||
|
\*(DC\(mic) flag=N ;;
|
||||||
|
\*(DC\*(ST) if\ test\ \(mif\ $i
|
||||||
|
\*(DC then cp\ $i\ junk$$;\ mv\ junk$$ $i
|
||||||
|
\*(DC elif\ test\ $flag
|
||||||
|
\*(DC then echo\ file\ \\'$i\\'\ does\ not\ exist
|
||||||
|
\*(DC else >$i
|
||||||
|
\*(DC fi
|
||||||
|
\*(DOesac
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
.sp
|
||||||
|
.ft B
|
||||||
|
.ce
|
||||||
|
Figure 4. The touch command
|
||||||
|
.ft
|
||||||
|
.sp
|
||||||
|
The \fItrap\fP command
|
||||||
|
appears before the creation
|
||||||
|
of the temporary file;
|
||||||
|
otherwise it would be
|
||||||
|
possible for the process
|
||||||
|
to die without removing
|
||||||
|
the file.
|
||||||
|
.LP
|
||||||
|
Since there is no signal 0 in UNIX
|
||||||
|
it is used by the shell to indicate the
|
||||||
|
commands to be executed on exit from the
|
||||||
|
shell script.
|
||||||
|
.LP
|
||||||
|
A script may, itself, elect to
|
||||||
|
ignore signals by specifying the null
|
||||||
|
string as the argument to trap.
|
||||||
|
The following fragment is taken from the
|
||||||
|
\fInohup\fP command.
|
||||||
|
.DS
|
||||||
|
trap \'\' 1 2 3 15
|
||||||
|
.DE
|
||||||
|
which causes \fIhangup, interrupt, quit \fRand\fI kill\fR
|
||||||
|
to be ignored both by the
|
||||||
|
script and by invoked commands.
|
||||||
|
.LP
|
||||||
|
Traps may be reset by saying
|
||||||
|
.DS
|
||||||
|
trap 2 3
|
||||||
|
.DE
|
||||||
|
which resets the traps for signals 2 and 3 to their default values.
|
||||||
|
A list of the current values of traps may be obtained
|
||||||
|
by writing
|
||||||
|
.DS
|
||||||
|
trap
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
The script \fIscan\fP (Figure 5) is an example
|
||||||
|
of the use of \fItrap\fP where there is no exit
|
||||||
|
in the trap command.
|
||||||
|
\fIscan\fP takes each directory
|
||||||
|
in the current directory, prompts
|
||||||
|
with its name, and then executes
|
||||||
|
commands typed at the terminal
|
||||||
|
until an end of file or an interrupt is received.
|
||||||
|
Interrupts are ignored while executing
|
||||||
|
the requested commands but cause
|
||||||
|
termination when \fIscan\fP is
|
||||||
|
waiting for input.
|
||||||
|
.DS
|
||||||
|
d=\`pwd\`
|
||||||
|
for\ i\ in\ \*(ST
|
||||||
|
do\ if\ test\ \(mid\ $d/$i
|
||||||
|
\*(DOthen\ cd\ $d/$i
|
||||||
|
\*(DO\*(THwhile\ echo\ "$i:"
|
||||||
|
\*(DO\*(TH\*(WHtrap\ exit\ 2
|
||||||
|
\*(DO\*(TH\*(WHread\ x
|
||||||
|
\*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done
|
||||||
|
\*(DOfi
|
||||||
|
done
|
||||||
|
.DE
|
||||||
|
.sp
|
||||||
|
.ft B
|
||||||
|
.ce
|
||||||
|
Figure 5. The scan command
|
||||||
|
.ft
|
||||||
|
.sp
|
||||||
|
\fIread x\fR is a built-in command that reads one line from the
|
||||||
|
standard input
|
||||||
|
and places the result in the variable \fBx\|.\fP
|
||||||
|
It returns a non-zero exit status if either
|
||||||
|
an end-of-file is read or an interrupt
|
||||||
|
is received.
|
||||||
|
.SH
|
||||||
|
3.8\ Command\ execution
|
||||||
|
.LP
|
||||||
|
To run a command (other than a built-in) the shell first creates
|
||||||
|
a new process using the system call \fIfork.\fP
|
||||||
|
The execution environment for the command
|
||||||
|
includes input, output and the states of signals, and
|
||||||
|
is established in the child process
|
||||||
|
before the command is executed.
|
||||||
|
The built-in command \fIexec\fP
|
||||||
|
is used in the rare cases when no fork
|
||||||
|
is required
|
||||||
|
and simply replaces the shell with a new command.
|
||||||
|
For example, a simple version of the \fInohup\fP
|
||||||
|
command looks like
|
||||||
|
.DS
|
||||||
|
trap \\'\\' 1 2 3 15
|
||||||
|
exec $\*(ST
|
||||||
|
.DE
|
||||||
|
The \fItrap\fP turns off the signals specified
|
||||||
|
so that they are ignored by subsequently created commands
|
||||||
|
and \fIexec\fP replaces the shell by the command
|
||||||
|
specified.
|
||||||
|
.LP
|
||||||
|
Most forms of input output redirection have already been
|
||||||
|
described.
|
||||||
|
In the following \fIword\fP is only subject
|
||||||
|
to parameter and command substitution.
|
||||||
|
No file name generation or blank interpretation
|
||||||
|
takes place so that, for example,
|
||||||
|
.DS
|
||||||
|
echo \*(ZZ >\*(ST.c
|
||||||
|
.DE
|
||||||
|
will write its output into a file whose name is \fB\*(ST.c\|.\fP
|
||||||
|
Input output specifications are evaluated left to right
|
||||||
|
as they appear in the command.
|
||||||
|
.IP >\ \fIword\fP 12
|
||||||
|
The standard output (file descriptor 1)
|
||||||
|
is sent to the file \fIword\fP which is
|
||||||
|
created if it does not already exist.
|
||||||
|
.IP \*(AP\ \fIword\fP 12
|
||||||
|
The standard output is sent to file \fIword.\fP
|
||||||
|
If the file exists then output is appended
|
||||||
|
(by seeking to the end);
|
||||||
|
otherwise the file is created.
|
||||||
|
.IP <\ \fIword\fP 12
|
||||||
|
The standard input (file descriptor 0)
|
||||||
|
is taken from the file \fIword.\fP
|
||||||
|
.IP \*(HE\ \fIword\fP 12
|
||||||
|
The standard input is taken from the lines
|
||||||
|
of shell input that follow up to but not
|
||||||
|
including a line consisting only of \fIword.\fP
|
||||||
|
If \fIword\fP is quoted then no interpretation
|
||||||
|
of the document occurs.
|
||||||
|
If \fIword\fP is not quoted
|
||||||
|
then parameter and command substitution
|
||||||
|
occur and \fB\\\fP is used to quote
|
||||||
|
the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character
|
||||||
|
of \fIword.\fP
|
||||||
|
In the latter case \fB\\newline\fP is ignored (c.f. quoted strings).
|
||||||
|
.IP >&\ \fIdigit\fP 12
|
||||||
|
The file descriptor \fIdigit\fP is duplicated using the system
|
||||||
|
call \fIdup\fP (2)
|
||||||
|
and the result is used as the standard output.
|
||||||
|
.IP <&\ \fIdigit\fP 12
|
||||||
|
The standard input is duplicated from file descriptor \fIdigit.\fP
|
||||||
|
.IP <&\(mi 12
|
||||||
|
The standard input is closed.
|
||||||
|
.IP >&\(mi 12
|
||||||
|
The standard output is closed.
|
||||||
|
.LP
|
||||||
|
Any of the above may be preceded by a digit in which
|
||||||
|
case the file descriptor created is that specified by the digit
|
||||||
|
instead of the default 0 or 1.
|
||||||
|
For example,
|
||||||
|
.DS
|
||||||
|
\*(ZZ 2>file
|
||||||
|
.DE
|
||||||
|
runs a command with message output (file descriptor 2)
|
||||||
|
directed to \fIfile.\fP
|
||||||
|
.DS
|
||||||
|
\*(ZZ 2>&1
|
||||||
|
.DE
|
||||||
|
runs a command with its standard output and message output
|
||||||
|
merged.
|
||||||
|
(Strictly speaking file descriptor 2 is created
|
||||||
|
by duplicating file descriptor 1 but the effect is usually to
|
||||||
|
merge the two streams.)
|
||||||
|
.\" Removed by Perry Metzger, most of this is now obsolete
|
||||||
|
.\"
|
||||||
|
.\" .LP
|
||||||
|
.\" The environment for a command run in the background such as
|
||||||
|
.\" .DS
|
||||||
|
.\" list \*(ST.c \*(VT lpr &
|
||||||
|
.\" .DE
|
||||||
|
.\" is modified in two ways.
|
||||||
|
.\" Firstly, the default standard input
|
||||||
|
.\" for such a command is the empty file \fB/dev/null\|.\fR
|
||||||
|
.\" This prevents two processes (the shell and the command),
|
||||||
|
.\" which are running in parallel, from trying to
|
||||||
|
.\" read the same input.
|
||||||
|
.\" Chaos would ensue
|
||||||
|
.\" if this were not the case.
|
||||||
|
.\" For example,
|
||||||
|
.\" .DS
|
||||||
|
.\" ed file &
|
||||||
|
.\" .DE
|
||||||
|
.\" would allow both the editor and the shell
|
||||||
|
.\" to read from the same input at the same time.
|
||||||
|
.\" .LP
|
||||||
|
.\" The other modification to the environment of a background
|
||||||
|
.\" command is to turn off the QUIT and INTERRUPT signals
|
||||||
|
.\" so that they are ignored by the command.
|
||||||
|
.\" This allows these signals to be used
|
||||||
|
.\" at the terminal without causing background
|
||||||
|
.\" commands to terminate.
|
||||||
|
.\" For this reason the UNIX convention
|
||||||
|
.\" for a signal is that if it is set to 1
|
||||||
|
.\" (ignored) then it is never changed
|
||||||
|
.\" even for a short time.
|
||||||
|
.\" Note that the shell command \fItrap\fP
|
||||||
|
.\" has no effect for an ignored signal.
|
||||||
|
.SH
|
||||||
|
3.9\ Invoking\ the\ shell
|
||||||
|
.LP
|
||||||
|
The following flags are interpreted by the shell
|
||||||
|
when it is invoked.
|
||||||
|
If the first character of argument zero is a minus,
|
||||||
|
then commands are read from the file \fB.profile\|.\fP
|
||||||
|
.IP \fB\(mic\fP\ \fIstring\fP
|
||||||
|
.br
|
||||||
|
If the \fB\(mic\fP flag is present then
|
||||||
|
commands are read from \fIstring\|.\fP
|
||||||
|
.IP \fB\(mis\fP
|
||||||
|
If the \fB\(mis\fP flag is present or if no
|
||||||
|
arguments remain
|
||||||
|
then commands are read from the standard input.
|
||||||
|
Shell output is written to
|
||||||
|
file descriptor 2.
|
||||||
|
.IP \fB\(mii\fP
|
||||||
|
If the \fB\(mii\fP flag is present or
|
||||||
|
if the shell input and output are attached to a terminal (as told by \fIgtty\fP)
|
||||||
|
then this shell is \fIinteractive.\fP
|
||||||
|
In this case TERMINATE is ignored (so that \fBkill 0\fP
|
||||||
|
does not kill an interactive shell) and INTERRUPT is caught and ignored
|
||||||
|
(so that \fBwait\fP is interruptable).
|
||||||
|
In all cases QUIT is ignored by the shell.
|
||||||
|
.SH
|
||||||
|
3.10\ Job\ Control
|
||||||
|
.LP
|
||||||
|
When a command or pipeline (also known as a \fIjob\fP) is running in
|
||||||
|
the foreground, entering the stop character (typically
|
||||||
|
\s-1CONTROL-Z\s0 but user settable with the \fIstty\fP(1) command)
|
||||||
|
will usually cause the job to stop.
|
||||||
|
.LP
|
||||||
|
The jobs associated with the current shell may be listed by entering
|
||||||
|
the \fIjobs\fP command.
|
||||||
|
Each job has an associated \fIjob number\fP.
|
||||||
|
Jobs that are stopped may be continued by entering
|
||||||
|
.DS
|
||||||
|
bg %\fIjobnumber\fP
|
||||||
|
.DE
|
||||||
|
and jobs may be moved to the foreground by entering
|
||||||
|
.DS
|
||||||
|
fg %\fIjobnumber\fP
|
||||||
|
.DE
|
||||||
|
If there is a sole job with a particular name (say only one instance
|
||||||
|
of \fIcc\fP running), \fIfg\fP and \fIbg\fP may also use name of the
|
||||||
|
command in place of the number, as in:
|
||||||
|
.DS
|
||||||
|
bg %cc
|
||||||
|
.DE
|
||||||
|
If no `\fB%\fP' clause is entered, most recently stopped job
|
||||||
|
(indicated with a `+' by the \fIjobs\fP command) will be assumed.
|
||||||
|
See the manual page for the shell for more details.
|
||||||
|
.SH
|
||||||
|
3.11\ Aliases
|
||||||
|
.LP
|
||||||
|
The \fIalias\fP command creates a so-called shell alias, which is an
|
||||||
|
abbreviation that macro-expands at run time into some other command.
|
||||||
|
For example:
|
||||||
|
.DS
|
||||||
|
alias ls="ls -F"
|
||||||
|
.DE
|
||||||
|
would cause the command sequence \fBls -F\fP to be executed whenever
|
||||||
|
the user types \fBls\fP into the shell.
|
||||||
|
Note that if the user types \fBls -a\fP, the shell will in fact
|
||||||
|
execute \fBls -F -a\fP.
|
||||||
|
The command \fBalias\fP on its own prints out all current aliases.
|
||||||
|
The \fIunalias\fP command, as in:
|
||||||
|
.DS
|
||||||
|
unalias ls
|
||||||
|
.DE
|
||||||
|
will remove an existing alias.
|
||||||
|
Aliases can shadow pre-existing commands, as in the example above.
|
||||||
|
They are typically used to override the interactive behavior of
|
||||||
|
commands in small ways, for example to always invoke some program with
|
||||||
|
a favorite option, and are almost never found in scripts.
|
||||||
|
.SH
|
||||||
|
3.12\ Command\ Line\ Editing\ and\ Recall
|
||||||
|
.LP
|
||||||
|
When working interactively with the shell, it is often tedious to
|
||||||
|
retype previously entered commands, especially if they are complicated.
|
||||||
|
The shell therefore maintains a so-called \fIhistory\fP, which is
|
||||||
|
stored in the file specified by the \fB\s-1HISTFILE\s0\fP environment
|
||||||
|
variable if it is set.
|
||||||
|
Users may view, edit, and re-enter previous lines of input using
|
||||||
|
a small subset of the commands of the \fIvi\fP(1) or
|
||||||
|
\fIemacs\fP(1)\(dg editors.
|
||||||
|
.FS
|
||||||
|
Technically, vi command editing is standardized by POSIX while emacs
|
||||||
|
is not.
|
||||||
|
However, all modern shells support both styles.
|
||||||
|
.FE
|
||||||
|
Emacs style editing may be selected by entering
|
||||||
|
.DS
|
||||||
|
set -o emacs
|
||||||
|
.DE
|
||||||
|
and vi style editing may be selected with
|
||||||
|
.DS
|
||||||
|
set -o vi
|
||||||
|
.DE
|
||||||
|
The details of how command line editing works are beyond the scope of
|
||||||
|
this document.
|
||||||
|
See the shell manual page for details.
|
||||||
|
.SH
|
||||||
|
Acknowledgements
|
||||||
|
.LP
|
||||||
|
The design of the shell is
|
||||||
|
based in part on the original UNIX shell
|
||||||
|
.[
|
||||||
|
unix command language thompson
|
||||||
|
.]
|
||||||
|
and the PWB/UNIX shell,
|
||||||
|
.[
|
||||||
|
pwb shell mashey unix
|
||||||
|
.]
|
||||||
|
some
|
||||||
|
features having been taken from both.
|
||||||
|
Similarities also exist with the
|
||||||
|
command interpreters
|
||||||
|
of the Cambridge Multiple Access System
|
||||||
|
.[
|
||||||
|
cambridge multiple access system hartley
|
||||||
|
.]
|
||||||
|
and of CTSS.
|
||||||
|
.[
|
||||||
|
ctss
|
||||||
|
.]
|
||||||
|
.LP
|
||||||
|
I would like to thank Dennis Ritchie
|
||||||
|
and John Mashey for many
|
||||||
|
discussions during the design of the shell.
|
||||||
|
I am also grateful to the members of the Computing Science Research Center
|
||||||
|
and to Joe Maranzano for their
|
||||||
|
comments on drafts of this document.
|
||||||
|
.SH
|
||||||
|
.[
|
||||||
|
$LIST$
|
||||||
|
.]
|
180
bin/sh/USD.doc/t4
Normal file
180
bin/sh/USD.doc/t4
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
.\" $NetBSD: t4,v 1.3 2010/08/22 02:19:07 perry Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions are
|
||||||
|
.\" met:
|
||||||
|
.\"
|
||||||
|
.\" Redistributions of source code and documentation must retain the above
|
||||||
|
.\" copyright notice, this list of conditions and the following
|
||||||
|
.\" disclaimer.
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.\" All advertising materials mentioning features or use of this software
|
||||||
|
.\" must display the following acknowledgement:
|
||||||
|
.\"
|
||||||
|
.\" This product includes software developed or owned by Caldera
|
||||||
|
.\" International, Inc. Neither the name of Caldera International, Inc.
|
||||||
|
.\" nor the names of other contributors may be used to endorse or promote
|
||||||
|
.\" products derived from this software without specific prior written
|
||||||
|
.\" permission.
|
||||||
|
.\"
|
||||||
|
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||||
|
.\" INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" @(#)t4 8.1 (Berkeley) 8/14/93
|
||||||
|
.\"
|
||||||
|
.bp
|
||||||
|
.SH
|
||||||
|
Appendix\ A\ -\ Grammar
|
||||||
|
.LP
|
||||||
|
Note: This grammar needs updating, it is obsolete.
|
||||||
|
.LP
|
||||||
|
.LD
|
||||||
|
\fIitem: word
|
||||||
|
input-output
|
||||||
|
name = value
|
||||||
|
.sp 0.7
|
||||||
|
simple-command: item
|
||||||
|
simple-command item
|
||||||
|
.sp 0.7
|
||||||
|
command: simple-command
|
||||||
|
\fB( \fIcommand-list \fB)
|
||||||
|
\fB{ \fIcommand-list \fB}
|
||||||
|
\fBfor \fIname \fBdo \fIcommand-list \fBdone
|
||||||
|
\fBfor \fIname \fBin \fIword \*(ZZ \fBdo \fIcommand-list \fBdone
|
||||||
|
\fBwhile \fIcommand-list \fBdo \fIcommand-list \fBdone
|
||||||
|
\fBuntil \fIcommand-list \fBdo \fIcommand-list \fBdone
|
||||||
|
\fBcase \fIword \fBin \fIcase-part \*(ZZ \fBesac
|
||||||
|
\fBif \fIcommand-list \fBthen \fIcommand-list \fIelse-part \fBfi
|
||||||
|
.sp 0.7
|
||||||
|
\fIpipeline: command
|
||||||
|
pipeline \fB\*(VT\fI command
|
||||||
|
.sp 0.7
|
||||||
|
andor: pipeline
|
||||||
|
andor \fB&&\fI pipeline
|
||||||
|
andor \fB\*(VT\*(VT\fI pipeline
|
||||||
|
.sp 0.7
|
||||||
|
command-list: andor
|
||||||
|
command-list \fB;\fI
|
||||||
|
command-list \fB&\fI
|
||||||
|
command-list \fB;\fI andor
|
||||||
|
command-list \fB&\fI andor
|
||||||
|
.sp 0.7
|
||||||
|
input-output: \fB> \fIfile
|
||||||
|
\fB< \fIfile
|
||||||
|
\fB\*(AP \fIword
|
||||||
|
\fB\*(HE \fIword
|
||||||
|
.sp 0.7
|
||||||
|
file: word
|
||||||
|
\fB&\fI digit
|
||||||
|
\fB&\fI \(mi
|
||||||
|
.sp 0.7
|
||||||
|
case-part: pattern\fB ) \fIcommand-list\fB ;;
|
||||||
|
.sp 0.7
|
||||||
|
\fIpattern: word
|
||||||
|
pattern \fB\*(VT\fI word
|
||||||
|
.sp 0.7
|
||||||
|
\fIelse-part: \fBelif \fIcommand-list\fB then\fI command-list else-part\fP
|
||||||
|
\fBelse \fIcommand-list\fI
|
||||||
|
empty
|
||||||
|
.sp 0.7
|
||||||
|
empty:
|
||||||
|
.sp 0.7
|
||||||
|
word: \fRa sequence of non-blank characters\fI
|
||||||
|
.sp 0.7
|
||||||
|
name: \fRa sequence of letters, digits or underscores starting with a letter\fI
|
||||||
|
.sp 0.7
|
||||||
|
digit: \fB0 1 2 3 4 5 6 7 8 9\fP
|
||||||
|
.DE
|
||||||
|
.LP
|
||||||
|
.bp
|
||||||
|
.SH
|
||||||
|
Appendix\ B\ -\ Meta-characters\ and\ Reserved\ Words
|
||||||
|
.LP
|
||||||
|
a) syntactic
|
||||||
|
.RS
|
||||||
|
.IP \fB\*(VT\fR 6
|
||||||
|
pipe symbol
|
||||||
|
.IP \fB&&\fR 6
|
||||||
|
`andf' symbol
|
||||||
|
.IP \fB\*(VT\*(VT\fR 6
|
||||||
|
`orf' symbol
|
||||||
|
.IP \fB;\fP 8
|
||||||
|
command separator
|
||||||
|
.IP \fB;;\fP 8
|
||||||
|
case delimiter
|
||||||
|
.IP \fB&\fP 8
|
||||||
|
background commands
|
||||||
|
.IP \fB(\ )\fP 8
|
||||||
|
command grouping
|
||||||
|
.IP \fB<\fP 8
|
||||||
|
input redirection
|
||||||
|
.IP \fB\*(HE\fP 8
|
||||||
|
input from a here document
|
||||||
|
.IP \fB>\fP 8
|
||||||
|
output creation
|
||||||
|
.IP \fB\*(AP\fP 8
|
||||||
|
output append
|
||||||
|
.sp 2
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
b) patterns
|
||||||
|
.RS
|
||||||
|
.IP \fB\*(ST\fP 8
|
||||||
|
match any character(s) including none
|
||||||
|
.IP \fB?\fP 8
|
||||||
|
match any single character
|
||||||
|
.IP \fB[...]\fP 8
|
||||||
|
match any of the enclosed characters
|
||||||
|
.sp 2
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
c) substitution
|
||||||
|
.RS
|
||||||
|
.IP \fB${...}\fP 8
|
||||||
|
substitute shell variable
|
||||||
|
.IP \fB$(...)\fP 8
|
||||||
|
substitute command output
|
||||||
|
.IP \fB\`...\`\fP 8
|
||||||
|
substitute command output
|
||||||
|
.IP \fB$((...))\fP 8
|
||||||
|
substitute arithmetic expression
|
||||||
|
.sp 2
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
d) quoting
|
||||||
|
.RS
|
||||||
|
.IP \fB\e\fP 8
|
||||||
|
quote the next character
|
||||||
|
.IP \fB\'...\'\fP 8
|
||||||
|
quote the enclosed characters except for \'
|
||||||
|
.IP \fB"\&..."\fP 8
|
||||||
|
quote the enclosed characters except
|
||||||
|
for \fB$ \` \e "\fP
|
||||||
|
.sp 2
|
||||||
|
.RE
|
||||||
|
.LP
|
||||||
|
e) reserved words
|
||||||
|
.DS
|
||||||
|
.ft B
|
||||||
|
if then else elif fi
|
||||||
|
case in esac
|
||||||
|
for while until do done
|
||||||
|
! { }
|
||||||
|
.ft
|
||||||
|
.DE
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: alias.c,v 1.14 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,15 +32,14 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: alias.c,v 1.14 2011/06/18 21:18:46 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
#include <sys/cdefs.h>
|
|
||||||
/*
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/alias.c,v 1.18 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
@ -49,18 +50,20 @@ __FBSDID("$FreeBSD: src/bin/sh/alias.c,v 1.18 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "alias.h"
|
#include "alias.h"
|
||||||
#include "options.h" /* XXX for argptr (should remove?) */
|
#include "options.h" /* XXX for argptr (should remove?) */
|
||||||
|
#include "builtins.h"
|
||||||
|
#include "var.h"
|
||||||
|
|
||||||
#define ATABSIZE 39
|
#define ATABSIZE 39
|
||||||
|
|
||||||
STATIC struct alias *atab[ATABSIZE];
|
struct alias *atab[ATABSIZE];
|
||||||
|
|
||||||
STATIC void setalias(const char *, const char *);
|
STATIC void setalias(char *, char *);
|
||||||
STATIC int unalias(const char *);
|
STATIC int unalias(char *);
|
||||||
STATIC struct alias **hashalias(const char *);
|
STATIC struct alias **hashalias(char *);
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
void
|
void
|
||||||
setalias(const char *name, const char *val)
|
setalias(char *name, char *val)
|
||||||
{
|
{
|
||||||
struct alias *ap, **app;
|
struct alias *ap, **app;
|
||||||
|
|
||||||
|
@ -78,6 +81,7 @@ setalias(const char *name, const char *val)
|
||||||
INTOFF;
|
INTOFF;
|
||||||
ap = ckmalloc(sizeof (struct alias));
|
ap = ckmalloc(sizeof (struct alias));
|
||||||
ap->name = savestr(name);
|
ap->name = savestr(name);
|
||||||
|
ap->flag = 0;
|
||||||
/*
|
/*
|
||||||
* XXX - HACK: in order that the parser will not finish reading the
|
* XXX - HACK: in order that the parser will not finish reading the
|
||||||
* alias value off the input before processing the next alias, we
|
* alias value off the input before processing the next alias, we
|
||||||
|
@ -87,7 +91,7 @@ setalias(const char *name, const char *val)
|
||||||
* expanding an alias, the value of the alias is pushed back on the
|
* 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
|
* 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
|
* string. The alias is marked as being in use. When the input
|
||||||
* routine finishes reading the string, it marks the alias not
|
* routine finishes reading the string, it markes the alias not
|
||||||
* in use. The problem is synchronization with the parser. Since
|
* in use. The problem is synchronization with the parser. Since
|
||||||
* it reads ahead, the alias is marked not in use before the
|
* it reads ahead, the alias is marked not in use before the
|
||||||
* resulting token(s) is next checked for further alias sub. The
|
* resulting token(s) is next checked for further alias sub. The
|
||||||
|
@ -106,14 +110,13 @@ setalias(const char *name, const char *val)
|
||||||
ap->val[len+1] = '\0';
|
ap->val[len+1] = '\0';
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ap->flag = 0;
|
|
||||||
ap->next = *app;
|
ap->next = *app;
|
||||||
*app = ap;
|
*app = ap;
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
unalias(const char *name)
|
unalias(char *name)
|
||||||
{
|
{
|
||||||
struct alias *ap, **app;
|
struct alias *ap, **app;
|
||||||
|
|
||||||
|
@ -146,7 +149,8 @@ unalias(const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
INCLUDE "alias.h"
|
MKINIT void rmaliases(void);
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
rmaliases();
|
rmaliases();
|
||||||
}
|
}
|
||||||
|
@ -174,7 +178,7 @@ rmaliases(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct alias *
|
struct alias *
|
||||||
lookupalias(const char *name, int check)
|
lookupalias(char *name, int check)
|
||||||
{
|
{
|
||||||
struct alias *ap = *hashalias(name);
|
struct alias *ap = *hashalias(name);
|
||||||
|
|
||||||
|
@ -189,6 +193,17 @@ lookupalias(const char *name, int check)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_alias_text(char *name)
|
||||||
|
{
|
||||||
|
struct alias *ap;
|
||||||
|
|
||||||
|
ap = lookupalias(name, 0);
|
||||||
|
if (ap == NULL)
|
||||||
|
return NULL;
|
||||||
|
return ap->val;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO - sort output
|
* TODO - sort output
|
||||||
*/
|
*/
|
||||||
|
@ -206,23 +221,23 @@ aliascmd(int argc, char **argv)
|
||||||
for (ap = atab[i]; ap; ap = ap->next) {
|
for (ap = atab[i]; ap; ap = ap->next) {
|
||||||
if (*ap->name != '\0') {
|
if (*ap->name != '\0') {
|
||||||
out1fmt("alias %s=", ap->name);
|
out1fmt("alias %s=", ap->name);
|
||||||
out1qstr(ap->val);
|
print_quoted(ap->val);
|
||||||
out1c('\n');
|
out1c('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
while ((n = *++argv) != NULL) {
|
while ((n = *++argv) != NULL) {
|
||||||
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
|
if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
|
||||||
if ((ap = lookupalias(n, 0)) == NULL) {
|
if ((ap = lookupalias(n, 0)) == NULL) {
|
||||||
outfmt(out2, "alias: %s not found\n", n);
|
outfmt(out2, "alias: %s not found\n", n);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
out1fmt("alias %s=", n);
|
out1fmt("alias %s=", n);
|
||||||
out1qstr(ap->val);
|
print_quoted(ap->val);
|
||||||
out1c('\n');
|
out1c('\n');
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
*v++ = '\0';
|
*v++ = '\0';
|
||||||
setalias(n, v);
|
setalias(n, v);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +247,7 @@ aliascmd(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
unaliascmd(int argc __unused, char **argv __unused)
|
unaliascmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -249,7 +264,7 @@ unaliascmd(int argc __unused, char **argv __unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC struct alias **
|
STATIC struct alias **
|
||||||
hashalias(const char *p)
|
hashalias(char *p)
|
||||||
{
|
{
|
||||||
unsigned int hashval;
|
unsigned int hashval;
|
||||||
|
|
||||||
|
@ -258,7 +273,3 @@ hashalias(const char *p)
|
||||||
hashval+= *p++;
|
hashval+= *p++;
|
||||||
return &atab[hashval % ATABSIZE];
|
return &atab[hashval % ATABSIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: alias.c,v 1.5 2006/05/22 12:41:12 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: alias.h,v 1.7 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/alias.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ALIASINUSE 1
|
#define ALIASINUSE 1
|
||||||
|
@ -42,11 +43,6 @@ struct alias {
|
||||||
int flag;
|
int flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alias *lookupalias(const char *, int);
|
struct alias *lookupalias(char *, int);
|
||||||
int aliascmd(int, char **);
|
char *get_alias_text(char *);
|
||||||
int unaliascmd(int, char **);
|
|
||||||
void rmaliases(void);
|
void rmaliases(void);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: alias.h,v 1.4 2006/03/31 11:30:54 philip Exp $
|
|
||||||
*/
|
|
206
bin/sh/arith.y
Normal file
206
bin/sh/arith.y
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
%{
|
||||||
|
/* $NetBSD: arith.y,v 1.22 2012/03/20 18:42:29 matt 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. 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.22 2012/03/20 18:42:29 matt Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "expand.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
|
||||||
|
typedef intmax_t YYSTYPE;
|
||||||
|
#define YYSTYPE YYSTYPE
|
||||||
|
|
||||||
|
intmax_t arith_result;
|
||||||
|
const char *arith_buf, *arith_startbuf;
|
||||||
|
|
||||||
|
__dead static void yyerror(const char *);
|
||||||
|
#ifdef TESTARITH
|
||||||
|
int main(int , char *[]);
|
||||||
|
int error(char *);
|
||||||
|
#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 {
|
||||||
|
/*
|
||||||
|
* yyparse() returns int, so we have to save
|
||||||
|
* the desired result elsewhere.
|
||||||
|
*/
|
||||||
|
arith_result = $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
|
||||||
|
;
|
||||||
|
%%
|
||||||
|
intmax_t
|
||||||
|
arith(const char *s)
|
||||||
|
{
|
||||||
|
intmax_t result;
|
||||||
|
|
||||||
|
arith_buf = arith_startbuf = s;
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
(void) yyparse();
|
||||||
|
result = arith_result;
|
||||||
|
arith_lex_reset(); /* reprime lex */
|
||||||
|
INTON;
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The exp(1) builtin.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
expcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *concat;
|
||||||
|
char **ap;
|
||||||
|
intmax_t 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 = "";
|
||||||
|
|
||||||
|
(void)arith(p);
|
||||||
|
i = arith_result;
|
||||||
|
|
||||||
|
out1fmt("%"PRIdMAX"\n", i);
|
||||||
|
return (! i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
#ifdef TEST_ARITH
|
||||||
|
#include <stdio.h>
|
||||||
|
main(argc, argv)
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
printf("%"PRIdMAX"\n", exp(argv[1]));
|
||||||
|
}
|
||||||
|
error(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
fprintf(stderr, "exp: %s\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
yyerror(const char *s)
|
||||||
|
{
|
||||||
|
|
||||||
|
yyerrok;
|
||||||
|
yyclearin;
|
||||||
|
arith_lex_reset(); /* reprime lex */
|
||||||
|
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
%{
|
%{
|
||||||
|
/* $NetBSD: arith_lex.l,v 1.16 2012/03/20 18:42:29 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -14,7 +16,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -31,103 +33,71 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: arith_lex.l,v 1.16 2012/03/20 18:42:29 matt Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "arith.h"
|
#include "arith.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "memalloc.h"
|
#include "expand.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
|
|
||||||
extern char *arith_buf, *arith_startbuf;
|
extern intmax_t yylval;
|
||||||
|
extern const char *arith_buf, *arith_startbuf;
|
||||||
#undef YY_INPUT
|
#undef YY_INPUT
|
||||||
#define YY_INPUT(buf,result,max) \
|
#define YY_INPUT(buf,result,max) \
|
||||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||||
#define YY_NO_UNPUT
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%option nounput noinput
|
||||||
|
|
||||||
%%
|
%%
|
||||||
[ \t\n] { ; }
|
[ \t\n] { ; }
|
||||||
|
0x[0-9a-fA-F]+ { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); }
|
||||||
0x[a-fA-F0-9]+ {
|
0[0-7]* { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); }
|
||||||
yylval.l_value = strtoarith_t(yytext, NULL, 16);
|
[1-9][0-9]* { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); }
|
||||||
return ARITH_NUM;
|
[A-Za-z_][A-Za-z_0-9]* { char *v = lookupvar(yytext);
|
||||||
}
|
if (v) {
|
||||||
|
yylval = strtoimax(v, &v, 0);
|
||||||
0[0-7]+ {
|
if (*v == 0)
|
||||||
yylval.l_value = strtoarith_t(yytext, NULL, 8);
|
return ARITH_NUM;
|
||||||
return ARITH_NUM;
|
}
|
||||||
}
|
error("arith: syntax error: \"%s\"", arith_startbuf);
|
||||||
|
|
||||||
[0-9]+ {
|
|
||||||
yylval.l_value = strtoarith_t(yytext, NULL, 10);
|
|
||||||
return ARITH_NUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
[A-Za-z][A-Za-z0-9_]* {
|
|
||||||
/*
|
|
||||||
* If variable doesn't exist, we should initialize
|
|
||||||
* it to zero.
|
|
||||||
*/
|
|
||||||
char *temp;
|
|
||||||
if (lookupvar(yytext) == NULL)
|
|
||||||
setvarsafe(yytext, "0", 0);
|
|
||||||
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
|
||||||
yylval.s_value = strcpy(temp, yytext);
|
|
||||||
|
|
||||||
return ARITH_VAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
"(" { 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; }
|
|
||||||
"=" { return ARITH_ASSIGN; }
|
|
||||||
"+=" { return ARITH_ADDASSIGN; }
|
|
||||||
"-=" { return ARITH_SUBASSIGN; }
|
|
||||||
"*=" { return ARITH_MULASSIGN; }
|
|
||||||
"/=" { return ARITH_DIVASSIGN; }
|
|
||||||
"%=" { return ARITH_REMASSIGN; }
|
|
||||||
">>=" { return ARITH_RSHASSIGN; }
|
|
||||||
"<<=" { return ARITH_LSHASSIGN; }
|
|
||||||
"&=" { return ARITH_BANDASSIGN; }
|
|
||||||
"^=" { return ARITH_BXORASSIGN; }
|
|
||||||
"|=" { return ARITH_BORASSIGN; }
|
|
||||||
. {
|
|
||||||
error("arith: syntax error: \"%s\"\n", arith_startbuf);
|
|
||||||
}
|
}
|
||||||
|
"(" { 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\"", arith_startbuf); }
|
||||||
%%
|
%%
|
||||||
|
|
||||||
void
|
void
|
||||||
arith_lex_reset(void)
|
arith_lex_reset(void) {
|
||||||
{
|
#ifdef YY_NEW_FILE
|
||||||
YY_NEW_FILE;
|
YY_NEW_FILE;
|
||||||
|
#endif
|
||||||
}
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: bltin.h,v 1.13 2008/10/12 01:40:37 dholland Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -29,63 +31,70 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)bltin.h 8.2 (Berkeley) 5/4/95
|
* @(#)bltin.h 8.1 (Berkeley) 5/31/93
|
||||||
* $FreeBSD: src/bin/sh/bltin/bltin.h,v 1.13 2004/04/06 20:06:53 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is included by programs which are optionally built into the
|
* 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
|
* shell.
|
||||||
* routines to ash routines using defines.
|
*
|
||||||
|
* We always define SHELL_BUILTIN, to allow other included headers to
|
||||||
|
* hide some of their symbols if appropriate.
|
||||||
|
*
|
||||||
|
* If SHELL is defined, we try to map the standard UNIX library routines
|
||||||
|
* to ash routines using defines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define SHELL_BUILTIN
|
||||||
#include "../shell.h"
|
#include "../shell.h"
|
||||||
#include "../mystring.h"
|
#include "../mystring.h"
|
||||||
#ifdef SHELL
|
#ifdef SHELL
|
||||||
#include "builtins.h"
|
|
||||||
#include "../output.h"
|
#include "../output.h"
|
||||||
|
#include "../error.h"
|
||||||
#undef stdout
|
#undef stdout
|
||||||
#define stdout out1
|
|
||||||
#undef stderr
|
#undef stderr
|
||||||
#define stderr out2
|
|
||||||
#define printf out1fmt
|
|
||||||
#undef putc
|
#undef putc
|
||||||
#define putc(c, file) outc(c, file)
|
|
||||||
#undef putchar
|
#undef putchar
|
||||||
#define putchar(c) out1c(c)
|
#undef fileno
|
||||||
#define fprintf outfmt
|
#undef ferror
|
||||||
#define fputs outstr
|
#define FILE struct output
|
||||||
#define fflush flushout
|
#define stdout out1
|
||||||
|
#define stderr out2
|
||||||
|
#define _RETURN_INT(x) ((x), 0) /* map from void foo() to int bar() */
|
||||||
|
#define fprintf(...) _RETURN_INT(outfmt(__VA_ARGS__))
|
||||||
|
#define printf(...) _RETURN_INT(out1fmt(__VA_ARGS__))
|
||||||
|
#define putc(c, file) _RETURN_INT(outc(c, file))
|
||||||
|
#define putchar(c) _RETURN_INT(out1c(c))
|
||||||
|
#define fputs(...) _RETURN_INT(outstr(__VA_ARGS__))
|
||||||
|
#define fflush(f) _RETURN_INT(flushout(f))
|
||||||
|
#define fileno(f) ((f)->fd)
|
||||||
|
#define ferror(f) ((f)->flags & OUTPUT_ERR)
|
||||||
#define INITARGS(argv)
|
#define INITARGS(argv)
|
||||||
#define warnx1(a, b, c) { \
|
#define err sh_err
|
||||||
char buf[64]; \
|
#define verr sh_verr
|
||||||
(void)snprintf(buf, sizeof(buf), a); \
|
#define errx sh_errx
|
||||||
error("%s", buf); \
|
#define verrx sh_verrx
|
||||||
}
|
#define warn sh_warn
|
||||||
#define warnx2(a, b, c) { \
|
#define vwarn sh_vwarn
|
||||||
char buf[64]; \
|
#define warnx sh_warnx
|
||||||
(void)snprintf(buf, sizeof(buf), a, b); \
|
#define vwarnx sh_vwarnx
|
||||||
error("%s", buf); \
|
#define exit sh_exit
|
||||||
}
|
#define setprogname(s)
|
||||||
#define warnx3(a, b, c) { \
|
#define getprogname() commandname
|
||||||
char buf[64]; \
|
#define setlocate(l,s) 0
|
||||||
(void)snprintf(buf, sizeof(buf), a, b, c); \
|
|
||||||
error("%s", buf); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#define getenv(p) bltinlookup((p),0)
|
||||||
|
|
||||||
|
#else /* ! SHELL */
|
||||||
#undef NULL
|
#undef NULL
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#undef main
|
#undef main
|
||||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||||
#endif
|
#endif /* ! SHELL */
|
||||||
|
|
||||||
pointer stalloc(int);
|
pointer stalloc(int);
|
||||||
void error(const char *, ...);
|
|
||||||
|
int echocmd(int, char **);
|
||||||
|
|
||||||
|
|
||||||
extern char *commandname;
|
extern const char *commandname;
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
|
|
||||||
*/
|
|
109
bin/sh/bltin/echo.1
Normal file
109
bin/sh/bltin/echo.1
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc 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. 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
|
||||||
|
.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 \*[Gt]\*[Am]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,3 +1,5 @@
|
||||||
|
/* $NetBSD: echo.c,v 1.14 2008/10/12 01:40:37 dholland Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -29,61 +31,65 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)echo.c 8.2 (Berkeley) 5/4/95
|
* @(#)echo.c 8.1 (Berkeley) 5/31/93
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/bltin/echo.c,v 1.14 2004/04/06 20:06:53 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Echo command.
|
* Echo command.
|
||||||
|
*
|
||||||
|
* echo is steeped in tradition - several of them!
|
||||||
|
* netbsd has supported 'echo [-n | -e] args' in spite of -e not being
|
||||||
|
* documented anywhere.
|
||||||
|
* Posix requires that -n be supported, output from strings containing
|
||||||
|
* \ is implementation defined
|
||||||
|
* The Single Unix Spec requires that \ escapes be treated as if -e
|
||||||
|
* were set, but that -n not be treated as an option.
|
||||||
|
* (ksh supports 'echo [-eEn] args', but not -- so that it is actually
|
||||||
|
* impossible to actually output '-n')
|
||||||
|
*
|
||||||
|
* It is suggested that 'printf "%b" "string"' be used to get \ sequences
|
||||||
|
* expanded. printf is now a builtin of netbsd's sh and csh.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: echo.c,v 1.14 2008/10/12 01:40:37 dholland Exp $");
|
||||||
|
|
||||||
|
#define main echocmd
|
||||||
|
|
||||||
#include "bltin.h"
|
#include "bltin.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
echocmd(argc, argv)
|
main(int argc, char **argv)
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
char *p;
|
char *p;
|
||||||
char c;
|
char c;
|
||||||
int count;
|
int count;
|
||||||
int nflag = 0;
|
int nflag = 0;
|
||||||
#ifdef __minix
|
|
||||||
int eflag = 0;
|
int eflag = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
ap = argv;
|
ap = argv;
|
||||||
if (argc)
|
if (argc)
|
||||||
ap++;
|
ap++;
|
||||||
|
|
||||||
if ((p = *ap) != NULL) {
|
if ((p = *ap) != NULL) {
|
||||||
#ifdef __minix
|
|
||||||
if (equal(p, "--")) {
|
|
||||||
ap++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (equal(p, "-n")) {
|
if (equal(p, "-n")) {
|
||||||
nflag++;
|
nflag = 1;
|
||||||
ap++;
|
ap++;
|
||||||
} else if (equal(p, "-e")) {
|
} else if (equal(p, "-e")) {
|
||||||
#ifdef __minix
|
eflag = 1;
|
||||||
eflag++;
|
|
||||||
#endif
|
|
||||||
ap++;
|
ap++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((p = *ap++) != NULL) {
|
while ((p = *ap++) != NULL) {
|
||||||
while ((c = *p++) != '\0') {
|
while ((c = *p++) != '\0') {
|
||||||
if (c == '\\' && eflag) {
|
if (c == '\\' && eflag) {
|
||||||
switch (*p++) {
|
switch (*p++) {
|
||||||
case 'a': c = '\a'; break;
|
case 'a': c = '\a'; break; /* bell */
|
||||||
case 'b': c = '\b'; break;
|
case 'b': c = '\b'; break;
|
||||||
case 'c': return 0; /* exit */
|
case 'c': return 0; /* exit */
|
||||||
case 'e': c = '\033'; break;
|
case 'e': c = 033; break; /* escape */
|
||||||
case 'f': c = '\f'; break;
|
case 'f': c = '\f'; break;
|
||||||
case 'n': c = '\n'; break;
|
case 'n': c = '\n'; break;
|
||||||
case 'r': c = '\r'; break;
|
case 'r': c = '\r'; break;
|
||||||
|
@ -97,6 +103,7 @@ echocmd(argc, argv)
|
||||||
c = (c << 3) + (*p++ - '0');
|
c = (c << 3) + (*p++ - '0');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* Output the '/' and char following */
|
||||||
p--;
|
p--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -108,9 +115,8 @@ echocmd(argc, argv)
|
||||||
}
|
}
|
||||||
if (! nflag)
|
if (! nflag)
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
fflush(stdout);
|
||||||
|
if (ferror(stdout))
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
|
# $NetBSD: builtins.def,v 1.22 2012/12/31 14:10:15 dsl Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 3. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
|
@ -31,63 +32,62 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/builtins.def,v 1.14 2004/04/06 20:06:51 markm Exp $
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This file lists all the builtin commands. The first column is the name
|
# 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
|
# of a C routine.
|
||||||
# is to be excluded from systems without job control, and the -h flag,
|
# The -j flag specifies that this command is to be excluded from systems
|
||||||
# if present specifies that this command is to be excluded from systems
|
# without job control.
|
||||||
# based on the NO_HISTORY compile-time symbol. The rest of the line
|
# The -h flag specifies that this command is to be excluded from systems
|
||||||
# specifies the command name or names used to run the command. The entry
|
# based on the SMALL compile-time symbol.
|
||||||
# for bltincmd, which is run when the user does not specify a command, must
|
# The -s flag specifies that this is a posix 'special builtin' command.
|
||||||
# come first.
|
# The -u flag specifies that this is a posix 'standard utility'.
|
||||||
#
|
# The rest of the line specifies the command name or names used to run
|
||||||
# NOTE: bltincmd must come first!
|
# the command.
|
||||||
|
|
||||||
bltincmd builtin
|
bltincmd -u command
|
||||||
commandcmd command
|
bgcmd -j -u bg
|
||||||
#if JOBS
|
breakcmd -s break -s continue
|
||||||
bgcmd -j bg
|
cdcmd -u cd chdir
|
||||||
#endif
|
dotcmd -s .
|
||||||
breakcmd break continue
|
|
||||||
#catfcmd catf
|
|
||||||
cdcmd cd chdir
|
|
||||||
dotcmd .
|
|
||||||
echocmd echo
|
echocmd echo
|
||||||
evalcmd eval
|
evalcmd -s eval
|
||||||
execcmd exec
|
execcmd -s exec
|
||||||
exitcmd exit
|
exitcmd -s exit
|
||||||
expcmd exp let
|
expcmd exp let
|
||||||
exportcmd export readonly
|
exportcmd -s export -s readonly
|
||||||
exprcmd expr test [
|
falsecmd -u false
|
||||||
falsecmd false
|
histcmd -h -u fc
|
||||||
histcmd -h fc
|
inputrc inputrc
|
||||||
#if JOBS
|
fgcmd -j -u fg
|
||||||
fgcmd -j fg
|
fgcmd_percent -j -u %
|
||||||
#endif
|
getoptscmd -u getopts
|
||||||
getoptscmd getopts
|
|
||||||
hashcmd hash
|
hashcmd hash
|
||||||
jobidcmd jobid
|
jobidcmd jobid
|
||||||
jobscmd jobs
|
jobscmd -u jobs
|
||||||
localcmd local
|
localcmd local
|
||||||
#ifndef SMALL
|
#ifndef SMALL
|
||||||
#printfcmd printf
|
printfcmd printf
|
||||||
#endif
|
#endif
|
||||||
pwdcmd pwd
|
pwdcmd -u pwd
|
||||||
readcmd read
|
readcmd -u read
|
||||||
returncmd return
|
returncmd -s return
|
||||||
setcmd set
|
setcmd -s set
|
||||||
setvarcmd setvar
|
setvarcmd setvar
|
||||||
shiftcmd shift
|
shiftcmd -s shift
|
||||||
trapcmd trap
|
timescmd -s times
|
||||||
truecmd : true
|
trapcmd -s trap
|
||||||
|
truecmd -s : -u true
|
||||||
typecmd type
|
typecmd type
|
||||||
umaskcmd umask
|
umaskcmd -u umask
|
||||||
unaliascmd unalias
|
unaliascmd -u unalias
|
||||||
unsetcmd unset
|
unsetcmd -s unset
|
||||||
waitcmd wait
|
waitcmd -u wait
|
||||||
aliascmd alias
|
aliascmd -u alias
|
||||||
ulimitcmd ulimit
|
ulimitcmd ulimit
|
||||||
bindcmd bind
|
testcmd test [
|
||||||
|
killcmd -u kill # mandated by posix for 'kill %job'
|
||||||
wordexpcmd wordexp
|
wordexpcmd wordexp
|
||||||
|
#newgrp -u newgrp # optional command in posix
|
||||||
|
|
||||||
|
#exprcmd expr
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: cd.c,v 1.44 2011/08/31 16:24:54 plunky Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,15 +32,14 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: cd.c,v 1.44 2011/08/31 16:24:54 plunky Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -46,7 +47,6 @@ __FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The cd and pwd commands.
|
* The cd and pwd commands.
|
||||||
|
@ -57,68 +57,74 @@ __FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include "nodes.h" /* for jobs.h */
|
#include "nodes.h" /* for jobs.h */
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "builtins.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "redir.h"
|
#include "redir.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "builtins.h"
|
|
||||||
#include "show.h"
|
#include "show.h"
|
||||||
#include "cd.h"
|
#include "cd.h"
|
||||||
|
|
||||||
STATIC int cdlogical(const char *);
|
STATIC int docd(const char *, int);
|
||||||
STATIC int cdphysical(const char *);
|
|
||||||
STATIC int docd(const char *, int, int);
|
|
||||||
STATIC char *getcomponent(void);
|
STATIC char *getcomponent(void);
|
||||||
STATIC int updatepwd(const char *);
|
STATIC void updatepwd(const char *);
|
||||||
|
STATIC void find_curdir(int noerror);
|
||||||
|
|
||||||
STATIC char *curdir = NULL; /* current working directory */
|
char *curdir = NULL; /* current working directory */
|
||||||
STATIC char *prevdir; /* previous working directory */
|
char *prevdir; /* previous working directory */
|
||||||
STATIC char *cdcomppath;
|
STATIC char *cdcomppath;
|
||||||
|
|
||||||
int
|
int
|
||||||
cdcmd(int argc, char **argv)
|
cdcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *dest;
|
const char *dest;
|
||||||
char *path;
|
const char *path, *p;
|
||||||
char *p;
|
char *d;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
int ch, phys, print = 0;
|
int print = cdprint; /* set -cdprint to enable */
|
||||||
|
|
||||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
while (nextopt("P") != '\0')
|
||||||
phys = Pflag;
|
;
|
||||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
|
||||||
switch (ch) {
|
/*
|
||||||
case 'L':
|
* Try (quite hard) to have 'curdir' defined, nothing has set
|
||||||
phys = 0;
|
* it on entry to the shell, but we want 'cd fred; cd -' to work.
|
||||||
break;
|
*/
|
||||||
case 'P':
|
getpwd(1);
|
||||||
phys = 1;
|
dest = *argptr;
|
||||||
break;
|
if (dest == NULL) {
|
||||||
default:
|
dest = bltinlookup("HOME", 1);
|
||||||
error("unknown option: -%c", optopt);
|
if (dest == NULL)
|
||||||
break;
|
error("HOME not set");
|
||||||
|
} else {
|
||||||
|
if (argptr[1]) {
|
||||||
|
/* Do 'ksh' style substitution */
|
||||||
|
if (!curdir)
|
||||||
|
error("PWD not set");
|
||||||
|
p = strstr(curdir, dest);
|
||||||
|
if (!p)
|
||||||
|
error("bad substitution");
|
||||||
|
d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
|
||||||
|
memcpy(d, curdir, p - curdir);
|
||||||
|
strcpy(d + (p - curdir), argptr[1]);
|
||||||
|
strcat(d, p + strlen(dest));
|
||||||
|
dest = d;
|
||||||
|
print = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc > 1)
|
|
||||||
error("too many arguments");
|
|
||||||
|
|
||||||
if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
|
||||||
error("HOME not set");
|
|
||||||
if (*dest == '\0')
|
|
||||||
dest = ".";
|
|
||||||
if (dest[0] == '-' && dest[1] == '\0') {
|
if (dest[0] == '-' && dest[1] == '\0') {
|
||||||
dest = prevdir ? prevdir : curdir;
|
dest = prevdir ? prevdir : curdir;
|
||||||
if (dest)
|
print = 1;
|
||||||
print = 1;
|
|
||||||
else
|
|
||||||
dest = ".";
|
|
||||||
}
|
}
|
||||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
if (*dest == '\0')
|
||||||
|
dest = ".";
|
||||||
|
p = dest;
|
||||||
|
if (*p == '.' && *++p == '.')
|
||||||
|
p++;
|
||||||
|
if (*p == 0 || *p == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||||
path = nullstr;
|
path = nullstr;
|
||||||
while ((p = padvance(&path, dest)) != NULL) {
|
while ((p = padvance(&path, dest)) != NULL) {
|
||||||
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||||
|
@ -127,41 +133,27 @@ cdcmd(int argc, char **argv)
|
||||||
* XXX - rethink
|
* XXX - rethink
|
||||||
*/
|
*/
|
||||||
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
||||||
p += 2;
|
print = strcmp(p + 2, dest);
|
||||||
print = strcmp(p, dest);
|
else
|
||||||
|
print = strcmp(p, dest);
|
||||||
}
|
}
|
||||||
if (docd(p, print, phys) >= 0)
|
if (docd(p, print) >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error("can't cd to %s", dest);
|
error("can't cd to %s", dest);
|
||||||
/*NOTREACHED*/
|
/* NOTREACHED */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually change the directory. In an interactive shell, print the
|
* Actually do the chdir. In an interactive shell, print the
|
||||||
* directory name if "print" is nonzero.
|
* directory name if "print" is nonzero.
|
||||||
*/
|
*/
|
||||||
STATIC int
|
|
||||||
docd(const char *dest, int print, int phys)
|
|
||||||
{
|
|
||||||
|
|
||||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
|
|
||||||
|
|
||||||
/* If logical cd fails, fall back to physical. */
|
|
||||||
if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if (print && iflag && curdir)
|
|
||||||
out1fmt("%s\n", curdir);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
cdlogical(const char *dest)
|
docd(const char *dest, int print)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *q;
|
char *q;
|
||||||
|
@ -170,6 +162,8 @@ cdlogical(const char *dest)
|
||||||
int first;
|
int first;
|
||||||
int badstat;
|
int badstat;
|
||||||
|
|
||||||
|
TRACE(("docd(\"%s\", %d) called\n", dest, print));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check each component of the path. If we find a symlink or
|
* Check each component of the path. If we find a symlink or
|
||||||
* something we can't stat, clear curdir to force a getcwd()
|
* something we can't stat, clear curdir to force a getcwd()
|
||||||
|
@ -196,38 +190,32 @@ cdlogical(const char *dest)
|
||||||
if (equal(component, ".."))
|
if (equal(component, ".."))
|
||||||
continue;
|
continue;
|
||||||
STACKSTRNUL(p);
|
STACKSTRNUL(p);
|
||||||
if (lstat(stackblock(), &statb) < 0) {
|
if ((lstat(stackblock(), &statb) < 0)
|
||||||
|
|| (S_ISLNK(statb.st_mode))) {
|
||||||
|
/* print = 1; */
|
||||||
badstat = 1;
|
badstat = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
|
if (chdir(dest) < 0) {
|
||||||
INTON;
|
INTON;
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
updatepwd(badstat ? NULL : dest);
|
||||||
INTON;
|
INTON;
|
||||||
return (0);
|
if (print && iflag == 1 && curdir)
|
||||||
|
out1fmt("%s\n", curdir);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
|
||||||
cdphysical(const char *dest)
|
|
||||||
{
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
|
|
||||||
INTON;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next component of the path name pointed to by cdcomppath.
|
* Get the next component of the path name pointed to by cdcomppath.
|
||||||
* This routine overwrites the string pointed to by cdcomppath.
|
* This routine overwrites the string pointed to by cdcomppath.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC char *
|
STATIC char *
|
||||||
getcomponent(void)
|
getcomponent(void)
|
||||||
{
|
{
|
||||||
|
@ -249,12 +237,14 @@ getcomponent(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update curdir (the name of the current directory) in response to a
|
* 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
|
* cd command. We also call hashcd to let the routines in exec.c know
|
||||||
* that the current directory has changed.
|
* that the current directory has changed.
|
||||||
*/
|
*/
|
||||||
STATIC int
|
|
||||||
|
STATIC void
|
||||||
updatepwd(const char *dir)
|
updatepwd(const char *dir)
|
||||||
{
|
{
|
||||||
char *new;
|
char *new;
|
||||||
|
@ -273,14 +263,14 @@ updatepwd(const char *dir)
|
||||||
INTOFF;
|
INTOFF;
|
||||||
prevdir = curdir;
|
prevdir = curdir;
|
||||||
curdir = NULL;
|
curdir = NULL;
|
||||||
if (getpwd() == NULL) {
|
getpwd(1);
|
||||||
INTON;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
setvar("PWD", curdir, VEXPORT);
|
|
||||||
setvar("OLDPWD", prevdir, VEXPORT);
|
|
||||||
INTON;
|
INTON;
|
||||||
return (0);
|
if (curdir) {
|
||||||
|
setvar("OLDPWD", prevdir, VEXPORT);
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
|
} else
|
||||||
|
unsetvar("PWD", 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
cdcomppath = stalloc(strlen(dir) + 1);
|
cdcomppath = stalloc(strlen(dir) + 1);
|
||||||
scopy(dir, cdcomppath);
|
scopy(dir, cdcomppath);
|
||||||
|
@ -309,82 +299,166 @@ updatepwd(const char *dir)
|
||||||
ckfree(prevdir);
|
ckfree(prevdir);
|
||||||
prevdir = curdir;
|
prevdir = curdir;
|
||||||
curdir = savestr(stackblock());
|
curdir = savestr(stackblock());
|
||||||
setvar("PWD", curdir, VEXPORT);
|
|
||||||
setvar("OLDPWD", prevdir, VEXPORT);
|
setvar("OLDPWD", prevdir, VEXPORT);
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
INTON;
|
INTON;
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Posix says the default should be 'pwd -L' (as below), however
|
||||||
|
* the 'cd' command (above) does something much nearer to the
|
||||||
|
* posix 'cd -P' (not the posix default of 'cd -L').
|
||||||
|
* If 'cd' is changed to support -P/L then the default here
|
||||||
|
* needs to be revisited if the historic behaviour is to be kept.
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
pwdcmd(int argc, char **argv)
|
pwdcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[PATH_MAX];
|
int i;
|
||||||
int ch, phys;
|
char opt = 'L';
|
||||||
|
|
||||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
while ((i = nextopt("LP")) != '\0')
|
||||||
phys = Pflag;
|
opt = i;
|
||||||
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
if (*argptr)
|
||||||
switch (ch) {
|
error("unexpected argument");
|
||||||
case 'L':
|
|
||||||
phys = 0;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
phys = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error("unknown option: -%c", optopt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc != 0)
|
if (opt == 'L')
|
||||||
error("too many arguments");
|
getpwd(0);
|
||||||
|
else
|
||||||
if (!phys && getpwd()) {
|
find_curdir(0);
|
||||||
out1str(curdir);
|
|
||||||
out1c('\n');
|
|
||||||
} else {
|
|
||||||
if (getcwd(buf, sizeof(buf)) == NULL)
|
|
||||||
error(".: %s", strerror(errno));
|
|
||||||
out1str(buf);
|
|
||||||
out1c('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
setvar("OLDPWD", prevdir, VEXPORT);
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
|
out1str(curdir);
|
||||||
|
out1c('\n');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
initpwd(void)
|
||||||
|
{
|
||||||
|
getpwd(1);
|
||||||
|
if (curdir)
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
|
else
|
||||||
|
sh_warnx("Cannot determine current working directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAXPWD 256
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out what the current directory is. If we already know the current
|
* Find out what the current directory is. If we already know the current
|
||||||
* directory, this routine returns immediately.
|
* directory, this routine returns immediately.
|
||||||
*/
|
*/
|
||||||
char *
|
void
|
||||||
getpwd(void)
|
getpwd(int noerror)
|
||||||
{
|
{
|
||||||
char buf[PATH_MAX];
|
char *pwd;
|
||||||
|
struct stat stdot, stpwd;
|
||||||
|
static int first = 1;
|
||||||
|
|
||||||
if (curdir)
|
if (curdir)
|
||||||
return curdir;
|
return;
|
||||||
if (getcwd(buf, sizeof(buf)) == NULL) {
|
|
||||||
char *pwd = getenv("PWD");
|
|
||||||
struct stat stdot, stpwd;
|
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = 0;
|
||||||
|
pwd = getenv("PWD");
|
||||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||||
stat(pwd, &stpwd) != -1 &&
|
stat(pwd, &stpwd) != -1 &&
|
||||||
stdot.st_dev == stpwd.st_dev &&
|
stdot.st_dev == stpwd.st_dev &&
|
||||||
stdot.st_ino == stpwd.st_ino) {
|
stdot.st_ino == stpwd.st_ino) {
|
||||||
curdir = savestr(pwd);
|
curdir = savestr(pwd);
|
||||||
return curdir;
|
return;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
curdir = savestr(buf);
|
|
||||||
|
|
||||||
return curdir;
|
find_curdir(noerror);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
STATIC void
|
||||||
* $PchId: cd.c,v 1.6 2006/05/22 12:42:03 philip Exp $
|
find_curdir(int noerror)
|
||||||
*/
|
{
|
||||||
|
int i;
|
||||||
|
char *pwd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) || defined(__minix)
|
||||||
|
|
||||||
|
for (i = MAXPWD;; i *= 2) {
|
||||||
|
pwd = stalloc(i);
|
||||||
|
if (getcwd(pwd, i) != NULL) {
|
||||||
|
curdir = savestr(pwd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stunalloc(pwd);
|
||||||
|
if (errno == ERANGE)
|
||||||
|
continue;
|
||||||
|
if (!noerror)
|
||||||
|
error("getcwd() failed: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int status;
|
||||||
|
struct job *jp;
|
||||||
|
int pip[2];
|
||||||
|
|
||||||
|
pwd = stalloc(MAXPWD);
|
||||||
|
INTOFF;
|
||||||
|
if (pipe(pip) < 0)
|
||||||
|
error("Pipe call failed");
|
||||||
|
jp = makejob(NULL, 1);
|
||||||
|
if (forkshell(jp, NULL, FORK_NOJOB) == 0) {
|
||||||
|
(void) close(pip[0]);
|
||||||
|
if (pip[1] != 1) {
|
||||||
|
close(1);
|
||||||
|
copyfd(pip[1], 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 = pwd;
|
||||||
|
while ((i = read(pip[0], p, pwd + 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 == pwd || p[-1] != '\n') {
|
||||||
|
if (noerror) {
|
||||||
|
INTON;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error("pwd command failed");
|
||||||
|
}
|
||||||
|
p[-1] = '\0';
|
||||||
|
INTON;
|
||||||
|
curdir = savestr(pwd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: cd.h,v 1.6 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1995
|
* Copyright (c) 1995
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -10,7 +12,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -26,13 +28,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $FreeBSD: src/bin/sh/cd.h,v 1.7 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *getpwd(void);
|
void initpwd(void);
|
||||||
int cdcmd (int, char **);
|
void getpwd(int);
|
||||||
int pwdcmd(int, char **);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: cd.h,v 1.3 2006/03/31 09:59:04 philip Exp $
|
|
||||||
*/
|
|
370
bin/sh/error.c
Normal file
370
bin/sh/error.c
Normal file
|
@ -0,0 +1,370 @@
|
||||||
|
/* $NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg 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. 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.38 2012/03/15 02:02:20 joerg Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Errors and exceptions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
#include "eval.h" /* for commandname */
|
||||||
|
#include "main.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "show.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code to handle exceptions in C.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct jmploc *handler;
|
||||||
|
int exception;
|
||||||
|
volatile int suppressint;
|
||||||
|
volatile int intpending;
|
||||||
|
|
||||||
|
|
||||||
|
static void exverror(int, const char *, va_list) __dead;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(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(void)
|
||||||
|
{
|
||||||
|
sigset_t nsigset;
|
||||||
|
|
||||||
|
if (suppressint) {
|
||||||
|
intpending = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intpending = 0;
|
||||||
|
sigemptyset(&nsigset);
|
||||||
|
sigprocmask(SIG_SETMASK, &nsigset, NULL);
|
||||||
|
if (rootshell && iflag)
|
||||||
|
exraise(EXINT);
|
||||||
|
else {
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
raise(SIGINT);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
static __printflike(2, 0) void
|
||||||
|
exvwarning(int sv_errno, const char *msg, va_list ap)
|
||||||
|
{
|
||||||
|
/* Partially emulate line buffered output so that:
|
||||||
|
* printf '%d\n' 1 a 2
|
||||||
|
* and
|
||||||
|
* printf '%d %d %d\n' 1 a 2
|
||||||
|
* both generate sensible text when stdout and stderr are merged.
|
||||||
|
*/
|
||||||
|
if (output.nextc != output.buf && output.nextc[-1] == '\n')
|
||||||
|
flushout(&output);
|
||||||
|
if (commandname)
|
||||||
|
outfmt(&errout, "%s: ", commandname);
|
||||||
|
else
|
||||||
|
outfmt(&errout, "%s: ", getprogname());
|
||||||
|
if (msg != NULL) {
|
||||||
|
doformat(&errout, msg, ap);
|
||||||
|
if (sv_errno >= 0)
|
||||||
|
outfmt(&errout, ": ");
|
||||||
|
}
|
||||||
|
if (sv_errno >= 0)
|
||||||
|
outfmt(&errout, "%s", strerror(sv_errno));
|
||||||
|
out2c('\n');
|
||||||
|
flushout(&errout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exverror is called to raise the error exception. If the second argument
|
||||||
|
* is not NULL then error prints an error message using printf style
|
||||||
|
* formatting. It then raises the error exception.
|
||||||
|
*/
|
||||||
|
static __printflike(2, 0) void
|
||||||
|
exverror(int cond, const char *msg, va_list ap)
|
||||||
|
{
|
||||||
|
CLEAR_PENDING_INT;
|
||||||
|
INTOFF;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (msg) {
|
||||||
|
TRACE(("exverror(%d, \"", cond));
|
||||||
|
TRACEV((msg, ap));
|
||||||
|
TRACE(("\") pid=%d\n", getpid()));
|
||||||
|
} else
|
||||||
|
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||||
|
#endif
|
||||||
|
if (msg)
|
||||||
|
exvwarning(-1, msg, ap);
|
||||||
|
|
||||||
|
flushall();
|
||||||
|
exraise(cond);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
error(const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, msg);
|
||||||
|
exverror(EXERROR, msg, ap);
|
||||||
|
/* NOTREACHED */
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
exerror(int cond, const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, msg);
|
||||||
|
exverror(cond, msg, ap);
|
||||||
|
/* NOTREACHED */
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* error/warning routines for external builtins
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_exit(int rval)
|
||||||
|
{
|
||||||
|
exerrno = rval & 255;
|
||||||
|
exraise(EXEXEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_err(int status, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
exvwarning(errno, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
sh_exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_verr(int status, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
exvwarning(errno, fmt, ap);
|
||||||
|
sh_exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_errx(int status, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
exvwarning(-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
sh_exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_verrx(int status, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
exvwarning(-1, fmt, ap);
|
||||||
|
sh_exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_warn(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
exvwarning(errno, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_vwarn(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
exvwarning(errno, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_warnx(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
exvwarning(-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_vwarnx(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
exvwarning(-1, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table of error messages.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct errname {
|
||||||
|
short errcode; /* error number */
|
||||||
|
short action; /* operation which encountered the error */
|
||||||
|
const 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" },
|
||||||
|
{ EEXIST, ALL, "file exists" },
|
||||||
|
{ 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 EMFILE
|
||||||
|
{ 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 EAGAIN
|
||||||
|
{ 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
|
||||||
|
#ifdef ENAMETOOLONG
|
||||||
|
{ ENAMETOOLONG, ALL, "file name too long" },
|
||||||
|
#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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *
|
||||||
|
errmsg(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,3 +1,5 @@
|
||||||
|
/* $NetBSD: error.h,v 1.19 2012/03/15 02:02:20 joerg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,28 +32,38 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/error.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* 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 locations. The global variable handler contains the location to
|
||||||
* jump to when an exception occurs, and the global variable exception
|
* jump to when an exception occurs, and the global variable exception
|
||||||
* contains a code identifying the exception. To implement nested
|
* contains a code identifying the exeception. To implement nested
|
||||||
* exception handlers, the user should save the value of handler on entry
|
* 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
|
* to an inner scope, set handler to point to a jmploc structure for the
|
||||||
* inner scope, and restore handler on exit from the scope.
|
* inner scope, and restore handler on exit from the scope.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
struct jmploc {
|
struct jmploc {
|
||||||
jmp_buf loc;
|
jmp_buf loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct jmploc *handler;
|
extern struct jmploc *handler;
|
||||||
extern volatile sig_atomic_t exception;
|
extern int exception;
|
||||||
|
extern int exerrno; /* error for EXEXEC */
|
||||||
|
|
||||||
/* exceptions */
|
/* exceptions */
|
||||||
#define EXINT 0 /* SIGINT received */
|
#define EXINT 0 /* SIGINT received */
|
||||||
|
@ -67,8 +79,8 @@ extern volatile sig_atomic_t exception;
|
||||||
* more fun than worrying about efficiency and portability. :-))
|
* more fun than worrying about efficiency and portability. :-))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern volatile sig_atomic_t suppressint;
|
extern volatile int suppressint;
|
||||||
extern volatile sig_atomic_t intpending;
|
extern volatile int intpending;
|
||||||
|
|
||||||
#define INTOFF suppressint++
|
#define INTOFF suppressint++
|
||||||
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||||
|
@ -76,12 +88,24 @@ extern volatile sig_atomic_t intpending;
|
||||||
#define CLEAR_PENDING_INT intpending = 0
|
#define CLEAR_PENDING_INT intpending = 0
|
||||||
#define int_pending() intpending
|
#define int_pending() intpending
|
||||||
|
|
||||||
#define __printf0like(a,b)
|
#if ! defined(SHELL_BUILTIN)
|
||||||
|
void exraise(int) __dead;
|
||||||
void exraise(int);
|
|
||||||
void onint(void);
|
void onint(void);
|
||||||
void error(const char *, ...) __printf0like(1, 2);
|
void error(const char *, ...) __dead __printflike(1, 2);
|
||||||
void exerror(int, const char *, ...) __printf0like(2, 3);
|
void exerror(int, const char *, ...) __dead __printflike(2, 3);
|
||||||
|
const char *errmsg(int, int);
|
||||||
|
#endif /* ! SHELL_BUILTIN */
|
||||||
|
|
||||||
|
void sh_err(int, const char *, ...) __dead __printflike(2, 3);
|
||||||
|
void sh_verr(int, const char *, va_list) __dead __printflike(2, 0);
|
||||||
|
void sh_errx(int, const char *, ...) __dead __printflike(2, 3);
|
||||||
|
void sh_verrx(int, const char *, va_list) __dead __printflike(2, 0);
|
||||||
|
void sh_warn(const char *, ...) __printflike(1, 2);
|
||||||
|
void sh_vwarn(const char *, va_list) __printflike(1, 0);
|
||||||
|
void sh_warnx(const char *, ...) __printflike(1, 2);
|
||||||
|
void sh_vwarnx(const char *, va_list) __printflike(1, 0);
|
||||||
|
|
||||||
|
void sh_exit(int) __dead;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -89,13 +113,7 @@ void exerror(int, const char *, ...) __printf0like(2, 3);
|
||||||
* so we use _setjmp instead.
|
* so we use _setjmp instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef BSD
|
#if defined(BSD) && !defined(__SVR4)
|
||||||
#ifndef __minix
|
|
||||||
#define setjmp(jmploc) _setjmp(jmploc)
|
#define setjmp(jmploc) _setjmp(jmploc)
|
||||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
|
|
||||||
*/
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: eval.h,v 1.15 2008/02/15 17:26:06 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,11 +32,11 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/eval.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern char *commandname; /* currently executing command */
|
extern const char *commandname; /* currently executing command */
|
||||||
extern int exitstatus; /* exit status of last command */
|
extern int exitstatus; /* exit status of last command */
|
||||||
|
extern int back_exitstatus; /* exit status of backquoted command */
|
||||||
extern struct strlist *cmdenviron; /* environment for builtin command */
|
extern struct strlist *cmdenviron; /* environment for builtin command */
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,18 +47,10 @@ struct backcmd { /* result of evalbackcmd */
|
||||||
struct job *jp; /* job structure for command */
|
struct job *jp; /* job structure for command */
|
||||||
};
|
};
|
||||||
|
|
||||||
int evalcmd(int, char **);
|
void evalstring(char *, int);
|
||||||
void evalstring(char *);
|
|
||||||
union node; /* BLETCH for ansi C */
|
union node; /* BLETCH for ansi C */
|
||||||
void evaltree(union node *, int);
|
void evaltree(union node *, int);
|
||||||
void evalbackcmd(union node *, struct backcmd *);
|
void evalbackcmd(union node *, struct backcmd *);
|
||||||
int bltincmd(int, char **);
|
|
||||||
int breakcmd(int, char **);
|
|
||||||
int returncmd(int, char **);
|
|
||||||
int falsecmd(int, char **);
|
|
||||||
int truecmd(int, char **);
|
|
||||||
int execcmd(int, char **);
|
|
||||||
int commandcmd(int, char **);
|
|
||||||
|
|
||||||
/* in_function returns nonzero if we are currently evaluating a function */
|
/* in_function returns nonzero if we are currently evaluating a function */
|
||||||
#define in_function() funcnest
|
#define in_function() funcnest
|
||||||
|
@ -68,7 +62,3 @@ extern int evalskip;
|
||||||
#define SKIPCONT 2
|
#define SKIPCONT 2
|
||||||
#define SKIPFUNC 3
|
#define SKIPFUNC 3
|
||||||
#define SKIPFILE 4
|
#define SKIPFILE 4
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: eval.h,v 1.3 2006/03/30 15:39:25 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: exec.c,v 1.45 2013/11/01 16:49:02 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,21 +32,22 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: exec.c,v 1.45 2013/11/01 16:49:02 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
#include <sys/cdefs.h>
|
|
||||||
/*
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.24.2.1 2004/09/30 04:41:55 des Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -97,13 +100,18 @@ STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
||||||
int exerrno = 0; /* Last exec error */
|
int exerrno = 0; /* Last exec error */
|
||||||
|
|
||||||
|
|
||||||
STATIC void tryexec(char *, char **, char **);
|
STATIC void tryexec(char *, char **, char **, int);
|
||||||
STATIC void printentry(struct tblentry *, int);
|
STATIC void printentry(struct tblentry *, int);
|
||||||
STATIC struct tblentry *cmdlookup(char *, int);
|
STATIC void clearcmdentry(int);
|
||||||
|
STATIC struct tblentry *cmdlookup(const char *, int);
|
||||||
STATIC void delete_cmd_entry(void);
|
STATIC void delete_cmd_entry(void);
|
||||||
STATIC void addcmdentry(char *, struct cmdentry *);
|
|
||||||
|
#ifndef BSD
|
||||||
|
STATIC void execinterp(char **, char **);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *const parsekwd[];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exec a program. Never returns. If you change this routine, you may
|
* Exec a program. Never returns. If you change this routine, you may
|
||||||
|
@ -111,19 +119,19 @@ STATIC void addcmdentry(char *, struct cmdentry *);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
shellexec(char **argv, char **envp, char *path, int index)
|
shellexec(char **argv, char **envp, const char *path, int idx, int vforked)
|
||||||
{
|
{
|
||||||
char *cmdname;
|
char *cmdname;
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
if (strchr(argv[0], '/') != NULL) {
|
if (strchr(argv[0], '/') != NULL) {
|
||||||
tryexec(argv[0], argv, envp);
|
tryexec(argv[0], argv, envp, vforked);
|
||||||
e = errno;
|
e = errno;
|
||||||
} else {
|
} else {
|
||||||
e = ENOENT;
|
e = ENOENT;
|
||||||
while ((cmdname = padvance(&path, argv[0])) != NULL) {
|
while ((cmdname = padvance(&path, argv[0])) != NULL) {
|
||||||
if (--index < 0 && pathopt == NULL) {
|
if (--idx < 0 && pathopt == NULL) {
|
||||||
tryexec(cmdname, argv, envp);
|
tryexec(cmdname, argv, envp, vforked);
|
||||||
if (errno != ENOENT && errno != ENOTDIR)
|
if (errno != ENOENT && errno != ENOTDIR)
|
||||||
e = errno;
|
e = errno;
|
||||||
}
|
}
|
||||||
|
@ -143,31 +151,137 @@ shellexec(char **argv, char **envp, char *path, int index)
|
||||||
exerrno = 2;
|
exerrno = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e == ENOENT || e == ENOTDIR)
|
TRACE(("shellexec failed for %s, errno %d, vforked %d, suppressint %d\n",
|
||||||
exerror(EXEXEC, "%s: not found", argv[0]);
|
argv[0], e, vforked, suppressint ));
|
||||||
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
|
exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
tryexec(char *cmd, char **argv, char **envp)
|
tryexec(char *cmd, char **argv, char **envp, int vforked)
|
||||||
{
|
{
|
||||||
int e;
|
int e;
|
||||||
|
#ifndef BSD
|
||||||
|
char *p;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SYSV
|
||||||
|
do {
|
||||||
|
execve(cmd, argv, envp);
|
||||||
|
} while (errno == EINTR);
|
||||||
|
#else
|
||||||
execve(cmd, argv, envp);
|
execve(cmd, argv, envp);
|
||||||
|
#endif
|
||||||
e = errno;
|
e = errno;
|
||||||
if (e == ENOEXEC) {
|
if (e == ENOEXEC) {
|
||||||
|
if (vforked) {
|
||||||
|
/* We are currently vfork(2)ed, so raise an
|
||||||
|
* exception, and evalcommand will try again
|
||||||
|
* with a normal fork(2).
|
||||||
|
*/
|
||||||
|
exraise(EXSHELLPROC);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
TRACE(("execve(cmd=%s) returned ENOEXEC\n", cmd));
|
||||||
|
#endif
|
||||||
initshellproc();
|
initshellproc();
|
||||||
setinputfile(cmd, 0);
|
setinputfile(cmd, 0);
|
||||||
commandname = arg0 = savestr(argv[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);
|
setparam(argv + 1);
|
||||||
exraise(EXSHELLPROC);
|
exraise(EXSHELLPROC);
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
errno = e;
|
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(char **argv, char **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);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a path search. The variable path (passed by reference) should be
|
* 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
|
* set to the start of the path before the first call; padvance will update
|
||||||
|
@ -178,13 +292,14 @@ tryexec(char *cmd, char **argv, char **envp)
|
||||||
* NULL.
|
* NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *pathopt;
|
const char *pathopt;
|
||||||
|
|
||||||
char *
|
char *
|
||||||
padvance(char **path, char *name)
|
padvance(const char **path, const char *name)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
const char *p;
|
||||||
char *start;
|
char *q;
|
||||||
|
const char *start;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (*path == NULL)
|
if (*path == NULL)
|
||||||
|
@ -219,7 +334,7 @@ padvance(char **path, char *name)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
hashcmd(int argc __unused, char **argv __unused)
|
hashcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
@ -239,7 +354,7 @@ hashcmd(int argc __unused, char **argv __unused)
|
||||||
if (*argptr == NULL) {
|
if (*argptr == NULL) {
|
||||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||||
if (cmdp->cmdtype == CMDNORMAL)
|
if (verbose || cmdp->cmdtype == CMDNORMAL)
|
||||||
printentry(cmdp, verbose);
|
printentry(cmdp, verbose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,14 +365,12 @@ hashcmd(int argc __unused, char **argv __unused)
|
||||||
&& (cmdp->cmdtype == CMDNORMAL
|
&& (cmdp->cmdtype == CMDNORMAL
|
||||||
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
find_command(name, &entry, 1, pathval());
|
find_command(name, &entry, DO_ERR, pathval());
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
||||||
cmdp = cmdlookup(name, 0);
|
cmdp = cmdlookup(name, 0);
|
||||||
if (cmdp != NULL)
|
if (cmdp != NULL)
|
||||||
printentry(cmdp, verbose);
|
printentry(cmdp, verbose);
|
||||||
else
|
|
||||||
outfmt(&errout, "%s: not found\n", name);
|
|
||||||
}
|
}
|
||||||
flushall();
|
flushall();
|
||||||
}
|
}
|
||||||
|
@ -270,34 +383,40 @@ hashcmd(int argc __unused, char **argv __unused)
|
||||||
STATIC void
|
STATIC void
|
||||||
printentry(struct tblentry *cmdp, int verbose)
|
printentry(struct tblentry *cmdp, int verbose)
|
||||||
{
|
{
|
||||||
int index;
|
int idx;
|
||||||
char *path;
|
const char *path;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (cmdp->cmdtype == CMDNORMAL) {
|
switch (cmdp->cmdtype) {
|
||||||
index = cmdp->param.index;
|
case CMDNORMAL:
|
||||||
|
idx = cmdp->param.index;
|
||||||
path = pathval();
|
path = pathval();
|
||||||
do {
|
do {
|
||||||
name = padvance(&path, cmdp->cmdname);
|
name = padvance(&path, cmdp->cmdname);
|
||||||
stunalloc(name);
|
stunalloc(name);
|
||||||
} while (--index >= 0);
|
} while (--idx >= 0);
|
||||||
out1str(name);
|
out1str(name);
|
||||||
} else if (cmdp->cmdtype == CMDBUILTIN) {
|
break;
|
||||||
|
case CMDSPLBLTIN:
|
||||||
|
out1fmt("special builtin %s", cmdp->cmdname);
|
||||||
|
break;
|
||||||
|
case CMDBUILTIN:
|
||||||
out1fmt("builtin %s", cmdp->cmdname);
|
out1fmt("builtin %s", cmdp->cmdname);
|
||||||
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
break;
|
||||||
|
case CMDFUNCTION:
|
||||||
out1fmt("function %s", cmdp->cmdname);
|
out1fmt("function %s", cmdp->cmdname);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
struct procstat ps;
|
||||||
INTOFF;
|
INTOFF;
|
||||||
name = commandtext(cmdp->param.func);
|
commandtext(&ps, cmdp->param.func);
|
||||||
out1c(' ');
|
|
||||||
out1str(name);
|
|
||||||
ckfree(name);
|
|
||||||
INTON;
|
INTON;
|
||||||
|
out1str("() { ");
|
||||||
|
out1str(ps.cmd);
|
||||||
|
out1str("; }");
|
||||||
}
|
}
|
||||||
#if DEBUG
|
break;
|
||||||
} else {
|
default:
|
||||||
error("internal error: cmdtype %d", cmdp->cmdtype);
|
error("internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (cmdp->rehash)
|
if (cmdp->rehash)
|
||||||
out1c('*');
|
out1c('*');
|
||||||
|
@ -312,36 +431,78 @@ printentry(struct tblentry *cmdp, int verbose)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
find_command(char *name, struct cmdentry *entry, int printerr, char *path)
|
find_command(char *name, struct cmdentry *entry, int act, const char *path)
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp, loc_cmd;
|
||||||
int index;
|
int idx;
|
||||||
int prev;
|
int prev;
|
||||||
char *fullname;
|
char *fullname;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
int e;
|
int e;
|
||||||
int i;
|
int (*bltin)(int,char **);
|
||||||
|
|
||||||
/* If name contains a slash, don't use the hash table */
|
/* If name contains a slash, don't use PATH or hash table */
|
||||||
if (strchr(name, '/') != NULL) {
|
if (strchr(name, '/') != NULL) {
|
||||||
|
if (act & DO_ABS) {
|
||||||
|
while (stat(name, &statb) < 0) {
|
||||||
|
#ifdef SYSV
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
if (errno != ENOENT && errno != ENOTDIR)
|
||||||
|
e = errno;
|
||||||
|
entry->cmdtype = CMDUNKNOWN;
|
||||||
|
entry->u.index = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry->cmdtype = CMDNORMAL;
|
||||||
|
entry->u.index = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
entry->cmdtype = CMDNORMAL;
|
entry->cmdtype = CMDNORMAL;
|
||||||
entry->u.index = 0;
|
entry->u.index = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If name is in the table, and not invalidated by cd, we're done */
|
if (path != pathval())
|
||||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
|
act |= DO_ALTPATH;
|
||||||
goto success;
|
|
||||||
|
if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL)
|
||||||
|
act |= DO_ALTBLTIN;
|
||||||
|
|
||||||
|
/* If name is in the table, check answer will be ok */
|
||||||
|
if ((cmdp = cmdlookup(name, 0)) != NULL) {
|
||||||
|
do {
|
||||||
|
switch (cmdp->cmdtype) {
|
||||||
|
case CMDNORMAL:
|
||||||
|
if (act & DO_ALTPATH) {
|
||||||
|
cmdp = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMDFUNCTION:
|
||||||
|
if (act & DO_NOFUNC) {
|
||||||
|
cmdp = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CMDBUILTIN:
|
||||||
|
if ((act & DO_ALTBLTIN) || builtinloc >= 0) {
|
||||||
|
cmdp = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* if not invalidated by cd, we're done */
|
||||||
|
if (cmdp->rehash == 0)
|
||||||
|
goto success;
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* If %builtin not in path, check for builtin next */
|
/* If %builtin not in path, check for builtin next */
|
||||||
if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
|
if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc < 0) &&
|
||||||
INTOFF;
|
(bltin = find_builtin(name)) != 0)
|
||||||
cmdp = cmdlookup(name, 1);
|
goto builtin_success;
|
||||||
cmdp->cmdtype = CMDBUILTIN;
|
|
||||||
cmdp->param.index = i;
|
|
||||||
INTON;
|
|
||||||
goto success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have to search path. */
|
/* We have to search path. */
|
||||||
prev = -1; /* where to start */
|
prev = -1; /* where to start */
|
||||||
|
@ -353,35 +514,35 @@ find_command(char *name, struct cmdentry *entry, int printerr, char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
e = ENOENT;
|
e = ENOENT;
|
||||||
index = -1;
|
idx = -1;
|
||||||
loop:
|
loop:
|
||||||
while ((fullname = padvance(&path, name)) != NULL) {
|
while ((fullname = padvance(&path, name)) != NULL) {
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
index++;
|
idx++;
|
||||||
if (pathopt) {
|
if (pathopt) {
|
||||||
if (prefix("builtin", pathopt)) {
|
if (prefix("builtin", pathopt)) {
|
||||||
if ((i = find_builtin(name)) < 0)
|
if ((bltin = find_builtin(name)) == 0)
|
||||||
goto loop;
|
goto loop;
|
||||||
INTOFF;
|
goto builtin_success;
|
||||||
cmdp = cmdlookup(name, 1);
|
|
||||||
cmdp->cmdtype = CMDBUILTIN;
|
|
||||||
cmdp->param.index = i;
|
|
||||||
INTON;
|
|
||||||
goto success;
|
|
||||||
} else if (prefix("func", pathopt)) {
|
} else if (prefix("func", pathopt)) {
|
||||||
/* handled below */
|
/* handled below */
|
||||||
} else {
|
} else {
|
||||||
goto loop; /* ignore unimplemented options */
|
/* ignore unimplemented options */
|
||||||
|
goto loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if rehash, don't redo absolute path names */
|
/* if rehash, don't redo absolute path names */
|
||||||
if (fullname[0] == '/' && index <= prev) {
|
if (fullname[0] == '/' && idx <= prev) {
|
||||||
if (index < prev)
|
if (idx < prev)
|
||||||
goto loop;
|
goto loop;
|
||||||
TRACE(("searchexec \"%s\": no change\n", name));
|
TRACE(("searchexec \"%s\": no change\n", name));
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
if (stat(fullname, &statb) < 0) {
|
while (stat(fullname, &statb) < 0) {
|
||||||
|
#ifdef SYSV
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
if (errno != ENOENT && errno != ENOTDIR)
|
if (errno != ENOENT && errno != ENOTDIR)
|
||||||
e = errno;
|
e = errno;
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -390,14 +551,19 @@ loop:
|
||||||
if (!S_ISREG(statb.st_mode))
|
if (!S_ISREG(statb.st_mode))
|
||||||
goto loop;
|
goto loop;
|
||||||
if (pathopt) { /* this is a %func directory */
|
if (pathopt) { /* this is a %func directory */
|
||||||
|
if (act & DO_NOFUNC)
|
||||||
|
goto loop;
|
||||||
stalloc(strlen(fullname) + 1);
|
stalloc(strlen(fullname) + 1);
|
||||||
readcmdfile(fullname);
|
readcmdfile(fullname);
|
||||||
if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
|
if ((cmdp = cmdlookup(name, 0)) == NULL ||
|
||||||
|
cmdp->cmdtype != CMDFUNCTION)
|
||||||
error("%s not defined in %s", name, fullname);
|
error("%s not defined in %s", name, fullname);
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
#ifdef notdef
|
#ifdef notdef
|
||||||
|
/* XXX this code stops root executing stuff, and is buggy
|
||||||
|
if you need a group from the group list. */
|
||||||
if (statb.st_uid == geteuid()) {
|
if (statb.st_uid == geteuid()) {
|
||||||
if ((statb.st_mode & 0100) == 0)
|
if ((statb.st_mode & 0100) == 0)
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -411,9 +577,13 @@ loop:
|
||||||
#endif
|
#endif
|
||||||
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
||||||
INTOFF;
|
INTOFF;
|
||||||
cmdp = cmdlookup(name, 1);
|
if (act & DO_ALTPATH) {
|
||||||
|
stalloc(strlen(fullname) + 1);
|
||||||
|
cmdp = &loc_cmd;
|
||||||
|
} else
|
||||||
|
cmdp = cmdlookup(name, 1);
|
||||||
cmdp->cmdtype = CMDNORMAL;
|
cmdp->cmdtype = CMDNORMAL;
|
||||||
cmdp->param.index = index;
|
cmdp->param.index = idx;
|
||||||
INTON;
|
INTON;
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
|
@ -421,19 +591,30 @@ loop:
|
||||||
/* We failed. If there was an entry for this command, delete it */
|
/* We failed. If there was an entry for this command, delete it */
|
||||||
if (cmdp)
|
if (cmdp)
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
if (printerr) {
|
if (act & DO_ERR)
|
||||||
if (e == ENOENT || e == ENOTDIR)
|
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
|
||||||
outfmt(out2, "%s: not found\n", name);
|
|
||||||
else
|
|
||||||
outfmt(out2, "%s: %s\n", name, strerror(e));
|
|
||||||
}
|
|
||||||
entry->cmdtype = CMDUNKNOWN;
|
entry->cmdtype = CMDUNKNOWN;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
builtin_success:
|
||||||
|
INTOFF;
|
||||||
|
if (act & DO_ALTPATH)
|
||||||
|
cmdp = &loc_cmd;
|
||||||
|
else
|
||||||
|
cmdp = cmdlookup(name, 1);
|
||||||
|
if (cmdp->cmdtype == CMDFUNCTION)
|
||||||
|
/* DO_NOFUNC must have been set */
|
||||||
|
cmdp = &loc_cmd;
|
||||||
|
cmdp->cmdtype = CMDBUILTIN;
|
||||||
|
cmdp->param.bltin = bltin;
|
||||||
|
INTON;
|
||||||
success:
|
success:
|
||||||
cmdp->rehash = 0;
|
if (cmdp) {
|
||||||
entry->cmdtype = cmdp->cmdtype;
|
cmdp->rehash = 0;
|
||||||
entry->u = cmdp->param;
|
entry->cmdtype = cmdp->cmdtype;
|
||||||
|
entry->u = cmdp->param;
|
||||||
|
} else
|
||||||
|
entry->cmdtype = CMDUNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,15 +624,48 @@ success:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
find_builtin(char *name)
|
(*find_builtin(char *name))(int, char **)
|
||||||
{
|
{
|
||||||
const struct builtincmd *bp;
|
const struct builtincmd *bp;
|
||||||
|
|
||||||
for (bp = builtincmd ; bp->name ; bp++) {
|
for (bp = builtincmd ; bp->name ; bp++) {
|
||||||
if (*bp->name == *name && equal(bp->name, name))
|
if (*bp->name == *name
|
||||||
return bp->code;
|
&& (*name == '%' || equal(bp->name, name)))
|
||||||
|
return bp->builtin;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
(*find_splbltin(char *name))(int, char **)
|
||||||
|
{
|
||||||
|
const struct builtincmd *bp;
|
||||||
|
|
||||||
|
for (bp = splbltincmd ; bp->name ; bp++) {
|
||||||
|
if (*bp->name == *name && equal(bp->name, name))
|
||||||
|
return bp->builtin;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At shell startup put special builtins into hash table.
|
||||||
|
* ensures they are executed first (see posix).
|
||||||
|
* We stop functions being added with the same name
|
||||||
|
* (as they are impossible to call)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
hash_special_builtins(void)
|
||||||
|
{
|
||||||
|
const struct builtincmd *bp;
|
||||||
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
|
for (bp = splbltincmd ; bp->name ; bp++) {
|
||||||
|
cmdp = cmdlookup(bp->name, 1);
|
||||||
|
cmdp->cmdtype = CMDSPLBLTIN;
|
||||||
|
cmdp->param.bltin = bp->builtin;
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -479,27 +693,28 @@ hashcd(void)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Fix command hash table when PATH changed.
|
||||||
* Called before PATH is changed. The argument is the new value of PATH;
|
* Called before PATH is changed. The argument is the new value of PATH;
|
||||||
* pathval() still returns the old value at this point. Called with
|
* pathval() still returns the old value at this point.
|
||||||
* interrupts off.
|
* Called with interrupts off.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
changepath(const char *newval)
|
changepath(const char *newval)
|
||||||
{
|
{
|
||||||
const char *old, *new;
|
const char *old, *new;
|
||||||
int index;
|
int idx;
|
||||||
int firstchange;
|
int firstchange;
|
||||||
int bltin;
|
int bltin;
|
||||||
|
|
||||||
old = pathval();
|
old = pathval();
|
||||||
new = newval;
|
new = newval;
|
||||||
firstchange = 9999; /* assume no change */
|
firstchange = 9999; /* assume no change */
|
||||||
index = 0;
|
idx = 0;
|
||||||
bltin = -1;
|
bltin = -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*old != *new) {
|
if (*old != *new) {
|
||||||
firstchange = index;
|
firstchange = idx;
|
||||||
if ((*old == '\0' && *new == ':')
|
if ((*old == '\0' && *new == ':')
|
||||||
|| (*old == ':' && *new == '\0'))
|
|| (*old == ':' && *new == '\0'))
|
||||||
firstchange++;
|
firstchange++;
|
||||||
|
@ -508,9 +723,9 @@ changepath(const char *newval)
|
||||||
if (*new == '\0')
|
if (*new == '\0')
|
||||||
break;
|
break;
|
||||||
if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
|
if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
|
||||||
bltin = index;
|
bltin = idx;
|
||||||
if (*new == ':') {
|
if (*new == ':') {
|
||||||
index++;
|
idx++;
|
||||||
}
|
}
|
||||||
new++, old++;
|
new++, old++;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +743,7 @@ changepath(const char *newval)
|
||||||
* PATH which has changed.
|
* PATH which has changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
STATIC void
|
||||||
clearcmdentry(int firstchange)
|
clearcmdentry(int firstchange)
|
||||||
{
|
{
|
||||||
struct tblentry **tblp;
|
struct tblentry **tblp;
|
||||||
|
@ -559,7 +774,13 @@ clearcmdentry(int firstchange)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
INCLUDE "exec.h"
|
MKINIT void deletefuncs(void);
|
||||||
|
MKINIT void hash_special_builtins(void);
|
||||||
|
|
||||||
|
INIT {
|
||||||
|
hash_special_builtins();
|
||||||
|
}
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
deletefuncs();
|
deletefuncs();
|
||||||
}
|
}
|
||||||
|
@ -598,14 +819,14 @@ deletefuncs(void)
|
||||||
* entry.
|
* entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC struct tblentry **lastcmdentry;
|
struct tblentry **lastcmdentry;
|
||||||
|
|
||||||
|
|
||||||
STATIC struct tblentry *
|
STATIC struct tblentry *
|
||||||
cmdlookup(char *name, int add)
|
cmdlookup(const char *name, int add)
|
||||||
{
|
{
|
||||||
int hashval;
|
int hashval;
|
||||||
char *p;
|
const char *p;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
|
|
||||||
|
@ -652,23 +873,42 @@ delete_cmd_entry(void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef notdef
|
||||||
|
void
|
||||||
|
getcmdentry(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
|
* Add a new command entry, replacing any existing command entry for
|
||||||
* the same name.
|
* the same name - except special builtins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
STATIC void
|
||||||
addcmdentry(char *name, struct cmdentry *entry)
|
addcmdentry(char *name, struct cmdentry *entry)
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
cmdp = cmdlookup(name, 1);
|
cmdp = cmdlookup(name, 1);
|
||||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
if (cmdp->cmdtype != CMDSPLBLTIN) {
|
||||||
freefunc(cmdp->param.func);
|
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||||
|
freefunc(cmdp->param.func);
|
||||||
|
}
|
||||||
|
cmdp->cmdtype = entry->cmdtype;
|
||||||
|
cmdp->param = entry->u;
|
||||||
}
|
}
|
||||||
cmdp->cmdtype = entry->cmdtype;
|
|
||||||
cmdp->param = entry->u;
|
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,16 +939,17 @@ unsetfunc(char *name)
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
if ((cmdp = cmdlookup(name, 0)) != NULL &&
|
||||||
|
cmdp->cmdtype == CMDFUNCTION) {
|
||||||
freefunc(cmdp->param.func);
|
freefunc(cmdp->param.func);
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate and print what a word is...
|
* Locate and print what a word is...
|
||||||
|
* also used for 'command -[v|V]'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -716,76 +957,115 @@ typecmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct cmdentry entry;
|
struct cmdentry entry;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
char **pp;
|
const char * const *pp;
|
||||||
struct alias *ap;
|
struct alias *ap;
|
||||||
int i;
|
int err = 0;
|
||||||
int error = 0;
|
char *arg;
|
||||||
extern char *const parsekwd[];
|
int c;
|
||||||
|
int V_flag = 0;
|
||||||
|
int v_flag = 0;
|
||||||
|
int p_flag = 0;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
while ((c = nextopt("vVp")) != 0) {
|
||||||
out1str(argv[i]);
|
switch (c) {
|
||||||
|
case 'v': v_flag = 1; break;
|
||||||
|
case 'V': V_flag = 1; break;
|
||||||
|
case 'p': p_flag = 1; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_flag && (v_flag || V_flag))
|
||||||
|
error("cannot specify -p with -v or -V");
|
||||||
|
|
||||||
|
while ((arg = *argptr++)) {
|
||||||
|
if (!v_flag)
|
||||||
|
out1str(arg);
|
||||||
/* First look at the keywords */
|
/* First look at the keywords */
|
||||||
for (pp = (char **)parsekwd; *pp; pp++)
|
for (pp = parsekwd; *pp; pp++)
|
||||||
if (**pp == *argv[i] && equal(*pp, argv[i]))
|
if (**pp == *arg && equal(*pp, arg))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (*pp) {
|
if (*pp) {
|
||||||
out1str(" is a shell keyword\n");
|
if (v_flag)
|
||||||
|
err = 1;
|
||||||
|
else
|
||||||
|
out1str(" is a shell keyword\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then look at the aliases */
|
/* Then look at the aliases */
|
||||||
if ((ap = lookupalias(argv[i], 1)) != NULL) {
|
if ((ap = lookupalias(arg, 1)) != NULL) {
|
||||||
out1fmt(" is an alias for %s\n", ap->val);
|
if (!v_flag)
|
||||||
|
out1fmt(" is an alias for \n");
|
||||||
|
out1fmt("%s\n", ap->val);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then check if it is a tracked alias */
|
/* Then check if it is a tracked alias */
|
||||||
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
|
if ((cmdp = cmdlookup(arg, 0)) != NULL) {
|
||||||
entry.cmdtype = cmdp->cmdtype;
|
entry.cmdtype = cmdp->cmdtype;
|
||||||
entry.u = cmdp->param;
|
entry.u = cmdp->param;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* Finally use brute force */
|
/* Finally use brute force */
|
||||||
find_command(argv[i], &entry, 0, pathval());
|
find_command(arg, &entry, DO_ABS, pathval());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (entry.cmdtype) {
|
switch (entry.cmdtype) {
|
||||||
case CMDNORMAL: {
|
case CMDNORMAL: {
|
||||||
if (strchr(argv[i], '/') == NULL) {
|
if (strchr(arg, '/') == NULL) {
|
||||||
char *path = pathval(), *name;
|
const char *path = pathval();
|
||||||
|
char *name;
|
||||||
int j = entry.u.index;
|
int j = entry.u.index;
|
||||||
do {
|
do {
|
||||||
name = padvance(&path, argv[i]);
|
name = padvance(&path, arg);
|
||||||
stunalloc(name);
|
stunalloc(name);
|
||||||
} while (--j >= 0);
|
} while (--j >= 0);
|
||||||
out1fmt(" is%s %s\n",
|
if (!v_flag)
|
||||||
cmdp ? " a tracked alias for" : "", name);
|
out1fmt(" is%s ",
|
||||||
|
cmdp ? " a tracked alias for" : "");
|
||||||
|
out1fmt("%s\n", name);
|
||||||
} else {
|
} else {
|
||||||
if (access(argv[i], X_OK) == 0)
|
if (access(arg, X_OK) == 0) {
|
||||||
out1fmt(" is %s\n", argv[i]);
|
if (!v_flag)
|
||||||
else
|
out1fmt(" is ");
|
||||||
out1fmt(": %s\n", strerror(errno));
|
out1fmt("%s\n", arg);
|
||||||
|
} else {
|
||||||
|
if (!v_flag)
|
||||||
|
out1fmt(": %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
else
|
||||||
|
err = 126;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMDFUNCTION:
|
case CMDFUNCTION:
|
||||||
out1str(" is a shell function\n");
|
if (!v_flag)
|
||||||
|
out1str(" is a shell function\n");
|
||||||
|
else
|
||||||
|
out1fmt("%s\n", arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMDBUILTIN:
|
case CMDBUILTIN:
|
||||||
out1str(" is a shell builtin\n");
|
if (!v_flag)
|
||||||
|
out1str(" is a shell builtin\n");
|
||||||
|
else
|
||||||
|
out1fmt("%s\n", arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMDSPLBLTIN:
|
||||||
|
if (!v_flag)
|
||||||
|
out1str(" is a special shell builtin\n");
|
||||||
|
else
|
||||||
|
out1fmt("%s\n", arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
out1str(": not found\n");
|
if (!v_flag)
|
||||||
error |= 127;
|
out1str(": not found\n");
|
||||||
|
err = 127;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: exec.c,v 1.6 2006/04/10 14:47:03 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: exec.h,v 1.23 2012/03/15 02:02:20 joerg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,41 +32,45 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||||
* $FreeBSD: src/bin/sh/exec.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* values of cmdtype */
|
/* values of cmdtype */
|
||||||
#define CMDUNKNOWN -1 /* no entry in table for command */
|
#define CMDUNKNOWN -1 /* no entry in table for command */
|
||||||
#define CMDNORMAL 0 /* command is an executable program */
|
#define CMDNORMAL 0 /* command is an executable program */
|
||||||
#define CMDBUILTIN 1 /* command is a shell builtin */
|
#define CMDFUNCTION 1 /* command is a shell function */
|
||||||
#define CMDFUNCTION 2 /* command is a shell function */
|
#define CMDBUILTIN 2 /* command is a shell builtin */
|
||||||
|
#define CMDSPLBLTIN 3 /* command is a special shell builtin */
|
||||||
|
|
||||||
|
|
||||||
struct cmdentry {
|
struct cmdentry {
|
||||||
int cmdtype;
|
int cmdtype;
|
||||||
union param {
|
union param {
|
||||||
int index;
|
int index;
|
||||||
|
int (*bltin)(int, char**);
|
||||||
union node *func;
|
union node *func;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern char *pathopt; /* set by padvance */
|
/* action to find_command() */
|
||||||
extern int exerrno; /* last exec error */
|
#define DO_ERR 0x01 /* prints errors */
|
||||||
|
#define DO_ABS 0x02 /* checks absolute paths */
|
||||||
|
#define DO_NOFUNC 0x04 /* don't return shell functions, for command */
|
||||||
|
#define DO_ALTPATH 0x08 /* using alternate path */
|
||||||
|
#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
|
||||||
|
|
||||||
void shellexec(char **, char **, char *, int);
|
extern const char *pathopt; /* set by padvance */
|
||||||
char *padvance(char **, char *);
|
|
||||||
int hashcmd(int, char **);
|
void shellexec(char **, char **, const char *, int, int) __dead;
|
||||||
void find_command(char *, struct cmdentry *, int, char *);
|
char *padvance(const char **, const char *);
|
||||||
int find_builtin(char *);
|
void find_command(char *, struct cmdentry *, int, const char *);
|
||||||
|
int (*find_builtin(char *))(int, char **);
|
||||||
|
int (*find_splbltin(char *))(int, char **);
|
||||||
void hashcd(void);
|
void hashcd(void);
|
||||||
void changepath(const char *);
|
void changepath(const char *);
|
||||||
void deletefuncs(void);
|
void deletefuncs(void);
|
||||||
|
void getcmdentry(char *, struct cmdentry *);
|
||||||
|
void addcmdentry(char *, struct cmdentry *);
|
||||||
void defun(char *, union node *);
|
void defun(char *, union node *);
|
||||||
int unsetfunc(char *);
|
int unsetfunc(char *);
|
||||||
int typecmd(int, char **);
|
void hash_special_builtins(void);
|
||||||
void clearcmdentry(int);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
|
|
||||||
*/
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: expand.h,v 1.19 2012/12/22 20:15:22 dsl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,9 +32,10 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/expand.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
struct strlist {
|
struct strlist {
|
||||||
struct strlist *next;
|
struct strlist *next;
|
||||||
char *text;
|
char *text;
|
||||||
|
@ -52,23 +55,19 @@ struct arglist {
|
||||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||||
|
#define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */
|
||||||
|
#define EXP_IN_QUOTES 0x40 /* don't set EXP_IFS_SPLIT again */
|
||||||
|
|
||||||
|
|
||||||
union node;
|
union node;
|
||||||
void expandhere(union node *, int);
|
void expandhere(union node *, int);
|
||||||
void expandarg(union node *, struct arglist *, int);
|
void expandarg(union node *, struct arglist *, int);
|
||||||
|
void expari(int);
|
||||||
int patmatch(char *, char *, int);
|
int patmatch(char *, char *, int);
|
||||||
void rmescapes(char *);
|
void rmescapes(char *);
|
||||||
int casematch(union node *, char *);
|
int casematch(union node *, char *);
|
||||||
int wordexpcmd(int, char **);
|
|
||||||
|
|
||||||
/* From arith.y */
|
/* From arith.y */
|
||||||
int arith(char *);
|
intmax_t arith(const char *);
|
||||||
int arith_assign(char *, arith_t);
|
|
||||||
int expcmd(int , char **);
|
|
||||||
void arith_lex_reset(void);
|
void arith_lex_reset(void);
|
||||||
|
int yylex(void);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
|
|
||||||
*/
|
|
9
minix/commands/ash/funcs/cmv → bin/sh/funcs/cmv
Executable file → Normal file
9
minix/commands/ash/funcs/cmv → bin/sh/funcs/cmv
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,7 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/cmv,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# Conditional move--don't replace an existing file.
|
# Conditional move--don't replace an existing file.
|
||||||
|
|
||||||
|
@ -44,6 +48,3 @@ cmv() {
|
||||||
fi
|
fi
|
||||||
/bin/mv "$1" "$2"
|
/bin/mv "$1" "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/dirs → bin/sh/funcs/dirs
Executable file → Normal file
9
minix/commands/ash/funcs/dirs → bin/sh/funcs/dirs
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,7 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/dirs,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -68,6 +72,3 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/kill → bin/sh/funcs/kill
Executable file → Normal file
9
minix/commands/ash/funcs/kill → bin/sh/funcs/kill
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,7 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)kill 8.2 (Berkeley) 5/4/95
|
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/kill,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# Convert job names to process ids and then run /bin/kill.
|
# Convert job names to process ids and then run /bin/kill.
|
||||||
|
|
||||||
|
@ -44,6 +48,3 @@ kill() {
|
||||||
done
|
done
|
||||||
/bin/kill $args
|
/bin/kill $args
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/login → bin/sh/funcs/login
Executable file → Normal file
9
minix/commands/ash/funcs/login → bin/sh/funcs/login
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,10 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)login 8.2 (Berkeley) 5/4/95
|
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/login,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# replaces the login builtin in the BSD shell
|
# replaces the login builtin in the BSD shell
|
||||||
login () exec login "$@"
|
login () exec login "$@"
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/newgrp → bin/sh/funcs/newgrp
Executable file → Normal file
9
minix/commands/ash/funcs/newgrp → bin/sh/funcs/newgrp
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,9 +34,5 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/newgrp,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
newgrp() exec newgrp "$@"
|
newgrp() exec newgrp "$@"
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/popd → bin/sh/funcs/popd
Executable file → Normal file
9
minix/commands/ash/funcs/popd → bin/sh/funcs/popd
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,7 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)popd 8.2 (Berkeley) 5/4/95
|
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/popd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -68,6 +72,3 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/pushd → bin/sh/funcs/pushd
Executable file → Normal file
9
minix/commands/ash/funcs/pushd → bin/sh/funcs/pushd
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,7 +34,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/pushd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -68,6 +72,3 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
9
minix/commands/ash/funcs/suspend → bin/sh/funcs/suspend
Executable file → Normal file
9
minix/commands/ash/funcs/suspend → bin/sh/funcs/suspend
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -12,6 +13,10 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# 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
|
# 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
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -29,13 +34,9 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/funcs/suspend,v 1.7 2004/04/06 20:06:53 markm Exp $
|
|
||||||
|
|
||||||
suspend() {
|
suspend() {
|
||||||
local -
|
local -
|
||||||
set +j
|
set +j
|
||||||
kill -TSTP 0
|
kill -TSTP 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: histedit.c,v 1.45 2012/03/20 18:42:29 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,20 +32,17 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: histedit.c,v 1.45 2012/03/20 18:42:29 matt Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <limits.h>
|
#include <sys/param.h>
|
||||||
#ifndef NO_PATHS_H
|
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -54,14 +53,13 @@ __FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "builtins.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "builtins.h"
|
|
||||||
#if !defined(NO_HISTORY)
|
|
||||||
#include "myhistedit.h"
|
#include "myhistedit.h"
|
||||||
#include "complete.h"
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#ifndef SMALL
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
|
|
||||||
|
@ -71,11 +69,14 @@ __FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $
|
||||||
History *hist; /* history cookie */
|
History *hist; /* history cookie */
|
||||||
EditLine *el; /* editline cookie */
|
EditLine *el; /* editline cookie */
|
||||||
int displayhist;
|
int displayhist;
|
||||||
static FILE *el_in, *el_out, *el_err;
|
static FILE *el_in, *el_out;
|
||||||
|
unsigned char _el_fn_complete(EditLine *, int);
|
||||||
|
|
||||||
STATIC char *fc_replace(const char *, char *, char *);
|
STATIC const char *fc_replace(const char *, char *, char *);
|
||||||
STATIC int not_fcnumber(char *);
|
|
||||||
STATIC int str_to_event(char *, int);
|
#ifdef DEBUG
|
||||||
|
extern FILE *tracefile;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set history and editing status. Called whenever the status may
|
* Set history and editing status. Called whenever the status may
|
||||||
|
@ -84,10 +85,11 @@ STATIC int str_to_event(char *, int);
|
||||||
void
|
void
|
||||||
histedit(void)
|
histedit(void)
|
||||||
{
|
{
|
||||||
|
FILE *el_err;
|
||||||
|
|
||||||
#define editing (Eflag || Vflag)
|
#define editing (Eflag || Vflag)
|
||||||
|
|
||||||
if (iflag) {
|
if (iflag == 1) {
|
||||||
if (!hist) {
|
if (!hist) {
|
||||||
/*
|
/*
|
||||||
* turn history on
|
* turn history on
|
||||||
|
@ -105,20 +107,37 @@ histedit(void)
|
||||||
/*
|
/*
|
||||||
* turn editing on
|
* turn editing on
|
||||||
*/
|
*/
|
||||||
|
char *term, *shname;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (el_in == NULL)
|
if (el_in == NULL)
|
||||||
el_in = fdopen(0, "r");
|
el_in = fdopen(0, "r");
|
||||||
if (el_err == NULL)
|
|
||||||
el_err = fdopen(1, "w");
|
|
||||||
if (el_out == NULL)
|
if (el_out == NULL)
|
||||||
el_out = fdopen(2, "w");
|
el_out = fdopen(2, "w");
|
||||||
if (el_in == NULL || el_err == NULL || el_out == NULL)
|
if (el_in == NULL || el_out == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
el = el_init(arg0, el_in, el_out, el_err);
|
el_err = el_out;
|
||||||
|
#if DEBUG
|
||||||
|
if (tracefile)
|
||||||
|
el_err = tracefile;
|
||||||
|
#endif
|
||||||
|
term = lookupvar("TERM");
|
||||||
|
if (term)
|
||||||
|
setenv("TERM", term, 1);
|
||||||
|
else
|
||||||
|
unsetenv("TERM");
|
||||||
|
shname = arg0;
|
||||||
|
if (shname[0] == '-')
|
||||||
|
shname++;
|
||||||
|
el = el_init(shname, el_in, el_out, el_err);
|
||||||
if (el != NULL) {
|
if (el != NULL) {
|
||||||
if (hist)
|
if (hist)
|
||||||
el_set(el, EL_HIST, history, hist);
|
el_set(el, EL_HIST, history, hist);
|
||||||
el_set(el, EL_PROMPT, getprompt);
|
el_set(el, EL_PROMPT, getprompt);
|
||||||
|
el_set(el, EL_SIGNAL, 1);
|
||||||
|
el_set(el, EL_ADDFN, "rl-complete",
|
||||||
|
"ReadLine compatible completion function",
|
||||||
|
_el_fn_complete);
|
||||||
} else {
|
} else {
|
||||||
bad:
|
bad:
|
||||||
out2str("sh: can't initialize editing\n");
|
out2str("sh: can't initialize editing\n");
|
||||||
|
@ -131,27 +150,13 @@ bad:
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
if (el) {
|
if (el) {
|
||||||
|
el_source(el, NULL);
|
||||||
if (Vflag)
|
if (Vflag)
|
||||||
el_set(el, EL_EDITOR, "vi");
|
el_set(el, EL_EDITOR, "vi");
|
||||||
else if (Eflag)
|
else if (Eflag)
|
||||||
el_set(el, EL_EDITOR, "emacs");
|
el_set(el, EL_EDITOR, "emacs");
|
||||||
el_set(el, EL_ADDFN, "ed-do-complete",
|
el_set(el, EL_BIND, "^I",
|
||||||
"Complete Argument", complete);
|
tabcomplete ? "rl-complete" : "ed-insert", NULL);
|
||||||
el_set(el, EL_ADDFN, "ed-list-complete",
|
|
||||||
"List Argument Completions", complete_list);
|
|
||||||
el_set(el, EL_ADDFN, "ed-maybe-complete",
|
|
||||||
"Complete Argument Or List Completions",
|
|
||||||
complete_or_list);
|
|
||||||
el_set(el, EL_ADDFN, "ed-expand",
|
|
||||||
"Expand Completions", complete_expand);
|
|
||||||
el_set(el, EL_BIND, "^I", "ed-maybe-complete", NULL);
|
|
||||||
el_set(el, EL_BIND, "-a", "=", "ed-list-complete",
|
|
||||||
NULL);
|
|
||||||
el_set(el, EL_BIND, "-a", "\\\\", "ed-do-complete",
|
|
||||||
NULL);
|
|
||||||
el_set(el, EL_BIND, "-a", "*", "ed-expand",
|
|
||||||
NULL);
|
|
||||||
el_source(el, NULL);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
|
@ -169,8 +174,7 @@ bad:
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sethistsize(hs)
|
sethistsize(const char *hs)
|
||||||
const char *hs;
|
|
||||||
{
|
{
|
||||||
int histsize;
|
int histsize;
|
||||||
HistEvent he;
|
HistEvent he;
|
||||||
|
@ -180,40 +184,63 @@ sethistsize(hs)
|
||||||
(histsize = atoi(hs)) < 0)
|
(histsize = atoi(hs)) < 0)
|
||||||
histsize = 100;
|
histsize = 100;
|
||||||
history(hist, &he, H_SETSIZE, histsize);
|
history(hist, &he, H_SETSIZE, histsize);
|
||||||
|
history(hist, &he, H_SETUNIQUE, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setterm(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
inputrc(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
out2str("usage: inputrc file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (el != NULL) {
|
||||||
|
if (el_source(el, argv[1])) {
|
||||||
|
out2str("inputrc: failed\n");
|
||||||
|
return 1;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
out2str("sh: inputrc ignored, not editing\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This command is provided since POSIX decided to standardize
|
||||||
|
* the Korn shell fc command. Oh well...
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
histcmd(int argc, char **argv)
|
histcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
char *editor = NULL;
|
const char * volatile editor = NULL;
|
||||||
HistEvent he;
|
HistEvent he;
|
||||||
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
int lflg = 0;
|
||||||
|
volatile int nflg = 0, rflg = 0, sflg = 0;
|
||||||
int i, retval;
|
int i, retval;
|
||||||
char *firststr, *laststr;
|
const char *firststr, *laststr;
|
||||||
int first, last, direction;
|
int first, last, direction;
|
||||||
char *pat = NULL, *repl;
|
char *pat = NULL, *repl; /* ksh "fc old=new" crap */
|
||||||
static int active = 0;
|
static int active = 0;
|
||||||
struct jmploc jmploc;
|
struct jmploc jmploc;
|
||||||
struct jmploc *volatile savehandler;
|
struct jmploc *volatile savehandler;
|
||||||
char editfile[PATH_MAX];
|
char editfile[MAXPATHLEN + 1];
|
||||||
FILE *efp;
|
FILE *efp;
|
||||||
int oldhistnum;
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
/* Avoid longjmp clobbering */
|
repl = NULL; /* XXX gcc4 */
|
||||||
(void) &editor;
|
efp = NULL; /* XXX gcc4 */
|
||||||
(void) &lflg;
|
|
||||||
(void) &nflg;
|
|
||||||
(void) &rflg;
|
|
||||||
(void) &sflg;
|
|
||||||
(void) &firststr;
|
|
||||||
(void) &laststr;
|
|
||||||
(void) &pat;
|
|
||||||
(void) &repl;
|
|
||||||
(void) &efp;
|
|
||||||
(void) &argc;
|
|
||||||
(void) &argv;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hist == NULL)
|
if (hist == NULL)
|
||||||
|
@ -223,12 +250,11 @@ histcmd(int argc, char **argv)
|
||||||
error("missing history argument");
|
error("missing history argument");
|
||||||
|
|
||||||
optreset = 1; optind = 1; /* initialize getopt */
|
optreset = 1; optind = 1; /* initialize getopt */
|
||||||
opterr = 0;
|
|
||||||
while (not_fcnumber(argv[optind]) &&
|
while (not_fcnumber(argv[optind]) &&
|
||||||
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
||||||
switch ((char)ch) {
|
switch ((char)ch) {
|
||||||
case 'e':
|
case 'e':
|
||||||
editor = optarg;
|
editor = optionarg;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
lflg = 1;
|
lflg = 1;
|
||||||
|
@ -244,9 +270,11 @@ histcmd(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
error("option -%c expects argument", optopt);
|
error("option -%c expects argument", optopt);
|
||||||
|
/* NOTREACHED */
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
error("unknown option: -%c", optopt);
|
error("unknown option: -%c", optopt);
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
argc -= optind, argv += optind;
|
argc -= optind, argv += optind;
|
||||||
|
|
||||||
|
@ -260,6 +288,7 @@ histcmd(int argc, char **argv)
|
||||||
* Catch interrupts to reset active counter and
|
* Catch interrupts to reset active counter and
|
||||||
* cleanup temp files.
|
* cleanup temp files.
|
||||||
*/
|
*/
|
||||||
|
savehandler = handler;
|
||||||
if (setjmp(jmploc.loc)) {
|
if (setjmp(jmploc.loc)) {
|
||||||
active = 0;
|
active = 0;
|
||||||
if (*editfile)
|
if (*editfile)
|
||||||
|
@ -267,7 +296,6 @@ histcmd(int argc, char **argv)
|
||||||
handler = savehandler;
|
handler = savehandler;
|
||||||
longjmp(handler->loc, 1);
|
longjmp(handler->loc, 1);
|
||||||
}
|
}
|
||||||
savehandler = handler;
|
|
||||||
handler = &jmploc;
|
handler = &jmploc;
|
||||||
if (++active > MAXHISTLOOPS) {
|
if (++active > MAXHISTLOOPS) {
|
||||||
active = 0;
|
active = 0;
|
||||||
|
@ -298,6 +326,13 @@ histcmd(int argc, char **argv)
|
||||||
*repl++ = '\0';
|
*repl++ = '\0';
|
||||||
argc--, argv++;
|
argc--, argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If -s is specified, accept only one operand
|
||||||
|
*/
|
||||||
|
if (sflg && argc >= 2)
|
||||||
|
error("too many args");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* determine [first] and [last]
|
* determine [first] and [last]
|
||||||
*/
|
*/
|
||||||
|
@ -316,6 +351,7 @@ histcmd(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("too many args");
|
error("too many args");
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Turn into event numbers.
|
* Turn into event numbers.
|
||||||
|
@ -341,7 +377,7 @@ histcmd(int argc, char **argv)
|
||||||
if (editor) {
|
if (editor) {
|
||||||
int fd;
|
int fd;
|
||||||
INTOFF; /* easier */
|
INTOFF; /* easier */
|
||||||
sprintf(editfile, "%s/_shXXXXXX", _PATH_TMP);
|
snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
|
||||||
if ((fd = mkstemp(editfile)) < 0)
|
if ((fd = mkstemp(editfile)) < 0)
|
||||||
error("can't create temporary file %s", editfile);
|
error("can't create temporary file %s", editfile);
|
||||||
if ((efp = fdopen(fd, "w")) == NULL) {
|
if ((efp = fdopen(fd, "w")) == NULL) {
|
||||||
|
@ -366,34 +402,29 @@ histcmd(int argc, char **argv)
|
||||||
out1fmt("%5d ", he.num);
|
out1fmt("%5d ", he.num);
|
||||||
out1str(he.str);
|
out1str(he.str);
|
||||||
} else {
|
} else {
|
||||||
char *s = pat ?
|
const char *s = pat ?
|
||||||
fc_replace(he.str, pat, repl) : (char *)he.str;
|
fc_replace(he.str, pat, repl) : he.str;
|
||||||
|
|
||||||
if (sflg) {
|
if (sflg) {
|
||||||
if (displayhist) {
|
if (displayhist) {
|
||||||
out2str(s);
|
out2str(s);
|
||||||
}
|
}
|
||||||
evalstring(s);
|
|
||||||
|
evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
|
||||||
if (displayhist && hist) {
|
if (displayhist && hist) {
|
||||||
/*
|
/*
|
||||||
* XXX what about recursive and
|
* XXX what about recursive and
|
||||||
* relative histnums.
|
* relative histnums.
|
||||||
*/
|
*/
|
||||||
oldhistnum = he.num;
|
|
||||||
history(hist, &he, H_ENTER, s);
|
history(hist, &he, H_ENTER, s);
|
||||||
/*
|
|
||||||
* XXX H_ENTER moves the internal
|
|
||||||
* cursor, set it back to the current
|
|
||||||
* entry.
|
|
||||||
*/
|
|
||||||
retval = history(hist, &he,
|
|
||||||
H_NEXT_EVENT, oldhistnum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
} else
|
} else
|
||||||
fputs(s, efp);
|
fputs(s, efp);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* At end? (if we were to loose last, we'd sure be
|
* At end? (if we were to lose last, we'd sure be
|
||||||
* messed up).
|
* messed up).
|
||||||
*/
|
*/
|
||||||
if (he.num == last)
|
if (he.num == last)
|
||||||
|
@ -405,7 +436,7 @@ histcmd(int argc, char **argv)
|
||||||
fclose(efp);
|
fclose(efp);
|
||||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||||
sprintf(editcmd, "%s %s", editor, editfile);
|
sprintf(editcmd, "%s %s", editor, editfile);
|
||||||
evalstring(editcmd); /* XXX - should use no JC command */
|
evalstring(editcmd, 0); /* XXX - should use no JC command */
|
||||||
INTON;
|
INTON;
|
||||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||||
unlink(editfile);
|
unlink(editfile);
|
||||||
|
@ -418,7 +449,7 @@ histcmd(int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC char *
|
STATIC const char *
|
||||||
fc_replace(const char *s, char *p, char *r)
|
fc_replace(const char *s, char *p, char *r)
|
||||||
{
|
{
|
||||||
char *dest;
|
char *dest;
|
||||||
|
@ -440,21 +471,21 @@ fc_replace(const char *s, char *p, char *r)
|
||||||
return (dest);
|
return (dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
not_fcnumber(char *s)
|
not_fcnumber(char *s)
|
||||||
{
|
{
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return (0);
|
return 0;
|
||||||
if (*s == '-')
|
if (*s == '-')
|
||||||
s++;
|
s++;
|
||||||
return (!is_number(s));
|
return (!is_number(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
str_to_event(char *str, int last)
|
str_to_event(const char *str, int last)
|
||||||
{
|
{
|
||||||
HistEvent he;
|
HistEvent he;
|
||||||
char *s = str;
|
const char *s = str;
|
||||||
int relative = 0;
|
int relative = 0;
|
||||||
int i, retval;
|
int i, retval;
|
||||||
|
|
||||||
|
@ -481,7 +512,8 @@ str_to_event(char *str, int last)
|
||||||
* the notion of first and last is
|
* the notion of first and last is
|
||||||
* backwards to that of the history package
|
* backwards to that of the history package
|
||||||
*/
|
*/
|
||||||
retval = history(hist, &he, last ? H_FIRST : H_LAST);
|
retval = history(hist, &he,
|
||||||
|
last ? H_FIRST : H_LAST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (retval == -1)
|
if (retval == -1)
|
||||||
|
@ -497,37 +529,17 @@ str_to_event(char *str, int last)
|
||||||
}
|
}
|
||||||
return (he.num);
|
return (he.num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
bindcmd(int argc, char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (el == NULL)
|
|
||||||
error("line editing is disabled");
|
|
||||||
return (el_parse(el, argc, argv));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
int
|
int
|
||||||
histcmd(int argc, char **argv)
|
histcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
error("not compiled with history support");
|
error("not compiled with history support");
|
||||||
/*NOTREACHED*/
|
/* NOTREACHED */
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bindcmd(int argc, char **argv)
|
inputrc(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
error("not compiled with history support");
|
||||||
error("not compiled with line editing support");
|
/* NOTREACHED */
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
#endif /* !NO_HISTORY */
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: histedit.c,v 1.6 2006/04/10 14:52:58 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,13 +32,8 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/init.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void init(void);
|
void init(void);
|
||||||
void reset(void);
|
void reset(void);
|
||||||
void initshellproc(void);
|
void initshellproc(void);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,24 +32,22 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
#include <sys/cdefs.h>
|
|
||||||
/*
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h> /* defines BUFSIZ */
|
#include <stdio.h> /* defines BUFSIZ */
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file implements the input routines used by the parser.
|
* This file implements the input routines used by the parser.
|
||||||
|
@ -64,10 +64,6 @@ __FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include "alias.h"
|
#include "alias.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "myhistedit.h"
|
#include "myhistedit.h"
|
||||||
#include "redir.h"
|
|
||||||
#include "trap.h"
|
|
||||||
|
|
||||||
static void popstring(void);
|
|
||||||
|
|
||||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
||||||
|
|
||||||
|
@ -91,7 +87,7 @@ struct parsefile {
|
||||||
int linno; /* current line */
|
int linno; /* current line */
|
||||||
int fd; /* file descriptor (or -1 if string) */
|
int fd; /* file descriptor (or -1 if string) */
|
||||||
int nleft; /* number of chars left in this line */
|
int nleft; /* number of chars left in this line */
|
||||||
int lleft; /* number of lines left in this buffer */
|
int lleft; /* number of chars left in this buffer */
|
||||||
char *nextc; /* next char in buffer */
|
char *nextc; /* next char in buffer */
|
||||||
char *buf; /* input buffer */
|
char *buf; /* input buffer */
|
||||||
struct strpush *strpush; /* for pushing strings at this level */
|
struct strpush *strpush; /* for pushing strings at this level */
|
||||||
|
@ -100,27 +96,24 @@ struct parsefile {
|
||||||
|
|
||||||
|
|
||||||
int plinno = 1; /* input line number */
|
int plinno = 1; /* input line number */
|
||||||
MKINIT int parsenleft; /* copy of parsefile->nleft */
|
int parsenleft; /* copy of parsefile->nleft */
|
||||||
MKINIT int parselleft; /* copy of parsefile->lleft */
|
MKINIT int parselleft; /* copy of parsefile->lleft */
|
||||||
char *parsenextc; /* copy of parsefile->nextc */
|
char *parsenextc; /* copy of parsefile->nextc */
|
||||||
MKINIT struct parsefile basepf; /* top level input file */
|
MKINIT struct parsefile basepf; /* top level input file */
|
||||||
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||||
STATIC struct parsefile *parsefile = &basepf; /* current input file */
|
struct parsefile *parsefile = &basepf; /* current input file */
|
||||||
int init_editline = 0; /* editline library initialized? */
|
int init_editline = 0; /* editline library initialized? */
|
||||||
int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
|
int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||||
|
|
||||||
EditLine *el; /* cookie for editline package */
|
|
||||||
|
|
||||||
STATIC void pushfile(void);
|
STATIC void pushfile(void);
|
||||||
static int preadfd(void);
|
static int preadfd(void);
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
|
INCLUDE <stdio.h>
|
||||||
INCLUDE "input.h"
|
INCLUDE "input.h"
|
||||||
INCLUDE "error.h"
|
INCLUDE "error.h"
|
||||||
|
|
||||||
INIT {
|
INIT {
|
||||||
extern char basebuf[];
|
|
||||||
|
|
||||||
basepf.nextc = basepf.buf = basebuf;
|
basepf.nextc = basepf.buf = basebuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,35 +173,40 @@ static int
|
||||||
preadfd(void)
|
preadfd(void)
|
||||||
{
|
{
|
||||||
int nr;
|
int nr;
|
||||||
parsenextc = parsefile->buf;
|
char *buf = parsefile->buf;
|
||||||
|
parsenextc = buf;
|
||||||
|
|
||||||
#if !defined(NO_HISTORY)
|
|
||||||
if (el != NULL && gotwinch) {
|
|
||||||
gotwinch = 0;
|
|
||||||
el_resize(el);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
retry:
|
retry:
|
||||||
#ifndef NO_HISTORY
|
#ifndef SMALL
|
||||||
if (parsefile->fd == 0 && el) {
|
if (parsefile->fd == 0 && el) {
|
||||||
const char *rl_cp;
|
static const char *rl_cp;
|
||||||
|
static int el_len;
|
||||||
|
|
||||||
rl_cp = el_gets(el, &nr);
|
|
||||||
if (rl_cp == NULL)
|
if (rl_cp == NULL)
|
||||||
nr = 0;
|
rl_cp = el_gets(el, &el_len);
|
||||||
|
if (rl_cp == NULL)
|
||||||
|
nr = el_len == 0 ? 0 : -1;
|
||||||
else {
|
else {
|
||||||
/* XXX - BUFSIZE should redesign so not necessary */
|
nr = el_len;
|
||||||
(void) strcpy(parsenextc, rl_cp);
|
if (nr > BUFSIZ - 8)
|
||||||
|
nr = BUFSIZ - 8;
|
||||||
|
memcpy(buf, rl_cp, nr);
|
||||||
|
if (nr != el_len) {
|
||||||
|
el_len -= nr;
|
||||||
|
rl_cp += nr;
|
||||||
|
} else
|
||||||
|
rl_cp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
|
nr = read(parsefile->fd, buf, BUFSIZ - 8);
|
||||||
|
|
||||||
|
|
||||||
if (nr <= 0) {
|
if (nr <= 0) {
|
||||||
if (nr < 0) {
|
if (nr < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
goto retry;
|
goto retry;
|
||||||
#ifdef EWOULDBLOCK
|
|
||||||
if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
|
if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
|
||||||
int flags = fcntl(0, F_GETFL, 0);
|
int flags = fcntl(0, F_GETFL, 0);
|
||||||
if (flags >= 0 && flags & O_NONBLOCK) {
|
if (flags >= 0 && flags & O_NONBLOCK) {
|
||||||
|
@ -219,7 +217,6 @@ retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* EWOULDBLOCK */
|
|
||||||
}
|
}
|
||||||
nr = -1;
|
nr = -1;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +229,7 @@ retry:
|
||||||
* 1) If a string was pushed back on the input, pop it;
|
* 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
|
* 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.
|
* from a string so we can't refill the buffer, return EOF.
|
||||||
* 3) If there is more in this buffer, use it else call read to fill it.
|
* 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.
|
* 4) Process input up to the next newline, deleting nul characters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -241,7 +238,9 @@ preadbuffer(void)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int more;
|
int more;
|
||||||
|
#ifndef SMALL
|
||||||
int something;
|
int something;
|
||||||
|
#endif
|
||||||
char savec;
|
char savec;
|
||||||
|
|
||||||
if (parsefile->strpush) {
|
if (parsefile->strpush) {
|
||||||
|
@ -265,7 +264,9 @@ again:
|
||||||
q = p = parsenextc;
|
q = p = parsenextc;
|
||||||
|
|
||||||
/* delete nul characters */
|
/* delete nul characters */
|
||||||
|
#ifndef SMALL
|
||||||
something = 0;
|
something = 0;
|
||||||
|
#endif
|
||||||
for (more = 1; more;) {
|
for (more = 1; more;) {
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case '\0':
|
case '\0':
|
||||||
|
@ -282,7 +283,9 @@ again:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
#ifndef SMALL
|
||||||
something = 1;
|
something = 1;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,11 +303,11 @@ check:
|
||||||
savec = *q;
|
savec = *q;
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
|
|
||||||
#if !defined(NO_HISTORY)
|
#ifndef SMALL
|
||||||
if (parsefile->fd == 0 && hist && something) {
|
if (parsefile->fd == 0 && hist && something) {
|
||||||
HistEvent he;
|
HistEvent he;
|
||||||
INTOFF;
|
INTOFF;
|
||||||
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
|
history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
|
||||||
parsenextc);
|
parsenextc);
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +345,7 @@ pushstring(char *s, int len, void *ap)
|
||||||
struct strpush *sp;
|
struct strpush *sp;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
/*dbgprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
/*debugprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
||||||
if (parsefile->strpush) {
|
if (parsefile->strpush) {
|
||||||
sp = ckmalloc(sizeof (struct strpush));
|
sp = ckmalloc(sizeof (struct strpush));
|
||||||
sp->prev = parsefile->strpush;
|
sp->prev = parsefile->strpush;
|
||||||
|
@ -360,7 +363,7 @@ pushstring(char *s, int len, void *ap)
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
popstring(void)
|
popstring(void)
|
||||||
{
|
{
|
||||||
struct strpush *sp = parsefile->strpush;
|
struct strpush *sp = parsefile->strpush;
|
||||||
|
@ -369,7 +372,7 @@ popstring(void)
|
||||||
parsenextc = sp->prevstring;
|
parsenextc = sp->prevstring;
|
||||||
parsenleft = sp->prevnleft;
|
parsenleft = sp->prevnleft;
|
||||||
parselleft = sp->prevlleft;
|
parselleft = sp->prevlleft;
|
||||||
/*dbgprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
/*debugprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
||||||
if (sp->ap)
|
if (sp->ap)
|
||||||
sp->ap->flag &= ~ALIASINUSE;
|
sp->ap->flag &= ~ALIASINUSE;
|
||||||
parsefile->strpush = sp->prev;
|
parsefile->strpush = sp->prev;
|
||||||
|
@ -384,27 +387,32 @@ popstring(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setinputfile(char *fname, int push)
|
setinputfile(const char *fname, int push)
|
||||||
{
|
{
|
||||||
|
unsigned char magic[4];
|
||||||
int fd;
|
int fd;
|
||||||
int fd2;
|
int fd2;
|
||||||
struct stat statbuf;
|
|
||||||
int saved_errno;
|
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||||
error("Can't open %s: %s", fname, strerror(errno));
|
error("Can't open %s", fname);
|
||||||
if (fstat(fd, &statbuf) < 0) {
|
|
||||||
saved_errno = errno;
|
/* Since the message "Syntax error: "(" unexpected" is not very
|
||||||
close(fd);
|
* helpful, we check if the file starts with the ELF magic to
|
||||||
error("Can't stat %s: %s", fname, strerror(saved_errno));
|
* avoid that message. The first lseek tries to make sure that
|
||||||
}
|
* we can later rewind the file.
|
||||||
if (!S_ISREG(statbuf.st_mode)) {
|
*/
|
||||||
close(fd);
|
if (lseek(fd, 0, SEEK_SET) == 0) {
|
||||||
error("Can't open %s: %s", fname, strerror(ENOEXEC));
|
if (read(fd, magic, 4) == 4) {
|
||||||
|
if (memcmp(magic, "\177ELF", 4) == 0)
|
||||||
|
error("Cannot execute ELF binary %s", fname);
|
||||||
|
}
|
||||||
|
if (lseek(fd, 0, SEEK_SET) != 0)
|
||||||
|
error("Cannot rewind the file %s", fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd < 10) {
|
if (fd < 10) {
|
||||||
fd2 = fcntl(fd, F_DUPFD, 10);
|
fd2 = copyfd(fd, 10, 0);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (fd2 < 0)
|
if (fd2 < 0)
|
||||||
error("Out of file descriptors");
|
error("Out of file descriptors");
|
||||||
|
@ -423,7 +431,7 @@ setinputfile(char *fname, int push)
|
||||||
void
|
void
|
||||||
setinputfd(int fd, int push)
|
setinputfd(int fd, int push)
|
||||||
{
|
{
|
||||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
if (push) {
|
if (push) {
|
||||||
pushfile();
|
pushfile();
|
||||||
parsefile->buf = ckmalloc(BUFSIZ);
|
parsefile->buf = ckmalloc(BUFSIZ);
|
||||||
|
@ -518,18 +526,25 @@ popallfiles(void)
|
||||||
/*
|
/*
|
||||||
* Close the file(s) that the shell is reading commands from. Called
|
* Close the file(s) that the shell is reading commands from. Called
|
||||||
* after a fork is done.
|
* after a fork is done.
|
||||||
|
*
|
||||||
|
* Takes one arg, vfork, which tells it to not modify its global vars
|
||||||
|
* as it is still running in the parent.
|
||||||
|
*
|
||||||
|
* This code is (probably) unnecessary as the 'close on exec' flag is
|
||||||
|
* set and should be enough. In the vfork case it is definitely wrong
|
||||||
|
* to close the fds as another fork() may be done later to feed data
|
||||||
|
* from a 'here' document into a pipe and we don't want to close the
|
||||||
|
* pipe!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
closescript(void)
|
closescript(int vforked)
|
||||||
{
|
{
|
||||||
|
if (vforked)
|
||||||
|
return;
|
||||||
popallfiles();
|
popallfiles();
|
||||||
if (parsefile->fd > 0) {
|
if (parsefile->fd > 0) {
|
||||||
close(parsefile->fd);
|
close(parsefile->fd);
|
||||||
parsefile->fd = 0;
|
parsefile->fd = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: input.c,v 1.7 2006/05/29 13:09:38 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/input.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||||
|
@ -50,15 +51,12 @@ int pgetc(void);
|
||||||
int preadbuffer(void);
|
int preadbuffer(void);
|
||||||
void pungetc(void);
|
void pungetc(void);
|
||||||
void pushstring(char *, int, void *);
|
void pushstring(char *, int, void *);
|
||||||
void setinputfile(char *, int);
|
void popstring(void);
|
||||||
|
void setinputfile(const char *, int);
|
||||||
void setinputfd(int, int);
|
void setinputfd(int, int);
|
||||||
void setinputstring(char *, int);
|
void setinputstring(char *, int);
|
||||||
void popfile(void);
|
void popfile(void);
|
||||||
void popallfiles(void);
|
void popallfiles(void);
|
||||||
void closescript(void);
|
void closescript(int);
|
||||||
|
|
||||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
|
|
||||||
*/
|
|
1527
bin/sh/jobs.c
Normal file
1527
bin/sh/jobs.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: jobs.h,v 1.20 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,15 +32,24 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "output.h"
|
||||||
|
|
||||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||||
#define FORK_FG 0
|
#define FORK_FG 0
|
||||||
#define FORK_BG 1
|
#define FORK_BG 1
|
||||||
#define FORK_NOJOB 2
|
#define FORK_NOJOB 2
|
||||||
|
|
||||||
#include <signal.h> /* for sig_atomic_t */
|
/* mode flags for showjob(s) */
|
||||||
|
#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
|
||||||
|
#define SHOW_MULTILINE 0x02 /* one line per process */
|
||||||
|
#define SHOW_PID 0x04 /* include process pid */
|
||||||
|
#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
|
||||||
|
#define SHOW_SIGNALLED 0x10 /* only if stopped/exited on signal */
|
||||||
|
#define SHOW_ISSIG 0x20 /* job was signalled */
|
||||||
|
#define SHOW_NO_FREE 0x40 /* do not free job */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A job structure contains information about a job. A job is either a
|
* A job structure contains information about a job. A job is either a
|
||||||
|
@ -46,57 +57,45 @@
|
||||||
* latter case, pidlist will be non-NULL, and will point to a -1 terminated
|
* latter case, pidlist will be non-NULL, and will point to a -1 terminated
|
||||||
* array of pids.
|
* array of pids.
|
||||||
*/
|
*/
|
||||||
|
#define MAXCMDTEXT 200
|
||||||
|
|
||||||
struct procstat {
|
struct procstat {
|
||||||
pid_t pid; /* process id */
|
pid_t pid; /* process id */
|
||||||
int status; /* status flags (defined above) */
|
int status; /* last process status from wait() */
|
||||||
char *cmd; /* text of command being run */
|
char cmd[MAXCMDTEXT];/* text of command being run */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* states */
|
|
||||||
#define JOBSTOPPED 1 /* all procs are stopped */
|
|
||||||
#define JOBDONE 2 /* all procs are completed */
|
|
||||||
|
|
||||||
|
|
||||||
struct job {
|
struct job {
|
||||||
struct procstat ps0; /* status of process */
|
struct procstat ps0; /* status of process */
|
||||||
struct procstat *ps; /* status or processes when more than one */
|
struct procstat *ps; /* status or processes when more than one */
|
||||||
short nprocs; /* number of processes */
|
int nprocs; /* number of processes */
|
||||||
pid_t pgrp; /* process group of this job */
|
pid_t pgrp; /* process group of this job */
|
||||||
char state; /* true if job is finished */
|
char state;
|
||||||
char used; /* true if this entry is in used */
|
#define JOBRUNNING 0 /* at least one proc running */
|
||||||
char changed; /* true if status has changed */
|
#define JOBSTOPPED 1 /* all procs are stopped */
|
||||||
char foreground; /* true if running in the foreground */
|
#define JOBDONE 2 /* all procs are completed */
|
||||||
|
char used; /* true if this entry is in used */
|
||||||
|
char changed; /* true if status has changed */
|
||||||
#if JOBS
|
#if JOBS
|
||||||
char jobctl; /* job running under job control */
|
char jobctl; /* job running under job control */
|
||||||
struct job *next; /* job used after this one */
|
int prev_job; /* previous job index */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern pid_t backgndpid; /* pid of last background process */
|
extern pid_t backgndpid; /* pid of last background process */
|
||||||
extern int job_warning; /* user was warned about stopped jobs */
|
extern int job_warning; /* user was warned about stopped jobs */
|
||||||
extern int in_waitcmd; /* are we in waitcmd()? */
|
|
||||||
extern int in_dowait; /* are we in dowait()? */
|
|
||||||
extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
|
|
||||||
|
|
||||||
void setjobctl(int);
|
void setjobctl(int);
|
||||||
int fgcmd(int, char **);
|
void showjobs(struct output *, int);
|
||||||
int bgcmd(int, char **);
|
|
||||||
int jobscmd(int, char **);
|
|
||||||
void showjobs(int, int, int);
|
|
||||||
int waitcmd(int, char **);
|
|
||||||
int jobidcmd(int, char **);
|
|
||||||
struct job *makejob(union node *, int);
|
struct job *makejob(union node *, int);
|
||||||
pid_t forkshell(struct job *, union node *, int);
|
int forkshell(struct job *, union node *, int);
|
||||||
int waitforjob(struct job *, int *);
|
void forkchild(struct job *, union node *, int, int);
|
||||||
|
int forkparent(struct job *, union node *, int, pid_t);
|
||||||
|
int waitforjob(struct job *);
|
||||||
int stoppedjobs(void);
|
int stoppedjobs(void);
|
||||||
char *commandtext(union node *);
|
void commandtext(struct procstat *, union node *);
|
||||||
|
int getjobpgrp(const char *);
|
||||||
|
|
||||||
#if ! JOBS
|
#if ! JOBS
|
||||||
#define setjobctl(on) /* do nothing */
|
#define setjobctl(on) /* do nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,11 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* 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
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -41,15 +39,9 @@
|
||||||
* in some way. The following macro will get this right on many machines.
|
* in some way. The following macro will get this right on many machines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ALIGN
|
#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
|
||||||
union align {
|
|
||||||
int i;
|
|
||||||
char *cp;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
|
* It appears that grabstackstr() will barf with such alignments
|
||||||
|
* because stalloc() will return a string allocated in a new stackblock.
|
||||||
*/
|
*/
|
||||||
|
#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,19 +32,21 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to check for mail. (Perhaps make part of main.c?)
|
* Routines to check for mail. (Perhaps make part of main.c?)
|
||||||
*/
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "exec.h" /* defines padvance() */
|
#include "exec.h" /* defines padvance() */
|
||||||
|
@ -51,9 +55,6 @@ __FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXMBOXES 10
|
#define MAXMBOXES 10
|
||||||
|
@ -74,7 +75,7 @@ void
|
||||||
chkmail(int silent)
|
chkmail(int silent)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *mpath;
|
const char *mpath;
|
||||||
char *p;
|
char *p;
|
||||||
char *q;
|
char *q;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
|
@ -85,7 +86,7 @@ chkmail(int silent)
|
||||||
if (nmboxes == 0)
|
if (nmboxes == 0)
|
||||||
return;
|
return;
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
mpath = mpathset()? mpathval() : mailval();
|
mpath = mpathset() ? mpathval() : mailval();
|
||||||
for (i = 0 ; i < nmboxes ; i++) {
|
for (i = 0 ; i < nmboxes ; i++) {
|
||||||
p = padvance(&mpath, nullstr);
|
p = padvance(&mpath, nullstr);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
|
@ -100,7 +101,7 @@ chkmail(int silent)
|
||||||
if (stat(p, &statb) < 0)
|
if (stat(p, &statb) < 0)
|
||||||
statb.st_mtime = 0;
|
statb.st_mtime = 0;
|
||||||
if (statb.st_mtime > mailtime[i] && ! silent) {
|
if (statb.st_mtime > mailtime[i] && ! silent) {
|
||||||
out2str(pathopt? pathopt : "you have mail");
|
out2str(pathopt ? pathopt : "you have mail");
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
}
|
}
|
||||||
mailtime[i] = statb.st_mtime;
|
mailtime[i] = statb.st_mtime;
|
||||||
|
@ -108,7 +109,7 @@ chkmail(int silent)
|
||||||
if (stat(p, &statb) < 0)
|
if (stat(p, &statb) < 0)
|
||||||
statb.st_size = 0;
|
statb.st_size = 0;
|
||||||
if (statb.st_size > mailtime[i] && ! silent) {
|
if (statb.st_size > mailtime[i] && ! silent) {
|
||||||
out2str(pathopt? pathopt : "you have mail");
|
out2str(pathopt ? pathopt : "you have mail");
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
}
|
}
|
||||||
mailtime[i] = statb.st_size;
|
mailtime[i] = statb.st_size;
|
||||||
|
@ -117,7 +118,3 @@ chkmail(int silent)
|
||||||
nmboxes = i;
|
nmboxes = i;
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: mail.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,11 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/mail.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void chkmail(int);
|
void chkmail(int);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: main.c,v 1.57 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,34 +32,35 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char const copyright[] =
|
__COPYRIGHT("@(#) Copyright (c) 1991, 1993\
|
||||||
"@(#) Copyright (c) 1991, 1993\n\
|
The Regents of the University of California. All rights reserved.");
|
||||||
The Regents of the University of California. All rights reserved.\n";
|
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
|
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: main.c,v 1.57 2011/06/18 21:18:46 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <stdlib.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <errno.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "builtins.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
|
@ -74,13 +77,20 @@ __FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "cd.h"
|
#include "cd.h"
|
||||||
#include "builtins.h"
|
|
||||||
|
#define PROFILE 0
|
||||||
|
|
||||||
int rootpid;
|
int rootpid;
|
||||||
int rootshell;
|
int rootshell;
|
||||||
|
int posix;
|
||||||
|
#if PROFILE
|
||||||
|
short profile_buf[16384];
|
||||||
|
extern int etext();
|
||||||
|
#endif
|
||||||
|
|
||||||
STATIC void read_profile(char *);
|
STATIC void read_profile(const char *);
|
||||||
STATIC char *find_dot_file(char *);
|
STATIC char *find_dot_file(char *);
|
||||||
|
int main(int, char **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main routine. We initialize things, parse the arguments, execute
|
* Main routine. We initialize things, parse the arguments, execute
|
||||||
|
@ -91,14 +101,19 @@ STATIC char *find_dot_file(char *);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct jmploc jmploc;
|
struct jmploc jmploc;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
volatile int state;
|
volatile int state;
|
||||||
char *shinit;
|
char *shinit;
|
||||||
|
|
||||||
(void) setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
posix = getenv("POSIXLY_CORRECT") != NULL;
|
||||||
|
#if PROFILE
|
||||||
|
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
||||||
|
#endif
|
||||||
state = 0;
|
state = 0;
|
||||||
if (setjmp(jmploc.loc)) {
|
if (setjmp(jmploc.loc)) {
|
||||||
/*
|
/*
|
||||||
|
@ -127,11 +142,15 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exception != EXSHELLPROC) {
|
if (exception != EXSHELLPROC) {
|
||||||
if (state == 0 || iflag == 0 || ! rootshell)
|
if (state == 0 || iflag == 0 || ! rootshell)
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
}
|
}
|
||||||
reset();
|
reset();
|
||||||
if (exception == EXINT) {
|
if (exception == EXINT
|
||||||
|
#if ATTY
|
||||||
|
&& (! attyset() || equal(termval(), "emacs"))
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
flushout(&errout);
|
flushout(&errout);
|
||||||
}
|
}
|
||||||
|
@ -147,30 +166,30 @@ main(int argc, char *argv[])
|
||||||
goto state4;
|
goto state4;
|
||||||
}
|
}
|
||||||
handler = &jmploc;
|
handler = &jmploc;
|
||||||
#if DEBUG
|
#ifdef DEBUG
|
||||||
|
#if DEBUG == 2
|
||||||
|
debug = 1;
|
||||||
|
#endif
|
||||||
opentrace();
|
opentrace();
|
||||||
trputs("Shell args: "); trargs(argv);
|
trputs("Shell args: "); trargs(argv);
|
||||||
#endif
|
#endif
|
||||||
rootpid = getpid();
|
rootpid = getpid();
|
||||||
rootshell = 1;
|
rootshell = 1;
|
||||||
init();
|
init();
|
||||||
|
initpwd();
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
procargs(argc, argv);
|
procargs(argc, argv);
|
||||||
if (getpwd() == NULL && iflag)
|
|
||||||
out2str("sh: cannot determine working directory\n");
|
|
||||||
if (argv[0] && argv[0][0] == '-') {
|
if (argv[0] && argv[0][0] == '-') {
|
||||||
state = 1;
|
state = 1;
|
||||||
read_profile("/etc/profile");
|
read_profile("/etc/profile");
|
||||||
state1:
|
state1:
|
||||||
state = 2;
|
state = 2;
|
||||||
if (privileged == 0)
|
read_profile(".profile");
|
||||||
read_profile(".profile");
|
|
||||||
else
|
|
||||||
read_profile("/etc/suid_profile");
|
|
||||||
}
|
}
|
||||||
state2:
|
state2:
|
||||||
state = 3;
|
state = 3;
|
||||||
if (!privileged && iflag) {
|
if ((iflag || !posix) &&
|
||||||
|
getuid() == geteuid() && getgid() == getegid()) {
|
||||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||||
state = 3;
|
state = 3;
|
||||||
read_profile(shinit);
|
read_profile(shinit);
|
||||||
|
@ -178,16 +197,33 @@ state2:
|
||||||
}
|
}
|
||||||
state3:
|
state3:
|
||||||
state = 4;
|
state = 4;
|
||||||
if (minusc) {
|
if (sflag == 0 || minusc) {
|
||||||
evalstring(minusc);
|
static int sigs[] = {
|
||||||
|
SIGINT, SIGQUIT, SIGHUP,
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
SIGTSTP,
|
||||||
|
#endif
|
||||||
|
SIGPIPE
|
||||||
|
};
|
||||||
|
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < SIGSSIZE; i++)
|
||||||
|
setsignal(sigs[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minusc)
|
||||||
|
evalstring(minusc, 0);
|
||||||
|
|
||||||
if (sflag || minusc == NULL) {
|
if (sflag || minusc == NULL) {
|
||||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||||
cmdloop(1);
|
cmdloop(1);
|
||||||
}
|
}
|
||||||
|
#if PROFILE
|
||||||
|
monitor(0);
|
||||||
|
#endif
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
/*NOTREACHED*/
|
/* NOTREACHED */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,11 +246,11 @@ cmdloop(int top)
|
||||||
if (pendingsigs)
|
if (pendingsigs)
|
||||||
dotrap();
|
dotrap();
|
||||||
inter = 0;
|
inter = 0;
|
||||||
if (iflag && top) {
|
if (iflag == 1 && top) {
|
||||||
inter++;
|
inter = 1;
|
||||||
showjobs(1, 0, 0);
|
showjobs(out2, SHOW_CHANGED);
|
||||||
chkmail(0);
|
chkmail(0);
|
||||||
flushout(&output);
|
flushout(&errout);
|
||||||
}
|
}
|
||||||
n = parsecmd(inter);
|
n = parsecmd(inter);
|
||||||
/* showtree(n); DEBUG */
|
/* showtree(n); DEBUG */
|
||||||
|
@ -249,9 +285,11 @@ cmdloop(int top)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
read_profile(char *name)
|
read_profile(const char *name)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
int xflag_set = 0;
|
||||||
|
int vflag_set = 0;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||||
|
@ -259,7 +297,20 @@ read_profile(char *name)
|
||||||
INTON;
|
INTON;
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
|
/* -q turns off -x and -v just when executing init files */
|
||||||
|
if (qflag) {
|
||||||
|
if (xflag)
|
||||||
|
xflag = 0, xflag_set = 1;
|
||||||
|
if (vflag)
|
||||||
|
vflag = 0, vflag_set = 1;
|
||||||
|
}
|
||||||
cmdloop(0);
|
cmdloop(0);
|
||||||
|
if (qflag) {
|
||||||
|
if (xflag_set)
|
||||||
|
xflag = 1;
|
||||||
|
if (vflag_set)
|
||||||
|
vflag = 1;
|
||||||
|
}
|
||||||
popfile();
|
popfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +329,7 @@ readcmdfile(char *name)
|
||||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||||
setinputfd(fd, 1);
|
setinputfd(fd, 1);
|
||||||
else
|
else
|
||||||
error("Can't open %s: %s", name, strerror(errno));
|
error("Can't open %s", name);
|
||||||
INTON;
|
INTON;
|
||||||
cmdloop(0);
|
cmdloop(0);
|
||||||
popfile();
|
popfile();
|
||||||
|
@ -295,40 +346,46 @@ readcmdfile(char *name)
|
||||||
STATIC char *
|
STATIC char *
|
||||||
find_dot_file(char *basename)
|
find_dot_file(char *basename)
|
||||||
{
|
{
|
||||||
static char localname[FILENAME_MAX+1];
|
|
||||||
char *fullname;
|
char *fullname;
|
||||||
char *path = pathval();
|
const char *path = pathval();
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
|
|
||||||
/* don't try this for absolute or relative paths */
|
/* don't try this for absolute or relative paths */
|
||||||
if( strchr(basename, '/'))
|
if (strchr(basename, '/'))
|
||||||
return basename;
|
return basename;
|
||||||
|
|
||||||
while ((fullname = padvance(&path, basename)) != NULL) {
|
while ((fullname = padvance(&path, basename)) != NULL) {
|
||||||
strcpy(localname, fullname);
|
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
|
||||||
|
/*
|
||||||
|
* Don't bother freeing here, since it will
|
||||||
|
* be freed by the caller.
|
||||||
|
*/
|
||||||
|
return fullname;
|
||||||
|
}
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
|
|
||||||
return localname;
|
|
||||||
}
|
}
|
||||||
return basename;
|
|
||||||
|
/* not found in the PATH */
|
||||||
|
error("%s: not found", basename);
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dotcmd(int argc, char **argv)
|
dotcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct strlist *sp;
|
|
||||||
exitstatus = 0;
|
exitstatus = 0;
|
||||||
|
|
||||||
for (sp = cmdenviron; sp ; sp = sp->next)
|
|
||||||
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
|
|
||||||
|
|
||||||
if (argc >= 2) { /* That's what SVR2 does */
|
if (argc >= 2) { /* That's what SVR2 does */
|
||||||
char *fullname = find_dot_file(argv[1]);
|
char *fullname;
|
||||||
|
struct stackmark smark;
|
||||||
|
|
||||||
|
setstackmark(&smark);
|
||||||
|
fullname = find_dot_file(argv[1]);
|
||||||
setinputfile(fullname, 1);
|
setinputfile(fullname, 1);
|
||||||
commandname = fullname;
|
commandname = fullname;
|
||||||
cmdloop(0);
|
cmdloop(0);
|
||||||
popfile();
|
popfile();
|
||||||
|
popstackmark(&smark);
|
||||||
}
|
}
|
||||||
return exitstatus;
|
return exitstatus;
|
||||||
}
|
}
|
||||||
|
@ -337,19 +394,10 @@ dotcmd(int argc, char **argv)
|
||||||
int
|
int
|
||||||
exitcmd(int argc, char **argv)
|
exitcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
extern int oexitstatus;
|
|
||||||
|
|
||||||
if (stoppedjobs())
|
if (stoppedjobs())
|
||||||
return 0;
|
return 0;
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
exitstatus = number(argv[1]);
|
exitstatus = number(argv[1]);
|
||||||
else
|
|
||||||
exitstatus = oexitstatus;
|
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
/*NOTREACHED*/
|
/* NOTREACHED */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: main.c,v 1.5 2006/05/22 12:03:02 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: main.h,v 1.11 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/main.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int rootpid; /* pid of main shell */
|
extern int rootpid; /* pid of main shell */
|
||||||
|
@ -38,9 +39,3 @@ extern int rootshell; /* true if we aren't a child of the main shell */
|
||||||
|
|
||||||
void readcmdfile(char *);
|
void readcmdfile(char *);
|
||||||
void cmdloop(int);
|
void cmdloop(int);
|
||||||
int dotcmd(int, char **);
|
|
||||||
int exitcmd(int, char **);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: memalloc.c,v 1.29 2008/02/15 17:26:06 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,36 +32,36 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: memalloc.c,v 1.29 2008/02/15 17:26:06 matt Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
#include <stdlib.h>
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/memalloc.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
#include <unistd.h>
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "machdep.h"
|
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "machdep.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "expand.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like malloc, but returns an error when out of space.
|
* Like malloc, but returns an error when out of space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pointer
|
pointer
|
||||||
ckmalloc(int nbytes)
|
ckmalloc(size_t nbytes)
|
||||||
{
|
{
|
||||||
pointer p;
|
pointer p;
|
||||||
|
|
||||||
if ((p = malloc(nbytes)) == NULL)
|
p = malloc(nbytes);
|
||||||
|
if (p == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,8 @@ ckmalloc(int nbytes)
|
||||||
pointer
|
pointer
|
||||||
ckrealloc(pointer p, int nbytes)
|
ckrealloc(pointer p, int nbytes)
|
||||||
{
|
{
|
||||||
if ((p = realloc(p, nbytes)) == NULL)
|
p = realloc(p, nbytes);
|
||||||
|
if (p == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -98,56 +101,46 @@ savestr(const char *s)
|
||||||
* to make this more efficient, and also to avoid all sorts of exception
|
* to make this more efficient, and also to avoid all sorts of exception
|
||||||
* handling code to handle interrupts in the middle of a parse.
|
* handling code to handle interrupts in the middle of a parse.
|
||||||
*
|
*
|
||||||
* The size 496 was chosen because with 16-byte alignment the total size
|
* The size 504 was chosen because the Ultrix malloc handles that size
|
||||||
* for the allocated block is 512.
|
* well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MINSIZE 496 /* minimum size of a block. */
|
#define MINSIZE 504 /* minimum size of a block */
|
||||||
|
|
||||||
|
|
||||||
struct stack_block {
|
struct stack_block {
|
||||||
struct stack_block *prev;
|
struct stack_block *prev;
|
||||||
/* Data follows */
|
char space[MINSIZE];
|
||||||
};
|
};
|
||||||
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
|
|
||||||
|
|
||||||
STATIC struct stack_block *stackp;
|
struct stack_block stackbase;
|
||||||
STATIC struct stackmark *markp;
|
struct stack_block *stackp = &stackbase;
|
||||||
char *stacknxt;
|
struct stackmark *markp;
|
||||||
int stacknleft;
|
char *stacknxt = stackbase.space;
|
||||||
|
int stacknleft = MINSIZE;
|
||||||
int sstrnleft;
|
int sstrnleft;
|
||||||
int herefd = -1;
|
int herefd = -1;
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
stnewblock(int nbytes)
|
|
||||||
{
|
|
||||||
struct stack_block *sp;
|
|
||||||
int allocsize;
|
|
||||||
|
|
||||||
if (nbytes < MINSIZE)
|
|
||||||
nbytes = MINSIZE;
|
|
||||||
|
|
||||||
allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes);
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
sp = ckmalloc(allocsize);
|
|
||||||
sp->prev = stackp;
|
|
||||||
stacknxt = SPACE(sp);
|
|
||||||
stacknleft = allocsize - (stacknxt - (char*)sp);
|
|
||||||
stackp = sp;
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pointer
|
pointer
|
||||||
stalloc(int nbytes)
|
stalloc(int nbytes)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
nbytes = ALIGN(nbytes);
|
nbytes = SHELL_ALIGN(nbytes);
|
||||||
if (nbytes > stacknleft)
|
if (nbytes > stacknleft) {
|
||||||
stnewblock(nbytes);
|
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;
|
p = stacknxt;
|
||||||
stacknxt += nbytes;
|
stacknxt += nbytes;
|
||||||
stacknleft -= nbytes;
|
stacknleft -= nbytes;
|
||||||
|
@ -159,7 +152,7 @@ void
|
||||||
stunalloc(pointer p)
|
stunalloc(pointer p)
|
||||||
{
|
{
|
||||||
if (p == NULL) { /*DEBUG */
|
if (p == NULL) { /*DEBUG */
|
||||||
write(STDERR_FILENO, "stunalloc\n", 10);
|
write(2, "stunalloc\n", 10);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
stacknleft += stacknxt - (char *)p;
|
stacknleft += stacknxt - (char *)p;
|
||||||
|
@ -210,32 +203,27 @@ popstackmark(struct stackmark *mark)
|
||||||
void
|
void
|
||||||
growstackblock(void)
|
growstackblock(void)
|
||||||
{
|
{
|
||||||
char *p;
|
int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
|
||||||
int newlen;
|
|
||||||
char *oldspace;
|
|
||||||
int oldlen;
|
|
||||||
struct stack_block *sp;
|
|
||||||
struct stack_block *oldstackp;
|
|
||||||
struct stackmark *xmark;
|
|
||||||
|
|
||||||
newlen = (stacknleft == 0) ? MINSIZE : stacknleft * 2 + 100;
|
if (stacknxt == stackp->space && stackp != &stackbase) {
|
||||||
newlen = ALIGN(newlen);
|
struct stack_block *oldstackp;
|
||||||
oldspace = stacknxt;
|
struct stackmark *xmark;
|
||||||
oldlen = stacknleft;
|
struct stack_block *sp;
|
||||||
|
|
||||||
if (stackp != NULL && stacknxt == SPACE(stackp)) {
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
oldstackp = stackp;
|
oldstackp = stackp;
|
||||||
stackp = oldstackp->prev;
|
sp = stackp;
|
||||||
sp = ckrealloc((pointer)oldstackp, newlen);
|
stackp = sp->prev;
|
||||||
|
sp = ckrealloc((pointer)sp,
|
||||||
|
sizeof(struct stack_block) - MINSIZE + newlen);
|
||||||
sp->prev = stackp;
|
sp->prev = stackp;
|
||||||
stackp = sp;
|
stackp = sp;
|
||||||
stacknxt = SPACE(sp);
|
stacknxt = sp->space;
|
||||||
stacknleft = newlen - (stacknxt - (char*)sp);
|
stacknleft = newlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stack marks pointing to the start of the old block
|
* Stack marks pointing to the start of the old block
|
||||||
* must be relocated to point to the new block
|
* must be relocated to point to the new block
|
||||||
*/
|
*/
|
||||||
xmark = markp;
|
xmark = markp;
|
||||||
while (xmark != NULL && xmark->stackp == oldstackp) {
|
while (xmark != NULL && xmark->stackp == oldstackp) {
|
||||||
|
@ -246,27 +234,26 @@ growstackblock(void)
|
||||||
}
|
}
|
||||||
INTON;
|
INTON;
|
||||||
} else {
|
} else {
|
||||||
p = stalloc(newlen);
|
char *oldspace = stacknxt;
|
||||||
if (oldlen != 0)
|
int oldlen = stacknleft;
|
||||||
memcpy(p, oldspace, oldlen);
|
char *p = stalloc(newlen);
|
||||||
stunalloc(p);
|
|
||||||
|
(void)memcpy(p, oldspace, oldlen);
|
||||||
|
stacknxt = p; /* free the space */
|
||||||
|
stacknleft += newlen; /* we just allocated */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grabstackblock(int len)
|
grabstackblock(int len)
|
||||||
{
|
{
|
||||||
len = ALIGN(len);
|
len = SHELL_ALIGN(len);
|
||||||
stacknxt += len;
|
stacknxt += len;
|
||||||
stacknleft -= len;
|
stacknleft -= len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following routines are somewhat easier to use that the above.
|
* The following routines are somewhat easier to use than the above.
|
||||||
* The user declares a variable of type STACKSTR, which may be declared
|
* The user declares a variable of type STACKSTR, which may be declared
|
||||||
* to be a register. The macro STARTSTACKSTR initializes things. Then
|
* to be a register. The macro STARTSTACKSTR initializes things. Then
|
||||||
* the user uses the macro STPUTC to add characters to the string. In
|
* the user uses the macro STPUTC to add characters to the string. In
|
||||||
|
@ -283,13 +270,10 @@ grabstackblock(int len)
|
||||||
* is space for at least one character.
|
* is space for at least one character.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
growstackstr(void)
|
growstackstr(void)
|
||||||
{
|
{
|
||||||
int len;
|
int len = stackblocksize();
|
||||||
|
|
||||||
len = stackblocksize();
|
|
||||||
if (herefd >= 0 && len >= 1024) {
|
if (herefd >= 0 && len >= 1024) {
|
||||||
xwrite(herefd, stackblock(), len);
|
xwrite(herefd, stackblock(), len);
|
||||||
sstrnleft = len - 1;
|
sstrnleft = len - 1;
|
||||||
|
@ -300,7 +284,6 @@ growstackstr(void)
|
||||||
return stackblock() + len;
|
return stackblock() + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called from CHECKSTRSPACE.
|
* Called from CHECKSTRSPACE.
|
||||||
*/
|
*/
|
||||||
|
@ -308,24 +291,17 @@ growstackstr(void)
|
||||||
char *
|
char *
|
||||||
makestrspace(void)
|
makestrspace(void)
|
||||||
{
|
{
|
||||||
int len;
|
int len = stackblocksize() - sstrnleft;
|
||||||
|
|
||||||
len = stackblocksize() - sstrnleft;
|
|
||||||
growstackblock();
|
growstackblock();
|
||||||
sstrnleft = stackblocksize() - len;
|
sstrnleft = stackblocksize() - len;
|
||||||
return stackblock() + len;
|
return stackblock() + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ungrabstackstr(char *s, char *p)
|
ungrabstackstr(char *s, char *p)
|
||||||
{
|
{
|
||||||
stacknleft += stacknxt - s;
|
stacknleft += stacknxt - s;
|
||||||
stacknxt = s;
|
stacknxt = s;
|
||||||
sstrnleft = stacknleft - (p - s);
|
sstrnleft = stacknleft - (p - s);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
}
|
||||||
* $PchId: memalloc.c,v 1.5 2006/05/22 12:03:26 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: memalloc.h,v 1.15 2008/02/15 17:26:06 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,14 +32,13 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/memalloc.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct stackmark {
|
struct stackmark {
|
||||||
struct stack_block *stackp;
|
struct stack_block *stackp;
|
||||||
char *stacknxt;
|
char *stacknxt;
|
||||||
int stacknleft;
|
int stacknleft;
|
||||||
struct stackmark *marknext;
|
struct stackmark *marknext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ extern int stacknleft;
|
||||||
extern int sstrnleft;
|
extern int sstrnleft;
|
||||||
extern int herefd;
|
extern int herefd;
|
||||||
|
|
||||||
pointer ckmalloc(int);
|
pointer ckmalloc(size_t);
|
||||||
pointer ckrealloc(pointer, int);
|
pointer ckrealloc(pointer, int);
|
||||||
char *savestr(const char *);
|
char *savestr(const char *);
|
||||||
pointer stalloc(int);
|
pointer stalloc(int);
|
||||||
|
@ -74,7 +75,3 @@ void ungrabstackstr(char *, char *);
|
||||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||||
|
|
||||||
#define ckfree(p) free((pointer)(p))
|
#define ckfree(p) free((pointer)(p))
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: miscbltin.c,v 1.42 2012/06/11 18:28:10 njoly Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,32 +32,28 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: miscbltin.c,v 1.42 2012/06/11 18:28:10 njoly Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
#include <sys/cdefs.h>
|
|
||||||
/*
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Miscellaneous builtins.
|
* Miscelaneous builtins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h> /* quad_t */
|
||||||
|
#include <sys/param.h> /* BSD4_4 */
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/select.h>
|
#include <sys/resource.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <termios.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
@ -63,159 +61,148 @@ __FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
#include "mystring.h"
|
||||||
|
|
||||||
|
#undef rflag
|
||||||
|
|
||||||
|
|
||||||
#undef eflag
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The read builtin. The -r option causes backslashes to be treated like
|
* The read builtin.
|
||||||
* ordinary characters.
|
* Backslahes escape the next char unless -r is specified.
|
||||||
*
|
*
|
||||||
* This uses unbuffered input, which may be avoidable in some cases.
|
* This uses unbuffered input, which may be avoidable in some cases.
|
||||||
|
*
|
||||||
|
* Note that if IFS=' :' then read x y should work so that:
|
||||||
|
* 'a b' x='a', y='b'
|
||||||
|
* ' a b ' x='a', y='b'
|
||||||
|
* ':b' x='', y='b'
|
||||||
|
* ':' x='', y=''
|
||||||
|
* '::' x='', y=''
|
||||||
|
* ': :' x='', y=''
|
||||||
|
* ':::' x='', y='::'
|
||||||
|
* ':b c:' x='', y='b c:'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
readcmd(int argc __unused, char **argv __unused)
|
readcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
int backslash;
|
|
||||||
char c;
|
char c;
|
||||||
int rflag;
|
int rflag;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
char *ifs;
|
const char *ifs;
|
||||||
char *p;
|
char *p;
|
||||||
int startword;
|
int startword;
|
||||||
int status;
|
int status;
|
||||||
int i;
|
int i;
|
||||||
struct timeval tv;
|
int is_ifs;
|
||||||
char *tvptr;
|
int saveall = 0;
|
||||||
#ifndef __minix
|
|
||||||
fd_set ifds;
|
|
||||||
struct termios told, tnew;
|
|
||||||
int tsaved;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rflag = 0;
|
rflag = 0;
|
||||||
prompt = NULL;
|
prompt = NULL;
|
||||||
tv.tv_sec = -1;
|
while ((i = nextopt("p:r")) != '\0') {
|
||||||
tv.tv_usec = 0;
|
if (i == 'p')
|
||||||
while ((i = nextopt("erp:t:")) != '\0') {
|
prompt = optionarg;
|
||||||
switch(i) {
|
else
|
||||||
case 'p':
|
|
||||||
prompt = shoptarg;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
rflag = 1;
|
rflag = 1;
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
tv.tv_sec = strtol(shoptarg, &tvptr, 0);
|
|
||||||
if (tvptr == shoptarg)
|
|
||||||
error("timeout value");
|
|
||||||
switch(*tvptr) {
|
|
||||||
case 0:
|
|
||||||
case 's':
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
tv.tv_sec *= 60;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case 'm':
|
|
||||||
tv.tv_sec *= 60;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error("timeout unit");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prompt && isatty(0)) {
|
if (prompt && isatty(0)) {
|
||||||
out2str(prompt);
|
out2str(prompt);
|
||||||
flushall();
|
flushall();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*(ap = argptr) == NULL)
|
if (*(ap = argptr) == NULL)
|
||||||
error("arg count");
|
error("arg count");
|
||||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
|
||||||
ifs = nullstr;
|
|
||||||
|
|
||||||
if (tv.tv_sec >= 0) {
|
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||||
#ifdef __minix
|
ifs = " \t\n";
|
||||||
abort();
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* See if we can disable input processing; this will
|
|
||||||
* not give the desired result if we are in a pipeline
|
|
||||||
* and someone upstream is still in line-by-line mode.
|
|
||||||
*/
|
|
||||||
tsaved = 0;
|
|
||||||
if (tcgetattr(0, &told) == 0) {
|
|
||||||
memcpy(&tnew, &told, sizeof(told));
|
|
||||||
cfmakeraw(&tnew);
|
|
||||||
tcsetattr(0, TCSANOW, &tnew);
|
|
||||||
tsaved = 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Wait for something to become available.
|
|
||||||
*/
|
|
||||||
FD_ZERO(&ifds);
|
|
||||||
FD_SET(0, &ifds);
|
|
||||||
status = select(1, &ifds, NULL, NULL, &tv);
|
|
||||||
if (tsaved)
|
|
||||||
tcsetattr(0, TCSANOW, &told);
|
|
||||||
/*
|
|
||||||
* If there's nothing ready, return an error.
|
|
||||||
*/
|
|
||||||
if (status <= 0)
|
|
||||||
return(1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
startword = 1;
|
startword = 2;
|
||||||
backslash = 0;
|
|
||||||
STARTSTACKSTR(p);
|
STARTSTACKSTR(p);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
if (read(0, &c, 1) != 1) {
|
||||||
status = 1;
|
status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
continue;
|
continue;
|
||||||
if (backslash) {
|
if (c == '\\' && !rflag) {
|
||||||
backslash = 0;
|
if (read(0, &c, 1) != 1) {
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (c != '\n')
|
if (c != '\n')
|
||||||
STPUTC(c, p);
|
STPUTC(c, p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!rflag && c == '\\') {
|
|
||||||
backslash++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
break;
|
break;
|
||||||
if (startword && *ifs == ' ' && strchr(ifs, c)) {
|
if (strchr(ifs, c))
|
||||||
|
is_ifs = strchr(" \t\n", c) ? 1 : 2;
|
||||||
|
else
|
||||||
|
is_ifs = 0;
|
||||||
|
|
||||||
|
if (startword != 0) {
|
||||||
|
if (is_ifs == 1) {
|
||||||
|
/* Ignore leading IFS whitespace */
|
||||||
|
if (saveall)
|
||||||
|
STPUTC(c, p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_ifs == 2 && startword == 1) {
|
||||||
|
/* Only one non-whitespace IFS per word */
|
||||||
|
startword = 2;
|
||||||
|
if (saveall)
|
||||||
|
STPUTC(c, p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_ifs == 0) {
|
||||||
|
/* append this character to the current variable */
|
||||||
|
startword = 0;
|
||||||
|
if (saveall)
|
||||||
|
/* Not just a spare terminator */
|
||||||
|
saveall++;
|
||||||
|
STPUTC(c, p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
startword = 0;
|
|
||||||
if (backslash && c == '\\') {
|
/* end of variable... */
|
||||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
startword = is_ifs;
|
||||||
status = 1;
|
|
||||||
break;
|
if (ap[1] == NULL) {
|
||||||
}
|
/* Last variable needs all IFS chars */
|
||||||
STPUTC(c, p);
|
saveall++;
|
||||||
} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
|
|
||||||
STACKSTRNUL(p);
|
|
||||||
setvar(*ap, stackblock(), 0);
|
|
||||||
ap++;
|
|
||||||
startword = 1;
|
|
||||||
STARTSTACKSTR(p);
|
|
||||||
} else {
|
|
||||||
STPUTC(c, p);
|
STPUTC(c, p);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STACKSTRNUL(p);
|
||||||
|
setvar(*ap, stackblock(), 0);
|
||||||
|
ap++;
|
||||||
|
STARTSTACKSTR(p);
|
||||||
}
|
}
|
||||||
STACKSTRNUL(p);
|
STACKSTRNUL(p);
|
||||||
|
|
||||||
|
/* Remove trailing IFS chars */
|
||||||
|
for (; stackblock() <= --p; *p = 0) {
|
||||||
|
if (!strchr(ifs, *p))
|
||||||
|
break;
|
||||||
|
if (strchr(" \t\n", *p))
|
||||||
|
/* Always remove whitespace */
|
||||||
|
continue;
|
||||||
|
if (saveall > 1)
|
||||||
|
/* Don't remove non-whitespace unless it was naked */
|
||||||
|
break;
|
||||||
|
}
|
||||||
setvar(*ap, stackblock(), 0);
|
setvar(*ap, stackblock(), 0);
|
||||||
|
|
||||||
|
/* Set any remaining args to "" */
|
||||||
while (*++ap != NULL)
|
while (*++ap != NULL)
|
||||||
setvar(*ap, nullstr, 0);
|
setvar(*ap, nullstr, 0);
|
||||||
return status;
|
return status;
|
||||||
|
@ -224,7 +211,7 @@ readcmd(int argc __unused, char **argv __unused)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
umaskcmd(int argc __unused, char **argv)
|
umaskcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *ap;
|
char *ap;
|
||||||
int mask;
|
int mask;
|
||||||
|
@ -276,7 +263,7 @@ umaskcmd(int argc __unused, char **argv)
|
||||||
out1fmt("%.4o\n", mask);
|
out1fmt("%.4o\n", mask);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isdigit(*ap)) {
|
if (isdigit((unsigned char)*ap)) {
|
||||||
mask = 0;
|
mask = 0;
|
||||||
do {
|
do {
|
||||||
if (*ap >= '8' || *ap < '0')
|
if (*ap >= '8' || *ap < '0')
|
||||||
|
@ -286,44 +273,23 @@ umaskcmd(int argc __unused, char **argv)
|
||||||
umask(mask);
|
umask(mask);
|
||||||
} else {
|
} else {
|
||||||
void *set;
|
void *set;
|
||||||
if ((set = setmode (ap)) == 0)
|
|
||||||
error("Illegal number: %s", ap);
|
|
||||||
|
|
||||||
mask = getmode (set, ~mask & 0777);
|
INTOFF;
|
||||||
|
if ((set = setmode(ap)) != 0) {
|
||||||
|
mask = getmode(set, ~mask & 0777);
|
||||||
|
ckfree(set);
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
if (!set)
|
||||||
|
error("Cannot set mode `%s' (%s)", ap,
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
umask(~mask & 0777);
|
umask(~mask & 0777);
|
||||||
free(set);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __minix
|
|
||||||
struct rlimit
|
|
||||||
{
|
|
||||||
unsigned long rlim_cur; /* current (soft) limit */
|
|
||||||
unsigned long rlim_max; /* maximum value for rlim_cur */
|
|
||||||
};
|
|
||||||
#define RLIM_INFINITY (((unsigned long)1 << 31) - 1)
|
|
||||||
|
|
||||||
int getrlimit (int, struct rlimit *);
|
|
||||||
int setrlimit (int, const struct rlimit *);
|
|
||||||
|
|
||||||
int getrlimit(resource, rlp)
|
|
||||||
int resource;
|
|
||||||
struct rlimit *rlp;
|
|
||||||
{
|
|
||||||
errno= ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int setrlimit(resource, rlp)
|
|
||||||
int resource;
|
|
||||||
const struct rlimit *rlp;
|
|
||||||
{
|
|
||||||
errno= ENOSYS;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ulimit builtin
|
* ulimit builtin
|
||||||
*
|
*
|
||||||
|
@ -336,7 +302,7 @@ const struct rlimit *rlp;
|
||||||
|
|
||||||
struct limits {
|
struct limits {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *units;
|
const char *unit;
|
||||||
int cmd;
|
int cmd;
|
||||||
int factor; /* multiply by to get rlim_{cur,max} values */
|
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||||
char option;
|
char option;
|
||||||
|
@ -344,49 +310,52 @@ struct limits {
|
||||||
|
|
||||||
static const struct limits limits[] = {
|
static const struct limits limits[] = {
|
||||||
#ifdef RLIMIT_CPU
|
#ifdef RLIMIT_CPU
|
||||||
{ "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
|
{ "time", "seconds", RLIMIT_CPU, 1, 't' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_FSIZE
|
#ifdef RLIMIT_FSIZE
|
||||||
{ "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
|
{ "file", "blocks", RLIMIT_FSIZE, 512, 'f' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_DATA
|
#ifdef RLIMIT_DATA
|
||||||
{ "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
|
{ "data", "kbytes", RLIMIT_DATA, 1024, 'd' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_STACK
|
#ifdef RLIMIT_STACK
|
||||||
{ "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
|
{ "stack", "kbytes", RLIMIT_STACK, 1024, 's' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_CORE
|
#ifdef RLIMIT_CORE
|
||||||
{ "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
|
{ "coredump", "blocks", RLIMIT_CORE, 512, 'c' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_RSS
|
#ifdef RLIMIT_RSS
|
||||||
{ "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
|
{ "memory", "kbytes", RLIMIT_RSS, 1024, 'm' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_MEMLOCK
|
#ifdef RLIMIT_MEMLOCK
|
||||||
{ "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
|
{ "locked memory","kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_NTHR
|
||||||
|
{ "thread", "threads", RLIMIT_NTHR, 1, 'r' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_NPROC
|
#ifdef RLIMIT_NPROC
|
||||||
{ "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
|
{ "process", "processes", RLIMIT_NPROC, 1, 'p' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_NOFILE
|
#ifdef RLIMIT_NOFILE
|
||||||
{ "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
|
{ "nofiles", "descriptors", RLIMIT_NOFILE, 1, 'n' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_VMEM
|
#ifdef RLIMIT_VMEM
|
||||||
{ "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
|
{ "vmemory", "kbytes", RLIMIT_VMEM, 1024, 'v' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_SWAP
|
#ifdef RLIMIT_SWAP
|
||||||
{ "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
|
{ "swap", "kbytes", RLIMIT_SWAP, 1024, 'w' },
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_SBSIZE
|
#ifdef RLIMIT_SBSIZE
|
||||||
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
|
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
|
||||||
#endif
|
#endif
|
||||||
{ (char *) 0, (char *)0, 0, 0, '\0' }
|
{ NULL, NULL, 0, 0, '\0' }
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
ulimitcmd(int argc __unused, char **argv __unused)
|
ulimitcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
intmax_t val = 0;
|
rlim_t val = 0;
|
||||||
enum { SOFT = 0x1, HARD = 0x2 }
|
enum { SOFT = 0x1, HARD = 0x2 }
|
||||||
how = SOFT | HARD;
|
how = SOFT | HARD;
|
||||||
const struct limits *l;
|
const struct limits *l;
|
||||||
|
@ -395,7 +364,7 @@ ulimitcmd(int argc __unused, char **argv __unused)
|
||||||
struct rlimit limit;
|
struct rlimit limit;
|
||||||
|
|
||||||
what = 'f';
|
what = 'f';
|
||||||
while ((optc = nextopt("HSatfdsmcnuvlb")) != '\0')
|
while ((optc = nextopt("HSabtfdscmlrpnv")) != '\0')
|
||||||
switch (optc) {
|
switch (optc) {
|
||||||
case 'H':
|
case 'H':
|
||||||
how = HARD;
|
how = HARD;
|
||||||
|
@ -424,56 +393,48 @@ ulimitcmd(int argc __unused, char **argv __unused)
|
||||||
if (strcmp(p, "unlimited") == 0)
|
if (strcmp(p, "unlimited") == 0)
|
||||||
val = RLIM_INFINITY;
|
val = RLIM_INFINITY;
|
||||||
else {
|
else {
|
||||||
val = 0;
|
val = (rlim_t) 0;
|
||||||
|
|
||||||
while ((c = *p++) >= '0' && c <= '9')
|
while ((c = *p++) >= '0' && c <= '9')
|
||||||
{
|
|
||||||
val = (val * 10) + (long)(c - '0');
|
val = (val * 10) + (long)(c - '0');
|
||||||
if (val < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c)
|
if (c)
|
||||||
error("bad number");
|
error("bad number");
|
||||||
val *= l->factor;
|
val *= l->factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (all) {
|
if (all) {
|
||||||
for (l = limits; l->name; l++) {
|
for (l = limits; l->name; l++) {
|
||||||
char optbuf[40];
|
getrlimit(l->cmd, &limit);
|
||||||
if (getrlimit(l->cmd, &limit) < 0)
|
|
||||||
error("can't get limit: %s", strerror(errno));
|
|
||||||
if (how & SOFT)
|
if (how & SOFT)
|
||||||
val = limit.rlim_cur;
|
val = limit.rlim_cur;
|
||||||
else if (how & HARD)
|
else if (how & HARD)
|
||||||
val = limit.rlim_max;
|
val = limit.rlim_max;
|
||||||
|
|
||||||
if (l->units)
|
out1fmt("%-13s (-%c %-11s) ", l->name, l->option,
|
||||||
snprintf(optbuf, sizeof(optbuf),
|
l->unit);
|
||||||
"(%s, -%c) ", l->units, l->option);
|
|
||||||
else
|
|
||||||
snprintf(optbuf, sizeof(optbuf),
|
|
||||||
"(-%c) ", l->option);
|
|
||||||
out1fmt("%-18s %18s ", l->name, optbuf);
|
|
||||||
if (val == RLIM_INFINITY)
|
if (val == RLIM_INFINITY)
|
||||||
out1fmt("unlimited\n");
|
out1fmt("unlimited\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val /= l->factor;
|
val /= l->factor;
|
||||||
out1fmt("%jd\n", (intmax_t)val);
|
#ifdef BSD4_4
|
||||||
|
out1fmt("%lld\n", (long long) val);
|
||||||
|
#else
|
||||||
|
out1fmt("%ld\n", (long) val);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getrlimit(l->cmd, &limit) < 0)
|
getrlimit(l->cmd, &limit);
|
||||||
error("can't get limit: %s", strerror(errno));
|
|
||||||
if (set) {
|
if (set) {
|
||||||
if (how & SOFT)
|
|
||||||
limit.rlim_cur = val;
|
|
||||||
if (how & HARD)
|
if (how & HARD)
|
||||||
limit.rlim_max = val;
|
limit.rlim_max = val;
|
||||||
|
if (how & SOFT)
|
||||||
|
limit.rlim_cur = val;
|
||||||
if (setrlimit(l->cmd, &limit) < 0)
|
if (setrlimit(l->cmd, &limit) < 0)
|
||||||
error("bad limit: %s", strerror(errno));
|
error("error setting limit (%s)", strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
if (how & SOFT)
|
if (how & SOFT)
|
||||||
val = limit.rlim_cur;
|
val = limit.rlim_cur;
|
||||||
|
@ -485,12 +446,12 @@ ulimitcmd(int argc __unused, char **argv __unused)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val /= l->factor;
|
val /= l->factor;
|
||||||
out1fmt("%jd\n", (intmax_t)val);
|
#ifdef BSD4_4
|
||||||
|
out1fmt("%lld\n", (long long) val);
|
||||||
|
#else
|
||||||
|
out1fmt("%ld\n", (long) val);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: miscbltin.c,v 1.7 2006/05/23 11:59:08 philip Exp $
|
|
||||||
*/
|
|
31
bin/sh/miscbltin.h
Normal file
31
bin/sh/miscbltin.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* $NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 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. 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(int, char **);
|
||||||
|
int umaskcmd(int, char **);
|
||||||
|
int ulimitcmd(int, char **);
|
128
minix/commands/ash/mkbuiltins.sh → bin/sh/mkbuiltins
Executable file → Normal file
128
minix/commands/ash/mkbuiltins.sh → bin/sh/mkbuiltins
Executable file → Normal file
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
|
# $NetBSD: mkbuiltins,v 1.22 2009/10/06 19:56:58 apb Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 3. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
|
@ -31,68 +32,105 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/mkbuiltins,v 1.13 2004/04/06 20:06:51 markm Exp $
|
|
||||||
|
|
||||||
#temp=`/usr/bin/mktemp -t ka`
|
|
||||||
temp=/tmp/mkb$$
|
|
||||||
havehist=1
|
havehist=1
|
||||||
if [ "X$1" = "X-h" ]; then
|
if [ x"$1" = x"-h" ]; then
|
||||||
havehist=0
|
havehist=0
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
shell=$1
|
||||||
|
builtins=$2
|
||||||
|
objdir=$3
|
||||||
|
|
||||||
havejobs=0
|
havejobs=0
|
||||||
if [ "X$1" = "X-j" ]; then
|
if grep '^#define JOBS[ ]*1' ${shell} > /dev/null
|
||||||
havejobs=0
|
then
|
||||||
shift
|
havejobs=1
|
||||||
elif grep '^#define[ ]*JOBS[ ]*1' $2 > /dev/null
|
|
||||||
then havejobs=1
|
|
||||||
fi
|
fi
|
||||||
objdir=$1
|
|
||||||
exec > ${objdir}/builtins.c
|
exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
|
||||||
cat <<\!
|
|
||||||
/*
|
echo '/*
|
||||||
* This file was generated by the mkbuiltins program.
|
* This file was generated by the mkbuiltins program.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
|
||||||
!
|
const struct builtincmd builtincmd[] = {
|
||||||
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
|
' >&3
|
||||||
print $0}' $3 | sed 's/-[hj]//' > $temp
|
|
||||||
#awk '{ printf "int %s();\n", $1}' $temp
|
|
||||||
echo '
|
|
||||||
int (*const builtinfunc[]) (int, char **) = {'
|
|
||||||
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
|
|
||||||
echo '};
|
|
||||||
|
|
||||||
const struct builtincmd builtincmd[] = {'
|
echo '/*
|
||||||
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.
|
* 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 {
|
struct builtincmd {
|
||||||
char *name;
|
const char *name;
|
||||||
int code;
|
int (*builtin)(int, char **);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int (*const builtinfunc[]) (int, char **);
|
extern const struct builtincmd builtincmd[];
|
||||||
extern const struct builtincmd builtincmd[];'
|
extern const struct builtincmd splbltincmd[];
|
||||||
awk '{ printf "int %s (int, char **);\n", $1 }' < $temp
|
|
||||||
rm -f $temp
|
|
||||||
|
|
||||||
#
|
' >&4
|
||||||
# $PchId: mkbuiltins,v 1.6 2006/05/22 12:42:58 philip Exp $
|
|
||||||
|
specials=
|
||||||
|
|
||||||
|
while read line
|
||||||
|
do
|
||||||
|
set -- $line
|
||||||
|
[ -z "$1" ] && continue
|
||||||
|
case "$1" in
|
||||||
|
\#if*|\#def*|\#end*)
|
||||||
|
echo $line >&3
|
||||||
|
echo $line >&4
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
\#*)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
func=$1
|
||||||
|
shift
|
||||||
|
[ x"$1" = x'-j' ] && {
|
||||||
|
[ $havejobs = 0 ] && continue
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
[ x"$1" = x'-h' ] && {
|
||||||
|
[ $havehist = 0 ] && continue
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
echo 'int '"$func"'(int, char **);' >&4
|
||||||
|
while
|
||||||
|
[ $# != 0 ] && [ x"$1" != x'#' ]
|
||||||
|
do
|
||||||
|
[ x"$1" = x'-s' ] && {
|
||||||
|
specials="$specials $2 $func"
|
||||||
|
shift 2
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[ x"$1" = x'-u' ] && shift
|
||||||
|
echo ' { "'$1'", '"$func"' },' >&3
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ' { 0, 0 },' >&3
|
||||||
|
echo '};' >&3
|
||||||
|
echo >&3
|
||||||
|
echo 'const struct builtincmd splbltincmd[] = {' >&3
|
||||||
|
|
||||||
|
set -- $specials
|
||||||
|
while
|
||||||
|
[ $# != 0 ]
|
||||||
|
do
|
||||||
|
echo ' { "'$1'", '"$2"' },' >&3
|
||||||
|
shift 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ' { 0, 0 },' >&3
|
||||||
|
echo "};" >&3
|
170
bin/sh/mkinit.sh
Executable file
170
bin/sh/mkinit.sh
Executable file
|
@ -0,0 +1,170 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# $NetBSD: mkinit.sh,v 1.5 2008/10/23 20:21:57 apb Exp $
|
||||||
|
|
||||||
|
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
# by David Laight.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||||
|
|
||||||
|
srcs="$*"
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
openparen='('
|
||||||
|
backslash='\'
|
||||||
|
|
||||||
|
includes=' "shell.h" "mystring.h" "init.h" '
|
||||||
|
defines=
|
||||||
|
decles=
|
||||||
|
event_init=
|
||||||
|
event_reset=
|
||||||
|
event_shellproc=
|
||||||
|
|
||||||
|
for src in $srcs; do
|
||||||
|
exec <$src
|
||||||
|
decnl="$nl"
|
||||||
|
while IFS=; read -r line; do
|
||||||
|
[ "$line" = x ]
|
||||||
|
case "$line " in
|
||||||
|
INIT["{ "]* ) event=init;;
|
||||||
|
RESET["{ "]* ) event=reset;;
|
||||||
|
SHELLPROC["{ "]* ) event=shellproc;;
|
||||||
|
INCLUDE[\ \ ]* )
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
# ignore duplicates
|
||||||
|
[ "${includes}" != "${includes%* $2 }" ] && continue
|
||||||
|
includes="$includes$2 "
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
MKINIT\ )
|
||||||
|
# struct declaration
|
||||||
|
decles="$decles$nl"
|
||||||
|
while
|
||||||
|
read -r line
|
||||||
|
decles="${decles}${line}${nl}"
|
||||||
|
[ "$line" != "};" ]
|
||||||
|
do
|
||||||
|
:
|
||||||
|
done
|
||||||
|
decnl="$nl"
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
MKINIT["{ "]* )
|
||||||
|
# strip initialiser
|
||||||
|
def=${line#MKINIT}
|
||||||
|
comment="${def#*;}"
|
||||||
|
def="${def%;$comment}"
|
||||||
|
def="${def%%=*}"
|
||||||
|
def="${def% }"
|
||||||
|
decles="${decles}${decnl}extern${def};${comment}${nl}"
|
||||||
|
decnl=
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
\#define[\ \ ]* )
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
# Ignore those with arguments
|
||||||
|
[ "$2" = "${2##*$openparen}" ] || continue
|
||||||
|
# and multiline definitions
|
||||||
|
[ "$line" = "${line%$backslash}" ] || continue
|
||||||
|
defines="${defines}#undef $2${nl}${line}${nl}"
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
* ) continue;;
|
||||||
|
esac
|
||||||
|
# code for events
|
||||||
|
ev="${nl} /* from $src: */${nl} {${nl}"
|
||||||
|
# Indent the text by an extra <tab>
|
||||||
|
while
|
||||||
|
read -r line
|
||||||
|
[ "$line" != "}" ]
|
||||||
|
do
|
||||||
|
[ -n "$line" -a "$line" = "${line###}" ] &&
|
||||||
|
line=" $line"
|
||||||
|
ev="${ev}${line}${nl}"
|
||||||
|
done
|
||||||
|
ev="${ev} }${nl}"
|
||||||
|
eval event_$event=\"\$event_$event\$ev\"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
exec >init.c.tmp
|
||||||
|
|
||||||
|
echo "/*"
|
||||||
|
echo " * This file was generated by the mkinit program."
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
|
||||||
|
IFS=' '
|
||||||
|
for f in $includes; do
|
||||||
|
echo "#include $f"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "$defines"
|
||||||
|
echo
|
||||||
|
echo "$decles"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "/*"
|
||||||
|
echo " * Initialization code."
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
echo "void"
|
||||||
|
echo "init(void)"
|
||||||
|
echo "{"
|
||||||
|
echo "${event_init}"
|
||||||
|
echo "}"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "/*"
|
||||||
|
echo " * This routine is called when an error or an interrupt occurs in an"
|
||||||
|
echo " * interactive shell and control is returned to the main command loop."
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
echo "void"
|
||||||
|
echo "reset(void)"
|
||||||
|
echo "{"
|
||||||
|
echo "${event_reset}"
|
||||||
|
echo "}"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "/*"
|
||||||
|
echo " * This routine is called to initialize the shell to run a shell procedure."
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
echo "void"
|
||||||
|
echo "initshellproc(void)"
|
||||||
|
echo "{"
|
||||||
|
echo "${event_shellproc}"
|
||||||
|
echo "}"
|
||||||
|
|
||||||
|
exec >&-
|
||||||
|
mv init.c.tmp init.c
|
214
bin/sh/mknodes.sh
Executable file
214
bin/sh/mknodes.sh
Executable file
|
@ -0,0 +1,214 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# $NetBSD: mknodes.sh,v 1.2 2008/04/29 06:53:00 martin Exp $
|
||||||
|
|
||||||
|
# Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
# by David Laight.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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=$1
|
||||||
|
nodes_pat=$2
|
||||||
|
objdir="$3"
|
||||||
|
|
||||||
|
exec <$nodetypes
|
||||||
|
exec >$objdir/nodes.h.tmp
|
||||||
|
|
||||||
|
echo "/*"
|
||||||
|
echo " * This file was generated by mknodes.sh"
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
|
||||||
|
tagno=0
|
||||||
|
while IFS=; read -r line; do
|
||||||
|
line="${line%%#*}"
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
IFS=
|
||||||
|
[ -z "$2" ] && continue
|
||||||
|
case "$line" in
|
||||||
|
[" "]* )
|
||||||
|
IFS=' '
|
||||||
|
[ $field = 0 ] && struct_list="$struct_list $struct"
|
||||||
|
eval field_${struct}_$field=\"\$*\"
|
||||||
|
eval numfld_$struct=\$field
|
||||||
|
field=$(($field + 1))
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
define=$1
|
||||||
|
struct=$2
|
||||||
|
echo "#define $define $tagno"
|
||||||
|
tagno=$(($tagno + 1))
|
||||||
|
eval define_$struct=\"\$define_$struct \$define\"
|
||||||
|
struct_define="$struct_define $struct"
|
||||||
|
field=0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
IFS=' '
|
||||||
|
for struct in $struct_list; do
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "struct $struct {"
|
||||||
|
field=0
|
||||||
|
while
|
||||||
|
eval line=\"\$field_${struct}_$field\"
|
||||||
|
field=$(($field + 1))
|
||||||
|
[ -n "$line" ]
|
||||||
|
do
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
name=$1
|
||||||
|
case $2 in
|
||||||
|
nodeptr ) type="union node *";;
|
||||||
|
nodelist ) type="struct nodelist *";;
|
||||||
|
string ) type="char *";;
|
||||||
|
int ) type="int ";;
|
||||||
|
* ) name=; shift 2; type="$*";;
|
||||||
|
esac
|
||||||
|
echo " $type$name;"
|
||||||
|
done
|
||||||
|
echo "};"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "union node {"
|
||||||
|
echo " int type;"
|
||||||
|
for struct in $struct_list; do
|
||||||
|
echo " struct $struct $struct;"
|
||||||
|
done
|
||||||
|
echo "};"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "struct nodelist {"
|
||||||
|
echo " struct nodelist *next;"
|
||||||
|
echo " union node *n;"
|
||||||
|
echo "};"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "union node *copyfunc(union node *);"
|
||||||
|
echo "void freefunc(union node *);"
|
||||||
|
|
||||||
|
mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
|
||||||
|
|
||||||
|
exec <$nodes_pat
|
||||||
|
exec >$objdir/nodes.c.tmp
|
||||||
|
|
||||||
|
echo "/*"
|
||||||
|
echo " * This file was generated by mknodes.sh"
|
||||||
|
echo " */"
|
||||||
|
echo
|
||||||
|
|
||||||
|
while IFS=; read -r line; do
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
IFS=
|
||||||
|
case "$1" in
|
||||||
|
'%SIZES' )
|
||||||
|
echo "static const short nodesize[$tagno] = {"
|
||||||
|
IFS=' '
|
||||||
|
for struct in $struct_define; do
|
||||||
|
echo " SHELL_ALIGN(sizeof (struct $struct)),"
|
||||||
|
done
|
||||||
|
echo "};"
|
||||||
|
;;
|
||||||
|
'%CALCSIZE' )
|
||||||
|
echo " if (n == NULL)"
|
||||||
|
echo " return;"
|
||||||
|
echo " funcblocksize += nodesize[n->type];"
|
||||||
|
echo " switch (n->type) {"
|
||||||
|
IFS=' '
|
||||||
|
for struct in $struct_list; do
|
||||||
|
eval defines=\"\$define_$struct\"
|
||||||
|
for define in $defines; do
|
||||||
|
echo " case $define:"
|
||||||
|
done
|
||||||
|
eval field=\$numfld_$struct
|
||||||
|
while
|
||||||
|
[ $field != 0 ]
|
||||||
|
do
|
||||||
|
eval line=\"\$field_${struct}_$field\"
|
||||||
|
field=$(($field - 1))
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
name=$1
|
||||||
|
cl=")"
|
||||||
|
case $2 in
|
||||||
|
nodeptr ) fn=calcsize;;
|
||||||
|
nodelist ) fn=sizenodelist;;
|
||||||
|
string ) fn="funcstringsize += strlen"
|
||||||
|
cl=") + 1";;
|
||||||
|
* ) continue;;
|
||||||
|
esac
|
||||||
|
echo " ${fn}(n->$struct.$name${cl};"
|
||||||
|
done
|
||||||
|
echo " break;"
|
||||||
|
done
|
||||||
|
echo " };"
|
||||||
|
;;
|
||||||
|
'%COPY' )
|
||||||
|
echo " if (n == NULL)"
|
||||||
|
echo " return NULL;"
|
||||||
|
echo " new = funcblock;"
|
||||||
|
echo " funcblock = (char *) funcblock + nodesize[n->type];"
|
||||||
|
echo " switch (n->type) {"
|
||||||
|
IFS=' '
|
||||||
|
for struct in $struct_list; do
|
||||||
|
eval defines=\"\$define_$struct\"
|
||||||
|
for define in $defines; do
|
||||||
|
echo " case $define:"
|
||||||
|
done
|
||||||
|
eval field=\$numfld_$struct
|
||||||
|
while
|
||||||
|
[ $field != 0 ]
|
||||||
|
do
|
||||||
|
eval line=\"\$field_${struct}_$field\"
|
||||||
|
field=$(($field - 1))
|
||||||
|
IFS=' '
|
||||||
|
set -- $line
|
||||||
|
name=$1
|
||||||
|
case $2 in
|
||||||
|
nodeptr ) fn="copynode(";;
|
||||||
|
nodelist ) fn="copynodelist(";;
|
||||||
|
string ) fn="nodesavestr(";;
|
||||||
|
int ) fn=;;
|
||||||
|
* ) continue;;
|
||||||
|
esac
|
||||||
|
f="$struct.$name"
|
||||||
|
echo " new->$f = ${fn}n->$f${fn:+)};"
|
||||||
|
done
|
||||||
|
echo " break;"
|
||||||
|
done
|
||||||
|
echo " };"
|
||||||
|
echo " new->type = n->type;"
|
||||||
|
;;
|
||||||
|
* ) echo "$line";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
|
59
minix/commands/ash/mktokens.sh → bin/sh/mktokens
Executable file → Normal file
59
minix/commands/ash/mktokens.sh → bin/sh/mktokens
Executable file → Normal file
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
|
# $NetBSD: mktokens,v 1.12 2008/10/25 22:18:15 apb Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 3. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
|
@ -31,17 +32,15 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||||
# $FreeBSD: src/bin/sh/mktokens,v 1.9 2004/04/06 20:06:51 markm Exp $
|
|
||||||
|
|
||||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
: ${AWK:=awk}
|
||||||
|
: ${SED:=sed}
|
||||||
|
|
||||||
# The following is a list of tokens. The second column is nonzero if the
|
# 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
|
# token marks the end of a list. The third column is the name to print in
|
||||||
# error messages.
|
# error messages.
|
||||||
|
|
||||||
#temp=`/usr/bin/mktemp -t ka`
|
cat > /tmp/ka$$ <<\!
|
||||||
temp=/tmp/mkt$$
|
|
||||||
cat > $temp <<\!
|
|
||||||
TEOF 1 end of file
|
TEOF 1 end of file
|
||||||
TNL 0 newline
|
TNL 0 newline
|
||||||
TSEMI 0 ";"
|
TSEMI 0 ";"
|
||||||
|
@ -71,54 +70,26 @@ TCASE 0 "case"
|
||||||
TESAC 1 "esac"
|
TESAC 1 "esac"
|
||||||
TNOT 0 "!"
|
TNOT 0 "!"
|
||||||
!
|
!
|
||||||
nl=`wc -l $temp`
|
nl=`wc -l /tmp/ka$$`
|
||||||
exec > token.h
|
exec > token.h
|
||||||
i=0
|
${AWK} '{print "#define " $1 " " NR-1}' /tmp/ka$$
|
||||||
while read line
|
|
||||||
do
|
|
||||||
set -$- $line
|
|
||||||
echo "#define $1 $i"
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done <$temp
|
|
||||||
echo '
|
echo '
|
||||||
/* Array indicating which tokens mark the end of a list */
|
/* Array indicating which tokens mark the end of a list */
|
||||||
const char tokendlist[] = {'
|
const char tokendlist[] = {'
|
||||||
while read line
|
${AWK} '{print "\t" $2 ","}' /tmp/ka$$
|
||||||
do
|
|
||||||
set -$- $line
|
|
||||||
echo " $2,"
|
|
||||||
done <$temp
|
|
||||||
echo '};
|
echo '};
|
||||||
|
|
||||||
const char *const tokname[] = {'
|
const char *const tokname[] = {'
|
||||||
sed -e 's/"/\\"/g' \
|
${SED} -e 's/"/\\"/g' \
|
||||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||||
$temp
|
/tmp/ka$$
|
||||||
echo '};
|
echo '};
|
||||||
'
|
'
|
||||||
i=0
|
${SED} 's/"//g' /tmp/ka$$ | ${AWK} '
|
||||||
go=
|
/TIF/{print "#define KWDOFFSET " NR-1; print "";
|
||||||
sed 's/"//g' $temp |
|
print "const char *const parsekwd[] = {"}
|
||||||
while read line
|
/TIF/,/neverfound/{print " \"" $3 "\","}'
|
||||||
do
|
|
||||||
set -$- $line
|
|
||||||
if [ "$1" = TIF ]
|
|
||||||
then
|
|
||||||
echo "#define KWDOFFSET $i"
|
|
||||||
echo
|
|
||||||
echo "const char *const parsekwd[] = {"
|
|
||||||
go=true
|
|
||||||
fi
|
|
||||||
if [ "$go" ]
|
|
||||||
then
|
|
||||||
echo " \"$3\","
|
|
||||||
fi
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
echo ' 0
|
echo ' 0
|
||||||
};'
|
};'
|
||||||
|
|
||||||
rm $temp
|
rm /tmp/ka$$
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: mktokens,v 1.5 2006/05/22 12:43:35 philip Exp $
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: myhistedit.h,v 1.11 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -10,7 +12,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -27,7 +29,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/myhistedit.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <histedit.h>
|
#include <histedit.h>
|
||||||
|
@ -38,13 +39,8 @@ extern int displayhist;
|
||||||
|
|
||||||
void histedit(void);
|
void histedit(void);
|
||||||
void sethistsize(const char *);
|
void sethistsize(const char *);
|
||||||
int histcmd(int, char **);
|
void setterm(const char *);
|
||||||
int bindcmd(int, char **);
|
int inputrc(int, char **);
|
||||||
|
int not_fcnumber(char *);
|
||||||
/* From libedit */
|
int str_to_event(const char *, int);
|
||||||
void re_goto_bottom(EditLine *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: myhistedit.h,v 1.5 2006/03/29 15:55:18 philip Exp $
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: mystring.c,v 1.17 2013/04/28 17:01:28 dholland Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,15 +32,14 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: mystring.c,v 1.17 2013/04/28 17:01:28 dholland Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String functions.
|
* String functions.
|
||||||
|
@ -57,7 +58,7 @@ __FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
|
||||||
|
|
||||||
char nullstr[1]; /* zero length string */
|
const char nullstr[1]; /* zero length string */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* equal - #defined in mystring.h
|
* equal - #defined in mystring.h
|
||||||
|
@ -109,8 +110,9 @@ prefix(const char *pfx, const char *string)
|
||||||
int
|
int
|
||||||
number(const char *s)
|
number(const char *s)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! is_number(s))
|
if (! is_number(s))
|
||||||
error("Illegal number: %s", (char *)s);
|
error("Illegal number: %s", s);
|
||||||
return atoi(s);
|
return atoi(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +131,3 @@ is_number(const char *p)
|
||||||
} while (*++p != '\0');
|
} while (*++p != '\0');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/mystring.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -42,7 +43,3 @@ int is_number(const char *);
|
||||||
|
|
||||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: mystring.h,v 1.3 2006/03/29 15:49:08 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: nodes.c.pat,v 1.13 2012/03/20 18:42:29 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/nodes.c.pat,v 1.15 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -41,17 +42,14 @@
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
|
#include "machdep.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#include "machdep.h"
|
|
||||||
|
|
||||||
STATIC int funcblocksize; /* size of structures in function */
|
int funcblocksize; /* size of structures in function */
|
||||||
STATIC int funcstringsize; /* size of strings in node */
|
int funcstringsize; /* size of strings in node */
|
||||||
STATIC pointer funcblock; /* block to allocate function from */
|
pointer funcblock; /* block to allocate function from */
|
||||||
STATIC char *funcstring; /* block to allocate strings from */
|
char *funcstring; /* block to allocate strings from */
|
||||||
|
|
||||||
%SIZES
|
%SIZES
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ copyfunc(union node *n)
|
||||||
funcstringsize = 0;
|
funcstringsize = 0;
|
||||||
calcsize(n);
|
calcsize(n);
|
||||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||||
funcstring = (char *)funcblock + funcblocksize;
|
funcstring = (char *) funcblock + funcblocksize;
|
||||||
return copynode(n);
|
return copynode(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +93,7 @@ STATIC void
|
||||||
sizenodelist(struct nodelist *lp)
|
sizenodelist(struct nodelist *lp)
|
||||||
{
|
{
|
||||||
while (lp) {
|
while (lp) {
|
||||||
funcblocksize += ALIGN(sizeof(struct nodelist));
|
funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
|
||||||
calcsize(lp->n);
|
calcsize(lp->n);
|
||||||
lp = lp->next;
|
lp = lp->next;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +120,8 @@ copynodelist(struct nodelist *lp)
|
||||||
lpp = &start;
|
lpp = &start;
|
||||||
while (lp) {
|
while (lp) {
|
||||||
*lpp = funcblock;
|
*lpp = funcblock;
|
||||||
funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
|
funcblock = (char *) funcblock +
|
||||||
|
SHELL_ALIGN(sizeof(struct nodelist));
|
||||||
(*lpp)->n = copynode(lp->n);
|
(*lpp)->n = copynode(lp->n);
|
||||||
lp = lp->next;
|
lp = lp->next;
|
||||||
lpp = &(*lpp)->next;
|
lpp = &(*lpp)->next;
|
||||||
|
@ -136,11 +135,11 @@ copynodelist(struct nodelist *lp)
|
||||||
STATIC char *
|
STATIC char *
|
||||||
nodesavestr(char *s)
|
nodesavestr(char *s)
|
||||||
{
|
{
|
||||||
char *p = s;
|
register char *p = s;
|
||||||
char *q = funcstring;
|
register char *q = funcstring;
|
||||||
char *rtn = funcstring;
|
char *rtn = funcstring;
|
||||||
|
|
||||||
while ((*q++ = *p++) != '\0')
|
while ((*q++ = *p++) != 0)
|
||||||
continue;
|
continue;
|
||||||
funcstring = q;
|
funcstring = q;
|
||||||
return rtn;
|
return rtn;
|
||||||
|
@ -158,7 +157,3 @@ freefunc(union node *n)
|
||||||
if (n)
|
if (n)
|
||||||
ckfree(n);
|
ckfree(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,4 +1,4 @@
|
||||||
#
|
# $NetBSD: nodetypes,v 1.13 2009/05/26 07:30:51 joerg Exp $
|
||||||
# Copyright (c) 1991, 1993
|
# Copyright (c) 1991, 1993
|
||||||
# The Regents of the University of California. All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 3. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
#
|
#
|
||||||
|
@ -30,7 +30,6 @@
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||||
# $FreeBSD: src/bin/sh/nodetypes,v 1.9 2004/04/06 20:06:51 markm Exp $
|
|
||||||
|
|
||||||
# This file describes the nodes used in parse trees. Unindented lines
|
# This file describes the nodes used in parse trees. Unindented lines
|
||||||
# contain a node type followed by a structure tag. Subsequent indented
|
# contain a node type followed by a structure tag. Subsequent indented
|
||||||
|
@ -65,7 +64,7 @@ NPIPE npipe # a pipeline
|
||||||
backgnd int # set to run pipeline in background
|
backgnd int # set to run pipeline in background
|
||||||
cmdlist nodelist # the commands in the pipeline
|
cmdlist nodelist # the commands in the pipeline
|
||||||
|
|
||||||
NREDIR nredir # redirection (of a compex command)
|
NREDIR nredir # redirection (of a complex command)
|
||||||
type int
|
type int
|
||||||
n nodeptr # the command
|
n nodeptr # the command
|
||||||
redirect nodeptr # list of file redirections
|
redirect nodeptr # list of file redirections
|
||||||
|
@ -113,10 +112,10 @@ NARG narg # represents a word
|
||||||
backquote nodelist # list of commands in back quotes
|
backquote nodelist # list of commands in back quotes
|
||||||
|
|
||||||
NTO nfile # fd> fname
|
NTO nfile # fd> fname
|
||||||
|
NCLOBBER nfile # fd>| fname
|
||||||
NFROM nfile # fd< fname
|
NFROM nfile # fd< fname
|
||||||
NFROMTO nfile # fd<> fname
|
NFROMTO nfile # fd<> fname
|
||||||
NAPPEND nfile # fd>> fname
|
NAPPEND nfile # fd>> fname
|
||||||
NCLOBBER nfile # fd>| fname
|
|
||||||
type int
|
type int
|
||||||
next nodeptr # next redirection in list
|
next nodeptr # next redirection in list
|
||||||
fd int # file descriptor being redirected
|
fd int # file descriptor being redirected
|
||||||
|
@ -140,8 +139,5 @@ NXHERE nhere # fd<<!
|
||||||
doc nodeptr # input to command (NARG node)
|
doc nodeptr # input to command (NARG node)
|
||||||
|
|
||||||
NNOT nnot # ! command (actually pipeline)
|
NNOT nnot # ! command (actually pipeline)
|
||||||
type int
|
type int
|
||||||
com nodeptr
|
com nodeptr
|
||||||
|
|
||||||
#
|
|
||||||
# $PchId: nodetypes,v 1.3 2006/03/29 15:43:35 philip Exp $
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: options.c,v 1.43 2012/03/20 18:42:29 matt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,15 +32,14 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: options.c,v 1.43 2012/03/20 18:42:29 matt Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -48,6 +49,7 @@ __FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $"
|
||||||
#define DEFINE_OPTIONS
|
#define DEFINE_OPTIONS
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#undef DEFINE_OPTIONS
|
#undef DEFINE_OPTIONS
|
||||||
|
#include "builtins.h"
|
||||||
#include "nodes.h" /* for other header files */
|
#include "nodes.h" /* for other header files */
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
@ -58,17 +60,16 @@ __FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "builtins.h"
|
#ifndef SMALL
|
||||||
#if !defined(NO_HISTORY)
|
|
||||||
#include "myhistedit.h"
|
#include "myhistedit.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "show.h"
|
||||||
|
|
||||||
char *arg0; /* value of $0 */
|
char *arg0; /* value of $0 */
|
||||||
struct shparam shellparam; /* current positional parameters */
|
struct shparam shellparam; /* current positional parameters */
|
||||||
char **argptr; /* argument list for builtin commands */
|
char **argptr; /* argument list for builtin commands */
|
||||||
char *shoptarg; /* set by nextopt (like getopt) */
|
char *optionarg; /* set by nextopt (like getopt) */
|
||||||
char *optptr; /* used by nextopt */
|
char *optptr; /* used by nextopt */
|
||||||
int editable; /* isatty(0) && isatty(1) */
|
|
||||||
|
|
||||||
char *minusc; /* argument to -c option */
|
char *minusc; /* argument to -c option */
|
||||||
|
|
||||||
|
@ -86,33 +87,43 @@ STATIC int getopts(char *, char *, char **, char ***, char **);
|
||||||
void
|
void
|
||||||
procargs(int argc, char **argv)
|
procargs(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
argptr = argv;
|
argptr = argv;
|
||||||
if (argc > 0)
|
if (argc > 0)
|
||||||
argptr++;
|
argptr++;
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
optlist[i].val = 2;
|
optlist[i].val = 2;
|
||||||
privileged = (getuid() != geteuid() || getgid() != getegid());
|
|
||||||
options(1);
|
options(1);
|
||||||
if (*argptr == NULL && minusc == NULL)
|
if (*argptr == NULL && minusc == NULL)
|
||||||
sflag = 1;
|
sflag = 1;
|
||||||
editable = (isatty(0) && isatty(1));
|
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
||||||
if (iflag == 2 && sflag == 1 && editable)
|
|
||||||
iflag = 1;
|
iflag = 1;
|
||||||
|
if (iflag == 1 && sflag == 2)
|
||||||
|
iflag = 2;
|
||||||
if (mflag == 2)
|
if (mflag == 2)
|
||||||
mflag = iflag;
|
mflag = iflag;
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
if (optlist[i].val == 2)
|
if (optlist[i].val == 2)
|
||||||
optlist[i].val = 0;
|
optlist[i].val = 0;
|
||||||
|
#if DEBUG == 2
|
||||||
|
debug = 1;
|
||||||
|
#endif
|
||||||
arg0 = argv[0];
|
arg0 = argv[0];
|
||||||
if (sflag == 0 && minusc == NULL) {
|
if (sflag == 0 && minusc == NULL) {
|
||||||
commandname = arg0 = *argptr++;
|
commandname = argv[0];
|
||||||
setinputfile(commandname, 0);
|
arg0 = *argptr++;
|
||||||
|
setinputfile(arg0, 0);
|
||||||
|
commandname = arg0;
|
||||||
}
|
}
|
||||||
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||||
if (argptr && minusc && *argptr)
|
if (minusc != NULL) {
|
||||||
arg0 = *argptr++;
|
if (argptr == NULL || *argptr == NULL)
|
||||||
|
error("Bad -c option");
|
||||||
|
minusc = *argptr++;
|
||||||
|
if (*argptr != 0)
|
||||||
|
arg0 = *argptr++;
|
||||||
|
}
|
||||||
|
|
||||||
shellparam.p = argptr;
|
shellparam.p = argptr;
|
||||||
shellparam.reset = 1;
|
shellparam.reset = 1;
|
||||||
|
@ -121,9 +132,6 @@ procargs(int argc, char **argv)
|
||||||
shellparam.nparam++;
|
shellparam.nparam++;
|
||||||
argptr++;
|
argptr++;
|
||||||
}
|
}
|
||||||
#ifdef __minix
|
|
||||||
if(!Eflag && !Vflag) Eflag = 1;
|
|
||||||
#endif
|
|
||||||
optschanged();
|
optschanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +140,7 @@ void
|
||||||
optschanged(void)
|
optschanged(void)
|
||||||
{
|
{
|
||||||
setinteractive(iflag);
|
setinteractive(iflag);
|
||||||
#if !defined(NO_HISTORY)
|
#ifndef SMALL
|
||||||
histedit();
|
histedit();
|
||||||
#endif
|
#endif
|
||||||
setjobctl(mflag);
|
setjobctl(mflag);
|
||||||
|
@ -146,6 +154,7 @@ optschanged(void)
|
||||||
STATIC void
|
STATIC void
|
||||||
options(int cmdline)
|
options(int cmdline)
|
||||||
{
|
{
|
||||||
|
static char empty[] = "";
|
||||||
char *p;
|
char *p;
|
||||||
int val;
|
int val;
|
||||||
int c;
|
int c;
|
||||||
|
@ -175,65 +184,62 @@ options(int cmdline)
|
||||||
}
|
}
|
||||||
while ((c = *p++) != '\0') {
|
while ((c = *p++) != '\0') {
|
||||||
if (c == 'c' && cmdline) {
|
if (c == 'c' && cmdline) {
|
||||||
char *q;
|
/* command is after shell args*/
|
||||||
#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
|
minusc = empty;
|
||||||
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') {
|
} else if (c == 'o') {
|
||||||
minus_o(*argptr, val);
|
minus_o(*argptr, val);
|
||||||
if (*argptr)
|
if (*argptr)
|
||||||
argptr++;
|
argptr++;
|
||||||
} else {
|
} else {
|
||||||
if (c == 'p' && !val && privileged) {
|
|
||||||
(void) setuid(getuid());
|
|
||||||
(void) setgid(getgid());
|
|
||||||
}
|
|
||||||
setoption(c, val);
|
setoption(c, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_opt_val(size_t i, int val)
|
||||||
|
{
|
||||||
|
size_t j;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
if (val && (flag = optlist[i].opt_set)) {
|
||||||
|
/* some options (eg vi/emacs) are mutually exclusive */
|
||||||
|
for (j = 0; j < NOPTS; j++)
|
||||||
|
if (optlist[j].opt_set == flag)
|
||||||
|
optlist[j].val = 0;
|
||||||
|
}
|
||||||
|
optlist[i].val = val;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (&optlist[i].val == &debug)
|
||||||
|
opentrace();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
minus_o(char *name, int val)
|
minus_o(char *name, int val)
|
||||||
{
|
{
|
||||||
int doneset, i;
|
size_t i;
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
if (val) {
|
if (val) {
|
||||||
/* "Pretty" output. */
|
|
||||||
out1str("Current option settings\n");
|
out1str("Current option settings\n");
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++) {
|
||||||
out1fmt("%-16s%s\n", optlist[i].name,
|
out1fmt("%-16s%s\n", optlist[i].name,
|
||||||
optlist[i].val ? "on" : "off");
|
optlist[i].val ? "on" : "off");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Output suitable for re-input to shell. */
|
out1str("set");
|
||||||
for (doneset = i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++) {
|
||||||
if (optlist[i].val) {
|
out1fmt(" %co %s",
|
||||||
if (!doneset) {
|
"+-"[optlist[i].val], optlist[i].name);
|
||||||
out1str("set");
|
}
|
||||||
doneset = 1;
|
out1str("\n");
|
||||||
}
|
|
||||||
out1fmt(" -o %s", optlist[i].name);
|
|
||||||
}
|
|
||||||
if (doneset)
|
|
||||||
out1c('\n');
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
if (equal(name, optlist[i].name)) {
|
if (equal(name, optlist[i].name)) {
|
||||||
if (!val && privileged && equal(name, "privileged")) {
|
set_opt_val(i, val);
|
||||||
(void) setuid(getuid());
|
|
||||||
(void) setgid(getgid());
|
|
||||||
}
|
|
||||||
setoption(optlist[i].letter, val);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error("Illegal option -o %s", name);
|
error("Illegal option -o %s", name);
|
||||||
|
@ -244,21 +250,15 @@ minus_o(char *name, int val)
|
||||||
STATIC void
|
STATIC void
|
||||||
setoption(int flag, int val)
|
setoption(int flag, int val)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
if (optlist[i].letter == flag) {
|
if (optlist[i].letter == flag) {
|
||||||
optlist[i].val = val;
|
set_opt_val( i, val );
|
||||||
if (val) {
|
|
||||||
/* #%$ hack for ksh semantics */
|
|
||||||
if (flag == 'V')
|
|
||||||
Eflag = 0;
|
|
||||||
else if (flag == 'E')
|
|
||||||
Vflag = 0;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error("Illegal option -%c", flag);
|
error("Illegal option -%c", flag);
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ INCLUDE "options.h"
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < NOPTS; i++)
|
for (i = 0; optlist[i].name; i++)
|
||||||
optlist[i].val = 0;
|
optlist[i].val = 0;
|
||||||
optschanged();
|
optschanged();
|
||||||
|
|
||||||
|
@ -288,7 +288,8 @@ setparam(char **argv)
|
||||||
char **ap;
|
char **ap;
|
||||||
int nparam;
|
int nparam;
|
||||||
|
|
||||||
for (nparam = 0 ; argv[nparam] ; nparam++);
|
for (nparam = 0 ; argv[nparam] ; nparam++)
|
||||||
|
continue;
|
||||||
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
*ap++ = savestr(*argv++);
|
*ap++ = savestr(*argv++);
|
||||||
|
@ -307,7 +308,7 @@ setparam(char **argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
freeparam(struct shparam *param)
|
freeparam(volatile struct shparam *param)
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
|
|
||||||
|
@ -358,7 +359,7 @@ int
|
||||||
setcmd(int argc, char **argv)
|
setcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
return showvarscmd(argc, argv);
|
return showvars(0, 0, 1);
|
||||||
INTOFF;
|
INTOFF;
|
||||||
options(0);
|
options(0);
|
||||||
optschanged();
|
optschanged();
|
||||||
|
@ -389,7 +390,7 @@ getoptsreset(const char *value)
|
||||||
int
|
int
|
||||||
getoptscmd(int argc, char **argv)
|
getoptscmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char **optbase = NULL;
|
char **optbase;
|
||||||
|
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
error("usage: getopts optstring var [arg]");
|
error("usage: getopts optstring var [arg]");
|
||||||
|
@ -409,17 +410,16 @@ getoptscmd(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
|
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
|
||||||
char **optptr)
|
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
char c = '?';
|
char c = '?';
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int ind = 0;
|
int ind = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
char s[10];
|
char s[12];
|
||||||
|
|
||||||
if ((p = *optptr) == NULL || *p == '\0') {
|
if ((p = *optpptr) == NULL || *p == '\0') {
|
||||||
/* Current word is done, advance */
|
/* Current word is done, advance */
|
||||||
if (*optnext == NULL)
|
if (*optnext == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -444,10 +444,9 @@ atend:
|
||||||
s[0] = c;
|
s[0] = c;
|
||||||
s[1] = '\0';
|
s[1] = '\0';
|
||||||
err |= setvarsafe("OPTARG", s, 0);
|
err |= setvarsafe("OPTARG", s, 0);
|
||||||
}
|
} else {
|
||||||
else {
|
outfmt(&errout, "Illegal option -%c\n", c);
|
||||||
out1fmt("Illegal option -%c\n", c);
|
(void) unsetvar("OPTARG", 0);
|
||||||
(void) unsetvar("OPTARG");
|
|
||||||
}
|
}
|
||||||
c = '?';
|
c = '?';
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -463,10 +462,9 @@ atend:
|
||||||
s[1] = '\0';
|
s[1] = '\0';
|
||||||
err |= setvarsafe("OPTARG", s, 0);
|
err |= setvarsafe("OPTARG", s, 0);
|
||||||
c = ':';
|
c = ':';
|
||||||
}
|
} else {
|
||||||
else {
|
outfmt(&errout, "No arg for -%c option\n", c);
|
||||||
out1fmt("No arg for -%c option\n", c);
|
(void) unsetvar("OPTARG", 0);
|
||||||
(void) unsetvar("OPTARG");
|
|
||||||
c = '?';
|
c = '?';
|
||||||
}
|
}
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -474,11 +472,10 @@ atend:
|
||||||
|
|
||||||
if (p == **optnext)
|
if (p == **optnext)
|
||||||
(*optnext)++;
|
(*optnext)++;
|
||||||
setvarsafe("OPTARG", p, 0);
|
err |= setvarsafe("OPTARG", p, 0);
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
} else
|
||||||
else
|
err |= setvarsafe("OPTARG", "", 0);
|
||||||
setvarsafe("OPTARG", "", 0);
|
|
||||||
ind = *optnext - optfirst + 1;
|
ind = *optnext - optfirst + 1;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -487,7 +484,7 @@ bad:
|
||||||
*optnext = NULL;
|
*optnext = NULL;
|
||||||
p = NULL;
|
p = NULL;
|
||||||
out:
|
out:
|
||||||
*optptr = p;
|
*optpptr = p;
|
||||||
fmtstr(s, sizeof(s), "%d", ind);
|
fmtstr(s, sizeof(s), "%d", ind);
|
||||||
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||||
s[0] = c;
|
s[0] = c;
|
||||||
|
@ -495,7 +492,7 @@ out:
|
||||||
err |= setvarsafe(optvar, s, 0);
|
err |= setvarsafe(optvar, s, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
*optnext = NULL;
|
*optnext = NULL;
|
||||||
*optptr = NULL;
|
*optpptr = NULL;
|
||||||
flushall();
|
flushall();
|
||||||
exraise(EXERROR);
|
exraise(EXERROR);
|
||||||
}
|
}
|
||||||
|
@ -514,9 +511,10 @@ out:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
nextopt(char *optstring)
|
nextopt(const char *optstring)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p;
|
||||||
|
const char *q;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if ((p = optptr) == NULL || *p == '\0') {
|
if ((p = optptr) == NULL || *p == '\0') {
|
||||||
|
@ -537,13 +535,9 @@ nextopt(char *optstring)
|
||||||
if (*++q == ':') {
|
if (*++q == ':') {
|
||||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||||
error("No arg for -%c option", c);
|
error("No arg for -%c option", c);
|
||||||
shoptarg = p;
|
optionarg = p;
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
optptr = p;
|
optptr = p;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: options.c,v 1.6 2006/05/29 13:09:12 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: options.h,v 1.20 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/options.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct shparam {
|
struct shparam {
|
||||||
|
@ -43,57 +44,74 @@ struct shparam {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#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 privileged optlist[15].val
|
|
||||||
#define Tflag optlist[16].val
|
|
||||||
#define Pflag optlist[17].val
|
|
||||||
|
|
||||||
#define NOPTS 18
|
|
||||||
|
|
||||||
struct optent {
|
struct optent {
|
||||||
const char *name;
|
const char *name; /* for set -o <name> */
|
||||||
const char letter;
|
const char letter; /* set [+/-]<letter> and $- */
|
||||||
char val;
|
const char opt_set; /* mutually exclusive option set */
|
||||||
|
unsigned char val; /* value of <letter>flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Those marked [U] are required by posix, but have no effect! */
|
||||||
|
|
||||||
#ifdef DEFINE_OPTIONS
|
#ifdef DEFINE_OPTIONS
|
||||||
struct optent optlist[NOPTS] = {
|
#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
|
||||||
{ "errexit", 'e', 0 },
|
struct optent optlist[] = {
|
||||||
{ "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 },
|
|
||||||
{ "privileged", 'p', 0 },
|
|
||||||
{ "trapsasync", 'T', 0 },
|
|
||||||
{ "physical", 'P', 0 },
|
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
extern struct optent optlist[NOPTS];
|
#define DEF_OPTS(name, letter, opt_set)
|
||||||
|
#endif
|
||||||
|
#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
|
||||||
|
|
||||||
|
DEF_OPT( "errexit", 'e' ) /* exit on error */
|
||||||
|
#define eflag optlist[0].val
|
||||||
|
DEF_OPT( "noglob", 'f' ) /* no pathname expansion */
|
||||||
|
#define fflag optlist[1].val
|
||||||
|
DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */
|
||||||
|
#define Iflag optlist[2].val
|
||||||
|
DEF_OPT( "interactive",'i' ) /* interactive shell */
|
||||||
|
#define iflag optlist[3].val
|
||||||
|
DEF_OPT( "monitor", 'm' ) /* job control */
|
||||||
|
#define mflag optlist[4].val
|
||||||
|
DEF_OPT( "noexec", 'n' ) /* [U] do not exec commands */
|
||||||
|
#define nflag optlist[5].val
|
||||||
|
DEF_OPT( "stdin", 's' ) /* read from stdin */
|
||||||
|
#define sflag optlist[6].val
|
||||||
|
DEF_OPT( "xtrace", 'x' ) /* trace after expansion */
|
||||||
|
#define xflag optlist[7].val
|
||||||
|
DEF_OPT( "verbose", 'v' ) /* trace read input */
|
||||||
|
#define vflag optlist[8].val
|
||||||
|
DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */
|
||||||
|
#define Vflag optlist[9].val
|
||||||
|
DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */
|
||||||
|
#define Eflag optlist[10].val
|
||||||
|
DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */
|
||||||
|
#define Cflag optlist[11].val
|
||||||
|
DEF_OPT( "allexport", 'a' ) /* export all variables */
|
||||||
|
#define aflag optlist[12].val
|
||||||
|
DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */
|
||||||
|
#define bflag optlist[13].val
|
||||||
|
DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */
|
||||||
|
#define uflag optlist[14].val
|
||||||
|
DEF_OPT( "quietprofile", 'q' )
|
||||||
|
#define qflag optlist[15].val
|
||||||
|
DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */
|
||||||
|
#define nolog optlist[16].val
|
||||||
|
DEF_OPT( "cdprint", 0 ) /* always print result of cd */
|
||||||
|
#define cdprint optlist[17].val
|
||||||
|
DEF_OPT( "tabcomplete", 0 ) /* <tab> causes filename expansion */
|
||||||
|
#define tabcomplete optlist[18].val
|
||||||
|
#ifdef DEBUG
|
||||||
|
DEF_OPT( "debug", 0 ) /* enable debug prints */
|
||||||
|
#define debug optlist[19].val
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFINE_OPTIONS
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
|
||||||
|
int sizeof_optlist = sizeof optlist;
|
||||||
|
#else
|
||||||
|
extern struct optent optlist[];
|
||||||
|
extern int sizeof_optlist;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,20 +119,12 @@ extern char *minusc; /* argument to -c option */
|
||||||
extern char *arg0; /* $0 */
|
extern char *arg0; /* $0 */
|
||||||
extern struct shparam shellparam; /* $@ */
|
extern struct shparam shellparam; /* $@ */
|
||||||
extern char **argptr; /* argument list for builtin commands */
|
extern char **argptr; /* argument list for builtin commands */
|
||||||
extern char *shoptarg; /* set by nextopt */
|
extern char *optionarg; /* set by nextopt */
|
||||||
extern char *optptr; /* used by nextopt */
|
extern char *optptr; /* used by nextopt */
|
||||||
extern int editable; /* isatty(0) && isatty(1) */
|
|
||||||
|
|
||||||
void procargs(int, char **);
|
void procargs(int, char **);
|
||||||
void optschanged(void);
|
void optschanged(void);
|
||||||
void setparam(char **);
|
void setparam(char **);
|
||||||
void freeparam(struct shparam *);
|
void freeparam(volatile struct shparam *);
|
||||||
int shiftcmd(int, char **);
|
int nextopt(const char *);
|
||||||
int setcmd(int, char **);
|
|
||||||
int getoptscmd(int, char **);
|
|
||||||
int nextopt(char *);
|
|
||||||
void getoptsreset(const char *);
|
void getoptsreset(const char *);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: options.h,v 1.5 2006/05/29 13:08:45 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: output.c,v 1.33 2010/08/30 06:27:14 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,9 +32,12 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
|
static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: output.c,v 1.33 2010/08/30 06:27:14 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
|
@ -47,28 +52,26 @@ static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
|
||||||
* Our output routines may be smaller than the stdio routines.
|
* Our output routines may be smaller than the stdio routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h> /* quad_t */
|
||||||
|
#include <sys/param.h> /* BSD4_4 */
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#include <stdio.h> /* defines BUFSIZ */
|
#include <stdio.h> /* defines BUFSIZ */
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "var.h"
|
|
||||||
#ifdef __STDC__
|
|
||||||
#include "stdarg.h"
|
|
||||||
#else
|
|
||||||
#include <varargs.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define OUTBUFSIZ BUFSIZ
|
#define OUTBUFSIZ BUFSIZ
|
||||||
#define BLOCK_OUT -2 /* output to a fixed block of memory */
|
#define BLOCK_OUT -2 /* output to a fixed block of memory */
|
||||||
#define MEM_OUT -3 /* output to dynamically allocated 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 output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
|
||||||
|
@ -102,11 +105,8 @@ RESET {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
open_mem(block, length, file)
|
open_mem(char *block, int length, struct output *file)
|
||||||
char *block;
|
{
|
||||||
int length;
|
|
||||||
struct output *file;
|
|
||||||
{
|
|
||||||
file->nextc = block;
|
file->nextc = block;
|
||||||
file->nleft = --length;
|
file->nleft = --length;
|
||||||
file->fd = BLOCK_OUT;
|
file->fd = BLOCK_OUT;
|
||||||
|
@ -116,16 +116,9 @@ open_mem(block, length, file)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
out1str(p)
|
out1str(const char *p)
|
||||||
const char *p;
|
|
||||||
{
|
|
||||||
outstr(p, out1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
out1qstr(const char *p)
|
|
||||||
{
|
{
|
||||||
outqstr(p, out1);
|
outstr(p, out1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,43 +130,49 @@ out2str(const char *p)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
outstr(p, file)
|
outstr(const char *p, struct output *file)
|
||||||
register const char *p;
|
{
|
||||||
register struct output *file;
|
|
||||||
{
|
|
||||||
while (*p)
|
while (*p)
|
||||||
outc(*p++, file);
|
outc(*p++, file);
|
||||||
if (file == out2)
|
if (file == out2)
|
||||||
flushout(file);
|
flushout(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like outstr(), but quote for re-input into the shell. */
|
|
||||||
void
|
void
|
||||||
outqstr(const char *p, struct output *file)
|
out2shstr(const char *p)
|
||||||
{
|
{
|
||||||
char ch;
|
outshstr(p, out2);
|
||||||
|
}
|
||||||
|
|
||||||
if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
|
|
||||||
p[strcspn(p, ifsval())] == '\0')) {
|
|
||||||
outstr(p, file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
out1c('\'');
|
void
|
||||||
while ((ch = *p++) != '\0') {
|
outshstr(const char *p, struct output *file)
|
||||||
switch (ch) {
|
{
|
||||||
case '\'':
|
static const char norm_chars [] \
|
||||||
/*
|
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-=";
|
||||||
* Can't quote single quotes inside single quotes;
|
int need_q = p[0] == 0 || p[strspn(p, norm_chars)] != 0;
|
||||||
* close them, write escaped single quote, open again.
|
char c;
|
||||||
*/
|
|
||||||
outstr("'\\''", file);
|
if (need_q)
|
||||||
break;
|
outc('\'', file);
|
||||||
default:
|
|
||||||
outc(ch, file);
|
while (c = *p++, c != 0){
|
||||||
|
if (c != '\''){
|
||||||
|
outc(c, file);
|
||||||
|
}else{
|
||||||
|
outc('\'', file);
|
||||||
|
outc('\\', file);
|
||||||
|
outc(c, file);
|
||||||
|
outc('\'', file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out1c('\'');
|
|
||||||
|
if (need_q)
|
||||||
|
outc('\'', file);
|
||||||
|
|
||||||
|
if (file == out2)
|
||||||
|
flushout(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,9 +180,8 @@ char out_junk[16];
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
emptyoutbuf(dest)
|
emptyoutbuf(struct output *dest)
|
||||||
struct output *dest;
|
{
|
||||||
{
|
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if (dest->fd == BLOCK_OUT) {
|
if (dest->fd == BLOCK_OUT) {
|
||||||
|
@ -212,16 +210,16 @@ emptyoutbuf(dest)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
flushall() {
|
flushall(void)
|
||||||
|
{
|
||||||
flushout(&output);
|
flushout(&output);
|
||||||
flushout(&errout);
|
flushout(&errout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
flushout(dest)
|
flushout(struct output *dest)
|
||||||
struct output *dest;
|
{
|
||||||
{
|
|
||||||
|
|
||||||
if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
|
if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
|
||||||
return;
|
return;
|
||||||
|
@ -233,7 +231,8 @@ flushout(dest)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
freestdout() {
|
freestdout(void)
|
||||||
|
{
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (output.buf) {
|
if (output.buf) {
|
||||||
ckfree(output.buf);
|
ckfree(output.buf);
|
||||||
|
@ -244,7 +243,6 @@ freestdout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void
|
void
|
||||||
outfmt(struct output *file, const char *fmt, ...)
|
outfmt(struct output *file, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -266,8 +264,9 @@ out1fmt(const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
dbgprintf(const char *fmt, ...)
|
debugprintf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
@ -276,9 +275,10 @@ dbgprintf(const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
flushout(out2);
|
flushout(out2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
fmtstr(char *outbuf, int length, const char *fmt, ...)
|
fmtstr(char *outbuf, size_t length, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
struct output strout;
|
struct output strout;
|
||||||
|
@ -295,82 +295,11 @@ fmtstr(char *outbuf, int length, const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
|
||||||
dbgprintf(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:
|
* Formatted output. This routine handles a subset of the printf formats:
|
||||||
* - Formats supported: d, u, o, X, s, and c.
|
* - Formats supported: d, u, o, p, X, s, and c.
|
||||||
* - The x format is also accepted but is treated like X.
|
* - The x format is also accepted but is treated like X.
|
||||||
* - The l modifier is accepted.
|
* - The l, ll and q modifiers are accepted.
|
||||||
* - The - and # flags are accepted; # only works with the o format.
|
* - The - and # flags are accepted; # only works with the o format.
|
||||||
* - Width and precision may be specified with any format except c.
|
* - Width and precision may be specified with any format except c.
|
||||||
* - An * may be given for the width or precision.
|
* - An * may be given for the width or precision.
|
||||||
|
@ -381,27 +310,40 @@ fmtstr(va_alist)
|
||||||
|
|
||||||
#define TEMPSIZE 24
|
#define TEMPSIZE 24
|
||||||
|
|
||||||
#ifdef __STDC__
|
#ifdef BSD4_4
|
||||||
static const char digit[16] = "0123456789ABCDEF";
|
#define HAVE_VASPRINTF 1
|
||||||
#else
|
|
||||||
static const char digit[17] = "0123456789ABCDEF";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
doformat(struct output *dest, const char *f, va_list ap)
|
doformat(struct output *dest, const char *f, va_list ap)
|
||||||
{
|
{
|
||||||
register char c;
|
#if HAVE_VASPRINTF
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
vasprintf(&s, f, ap);
|
||||||
|
if (s == NULL)
|
||||||
|
error("Could not allocate formatted output buffer");
|
||||||
|
outstr(s, dest);
|
||||||
|
free(s);
|
||||||
|
#else /* !HAVE_VASPRINTF */
|
||||||
|
static const char digit[] = "0123456789ABCDEF";
|
||||||
|
char c;
|
||||||
char temp[TEMPSIZE];
|
char temp[TEMPSIZE];
|
||||||
int flushleft;
|
int flushleft;
|
||||||
int sharp;
|
int sharp;
|
||||||
int width;
|
int width;
|
||||||
int prec;
|
int prec;
|
||||||
int islong;
|
int islong;
|
||||||
|
int isquad;
|
||||||
char *p;
|
char *p;
|
||||||
int sign;
|
int sign;
|
||||||
|
#ifdef BSD4_4
|
||||||
|
quad_t l;
|
||||||
|
u_quad_t num;
|
||||||
|
#else
|
||||||
long l;
|
long l;
|
||||||
unsigned long num;
|
u_long num;
|
||||||
|
#endif
|
||||||
unsigned base;
|
unsigned base;
|
||||||
int len;
|
int len;
|
||||||
int size;
|
int size;
|
||||||
|
@ -417,6 +359,7 @@ doformat(struct output *dest, const char *f, va_list ap)
|
||||||
width = 0;
|
width = 0;
|
||||||
prec = -1;
|
prec = -1;
|
||||||
islong = 0;
|
islong = 0;
|
||||||
|
isquad = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*f == '-')
|
if (*f == '-')
|
||||||
flushleft++;
|
flushleft++;
|
||||||
|
@ -446,11 +389,23 @@ doformat(struct output *dest, const char *f, va_list ap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*f == 'l') {
|
if (*f == 'l') {
|
||||||
islong++;
|
f++;
|
||||||
|
if (*f == 'l') {
|
||||||
|
isquad++;
|
||||||
|
f++;
|
||||||
|
} else
|
||||||
|
islong++;
|
||||||
|
} else if (*f == 'q') {
|
||||||
|
isquad++;
|
||||||
f++;
|
f++;
|
||||||
}
|
}
|
||||||
switch (*f) {
|
switch (*f) {
|
||||||
case 'd':
|
case 'd':
|
||||||
|
#ifdef BSD4_4
|
||||||
|
if (isquad)
|
||||||
|
l = va_arg(ap, quad_t);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (islong)
|
if (islong)
|
||||||
l = va_arg(ap, long);
|
l = va_arg(ap, long);
|
||||||
else
|
else
|
||||||
|
@ -469,12 +424,21 @@ doformat(struct output *dest, const char *f, va_list ap)
|
||||||
case 'o':
|
case 'o':
|
||||||
base = 8;
|
base = 8;
|
||||||
goto uns_number;
|
goto uns_number;
|
||||||
|
case 'p':
|
||||||
|
outc('0', dest);
|
||||||
|
outc('x', dest);
|
||||||
|
/*FALLTHROUGH*/
|
||||||
case 'x':
|
case 'x':
|
||||||
/* we don't implement 'x'; treat like 'X' */
|
/* we don't implement 'x'; treat like 'X' */
|
||||||
case 'X':
|
case 'X':
|
||||||
base = 16;
|
base = 16;
|
||||||
uns_number: /* an unsigned number */
|
uns_number: /* an unsigned number */
|
||||||
sign = 0;
|
sign = 0;
|
||||||
|
#ifdef BSD4_4
|
||||||
|
if (isquad)
|
||||||
|
num = va_arg(ap, u_quad_t);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (islong)
|
if (islong)
|
||||||
num = va_arg(ap, unsigned long);
|
num = va_arg(ap, unsigned long);
|
||||||
else
|
else
|
||||||
|
@ -542,6 +506,7 @@ number: /* process a number */
|
||||||
}
|
}
|
||||||
f++;
|
f++;
|
||||||
}
|
}
|
||||||
|
#endif /* !HAVE_VASPRINTF */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -551,11 +516,8 @@ number: /* process a number */
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
xwrite(fd, buf, nbytes)
|
xwrite(int fd, char *buf, int nbytes)
|
||||||
int fd;
|
{
|
||||||
char *buf;
|
|
||||||
int nbytes;
|
|
||||||
{
|
|
||||||
int ntry;
|
int ntry;
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
|
@ -578,6 +540,17 @@ xwrite(fd, buf, nbytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $
|
* Version of ioctl that retries after a signal is caught.
|
||||||
|
* XXX unused function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
xioctl(int fd, unsigned long request, char *arg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: output.h,v 1.24 2012/03/15 02:02:20 joerg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/output.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OUTPUT_INCL
|
#ifndef OUTPUT_INCL
|
||||||
|
@ -46,41 +47,38 @@ struct output {
|
||||||
short flags;
|
short flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* flags for ->flags */
|
||||||
|
#define OUTPUT_ERR 01 /* error occurred on output */
|
||||||
|
|
||||||
extern struct output output;
|
extern struct output output;
|
||||||
extern struct output errout;
|
extern struct output errout;
|
||||||
extern struct output memout;
|
extern struct output memout;
|
||||||
extern struct output *out1;
|
extern struct output *out1;
|
||||||
extern struct output *out2;
|
extern struct output *out2;
|
||||||
|
|
||||||
#ifndef __printflike
|
|
||||||
#define __printflike(a,b)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void open_mem(char *, int, struct output *);
|
void open_mem(char *, int, struct output *);
|
||||||
void out1str(const char *);
|
void out1str(const char *);
|
||||||
void out1qstr(const char *);
|
|
||||||
void out2str(const char *);
|
void out2str(const char *);
|
||||||
void out2qstr(const char *);
|
|
||||||
void outstr(const char *, struct output *);
|
void outstr(const char *, struct output *);
|
||||||
void outqstr(const char *, struct output *);
|
void out2shstr(const char *);
|
||||||
|
void outshstr(const char *, struct output *);
|
||||||
void emptyoutbuf(struct output *);
|
void emptyoutbuf(struct output *);
|
||||||
void flushall(void);
|
void flushall(void);
|
||||||
void flushout(struct output *);
|
void flushout(struct output *);
|
||||||
void freestdout(void);
|
void freestdout(void);
|
||||||
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
|
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
|
||||||
void out1fmt(const char *, ...) __printflike(1, 2);
|
void out1fmt(const char *, ...) __printflike(1, 2);
|
||||||
void dbgprintf(const char *, ...) __printflike(1, 2);
|
#ifdef DEBUG
|
||||||
void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
|
void debugprintf(const char *, ...) __printflike(1, 2);
|
||||||
|
#endif
|
||||||
|
void fmtstr(char *, size_t, const char *, ...) __printflike(3, 4);
|
||||||
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
|
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
|
||||||
int xwrite(int, char *, int);
|
int xwrite(int, char *, int);
|
||||||
|
int xioctl(int, unsigned long, char *);
|
||||||
|
|
||||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||||
#define out1c(c) outc(c, out1);
|
#define out1c(c) outc(c, out1)
|
||||||
#define out2c(c) outc(c, out2);
|
#define out2c(c) outc(c, out2)
|
||||||
|
|
||||||
#define OUTPUT_INCL
|
#define OUTPUT_INCL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: output.h,v 1.5 2006/05/23 12:04:54 philip Exp $
|
|
||||||
*/
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: parser.h,v 1.18 2013/10/02 19:52:58 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,24 +32,28 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* control characters in argument strings */
|
/* control characters in argument strings */
|
||||||
#define CTLESC '\201'
|
#define CTL_FIRST '\201' /* first 'special' character */
|
||||||
#define CTLVAR '\202'
|
#define CTLESC '\201' /* escape next character */
|
||||||
|
#define CTLVAR '\202' /* variable defn */
|
||||||
#define CTLENDVAR '\203'
|
#define CTLENDVAR '\203'
|
||||||
#define CTLBACKQ '\204'
|
#define CTLBACKQ '\204'
|
||||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||||
/* CTLBACKQ | CTLQUOTE == '\205' */
|
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||||
#define CTLARI '\206'
|
#define CTLARI '\206' /* arithmetic expression */
|
||||||
#define CTLENDARI '\207'
|
#define CTLENDARI '\207'
|
||||||
#define CTLQUOTEMARK '\210'
|
#define CTLQUOTEMARK '\210'
|
||||||
|
#define CTLQUOTEEND '\211' /* only inside ${...} */
|
||||||
|
#define CTL_LAST '\211' /* last 'special' character */
|
||||||
|
|
||||||
/* variable substitution byte (follows CTLVAR) */
|
/* variable substitution byte (follows CTLVAR) */
|
||||||
#define VSTYPE 0x0f /* type of variable substitution */
|
#define VSTYPE 0x0f /* type of variable substitution */
|
||||||
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
||||||
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
#define VSLINENO 0x20 /* expansion of $LINENO, the line number
|
||||||
|
follows immediately */
|
||||||
|
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
||||||
|
|
||||||
/* values of VSTYPE field */
|
/* values of VSTYPE field */
|
||||||
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
||||||
|
@ -75,8 +81,4 @@ extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||||
union node *parsecmd(int);
|
union node *parsecmd(int);
|
||||||
void fixredir(union node *, const char *, int);
|
void fixredir(union node *, const char *, int);
|
||||||
int goodname(char *);
|
int goodname(char *);
|
||||||
char *getprompt(void *);
|
const char *getprompt(void *);
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: redir.c,v 1.35 2013/06/27 23:22:04 yamt Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,18 +32,17 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: redir.c,v 1.35 2013/06/27 23:22:04 yamt Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/param.h> /* PIPE_BUF */
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -53,25 +54,31 @@ __FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
* Code for dealing with input/output redirection.
|
* Code for dealing with input/output redirection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
#include "options.h"
|
||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
#include "redir.h"
|
#include "redir.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||||
#define PIPESIZE 4096 /* amount of buffering in a pipe */
|
#define CLOSED -1 /* fd was not open before redir */
|
||||||
|
#ifndef PIPE_BUF
|
||||||
|
# define PIPESIZE 4096 /* amount of buffering in a pipe */
|
||||||
|
#else
|
||||||
|
# define PIPESIZE PIPE_BUF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
MKINIT
|
MKINIT
|
||||||
struct redirtab {
|
struct redirtab {
|
||||||
struct redirtab *next;
|
struct redirtab *next;
|
||||||
int renamed[10];
|
short renamed[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,10 +89,10 @@ MKINIT struct redirtab *redirlist;
|
||||||
* background commands, where we want to redirect fd0 to /dev/null only
|
* background commands, where we want to redirect fd0 to /dev/null only
|
||||||
* if it hasn't already been redirected.
|
* if it hasn't already been redirected.
|
||||||
*/
|
*/
|
||||||
STATIC int fd0_redirected = 0;
|
int fd0_redirected = 0;
|
||||||
|
|
||||||
STATIC void openredirect(union node *, char[10 ]);
|
STATIC void openredirect(union node *, char[10], int);
|
||||||
STATIC int openhere(union node *);
|
STATIC int openhere(const union node *);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,13 +110,15 @@ redirect(union node *redir, int flags)
|
||||||
struct redirtab *sv = NULL;
|
struct redirtab *sv = NULL;
|
||||||
int i;
|
int i;
|
||||||
int fd;
|
int fd;
|
||||||
int try;
|
|
||||||
char memory[10]; /* file descriptors to write to memory */
|
char memory[10]; /* file descriptors to write to memory */
|
||||||
|
|
||||||
for (i = 10 ; --i >= 0 ; )
|
for (i = 10 ; --i >= 0 ; )
|
||||||
memory[i] = 0;
|
memory[i] = 0;
|
||||||
memory[1] = flags & REDIR_BACKQ;
|
memory[1] = flags & REDIR_BACKQ;
|
||||||
if (flags & REDIR_PUSH) {
|
if (flags & REDIR_PUSH) {
|
||||||
|
/* We don't have to worry about REDIR_VFORK here, as
|
||||||
|
* flags & REDIR_PUSH is never true if REDIR_VFORK is set.
|
||||||
|
*/
|
||||||
sv = ckmalloc(sizeof (struct redirtab));
|
sv = ckmalloc(sizeof (struct redirtab));
|
||||||
for (i = 0 ; i < 10 ; i++)
|
for (i = 0 ; i < 10 ; i++)
|
||||||
sv->renamed[i] = EMPTY;
|
sv->renamed[i] = EMPTY;
|
||||||
|
@ -118,38 +127,32 @@ redirect(union node *redir, int flags)
|
||||||
}
|
}
|
||||||
for (n = redir ; n ; n = n->nfile.next) {
|
for (n = redir ; n ; n = n->nfile.next) {
|
||||||
fd = n->nfile.fd;
|
fd = n->nfile.fd;
|
||||||
try = 0;
|
|
||||||
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
||||||
n->ndup.dupfd == fd)
|
n->ndup.dupfd == fd)
|
||||||
continue; /* redirect from/to same file descriptor */
|
continue; /* redirect from/to same file descriptor */
|
||||||
|
|
||||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
again:
|
|
||||||
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EBADF:
|
case EBADF:
|
||||||
if (!try) {
|
i = CLOSED;
|
||||||
openredirect(n, memory);
|
break;
|
||||||
try++;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH*/
|
|
||||||
default:
|
default:
|
||||||
INTON;
|
INTON;
|
||||||
error("%d: %s", fd, strerror(errno));
|
error("%d: %s", fd, strerror(errno));
|
||||||
break;
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
if (!try) {
|
(void)fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||||
sv->renamed[fd] = i;
|
sv->renamed[fd] = i;
|
||||||
}
|
|
||||||
INTON;
|
INTON;
|
||||||
|
} else {
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
if (fd == 0)
|
if (fd == 0)
|
||||||
fd0_redirected++;
|
fd0_redirected++;
|
||||||
if (!try)
|
openredirect(n, memory, flags);
|
||||||
openredirect(n, memory);
|
|
||||||
}
|
}
|
||||||
if (memory[1])
|
if (memory[1])
|
||||||
out1 = &memout;
|
out1 = &memout;
|
||||||
|
@ -159,15 +162,12 @@ again:
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
openredirect(union node *redir, char memory[10])
|
openredirect(union node *redir, char memory[10], int flags)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
|
||||||
int fd = redir->nfile.fd;
|
int fd = redir->nfile.fd;
|
||||||
char *fname;
|
char *fname;
|
||||||
int f;
|
int f;
|
||||||
|
int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
|
||||||
/* Assume redirection succeeds. */
|
|
||||||
{ extern int exitstatus; exitstatus = 0; }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We suppress interrupts so that we won't leave open file
|
* We suppress interrupts so that we won't leave open file
|
||||||
|
@ -179,56 +179,64 @@ openredirect(union node *redir, char memory[10])
|
||||||
switch (redir->nfile.type) {
|
switch (redir->nfile.type) {
|
||||||
case NFROM:
|
case NFROM:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
if ((f = open(fname, O_RDONLY)) < 0)
|
if (flags & REDIR_VFORK)
|
||||||
error("cannot open %s: %s", fname, strerror(errno));
|
eflags = O_NONBLOCK;
|
||||||
movefd:
|
else
|
||||||
if (f != fd) {
|
eflags = 0;
|
||||||
dup2(f, fd);
|
if ((f = open(fname, O_RDONLY|eflags)) < 0)
|
||||||
close(f);
|
goto eopen;
|
||||||
}
|
if (eflags)
|
||||||
|
(void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
|
||||||
break;
|
break;
|
||||||
case NFROMTO:
|
case NFROMTO:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
|
if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||||
error("cannot create %s: %s", fname, strerror(errno));
|
goto ecreate;
|
||||||
goto movefd;
|
break;
|
||||||
case NTO:
|
case NTO:
|
||||||
fname = redir->nfile.expfname;
|
if (Cflag)
|
||||||
if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode))
|
oflags |= O_EXCL;
|
||||||
error("cannot create %s: %s", fname,
|
/* FALLTHROUGH */
|
||||||
strerror(EEXIST));
|
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
|
||||||
error("cannot create %s: %s", fname, strerror(errno));
|
|
||||||
goto movefd;
|
|
||||||
case NCLOBBER:
|
case NCLOBBER:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
if ((f = open(fname, oflags, 0666)) < 0)
|
||||||
error("cannot create %s: %s", fname, strerror(errno));
|
goto ecreate;
|
||||||
goto movefd;
|
break;
|
||||||
case NAPPEND:
|
case NAPPEND:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||||
error("cannot create %s: %s", fname, strerror(errno));
|
goto ecreate;
|
||||||
goto movefd;
|
break;
|
||||||
case NTOFD:
|
case NTOFD:
|
||||||
case NFROMFD:
|
case NFROMFD:
|
||||||
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
|
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
|
||||||
if (memory[redir->ndup.dupfd])
|
if (memory[redir->ndup.dupfd])
|
||||||
memory[fd] = 1;
|
memory[fd] = 1;
|
||||||
else
|
else
|
||||||
dup2(redir->ndup.dupfd, fd);
|
copyfd(redir->ndup.dupfd, fd, 1);
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
break;
|
INTON;
|
||||||
|
return;
|
||||||
case NHERE:
|
case NHERE:
|
||||||
case NXHERE:
|
case NXHERE:
|
||||||
f = openhere(redir);
|
f = openhere(redir);
|
||||||
goto movefd;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f != fd) {
|
||||||
|
copyfd(f, fd, 1);
|
||||||
|
close(f);
|
||||||
|
}
|
||||||
INTON;
|
INTON;
|
||||||
|
return;
|
||||||
|
ecreate:
|
||||||
|
exerrno = 1;
|
||||||
|
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
||||||
|
eopen:
|
||||||
|
exerrno = 1;
|
||||||
|
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,13 +247,13 @@ movefd:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
openhere(union node *redir)
|
openhere(const union node *redir)
|
||||||
{
|
{
|
||||||
int pip[2];
|
int pip[2];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (pipe(pip) < 0)
|
if (pipe(pip) < 0)
|
||||||
error("Pipe call failed: %s", strerror(errno));
|
error("Pipe call failed");
|
||||||
if (redir->type == NHERE) {
|
if (redir->type == NHERE) {
|
||||||
len = strlen(redir->nhere.doc->narg.text);
|
len = strlen(redir->nhere.doc->narg.text);
|
||||||
if (len <= PIPESIZE) {
|
if (len <= PIPESIZE) {
|
||||||
|
@ -253,12 +261,14 @@ openhere(union node *redir)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
|
if (forkshell(NULL, NULL, FORK_NOJOB) == 0) {
|
||||||
close(pip[0]);
|
close(pip[0]);
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGQUIT, SIG_IGN);
|
signal(SIGQUIT, SIG_IGN);
|
||||||
signal(SIGHUP, SIG_IGN);
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
#ifdef SIGTSTP
|
||||||
signal(SIGTSTP, SIG_IGN);
|
signal(SIGTSTP, SIG_IGN);
|
||||||
|
#endif
|
||||||
signal(SIGPIPE, SIG_DFL);
|
signal(SIGPIPE, SIG_DFL);
|
||||||
if (redir->type == NHERE)
|
if (redir->type == NHERE)
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||||
|
@ -287,11 +297,10 @@ popredir(void)
|
||||||
if (rp->renamed[i] != EMPTY) {
|
if (rp->renamed[i] != EMPTY) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
fd0_redirected--;
|
fd0_redirected--;
|
||||||
|
close(i);
|
||||||
if (rp->renamed[i] >= 0) {
|
if (rp->renamed[i] >= 0) {
|
||||||
dup2(rp->renamed[i], i);
|
copyfd(rp->renamed[i], i, 1);
|
||||||
close(rp->renamed[i]);
|
close(rp->renamed[i]);
|
||||||
} else {
|
|
||||||
close(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,15 +324,14 @@ RESET {
|
||||||
}
|
}
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
clearredir();
|
clearredir(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Return true if fd 0 has already been redirected at least once. */
|
/* Return true if fd 0 has already been redirected at least once. */
|
||||||
int
|
int
|
||||||
fd0_redirected_p(void)
|
fd0_redirected_p (void) {
|
||||||
{
|
|
||||||
return fd0_redirected != 0;
|
return fd0_redirected != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +340,7 @@ fd0_redirected_p(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
clearredir(void)
|
clearredir(int vforked)
|
||||||
{
|
{
|
||||||
struct redirtab *rp;
|
struct redirtab *rp;
|
||||||
int i;
|
int i;
|
||||||
|
@ -342,11 +350,34 @@ clearredir(void)
|
||||||
if (rp->renamed[i] >= 0) {
|
if (rp->renamed[i] >= 0) {
|
||||||
close(rp->renamed[i]);
|
close(rp->renamed[i]);
|
||||||
}
|
}
|
||||||
rp->renamed[i] = EMPTY;
|
if (!vforked)
|
||||||
|
rp->renamed[i] = EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
|
* 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(int from, int to, int equal)
|
||||||
|
{
|
||||||
|
int newfd;
|
||||||
|
|
||||||
|
if (equal)
|
||||||
|
newfd = dup2(from, to);
|
||||||
|
else
|
||||||
|
newfd = fcntl(from, F_DUPFD, to);
|
||||||
|
if (newfd < 0) {
|
||||||
|
if (errno == EMFILE)
|
||||||
|
return EMPTY;
|
||||||
|
else
|
||||||
|
error("%d: %s", from, strerror(errno));
|
||||||
|
}
|
||||||
|
return newfd;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: redir.h,v 1.16 2011/02/17 15:13:49 pooka Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,20 +32,17 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/redir.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* flags passed to redirect */
|
/* flags passed to redirect */
|
||||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||||
|
#define REDIR_VFORK 04 /* running under vfork(2), be careful */
|
||||||
|
|
||||||
union node;
|
union node;
|
||||||
void redirect(union node *, int);
|
void redirect(union node *, int);
|
||||||
void popredir(void);
|
void popredir(void);
|
||||||
int fd0_redirected_p(void);
|
int fd0_redirected_p(void);
|
||||||
void clearredir(void);
|
void clearredir(int);
|
||||||
|
int copyfd(int, int, int);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
|
|
||||||
*/
|
|
2002
bin/sh/sh.1
Normal file
2002
bin/sh/sh.1
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: shell.h,v 1.18 2013/04/28 17:01:28 dholland Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,57 +32,58 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h> /* for mode_t */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The follow should be set to reflect the type of system you have:
|
* The follow should be set to reflect the type of system you have:
|
||||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||||
* TILDE -> 1 if you want the shell to expand ~logname.
|
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
||||||
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
|
|
||||||
* READLINE -> 1 if line editing by readline() should be enabled.
|
|
||||||
* define BSD if you are running 4.2 BSD or later.
|
* define BSD if you are running 4.2 BSD or later.
|
||||||
* define SYSV if you are running under System V.
|
* define SYSV if you are running under System V.
|
||||||
* define DEBUG=1 to compile in debugging (set global "debug" to turn on)
|
* define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
|
||||||
* define DEBUG=2 to compile in and turn on debugging.
|
* define DEBUG=2 to compile in and turn on debugging.
|
||||||
|
* define DO_SHAREDVFORK to indicate that vfork(2) shares its address
|
||||||
|
* with its parent.
|
||||||
*
|
*
|
||||||
* When debugging is on, debugging info will be written to $HOME/trace and
|
* When debugging is on, debugging info will be written to ./trace and
|
||||||
* a quit signal will generate a core dump.
|
* a quit signal will generate a core dump.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JOBS
|
#include <sys/param.h>
|
||||||
#define JOBS 1
|
|
||||||
#endif
|
#if defined(__minix)
|
||||||
|
#define JOBS 0
|
||||||
|
#else
|
||||||
|
#define JOBS 1
|
||||||
|
#endif /* defined(__minix) */
|
||||||
#ifndef BSD
|
#ifndef BSD
|
||||||
#define BSD 1
|
#define BSD 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG 0
|
|
||||||
#endif
|
|
||||||
#define POSIX 1
|
|
||||||
|
|
||||||
/*
|
#ifndef DO_SHAREDVFORK
|
||||||
* Type of used arithmetics. SUSv3 requires us to have at least signed long.
|
#if !defined(__minix)
|
||||||
*/
|
#if __NetBSD_Version__ >= 104000000
|
||||||
typedef long arith_t;
|
#define DO_SHAREDVFORK
|
||||||
#define ARITH_FORMAT_STR "%ld"
|
#endif
|
||||||
#define atoarith_t(arg) strtol(arg, NULL, 0)
|
#endif /* !defined(__minix) */
|
||||||
#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
|
#endif
|
||||||
|
|
||||||
typedef void *pointer;
|
typedef void *pointer;
|
||||||
#define STATIC static
|
#ifndef NULL
|
||||||
#define MKINIT /* empty */
|
#define NULL (void *)0
|
||||||
|
#endif
|
||||||
|
#define STATIC /* empty */
|
||||||
|
#define MKINIT /* empty */
|
||||||
|
|
||||||
extern char nullstr[1]; /* null string */
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
#if DEBUG
|
extern const char nullstr[1]; /* null string */
|
||||||
#define TRACE(param) sh_trace param
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define TRACE(param) trace param
|
||||||
|
#define TRACEV(param) tracev param
|
||||||
#else
|
#else
|
||||||
#define TRACE(param)
|
#define TRACE(param)
|
||||||
|
#define TRACEV(param)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: shell.h,v 1.7 2006/05/22 12:47:00 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: show.c,v 1.28 2011/08/23 10:01:32 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,39 +32,37 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: show.c,v 1.28 2011/08/23 10:01:32 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/show.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <errno.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "show.h"
|
#include "show.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
static void trputc(int c);
|
#ifdef DEBUG
|
||||||
static void shtree(union node *, int, char *, FILE*);
|
static void shtree(union node *, int, char *, FILE*);
|
||||||
static void shcmd(union node *, FILE *);
|
static void shcmd(union node *, FILE *);
|
||||||
static void sharg(union node *, FILE *);
|
static void sharg(union node *, FILE *);
|
||||||
static void indent(int, char *, FILE *);
|
static void indent(int, char *, FILE *);
|
||||||
static void trstring(char *);
|
static void trstring(char *);
|
||||||
static void showtree(union node *n);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
showtree(union node *n)
|
showtree(union node *n)
|
||||||
{
|
{
|
||||||
trputs("showtree called\n");
|
trputs("showtree called\n");
|
||||||
|
@ -74,7 +74,7 @@ static void
|
||||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||||
{
|
{
|
||||||
struct nodelist *lp;
|
struct nodelist *lp;
|
||||||
char *s;
|
const char *s;
|
||||||
|
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -126,7 +126,7 @@ shcmd(union node *cmd, FILE *fp)
|
||||||
{
|
{
|
||||||
union node *np;
|
union node *np;
|
||||||
int first;
|
int first;
|
||||||
char *s;
|
const char *s;
|
||||||
int dftfd;
|
int dftfd;
|
||||||
|
|
||||||
first = 1;
|
first = 1;
|
||||||
|
@ -141,22 +141,19 @@ shcmd(union node *cmd, FILE *fp)
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
switch (np->nfile.type) {
|
switch (np->nfile.type) {
|
||||||
case NTO: s = ">"; dftfd = 1; break;
|
case NTO: s = ">"; dftfd = 1; break;
|
||||||
|
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
||||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||||
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
|
||||||
case NFROM: s = "<"; dftfd = 0; break;
|
case NFROM: s = "<"; dftfd = 0; break;
|
||||||
case NFROMTO: s = "<>"; dftfd = 0; break;
|
|
||||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
case NFROMFD: s = "<&"; dftfd = 0; break;
|
||||||
|
case NFROMTO: s = "<>"; dftfd = 0; break;
|
||||||
default: s = "*error*"; dftfd = 0; break;
|
default: s = "*error*"; dftfd = 0; break;
|
||||||
}
|
}
|
||||||
if (np->nfile.fd != dftfd)
|
if (np->nfile.fd != dftfd)
|
||||||
fprintf(fp, "%d", np->nfile.fd);
|
fprintf(fp, "%d", np->nfile.fd);
|
||||||
fputs(s, fp);
|
fputs(s, fp);
|
||||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
||||||
if (np->ndup.dupfd >= 0)
|
fprintf(fp, "%d", np->ndup.dupfd);
|
||||||
fprintf(fp, "%d", np->ndup.dupfd);
|
|
||||||
else
|
|
||||||
fprintf(fp, "-");
|
|
||||||
} else {
|
} else {
|
||||||
sharg(np->nfile.fname, fp);
|
sharg(np->nfile.fname, fp);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +172,6 @@ sharg(union node *arg, FILE *fp)
|
||||||
|
|
||||||
if (arg->type != NARG) {
|
if (arg->type != NARG) {
|
||||||
printf("<node type %d>\n", arg->type);
|
printf("<node type %d>\n", arg->type);
|
||||||
fflush(stdout);
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
bqlist = arg->narg.backquote;
|
bqlist = arg->narg.backquote;
|
||||||
|
@ -262,6 +258,8 @@ indent(int amount, char *pfx, FILE *fp)
|
||||||
putc('\t', fp);
|
putc('\t', fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -271,46 +269,52 @@ indent(int amount, char *pfx, FILE *fp)
|
||||||
|
|
||||||
FILE *tracefile;
|
FILE *tracefile;
|
||||||
|
|
||||||
#if DEBUG == 2
|
|
||||||
int debug = 1;
|
|
||||||
#else
|
|
||||||
int debug = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
static void
|
void
|
||||||
trputc(int c)
|
trputc(int c)
|
||||||
{
|
{
|
||||||
if (tracefile == NULL)
|
if (debug != 1 || !tracefile)
|
||||||
return;
|
return;
|
||||||
putc(c, tracefile);
|
putc(c, tracefile);
|
||||||
if (c == '\n')
|
|
||||||
fflush(tracefile);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
sh_trace(const char *fmt, ...)
|
trace(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
va_list va;
|
va_list va;
|
||||||
|
|
||||||
|
if (debug != 1 || !tracefile)
|
||||||
|
return;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
if (tracefile != NULL) {
|
(void) vfprintf(tracefile, fmt, va);
|
||||||
(void) vfprintf(tracefile, fmt, va);
|
|
||||||
if (strchr(fmt, '\n'))
|
|
||||||
(void) fflush(tracefile);
|
|
||||||
}
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tracev(const char *fmt, va_list va)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
va_list ap;
|
||||||
|
if (debug != 1 || !tracefile)
|
||||||
|
return;
|
||||||
|
va_copy(ap, va);
|
||||||
|
(void) vfprintf(tracefile, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
trputs(char *s)
|
trputs(const char *s)
|
||||||
{
|
{
|
||||||
if (tracefile == NULL)
|
if (debug != 1 || !tracefile)
|
||||||
return;
|
return;
|
||||||
fputs(s, tracefile);
|
fputs(s, tracefile);
|
||||||
if (strchr(s, '\n'))
|
|
||||||
fflush(tracefile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,7 +324,7 @@ trstring(char *s)
|
||||||
char *p;
|
char *p;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (tracefile == NULL)
|
if (debug != 1 || !tracefile)
|
||||||
return;
|
return;
|
||||||
putc('"', tracefile);
|
putc('"', tracefile);
|
||||||
for (p = s ; *p ; p++) {
|
for (p = s ; *p ; p++) {
|
||||||
|
@ -352,12 +356,14 @@ backslash: putc('\\', tracefile);
|
||||||
}
|
}
|
||||||
putc('"', tracefile);
|
putc('"', tracefile);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
trargs(char **ap)
|
trargs(char **ap)
|
||||||
{
|
{
|
||||||
if (tracefile == NULL)
|
#ifdef DEBUG
|
||||||
|
if (debug != 1 || !tracefile)
|
||||||
return;
|
return;
|
||||||
while (*ap) {
|
while (*ap) {
|
||||||
trstring(*ap++);
|
trstring(*ap++);
|
||||||
|
@ -366,18 +372,25 @@ trargs(char **ap)
|
||||||
else
|
else
|
||||||
putc('\n', tracefile);
|
putc('\n', tracefile);
|
||||||
}
|
}
|
||||||
fflush(tracefile);
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
opentrace(void)
|
opentrace(void)
|
||||||
{
|
{
|
||||||
char s[100];
|
char s[100];
|
||||||
|
#ifdef O_APPEND
|
||||||
int flags;
|
int flags;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!debug)
|
if (debug != 1) {
|
||||||
|
if (tracefile)
|
||||||
|
fflush(tracefile);
|
||||||
|
/* leave open because libedit might be using it */
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#ifdef not_this_way
|
#ifdef not_this_way
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -391,19 +404,27 @@ opentrace(void)
|
||||||
strcat(s, "/trace");
|
strcat(s, "/trace");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
scopy("./trace", s);
|
snprintf(s, sizeof(s), "./trace.%d", (int)getpid());
|
||||||
#endif /* not_this_way */
|
#endif /* not_this_way */
|
||||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
if (tracefile) {
|
||||||
fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
|
if (!freopen(s, "a", tracefile)) {
|
||||||
return;
|
fprintf(stderr, "Can't re-open %s\n", s);
|
||||||
|
tracefile = NULL;
|
||||||
|
debug = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||||
|
fprintf(stderr, "Can't open %s\n", s);
|
||||||
|
debug = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef O_APPEND
|
||||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||||
|
#endif
|
||||||
|
setlinebuf(tracefile);
|
||||||
fputs("\nTracing started.\n", tracefile);
|
fputs("\nTracing started.\n", tracefile);
|
||||||
fflush(tracefile);
|
|
||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: show.c,v 1.6 2006/05/22 12:27:51 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1995
|
* Copyright (c) 1995
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -10,7 +12,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -27,16 +29,17 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/show.h,v 1.11 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef DEBUG
|
#include <stdarg.h>
|
||||||
void sh_trace(const char *, ...);
|
|
||||||
|
union node;
|
||||||
|
void showtree(union node *);
|
||||||
|
void trace(const char *, ...);
|
||||||
|
void tracev(const char *, va_list);
|
||||||
void trargs(char **);
|
void trargs(char **);
|
||||||
void trputs(char *);
|
#ifdef DEBUG
|
||||||
|
void trputc(int);
|
||||||
|
void trputs(const char *);
|
||||||
void opentrace(void);
|
void opentrace(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: show.h,v 1.4 2006/03/29 13:28:45 philip Exp $
|
|
||||||
*/
|
|
105
bin/sh/syntax.c
Normal file
105
bin/sh/syntax.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* $NetBSD: syntax.c,v 1.3 2012/03/28 20:11:25 christos Exp $ */
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__RCSID("$NetBSD: syntax.c,v 1.3 2012/03/28 20:11:25 christos Exp $");
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include "shell.h"
|
||||||
|
#include "syntax.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
#if CWORD != 0
|
||||||
|
#error initialisation assumes 'CWORD' is zero
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ndx(ch) (ch + 1 - CHAR_MIN)
|
||||||
|
#define set(ch, val) [ndx(ch)] = val,
|
||||||
|
#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
|
||||||
|
|
||||||
|
/* syntax table used when not in quotes */
|
||||||
|
const char basesyntax[257] = { CEOF,
|
||||||
|
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||||
|
set('\n', CNL)
|
||||||
|
set('\\', CBACK)
|
||||||
|
set('\'', CSQUOTE)
|
||||||
|
set('"', CDQUOTE)
|
||||||
|
set('`', CBQUOTE)
|
||||||
|
set('$', CVAR)
|
||||||
|
set('}', CENDVAR)
|
||||||
|
set('<', CSPCL)
|
||||||
|
set('>', CSPCL)
|
||||||
|
set('(', CSPCL)
|
||||||
|
set(')', CSPCL)
|
||||||
|
set(';', CSPCL)
|
||||||
|
set('&', CSPCL)
|
||||||
|
set('|', CSPCL)
|
||||||
|
set(' ', CSPCL)
|
||||||
|
set('\t', CSPCL)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* syntax table used when in double quotes */
|
||||||
|
const char dqsyntax[257] = { CEOF,
|
||||||
|
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||||
|
set('\n', CNL)
|
||||||
|
set('\\', CBACK)
|
||||||
|
set('"', CDQUOTE)
|
||||||
|
set('`', CBQUOTE)
|
||||||
|
set('$', CVAR)
|
||||||
|
set('}', CENDVAR)
|
||||||
|
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||||
|
set('!', CCTL)
|
||||||
|
set('*', CCTL)
|
||||||
|
set('?', CCTL)
|
||||||
|
set('[', CCTL)
|
||||||
|
set('=', CCTL)
|
||||||
|
set('~', CCTL)
|
||||||
|
set(':', CCTL)
|
||||||
|
set('/', CCTL)
|
||||||
|
set('-', CCTL)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* syntax table used when in single quotes */
|
||||||
|
const char sqsyntax[257] = { CEOF,
|
||||||
|
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||||
|
set('\n', CNL)
|
||||||
|
set('\'', CSQUOTE)
|
||||||
|
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||||
|
set('!', CCTL)
|
||||||
|
set('*', CCTL)
|
||||||
|
set('?', CCTL)
|
||||||
|
set('[', CCTL)
|
||||||
|
set('=', CCTL)
|
||||||
|
set('~', CCTL)
|
||||||
|
set(':', CCTL)
|
||||||
|
set('/', CCTL)
|
||||||
|
set('-', CCTL)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* syntax table used when in arithmetic */
|
||||||
|
const char arisyntax[257] = { CEOF,
|
||||||
|
set_range(CTL_FIRST, CTL_LAST, CCTL)
|
||||||
|
set('\n', CNL)
|
||||||
|
set('\\', CBACK)
|
||||||
|
set('`', CBQUOTE)
|
||||||
|
set('\'', CSQUOTE)
|
||||||
|
set('"', CDQUOTE)
|
||||||
|
set('$', CVAR)
|
||||||
|
set('}', CENDVAR)
|
||||||
|
set('(', CLP)
|
||||||
|
set(')', CRP)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* character classification table */
|
||||||
|
const char is_type[257] = { 0,
|
||||||
|
set_range('0', '9', ISDIGIT)
|
||||||
|
set_range('a', 'z', ISLOWER)
|
||||||
|
set_range('A', 'Z', ISUPPER)
|
||||||
|
set('_', ISUNDER)
|
||||||
|
set('#', ISSPECL)
|
||||||
|
set('?', ISSPECL)
|
||||||
|
set('$', ISSPECL)
|
||||||
|
set('!', ISSPECL)
|
||||||
|
set('-', ISSPECL)
|
||||||
|
set('*', ISSPECL)
|
||||||
|
set('@', ISSPECL)
|
||||||
|
};
|
83
bin/sh/syntax.h
Normal file
83
bin/sh/syntax.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* $NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl 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. 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>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* Syntax classes */
|
||||||
|
#define CWORD 0 /* character is nothing special */
|
||||||
|
#define CNL 1 /* newline character */
|
||||||
|
#define CBACK 2 /* a backslash character */
|
||||||
|
#define CSQUOTE 3 /* single quote */
|
||||||
|
#define CDQUOTE 4 /* double quote */
|
||||||
|
#define CBQUOTE 5 /* backwards single quote */
|
||||||
|
#define CVAR 6 /* a dollar sign */
|
||||||
|
#define CENDVAR 7 /* a '}' character */
|
||||||
|
#define CLP 8 /* a left paren in arithmetic */
|
||||||
|
#define CRP 9 /* a right paren in arithmetic */
|
||||||
|
#define CEOF 10 /* end of file */
|
||||||
|
#define CCTL 11 /* like CWORD, except it must be escaped */
|
||||||
|
#define CSPCL 12 /* these terminate a word */
|
||||||
|
|
||||||
|
/* Syntax classes for is_ functions */
|
||||||
|
#define ISDIGIT 01 /* a digit */
|
||||||
|
#define ISUPPER 02 /* an upper case letter */
|
||||||
|
#define ISLOWER 04 /* a lower case letter */
|
||||||
|
#define ISUNDER 010 /* an underscore */
|
||||||
|
#define ISSPECL 020 /* the name of a special parameter */
|
||||||
|
|
||||||
|
#define PEOF (CHAR_MIN - 1)
|
||||||
|
#define SYNBASE (-PEOF)
|
||||||
|
/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
|
||||||
|
#define UPEOF ((char)PEOF)
|
||||||
|
|
||||||
|
|
||||||
|
#define BASESYNTAX (basesyntax + SYNBASE)
|
||||||
|
#define DQSYNTAX (dqsyntax + SYNBASE)
|
||||||
|
#define SQSYNTAX (sqsyntax + SYNBASE)
|
||||||
|
#define ARISYNTAX (arisyntax + SYNBASE)
|
||||||
|
|
||||||
|
/* These defines assume that the digits are contiguous */
|
||||||
|
#define is_digit(c) ((unsigned)((c) - '0') <= 9)
|
||||||
|
#define is_alpha(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
|
||||||
|
#define is_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
|
||||||
|
#define is_in_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
|
||||||
|
#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
|
||||||
|
#define digit_val(c) ((c) - '0')
|
||||||
|
|
||||||
|
extern const char basesyntax[];
|
||||||
|
extern const char dqsyntax[];
|
||||||
|
extern const char sqsyntax[];
|
||||||
|
extern const char arisyntax[];
|
||||||
|
extern const char is_type[];
|
475
bin/sh/trap.c
Normal file
475
bin/sh/trap.c
Normal file
|
@ -0,0 +1,475 @@
|
||||||
|
/* $NetBSD: trap.c,v 1.35 2011/06/18 21:18:46 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. 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.35 2011/06/18 21:18:46 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 "builtins.h"
|
||||||
|
#include "syntax.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "trap.h"
|
||||||
|
#include "mystring.h"
|
||||||
|
#include "var.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 */
|
||||||
|
|
||||||
|
|
||||||
|
char *trap[NSIG+1]; /* trap handler commands */
|
||||||
|
MKINIT char sigmode[NSIG]; /* current value of signal */
|
||||||
|
volatile char gotsig[NSIG]; /* indicates specified signal received */
|
||||||
|
int pendingsigs; /* indicates some signal received */
|
||||||
|
|
||||||
|
static int getsigaction(int, sig_t *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the signal number described by `p' (as a number or a name)
|
||||||
|
* or -1 if it isn't one
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
signame_to_signum(const char *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (is_number(p))
|
||||||
|
return number(p);
|
||||||
|
|
||||||
|
if (strcasecmp(p, "exit") == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strncasecmp(p, "sig", 3) == 0)
|
||||||
|
p += 3;
|
||||||
|
|
||||||
|
for (i = 0; i < NSIG; ++i)
|
||||||
|
if (strcasecmp (p, sys_signame[i]) == 0)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a list of valid signal names
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
printsignals(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
out1str("EXIT ");
|
||||||
|
|
||||||
|
for (n = 1; n < NSIG; n++) {
|
||||||
|
out1fmt("%s", sys_signame[n]);
|
||||||
|
if ((n == NSIG/2) || n == (NSIG - 1))
|
||||||
|
out1str("\n");
|
||||||
|
else
|
||||||
|
out1c(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The trap builtin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
trapcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *action;
|
||||||
|
char **ap;
|
||||||
|
int signo;
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
for (signo = 0 ; signo <= NSIG ; signo++)
|
||||||
|
if (trap[signo] != NULL) {
|
||||||
|
out1fmt("trap -- ");
|
||||||
|
print_quoted(trap[signo]);
|
||||||
|
out1fmt(" %s\n",
|
||||||
|
(signo) ? sys_signame[signo] : "EXIT");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ap = argv + 1;
|
||||||
|
|
||||||
|
action = NULL;
|
||||||
|
|
||||||
|
if (strcmp(*ap, "--") == 0)
|
||||||
|
if (*++ap == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (signame_to_signum(*ap) == -1) {
|
||||||
|
if ((*ap)[0] == '-') {
|
||||||
|
if ((*ap)[1] == '\0')
|
||||||
|
ap++;
|
||||||
|
else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
|
||||||
|
printsignals();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("bad option %s\n", *ap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
action = *ap++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*ap) {
|
||||||
|
if (is_number(*ap))
|
||||||
|
signo = number(*ap);
|
||||||
|
else
|
||||||
|
signo = signame_to_signum(*ap);
|
||||||
|
|
||||||
|
if (signo < 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, 0);
|
||||||
|
INTON;
|
||||||
|
ap++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear traps on a fork or vfork.
|
||||||
|
* Takes one arg vfork, to tell it to not be destructive of
|
||||||
|
* the parents variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_traps(int vforked)
|
||||||
|
{
|
||||||
|
char **tp;
|
||||||
|
|
||||||
|
for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
|
||||||
|
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||||
|
INTOFF;
|
||||||
|
if (!vforked) {
|
||||||
|
ckfree(*tp);
|
||||||
|
*tp = NULL;
|
||||||
|
}
|
||||||
|
if (tp != &trap[0])
|
||||||
|
setsignal(tp - trap, vforked);
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the signal handler for the specified signal. The routine figures
|
||||||
|
* out what it should be set to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sig_t
|
||||||
|
setsignal(int signo, int vforked)
|
||||||
|
{
|
||||||
|
int action;
|
||||||
|
sig_t sigact = SIG_DFL, sig;
|
||||||
|
char *t, tsig;
|
||||||
|
|
||||||
|
if ((t = trap[signo]) == NULL)
|
||||||
|
action = S_DFL;
|
||||||
|
else if (*t != '\0')
|
||||||
|
action = S_CATCH;
|
||||||
|
else
|
||||||
|
action = S_IGN;
|
||||||
|
if (rootshell && !vforked && action == S_DFL) {
|
||||||
|
switch (signo) {
|
||||||
|
case SIGINT:
|
||||||
|
if (iflag || minusc || sflag == 0)
|
||||||
|
action = S_CATCH;
|
||||||
|
break;
|
||||||
|
case SIGQUIT:
|
||||||
|
#ifdef 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];
|
||||||
|
tsig = *t;
|
||||||
|
if (tsig == 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) {
|
||||||
|
/*
|
||||||
|
* POSIX 3.14.13 states that non-interactive shells
|
||||||
|
* should ignore trap commands for signals that were
|
||||||
|
* ignored upon entry, and leaves the behavior
|
||||||
|
* unspecified for interactive shells. On interactive
|
||||||
|
* shells, or if job control is on, and we have a job
|
||||||
|
* control related signal, we allow the trap to work.
|
||||||
|
*
|
||||||
|
* This change allows us to be POSIX compliant, and
|
||||||
|
* at the same time override the default behavior if
|
||||||
|
* we need to by setting the interactive flag.
|
||||||
|
*/
|
||||||
|
if ((mflag && (signo == SIGTSTP ||
|
||||||
|
signo == SIGTTIN || signo == SIGTTOU)) || iflag) {
|
||||||
|
tsig = S_IGN;
|
||||||
|
} else
|
||||||
|
tsig = S_HARD_IGN;
|
||||||
|
} else {
|
||||||
|
tsig = S_RESET; /* force to be set */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tsig == S_HARD_IGN || tsig == 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;
|
||||||
|
}
|
||||||
|
sig = signal(signo, sigact);
|
||||||
|
if (sig != SIG_ERR) {
|
||||||
|
sigset_t ss;
|
||||||
|
if (!vforked)
|
||||||
|
*t = action;
|
||||||
|
if (action == S_CATCH)
|
||||||
|
(void)siginterrupt(signo, 1);
|
||||||
|
/*
|
||||||
|
* If our parent accidentally blocked signals for
|
||||||
|
* us make sure we unblock them
|
||||||
|
*/
|
||||||
|
(void)sigemptyset(&ss);
|
||||||
|
(void)sigaddset(&ss, signo);
|
||||||
|
(void)sigprocmask(SIG_UNBLOCK, &ss, NULL);
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the current setting for sig w/o changing it.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getsigaction(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(int signo, int vforked)
|
||||||
|
{
|
||||||
|
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
|
||||||
|
signal(signo, SIG_IGN);
|
||||||
|
}
|
||||||
|
if (!vforked)
|
||||||
|
sigmode[signo - 1] = S_HARD_IGN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef mkinit
|
||||||
|
INCLUDE <signal.h>
|
||||||
|
INCLUDE "trap.h"
|
||||||
|
|
||||||
|
SHELLPROC {
|
||||||
|
char *sm;
|
||||||
|
|
||||||
|
clear_traps(0);
|
||||||
|
for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
|
||||||
|
if (*sm == S_IGN)
|
||||||
|
*sm = S_HARD_IGN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
onsig(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(void)
|
||||||
|
{
|
||||||
|
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], 0);
|
||||||
|
exitstatus=savestatus;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
pendingsigs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controls whether the shell is interactive or not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
setinteractive(int on)
|
||||||
|
{
|
||||||
|
static int is_interactive;
|
||||||
|
|
||||||
|
if (on == is_interactive)
|
||||||
|
return;
|
||||||
|
setsignal(SIGINT, 0);
|
||||||
|
setsignal(SIGQUIT, 0);
|
||||||
|
setsignal(SIGTERM, 0);
|
||||||
|
is_interactive = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to exit the shell.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
exitshell(int status)
|
||||||
|
{
|
||||||
|
struct jmploc loc1, loc2;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
|
||||||
|
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, 0);
|
||||||
|
}
|
||||||
|
l1: handler = &loc2; /* probably unnecessary */
|
||||||
|
flushall();
|
||||||
|
#if JOBS
|
||||||
|
setjobctl(0);
|
||||||
|
#endif
|
||||||
|
l2: _exit(status);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: trap.h,v 1.20 2012/03/15 02:02:20 joerg Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,23 +32,14 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||||
* $FreeBSD: src/bin/sh/trap.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int pendingsigs;
|
extern int pendingsigs;
|
||||||
extern int in_dotrap;
|
|
||||||
extern int is_interactive;
|
|
||||||
extern volatile sig_atomic_t gotwinch;
|
|
||||||
|
|
||||||
int trapcmd(int, char **);
|
void clear_traps(int);
|
||||||
void clear_traps(void);
|
sig_t setsignal(int, int);
|
||||||
void setsignal(int);
|
void ignoresig(int, int);
|
||||||
void ignoresig(int);
|
void onsig(int);
|
||||||
void dotrap(void);
|
void dotrap(void);
|
||||||
void setinteractive(int);
|
void setinteractive(int);
|
||||||
void exitshell(int);
|
void exitshell(int) __dead;
|
||||||
char *strsiglist(int);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: var.c,v 1.43 2013/11/01 16:49:02 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,28 +32,25 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: var.c,v 1.43 2013/11/01 16:49:02 christos Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
#include <sys/cdefs.h>
|
|
||||||
/*
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef NO_PATHS_H
|
#include <string.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
#include <limits.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shell variables.
|
* Shell variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <locale.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
|
@ -60,49 +59,57 @@ __FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "builtins.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#if !defined(NO_HISTORY)
|
#include "show.h"
|
||||||
|
#ifndef SMALL
|
||||||
#include "myhistedit.h"
|
#include "myhistedit.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "builtins.h"
|
#ifdef SMALL
|
||||||
|
|
||||||
#ifndef _PATH_DEFPATH
|
|
||||||
#define _PATH_DEFPATH "/usr/bin:/bin"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VTABSIZE 39
|
#define VTABSIZE 39
|
||||||
|
#else
|
||||||
|
#define VTABSIZE 517
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct varinit {
|
struct varinit {
|
||||||
struct var *var;
|
struct var *var;
|
||||||
int flags;
|
int flags;
|
||||||
char *text;
|
const char *text;
|
||||||
void (*func)(const char *);
|
void (*func)(const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct localvar *localvars;
|
||||||
|
|
||||||
#ifndef NO_HISTORY
|
#if ATTY
|
||||||
|
struct var vatty;
|
||||||
|
#endif
|
||||||
|
#ifndef SMALL
|
||||||
struct var vhistsize;
|
struct var vhistsize;
|
||||||
|
struct var vterm;
|
||||||
#endif
|
#endif
|
||||||
struct var vifs;
|
struct var vifs;
|
||||||
struct var vmail;
|
struct var vmail;
|
||||||
struct var vmpath;
|
struct var vmpath;
|
||||||
struct var vpath;
|
struct var vpath;
|
||||||
struct var vppid;
|
|
||||||
struct var vps1;
|
struct var vps1;
|
||||||
struct var vps2;
|
struct var vps2;
|
||||||
struct var vpse;
|
struct var vps4;
|
||||||
struct var vvers;
|
struct var vvers;
|
||||||
STATIC struct var voptind;
|
struct var voptind;
|
||||||
|
|
||||||
STATIC const struct varinit varinit[] = {
|
const struct varinit varinit[] = {
|
||||||
#if !defined(NO_HISTORY)
|
#if ATTY
|
||||||
|
{ &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
|
||||||
|
NULL },
|
||||||
|
#endif
|
||||||
|
#ifndef SMALL
|
||||||
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||||
sethistsize },
|
sethistsize },
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,26 +121,27 @@ STATIC const struct varinit varinit[] = {
|
||||||
NULL },
|
NULL },
|
||||||
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
||||||
changepath },
|
changepath },
|
||||||
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
|
|
||||||
NULL },
|
|
||||||
/*
|
/*
|
||||||
* vps1 depends on uid
|
* vps1 depends on uid
|
||||||
*/
|
*/
|
||||||
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||||
NULL },
|
NULL },
|
||||||
{ &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
|
{ &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ",
|
||||||
NULL },
|
NULL },
|
||||||
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
|
#ifndef SMALL
|
||||||
|
{ &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=",
|
||||||
|
setterm },
|
||||||
|
#endif
|
||||||
|
{ &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1",
|
||||||
getoptsreset },
|
getoptsreset },
|
||||||
{ NULL, 0, NULL,
|
{ NULL, 0, NULL,
|
||||||
NULL }
|
NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC struct var *vartab[VTABSIZE];
|
struct var *vartab[VTABSIZE];
|
||||||
|
|
||||||
STATIC struct var **hashvar(char *);
|
STATIC int strequal(const char *, const char *);
|
||||||
STATIC int varequal(char *, char *);
|
STATIC struct var *find_var(const char *, struct var ***, int *);
|
||||||
STATIC int localevar(char *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the varable symbol tables and import the environment
|
* Initialize the varable symbol tables and import the environment
|
||||||
|
@ -141,9 +149,9 @@ STATIC int localevar(char *);
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
INCLUDE "var.h"
|
INCLUDE "var.h"
|
||||||
|
MKINIT char **environ;
|
||||||
INIT {
|
INIT {
|
||||||
char **envp;
|
char **envp;
|
||||||
extern char **environ;
|
|
||||||
|
|
||||||
initvar();
|
initvar();
|
||||||
for (envp = environ ; *envp ; envp++) {
|
for (envp = environ ; *envp ; envp++) {
|
||||||
|
@ -163,35 +171,28 @@ INIT {
|
||||||
void
|
void
|
||||||
initvar(void)
|
initvar(void)
|
||||||
{
|
{
|
||||||
char ppid[20];
|
|
||||||
const struct varinit *ip;
|
const struct varinit *ip;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
|
|
||||||
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
|
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
|
||||||
if ((vp->flags & VEXPORT) == 0) {
|
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
|
||||||
vpp = hashvar(ip->text);
|
continue;
|
||||||
vp->next = *vpp;
|
vp->next = *vpp;
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
vp->text = ip->text;
|
vp->text = strdup(ip->text);
|
||||||
vp->flags = ip->flags;
|
vp->flags = ip->flags;
|
||||||
vp->func = ip->func;
|
vp->func = ip->func;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* PS1 depends on uid
|
* PS1 depends on uid
|
||||||
*/
|
*/
|
||||||
if ((vps1.flags & VEXPORT) == 0) {
|
if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
|
||||||
vpp = hashvar("PS1=");
|
|
||||||
vps1.next = *vpp;
|
vps1.next = *vpp;
|
||||||
*vpp = &vps1;
|
*vpp = &vps1;
|
||||||
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
|
vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
|
||||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||||
}
|
}
|
||||||
if ((vppid.flags & VEXPORT) == 0) {
|
|
||||||
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
|
|
||||||
setvarsafe("PPID", ppid, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,15 +200,11 @@ initvar(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
setvarsafe(char *name, char *val, int flags)
|
setvarsafe(const char *name, const char *val, int flags)
|
||||||
{
|
{
|
||||||
struct jmploc jmploc;
|
struct jmploc jmploc;
|
||||||
struct jmploc *volatile savehandler = handler;
|
struct jmploc *volatile savehandler = handler;
|
||||||
int err = 0;
|
int volatile err = 0;
|
||||||
#if __GNUC__
|
|
||||||
/* Avoid longjmp clobbering */
|
|
||||||
(void) &err;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (setjmp(jmploc.loc))
|
if (setjmp(jmploc.loc))
|
||||||
err = 1;
|
err = 1;
|
||||||
|
@ -220,14 +217,16 @@ setvarsafe(char *name, char *val, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the value of a variable. The flags argument is tored with the
|
* 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.
|
* flags of the variable. If val is NULL, the variable is unset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setvar(char *name, char *val, int flags)
|
setvar(const char *name, const char *val, int flags)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
const char *p;
|
||||||
|
const char *q;
|
||||||
|
char *d;
|
||||||
int len;
|
int len;
|
||||||
int namelen;
|
int namelen;
|
||||||
char *nameeq;
|
char *nameeq;
|
||||||
|
@ -255,37 +254,18 @@ setvar(char *name, char *val, int flags)
|
||||||
} else {
|
} else {
|
||||||
len += strlen(val);
|
len += strlen(val);
|
||||||
}
|
}
|
||||||
p = nameeq = ckmalloc(len);
|
d = nameeq = ckmalloc(len);
|
||||||
q = name;
|
q = name;
|
||||||
while (--namelen >= 0)
|
while (--namelen >= 0)
|
||||||
*p++ = *q++;
|
*d++ = *q++;
|
||||||
*p++ = '=';
|
*d++ = '=';
|
||||||
*p = '\0';
|
*d = '\0';
|
||||||
if (val)
|
if (val)
|
||||||
scopy(val, p);
|
scopy(val, d);
|
||||||
setvareq(nameeq, flags);
|
setvareq(nameeq, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
|
||||||
localevar(char *s)
|
|
||||||
{
|
|
||||||
static char *lnames[7] = {
|
|
||||||
"ALL", "COLLATE", "CTYPE", "MONETARY",
|
|
||||||
"NUMERIC", "TIME", NULL
|
|
||||||
};
|
|
||||||
char **ss;
|
|
||||||
|
|
||||||
if (*s != 'L')
|
|
||||||
return 0;
|
|
||||||
if (varequal(s + 1, "ANG"))
|
|
||||||
return 1;
|
|
||||||
if (strncmp(s + 1, "C_", 2) != 0)
|
|
||||||
return 0;
|
|
||||||
for (ss = lnames; *ss ; ss++)
|
|
||||||
if (varequal(s + 3, *ss))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Same as setvar except that the variable and value are passed in
|
* Same as setvar except that the variable and value are passed in
|
||||||
|
@ -298,56 +278,47 @@ void
|
||||||
setvareq(char *s, int flags)
|
setvareq(char *s, int flags)
|
||||||
{
|
{
|
||||||
struct var *vp, **vpp;
|
struct var *vp, **vpp;
|
||||||
int len;
|
int nlen;
|
||||||
|
|
||||||
if (aflag)
|
if (aflag)
|
||||||
flags |= VEXPORT;
|
flags |= VEXPORT;
|
||||||
vpp = hashvar(s);
|
vp = find_var(s, &vpp, &nlen);
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
if (vp != NULL) {
|
||||||
if (varequal(s, vp->text)) {
|
if (vp->flags & VREADONLY)
|
||||||
if (vp->flags & VREADONLY) {
|
error("%.*s: is read only", vp->name_len, s);
|
||||||
len = strchr(s, '=') - s;
|
if (flags & VNOSET)
|
||||||
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);
|
|
||||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
|
||||||
putenv(s);
|
|
||||||
(void) setlocale(LC_ALL, "");
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
return;
|
return;
|
||||||
}
|
INTOFF;
|
||||||
|
|
||||||
|
if (vp->func && (flags & VNOFUNC) == 0)
|
||||||
|
(*vp->func)(s + vp->name_len + 1);
|
||||||
|
|
||||||
|
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||||
|
ckfree(vp->text);
|
||||||
|
|
||||||
|
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||||
|
vp->flags |= flags & ~VNOFUNC;
|
||||||
|
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 */
|
/* not found */
|
||||||
|
if (flags & VNOSET)
|
||||||
|
return;
|
||||||
vp = ckmalloc(sizeof (*vp));
|
vp = ckmalloc(sizeof (*vp));
|
||||||
vp->flags = flags;
|
vp->flags = flags & ~VNOFUNC;
|
||||||
vp->text = s;
|
vp->text = s;
|
||||||
|
vp->name_len = nlen;
|
||||||
vp->next = *vpp;
|
vp->next = *vpp;
|
||||||
vp->func = NULL;
|
vp->func = NULL;
|
||||||
INTOFF;
|
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
if ((vp->flags & VEXPORT) && localevar(s)) {
|
|
||||||
putenv(s);
|
|
||||||
(void) setlocale(LC_ALL, "");
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,17 +328,25 @@ setvareq(char *s, int flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
listsetvar(struct strlist *list)
|
listsetvar(struct strlist *list, int flags)
|
||||||
{
|
{
|
||||||
struct strlist *lp;
|
struct strlist *lp;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
for (lp = list ; lp ; lp = lp->next) {
|
for (lp = list ; lp ; lp = lp->next) {
|
||||||
setvareq(savestr(lp->text), 0);
|
setvareq(savestr(lp->text), flags);
|
||||||
}
|
}
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
listmklocal(struct strlist *list, int flags)
|
||||||
|
{
|
||||||
|
struct strlist *lp;
|
||||||
|
|
||||||
|
for (lp = list ; lp ; lp = lp->next)
|
||||||
|
mklocal(lp->text, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -375,18 +354,14 @@ listsetvar(struct strlist *list)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
lookupvar(char *name)
|
lookupvar(const char *name)
|
||||||
{
|
{
|
||||||
struct var *v;
|
struct var *v;
|
||||||
|
|
||||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
v = find_var(name, NULL, NULL);
|
||||||
if (varequal(v->text, name)) {
|
if (v == NULL || v->flags & VUNSET)
|
||||||
if (v->flags & VUNSET)
|
return NULL;
|
||||||
return NULL;
|
return v->text + v->name_len + 1;
|
||||||
return strchr(v->text, '=') + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -398,24 +373,21 @@ lookupvar(char *name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bltinlookup(char *name, int doall)
|
bltinlookup(const char *name, int doall)
|
||||||
{
|
{
|
||||||
struct strlist *sp;
|
struct strlist *sp;
|
||||||
struct var *v;
|
struct var *v;
|
||||||
|
|
||||||
for (sp = cmdenviron ; sp ; sp = sp->next) {
|
for (sp = cmdenviron ; sp ; sp = sp->next) {
|
||||||
if (varequal(sp->text, name))
|
if (strequal(sp->text, name))
|
||||||
return strchr(sp->text, '=') + 1;
|
return strchr(sp->text, '=') + 1;
|
||||||
}
|
}
|
||||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
|
||||||
if (varequal(v->text, name)) {
|
v = find_var(name, NULL, NULL);
|
||||||
if ((v->flags & VUNSET)
|
|
||||||
|| (!doall && (v->flags & VEXPORT) == 0))
|
if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
|
||||||
return NULL;
|
return NULL;
|
||||||
return strchr(v->text, '=') + 1;
|
return v->text + v->name_len + 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,7 +403,8 @@ environment(void)
|
||||||
int nenv;
|
int nenv;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
char **env, **ep;
|
char **env;
|
||||||
|
char **ep;
|
||||||
|
|
||||||
nenv = 0;
|
nenv = 0;
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||||
|
@ -457,6 +430,8 @@ environment(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
|
void shprocvar(void);
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
shprocvar();
|
shprocvar();
|
||||||
}
|
}
|
||||||
|
@ -496,24 +471,94 @@ shprocvar(void)
|
||||||
* any variables.
|
* any variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
print_quoted(const char *p)
|
||||||
|
{
|
||||||
|
const char *q;
|
||||||
|
|
||||||
|
if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
|
||||||
|
out1fmt("%s", p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (*p) {
|
||||||
|
if (*p == '\'') {
|
||||||
|
out1fmt("\\'");
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
q = strchr(p, '\'');
|
||||||
|
if (!q) {
|
||||||
|
out1fmt("'%s'", p );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out1fmt("'%.*s'", (int)(q - p), p );
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_var(const void *v_v1, const void *v_v2)
|
||||||
|
{
|
||||||
|
const struct var * const *v1 = v_v1;
|
||||||
|
const struct var * const *v2 = v_v2;
|
||||||
|
|
||||||
|
/* XXX Will anyone notice we include the '=' of the shorter name? */
|
||||||
|
return strcoll((*v1)->text, (*v2)->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* POSIX requires that 'set' (but not export or readonly) output the
|
||||||
|
* variables in lexicographic order - by the locale's collating order (sigh).
|
||||||
|
* Maybe we could keep them in an ordered balanced binary tree
|
||||||
|
* instead of hashed lists.
|
||||||
|
* For now just roll 'em through qsort for printing...
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
showvarscmd(int argc __unused, char **argv __unused)
|
showvars(const char *name, int flag, int show_value)
|
||||||
{
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
const char *s;
|
const char *p;
|
||||||
|
|
||||||
|
static struct var **list; /* static in case we are interrupted */
|
||||||
|
static int list_len;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (!list) {
|
||||||
|
list_len = 32;
|
||||||
|
list = ckmalloc(list_len * sizeof *list);
|
||||||
|
}
|
||||||
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||||
if (vp->flags & VUNSET)
|
if (flag && !(vp->flags & flag))
|
||||||
continue;
|
continue;
|
||||||
for (s = vp->text; *s != '='; s++)
|
if (vp->flags & VUNSET && !(show_value & 2))
|
||||||
out1c(*s);
|
continue;
|
||||||
out1c('=');
|
if (count >= list_len) {
|
||||||
out1qstr(s + 1);
|
list = ckrealloc(list,
|
||||||
out1c('\n');
|
(list_len << 1) * sizeof *list);
|
||||||
|
list_len <<= 1;
|
||||||
|
}
|
||||||
|
list[count++] = vp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsort(list, count, sizeof *list, sort_var);
|
||||||
|
|
||||||
|
for (vpp = list; count--; vpp++) {
|
||||||
|
vp = *vpp;
|
||||||
|
if (name)
|
||||||
|
out1fmt("%s ", name);
|
||||||
|
for (p = vp->text ; *p != '=' ; p++)
|
||||||
|
out1c(*p);
|
||||||
|
if (!(vp->flags & VUNSET) && show_value) {
|
||||||
|
out1fmt("=");
|
||||||
|
print_quoted(++p);
|
||||||
|
}
|
||||||
|
out1c('\n');
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,71 +571,29 @@ showvarscmd(int argc __unused, char **argv __unused)
|
||||||
int
|
int
|
||||||
exportcmd(int argc, char **argv)
|
exportcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct var **vpp;
|
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
char *name;
|
char *name;
|
||||||
char *p;
|
const char *p;
|
||||||
char *cmdname;
|
|
||||||
int ch, values;
|
|
||||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||||
|
int pflag;
|
||||||
|
|
||||||
cmdname = argv[0];
|
pflag = nextopt("p") == 'p' ? 3 : 0;
|
||||||
optreset = optind = 1;
|
if (argc <= 1 || pflag) {
|
||||||
opterr = 0;
|
showvars( pflag ? argv[0] : 0, flag, pflag );
|
||||||
values = 0;
|
return 0;
|
||||||
while ((ch = getopt(argc, argv, "p")) != -1) {
|
|
||||||
switch (ch) {
|
|
||||||
case 'p':
|
|
||||||
values = 1;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
error("unknown option: -%c", optopt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
listsetvar(cmdenviron);
|
while ((name = *argptr++) != NULL) {
|
||||||
if (argc != 0) {
|
if ((p = strchr(name, '=')) != NULL) {
|
||||||
while ((name = *argptr++) != NULL) {
|
p++;
|
||||||
if ((p = strchr(name, '=')) != NULL) {
|
} else {
|
||||||
p++;
|
vp = find_var(name, NULL, NULL);
|
||||||
} else {
|
if (vp != NULL) {
|
||||||
vpp = hashvar(name);
|
vp->flags |= flag;
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
continue;
|
||||||
if (varequal(vp->text, name)) {
|
|
||||||
|
|
||||||
vp->flags |= flag;
|
|
||||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
|
||||||
putenv(vp->text);
|
|
||||||
(void) setlocale(LC_ALL, "");
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
if (values) {
|
|
||||||
out1str(cmdname);
|
|
||||||
out1c(' ');
|
|
||||||
}
|
|
||||||
for (p = vp->text ; *p != '=' ; p++)
|
|
||||||
out1c(*p);
|
|
||||||
if (values && !(vp->flags & VUNSET)) {
|
|
||||||
out1c('=');
|
|
||||||
out1qstr(p + 1);
|
|
||||||
}
|
|
||||||
out1c('\n');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setvar(name, p, flag);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -601,28 +604,28 @@ found:;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
localcmd(int argc __unused, char **argv __unused)
|
localcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (! in_function())
|
if (! in_function())
|
||||||
error("Not in a function");
|
error("Not in a function");
|
||||||
while ((name = *argptr++) != NULL) {
|
while ((name = *argptr++) != NULL) {
|
||||||
mklocal(name);
|
mklocal(name, 0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a variable a local variable. When a variable is made local, it's
|
* Make a variable a local variable. When a variable is made local, its
|
||||||
* value and flags are saved in a localvar structure. The saved values
|
* value and flags are saved in a localvar structure. The saved values
|
||||||
* will be restored when the shell function returns. We handle the name
|
* will be restored when the shell function returns. We handle the name
|
||||||
* "-" as a special case.
|
* "-" as a special case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
mklocal(char *name)
|
mklocal(const char *name, int flags)
|
||||||
{
|
{
|
||||||
struct localvar *lvp;
|
struct localvar *lvp;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
|
@ -631,17 +634,17 @@ mklocal(char *name)
|
||||||
INTOFF;
|
INTOFF;
|
||||||
lvp = ckmalloc(sizeof (struct localvar));
|
lvp = ckmalloc(sizeof (struct localvar));
|
||||||
if (name[0] == '-' && name[1] == '\0') {
|
if (name[0] == '-' && name[1] == '\0') {
|
||||||
lvp->text = ckmalloc(sizeof optlist);
|
char *p;
|
||||||
memcpy(lvp->text, optlist, sizeof optlist);
|
p = ckmalloc(sizeof_optlist);
|
||||||
|
lvp->text = memcpy(p, optlist, sizeof_optlist);
|
||||||
vp = NULL;
|
vp = NULL;
|
||||||
} else {
|
} else {
|
||||||
vpp = hashvar(name);
|
vp = find_var(name, &vpp, NULL);
|
||||||
for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
|
|
||||||
if (vp == NULL) {
|
if (vp == NULL) {
|
||||||
if (strchr(name, '='))
|
if (strchr(name, '='))
|
||||||
setvareq(savestr(name), VSTRFIXED);
|
setvareq(savestr(name), VSTRFIXED|flags);
|
||||||
else
|
else
|
||||||
setvar(name, NULL, VSTRFIXED);
|
setvar(name, NULL, VSTRFIXED|flags);
|
||||||
vp = *vpp; /* the new variable */
|
vp = *vpp; /* the new variable */
|
||||||
lvp->text = NULL;
|
lvp->text = NULL;
|
||||||
lvp->flags = VUNSET;
|
lvp->flags = VUNSET;
|
||||||
|
@ -649,8 +652,8 @@ mklocal(char *name)
|
||||||
lvp->text = vp->text;
|
lvp->text = vp->text;
|
||||||
lvp->flags = vp->flags;
|
lvp->flags = vp->flags;
|
||||||
vp->flags |= VSTRFIXED|VTEXTFIXED;
|
vp->flags |= VSTRFIXED|VTEXTFIXED;
|
||||||
if (strchr(name, '='))
|
if (name[vp->name_len] == '=')
|
||||||
setvareq(savestr(name), 0);
|
setvareq(savestr(name), flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lvp->vp = vp;
|
lvp->vp = vp;
|
||||||
|
@ -673,12 +676,15 @@ poplocalvars(void)
|
||||||
while ((lvp = localvars) != NULL) {
|
while ((lvp = localvars) != NULL) {
|
||||||
localvars = lvp->next;
|
localvars = lvp->next;
|
||||||
vp = lvp->vp;
|
vp = lvp->vp;
|
||||||
|
TRACE(("poplocalvar %s", vp ? vp->text : "-"));
|
||||||
if (vp == NULL) { /* $- saved */
|
if (vp == NULL) { /* $- saved */
|
||||||
memcpy(optlist, lvp->text, sizeof optlist);
|
memcpy(optlist, lvp->text, sizeof_optlist);
|
||||||
ckfree(lvp->text);
|
ckfree(lvp->text);
|
||||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||||
(void)unsetvar(vp->text);
|
(void)unsetvar(vp->text, 0);
|
||||||
} else {
|
} else {
|
||||||
|
if (vp->func && (vp->flags & VNOFUNC) == 0)
|
||||||
|
(*vp->func)(lvp->text + vp->name_len + 1);
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
if ((vp->flags & VTEXTFIXED) == 0)
|
||||||
ckfree(vp->text);
|
ckfree(vp->text);
|
||||||
vp->flags = lvp->flags;
|
vp->flags = lvp->flags;
|
||||||
|
@ -709,7 +715,7 @@ setvarcmd(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
unsetcmd(int argc __unused, char **argv __unused)
|
unsetcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
int i;
|
int i;
|
||||||
|
@ -717,11 +723,11 @@ unsetcmd(int argc __unused, char **argv __unused)
|
||||||
int flg_var = 0;
|
int flg_var = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
while ((i = nextopt("vf")) != '\0') {
|
while ((i = nextopt("evf")) != '\0') {
|
||||||
if (i == 'f')
|
if (i == 'f')
|
||||||
flg_func = 1;
|
flg_func = 1;
|
||||||
else
|
else
|
||||||
flg_var = 1;
|
flg_var = i;
|
||||||
}
|
}
|
||||||
if (flg_func == 0 && flg_var == 0)
|
if (flg_func == 0 && flg_var == 0)
|
||||||
flg_var = 1;
|
flg_var = 1;
|
||||||
|
@ -730,7 +736,7 @@ unsetcmd(int argc __unused, char **argv __unused)
|
||||||
if (flg_func)
|
if (flg_func)
|
||||||
ret |= unsetfunc(*ap);
|
ret |= unsetfunc(*ap);
|
||||||
if (flg_var)
|
if (flg_var)
|
||||||
ret |= unsetvar(*ap);
|
ret |= unsetvar(*ap, flg_var == 'e');
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -741,58 +747,38 @@ unsetcmd(int argc __unused, char **argv __unused)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
unsetvar(char *s)
|
unsetvar(const char *s, int unexport)
|
||||||
{
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
|
||||||
vpp = hashvar(s);
|
vp = find_var(s, &vpp, NULL);
|
||||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
if (vp == NULL)
|
||||||
if (varequal(vp->text, s)) {
|
return 0;
|
||||||
if (vp->flags & VREADONLY)
|
|
||||||
return (1);
|
if (vp->flags & VREADONLY)
|
||||||
INTOFF;
|
return 1;
|
||||||
if (*(strchr(vp->text, '=') + 1) != '\0')
|
|
||||||
setvar(s, nullstr, 0);
|
INTOFF;
|
||||||
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
if (unexport) {
|
||||||
unsetenv(s);
|
vp->flags &= ~VEXPORT;
|
||||||
setlocale(LC_ALL, "");
|
} else {
|
||||||
}
|
if (vp->text[vp->name_len + 1] != '\0')
|
||||||
vp->flags &= ~VEXPORT;
|
setvar(s, nullstr, 0);
|
||||||
vp->flags |= VUNSET;
|
vp->flags &= ~VEXPORT;
|
||||||
if ((vp->flags & VSTRFIXED) == 0) {
|
vp->flags |= VUNSET;
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
if ((vp->flags & VSTRFIXED) == 0) {
|
||||||
ckfree(vp->text);
|
if ((vp->flags & VTEXTFIXED) == 0)
|
||||||
*vpp = vp->next;
|
ckfree(vp->text);
|
||||||
ckfree(vp);
|
*vpp = vp->next;
|
||||||
}
|
ckfree(vp);
|
||||||
INTON;
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
INTON;
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the appropriate entry in the hash table from the name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATIC struct var **
|
|
||||||
hashvar(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
|
* Returns true if the two strings specify the same varable. The first
|
||||||
* variable name is terminated by '='; the second may be terminated by
|
* variable name is terminated by '='; the second may be terminated by
|
||||||
|
@ -800,7 +786,7 @@ hashvar(char *p)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
varequal(char *p, char *q)
|
strequal(const char *p, const char *q)
|
||||||
{
|
{
|
||||||
while (*p == *q++) {
|
while (*p == *q++) {
|
||||||
if (*p++ == '=')
|
if (*p++ == '=')
|
||||||
|
@ -812,5 +798,39 @@ varequal(char *p, char *q)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
|
* Search for a variable.
|
||||||
|
* 'name' may be terminated by '=' or a NUL.
|
||||||
|
* vppp is set to the pointer to vp, or the list head if vp isn't found
|
||||||
|
* lenp is set to the number of charactets in 'name'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
STATIC struct var *
|
||||||
|
find_var(const char *name, struct var ***vppp, int *lenp)
|
||||||
|
{
|
||||||
|
unsigned int hashval;
|
||||||
|
int len;
|
||||||
|
struct var *vp, **vpp;
|
||||||
|
const char *p = name;
|
||||||
|
|
||||||
|
hashval = 0;
|
||||||
|
while (*p && *p != '=')
|
||||||
|
hashval = 2 * hashval + (unsigned char)*p++;
|
||||||
|
len = p - name;
|
||||||
|
|
||||||
|
if (lenp)
|
||||||
|
*lenp = len;
|
||||||
|
vpp = &vartab[hashval % VTABSIZE];
|
||||||
|
if (vppp)
|
||||||
|
*vppp = vpp;
|
||||||
|
|
||||||
|
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||||
|
if (vp->name_len != len)
|
||||||
|
continue;
|
||||||
|
if (memcmp(vp->text, name, len) != 0)
|
||||||
|
continue;
|
||||||
|
if (vppp)
|
||||||
|
*vppp = vpp;
|
||||||
|
return vp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* $NetBSD: var.h,v 1.25 2011/06/18 21:18:46 christos Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
@ -13,7 +15,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -30,7 +32,6 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||||
* $FreeBSD: src/bin/sh/var.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -40,17 +41,19 @@
|
||||||
/* flags */
|
/* flags */
|
||||||
#define VEXPORT 0x01 /* variable is exported */
|
#define VEXPORT 0x01 /* variable is exported */
|
||||||
#define VREADONLY 0x02 /* variable cannot be modified */
|
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||||
#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
|
#define VSTRFIXED 0x04 /* variable struct is statically allocated */
|
||||||
#define VTEXTFIXED 0x08 /* text is staticly allocated */
|
#define VTEXTFIXED 0x08 /* text is statically allocated */
|
||||||
#define VSTACK 0x10 /* text is allocated on the stack */
|
#define VSTACK 0x10 /* text is allocated on the stack */
|
||||||
#define VUNSET 0x20 /* the variable is not set */
|
#define VUNSET 0x20 /* the variable is not set */
|
||||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||||
|
#define VNOSET 0x80 /* do not set variable - just readonly test */
|
||||||
|
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
struct var *next; /* next entry in hash list */
|
struct var *next; /* next entry in hash list */
|
||||||
int flags; /* flags are defined above */
|
int flags; /* flags are defined above */
|
||||||
char *text; /* name=value */
|
char *text; /* name=value */
|
||||||
|
int name_len; /* length of name */
|
||||||
void (*func)(const char *);
|
void (*func)(const char *);
|
||||||
/* function to be called when */
|
/* function to be called when */
|
||||||
/* the variable gets set/unset */
|
/* the variable gets set/unset */
|
||||||
|
@ -65,17 +68,21 @@ struct localvar {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct localvar *localvars;
|
extern struct localvar *localvars;
|
||||||
|
|
||||||
|
#if ATTY
|
||||||
|
extern struct var vatty;
|
||||||
|
#endif
|
||||||
extern struct var vifs;
|
extern struct var vifs;
|
||||||
extern struct var vmail;
|
extern struct var vmail;
|
||||||
extern struct var vmpath;
|
extern struct var vmpath;
|
||||||
extern struct var vpath;
|
extern struct var vpath;
|
||||||
extern struct var vppid;
|
|
||||||
extern struct var vps1;
|
extern struct var vps1;
|
||||||
extern struct var vps2;
|
extern struct var vps2;
|
||||||
extern struct var vpse;
|
extern struct var vps4;
|
||||||
#ifndef NO_HISTORY
|
#ifndef SMALL
|
||||||
|
extern struct var vterm;
|
||||||
|
extern struct var vtermcap;
|
||||||
extern struct var vhistsize;
|
extern struct var vhistsize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -92,33 +99,31 @@ extern struct var vhistsize;
|
||||||
#define pathval() (vpath.text + 5)
|
#define pathval() (vpath.text + 5)
|
||||||
#define ps1val() (vps1.text + 4)
|
#define ps1val() (vps1.text + 4)
|
||||||
#define ps2val() (vps2.text + 4)
|
#define ps2val() (vps2.text + 4)
|
||||||
#define pseval() (vpse.text + 4)
|
#define ps4val() (vps4.text + 4)
|
||||||
#define optindval() (voptind.text + 7)
|
#define optindval() (voptind.text + 7)
|
||||||
#ifndef NO_HISTORY
|
#ifndef SMALL
|
||||||
#define histsizeval() (vhistsize.text + 9)
|
#define histsizeval() (vhistsize.text + 9)
|
||||||
|
#define termval() (vterm.text + 5)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ATTY
|
||||||
|
#define attyset() ((vatty.flags & VUNSET) == 0)
|
||||||
|
#endif
|
||||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||||
|
|
||||||
void initvar(void);
|
void initvar(void);
|
||||||
void setvar(char *, char *, int);
|
void setvar(const char *, const char *, int);
|
||||||
void setvareq(char *, int);
|
void setvareq(char *, int);
|
||||||
struct strlist;
|
struct strlist;
|
||||||
void listsetvar(struct strlist *);
|
void listsetvar(struct strlist *, int);
|
||||||
char *lookupvar(char *);
|
char *lookupvar(const char *);
|
||||||
char *bltinlookup(char *, int);
|
char *bltinlookup(const char *, int);
|
||||||
char **environment(void);
|
char **environment(void);
|
||||||
void shprocvar(void);
|
void shprocvar(void);
|
||||||
int showvarscmd(int, char **);
|
int showvars(const char *, int, int);
|
||||||
int exportcmd(int, char **);
|
void mklocal(const char *, int);
|
||||||
int localcmd(int, char **);
|
void listmklocal(struct strlist *, int);
|
||||||
void mklocal(char *);
|
|
||||||
void poplocalvars(void);
|
void poplocalvars(void);
|
||||||
int setvarcmd(int, char **);
|
int unsetvar(const char *, int);
|
||||||
int unsetcmd(int, char **);
|
int setvarsafe(const char *, const char *, int);
|
||||||
int unsetvar(char *);
|
void print_quoted(const char *);
|
||||||
int setvarsafe(char *, char *, int);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: var.h,v 1.4 2006/03/29 12:04:45 philip Exp $
|
|
||||||
*/
|
|
|
@ -2214,14 +2214,14 @@
|
||||||
./usr/Makefile minix-sys
|
./usr/Makefile minix-sys
|
||||||
./usr/man minix-sys
|
./usr/man minix-sys
|
||||||
./usr/man/man1 minix-sys
|
./usr/man/man1 minix-sys
|
||||||
./usr/man/man1/..1 minix-sys
|
./usr/man/man1/..1 minix-sys obsolete
|
||||||
./usr/man/man1/[.1 minix-sys
|
./usr/man/man1/[.1 minix-sys
|
||||||
./usr/man/man1/addr2line.1 minix-sys binutils
|
./usr/man/man1/addr2line.1 minix-sys binutils
|
||||||
./usr/man/man1/apropos.1 minix-sys
|
./usr/man/man1/apropos.1 minix-sys
|
||||||
./usr/man/man1/ar.1 minix-sys binutils
|
./usr/man/man1/ar.1 minix-sys binutils
|
||||||
./usr/man/man1/as.1 minix-sys binutils
|
./usr/man/man1/as.1 minix-sys binutils
|
||||||
./usr/man/man1/asa.1 minix-sys
|
./usr/man/man1/asa.1 minix-sys
|
||||||
./usr/man/man1/ash.1 minix-sys
|
./usr/man/man1/ash.1 minix-sys obsolete
|
||||||
./usr/man/man1/at.1 minix-sys
|
./usr/man/man1/at.1 minix-sys
|
||||||
./usr/man/man1/atf2kyua.1 minix-sys kyua
|
./usr/man/man1/atf2kyua.1 minix-sys kyua
|
||||||
./usr/man/man1/atf-check.1 minix-sys atf
|
./usr/man/man1/atf-check.1 minix-sys atf
|
||||||
|
@ -2235,7 +2235,7 @@
|
||||||
./usr/man/man1/banner.1 minix-sys
|
./usr/man/man1/banner.1 minix-sys
|
||||||
./usr/man/man1/basename.1 minix-sys
|
./usr/man/man1/basename.1 minix-sys
|
||||||
./usr/man/man1/bdes.1 minix-sys
|
./usr/man/man1/bdes.1 minix-sys
|
||||||
./usr/man/man1/break.1 minix-sys
|
./usr/man/man1/break.1 minix-sys obsolete
|
||||||
./usr/man/man1/bsdtar.1 minix-sys
|
./usr/man/man1/bsdtar.1 minix-sys
|
||||||
./usr/man/man1/bsfilt.1 minix-sys
|
./usr/man/man1/bsfilt.1 minix-sys
|
||||||
./usr/man/man1/bunzip2.1 minix-sys
|
./usr/man/man1/bunzip2.1 minix-sys
|
||||||
|
@ -2245,12 +2245,12 @@
|
||||||
./usr/man/man1/c++.1 minix-sys gcccmds
|
./usr/man/man1/c++.1 minix-sys gcccmds
|
||||||
./usr/man/man1/cal.1 minix-sys
|
./usr/man/man1/cal.1 minix-sys
|
||||||
./usr/man/man1/calendar.1 minix-sys
|
./usr/man/man1/calendar.1 minix-sys
|
||||||
./usr/man/man1/case.1 minix-sys
|
./usr/man/man1/case.1 minix-sys obsolete
|
||||||
./usr/man/man1/cat.1 minix-sys
|
./usr/man/man1/cat.1 minix-sys
|
||||||
./usr/man/man1/cawf.1 minix-sys
|
./usr/man/man1/cawf.1 minix-sys
|
||||||
./usr/man/man1/cc.1 minix-sys gcccmds
|
./usr/man/man1/cc.1 minix-sys gcccmds
|
||||||
./usr/man/man1/cccp.1 minix-sys gcccmds
|
./usr/man/man1/cccp.1 minix-sys gcccmds
|
||||||
./usr/man/man1/cd.1 minix-sys
|
./usr/man/man1/cd.1 minix-sys obsolete
|
||||||
./usr/man/man1/c++filt.1 minix-sys binutils
|
./usr/man/man1/c++filt.1 minix-sys binutils
|
||||||
./usr/man/man1/checknr.1 minix-sys
|
./usr/man/man1/checknr.1 minix-sys
|
||||||
./usr/man/man1/chfn.1 minix-sys
|
./usr/man/man1/chfn.1 minix-sys
|
||||||
|
@ -2268,9 +2268,9 @@
|
||||||
./usr/man/man1/colrm.1 minix-sys
|
./usr/man/man1/colrm.1 minix-sys
|
||||||
./usr/man/man1/column.1 minix-sys
|
./usr/man/man1/column.1 minix-sys
|
||||||
./usr/man/man1/comm.1 minix-sys
|
./usr/man/man1/comm.1 minix-sys
|
||||||
./usr/man/man1/command.1 minix-sys
|
./usr/man/man1/command.1 minix-sys obsolete
|
||||||
./usr/man/man1/compress.1 minix-sys
|
./usr/man/man1/compress.1 minix-sys
|
||||||
./usr/man/man1/continue.1 minix-sys
|
./usr/man/man1/continue.1 minix-sys obsolete
|
||||||
./usr/man/man1/cp.1 minix-sys
|
./usr/man/man1/cp.1 minix-sys
|
||||||
./usr/man/man1/cpio.1 minix-sys
|
./usr/man/man1/cpio.1 minix-sys
|
||||||
./usr/man/man1/cpp.1 minix-sys gcccmds
|
./usr/man/man1/cpp.1 minix-sys gcccmds
|
||||||
|
@ -2296,12 +2296,12 @@
|
||||||
./usr/man/man1/eject.1 minix-sys
|
./usr/man/man1/eject.1 minix-sys
|
||||||
./usr/man/man1/elfedit.1 minix-sys binutils
|
./usr/man/man1/elfedit.1 minix-sys binutils
|
||||||
./usr/man/man1/env.1 minix-sys
|
./usr/man/man1/env.1 minix-sys
|
||||||
./usr/man/man1/eval.1 minix-sys
|
./usr/man/man1/eval.1 minix-sys obsolete
|
||||||
./usr/man/man1/ex.1 minix-sys
|
./usr/man/man1/ex.1 minix-sys
|
||||||
./usr/man/man1/exec.1 minix-sys
|
./usr/man/man1/exec.1 minix-sys obsolete
|
||||||
./usr/man/man1/exit.1 minix-sys
|
./usr/man/man1/exit.1 minix-sys obsolete
|
||||||
./usr/man/man1/expand.1 minix-sys
|
./usr/man/man1/expand.1 minix-sys
|
||||||
./usr/man/man1/export.1 minix-sys
|
./usr/man/man1/export.1 minix-sys obsolete
|
||||||
./usr/man/man1/expr.1 minix-sys
|
./usr/man/man1/expr.1 minix-sys
|
||||||
./usr/man/man1/false.1 minix-sys
|
./usr/man/man1/false.1 minix-sys
|
||||||
./usr/man/man1/fetch.1 minix-sys
|
./usr/man/man1/fetch.1 minix-sys
|
||||||
|
@ -2312,7 +2312,7 @@
|
||||||
./usr/man/man1/flex.1 minix-sys
|
./usr/man/man1/flex.1 minix-sys
|
||||||
./usr/man/man1/flexdoc.1 minix-sys
|
./usr/man/man1/flexdoc.1 minix-sys
|
||||||
./usr/man/man1/fold.1 minix-sys
|
./usr/man/man1/fold.1 minix-sys
|
||||||
./usr/man/man1/for.1 minix-sys
|
./usr/man/man1/for.1 minix-sys obsolete
|
||||||
./usr/man/man1/format.1 minix-sys
|
./usr/man/man1/format.1 minix-sys
|
||||||
./usr/man/man1/fpr.1 minix-sys
|
./usr/man/man1/fpr.1 minix-sys
|
||||||
./usr/man/man1/from.1 minix-sys
|
./usr/man/man1/from.1 minix-sys
|
||||||
|
@ -2325,7 +2325,7 @@
|
||||||
./usr/man/man1/gcpp.1 minix-sys gcccmds
|
./usr/man/man1/gcpp.1 minix-sys gcccmds
|
||||||
./usr/man/man1/genassym.1 minix-sys
|
./usr/man/man1/genassym.1 minix-sys
|
||||||
./usr/man/man1/getopt.1 minix-sys
|
./usr/man/man1/getopt.1 minix-sys
|
||||||
./usr/man/man1/getopts.1 minix-sys
|
./usr/man/man1/getopts.1 minix-sys obsolete
|
||||||
./usr/man/man1/gprof.1 minix-sys binutils
|
./usr/man/man1/gprof.1 minix-sys binutils
|
||||||
./usr/man/man1/grep.1 minix-sys
|
./usr/man/man1/grep.1 minix-sys
|
||||||
./usr/man/man1/groups.1 minix-sys
|
./usr/man/man1/groups.1 minix-sys
|
||||||
|
@ -2333,14 +2333,14 @@
|
||||||
./usr/man/man1/gzcat.1 minix-sys
|
./usr/man/man1/gzcat.1 minix-sys
|
||||||
./usr/man/man1/gzexe.1 minix-sys
|
./usr/man/man1/gzexe.1 minix-sys
|
||||||
./usr/man/man1/gzip.1 minix-sys
|
./usr/man/man1/gzip.1 minix-sys
|
||||||
./usr/man/man1/hash.1 minix-sys
|
./usr/man/man1/hash.1 minix-sys obsolete
|
||||||
./usr/man/man1/head.1 minix-sys
|
./usr/man/man1/head.1 minix-sys
|
||||||
./usr/man/man1/hexdump.1 minix-sys
|
./usr/man/man1/hexdump.1 minix-sys
|
||||||
./usr/man/man1/host.1 minix-sys
|
./usr/man/man1/host.1 minix-sys
|
||||||
./usr/man/man1/hostaddr.1 minix-sys
|
./usr/man/man1/hostaddr.1 minix-sys
|
||||||
./usr/man/man1/hostname.1 minix-sys
|
./usr/man/man1/hostname.1 minix-sys
|
||||||
./usr/man/man1/id.1 minix-sys
|
./usr/man/man1/id.1 minix-sys
|
||||||
./usr/man/man1/if.1 minix-sys
|
./usr/man/man1/if.1 minix-sys obsolete
|
||||||
./usr/man/man1/ifdef.1 minix-sys
|
./usr/man/man1/ifdef.1 minix-sys
|
||||||
./usr/man/man1/indent.1 minix-sys
|
./usr/man/man1/indent.1 minix-sys
|
||||||
./usr/man/man1/info.1 minix-sys
|
./usr/man/man1/info.1 minix-sys
|
||||||
|
@ -2351,7 +2351,7 @@
|
||||||
./usr/man/man1/isodir.1 minix-sys
|
./usr/man/man1/isodir.1 minix-sys
|
||||||
./usr/man/man1/isoinfo.1 minix-sys
|
./usr/man/man1/isoinfo.1 minix-sys
|
||||||
./usr/man/man1/isoread.1 minix-sys
|
./usr/man/man1/isoread.1 minix-sys
|
||||||
./usr/man/man1/jobs.1 minix-sys
|
./usr/man/man1/jobs.1 minix-sys obsolete
|
||||||
./usr/man/man1/join.1 minix-sys
|
./usr/man/man1/join.1 minix-sys
|
||||||
./usr/man/man1/jot.1 minix-sys
|
./usr/man/man1/jot.1 minix-sys
|
||||||
./usr/man/man1/kill.1 minix-sys
|
./usr/man/man1/kill.1 minix-sys
|
||||||
|
@ -2384,7 +2384,7 @@
|
||||||
./usr/man/man1/ln.1 minix-sys
|
./usr/man/man1/ln.1 minix-sys
|
||||||
./usr/man/man1/loadfont.1 minix-sys
|
./usr/man/man1/loadfont.1 minix-sys
|
||||||
./usr/man/man1/loadkeys.1 minix-sys
|
./usr/man/man1/loadkeys.1 minix-sys
|
||||||
./usr/man/man1/local.1 minix-sys
|
./usr/man/man1/local.1 minix-sys obsolete
|
||||||
./usr/man/man1/lock.1 minix-sys
|
./usr/man/man1/lock.1 minix-sys
|
||||||
./usr/man/man1/logger.1 minix-sys
|
./usr/man/man1/logger.1 minix-sys
|
||||||
./usr/man/man1/login.1 minix-sys
|
./usr/man/man1/login.1 minix-sys
|
||||||
|
@ -2454,13 +2454,13 @@
|
||||||
./usr/man/man1/pwhash.1 minix-sys
|
./usr/man/man1/pwhash.1 minix-sys
|
||||||
./usr/man/man1/ranlib.1 minix-sys binutils
|
./usr/man/man1/ranlib.1 minix-sys binutils
|
||||||
./usr/man/man1/rcp.1 minix-sys
|
./usr/man/man1/rcp.1 minix-sys
|
||||||
./usr/man/man1/read.1 minix-sys
|
./usr/man/man1/read.1 minix-sys obsolete
|
||||||
./usr/man/man1/readelf.1 minix-sys binutils
|
./usr/man/man1/readelf.1 minix-sys binutils
|
||||||
./usr/man/man1/readlink.1 minix-sys
|
./usr/man/man1/readlink.1 minix-sys
|
||||||
./usr/man/man1/readonly.1 minix-sys
|
./usr/man/man1/readonly.1 minix-sys obsolete
|
||||||
./usr/man/man1/recwave.1 minix-sys
|
./usr/man/man1/recwave.1 minix-sys
|
||||||
./usr/man/man1/remsync.1 minix-sys
|
./usr/man/man1/remsync.1 minix-sys
|
||||||
./usr/man/man1/return.1 minix-sys
|
./usr/man/man1/return.1 minix-sys obsolete
|
||||||
./usr/man/man1/rev.1 minix-sys
|
./usr/man/man1/rev.1 minix-sys
|
||||||
./usr/man/man1/rget.1 minix-sys
|
./usr/man/man1/rget.1 minix-sys
|
||||||
./usr/man/man1/rlogin.1 minix-sys
|
./usr/man/man1/rlogin.1 minix-sys
|
||||||
|
@ -2472,12 +2472,12 @@
|
||||||
./usr/man/man1/sdiff.1 minix-sys
|
./usr/man/man1/sdiff.1 minix-sys
|
||||||
./usr/man/man1/sed.1 minix-sys
|
./usr/man/man1/sed.1 minix-sys
|
||||||
./usr/man/man1/seq.1 minix-sys
|
./usr/man/man1/seq.1 minix-sys
|
||||||
./usr/man/man1/set.1 minix-sys
|
./usr/man/man1/set.1 minix-sys obsolete
|
||||||
./usr/man/man1/setvar.1 minix-sys
|
./usr/man/man1/setvar.1 minix-sys obsolete
|
||||||
./usr/man/man1/sh.1 minix-sys
|
./usr/man/man1/sh.1 minix-sys
|
||||||
./usr/man/man1/sha1.1 minix-sys
|
./usr/man/man1/sha1.1 minix-sys
|
||||||
./usr/man/man1/shar.1 minix-sys
|
./usr/man/man1/shar.1 minix-sys
|
||||||
./usr/man/man1/shift.1 minix-sys
|
./usr/man/man1/shift.1 minix-sys obsolete
|
||||||
./usr/man/man1/shlock.1 minix-sys
|
./usr/man/man1/shlock.1 minix-sys
|
||||||
./usr/man/man1/shuffle.1 minix-sys
|
./usr/man/man1/shuffle.1 minix-sys
|
||||||
./usr/man/man1/size.1 minix-sys binutils
|
./usr/man/man1/size.1 minix-sys binutils
|
||||||
|
@ -2514,13 +2514,13 @@
|
||||||
./usr/man/man1/touch.1 minix-sys
|
./usr/man/man1/touch.1 minix-sys
|
||||||
./usr/man/man1/tput.1 minix-sys
|
./usr/man/man1/tput.1 minix-sys
|
||||||
./usr/man/man1/tr.1 minix-sys
|
./usr/man/man1/tr.1 minix-sys
|
||||||
./usr/man/man1/trap.1 minix-sys
|
./usr/man/man1/trap.1 minix-sys obsolete
|
||||||
./usr/man/man1/true.1 minix-sys
|
./usr/man/man1/true.1 minix-sys
|
||||||
./usr/man/man1/truncate.1 minix-sys
|
./usr/man/man1/truncate.1 minix-sys
|
||||||
./usr/man/man1/tsort.1 minix-sys
|
./usr/man/man1/tsort.1 minix-sys
|
||||||
./usr/man/man1/tty.1 minix-sys
|
./usr/man/man1/tty.1 minix-sys
|
||||||
./usr/man/man1/ul.1 minix-sys
|
./usr/man/man1/ul.1 minix-sys
|
||||||
./usr/man/man1/umask.1 minix-sys
|
./usr/man/man1/umask.1 minix-sys obsolete
|
||||||
./usr/man/man1/umount.1 minix-sys
|
./usr/man/man1/umount.1 minix-sys
|
||||||
./usr/man/man1/uname.1 minix-sys
|
./usr/man/man1/uname.1 minix-sys
|
||||||
./usr/man/man1/uncompress.1 minix-sys
|
./usr/man/man1/uncompress.1 minix-sys
|
||||||
|
@ -2530,7 +2530,7 @@
|
||||||
./usr/man/man1/uniq.1 minix-sys
|
./usr/man/man1/uniq.1 minix-sys
|
||||||
./usr/man/man1/units.1 minix-sys
|
./usr/man/man1/units.1 minix-sys
|
||||||
./usr/man/man1/unlzma.1 minix-sys
|
./usr/man/man1/unlzma.1 minix-sys
|
||||||
./usr/man/man1/unset.1 minix-sys
|
./usr/man/man1/unset.1 minix-sys obsolete
|
||||||
./usr/man/man1/unvis.1 minix-sys
|
./usr/man/man1/unvis.1 minix-sys
|
||||||
./usr/man/man1/unxz.1 minix-sys
|
./usr/man/man1/unxz.1 minix-sys
|
||||||
./usr/man/man1/unzip.1 minix-sys
|
./usr/man/man1/unzip.1 minix-sys
|
||||||
|
@ -2544,7 +2544,7 @@
|
||||||
./usr/man/man1/vis.1 minix-sys
|
./usr/man/man1/vis.1 minix-sys
|
||||||
./usr/man/man1/vol.1 minix-sys
|
./usr/man/man1/vol.1 minix-sys
|
||||||
./usr/man/man1/w.1 minix-sys
|
./usr/man/man1/w.1 minix-sys
|
||||||
./usr/man/man1/wait.1 minix-sys
|
./usr/man/man1/wait.1 minix-sys obsolete
|
||||||
./usr/man/man1/wall.1 minix-sys
|
./usr/man/man1/wall.1 minix-sys
|
||||||
./usr/man/man1/wc.1 minix-sys
|
./usr/man/man1/wc.1 minix-sys
|
||||||
./usr/man/man1/what.1 minix-sys
|
./usr/man/man1/what.1 minix-sys
|
||||||
|
@ -5249,6 +5249,15 @@
|
||||||
./usr/share/doc/psd/19.curses/twinkle1.c minix-sys
|
./usr/share/doc/psd/19.curses/twinkle1.c minix-sys
|
||||||
./usr/share/doc/psd/19.curses/twinkle2.c minix-sys
|
./usr/share/doc/psd/19.curses/twinkle2.c minix-sys
|
||||||
./usr/share/doc/psd/19.curses/win_st.c minix-sys
|
./usr/share/doc/psd/19.curses/win_st.c minix-sys
|
||||||
|
./usr/share/doc/usd minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/Makefile minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/Rv7man minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/t1 minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/t2 minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/t3 minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/t4 minix-sys
|
||||||
|
./usr/share/doc/usd/03.shell/t.mac minix-sys
|
||||||
./usr/share/examples minix-sys atf
|
./usr/share/examples minix-sys atf
|
||||||
./usr/share/examples/atf minix-sys atf
|
./usr/share/examples/atf minix-sys atf
|
||||||
./usr/share/examples/atf/atf-run.hooks minix-sys atf,!kyua
|
./usr/share/examples/atf/atf-run.hooks minix-sys atf,!kyua
|
||||||
|
|
|
@ -114,6 +114,8 @@
|
||||||
./usr/share/doc/html/bzip2
|
./usr/share/doc/html/bzip2
|
||||||
./usr/share/doc/psd
|
./usr/share/doc/psd
|
||||||
./usr/share/doc/psd/19.curses
|
./usr/share/doc/psd/19.curses
|
||||||
|
./usr/share/doc/usd
|
||||||
|
./usr/share/doc/usd/03.shell
|
||||||
./usr/share/info
|
./usr/share/info
|
||||||
./usr/share/games
|
./usr/share/games
|
||||||
./usr/share/games/fortune
|
./usr/share/games/fortune
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
# Activate emacs keybindings and command line history support
|
# Activate emacs keybindings and command line history support
|
||||||
set -o emacs
|
set -o emacs
|
||||||
|
set -o tabcomplete
|
||||||
|
|
||||||
# Set the default path
|
# Set the default path
|
||||||
PATH=/usr/local/bin:/usr/pkg/bin:/usr/bin:/bin:/usr/games
|
PATH=/usr/local/bin:/usr/pkg/bin:/usr/bin:/bin:/usr/games
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
SUBDIR= add_route arp ash at backup btrace \
|
SUBDIR= add_route arp at backup btrace \
|
||||||
cawf cdprobe \
|
cawf cdprobe \
|
||||||
ci cleantmp cmp co \
|
ci cleantmp cmp co \
|
||||||
compress crc cron crontab \
|
compress crc cron crontab \
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
# Makefile for ash.
|
|
||||||
|
|
||||||
.include <bsd.own.mk>
|
|
||||||
|
|
||||||
PROG= sh
|
|
||||||
BINDIR= /bin
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
# Enable this line to disable command line editing
|
|
||||||
#EDIT=-DNO_HISTORY
|
|
||||||
|
|
||||||
# Enable this line if your system does not have a <paths.h>
|
|
||||||
#NO_PATHS_H=-DNO_PATHS_H
|
|
||||||
|
|
||||||
# Enable this if you don't want job control
|
|
||||||
NO_JOBS=-DJOBS=0
|
|
||||||
MKB_NO_JOBS=-j
|
|
||||||
|
|
||||||
SRCS= alias.c arith.y arith_lex.l cd.c complete.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 output.c parser.c redir.c show.c \
|
|
||||||
trap.c var.c setmode.c
|
|
||||||
|
|
||||||
.include "${.CURDIR}/bltin/Makefile.inc"
|
|
||||||
|
|
||||||
GENSRCS= builtins.c init.c nodes.c syntax.c operators.c signames.c
|
|
||||||
GENHDRS= builtins.h nodes.h syntax.h token.h operators.h signames.h
|
|
||||||
|
|
||||||
SRCS+= ${GENSRCS}
|
|
||||||
|
|
||||||
CLEANFILES+=${GENSRCS} ${GENHDRS}
|
|
||||||
|
|
||||||
DPADD+= ${LIBL} ${LIBEDIT}
|
|
||||||
LDADD+= -ll -ledit
|
|
||||||
|
|
||||||
CPPFLAGS+= -DSHELL
|
|
||||||
CPPFLAGS+=${EDIT} ${NO_PATHS_H} ${NO_JOBS}
|
|
||||||
|
|
||||||
CPPFLAGS+= -I. -I${.CURDIR}
|
|
||||||
|
|
||||||
# A. Generate C tools used to build ash
|
|
||||||
.for tool in init nodes signames syntax
|
|
||||||
${.OBJDIR}/mk${tool}: ${.CURDIR}/mk${tool}.c
|
|
||||||
${HOST_CC} ${HOST_CFLAGS} ${HOST_CPPFLAGS} ${.ALLSRC} -o ${.TARGET}
|
|
||||||
|
|
||||||
CLEANFILES+= ${.OBJDIR}/mk${tool}
|
|
||||||
.endfor
|
|
||||||
|
|
||||||
# B. Generates C sources from C tools
|
|
||||||
NODES_ARGS:= ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat
|
|
||||||
INIT_ARGS:= alias.c eval.c exec.c input.c jobs.c options.c parser.c \
|
|
||||||
redir.c trap.c var.c
|
|
||||||
|
|
||||||
.for tool in nodes signames syntax
|
|
||||||
${tool}.c ${tool}.h: ${.OBJDIR}/mk${tool}
|
|
||||||
${.OBJDIR}/mk${tool} ${${tool:tu}_ARGS}
|
|
||||||
.endfor
|
|
||||||
|
|
||||||
init.c: ${.OBJDIR}/mkinit \
|
|
||||||
alias.c eval.c exec.c input.c jobs.c options.c parser.c \
|
|
||||||
redir.c trap.c var.c
|
|
||||||
${.OBJDIR}/mkinit ${.ALLSRC:S,^${.OBJDIR}/mkinit$,,}
|
|
||||||
|
|
||||||
# C. Generates C sources from shell scripts
|
|
||||||
token.h:
|
|
||||||
${.CURDIR}/mktokens.sh
|
|
||||||
|
|
||||||
builtins.c builtins.h:
|
|
||||||
${.CURDIR}/mkbuiltins.sh ${MKB_NO_JOBS} . ${.CURDIR}/shell.h ${.CURDIR}/builtins.def
|
|
||||||
|
|
||||||
operators.c operators.h:
|
|
||||||
${.CURDIR}/bltin/mkexpr.sh ${.CURDIR}/bltin/unary_op ${.CURDIR}/bltin/binary_op
|
|
||||||
|
|
||||||
# D. Generates sources from yacc/lex
|
|
||||||
LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
|
||||||
|
|
||||||
YFLAGS:= -d
|
|
||||||
CLEANFILES+= arith.h arith.y.o
|
|
||||||
|
|
||||||
parser.c: token.h
|
|
||||||
y.tab.h: arith.y
|
|
||||||
arith.h: y.tab.h
|
|
||||||
arith_lex.l: arith.h
|
|
||||||
|
|
||||||
# Explicit dependencies to ensure creation when needed
|
|
||||||
# LSC FIXME Under MINIX, the build system curiously needs more help.
|
|
||||||
# is it because of the missing order tools?
|
|
||||||
expand.c: arith.h
|
|
||||||
trap.c: signames.h
|
|
||||||
cd.c complete.c eval.c exec.c expand.c jobs.c main.c options.c parser.c redir.c show.c trap.c var.c: nodes.h
|
|
||||||
eval.c exec.c expand.c input.c input.h jobs.c mystring.c output.c parser.c trap.c var.c: syntax.h
|
|
||||||
cd.c eval.c exec.c histedit.cjobs.c main.c miscbltin.c options.c trap.c var.c: builtins.h
|
|
||||||
|
|
||||||
# LSC: Seems that this file is implicitly taken into account by NetBSD's make,
|
|
||||||
# still seems to be ignored / not found currently.
|
|
||||||
# It's a sad story, as it has default rules to manage yacc / lex files. So for
|
|
||||||
# a happy ending here it is explicitly included:
|
|
||||||
.include <sys.mk>
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
%{
|
|
||||||
/*-
|
|
||||||
* 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.
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifndef lint
|
|
||||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
|
||||||
#endif
|
|
||||||
#endif /* not lint */
|
|
||||||
/*
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.19 2004/05/24 10:11:31 stefanf Exp $");
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "expand.h"
|
|
||||||
#include "var.h"
|
|
||||||
%}
|
|
||||||
%union {
|
|
||||||
arith_t l_value;
|
|
||||||
char* s_value;
|
|
||||||
}
|
|
||||||
%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
|
||||||
%token <s_value> ARITH_VAR
|
|
||||||
|
|
||||||
%type <l_value> expr
|
|
||||||
%right ARITH_ASSIGN
|
|
||||||
%right ARITH_ADDASSIGN ARITH_SUBASSIGN
|
|
||||||
%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
|
|
||||||
%right ARITH_RSHASSIGN ARITH_LSHASSIGN
|
|
||||||
%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
|
|
||||||
%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 |
|
|
||||||
ARITH_VAR
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
arith_t arith_val;
|
|
||||||
char *str_val;
|
|
||||||
|
|
||||||
if (lookupvar($1) == NULL)
|
|
||||||
setvarsafe($1, "0", 0);
|
|
||||||
str_val = lookupvar($1);
|
|
||||||
arith_val = strtoarith_t(str_val, &p, 0);
|
|
||||||
/*
|
|
||||||
* Conversion is successful only in case
|
|
||||||
* we've converted _all_ characters.
|
|
||||||
*/
|
|
||||||
if (*p != '\0')
|
|
||||||
yyerror("variable conversion error");
|
|
||||||
$$ = arith_val;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_ASSIGN expr
|
|
||||||
{
|
|
||||||
if (arith_assign($1, $3) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = $3;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_ADDASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) + $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_SUBASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) - $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_MULASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) * $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_DIVASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
if ($3 == 0)
|
|
||||||
yyerror("division by zero");
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) / $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_REMASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
if ($3 == 0)
|
|
||||||
yyerror("division by zero");
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) % $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_RSHASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) >> $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_LSHASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) << $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_BANDASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) & $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_BXORASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) ^ $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} |
|
|
||||||
ARITH_VAR ARITH_BORASSIGN expr
|
|
||||||
{
|
|
||||||
arith_t value;
|
|
||||||
|
|
||||||
value = atoarith_t(lookupvar($1)) | $3;
|
|
||||||
if (arith_assign($1, value) != 0)
|
|
||||||
yyerror("variable assignment error");
|
|
||||||
$$ = value;
|
|
||||||
} ;
|
|
||||||
%%
|
|
||||||
#include "error.h"
|
|
||||||
#include "output.h"
|
|
||||||
#include "memalloc.h"
|
|
||||||
|
|
||||||
#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
|
|
||||||
|
|
||||||
char *arith_buf, *arith_startbuf;
|
|
||||||
|
|
||||||
int yylex(void);
|
|
||||||
int yyparse(void);
|
|
||||||
|
|
||||||
int
|
|
||||||
arith_assign(char *name, arith_t value)
|
|
||||||
{
|
|
||||||
char *str;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
str = (char *)ckmalloc(lstrlen(value));
|
|
||||||
sprintf(str, ARITH_FORMAT_STR, value);
|
|
||||||
ret = setvarsafe(name, str, 0);
|
|
||||||
free(str);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
arith(char *s)
|
|
||||||
{
|
|
||||||
long result;
|
|
||||||
|
|
||||||
arith_buf = arith_startbuf = s;
|
|
||||||
|
|
||||||
INTOFF;
|
|
||||||
result = yyparse();
|
|
||||||
arith_lex_reset(); /* Reprime lex. */
|
|
||||||
INTON;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
yyerror(char *s)
|
|
||||||
{
|
|
||||||
|
|
||||||
yyerrok;
|
|
||||||
yyclearin;
|
|
||||||
arith_lex_reset(); /* Reprime lex. */
|
|
||||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The exp(1) builtin.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expcmd(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("%ld\n", i);
|
|
||||||
return !i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************/
|
|
||||||
#ifdef TEST_ARITH
|
|
||||||
#include <stdio.h>
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
printf("%d\n", exp(argv[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
error(char *s)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "exp: %s\n", s);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,12 +0,0 @@
|
||||||
/*
|
|
||||||
arith_lex.h
|
|
||||||
|
|
||||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
int yylex(void);
|
|
||||||
void arith_lex_reset(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* $PchId: arith_lex.h,v 1.1 2001/05/18 19:57:55 philip Exp $
|
|
||||||
*/
|
|
|
@ -1,40 +0,0 @@
|
||||||
ASH GENERAL PUBLIC LICENSE
|
|
||||||
|
|
||||||
1. You may copy and distribute ash code or code derived from it in
|
|
||||||
source or object form, provided that you conspicuously and appropriately
|
|
||||||
publish on each copy a valid copyright notice "Copyright 1989 by Kenneth
|
|
||||||
Almquist." (or with whatever year is appropriate); keep intact the
|
|
||||||
notices on all files that refer to this License Agreement and to the
|
|
||||||
absence of any warranty; and give any other recipients of the ash program
|
|
||||||
a copy of this License Agreement along with the program.
|
|
||||||
|
|
||||||
2. You may not copy, sublicense, distribute or transfer ash except as
|
|
||||||
expressly provided under this License Agreement. Any attempt otherwise
|
|
||||||
to copy, sublicense, distribute or transfer ash is void and your rights
|
|
||||||
to use ash under this License agreement shall be automatically terminated.
|
|
||||||
However, parties who have received computer software programs from you
|
|
||||||
with this License Agreement will not have their licenses terminated so
|
|
||||||
long as such parties remain in full compliance.
|
|
||||||
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
Because ash is licensed free of charge, I provide absolutely no
|
|
||||||
warranty, to the extent permitted by applicable state law. Except
|
|
||||||
when otherwise stated in writing, Kenneth Almquist and/or other
|
|
||||||
parties provide ash "as is" without warranty of any kind, either
|
|
||||||
expressed or implied, including, but not limited to, the implied
|
|
||||||
warranties of merchantability and fitness for a particular purpose.
|
|
||||||
The entire risk as to the quality and performance of the program is
|
|
||||||
with you. Should the ash program prove defective, you assume the cost
|
|
||||||
of all necessary servicing, repair or correction.
|
|
||||||
|
|
||||||
In no event unless required by applicable law will Kenneth Almquist
|
|
||||||
and/or any other party who may modify and redistribute ash as permitted
|
|
||||||
above, be liable to you for damages, including any lost profits, lost
|
|
||||||
monies, or other special, incidental or consequential damages arising
|
|
||||||
out of the use or inability to use (including but not limited to loss
|
|
||||||
of data or data being rendered inaccurate or losses sustained by third
|
|
||||||
parties or a failure of the program to operate with programs provided
|
|
||||||
by other parties) the program, even if you have been advised of the
|
|
||||||
possibility of such damages, or for any claim by any other party.
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/bltin
|
|
||||||
|
|
||||||
SRCS+= echo.c error.c expr.c regexp.c
|
|
||||||
|
|
||||||
# LSC Again nbmake seems dumber on MINIX...
|
|
||||||
expr.c: operators.h
|
|
|
@ -1,27 +0,0 @@
|
||||||
# List of binary operators used by test/expr.
|
|
||||||
#
|
|
||||||
# Copyright 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
# This file is part of ash, which is distributed under the terms specified
|
|
||||||
# by the Ash General Public License. See the file named LICENSE.
|
|
||||||
|
|
||||||
OR1 -o 1
|
|
||||||
OR2 | 1
|
|
||||||
AND1 -a 2
|
|
||||||
AND2 & 2
|
|
||||||
STREQ = 4 OP_STRING
|
|
||||||
STRNE != 4 OP_STRING
|
|
||||||
NEWER -newer 4 OP_STRING
|
|
||||||
NEWER -nt 4 OP_STRING
|
|
||||||
OLDER -ot 4 OP_STRING
|
|
||||||
EQ -eq 4 OP_INT
|
|
||||||
NE -ne 4 OP_INT
|
|
||||||
GT -gt 4 OP_INT
|
|
||||||
LT -lt 4 OP_INT
|
|
||||||
LE -le 4 OP_INT
|
|
||||||
GE -ge 4 OP_INT
|
|
||||||
PLUS + 5 OP_INT
|
|
||||||
MINUS - 5 OP_INT
|
|
||||||
TIMES * 6 OP_INT
|
|
||||||
DIVIDE / 6 OP_INT
|
|
||||||
REM % 6 OP_INT
|
|
||||||
MATCHPAT : 7 OP_STRING
|
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* Copy the files given as arguments to the standard output. The file
|
|
||||||
* name "-" refers to the standard input.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define main catfcmd
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
#include "../error.h"
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SBUFSIZE
|
|
||||||
#define BUFSIZE() SBUFSIZE
|
|
||||||
#else
|
|
||||||
#ifdef MAXBSIZE
|
|
||||||
#define BUFSIZE() MAXBSIZE
|
|
||||||
#else
|
|
||||||
#define BUFSIZE() BSIZE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
|
||||||
char *filename;
|
|
||||||
char *buf = stalloc(BUFSIZE());
|
|
||||||
int fd;
|
|
||||||
int i;
|
|
||||||
#ifdef SHELL
|
|
||||||
volatile int input;
|
|
||||||
struct jmploc jmploc;
|
|
||||||
struct jmploc *volatile savehandler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INITARGS(argv);
|
|
||||||
#ifdef SHELL
|
|
||||||
input = -1;
|
|
||||||
if (setjmp(jmploc.loc)) {
|
|
||||||
close(input);
|
|
||||||
handler = savehandler;
|
|
||||||
longjmp(handler, 1);
|
|
||||||
}
|
|
||||||
savehandler = handler;
|
|
||||||
handler = &jmploc;
|
|
||||||
#endif
|
|
||||||
while ((filename = *++argv) != NULL) {
|
|
||||||
if (filename[0] == '-' && filename[1] == '\0') {
|
|
||||||
fd = 0;
|
|
||||||
} else {
|
|
||||||
#ifdef SHELL
|
|
||||||
INTOFF;
|
|
||||||
if ((fd = open(filename, O_RDONLY)) < 0)
|
|
||||||
error("Can't open %s", filename);
|
|
||||||
input = fd;
|
|
||||||
INTON;
|
|
||||||
#else
|
|
||||||
if ((fd = open(filename, O_RDONLY)) < 0) {
|
|
||||||
fprintf(stderr, "catf: Can't open %s\n", filename);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
while ((i = read(fd, buf, BUFSIZE())) > 0) {
|
|
||||||
#ifdef SHELL
|
|
||||||
if (out1 == &memout) {
|
|
||||||
register char *p;
|
|
||||||
for (p = buf ; --i >= 0 ; p++) {
|
|
||||||
outc(*p, &memout);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
write(1, buf, i);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
write(1, buf, i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (fd != 0)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
#ifdef SHELL
|
|
||||||
handler = savehandler;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
char *commandname;
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
#ifdef __STDC__
|
|
||||||
error(char *msg, ...) {
|
|
||||||
#else
|
|
||||||
error(msg)
|
|
||||||
char *msg;
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: %s\n", commandname, msg);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
|
@ -1,482 +0,0 @@
|
||||||
/*
|
|
||||||
* The expr and test commands.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
#include "operators.h"
|
|
||||||
#include <regex.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define STACKSIZE 12
|
|
||||||
#define NESTINCR 16
|
|
||||||
|
|
||||||
/* data types */
|
|
||||||
#define STRING 0
|
|
||||||
#define INTEGER 1
|
|
||||||
#define BOOLEAN 2
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This structure hold a value. The type keyword specifies the type of
|
|
||||||
* the value, and the union u holds the value. The value of a boolean
|
|
||||||
* is stored in u.num (1 = TRUE, 0 = FALSE).
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct value {
|
|
||||||
int type;
|
|
||||||
union {
|
|
||||||
char *string;
|
|
||||||
long num;
|
|
||||||
} u;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct operator {
|
|
||||||
short op; /* which operator */
|
|
||||||
short pri; /* priority of operator */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct filestat {
|
|
||||||
char *name; /* name of file */
|
|
||||||
int rcode; /* return code from stat */
|
|
||||||
struct stat stat; /* status info on file */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern char *match_begin[10]; /* matched string */
|
|
||||||
extern short match_length[10]; /* defined in regexp.c */
|
|
||||||
extern short number_parens; /* number of \( \) pairs */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
static int expr_is_false(struct value *);
|
|
||||||
static void expr_operator(int, struct value *, struct filestat *);
|
|
||||||
static int lookup_op(char *, char *const*);
|
|
||||||
#else
|
|
||||||
static int expr_is_false();
|
|
||||||
static void expr_operator();
|
|
||||||
static int lookup_op();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int exprcmd(argc, argv) int argc; char **argv; {
|
|
||||||
char **ap;
|
|
||||||
char *opname;
|
|
||||||
char c;
|
|
||||||
char *p;
|
|
||||||
int print;
|
|
||||||
int nest; /* parenthises nesting */
|
|
||||||
int op;
|
|
||||||
int pri;
|
|
||||||
int skipping;
|
|
||||||
int binary;
|
|
||||||
struct operator opstack[STACKSIZE];
|
|
||||||
struct operator *opsp;
|
|
||||||
struct value valstack[STACKSIZE + 1];
|
|
||||||
struct value *valsp;
|
|
||||||
struct filestat fs;
|
|
||||||
|
|
||||||
INITARGS(argv);
|
|
||||||
c = **argv;
|
|
||||||
print = 1;
|
|
||||||
if (c == 't')
|
|
||||||
print = 0;
|
|
||||||
else if (c == '[') {
|
|
||||||
if (! equal(argv[argc - 1], "]"))
|
|
||||||
error("missing ]");
|
|
||||||
argv[argc - 1] = NULL;
|
|
||||||
print = 0;
|
|
||||||
}
|
|
||||||
ap = argv + 1;
|
|
||||||
fs.name = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We use operator precedence parsing, evaluating the expression
|
|
||||||
* as we parse it. Parentheses are handled by bumping up the
|
|
||||||
* priority of operators using the variable "nest." We use the
|
|
||||||
* variable "skipping" to turn off evaluation temporarily for the
|
|
||||||
* short circuit boolean operators. (It is important do the short
|
|
||||||
* circuit evaluation because under NFS a stat operation can take
|
|
||||||
* infinitely long.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
nest = 0;
|
|
||||||
skipping = 0;
|
|
||||||
opsp = opstack + STACKSIZE;
|
|
||||||
valsp = valstack;
|
|
||||||
if (*ap == NULL) {
|
|
||||||
valstack[0].type = BOOLEAN;
|
|
||||||
valstack[0].u.num = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
opname = *ap++;
|
|
||||||
if (opname == NULL)
|
|
||||||
syntax: error("syntax error");
|
|
||||||
if (opname[0] == '(' && opname[1] == '\0') {
|
|
||||||
nest += NESTINCR;
|
|
||||||
continue;
|
|
||||||
} else if (*ap && (op = lookup_op(opname, unary_op)) >= 0) {
|
|
||||||
if (opsp == &opstack[0])
|
|
||||||
overflow: error("Expression too complex");
|
|
||||||
--opsp;
|
|
||||||
opsp->op = op;
|
|
||||||
opsp->pri = op_priority[op] + nest;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (opname[0] == '\'') {
|
|
||||||
for (p = opname ; *++p != '\0' ; );
|
|
||||||
if (--p > opname && *p == '\'') {
|
|
||||||
*p = '\0';
|
|
||||||
opname++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
valsp->type = STRING;
|
|
||||||
valsp->u.string = opname;
|
|
||||||
valsp++;
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
opname = *ap++;
|
|
||||||
if (opname == NULL) {
|
|
||||||
if (nest != 0)
|
|
||||||
goto syntax;
|
|
||||||
pri = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (opname[0] != ')' || opname[1] != '\0') {
|
|
||||||
if ((op = lookup_op(opname, binary_op)) < 0)
|
|
||||||
goto syntax;
|
|
||||||
op += FIRST_BINARY_OP;
|
|
||||||
pri = op_priority[op] + nest;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((nest -= NESTINCR) < 0)
|
|
||||||
goto syntax;
|
|
||||||
}
|
|
||||||
while (opsp < &opstack[STACKSIZE] && opsp->pri >= pri) {
|
|
||||||
binary = opsp->op;
|
|
||||||
for (;;) {
|
|
||||||
valsp--;
|
|
||||||
c = op_argflag[opsp->op];
|
|
||||||
if (c == OP_INT) {
|
|
||||||
if (valsp->type == STRING)
|
|
||||||
valsp->u.num = atol(valsp->u.string);
|
|
||||||
valsp->type = INTEGER;
|
|
||||||
} else if (c >= OP_STRING) { /* OP_STRING or OP_FILE */
|
|
||||||
if (valsp->type == INTEGER) {
|
|
||||||
p = stalloc(32);
|
|
||||||
#ifdef SHELL
|
|
||||||
fmtstr(p, 32, "%ld", valsp->u.num);
|
|
||||||
#else
|
|
||||||
sprintf(p, "%d", valsp->u.num);
|
|
||||||
#endif
|
|
||||||
valsp->u.string = p;
|
|
||||||
} else if (valsp->type == BOOLEAN) {
|
|
||||||
if (valsp->u.num)
|
|
||||||
valsp->u.string = "true";
|
|
||||||
else
|
|
||||||
valsp->u.string = "";
|
|
||||||
}
|
|
||||||
valsp->type = STRING;
|
|
||||||
if (c == OP_FILE
|
|
||||||
&& (fs.name == NULL
|
|
||||||
|| ! equal(fs.name, valsp->u.string))) {
|
|
||||||
fs.name = valsp->u.string;
|
|
||||||
fs.rcode = stat(valsp->u.string, &fs.stat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (binary < FIRST_BINARY_OP)
|
|
||||||
break;
|
|
||||||
binary = 0;
|
|
||||||
}
|
|
||||||
if (! skipping)
|
|
||||||
expr_operator(opsp->op, valsp, &fs);
|
|
||||||
else if (opsp->op == AND1 || opsp->op == OR1)
|
|
||||||
skipping--;
|
|
||||||
valsp++; /* push value */
|
|
||||||
opsp++; /* pop operator */
|
|
||||||
}
|
|
||||||
if (opname == NULL)
|
|
||||||
break;
|
|
||||||
if (opsp == &opstack[0])
|
|
||||||
goto overflow;
|
|
||||||
if (op == AND1 || op == AND2) {
|
|
||||||
op = AND1;
|
|
||||||
if (skipping || expr_is_false(valsp - 1))
|
|
||||||
skipping++;
|
|
||||||
}
|
|
||||||
if (op == OR1 || op == OR2) {
|
|
||||||
op = OR1;
|
|
||||||
if (skipping || ! expr_is_false(valsp - 1))
|
|
||||||
skipping++;
|
|
||||||
}
|
|
||||||
opsp--;
|
|
||||||
opsp->op = op;
|
|
||||||
opsp->pri = pri;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
if (print) {
|
|
||||||
if (valstack[0].type == STRING)
|
|
||||||
printf("%s\n", valstack[0].u.string);
|
|
||||||
else if (valstack[0].type == INTEGER)
|
|
||||||
printf("%ld\n", valstack[0].u.num);
|
|
||||||
else if (valstack[0].u.num != 0)
|
|
||||||
printf("true\n");
|
|
||||||
}
|
|
||||||
return expr_is_false(&valstack[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
expr_is_false(val)
|
|
||||||
struct value *val;
|
|
||||||
{
|
|
||||||
if (val->type == STRING) {
|
|
||||||
if (val->u.string[0] == '\0')
|
|
||||||
return 1;
|
|
||||||
} else { /* INTEGER or BOOLEAN */
|
|
||||||
if (val->u.num == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute an operator. Op is the operator. Sp is the stack pointer;
|
|
||||||
* sp[0] refers to the first operand, sp[1] refers to the second operand
|
|
||||||
* (if any), and the result is placed in sp[0]. The operands are converted
|
|
||||||
* to the type expected by the operator before expr_operator is called.
|
|
||||||
* Fs is a pointer to a structure which holds the value of the last call
|
|
||||||
* to stat, to avoid repeated stat calls on the same file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
expr_operator(op, sp, fs)
|
|
||||||
int op;
|
|
||||||
struct value *sp;
|
|
||||||
struct filestat *fs;
|
|
||||||
{
|
|
||||||
int i, r;
|
|
||||||
struct stat st1, st2;
|
|
||||||
regex_t pat;
|
|
||||||
regmatch_t rm[2];
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
case NOT:
|
|
||||||
sp->u.num = expr_is_false(sp);
|
|
||||||
sp->type = BOOLEAN;
|
|
||||||
break;
|
|
||||||
case EXISTS:
|
|
||||||
if (fs->rcode >= 0) goto true;
|
|
||||||
goto false;
|
|
||||||
case ISREAD:
|
|
||||||
i = 04;
|
|
||||||
goto permission;
|
|
||||||
case ISWRITE:
|
|
||||||
i = 02;
|
|
||||||
goto permission;
|
|
||||||
case ISEXEC:
|
|
||||||
i = 01;
|
|
||||||
permission:
|
|
||||||
if (fs->stat.st_uid == geteuid())
|
|
||||||
i <<= 6;
|
|
||||||
else if (fs->stat.st_gid == getegid())
|
|
||||||
i <<= 3;
|
|
||||||
goto filebit; /* true if (stat.st_mode & i) != 0 */
|
|
||||||
case ISFILE:
|
|
||||||
i = S_IFREG;
|
|
||||||
goto filetype;
|
|
||||||
case ISDIR:
|
|
||||||
i = S_IFDIR;
|
|
||||||
goto filetype;
|
|
||||||
case ISCHAR:
|
|
||||||
i = S_IFCHR;
|
|
||||||
goto filetype;
|
|
||||||
case ISBLOCK:
|
|
||||||
i = S_IFBLK;
|
|
||||||
goto filetype;
|
|
||||||
case ISFIFO:
|
|
||||||
#ifdef S_IFIFO
|
|
||||||
i = S_IFIFO;
|
|
||||||
goto filetype;
|
|
||||||
#else
|
|
||||||
goto false;
|
|
||||||
#endif
|
|
||||||
filetype:
|
|
||||||
if ((fs->stat.st_mode & S_IFMT) == i && fs->rcode >= 0) {
|
|
||||||
true:
|
|
||||||
sp->u.num = 1;
|
|
||||||
} else {
|
|
||||||
false:
|
|
||||||
sp->u.num = 0;
|
|
||||||
}
|
|
||||||
sp->type = BOOLEAN;
|
|
||||||
break;
|
|
||||||
case ISSETUID:
|
|
||||||
i = S_ISUID;
|
|
||||||
goto filebit;
|
|
||||||
case ISSETGID:
|
|
||||||
i = S_ISGID;
|
|
||||||
goto filebit;
|
|
||||||
case ISSTICKY:
|
|
||||||
i = S_ISVTX;
|
|
||||||
filebit:
|
|
||||||
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case ISSLINK:
|
|
||||||
if (lstat(fs->name, &st1) == -1)
|
|
||||||
goto false;
|
|
||||||
if (S_ISLNK(st1.st_mode))
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case ISSIZE:
|
|
||||||
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
|
|
||||||
sp->type = INTEGER;
|
|
||||||
break;
|
|
||||||
case OLDER:
|
|
||||||
case NEWER:
|
|
||||||
if (stat(sp->u.string, &st1) != 0) {
|
|
||||||
sp->u.num = 0;
|
|
||||||
} else if (stat((sp + 1)->u.string, &st2) != 0) {
|
|
||||||
sp->u.num = 1;
|
|
||||||
} else {
|
|
||||||
int isnewer = st1.st_mtime >= st2.st_mtime;
|
|
||||||
if(op == NEWER)
|
|
||||||
sp->u.num = isnewer;
|
|
||||||
else
|
|
||||||
sp->u.num = !isnewer;
|
|
||||||
}
|
|
||||||
sp->type = INTEGER;
|
|
||||||
break;
|
|
||||||
case ISTTY:
|
|
||||||
sp->u.num = isatty(sp->u.num);
|
|
||||||
sp->type = BOOLEAN;
|
|
||||||
break;
|
|
||||||
case NULSTR:
|
|
||||||
if (sp->u.string[0] == '\0')
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case STRLEN:
|
|
||||||
sp->u.num = strlen(sp->u.string);
|
|
||||||
sp->type = INTEGER;
|
|
||||||
break;
|
|
||||||
case OR1:
|
|
||||||
case AND1:
|
|
||||||
/*
|
|
||||||
* These operators are mostly handled by the parser. If we
|
|
||||||
* get here it means that both operands were evaluated, so
|
|
||||||
* the value is the value of the second operand.
|
|
||||||
*/
|
|
||||||
*sp = *(sp + 1);
|
|
||||||
break;
|
|
||||||
case STREQ:
|
|
||||||
case STRNE:
|
|
||||||
i = 0;
|
|
||||||
if (equal(sp->u.string, (sp + 1)->u.string))
|
|
||||||
i++;
|
|
||||||
if (op == STRNE)
|
|
||||||
i = 1 - i;
|
|
||||||
sp->u.num = i;
|
|
||||||
sp->type = BOOLEAN;
|
|
||||||
break;
|
|
||||||
case EQ:
|
|
||||||
if (sp->u.num == (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case NE:
|
|
||||||
if (sp->u.num != (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case GT:
|
|
||||||
if (sp->u.num > (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case LT:
|
|
||||||
if (sp->u.num < (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case LE:
|
|
||||||
if (sp->u.num <= (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case GE:
|
|
||||||
if (sp->u.num >= (sp + 1)->u.num)
|
|
||||||
goto true;
|
|
||||||
goto false;
|
|
||||||
case PLUS:
|
|
||||||
sp->u.num += (sp + 1)->u.num;
|
|
||||||
break;
|
|
||||||
case MINUS:
|
|
||||||
sp->u.num -= (sp + 1)->u.num;
|
|
||||||
break;
|
|
||||||
case TIMES:
|
|
||||||
sp->u.num *= (sp + 1)->u.num;
|
|
||||||
break;
|
|
||||||
case DIVIDE:
|
|
||||||
if ((sp + 1)->u.num == 0)
|
|
||||||
error("Division by zero");
|
|
||||||
sp->u.num /= (sp + 1)->u.num;
|
|
||||||
break;
|
|
||||||
case REM:
|
|
||||||
if ((sp + 1)->u.num == 0)
|
|
||||||
error("Division by zero");
|
|
||||||
sp->u.num %= (sp + 1)->u.num;
|
|
||||||
break;
|
|
||||||
case MATCHPAT:
|
|
||||||
{
|
|
||||||
r = regcomp(&pat, (sp + 1)->u.string, 0);
|
|
||||||
if (r)
|
|
||||||
error("Bad regular expression");
|
|
||||||
if (regexec(&pat, sp->u.string, 2, rm, 0) == 0 &&
|
|
||||||
rm[0].rm_so == 0)
|
|
||||||
{
|
|
||||||
if (pat.re_nsub > 0) {
|
|
||||||
sp->u.string[rm[1].rm_eo] = '\0';
|
|
||||||
sp->u.string = sp->u.string+rm[1].rm_so;
|
|
||||||
} else {
|
|
||||||
sp->u.num = rm[0].rm_eo;
|
|
||||||
sp->type = INTEGER;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (pat.re_nsub > 0) {
|
|
||||||
sp->u.string[0] = '\0';
|
|
||||||
} else {
|
|
||||||
sp->u.num = 0;
|
|
||||||
sp->type = INTEGER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
lookup_op(name, table)
|
|
||||||
char *name;
|
|
||||||
char *const*table;
|
|
||||||
{
|
|
||||||
register char *const*tp;
|
|
||||||
register char const *p;
|
|
||||||
char c = name[1];
|
|
||||||
|
|
||||||
for (tp = table ; (p = *tp) != NULL ; tp++) {
|
|
||||||
if (p[1] == c && equal(p, name))
|
|
||||||
return tp - table;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* The line command. Reads one line from the standard input and writes it
|
|
||||||
* to the standard output.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define main linecmd
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
|
||||||
char c;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (read(0, &c, 1) != 1) {
|
|
||||||
putchar('\n');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
putchar(c);
|
|
||||||
if (c == '\n')
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
# This file is part of ash, which is distributed under the terms specified
|
|
||||||
# by the Ash General Public License. See the file named LICENSE.
|
|
||||||
|
|
||||||
LIBFILES=catfcmd.o echocmd.o exprcmd.o linecmd.o nlechocmd.o\
|
|
||||||
operators.o regexp.o
|
|
||||||
DEBUG=-g
|
|
||||||
CFLAGS=$(DEBUG)
|
|
||||||
#CC=gcc
|
|
||||||
|
|
||||||
all:$P bltinlib.a catf echo expr line nlecho true umask
|
|
||||||
|
|
||||||
bltinlib.a:$P $(LIBFILES)
|
|
||||||
ar rc $@ $(LIBFILES)
|
|
||||||
|
|
||||||
catf: catf.c bltin.h ../shell.h ../error.h error.o stalloc.o
|
|
||||||
$(CC) $(CFLAGS) -o $@ catf.c error.o stalloc.o
|
|
||||||
|
|
||||||
catfcmd.o: catf.c bltin.h ../shell.h ../error.h
|
|
||||||
$(CC) -DSHELL $(CFLAGS) -c catf.c
|
|
||||||
mv catf.o $@
|
|
||||||
|
|
||||||
expr: expr.c bltin.h ../shell.h operators.h operators.o regexp.o error.o stalloc.o
|
|
||||||
$(CC) $(CFLAGS) -o $@ expr.c operators.o regexp.o error.o stalloc.o
|
|
||||||
-rm -f test '['
|
|
||||||
ln expr test
|
|
||||||
ln expr '['
|
|
||||||
|
|
||||||
exprcmd.o: expr.c bltin.h ../shell.h operators.h
|
|
||||||
$(CC) -DSHELL $(CFLAGS) -c expr.c
|
|
||||||
mv expr.o $@
|
|
||||||
|
|
||||||
operators.c operators.h: unary_op binary_op mkexpr
|
|
||||||
./mkexpr
|
|
||||||
|
|
||||||
operators.o: ../shell.h operators.h
|
|
||||||
|
|
||||||
regexp.o: bltin.h ../shell.h
|
|
||||||
|
|
||||||
echo: echo.c bltin.h ../shell.h
|
|
||||||
$(CC) $(CFLAGS) -o $@ echo.c
|
|
||||||
|
|
||||||
echocmd.o: echo.c bltin.h ../shell.h
|
|
||||||
$(CC) -DSHELL $(CFLAGS) -c echo.c
|
|
||||||
mv echo.o $@
|
|
||||||
|
|
||||||
line: line.c bltin.h ../shell.h
|
|
||||||
$(CC) $(CFLAGS) -o $@ line.c
|
|
||||||
|
|
||||||
linecmd.o: line.c bltin.h ../shell.h
|
|
||||||
$(CC) -DSHELL $(CFLAGS) -c line.c
|
|
||||||
mv line.o $@
|
|
||||||
|
|
||||||
nlecho: nlecho.c bltin.h ../shell.h
|
|
||||||
$(CC) $(CFLAGS) -o $@ nlecho.c
|
|
||||||
|
|
||||||
nlechocmd.o: nlecho.c bltin.h ../shell.h
|
|
||||||
$(CC) -DSHELL $(CFLAGS) -c nlecho.c
|
|
||||||
mv nlecho.o $@
|
|
||||||
|
|
||||||
umask: umask.c bltin.h
|
|
||||||
$(CC) $(CFLAGS) -o $@ umask.c
|
|
||||||
|
|
||||||
true:
|
|
||||||
> :
|
|
||||||
chmod 755 :
|
|
||||||
rm -f true
|
|
||||||
ln : true
|
|
||||||
|
|
||||||
stalloc.o: ../shell.h
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# Copyright 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
#
|
|
||||||
# This file is part of ash. Ash is distributed under the terms specified
|
|
||||||
# by the Ash General Public License. See the file named LICENSE.
|
|
||||||
|
|
||||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
|
||||||
|
|
||||||
if [ $# -ne 2 ]
|
|
||||||
then
|
|
||||||
echo "Usage: $0 <unary_op> <binary_op>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
unary_op="$1"
|
|
||||||
binary_op="$2"
|
|
||||||
|
|
||||||
exec > operators.h
|
|
||||||
i=0
|
|
||||||
sed -e '/^[^#]/!d' "$unary_op" "$binary_op" | while read line
|
|
||||||
do
|
|
||||||
set -$- $line
|
|
||||||
echo "#define $1 $i"
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
echo
|
|
||||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' "$unary_op" | wc -l`
|
|
||||||
echo '
|
|
||||||
#define OP_INT 1 /* arguments to operator are integer */
|
|
||||||
#define OP_STRING 2 /* arguments to operator are string */
|
|
||||||
#define OP_FILE 3 /* argument is a file name */
|
|
||||||
|
|
||||||
extern char *const unary_op[];
|
|
||||||
extern char *const binary_op[];
|
|
||||||
extern const char op_priority[];
|
|
||||||
extern const char op_argflag[];'
|
|
||||||
|
|
||||||
exec > operators.c
|
|
||||||
echo '/*
|
|
||||||
* Operators used in the expr/test command.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "shell.h"
|
|
||||||
#include "operators.h"
|
|
||||||
|
|
||||||
char *const unary_op[] = {'
|
|
||||||
sed -e '/^[^#]/!d
|
|
||||||
s/[ ][ ]*/ /g
|
|
||||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
|
||||||
' "$unary_op"
|
|
||||||
echo ' NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
char *const binary_op[] = {'
|
|
||||||
sed -e '/^[^#]/!d
|
|
||||||
s/[ ][ ]*/ /g
|
|
||||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
|
||||||
' "$binary_op"
|
|
||||||
echo ' NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
const char op_priority[] = {'
|
|
||||||
sed -e '/^[^#]/!d
|
|
||||||
s/[ ][ ]*/ /g
|
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
|
|
||||||
' "$unary_op" "$binary_op"
|
|
||||||
echo '};
|
|
||||||
|
|
||||||
const char op_argflag[] = {'
|
|
||||||
sed -e '/^[^#]/!d
|
|
||||||
s/[ ][ ]*/ /g
|
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
|
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
|
|
||||||
' "$unary_op" "$binary_op"
|
|
||||||
echo '};'
|
|
|
@ -1,8 +0,0 @@
|
||||||
/*
|
|
||||||
myregexp.h
|
|
||||||
|
|
||||||
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *re_compile(char *pattern);
|
|
||||||
int re_match(char *pattern, char *string);
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Echo the command argument to the standard output, one line at a time.
|
|
||||||
* This command is useful for debugging th shell and whenever you what
|
|
||||||
* to output strings literally.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define main nlechocmd
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
|
||||||
register char **ap;
|
|
||||||
|
|
||||||
for (ap = argv + 1 ; *ap ; ap++) {
|
|
||||||
fputs(*ap, stdout);
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,301 +0,0 @@
|
||||||
/*
|
|
||||||
* Regular expression matching for expr(1). Bugs: The upper bound of
|
|
||||||
* a range specified by the \{ feature cannot be zero.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "bltin.h"
|
|
||||||
#include "myregexp.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define RE_END 0 /* end of regular expression */
|
|
||||||
#define RE_LITERAL 1 /* normal character follows */
|
|
||||||
#define RE_DOT 2 /* "." */
|
|
||||||
#define RE_CCL 3 /* "[...]" */
|
|
||||||
#define RE_NCCL 4 /* "[^...]" */
|
|
||||||
#define RE_LP 5 /* "\(" */
|
|
||||||
#define RE_RP 6 /* "\)" */
|
|
||||||
#define RE_MATCHED 7 /* "\digit" */
|
|
||||||
#define RE_EOS 8 /* "$" matches end of string */
|
|
||||||
#define RE_STAR 9 /* "*" */
|
|
||||||
#define RE_RANGE 10 /* "\{num,num\}" */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *match_begin[10];
|
|
||||||
short match_length[10];
|
|
||||||
short number_parens;
|
|
||||||
static int match(char *pattern, char *string);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
re_compile(pattern)
|
|
||||||
char *pattern;
|
|
||||||
{
|
|
||||||
register char *p;
|
|
||||||
register char c;
|
|
||||||
char *comp;
|
|
||||||
register char *q;
|
|
||||||
char *begin;
|
|
||||||
char *endp;
|
|
||||||
register int len;
|
|
||||||
int first;
|
|
||||||
int type;
|
|
||||||
char *stackp;
|
|
||||||
char stack[10];
|
|
||||||
int paren_num;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
p = pattern;
|
|
||||||
if (*p == '^')
|
|
||||||
p++;
|
|
||||||
comp = q = malloc(2 * strlen(p) + 1);
|
|
||||||
begin = q;
|
|
||||||
stackp = stack;
|
|
||||||
paren_num = 0;
|
|
||||||
for (;;) {
|
|
||||||
switch (c = *p++) {
|
|
||||||
case '\0':
|
|
||||||
*q = '\0';
|
|
||||||
goto out;
|
|
||||||
case '.':
|
|
||||||
*q++ = RE_DOT;
|
|
||||||
len = 1;
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
begin = q;
|
|
||||||
*q = RE_CCL;
|
|
||||||
if (*p == '^') {
|
|
||||||
*q = RE_NCCL;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
q++;
|
|
||||||
first = 1;
|
|
||||||
while (*p != ']' || first == 1) {
|
|
||||||
if (p[1] == '-' && p[2] != ']') {
|
|
||||||
*q++ = '-';
|
|
||||||
*q++ = p[0];
|
|
||||||
*q++ = p[2];
|
|
||||||
p += 3;
|
|
||||||
} else if (*p == '-') {
|
|
||||||
*q++ = '-';
|
|
||||||
*q++ = '-';
|
|
||||||
*q++ = '-';
|
|
||||||
p++;
|
|
||||||
} else {
|
|
||||||
*q++ = *p++;
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
*q++ = '\0';
|
|
||||||
len = q - begin;
|
|
||||||
break;
|
|
||||||
case '$':
|
|
||||||
if (*p != '\0')
|
|
||||||
goto dft;
|
|
||||||
*q++ = RE_EOS;
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
if (len == 0)
|
|
||||||
goto dft;
|
|
||||||
type = RE_STAR;
|
|
||||||
range:
|
|
||||||
i = (type == RE_RANGE)? 3 : 1;
|
|
||||||
endp = q + i;
|
|
||||||
begin = q - len;
|
|
||||||
do {
|
|
||||||
--q;
|
|
||||||
*(q + i) = *q;
|
|
||||||
} while (--len > 0);
|
|
||||||
q = begin;
|
|
||||||
*q++ = type;
|
|
||||||
if (type == RE_RANGE) {
|
|
||||||
i = 0;
|
|
||||||
while ((unsigned)(*p - '0') <= 9)
|
|
||||||
i = 10 * i + (*p++ - '0');
|
|
||||||
*q++ = i;
|
|
||||||
if (*p != ',') {
|
|
||||||
*q++ = i;
|
|
||||||
} else {
|
|
||||||
p++;
|
|
||||||
i = 0;
|
|
||||||
while ((unsigned)(*p - '0') <= 9)
|
|
||||||
i = 10 * i + (*p++ - '0');
|
|
||||||
*q++ = i;
|
|
||||||
}
|
|
||||||
if (*p != '\\' || *++p != '}')
|
|
||||||
error("RE error");
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
q = endp;
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
if ((c = *p++) == '(') {
|
|
||||||
if (++paren_num > 9)
|
|
||||||
error("RE error");
|
|
||||||
*q++ = RE_LP;
|
|
||||||
*q++ = paren_num;
|
|
||||||
*stackp++ = paren_num;
|
|
||||||
len = 0;
|
|
||||||
} else if (c == ')') {
|
|
||||||
if (stackp == stack)
|
|
||||||
error("RE error");
|
|
||||||
*q++ = RE_RP;
|
|
||||||
*q++ = *--stackp;
|
|
||||||
len = 0;
|
|
||||||
} else if (c == '{') {
|
|
||||||
type = RE_RANGE;
|
|
||||||
goto range;
|
|
||||||
} else if ((unsigned)(c - '1') < 9) {
|
|
||||||
/* should check validity here */
|
|
||||||
*q++ = RE_MATCHED;
|
|
||||||
*q++ = c - '0';
|
|
||||||
len = 2;
|
|
||||||
} else {
|
|
||||||
goto dft;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dft: *q++ = RE_LITERAL;
|
|
||||||
*q++ = c;
|
|
||||||
len = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (stackp != stack)
|
|
||||||
error("RE error");
|
|
||||||
number_parens = paren_num;
|
|
||||||
return comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
re_match(pattern, string)
|
|
||||||
char *pattern;
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
char **pp;
|
|
||||||
|
|
||||||
match_begin[0] = string;
|
|
||||||
for (pp = &match_begin[1] ; pp <= &match_begin[9] ; pp++)
|
|
||||||
*pp = 0;
|
|
||||||
return match(pattern, string);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
match(pattern, string)
|
|
||||||
char *pattern;
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
register char *p, *q;
|
|
||||||
int counting;
|
|
||||||
int low, high, count;
|
|
||||||
char *curpat;
|
|
||||||
char *start_count;
|
|
||||||
int negate;
|
|
||||||
int found;
|
|
||||||
char *r;
|
|
||||||
int len;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
p = pattern;
|
|
||||||
q = string;
|
|
||||||
counting = 0;
|
|
||||||
for (;;) {
|
|
||||||
if (counting) {
|
|
||||||
if (++count > high)
|
|
||||||
goto bad;
|
|
||||||
p = curpat;
|
|
||||||
}
|
|
||||||
switch (*p++) {
|
|
||||||
case RE_END:
|
|
||||||
match_length[0] = q - match_begin[0];
|
|
||||||
return 1;
|
|
||||||
case RE_LITERAL:
|
|
||||||
if (*q++ != *p++)
|
|
||||||
goto bad;
|
|
||||||
break;
|
|
||||||
case RE_DOT:
|
|
||||||
if (*q++ == '\0')
|
|
||||||
goto bad;
|
|
||||||
break;
|
|
||||||
case RE_CCL:
|
|
||||||
negate = 0;
|
|
||||||
goto ccl;
|
|
||||||
case RE_NCCL:
|
|
||||||
negate = 1;
|
|
||||||
ccl:
|
|
||||||
found = 0;
|
|
||||||
c = *q++;
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '-') {
|
|
||||||
if (c >= *++p && c <= *++p)
|
|
||||||
found = 1;
|
|
||||||
} else {
|
|
||||||
if (c == *p)
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
if (found == negate)
|
|
||||||
goto bad;
|
|
||||||
break;
|
|
||||||
case RE_LP:
|
|
||||||
match_begin[*p++] = q;
|
|
||||||
break;
|
|
||||||
case RE_RP:
|
|
||||||
match_length[*p] = q - match_begin[*p];
|
|
||||||
p++;
|
|
||||||
break;
|
|
||||||
case RE_MATCHED:
|
|
||||||
r = match_begin[*p];
|
|
||||||
len = match_length[*p++];
|
|
||||||
while (--len >= 0) {
|
|
||||||
if (*q++ != *r++)
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RE_EOS:
|
|
||||||
if (*q != '\0')
|
|
||||||
goto bad;
|
|
||||||
break;
|
|
||||||
case RE_STAR:
|
|
||||||
low = 0;
|
|
||||||
high = 32767;
|
|
||||||
goto range;
|
|
||||||
case RE_RANGE:
|
|
||||||
low = *p++;
|
|
||||||
high = *p++;
|
|
||||||
if (high == 0)
|
|
||||||
high = 32767;
|
|
||||||
range:
|
|
||||||
curpat = p;
|
|
||||||
start_count = q;
|
|
||||||
count = 0;
|
|
||||||
counting++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bad:
|
|
||||||
if (! counting)
|
|
||||||
return 0;
|
|
||||||
len = 1;
|
|
||||||
if (*curpat == RE_MATCHED)
|
|
||||||
len = match_length[curpat[1]];
|
|
||||||
while (--count >= low) {
|
|
||||||
if (match(p, start_count + count * len))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../shell.h"
|
|
||||||
|
|
||||||
|
|
||||||
void error();
|
|
||||||
pointer malloc();
|
|
||||||
|
|
||||||
|
|
||||||
pointer
|
|
||||||
stalloc(nbytes) {
|
|
||||||
register pointer p;
|
|
||||||
|
|
||||||
if ((p = malloc(nbytes)) == NULL)
|
|
||||||
error("Out of space");
|
|
||||||
return p;
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
|
||||||
int mask;
|
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
fprintf(stderr, "umask: only builtin version of umask can set value\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
printf("%.4o\n", umask(0));
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
# List of unary operators used by test/expr.
|
|
||||||
#
|
|
||||||
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
# This file is part of ash, which is distributed under the terms specified
|
|
||||||
# by the Ash General Public License. See the file named LICENSE.
|
|
||||||
|
|
||||||
NOT ! 3
|
|
||||||
EXISTS -e 12 OP_FILE
|
|
||||||
ISREAD -r 12 OP_FILE
|
|
||||||
ISWRITE -w 12 OP_FILE
|
|
||||||
ISEXEC -x 12 OP_FILE
|
|
||||||
ISFILE -f 12 OP_FILE
|
|
||||||
ISDIR -d 12 OP_FILE
|
|
||||||
ISCHAR -c 12 OP_FILE
|
|
||||||
ISBLOCK -b 12 OP_FILE
|
|
||||||
ISFIFO -p 12 OP_FILE
|
|
||||||
ISSETUID -u 12 OP_FILE
|
|
||||||
ISSETGID -g 12 OP_FILE
|
|
||||||
ISSTICKY -k 12 OP_FILE
|
|
||||||
ISSLINK -h 12 OP_FILE
|
|
||||||
ISSIZE -s 12 OP_FILE
|
|
||||||
ISTTY -t 12 OP_INT
|
|
||||||
NULSTR -z 12 OP_STRING
|
|
||||||
STRLEN -n 12 OP_STRING
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue