mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-04 09:09:56 +00:00
Upgrade csh.
This commit is contained in:
parent
9a823cff39
commit
325c70b76a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=59355
@ -6,36 +6,66 @@
|
||||
#
|
||||
# To profile, put -DPROF in DEFS and -pg in CFLAGS, and recompile.
|
||||
|
||||
TCSHDIR= ${.CURDIR}/../../contrib/tcsh
|
||||
.PATH: ${TCSHDIR}
|
||||
|
||||
PROG= csh
|
||||
DFLAGS=-DBUILTIN -DFILEC -DNLS -DSHORT_STRINGS
|
||||
CFLAGS+=-I${.CURDIR} -I. ${DFLAGS}
|
||||
SRCS= alloc.c char.c const.c csh.c dir.c dol.c err.c exec.c exp.c file.c \
|
||||
func.c glob.c hist.c init.c lex.c misc.c parse.c printf.c proc.c \
|
||||
sem.c set.c str.c time.c const.h errnum.h
|
||||
.PATH: ${.CURDIR}/../../usr.bin/printf
|
||||
DFLAGS= -D_PATH_TCSHELL='"${DESTDIR}/bin/${PROG}"'
|
||||
CFLAGS+= -I${TCSHDIR} -I${.CURDIR} -I. ${DFLAGS}
|
||||
SRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
|
||||
sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
|
||||
sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
|
||||
sh.set.c sh.time.c sh.h sh.char.h sh.dir.h sh.proc.h
|
||||
SRCS+= sh.decls.h glob.c glob.h mi.termios.c mi.wait.h mi.varargs.h
|
||||
SRCS+= tw.decls.h tw.h tw.help.c tw.init.c tw.parse.c tw.spell.c \
|
||||
tw.comp.c tw.color.c
|
||||
SRCS+= ed.chared.c ed.decls.h ed.defns.c ed.h ed.init.c ed.inputl.c \
|
||||
ed.refresh.c ed.screen.c ed.xmap.c ed.term.c ed.term.h
|
||||
SRCS+= tc.alloc.c tc.bind.c tc.const.c tc.decls.h tc.disc.c \
|
||||
tc.func.c tc.os.c tc.os.h tc.printf.c tc.prompt.c \
|
||||
tc.sched.c tc.sig.c tc.sig.h tc.str.c sh.types.h tc.vers.c tc.wait.h \
|
||||
tc.who.c tc.h
|
||||
SRCS+= tc.defs.c
|
||||
|
||||
MAN1= csh.1
|
||||
# MLINKS for Shell built in commands for which there are no userland
|
||||
# utilities of the same name are handled with the associated manpage,
|
||||
# builtin.1 in share/man/man1/.
|
||||
|
||||
CLEANFILES+=const.h errnum.h
|
||||
DPADD+= ${LIBNCURSES} ${LIBCRYPT}
|
||||
LDADD+= -lncurses -lcrypt
|
||||
|
||||
const.h: errnum.h
|
||||
csh.1: tcsh.man
|
||||
ln -sf ${.ALLSRC} ${.TARGET}
|
||||
|
||||
errnum.h: err.c
|
||||
GENHDRS+= ed.defns.h tc.const.h sh.err.h
|
||||
SRCS+= ${GENHDRS}
|
||||
CLEANFILES+= ${GENHDRS}
|
||||
|
||||
ed.defns.h: ed.defns.c
|
||||
@rm -f ${.TARGET}
|
||||
@echo '/* Do not edit this file, make creates it. */' > ${.TARGET}
|
||||
@echo '#ifndef _h_sh_error' >> ${.TARGET}
|
||||
@echo '#define _h_sh_error' >> ${.TARGET}
|
||||
@echo '#ifndef _h_ed_defns' >> ${.TARGET}
|
||||
@echo '#define _h_ed_defns' >> ${.TARGET}
|
||||
grep '[FV]_' ${TCSHDIR}/ed.defns.c | grep '^#define' >> ${.TARGET}
|
||||
@echo '#endif /* _h_ed_defns */' >> ${.TARGET}
|
||||
|
||||
sh.err.h: sh.err.c
|
||||
@rm -f ${.TARGET}
|
||||
@echo '/* Do not edit this file, make creates it. */' > ${.TARGET}
|
||||
@echo '#ifndef _h_sh_err' >> ${.TARGET}
|
||||
@echo '#define _h_sh_err' >> ${.TARGET}
|
||||
egrep 'ERR_' ${.ALLSRC} | egrep '^#define' >> ${.TARGET}
|
||||
@echo '#endif /* _h_sh_error */' >> ${.TARGET}
|
||||
@echo '#endif /* _h_sh_err */' >> ${.TARGET}
|
||||
|
||||
const.h: const.c
|
||||
tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h
|
||||
@rm -f ${.TARGET}
|
||||
@echo '/* Do not edit this file, make creates it. */' > ${.TARGET}
|
||||
${CC} -E ${CFLAGS} ${.ALLSRC} | egrep 'Char STR' | \
|
||||
@echo '#ifndef _h_tc_const' >> ${.TARGET}
|
||||
@echo '#define _h_tc_const' >> ${.TARGET}
|
||||
${CC} -E ${CFLAGS} ${.ALLSRC} -D_h_tc_const | egrep 'Char STR' | \
|
||||
sed -e 's/Char \([a-zA-Z0-9_]*\)\(.*\)/extern Char \1[];/' | \
|
||||
sort >> ${.TARGET}
|
||||
@echo '#endif /* _h_tc_const */' >> ${.TARGET}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
130
bin/csh/alloc.c
130
bin/csh/alloc.c
@ -1,130 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1983, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)alloc.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
char *memtop = NULL; /* PWP: top of current memory */
|
||||
char *membot = NULL; /* PWP: bottom of allocatable memory */
|
||||
|
||||
ptr_t
|
||||
Malloc(n)
|
||||
size_t n;
|
||||
{
|
||||
ptr_t ptr;
|
||||
|
||||
if (membot == NULL)
|
||||
memtop = membot = sbrk(0);
|
||||
if ((ptr = malloc(n)) == (ptr_t) 0) {
|
||||
child++;
|
||||
stderror(ERR_NOMEM);
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
ptr_t
|
||||
Realloc(p, n)
|
||||
ptr_t p;
|
||||
size_t n;
|
||||
{
|
||||
ptr_t ptr;
|
||||
|
||||
if (membot == NULL)
|
||||
memtop = membot = sbrk(0);
|
||||
if ((ptr = realloc(p, n)) == (ptr_t) 0) {
|
||||
child++;
|
||||
stderror(ERR_NOMEM);
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
ptr_t
|
||||
Calloc(s, n)
|
||||
size_t s, n;
|
||||
{
|
||||
ptr_t ptr;
|
||||
|
||||
if (membot == NULL)
|
||||
memtop = membot = sbrk(0);
|
||||
if ((ptr = calloc(s, n)) == (ptr_t) 0) {
|
||||
child++;
|
||||
stderror(ERR_NOMEM);
|
||||
}
|
||||
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
void
|
||||
Free(p)
|
||||
ptr_t p;
|
||||
{
|
||||
if (p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* mstats - print out statistics about malloc
|
||||
*
|
||||
* Prints two lines of numbers, one showing the length of the free list
|
||||
* for each size category, the second showing the number of mallocs -
|
||||
* frees for each size category.
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
showall(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
memtop = (char *) sbrk(0);
|
||||
(void) fprintf(cshout, "Allocated memory from 0x%lx to 0x%lx (%ld).\n",
|
||||
(unsigned long) membot, (unsigned long) memtop,
|
||||
(unsigned long) (memtop - membot));
|
||||
}
|
316
bin/csh/char.c
316
bin/csh/char.c
@ -1,316 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)char.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "char.h"
|
||||
|
||||
unsigned short _cmap[256] = {
|
||||
/* nul soh stx etx */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* eot enq ack bel */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* bs ht nl vt */
|
||||
_CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR,
|
||||
|
||||
/* np cr so si */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* dle dc1 dc2 dc3 */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* dc4 nak syn etb */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* can em sub esc */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* fs gs rs us */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* sp ! " # */
|
||||
_SP|_META, 0, _QF, _META,
|
||||
|
||||
/* $ % & ' */
|
||||
_DOL, 0, _META|_CMD, _QF,
|
||||
|
||||
/* ( ) * + */
|
||||
_META|_CMD, _META, _GLOB, 0,
|
||||
|
||||
/* , - . / */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* 0 1 2 3 */
|
||||
_DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
|
||||
|
||||
/* 4 5 6 7 */
|
||||
_DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD,
|
||||
|
||||
/* 8 9 : ; */
|
||||
_DIG|_XD, _DIG|_XD, 0, _META|_CMD,
|
||||
|
||||
/* < = > ? */
|
||||
_META, 0, _META, _GLOB,
|
||||
|
||||
/* @ A B C */
|
||||
0, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD,
|
||||
|
||||
/* D E F G */
|
||||
_LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP,
|
||||
|
||||
/* H I J K */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* L M N O */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* P Q R S */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* T U V W */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* X Y Z [ */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _GLOB,
|
||||
|
||||
/* \ ] ^ _ */
|
||||
_ESC, 0, 0, 0,
|
||||
|
||||
/* ` a b c */
|
||||
_QB|_GLOB|_META, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD,
|
||||
|
||||
/* d e f g */
|
||||
_LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW,
|
||||
|
||||
/* h i j k */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* l m n o */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* p q r s */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* t u v w */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* x y z { */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _GLOB,
|
||||
|
||||
/* | } ~ del */
|
||||
_META|_CMD, 0, 0, _CTR,
|
||||
|
||||
#if defined(SHORT_STRINGS) && !defined(KANJI)
|
||||
/****************************************************************/
|
||||
/* 128 - 255 The below is supposedly ISO 8859/1 */
|
||||
/****************************************************************/
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* (undef) (undef) (undef) (undef) */
|
||||
_CTR, _CTR, _CTR, _CTR,
|
||||
|
||||
/* nobreakspace exclamdown cent sterling */
|
||||
_SP, 0, 0, 0,
|
||||
|
||||
/* currency yen brokenbar section */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* diaeresis copyright ordfeminine guillemotleft */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* notsign hyphen registered macron */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* degree plusminus twosuperior threesuperior */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* acute mu paragraph periodcentered */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* cedilla onesuperior masculine guillemotright */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* onequarter onehalf threequarters questiondown */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* Agrave Aacute Acircumflex Atilde */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* Adiaeresis Aring AE Ccedilla */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* Egrave Eacute Ecircumflex Ediaeresis */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* Igrave Iacute Icircumflex Idiaeresis */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* ETH Ntilde Ograve Oacute */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* Ocircumflex Otilde Odiaeresis multiply */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, 0,
|
||||
|
||||
/* Ooblique Ugrave Uacute Ucircumflex */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP,
|
||||
|
||||
/* Udiaeresis Yacute THORN ssharp */
|
||||
_LET|_UP, _LET|_UP, _LET|_UP, _LET|_LOW,
|
||||
|
||||
/* agrave aacute acircumflex atilde */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* adiaeresis aring ae ccedilla */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* egrave eacute ecircumflex ediaeresis */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* igrave iacute icircumflex idiaeresis */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* eth ntilde ograve oacute */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* ocircumflex otilde odiaeresis division */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, 0,
|
||||
|
||||
/* oslash ugrave uacute ucircumflex */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
|
||||
/* udiaeresis yacute thorn ydiaeresis */
|
||||
_LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW,
|
||||
#endif /* SHORT_STRINGS && !KANJI */
|
||||
};
|
||||
|
||||
#ifndef NLS
|
||||
/* _cmap_lower, _cmap_upper for ISO 8859/1 */
|
||||
|
||||
unsigned char _cmap_lower[256] = {
|
||||
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
||||
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
|
||||
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
|
||||
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
|
||||
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
|
||||
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
|
||||
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
|
||||
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
|
||||
0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
|
||||
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
|
||||
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
|
||||
0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
|
||||
0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
|
||||
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
|
||||
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
|
||||
0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
|
||||
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
||||
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
|
||||
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
|
||||
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
|
||||
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
|
||||
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
|
||||
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
||||
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
||||
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
|
||||
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
|
||||
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0327,
|
||||
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0337,
|
||||
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
|
||||
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
|
||||
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
|
||||
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
|
||||
};
|
||||
|
||||
unsigned char _cmap_upper[256] = {
|
||||
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
|
||||
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
|
||||
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
|
||||
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
|
||||
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
|
||||
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
|
||||
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
|
||||
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
|
||||
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
|
||||
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
|
||||
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
|
||||
0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
|
||||
0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
|
||||
0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
|
||||
0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
|
||||
0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
|
||||
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
||||
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
|
||||
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
|
||||
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
|
||||
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
|
||||
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
|
||||
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
||||
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
||||
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
||||
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
|
||||
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
|
||||
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
|
||||
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
||||
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
|
||||
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0367,
|
||||
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0377,
|
||||
};
|
||||
#endif /* NLS */
|
@ -1,97 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)char.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
extern unsigned short _cmap[];
|
||||
|
||||
#ifndef NLS
|
||||
extern unsigned char _cmap_lower[], _cmap_upper[];
|
||||
|
||||
#endif
|
||||
|
||||
#define _QF 0x0001 /* '" (Forward quotes) */
|
||||
#define _QB 0x0002 /* ` (Backquote) */
|
||||
#define _SP 0x0004 /* space and tab */
|
||||
#define _NL 0x0008 /* \n */
|
||||
#define _META 0x0010 /* lex meta characters, sp #'`";&<>()|\t\n */
|
||||
#define _GLOB 0x0020 /* glob characters, *?{[` */
|
||||
#define _ESC 0x0040 /* \ */
|
||||
#define _DOL 0x0080 /* $ */
|
||||
#define _DIG 0x0100 /* 0-9 */
|
||||
#define _LET 0x0200 /* a-z, A-Z, _ */
|
||||
#define _UP 0x0400 /* A-Z */
|
||||
#define _LOW 0x0800 /* a-z */
|
||||
#define _XD 0x1000 /* 0-9, a-f, A-F */
|
||||
#define _CMD 0x2000 /* lex end of command chars, ;&(|` */
|
||||
#define _CTR 0x4000 /* control */
|
||||
|
||||
#define cmap(c, bits) \
|
||||
(((c) & QUOTE) ? 0 : (_cmap[(unsigned char)(c)] & (bits)))
|
||||
|
||||
#define isglob(c) cmap(c, _GLOB)
|
||||
#define isspc(c) cmap(c, _SP)
|
||||
#define ismeta(c) cmap(c, _META)
|
||||
#define iscmdmeta(c) cmap(c, _CMD)
|
||||
#define letter(c) (((c) & QUOTE) ? 0 : \
|
||||
(isalpha((unsigned char) (c)) || (c) == '_'))
|
||||
#define alnum(c) (((c) & QUOTE) ? 0 : \
|
||||
(isalnum((unsigned char) (c)) || (c) == '_'))
|
||||
#ifdef NLS
|
||||
#define Isspace(c) (((c) & QUOTE) ? 0 : isspace((unsigned char) (c)))
|
||||
#define Isdigit(c) (((c) & QUOTE) ? 0 : isdigit((unsigned char) (c)))
|
||||
#define Isalpha(c) (((c) & QUOTE) ? 0 : isalpha((unsigned char) (c)))
|
||||
#define Islower(c) (((c) & QUOTE) ? 0 : islower((unsigned char) (c)))
|
||||
#define Isupper(c) (((c) & QUOTE) ? 0 : isupper((unsigned char) (c)))
|
||||
#define Tolower(c) (((c) & QUOTE) ? 0 : tolower((unsigned char) (c)))
|
||||
#define Toupper(c) (((c) & QUOTE) ? 0 : toupper((unsigned char) (c)))
|
||||
#define Isxdigit(c) (((c) & QUOTE) ? 0 : isxdigit((unsigned char) (c)))
|
||||
#define Isalnum(c) (((c) & QUOTE) ? 0 : isalnum((unsigned char) (c)))
|
||||
#define Iscntrl(c) (((c) & QUOTE) ? 0 : iscntrl((unsigned char) (c)))
|
||||
#define Isprint(c) (((c) & QUOTE) ? 0 : isprint((unsigned char) (c)))
|
||||
#else
|
||||
#define Isspace(c) cmap(c, _SP|_NL)
|
||||
#define Isdigit(c) cmap(c, _DIG)
|
||||
#define Isalpha(c) (cmap(c,_LET) && !(((c) & META) && AsciiOnly))
|
||||
#define Islower(c) (cmap(c,_LOW) && !(((c) & META) && AsciiOnly))
|
||||
#define Isupper(c) (cmap(c, _UP) && !(((c) & META) && AsciiOnly))
|
||||
#define Tolower(c) (_cmap_lower[(unsigned char)(c)])
|
||||
#define Toupper(c) (_cmap_upper[(unsigned char)(c)])
|
||||
#define Isxdigit(c) cmap(c, _XD)
|
||||
#define Isalnum(c) (cmap(c, _DIG|_LET) && !(((c) & META) && AsciiOnly))
|
||||
#define Iscntrl(c) (cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
|
||||
#define Isprint(c) (!cmap(c,_CTR) && !(((c) & META) && AsciiOnly))
|
||||
#endif
|
153
bin/csh/config.h
Normal file
153
bin/csh/config.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* config.h. Generated automatically by configure. */
|
||||
/*
|
||||
* config.h -- configure various defines for tcsh
|
||||
*
|
||||
* All source files should #include this FIRST.
|
||||
*
|
||||
* Edit this to match your system type.
|
||||
*/
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#ifndef _h_config
|
||||
#define _h_config
|
||||
/****************** System dependant compilation flags ****************/
|
||||
/*
|
||||
* POSIX This system supports IEEE Std 1003.1-1988 (POSIX).
|
||||
*/
|
||||
#define POSIX
|
||||
|
||||
/*
|
||||
* POSIXJOBS This system supports the optional IEEE Std 1003.1-1988 (POSIX)
|
||||
* job control facilities.
|
||||
*/
|
||||
#define POSIXJOBS
|
||||
|
||||
/*
|
||||
* POSIXSIGS Use the POSIX signal facilities to emulate BSD signals.
|
||||
*/
|
||||
/* #undef POSIXSIGS */
|
||||
|
||||
/*
|
||||
* VFORK This machine has a vfork().
|
||||
* It used to be that for job control to work, this define
|
||||
* was mandatory. This is not the case any more.
|
||||
* If you think you still need it, but you don't have vfork,
|
||||
* define this anyway and then do #define vfork fork.
|
||||
* I do this anyway on a Sun because of yellow pages brain damage,
|
||||
* [should not be needed under 4.1]
|
||||
* and on the iris4d cause SGI's fork is sufficiently "virtual"
|
||||
* that vfork isn't necessary. (Besides, SGI's vfork is weird).
|
||||
* Note that some machines eg. rs6000 have a vfork, but not
|
||||
* with the berkeley semantics, so we cannot use it there either.
|
||||
*/
|
||||
#define VFORK
|
||||
|
||||
/*
|
||||
* BSDJOBS You have BSD-style job control (both process groups and
|
||||
* a tty that deals correctly
|
||||
*/
|
||||
#define BSDJOBS
|
||||
|
||||
/*
|
||||
* BSDSIGS You have 4.2-style signals, rather than USG style.
|
||||
* Note: POSIX systems should not define this unless they
|
||||
* have sigvec() and friends (ie: 4.3BSD-RENO, HP-UX).
|
||||
*/
|
||||
#define BSDSIGS
|
||||
|
||||
/*
|
||||
* BSDTIMES You have BSD-style process time stuff (like rusage)
|
||||
* This may or may not be true. For example, Apple Unix
|
||||
* (OREO) has BSDJOBS and BSDSIGS but not BSDTIMES.
|
||||
*/
|
||||
#define BSDTIMES
|
||||
|
||||
/*
|
||||
* BSDLIMIT You have BSD-style resource limit stuff (getrlimit/setrlimit)
|
||||
*/
|
||||
#define BSDLIMIT
|
||||
|
||||
/*
|
||||
* BSDNICE Your system uses setpriority() instead of nice, to
|
||||
* change a processes scheduling priority
|
||||
*/
|
||||
#define BSDNICE
|
||||
|
||||
/*
|
||||
* TERMIO You have struct termio instead of struct sgttyb.
|
||||
* This is usually the case for SYSV systems, where
|
||||
* BSD uses sgttyb. POSIX systems should define this
|
||||
* anyway, even though they use struct termios.
|
||||
*/
|
||||
#define TERMIO
|
||||
|
||||
/*
|
||||
* SYSVREL Your machine is SYSV based (HPUX, A/UX)
|
||||
* NOTE: don't do this if you are on a Pyramid -- tcsh is
|
||||
* built in a BSD universe.
|
||||
* Set SYSVREL to 1, 2, 3, or 4, depending the version of System V
|
||||
* you are running. Or set it to 0 if you are not SYSV based
|
||||
*/
|
||||
#define SYSVREL 0
|
||||
|
||||
/*
|
||||
* YPBUGS Work around Sun YP bugs that cause expansion of ~username
|
||||
* to send command output to /dev/null
|
||||
*/
|
||||
/* #undef YPBUGS */
|
||||
|
||||
/*
|
||||
* SIGVOID Define this if your signal handlers return void. On older
|
||||
* systems, signal returns int, but on newer ones, it returns void.
|
||||
*/
|
||||
#define SIGVOID
|
||||
|
||||
/*
|
||||
* HAVEDUP2 Define this if your system supports dup2().
|
||||
*/
|
||||
#define HAVEDUP2
|
||||
|
||||
/*
|
||||
* UTHOST Does the utmp file have a host field?
|
||||
*/
|
||||
#define UTHOST
|
||||
|
||||
/*
|
||||
* DIRENT Your system has <dirent.h> instead of <sys/dir.h>
|
||||
*/
|
||||
#define DIRENT
|
||||
/****************** local defines *********************/
|
||||
/****************** configurable hacks ****************/
|
||||
|
||||
/* have been moved to config_f.h */
|
||||
#include "config_f.h"
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#define NLS_BUGS
|
||||
#endif
|
||||
|
||||
#if defined(__bsdi__)
|
||||
/*
|
||||
* _PATH_TCSHELL if you've change the installation location (vix)
|
||||
*/
|
||||
# ifdef _BSDI_VERSION >= 199701
|
||||
# define _PATH_TCSHELL "/bin/tcsh"
|
||||
/* # undef SYSMALLOC */
|
||||
# define SYSMALLOC
|
||||
# else
|
||||
# define _PATH_TCSHELL "/usr/contrib/bin/tcsh"
|
||||
# endif
|
||||
|
||||
# undef NLS
|
||||
# undef NLS_CATALOGS
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
# define SYSMALLOC
|
||||
|
||||
#else
|
||||
# define NLS_CATALOGS
|
||||
#endif
|
||||
|
||||
#endif /* _h_config */
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
153
bin/csh/config_p.h
Normal file
153
bin/csh/config_p.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* config.h. Generated automatically by configure. */
|
||||
/*
|
||||
* config.h -- configure various defines for tcsh
|
||||
*
|
||||
* All source files should #include this FIRST.
|
||||
*
|
||||
* Edit this to match your system type.
|
||||
*/
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#ifndef _h_config
|
||||
#define _h_config
|
||||
/****************** System dependant compilation flags ****************/
|
||||
/*
|
||||
* POSIX This system supports IEEE Std 1003.1-1988 (POSIX).
|
||||
*/
|
||||
#define POSIX
|
||||
|
||||
/*
|
||||
* POSIXJOBS This system supports the optional IEEE Std 1003.1-1988 (POSIX)
|
||||
* job control facilities.
|
||||
*/
|
||||
#define POSIXJOBS
|
||||
|
||||
/*
|
||||
* POSIXSIGS Use the POSIX signal facilities to emulate BSD signals.
|
||||
*/
|
||||
/* #undef POSIXSIGS */
|
||||
|
||||
/*
|
||||
* VFORK This machine has a vfork().
|
||||
* It used to be that for job control to work, this define
|
||||
* was mandatory. This is not the case any more.
|
||||
* If you think you still need it, but you don't have vfork,
|
||||
* define this anyway and then do #define vfork fork.
|
||||
* I do this anyway on a Sun because of yellow pages brain damage,
|
||||
* [should not be needed under 4.1]
|
||||
* and on the iris4d cause SGI's fork is sufficiently "virtual"
|
||||
* that vfork isn't necessary. (Besides, SGI's vfork is weird).
|
||||
* Note that some machines eg. rs6000 have a vfork, but not
|
||||
* with the berkeley semantics, so we cannot use it there either.
|
||||
*/
|
||||
#define VFORK
|
||||
|
||||
/*
|
||||
* BSDJOBS You have BSD-style job control (both process groups and
|
||||
* a tty that deals correctly
|
||||
*/
|
||||
#define BSDJOBS
|
||||
|
||||
/*
|
||||
* BSDSIGS You have 4.2-style signals, rather than USG style.
|
||||
* Note: POSIX systems should not define this unless they
|
||||
* have sigvec() and friends (ie: 4.3BSD-RENO, HP-UX).
|
||||
*/
|
||||
#define BSDSIGS
|
||||
|
||||
/*
|
||||
* BSDTIMES You have BSD-style process time stuff (like rusage)
|
||||
* This may or may not be true. For example, Apple Unix
|
||||
* (OREO) has BSDJOBS and BSDSIGS but not BSDTIMES.
|
||||
*/
|
||||
#define BSDTIMES
|
||||
|
||||
/*
|
||||
* BSDLIMIT You have BSD-style resource limit stuff (getrlimit/setrlimit)
|
||||
*/
|
||||
#define BSDLIMIT
|
||||
|
||||
/*
|
||||
* BSDNICE Your system uses setpriority() instead of nice, to
|
||||
* change a processes scheduling priority
|
||||
*/
|
||||
#define BSDNICE
|
||||
|
||||
/*
|
||||
* TERMIO You have struct termio instead of struct sgttyb.
|
||||
* This is usually the case for SYSV systems, where
|
||||
* BSD uses sgttyb. POSIX systems should define this
|
||||
* anyway, even though they use struct termios.
|
||||
*/
|
||||
#define TERMIO
|
||||
|
||||
/*
|
||||
* SYSVREL Your machine is SYSV based (HPUX, A/UX)
|
||||
* NOTE: don't do this if you are on a Pyramid -- tcsh is
|
||||
* built in a BSD universe.
|
||||
* Set SYSVREL to 1, 2, 3, or 4, depending the version of System V
|
||||
* you are running. Or set it to 0 if you are not SYSV based
|
||||
*/
|
||||
#define SYSVREL 0
|
||||
|
||||
/*
|
||||
* YPBUGS Work around Sun YP bugs that cause expansion of ~username
|
||||
* to send command output to /dev/null
|
||||
*/
|
||||
/* #undef YPBUGS */
|
||||
|
||||
/*
|
||||
* SIGVOID Define this if your signal handlers return void. On older
|
||||
* systems, signal returns int, but on newer ones, it returns void.
|
||||
*/
|
||||
#define SIGVOID
|
||||
|
||||
/*
|
||||
* HAVEDUP2 Define this if your system supports dup2().
|
||||
*/
|
||||
#define HAVEDUP2
|
||||
|
||||
/*
|
||||
* UTHOST Does the utmp file have a host field?
|
||||
*/
|
||||
#define UTHOST
|
||||
|
||||
/*
|
||||
* DIRENT Your system has <dirent.h> instead of <sys/dir.h>
|
||||
*/
|
||||
#define DIRENT
|
||||
/****************** local defines *********************/
|
||||
/****************** configurable hacks ****************/
|
||||
|
||||
/* have been moved to config_f.h */
|
||||
#include "config_f.h"
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#define NLS_BUGS
|
||||
#endif
|
||||
|
||||
#if defined(__bsdi__)
|
||||
/*
|
||||
* _PATH_TCSHELL if you've change the installation location (vix)
|
||||
*/
|
||||
# ifdef _BSDI_VERSION >= 199701
|
||||
# define _PATH_TCSHELL "/bin/tcsh"
|
||||
/* # undef SYSMALLOC */
|
||||
# define SYSMALLOC
|
||||
# else
|
||||
# define _PATH_TCSHELL "/usr/contrib/bin/tcsh"
|
||||
# endif
|
||||
|
||||
# undef NLS
|
||||
# undef NLS_CATALOGS
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
# define SYSMALLOC
|
||||
|
||||
#else
|
||||
# define NLS_CATALOGS
|
||||
#endif
|
||||
|
||||
#endif /* _h_config */
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
167
bin/csh/const.c
167
bin/csh/const.c
@ -1,167 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)const.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* tc.const.c: String constants for csh.
|
||||
*/
|
||||
|
||||
#include "csh.h"
|
||||
|
||||
Char STR0[] = { '0', '\0' };
|
||||
Char STR1[] = { '1', '\0' };
|
||||
Char STRHOME[] = { 'H', 'O', 'M', 'E', '\0' };
|
||||
Char STRLANG[] = { 'L', 'A', 'N', 'G', '\0' };
|
||||
Char STRLC_ALL[] = { 'L', 'C', '_', 'A', 'L', 'L', '\0' };
|
||||
Char STRLC_CTYPE[] = { 'L', 'C', '_', 'C', 'T', 'Y', 'P', 'E', '\0' };
|
||||
Char STRLC_COLLATE[] = { 'L', 'C', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', '\0' };
|
||||
Char STRLOGNAME[] = { 'L', 'O', 'G', 'N', 'A', 'M', 'E', '\0' };
|
||||
Char STRLbrace[] = { '{', '\0' };
|
||||
Char STRLparen[] = { '(', '\0' };
|
||||
Char STRLparensp[] = { '(', ' ', '\0' };
|
||||
Char STRNULL[] = { '\0' };
|
||||
Char STRPATH[] = { 'P', 'A', 'T', 'H', '\0' };
|
||||
Char STRPWD[] = { 'P', 'W', 'D', '\0' };
|
||||
Char STRQNULL[] = { '\0' | QUOTE, '\0' };
|
||||
Char STRRbrace[] = { '}', '\0' };
|
||||
Char STRspRparen[] = { ' ', ')', '\0' };
|
||||
Char STRTERM[] = { 'T', 'E', 'R', 'M', '\0' };
|
||||
Char STRUSER[] = { 'U', 'S', 'E', 'R', '\0' };
|
||||
Char STRalias[] = { 'a', 'l', 'i', 'a', 's', '\0' };
|
||||
Char STRand[] = { '&', '\0' };
|
||||
Char STRand2[] = { '&', '&', '\0' };
|
||||
Char STRaout[] = { 'a', '.', 'o', 'u', 't', '\0' };
|
||||
Char STRargv[] = { 'a', 'r', 'g', 'v', '\0' };
|
||||
Char STRbang[] = { '!', '\0' };
|
||||
Char STRcaret[] = { '^', '\0' };
|
||||
Char STRcdpath[] = { 'c', 'd', 'p', 'a', 't', 'h', '\0' };
|
||||
Char STRcent2[] = { '%', '%', '\0' };
|
||||
Char STRcenthash[] = { '%', '#', '\0' };
|
||||
Char STRcentplus[] = { '%', '+', '\0' };
|
||||
Char STRcentminus[] = { '%', '-', '\0' };
|
||||
Char STRchase_symlinks[] = { 'c', 'h', 'a', 's', 'e', '_', 's', 'y', 'm', 'l',
|
||||
'i', 'n', 'k', 's', '\0' };
|
||||
Char STRchild[] = { 'c', 'h', 'i', 'l', 'd', '\0' };
|
||||
Char STRcolon[] = { ':', '\0' };
|
||||
Char STRcwd[] = { 'c', 'w', 'd', '\0' };
|
||||
Char STRdefault[] = { 'd', 'e', 'f', 'a', 'u', 'l', 't', '\0' };
|
||||
Char STRdot[] = { '.', '\0' };
|
||||
Char STRdotdotsl[] = { '.', '.', '/', '\0' };
|
||||
Char STRdotsl[] = { '.', '/', '\0' };
|
||||
Char STRecho[] = { 'e', 'c', 'h', 'o', '\0' };
|
||||
Char STRequal[] = { '=', '\0' };
|
||||
Char STRfakecom[] = { '{', ' ', '.', '.', '.', ' ', '}', '\0' };
|
||||
Char STRfakecom1[] = { '`', ' ', '.', '.', '.', ' ', '`', '\0' };
|
||||
Char STRfignore[] = { 'f', 'i', 'g', 'n', 'o', 'r', 'e', '\0' };
|
||||
#ifdef FILEC
|
||||
Char STRfilec[] = { 'f', 'i', 'l', 'e', 'c', '\0' };
|
||||
#endif /* FILEC */
|
||||
Char STRhistchars[] = { 'h', 'i', 's', 't', 'c', 'h', 'a', 'r', 's', '\0' };
|
||||
Char STRtildothist[] = { '~', '/', '.', 'h', 'i', 's', 't', 'o', 'r',
|
||||
'y', '\0' };
|
||||
Char STRhistfile[] = { 'h', 'i', 's', 't', 'f', 'i', 'l', 'e', '\0' };
|
||||
Char STRhistory[] = { 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' };
|
||||
Char STRhome[] = { 'h', 'o', 'm', 'e', '\0' };
|
||||
Char STRignore_symlinks[] = { 'i', 'g', 'n', 'o', 'r', 'e', '_', 's', 'y', 'm',
|
||||
'l', 'i', 'n', 'k', 's', '\0' };
|
||||
Char STRignoreeof[] = { 'i', 'g', 'n', 'o', 'r', 'e', 'e', 'o', 'f', '\0' };
|
||||
Char STRjobs[] = { 'j', 'o', 'b', 's', '\0' };
|
||||
Char STRlistjobs[] = { 'l', 'i', 's', 't', 'j', 'o', 'b', 's', '\0' };
|
||||
Char STRlogout[] = { 'l', 'o', 'g', 'o', 'u', 't', '\0' };
|
||||
Char STRlong[] = { 'l', 'o', 'n', 'g', '\0' };
|
||||
Char STRmail[] = { 'm', 'a', 'i', 'l', '\0' };
|
||||
Char STRmh[] = { '-', 'h', '\0' };
|
||||
Char STRminus[] = { '-', '\0' };
|
||||
Char STRml[] = { '-', 'l', '\0' };
|
||||
Char STRmn[] = { '-', 'n', '\0' };
|
||||
Char STRmquestion[] = { '?' | QUOTE, ' ', '\0' };
|
||||
Char STRnice[] = { 'n', 'i', 'c', 'e', '\0' };
|
||||
Char STRnoambiguous[] = { 'n', 'o', 'a', 'm', 'b', 'i', 'g', 'u', 'o', 'u',
|
||||
's', '\0' };
|
||||
Char STRnobeep[] = { 'n', 'o', 'b', 'e', 'e', 'p', '\0' };
|
||||
Char STRnoclobber[] = { 'n', 'o', 'c', 'l', 'o', 'b', 'b', 'e', 'r', '\0' };
|
||||
Char STRnoglob[] = { 'n', 'o', 'g', 'l', 'o', 'b', '\0' };
|
||||
Char STRnohup[] = { 'n', 'o', 'h', 'u', 'p', '\0' };
|
||||
Char STRnonomatch[] = { 'n', 'o', 'n', 'o', 'm', 'a', 't', 'c', 'h', '\0' };
|
||||
Char STRnormal[] = { 'n', 'o', 'r', 'm', 'a', 'l', '\0' };
|
||||
Char STRnotify[] = { 'n', 'o', 't', 'i', 'f', 'y', '\0' };
|
||||
Char STRor[] = { '|', '\0' };
|
||||
Char STRor2[] = { '|', '|', '\0' };
|
||||
Char STRpath[] = { 'p', 'a', 't', 'h', '\0' };
|
||||
Char STRprintexitvalue[] = { 'p', 'r', 'i', 'n', 't', 'e', 'x', 'i', 't', 'v',
|
||||
'a', 'l', 'u', 'e', '\0' };
|
||||
Char STRprompt[] = { 'p', 'r', 'o', 'm', 'p', 't', '\0' };
|
||||
Char STRprompt2[] = { 'p', 'r', 'o', 'm', 'p', 't', '2', '\0' };
|
||||
Char STRpushdsilent[] = { 'p', 'u', 's', 'h', 'd', 's', 'i', 'l', 'e', 'n',
|
||||
't', '\0' };
|
||||
Char STRret[] = { '\n', '\0' };
|
||||
Char STRsavehist[] = { 's', 'a', 'v', 'e', 'h', 'i', 's', 't', '\0' };
|
||||
Char STRsemisp[] = { ';', ' ', '\0' };
|
||||
Char STRshell[] = { 's', 'h', 'e', 'l', 'l', '\0' };
|
||||
Char STRslash[] = { '/', '\0' };
|
||||
Char STRsldotcshrc[] = { '/', '.', 'c', 's', 'h', 'r', 'c', '\0' };
|
||||
Char STRsldotlogin[] = { '/', '.', 'l', 'o', 'g', 'i', 'n', '\0' };
|
||||
Char STRsldthist[] = { '/', '.', 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' };
|
||||
Char STRsldtlogout[] = { '/', '.', 'l', 'o', 'g', 'o', 'u', 't', '\0' };
|
||||
Char STRsource[] = { 's', 'o', 'u', 'r', 'c', 'e', '\0' };
|
||||
Char STRsp3dots[] = { ' ', '.', '.', '.', '\0' };
|
||||
Char STRspLarrow2sp[] = { ' ', '<', '<', ' ', '\0' };
|
||||
Char STRspLarrowsp[] = { ' ', '<', ' ', '\0' };
|
||||
Char STRspRarrow[] = { ' ', '>', '\0' };
|
||||
Char STRspRarrow2[] = { ' ', '>', '>', '\0' };
|
||||
Char STRRparen[] = { ')', '\0' };
|
||||
Char STRspace[] = { ' ', '\0' };
|
||||
Char STRspand2sp[] = { ' ', '&', '&', ' ', '\0' };
|
||||
Char STRspor2sp[] = { ' ', '|', '|', ' ', '\0' };
|
||||
Char STRsporsp[] = { ' ', '|', ' ', '\0' };
|
||||
Char STRstar[] = { '*', '\0' };
|
||||
Char STRstatus[] = { 's', 't', 'a', 't', 'u', 's', '\0' };
|
||||
Char STRsymcent[] = { '%', ' ', '\0' };
|
||||
Char STRsymhash[] = { '#', ' ', '\0' };
|
||||
Char STRterm[] = { 't', 'e', 'r', 'm', '\0' };
|
||||
Char STRthen[] = { 't', 'h', 'e', 'n', '\0' };
|
||||
Char STRtilde[] = { '~', '\0' };
|
||||
Char STRtime[] = { 't', 'i', 'm', 'e', '\0' };
|
||||
Char STRtmpsh[] = { '/', 't', 'm', 'p', '/', 's', 'h', '\0' };
|
||||
Char STRunalias[] = { 'u', 'n', 'a', 'l', 'i', 'a', 's', '\0' };
|
||||
Char STRuser[] = { 'u', 's', 'e', 'r', '\0' };
|
||||
Char STRverbose[] = { 'v', 'e', 'r', 'b', 'o', 's', 'e', '\0' };
|
||||
Char STRwordchars[] = { 'w', 'o', 'r', 'd', 'c', 'h', 'a', 'r', 's', '\0' };
|
1362
bin/csh/csh.c
1362
bin/csh/csh.c
File diff suppressed because it is too large
Load Diff
551
bin/csh/csh.h
551
bin/csh/csh.h
@ -1,551 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)csh.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fundamental definitions which may vary from system to system.
|
||||
*
|
||||
* BUFSIZ The i/o buffering size; also limits word size
|
||||
* MAILINTVL How often to mailcheck; more often is more expensive
|
||||
*/
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ 1024 /* default buffer size */
|
||||
#endif /* BUFSIZ */
|
||||
|
||||
#define FORKSLEEP 10 /* delay loop on non-interactive fork failure */
|
||||
#define MAILINTVL 600 /* 10 minutes */
|
||||
|
||||
/*
|
||||
* The shell moves std in/out/diag and the old std input away from units
|
||||
* 0, 1, and 2 so that it is easy to set up these standards for invoked
|
||||
* commands.
|
||||
*/
|
||||
#define FSHTTY 15 /* /dev/tty when manip pgrps */
|
||||
#define FSHIN 16 /* Preferred desc for shell input */
|
||||
#define FSHOUT 17 /* ... shell output */
|
||||
#define FSHERR 18 /* ... shell diagnostics */
|
||||
#define FOLDSTD 19 /* ... old std input */
|
||||
|
||||
#ifdef PROF
|
||||
#define xexit(n) done(n)
|
||||
#endif
|
||||
|
||||
#ifdef SHORT_STRINGS
|
||||
typedef short Char;
|
||||
|
||||
#define SAVE(a) (Strsave(str2short(a)))
|
||||
#else
|
||||
typedef char Char;
|
||||
|
||||
#define SAVE(a) (strsave(a))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure a variable is not stored in a register by taking its address
|
||||
* This is used where variables might be clobbered by longjmp.
|
||||
*/
|
||||
#define UNREGISTER(a) (void) &a
|
||||
|
||||
typedef void *ioctl_t; /* Third arg of ioctl */
|
||||
|
||||
typedef void *ptr_t;
|
||||
|
||||
#include "const.h"
|
||||
#include "char.h"
|
||||
#include "errnum.h"
|
||||
|
||||
#define xmalloc(i) Malloc(i)
|
||||
#define xrealloc(p, i) Realloc(p, i)
|
||||
#define xcalloc(n, s) Calloc(n, s)
|
||||
#define xfree(p) Free(p)
|
||||
|
||||
#include <stdio.h>
|
||||
FILE *cshin, *cshout, *csherr;
|
||||
|
||||
#define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
|
||||
|
||||
typedef int bool;
|
||||
|
||||
#define eq(a, b) (Strcmp(a, b) == 0)
|
||||
|
||||
/* globone() flags */
|
||||
#define G_ERROR 0 /* default action: error if multiple words */
|
||||
#define G_IGNORE 1 /* ignore the rest of the words */
|
||||
#define G_APPEND 2 /* make a sentence by cat'ing the words */
|
||||
|
||||
/*
|
||||
* Global flags
|
||||
*/
|
||||
bool chkstop; /* Warned of stopped jobs... allow exit */
|
||||
bool didfds; /* Have setup i/o fd's for child */
|
||||
bool doneinp; /* EOF indicator after reset from readc */
|
||||
bool exiterr; /* Exit if error or non-zero exit status */
|
||||
bool child; /* Child shell ... errors cause exit */
|
||||
bool haderr; /* Reset was because of an error */
|
||||
bool intty; /* Input is a tty */
|
||||
bool intact; /* We are interactive... therefore prompt */
|
||||
bool justpr; /* Just print because of :p hist mod */
|
||||
bool loginsh; /* We are a loginsh -> .login/.logout */
|
||||
bool neednote; /* Need to pnotify() */
|
||||
bool noexec; /* Don't execute, just syntax check */
|
||||
bool pjobs; /* want to print jobs if interrupted */
|
||||
bool setintr; /* Set interrupts on/off -> Wait intr... */
|
||||
bool timflg; /* Time the next waited for command */
|
||||
bool havhash; /* path hashing is available */
|
||||
|
||||
#ifdef FILEC
|
||||
bool filec; /* doing filename expansion */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global i/o info
|
||||
*/
|
||||
Char *arginp; /* Argument input for sh -c and internal `xx` */
|
||||
int onelflg; /* 2 -> need line for -t, 1 -> exit on read */
|
||||
Char *ffile; /* Name of shell file for $0 */
|
||||
|
||||
char *seterr; /* Error message from scanner/parser */
|
||||
Char *shtemp; /* Temp name for << shell files in /tmp */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
struct timeval time0; /* Time at which the shell started */
|
||||
struct rusage ru0;
|
||||
|
||||
/*
|
||||
* Miscellany
|
||||
*/
|
||||
Char *doldol; /* Character pid for $$ */
|
||||
int backpid; /* Pid of the last background process */
|
||||
int uid, euid; /* Invokers uid */
|
||||
int gid, egid; /* Invokers gid */
|
||||
time_t chktim; /* Time mail last checked */
|
||||
int shpgrp; /* Pgrp of shell */
|
||||
int tpgrp; /* Terminal process group */
|
||||
|
||||
/* If tpgrp is -1, leave tty alone! */
|
||||
int opgrp; /* Initial pgrp and tty pgrp */
|
||||
|
||||
|
||||
/*
|
||||
* To be able to redirect i/o for builtins easily, the shell moves the i/o
|
||||
* descriptors it uses away from 0,1,2.
|
||||
* Ideally these should be in units which are closed across exec's
|
||||
* (this saves work) but for version 6, this is not usually possible.
|
||||
* The desired initial values for these descriptors are F{SHIN,...}.
|
||||
*/
|
||||
int SHIN; /* Current shell input (script) */
|
||||
int SHOUT; /* Shell output */
|
||||
int SHERR; /* Diagnostic output... shell errs go here */
|
||||
int OLDSTD; /* Old standard input (def for cmds) */
|
||||
|
||||
/*
|
||||
* Error control
|
||||
*
|
||||
* Errors in scanning and parsing set up an error message to be printed
|
||||
* at the end and complete. Other errors always cause a reset.
|
||||
* Because of source commands and .cshrc we need nested error catches.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
jmp_buf reslab;
|
||||
|
||||
#define setexit() (setjmp(reslab))
|
||||
#define reset() longjmp(reslab, 1)
|
||||
/* Should use structure assignment here */
|
||||
#define getexit(a) memmove((char *)(a), (char *)reslab, sizeof reslab)
|
||||
#define resexit(a) memmove((char *)reslab, (char *)(a), sizeof reslab)
|
||||
|
||||
Char *gointr; /* Label for an onintr transfer */
|
||||
|
||||
#include <signal.h>
|
||||
sig_t parintr; /* Parents interrupt catch */
|
||||
sig_t parterm; /* Parents terminate catch */
|
||||
|
||||
/*
|
||||
* Lexical definitions.
|
||||
*
|
||||
* All lexical space is allocated dynamically.
|
||||
* The eighth/sixteenth bit of characters is used to prevent recognition,
|
||||
* and eventually stripped.
|
||||
*/
|
||||
#define META 0200
|
||||
#define ASCII 0177
|
||||
#ifdef SHORT_STRINGS
|
||||
#define CHAR 0377
|
||||
#define QUOTE 0100000 /* 16nth char bit used for 'ing */
|
||||
#define TRIM 0077777 /* Mask to strip quote bit */
|
||||
#else
|
||||
#define CHAR 0177
|
||||
#define QUOTE 0200 /* Eighth char bit used for 'ing */
|
||||
#define TRIM 0177 /* Mask to strip quote bit */
|
||||
#endif
|
||||
|
||||
int AsciiOnly; /* If set only 7 bits is expected in characters */
|
||||
|
||||
/*
|
||||
* Each level of input has a buffered input structure.
|
||||
* There are one or more blocks of buffered input for each level,
|
||||
* exactly one if the input is seekable and tell is available.
|
||||
* In other cases, the shell buffers enough blocks to keep all loops
|
||||
* in the buffer.
|
||||
*/
|
||||
struct Bin {
|
||||
off_t Bfseekp; /* Seek pointer */
|
||||
off_t Bfbobp; /* Seekp of beginning of buffers */
|
||||
off_t Bfeobp; /* Seekp of end of buffers */
|
||||
int Bfblocks; /* Number of buffer blocks */
|
||||
Char **Bfbuf; /* The array of buffer blocks */
|
||||
} B;
|
||||
|
||||
/*
|
||||
* This structure allows us to seek inside aliases
|
||||
*/
|
||||
struct Ain {
|
||||
int type;
|
||||
#define I_SEEK -1 /* Invalid seek */
|
||||
#define A_SEEK 0 /* Alias seek */
|
||||
#define F_SEEK 1 /* File seek */
|
||||
#define E_SEEK 2 /* Eval seek */
|
||||
union {
|
||||
off_t _f_seek;
|
||||
Char* _c_seek;
|
||||
} fc;
|
||||
#define f_seek fc._f_seek
|
||||
#define c_seek fc._c_seek
|
||||
Char **a_seek;
|
||||
} ;
|
||||
extern int aret; /* What was the last character returned */
|
||||
#define SEEKEQ(a, b) ((a)->type == (b)->type && \
|
||||
(a)->f_seek == (b)->f_seek && \
|
||||
(a)->a_seek == (b)->a_seek)
|
||||
|
||||
#define fseekp B.Bfseekp
|
||||
#define fbobp B.Bfbobp
|
||||
#define feobp B.Bfeobp
|
||||
#define fblocks B.Bfblocks
|
||||
#define fbuf B.Bfbuf
|
||||
|
||||
/*
|
||||
* The shell finds commands in loops by reseeking the input
|
||||
* For whiles, in particular, it reseeks to the beginning of the
|
||||
* line the while was on; hence the while placement restrictions.
|
||||
*/
|
||||
struct Ain lineloc;
|
||||
|
||||
bool cantell; /* Is current source tellable ? */
|
||||
|
||||
/*
|
||||
* Input lines are parsed into doubly linked circular
|
||||
* lists of words of the following form.
|
||||
*/
|
||||
struct wordent {
|
||||
Char *word;
|
||||
struct wordent *prev;
|
||||
struct wordent *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* During word building, both in the initial lexical phase and
|
||||
* when expanding $ variable substitutions, expansion by `!' and `$'
|
||||
* must be inhibited when reading ahead in routines which are themselves
|
||||
* processing `!' and `$' expansion or after characters such as `\' or in
|
||||
* quotations. The following flags are passed to the getC routines
|
||||
* telling them which of these substitutions are appropriate for the
|
||||
* next character to be returned.
|
||||
*/
|
||||
#define DODOL 1
|
||||
#define DOEXCL 2
|
||||
#define DOALL DODOL|DOEXCL
|
||||
|
||||
/*
|
||||
* Labuf implements a general buffer for lookahead during lexical operations.
|
||||
* Text which is to be placed in the input stream can be stuck here.
|
||||
* We stick parsed ahead $ constructs during initial input,
|
||||
* process id's from `$$', and modified variable values (from qualifiers
|
||||
* during expansion in sh.dol.c) here.
|
||||
*/
|
||||
Char *lap;
|
||||
|
||||
/*
|
||||
* Parser structure
|
||||
*
|
||||
* Each command is parsed to a tree of command structures and
|
||||
* flags are set bottom up during this process, to be propagated down
|
||||
* as needed during the semantics/execution pass (sh.sem.c).
|
||||
*/
|
||||
struct command {
|
||||
short t_dtyp; /* Type of node */
|
||||
#define NODE_COMMAND 1 /* t_dcom <t_dlef >t_drit */
|
||||
#define NODE_PAREN 2 /* ( t_dspr ) <t_dlef >t_drit */
|
||||
#define NODE_PIPE 3 /* t_dlef | t_drit */
|
||||
#define NODE_LIST 4 /* t_dlef ; t_drit */
|
||||
#define NODE_OR 5 /* t_dlef || t_drit */
|
||||
#define NODE_AND 6 /* t_dlef && t_drit */
|
||||
short t_dflg; /* Flags, e.g. F_AMPERSAND|... */
|
||||
#define F_SAVE (F_NICE|F_TIME|F_NOHUP) /* save these when re-doing */
|
||||
|
||||
#define F_AMPERSAND (1<<0) /* executes in background */
|
||||
#define F_APPEND (1<<1) /* output is redirected >> */
|
||||
#define F_PIPEIN (1<<2) /* input is a pipe */
|
||||
#define F_PIPEOUT (1<<3) /* output is a pipe */
|
||||
#define F_NOFORK (1<<4) /* don't fork, last ()ized cmd */
|
||||
#define F_NOINTERRUPT (1<<5) /* should be immune from intr's */
|
||||
/* spare */
|
||||
#define F_STDERR (1<<7) /* redirect unit 2 with unit 1 */
|
||||
#define F_OVERWRITE (1<<8) /* output was ! */
|
||||
#define F_READ (1<<9) /* input redirection is << */
|
||||
#define F_REPEAT (1<<10) /* reexec aft if, repeat,... */
|
||||
#define F_NICE (1<<11) /* t_nice is meaningful */
|
||||
#define F_NOHUP (1<<12) /* nohup this command */
|
||||
#define F_TIME (1<<13) /* time this command */
|
||||
union {
|
||||
Char *T_dlef; /* Input redirect word */
|
||||
struct command *T_dcar; /* Left part of list/pipe */
|
||||
} L;
|
||||
union {
|
||||
Char *T_drit; /* Output redirect word */
|
||||
struct command *T_dcdr; /* Right part of list/pipe */
|
||||
} R;
|
||||
#define t_dlef L.T_dlef
|
||||
#define t_dcar L.T_dcar
|
||||
#define t_drit R.T_drit
|
||||
#define t_dcdr R.T_dcdr
|
||||
Char **t_dcom; /* Command/argument vector */
|
||||
struct command *t_dspr; /* Pointer to ()'d subtree */
|
||||
int t_nice;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* These are declared here because they want to be
|
||||
* initialized in sh.init.c (to allow them to be made readonly)
|
||||
*/
|
||||
|
||||
extern struct biltins {
|
||||
char *bname;
|
||||
void (*bfunct) __P((Char **, struct command *));
|
||||
short minargs, maxargs;
|
||||
} bfunc[];
|
||||
extern int nbfunc;
|
||||
|
||||
extern struct srch {
|
||||
char *s_name;
|
||||
short s_value;
|
||||
} srchn[];
|
||||
extern int nsrchn;
|
||||
|
||||
/*
|
||||
* The keywords for the parser
|
||||
*/
|
||||
#define T_BREAK 0
|
||||
#define T_BRKSW 1
|
||||
#define T_CASE 2
|
||||
#define T_DEFAULT 3
|
||||
#define T_ELSE 4
|
||||
#define T_END 5
|
||||
#define T_ENDIF 6
|
||||
#define T_ENDSW 7
|
||||
#define T_EXIT 8
|
||||
#define T_FOREACH 9
|
||||
#define T_GOTO 10
|
||||
#define T_IF 11
|
||||
#define T_LABEL 12
|
||||
#define T_LET 13
|
||||
#define T_SET 14
|
||||
#define T_SWITCH 15
|
||||
#define T_TEST 16
|
||||
#define T_THEN 17
|
||||
#define T_WHILE 18
|
||||
|
||||
/*
|
||||
* Structure defining the existing while/foreach loops at this
|
||||
* source level. Loops are implemented by seeking back in the
|
||||
* input. For foreach (fe), the word list is attached here.
|
||||
*/
|
||||
struct whyle {
|
||||
struct Ain w_start; /* Point to restart loop */
|
||||
struct Ain w_end; /* End of loop (0 if unknown) */
|
||||
Char **w_fe, **w_fe0; /* Current/initial wordlist for fe */
|
||||
Char *w_fename; /* Name for fe */
|
||||
struct whyle *w_next; /* Next (more outer) loop */
|
||||
} *whyles;
|
||||
|
||||
/*
|
||||
* Variable structure
|
||||
*
|
||||
* Aliases and variables are stored in AVL balanced binary trees.
|
||||
*/
|
||||
struct varent {
|
||||
Char **vec; /* Array of words which is the value */
|
||||
Char *v_name; /* Name of variable/alias */
|
||||
struct varent *v_link[3]; /* The links, see below */
|
||||
int v_bal; /* Balance factor */
|
||||
} shvhed, aliases;
|
||||
|
||||
#define v_left v_link[0]
|
||||
#define v_right v_link[1]
|
||||
#define v_parent v_link[2]
|
||||
|
||||
#define adrof(v) adrof1(v, &shvhed)
|
||||
#define value(v) value1(v, &shvhed)
|
||||
|
||||
/*
|
||||
* The following are for interfacing redo substitution in
|
||||
* aliases to the lexical routines.
|
||||
*/
|
||||
struct wordent *alhistp; /* Argument list (first) */
|
||||
struct wordent *alhistt; /* Node after last in arg list */
|
||||
Char **alvec, *alvecp; /* The (remnants of) alias vector */
|
||||
|
||||
/*
|
||||
* Filename/command name expansion variables
|
||||
*/
|
||||
int gflag; /* After tglob -> is globbing needed? */
|
||||
|
||||
#define MAXVARLEN 30 /* Maximum number of char in a variable name */
|
||||
|
||||
/*
|
||||
* Variables for filename expansion
|
||||
*/
|
||||
extern Char **gargv; /* Pointer to the (stack) arglist */
|
||||
extern long gargc; /* Number args in gargv */
|
||||
|
||||
/*
|
||||
* Variables for command expansion.
|
||||
*/
|
||||
extern Char **pargv; /* Pointer to the argv list space */
|
||||
extern long pargc; /* Count of arguments in pargv */
|
||||
Char *pargs; /* Pointer to start current word */
|
||||
long pnleft; /* Number of chars left in pargs */
|
||||
Char *pargcp; /* Current index into pargs */
|
||||
|
||||
/*
|
||||
* History list
|
||||
*
|
||||
* Each history list entry contains an embedded wordlist
|
||||
* from the scanner, a number for the event, and a reference count
|
||||
* to aid in discarding old entries.
|
||||
*
|
||||
* Essentially "invisible" entries are put on the history list
|
||||
* when history substitution includes modifiers, and thrown away
|
||||
* at the next discarding since their event numbers are very negative.
|
||||
*/
|
||||
struct Hist {
|
||||
struct wordent Hlex;
|
||||
int Hnum;
|
||||
int Href;
|
||||
struct Hist *Hnext;
|
||||
} Histlist;
|
||||
|
||||
struct wordent paraml; /* Current lexical word list */
|
||||
int eventno; /* Next events number */
|
||||
int lastev; /* Last event reference (default) */
|
||||
|
||||
Char HIST; /* history invocation character */
|
||||
Char HISTSUB; /* auto-substitute character */
|
||||
|
||||
/*
|
||||
* strings.h:
|
||||
*/
|
||||
#ifndef SHORT_STRINGS
|
||||
#define Strchr(a, b) strchr(a, b)
|
||||
#define Strrchr(a, b) strrchr(a, b)
|
||||
#define Strcat(a, b) strcat(a, b)
|
||||
#define Strncat(a, b, c) strncat(a, b, c)
|
||||
#define Strcpy(a, b) strcpy(a, b)
|
||||
#define Strncpy(a, b, c) strncpy(a, b, c)
|
||||
#define Strlen(a) strlen(a)
|
||||
#define Strcmp(a, b) strcmp(a, b)
|
||||
#define Strncmp(a, b, c) strncmp(a, b, c)
|
||||
|
||||
#define Strspl(a, b) strspl(a, b)
|
||||
#define Strsave(a) strsave(a)
|
||||
#define Strend(a) strend(a)
|
||||
#define Strstr(a, b) strstr(a, b)
|
||||
|
||||
#define str2short(a) (a)
|
||||
#define blk2short(a) saveblk(a)
|
||||
#define short2blk(a) saveblk(a)
|
||||
#define short2str(a) strip(a)
|
||||
#else
|
||||
#define Strchr(a, b) s_strchr(a, b)
|
||||
#define Strrchr(a, b) s_strrchr(a, b)
|
||||
#define Strcat(a, b) s_strcat(a, b)
|
||||
#define Strncat(a, b, c) s_strncat(a, b, c)
|
||||
#define Strcpy(a, b) s_strcpy(a, b)
|
||||
#define Strncpy(a, b, c) s_strncpy(a, b, c)
|
||||
#define Strlen(a) s_strlen(a)
|
||||
#define Strcmp(a, b) s_strcmp(a, b)
|
||||
#define Strncmp(a, b, c) s_strncmp(a, b, c)
|
||||
|
||||
#define Strspl(a, b) s_strspl(a, b)
|
||||
#define Strsave(a) s_strsave(a)
|
||||
#define Strend(a) s_strend(a)
|
||||
#define Strstr(a, b) s_strstr(a, b)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* setname is a macro to save space (see sh.err.c)
|
||||
*/
|
||||
char *bname;
|
||||
|
||||
#define setname(a) (bname = (a))
|
||||
|
||||
Char *Vsav;
|
||||
Char *Vdp;
|
||||
Char *Vexpath;
|
||||
char **Vt;
|
||||
|
||||
Char **evalvec;
|
||||
Char *evalp;
|
||||
|
||||
/* word_chars is set by default to WORD_CHARS but can be overridden by
|
||||
the wordchars variable--if unset, reverts to WORD_CHARS */
|
||||
|
||||
Char *word_chars;
|
||||
|
||||
#define WORD_CHARS "*?_-.[]~=" /* default chars besides alnums in words */
|
||||
|
||||
Char *STR_SHELLPATH;
|
||||
|
||||
#include <paths.h>
|
||||
#ifdef _PATH_BSHELL
|
||||
Char *STR_BSHELL;
|
||||
#endif
|
||||
Char *STR_WORD_CHARS;
|
||||
Char **STR_environ;
|
933
bin/csh/dir.c
933
bin/csh/dir.c
@ -1,933 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)dir.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "dir.h"
|
||||
#include "extern.h"
|
||||
|
||||
/* Directory management. */
|
||||
|
||||
static struct directory
|
||||
*dfind __P((Char *));
|
||||
static Char *dfollow __P((Char *));
|
||||
static void printdirs __P((void));
|
||||
static Char *dgoto __P((Char *));
|
||||
static void dnewcwd __P((struct directory *));
|
||||
static void dset __P((Char *));
|
||||
|
||||
struct directory dhead; /* "head" of loop */
|
||||
int printd; /* force name to be printed */
|
||||
|
||||
static int dirflag = 0;
|
||||
|
||||
/*
|
||||
* dinit - initialize current working directory
|
||||
*/
|
||||
void
|
||||
dinit(hp)
|
||||
Char *hp;
|
||||
{
|
||||
char *tcp;
|
||||
Char *cp;
|
||||
struct directory *dp;
|
||||
char path[MAXPATHLEN];
|
||||
static char *emsg = "csh: Trying to start from \"%s\"\n";
|
||||
|
||||
/* Don't believe the login shell home, because it may be a symlink */
|
||||
tcp = getcwd(path, MAXPATHLEN); /* see ngetwd.c for System V version */
|
||||
if (tcp == NULL || *tcp == '\0') {
|
||||
(void) fprintf(csherr, "csh: %s: %s\n", path, strerror(errno));
|
||||
if (hp && *hp) {
|
||||
tcp = short2str(hp);
|
||||
if (chdir(tcp) == -1)
|
||||
cp = NULL;
|
||||
else
|
||||
cp = hp;
|
||||
(void) fprintf(csherr, emsg, vis_str(hp));
|
||||
}
|
||||
else
|
||||
cp = NULL;
|
||||
if (cp == NULL) {
|
||||
(void) fprintf(csherr, emsg, "/");
|
||||
if (chdir("/") == -1)
|
||||
/* I am not even try to print an error message! */
|
||||
xexit(1);
|
||||
cp = SAVE("/");
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct stat swd, shp;
|
||||
|
||||
/*
|
||||
* See if $HOME is the working directory we got and use that
|
||||
*/
|
||||
if (hp && *hp &&
|
||||
stat(tcp, &swd) != -1 && stat(short2str(hp), &shp) != -1 &&
|
||||
swd.st_dev == shp.st_dev && swd.st_ino == shp.st_ino)
|
||||
cp = hp;
|
||||
else {
|
||||
char *cwd;
|
||||
|
||||
/*
|
||||
* use PWD if we have it (for subshells)
|
||||
*/
|
||||
if ((cwd = getenv("PWD")) != NULL) {
|
||||
if (stat(cwd, &shp) != -1 && swd.st_dev == shp.st_dev &&
|
||||
swd.st_ino == shp.st_ino)
|
||||
tcp = cwd;
|
||||
}
|
||||
cp = dcanon(SAVE(tcp), STRNULL);
|
||||
}
|
||||
}
|
||||
|
||||
dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
|
||||
dp->di_name = Strsave(cp);
|
||||
dp->di_count = 0;
|
||||
dhead.di_next = dhead.di_prev = dp;
|
||||
dp->di_next = dp->di_prev = &dhead;
|
||||
printd = 0;
|
||||
dnewcwd(dp);
|
||||
}
|
||||
|
||||
static void
|
||||
dset(dp)
|
||||
Char *dp;
|
||||
{
|
||||
/*
|
||||
* Don't call set() directly cause if the directory contains ` or
|
||||
* other junk characters glob will fail.
|
||||
*/
|
||||
Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
|
||||
|
||||
vec[0] = Strsave(dp);
|
||||
vec[1] = 0;
|
||||
setq(STRcwd, vec, &shvhed);
|
||||
Setenv(STRPWD, dp);
|
||||
}
|
||||
|
||||
#define DIR_LONG 1
|
||||
#define DIR_VERT 2
|
||||
#define DIR_LINE 4
|
||||
|
||||
static void
|
||||
skipargs(v, str)
|
||||
Char ***v;
|
||||
char *str;
|
||||
{
|
||||
Char **n = *v, *s;
|
||||
|
||||
dirflag = 0;
|
||||
for (n++; *n != NULL && (*n)[0] == '-'; n++)
|
||||
for (s = &((*n)[1]); *s; s++)
|
||||
switch (*s) {
|
||||
case 'l':
|
||||
dirflag |= DIR_LONG;
|
||||
break;
|
||||
case 'v':
|
||||
dirflag |= DIR_VERT;
|
||||
break;
|
||||
case 'n':
|
||||
dirflag |= DIR_LINE;
|
||||
break;
|
||||
default:
|
||||
stderror(ERR_DIRUS, vis_str(**v), str);
|
||||
break;
|
||||
}
|
||||
*v = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* dodirs - list all directories in directory loop
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dodirs(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
skipargs(&v, "");
|
||||
|
||||
if (*v != NULL)
|
||||
stderror(ERR_DIRUS, "dirs", "");
|
||||
printdirs();
|
||||
}
|
||||
|
||||
static void
|
||||
printdirs()
|
||||
{
|
||||
struct directory *dp;
|
||||
Char *s, *hp = value(STRhome);
|
||||
int idx, len, cur;
|
||||
|
||||
if (*hp == '\0')
|
||||
hp = NULL;
|
||||
dp = dcwd;
|
||||
idx = 0;
|
||||
cur = 0;
|
||||
do {
|
||||
if (dp == &dhead)
|
||||
continue;
|
||||
if (dirflag & DIR_VERT) {
|
||||
(void) fprintf(cshout, "%d\t", idx++);
|
||||
cur = 0;
|
||||
}
|
||||
if (!(dirflag & DIR_LONG) && hp != NULL && !eq(hp, STRslash) &&
|
||||
(len = Strlen(hp), Strncmp(hp, dp->di_name, len) == 0) &&
|
||||
(dp->di_name[len] == '\0' || dp->di_name[len] == '/'))
|
||||
len = Strlen(s = (dp->di_name + len)) + 2;
|
||||
else
|
||||
len = Strlen(s = dp->di_name) + 1;
|
||||
|
||||
cur += len;
|
||||
if ((dirflag & DIR_LINE) && cur >= 80 - 1 && len < 80) {
|
||||
(void) fprintf(cshout, "\n");
|
||||
cur = len;
|
||||
}
|
||||
(void) fprintf(cshout, s != dp->di_name ? "~%s%c" : "%s%c",
|
||||
vis_str(s), (dirflag & DIR_VERT) ? '\n' : ' ');
|
||||
} while ((dp = dp->di_prev) != dcwd);
|
||||
if (!(dirflag & DIR_VERT))
|
||||
(void) fprintf(cshout, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
dtildepr(home, dir)
|
||||
Char *home, *dir;
|
||||
{
|
||||
|
||||
if (!eq(home, STRslash) && prefix(home, dir))
|
||||
(void) fprintf(cshout, "~%s", vis_str(dir + Strlen(home)));
|
||||
else
|
||||
(void) fprintf(cshout, "%s", vis_str(dir));
|
||||
}
|
||||
|
||||
void
|
||||
dtilde()
|
||||
{
|
||||
struct directory *d = dcwd;
|
||||
|
||||
do {
|
||||
if (d == &dhead)
|
||||
continue;
|
||||
d->di_name = dcanon(d->di_name, STRNULL);
|
||||
} while ((d = d->di_prev) != dcwd);
|
||||
|
||||
dset(dcwd->di_name);
|
||||
}
|
||||
|
||||
|
||||
/* dnormalize():
|
||||
* If the name starts with . or .. then we might need to normalize
|
||||
* it depending on the symbolic link flags
|
||||
*/
|
||||
Char *
|
||||
dnormalize(cp)
|
||||
Char *cp;
|
||||
{
|
||||
|
||||
#define UC (unsigned char)
|
||||
#define ISDOT(c) (UC(c)[0] == '.' && ((UC(c)[1] == '\0') || (UC(c)[1] == '/')))
|
||||
#define ISDOTDOT(c) (UC(c)[0] == '.' && ISDOT(&((c)[1])))
|
||||
|
||||
if ((unsigned char) cp[0] == '/')
|
||||
return (Strsave(cp));
|
||||
|
||||
if (adrof(STRignore_symlinks)) {
|
||||
int dotdot = 0;
|
||||
Char *dp, *cwd;
|
||||
|
||||
cwd = (Char *) xmalloc((size_t) ((Strlen(dcwd->di_name) + 3) *
|
||||
sizeof(Char)));
|
||||
(void) Strcpy(cwd, dcwd->di_name);
|
||||
|
||||
/*
|
||||
* Ignore . and count ..'s
|
||||
*/
|
||||
while (*cp) {
|
||||
if (ISDOT(cp)) {
|
||||
if (*++cp)
|
||||
cp++;
|
||||
}
|
||||
else if (ISDOTDOT(cp)) {
|
||||
dotdot++;
|
||||
cp += 2;
|
||||
if (*cp)
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (dotdot > 0)
|
||||
if ((dp = Strrchr(cwd, '/'))) {
|
||||
*dp = '\0';
|
||||
dotdot--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
if (*cp) {
|
||||
cwd[dotdot = Strlen(cwd)] = '/';
|
||||
cwd[dotdot + 1] = '\0';
|
||||
dp = Strspl(cwd, cp);
|
||||
xfree((ptr_t) cwd);
|
||||
return dp;
|
||||
}
|
||||
else {
|
||||
if (!*cwd) {
|
||||
cwd[0] = '/';
|
||||
cwd[1] = '\0';
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
}
|
||||
return Strsave(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* dochngd - implement chdir command.
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dochngd(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
Char *cp;
|
||||
struct directory *dp;
|
||||
|
||||
skipargs(&v, " [<dir>]");
|
||||
printd = 0;
|
||||
if (*v == NULL) {
|
||||
if ((cp = value(STRhome)) == NULL || *cp == 0)
|
||||
stderror(ERR_NAME | ERR_NOHOMEDIR);
|
||||
if (chdir(short2str(cp)) < 0)
|
||||
stderror(ERR_NAME | ERR_CANTCHANGE);
|
||||
cp = Strsave(cp);
|
||||
}
|
||||
else if (v[1] != NULL) {
|
||||
stderror(ERR_NAME | ERR_TOOMANY);
|
||||
/* NOTREACHED */
|
||||
return;
|
||||
}
|
||||
else if ((dp = dfind(*v)) != 0) {
|
||||
char *tmp;
|
||||
|
||||
printd = 1;
|
||||
if (chdir(tmp = short2str(dp->di_name)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
dcwd->di_prev->di_next = dcwd->di_next;
|
||||
dcwd->di_next->di_prev = dcwd->di_prev;
|
||||
dfree(dcwd);
|
||||
dnewcwd(dp);
|
||||
return;
|
||||
}
|
||||
else
|
||||
cp = dfollow(*v);
|
||||
dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
|
||||
dp->di_name = cp;
|
||||
dp->di_count = 0;
|
||||
dp->di_next = dcwd->di_next;
|
||||
dp->di_prev = dcwd->di_prev;
|
||||
dp->di_prev->di_next = dp;
|
||||
dp->di_next->di_prev = dp;
|
||||
dfree(dcwd);
|
||||
dnewcwd(dp);
|
||||
}
|
||||
|
||||
static Char *
|
||||
dgoto(cp)
|
||||
Char *cp;
|
||||
{
|
||||
Char *dp;
|
||||
|
||||
if (*cp != '/') {
|
||||
Char *p, *q;
|
||||
int cwdlen;
|
||||
|
||||
for (p = dcwd->di_name; *p++;)
|
||||
continue;
|
||||
if ((cwdlen = p - dcwd->di_name - 1) == 1) /* root */
|
||||
cwdlen = 0;
|
||||
for (p = cp; *p++;)
|
||||
continue;
|
||||
dp = (Char *) xmalloc((size_t)((cwdlen + (p - cp) + 1) * sizeof(Char)));
|
||||
for (p = dp, q = dcwd->di_name; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
if (cwdlen)
|
||||
p[-1] = '/';
|
||||
else
|
||||
p--; /* don't add a / after root */
|
||||
for (q = cp; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
xfree((ptr_t) cp);
|
||||
cp = dp;
|
||||
dp += cwdlen;
|
||||
}
|
||||
else
|
||||
dp = cp;
|
||||
|
||||
cp = dcanon(cp, dp);
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
* dfollow - change to arg directory; fall back on cdpath if not valid
|
||||
*/
|
||||
static Char *
|
||||
dfollow(cp)
|
||||
Char *cp;
|
||||
{
|
||||
Char *dp;
|
||||
struct varent *c;
|
||||
char ebuf[MAXPATHLEN];
|
||||
int serrno;
|
||||
|
||||
cp = globone(cp, G_ERROR);
|
||||
/*
|
||||
* if we are ignoring symlinks, try to fix relatives now.
|
||||
*/
|
||||
dp = dnormalize(cp);
|
||||
if (chdir(short2str(dp)) >= 0) {
|
||||
xfree((ptr_t) cp);
|
||||
return dgoto(dp);
|
||||
}
|
||||
else {
|
||||
xfree((ptr_t) dp);
|
||||
if (chdir(short2str(cp)) >= 0)
|
||||
return dgoto(cp);
|
||||
serrno = errno;
|
||||
}
|
||||
|
||||
if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp)
|
||||
&& (c = adrof(STRcdpath))) {
|
||||
Char **cdp;
|
||||
Char *p;
|
||||
Char buf[MAXPATHLEN];
|
||||
|
||||
for (cdp = c->vec; *cdp; cdp++) {
|
||||
for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';)
|
||||
continue;
|
||||
dp[-1] = '/';
|
||||
for (p = cp; (*dp++ = *p++) != '\0';)
|
||||
continue;
|
||||
if (chdir(short2str(buf)) >= 0) {
|
||||
printd = 1;
|
||||
xfree((ptr_t) cp);
|
||||
cp = Strsave(buf);
|
||||
return dgoto(cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
dp = value(cp);
|
||||
if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) {
|
||||
xfree((ptr_t) cp);
|
||||
cp = Strsave(dp);
|
||||
printd = 1;
|
||||
return dgoto(cp);
|
||||
}
|
||||
(void) strcpy(ebuf, short2str(cp));
|
||||
xfree((ptr_t) cp);
|
||||
stderror(ERR_SYSTEM, ebuf, strerror(serrno));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dopushd - push new directory onto directory stack.
|
||||
* with no arguments exchange top and second.
|
||||
* with numeric argument (+n) bring it to top.
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dopushd(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
struct directory *dp;
|
||||
|
||||
skipargs(&v, " [<dir>|+<n>]");
|
||||
printd = 1;
|
||||
if (*v == NULL) {
|
||||
char *tmp;
|
||||
|
||||
if ((dp = dcwd->di_prev) == &dhead)
|
||||
dp = dhead.di_prev;
|
||||
if (dp == dcwd)
|
||||
stderror(ERR_NAME | ERR_NODIR);
|
||||
if (chdir(tmp = short2str(dp->di_name)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
dp->di_prev->di_next = dp->di_next;
|
||||
dp->di_next->di_prev = dp->di_prev;
|
||||
dp->di_next = dcwd->di_next;
|
||||
dp->di_prev = dcwd;
|
||||
dcwd->di_next->di_prev = dp;
|
||||
dcwd->di_next = dp;
|
||||
}
|
||||
else if (v[1] != NULL) {
|
||||
stderror(ERR_NAME | ERR_TOOMANY);
|
||||
/* NOTREACHED */
|
||||
return;
|
||||
}
|
||||
else if ((dp = dfind(*v)) != NULL) {
|
||||
char *tmp;
|
||||
|
||||
if (chdir(tmp = short2str(dp->di_name)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
}
|
||||
else {
|
||||
Char *ccp;
|
||||
|
||||
ccp = dfollow(*v);
|
||||
dp = (struct directory *) xcalloc(sizeof(struct directory), 1);
|
||||
dp->di_name = ccp;
|
||||
dp->di_count = 0;
|
||||
dp->di_prev = dcwd;
|
||||
dp->di_next = dcwd->di_next;
|
||||
dcwd->di_next = dp;
|
||||
dp->di_next->di_prev = dp;
|
||||
}
|
||||
dnewcwd(dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* dfind - find a directory if specified by numeric (+n) argument
|
||||
*/
|
||||
static struct directory *
|
||||
dfind(cp)
|
||||
Char *cp;
|
||||
{
|
||||
struct directory *dp;
|
||||
int i;
|
||||
Char *ep;
|
||||
|
||||
if (*cp++ != '+')
|
||||
return (0);
|
||||
for (ep = cp; Isdigit(*ep); ep++)
|
||||
continue;
|
||||
if (*ep)
|
||||
return (0);
|
||||
i = getn(cp);
|
||||
if (i <= 0)
|
||||
return (0);
|
||||
for (dp = dcwd; i != 0; i--) {
|
||||
if ((dp = dp->di_prev) == &dhead)
|
||||
dp = dp->di_prev;
|
||||
if (dp == dcwd)
|
||||
stderror(ERR_NAME | ERR_DEEP);
|
||||
}
|
||||
return (dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* dopopd - pop a directory out of the directory stack
|
||||
* with a numeric argument just discard it.
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dopopd(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
struct directory *dp, *p = NULL;
|
||||
|
||||
skipargs(&v, " [+<n>]");
|
||||
printd = 1;
|
||||
if (*v == NULL)
|
||||
dp = dcwd;
|
||||
else if (v[1] != NULL) {
|
||||
stderror(ERR_NAME | ERR_TOOMANY);
|
||||
/* NOTREACHED */
|
||||
return;
|
||||
}
|
||||
else if ((dp = dfind(*v)) == 0)
|
||||
stderror(ERR_NAME | ERR_BADDIR);
|
||||
if (dp->di_prev == &dhead && dp->di_next == &dhead)
|
||||
stderror(ERR_NAME | ERR_EMPTY);
|
||||
if (dp == dcwd) {
|
||||
char *tmp;
|
||||
|
||||
if ((p = dp->di_prev) == &dhead)
|
||||
p = dhead.di_prev;
|
||||
if (chdir(tmp = short2str(p->di_name)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
}
|
||||
dp->di_prev->di_next = dp->di_next;
|
||||
dp->di_next->di_prev = dp->di_prev;
|
||||
if (dp == dcwd)
|
||||
dnewcwd(p);
|
||||
else {
|
||||
printdirs();
|
||||
}
|
||||
dfree(dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* dfree - free the directory (or keep it if it still has ref count)
|
||||
*/
|
||||
void
|
||||
dfree(dp)
|
||||
struct directory *dp;
|
||||
{
|
||||
|
||||
if (dp->di_count != 0) {
|
||||
dp->di_next = dp->di_prev = 0;
|
||||
}
|
||||
else {
|
||||
xfree((char *) dp->di_name);
|
||||
xfree((ptr_t) dp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
|
||||
* we are of course assuming that the file system is standardly
|
||||
* constructed (always have ..'s, directories have links)
|
||||
*/
|
||||
Char *
|
||||
dcanon(cp, p)
|
||||
Char *cp, *p;
|
||||
{
|
||||
Char *sp;
|
||||
Char *p1, *p2; /* general purpose */
|
||||
bool slash;
|
||||
|
||||
Char link[MAXPATHLEN];
|
||||
char tlink[MAXPATHLEN];
|
||||
int cc;
|
||||
Char *newcp;
|
||||
|
||||
/*
|
||||
* christos: if the path given does not start with a slash prepend cwd. If
|
||||
* cwd does not start with a path or the result would be too long abort().
|
||||
*/
|
||||
if (*cp != '/') {
|
||||
Char tmpdir[MAXPATHLEN];
|
||||
|
||||
p1 = value(STRcwd);
|
||||
if (p1 == NULL || *p1 != '/')
|
||||
abort();
|
||||
if (Strlen(p1) + Strlen(cp) + 1 >= MAXPATHLEN)
|
||||
abort();
|
||||
(void) Strcpy(tmpdir, p1);
|
||||
(void) Strcat(tmpdir, STRslash);
|
||||
(void) Strcat(tmpdir, cp);
|
||||
xfree((ptr_t) cp);
|
||||
cp = p = Strsave(tmpdir);
|
||||
}
|
||||
|
||||
while (*p) { /* for each component */
|
||||
sp = p; /* save slash address */
|
||||
while (*++p == '/') /* flush extra slashes */
|
||||
continue;
|
||||
if (p != ++sp)
|
||||
for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
p = sp; /* save start of component */
|
||||
slash = 0;
|
||||
while (*++p) /* find next slash or end of path */
|
||||
if (*p == '/') {
|
||||
slash = 1;
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*sp == '\0') /* if component is null */
|
||||
if (--sp == cp) /* if path is one char (i.e. /) */
|
||||
break;
|
||||
else
|
||||
*sp = '\0';
|
||||
else if (sp[0] == '.' && sp[1] == 0) {
|
||||
if (slash) {
|
||||
for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
p = --sp;
|
||||
}
|
||||
else if (--sp != cp)
|
||||
*sp = '\0';
|
||||
}
|
||||
else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) {
|
||||
/*
|
||||
* We have something like "yyy/xxx/..", where "yyy" can be null or
|
||||
* a path starting at /, and "xxx" is a single component. Before
|
||||
* compressing "xxx/..", we want to expand "yyy/xxx", if it is a
|
||||
* symbolic link.
|
||||
*/
|
||||
*--sp = 0; /* form the pathname for readlink */
|
||||
if (sp != cp && !adrof(STRignore_symlinks) &&
|
||||
(cc = readlink(short2str(cp), tlink, sizeof(tlink) - 1)) >= 0) {
|
||||
(void) Strcpy(link, str2short(tlink));
|
||||
link[cc] = '\0';
|
||||
|
||||
if (slash)
|
||||
*p = '/';
|
||||
/*
|
||||
* Point p to the '/' in "/..", and restore the '/'.
|
||||
*/
|
||||
*(p = sp) = '/';
|
||||
/*
|
||||
* find length of p
|
||||
*/
|
||||
for (p1 = p; *p1++;)
|
||||
continue;
|
||||
if (*link != '/') {
|
||||
/*
|
||||
* Relative path, expand it between the "yyy/" and the
|
||||
* "/..". First, back sp up to the character past "yyy/".
|
||||
*/
|
||||
while (*--sp != '/')
|
||||
continue;
|
||||
sp++;
|
||||
*sp = 0;
|
||||
/*
|
||||
* New length is "yyy/" + link + "/.." and rest
|
||||
*/
|
||||
p1 = newcp = (Char *) xmalloc((size_t)
|
||||
(((sp - cp) + cc + (p1 - p)) *
|
||||
sizeof(Char)));
|
||||
/*
|
||||
* Copy new path into newcp
|
||||
*/
|
||||
for (p2 = cp; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
/*
|
||||
* Restart canonicalization at expanded "/xxx".
|
||||
*/
|
||||
p = sp - cp - 1 + newcp;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* New length is link + "/.." and rest
|
||||
*/
|
||||
p1 = newcp = (Char *) xmalloc((size_t)
|
||||
((cc + (p1 - p)) * sizeof(Char)));
|
||||
/*
|
||||
* Copy new path into newcp
|
||||
*/
|
||||
for (p2 = link; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
/*
|
||||
* Restart canonicalization at beginning
|
||||
*/
|
||||
p = newcp;
|
||||
}
|
||||
xfree((ptr_t) cp);
|
||||
cp = newcp;
|
||||
continue; /* canonicalize the link */
|
||||
}
|
||||
*sp = '/';
|
||||
if (sp != cp)
|
||||
while (*--sp != '/')
|
||||
continue;
|
||||
if (slash) {
|
||||
for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
p = sp;
|
||||
}
|
||||
else if (cp == sp)
|
||||
*++sp = '\0';
|
||||
else
|
||||
*sp = '\0';
|
||||
}
|
||||
else { /* normal dir name (not . or .. or nothing) */
|
||||
|
||||
if (sp != cp && adrof(STRchase_symlinks) &&
|
||||
!adrof(STRignore_symlinks) &&
|
||||
(cc = readlink(short2str(cp), tlink, sizeof(tlink) - 1)) >= 0) {
|
||||
(void) Strcpy(link, str2short(tlink));
|
||||
link[cc] = '\0';
|
||||
|
||||
/*
|
||||
* restore the '/'.
|
||||
*/
|
||||
if (slash)
|
||||
*p = '/';
|
||||
|
||||
/*
|
||||
* point sp to p (rather than backing up).
|
||||
*/
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* find length of p
|
||||
*/
|
||||
for (p1 = p; *p1++;)
|
||||
continue;
|
||||
if (*link != '/') {
|
||||
/*
|
||||
* Relative path, expand it between the "yyy/" and the
|
||||
* remainder. First, back sp up to the character past
|
||||
* "yyy/".
|
||||
*/
|
||||
while (*--sp != '/')
|
||||
continue;
|
||||
sp++;
|
||||
*sp = 0;
|
||||
/*
|
||||
* New length is "yyy/" + link + "/.." and rest
|
||||
*/
|
||||
p1 = newcp = (Char *) xmalloc((size_t)
|
||||
(((sp - cp) + cc + (p1 - p))
|
||||
* sizeof(Char)));
|
||||
/*
|
||||
* Copy new path into newcp
|
||||
*/
|
||||
for (p2 = cp; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
/*
|
||||
* Restart canonicalization at expanded "/xxx".
|
||||
*/
|
||||
p = sp - cp - 1 + newcp;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* New length is link + the rest
|
||||
*/
|
||||
p1 = newcp = (Char *) xmalloc((size_t)
|
||||
((cc + (p1 - p)) * sizeof(Char)));
|
||||
/*
|
||||
* Copy new path into newcp
|
||||
*/
|
||||
for (p2 = link; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
|
||||
continue;
|
||||
/*
|
||||
* Restart canonicalization at beginning
|
||||
*/
|
||||
p = newcp;
|
||||
}
|
||||
xfree((ptr_t) cp);
|
||||
cp = newcp;
|
||||
continue; /* canonicalize the link */
|
||||
}
|
||||
if (slash)
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fix home...
|
||||
*/
|
||||
p1 = value(STRhome);
|
||||
cc = Strlen(p1);
|
||||
/*
|
||||
* See if we're not in a subdir of STRhome
|
||||
*/
|
||||
if (p1 && *p1 == '/' &&
|
||||
(Strncmp(p1, cp, cc) != 0 || (cp[cc] != '/' && cp[cc] != '\0'))) {
|
||||
static ino_t home_ino = -1;
|
||||
static dev_t home_dev = -1;
|
||||
static Char *home_ptr = NULL;
|
||||
struct stat statbuf;
|
||||
|
||||
/*
|
||||
* Get dev and ino of STRhome
|
||||
*/
|
||||
if (home_ptr != p1 &&
|
||||
stat(short2str(p1), &statbuf) != -1) {
|
||||
home_dev = statbuf.st_dev;
|
||||
home_ino = statbuf.st_ino;
|
||||
home_ptr = p1;
|
||||
}
|
||||
/*
|
||||
* Start comparing dev & ino backwards
|
||||
*/
|
||||
p2 = Strcpy(link, cp);
|
||||
for (sp = NULL; *p2 && stat(short2str(p2), &statbuf) != -1;) {
|
||||
if (statbuf.st_dev == home_dev &&
|
||||
statbuf.st_ino == home_ino) {
|
||||
sp = (Char *) - 1;
|
||||
break;
|
||||
}
|
||||
if ((sp = Strrchr(p2, '/')) != NULL)
|
||||
*sp = '\0';
|
||||
}
|
||||
/*
|
||||
* See if we found it
|
||||
*/
|
||||
if (*p2 && sp == (Char *) -1) {
|
||||
/*
|
||||
* Use STRhome to make '~' work
|
||||
*/
|
||||
newcp = Strspl(p1, cp + Strlen(p2));
|
||||
xfree((ptr_t) cp);
|
||||
cp = newcp;
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dnewcwd - make a new directory in the loop the current one
|
||||
*/
|
||||
static void
|
||||
dnewcwd(dp)
|
||||
struct directory *dp;
|
||||
{
|
||||
dcwd = dp;
|
||||
dset(dcwd->di_name);
|
||||
if (printd && !(adrof(STRpushdsilent)))
|
||||
printdirs();
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dir.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure for entries in directory stack.
|
||||
*/
|
||||
struct directory {
|
||||
struct directory *di_next; /* next in loop */
|
||||
struct directory *di_prev; /* prev in loop */
|
||||
unsigned short *di_count; /* refcount of processes */
|
||||
Char *di_name; /* actual name */
|
||||
};
|
||||
struct directory *dcwd; /* the one we are in now */
|
991
bin/csh/dol.c
991
bin/csh/dol.c
@ -1,991 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)dol.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* These routines perform variable substitution and quoting via ' and ".
|
||||
* To this point these constructs have been preserved in the divided
|
||||
* input words. Here we expand variables and turn quoting via ' and " into
|
||||
* QUOTE bits on characters (which prevent further interpretation).
|
||||
* If the `:q' modifier was applied during history expansion, then
|
||||
* some QUOTEing may have occurred already, so we dont "trim()" here.
|
||||
*/
|
||||
|
||||
static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */
|
||||
static Char *Dcp, **Dvp; /* Input vector for Dreadc */
|
||||
|
||||
#define DEOF -1
|
||||
|
||||
#define unDgetC(c) Dpeekc = c
|
||||
|
||||
#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */
|
||||
|
||||
/*
|
||||
* The following variables give the information about the current
|
||||
* $ expansion, recording the current word position, the remaining
|
||||
* words within this expansion, the count of remaining words, and the
|
||||
* information about any : modifier which is being applied.
|
||||
*/
|
||||
#define MAXWLEN (BUFSIZ - 4)
|
||||
#define MAXMOD MAXWLEN /* This cannot overflow */
|
||||
static Char *dolp; /* Remaining chars from this word */
|
||||
static Char **dolnxt; /* Further words */
|
||||
static int dolcnt; /* Count of further words */
|
||||
static Char dolmod[MAXMOD]; /* : modifier character */
|
||||
static int dolnmod; /* Number of modifiers */
|
||||
static int dolmcnt; /* :gx -> 10000, else 1 */
|
||||
static int dolwcnt; /* :wx -> 10000, else 1 */
|
||||
|
||||
static void Dfix2 __P((Char **));
|
||||
static Char *Dpack __P((Char *, Char *));
|
||||
static int Dword __P((void));
|
||||
static void dolerror __P((Char *));
|
||||
static int DgetC __P((int));
|
||||
static void Dgetdol __P((void));
|
||||
static void fixDolMod __P((void));
|
||||
static void setDolp __P((Char *));
|
||||
static void unDredc __P((int));
|
||||
static int Dredc __P((void));
|
||||
static void Dtestq __P((int));
|
||||
|
||||
|
||||
/*
|
||||
* Fix up the $ expansions and quotations in the
|
||||
* argument list to command t.
|
||||
*/
|
||||
void
|
||||
Dfix(t)
|
||||
struct command *t;
|
||||
{
|
||||
Char **pp;
|
||||
Char *p;
|
||||
|
||||
if (noexec)
|
||||
return;
|
||||
/* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
|
||||
for (pp = t->t_dcom; (p = *pp++) != NULL;)
|
||||
for (; *p; p++) {
|
||||
if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */
|
||||
Dfix2(t->t_dcom); /* found one */
|
||||
blkfree(t->t_dcom);
|
||||
t->t_dcom = gargv;
|
||||
gargv = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $ substitute one word, for i/o redirection
|
||||
*/
|
||||
Char *
|
||||
Dfix1(cp)
|
||||
Char *cp;
|
||||
{
|
||||
Char *Dv[2];
|
||||
|
||||
if (noexec)
|
||||
return (0);
|
||||
Dv[0] = cp;
|
||||
Dv[1] = NULL;
|
||||
Dfix2(Dv);
|
||||
if (gargc != 1) {
|
||||
setname(vis_str(cp));
|
||||
stderror(ERR_NAME | ERR_AMBIG);
|
||||
}
|
||||
cp = Strsave(gargv[0]);
|
||||
blkfree(gargv), gargv = 0;
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine to do actual fixing after state initialization.
|
||||
*/
|
||||
static void
|
||||
Dfix2(v)
|
||||
Char **v;
|
||||
{
|
||||
ginit(); /* Initialize glob's area pointers */
|
||||
Dvp = v;
|
||||
Dcp = STRNULL; /* Setup input vector for Dreadc */
|
||||
unDgetC(0);
|
||||
unDredc(0); /* Clear out any old peeks (at error) */
|
||||
dolp = 0;
|
||||
dolcnt = 0; /* Clear out residual $ expands (...) */
|
||||
while (Dword())
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pack up more characters in this word
|
||||
*/
|
||||
static Char *
|
||||
Dpack(wbuf, wp)
|
||||
Char *wbuf, *wp;
|
||||
{
|
||||
int c;
|
||||
int i = MAXWLEN - (wp - wbuf);
|
||||
|
||||
for (;;) {
|
||||
c = DgetC(DODOL);
|
||||
if (c == '\\') {
|
||||
c = DgetC(0);
|
||||
if (c == DEOF) {
|
||||
unDredc(c);
|
||||
*wp = 0;
|
||||
Gcat(STRNULL, wbuf);
|
||||
return (NULL);
|
||||
}
|
||||
if (c == '\n')
|
||||
c = ' ';
|
||||
else
|
||||
c |= QUOTE;
|
||||
}
|
||||
if (c == DEOF) {
|
||||
unDredc(c);
|
||||
*wp = 0;
|
||||
Gcat(STRNULL, wbuf);
|
||||
return (NULL);
|
||||
}
|
||||
if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */
|
||||
unDgetC(c);
|
||||
if (cmap(c, QUOTES))
|
||||
return (wp);
|
||||
*wp++ = 0;
|
||||
Gcat(STRNULL, wbuf);
|
||||
return (NULL);
|
||||
}
|
||||
if (--i <= 0)
|
||||
stderror(ERR_WTOOLONG);
|
||||
*wp++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a word. This routine is analogous to the routine
|
||||
* word() in sh.lex.c for the main lexical input. One difference
|
||||
* here is that we don't get a newline to terminate our expansion.
|
||||
* Rather, DgetC will return a DEOF when we hit the end-of-input.
|
||||
*/
|
||||
static int
|
||||
Dword()
|
||||
{
|
||||
int c, c1;
|
||||
Char wbuf[BUFSIZ];
|
||||
Char *wp = wbuf;
|
||||
int i = MAXWLEN;
|
||||
bool dolflg;
|
||||
bool sofar = 0, done = 0;
|
||||
|
||||
while (!done) {
|
||||
done = 1;
|
||||
c = DgetC(DODOL);
|
||||
switch (c) {
|
||||
|
||||
case DEOF:
|
||||
if (sofar == 0)
|
||||
return (0);
|
||||
/* finish this word and catch the code above the next time */
|
||||
unDredc(c);
|
||||
/* fall into ... */
|
||||
|
||||
case '\n':
|
||||
*wp = 0;
|
||||
Gcat(STRNULL, wbuf);
|
||||
return (1);
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
done = 0;
|
||||
break;
|
||||
|
||||
case '`':
|
||||
/* We preserve ` quotations which are done yet later */
|
||||
*wp++ = c, --i;
|
||||
case '\'':
|
||||
case '"':
|
||||
/*
|
||||
* Note that DgetC never returns a QUOTES character from an
|
||||
* expansion, so only true input quotes will get us here or out.
|
||||
*/
|
||||
c1 = c;
|
||||
dolflg = c1 == '"' ? DODOL : 0;
|
||||
for (;;) {
|
||||
c = DgetC(dolflg);
|
||||
if (c == c1)
|
||||
break;
|
||||
if (c == '\n' || c == DEOF)
|
||||
stderror(ERR_UNMATCHED, c1);
|
||||
if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))
|
||||
--wp, ++i;
|
||||
if (--i <= 0)
|
||||
stderror(ERR_WTOOLONG);
|
||||
switch (c1) {
|
||||
|
||||
case '"':
|
||||
/*
|
||||
* Leave any `s alone for later. Other chars are all
|
||||
* quoted, thus `...` can tell it was within "...".
|
||||
*/
|
||||
*wp++ = c == '`' ? '`' : c | QUOTE;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
/* Prevent all further interpretation */
|
||||
*wp++ = c | QUOTE;
|
||||
break;
|
||||
|
||||
case '`':
|
||||
/* Leave all text alone for later */
|
||||
*wp++ = c;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c1 == '`')
|
||||
*wp++ = '`' /* i--; eliminated */;
|
||||
sofar = 1;
|
||||
if ((wp = Dpack(wbuf, wp)) == NULL)
|
||||
return (1);
|
||||
else {
|
||||
i = MAXWLEN - (wp - wbuf);
|
||||
done = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
c = DgetC(0); /* No $ subst! */
|
||||
if (c == '\n' || c == DEOF) {
|
||||
done = 0;
|
||||
break;
|
||||
}
|
||||
c |= QUOTE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (done) {
|
||||
unDgetC(c);
|
||||
sofar = 1;
|
||||
if ((wp = Dpack(wbuf, wp)) == NULL)
|
||||
return (1);
|
||||
else {
|
||||
i = MAXWLEN - (wp - wbuf);
|
||||
done = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Really NOTREACHED */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get a character, performing $ substitution unless flag is 0.
|
||||
* Any QUOTES character which is returned from a $ expansion is
|
||||
* QUOTEd so that it will not be recognized above.
|
||||
*/
|
||||
static int
|
||||
DgetC(flag)
|
||||
int flag;
|
||||
{
|
||||
int c;
|
||||
|
||||
top:
|
||||
if ((c = Dpeekc) != '\0') {
|
||||
Dpeekc = 0;
|
||||
return (c);
|
||||
}
|
||||
if (lap) {
|
||||
c = *lap++ & (QUOTE | TRIM);
|
||||
if (c == 0) {
|
||||
lap = 0;
|
||||
goto top;
|
||||
}
|
||||
quotspec:
|
||||
if (cmap(c, QUOTES))
|
||||
return (c | QUOTE);
|
||||
return (c);
|
||||
}
|
||||
if (dolp) {
|
||||
if ((c = *dolp++ & (QUOTE | TRIM)) != '\0')
|
||||
goto quotspec;
|
||||
if (dolcnt > 0) {
|
||||
setDolp(*dolnxt++);
|
||||
--dolcnt;
|
||||
return (' ');
|
||||
}
|
||||
dolp = 0;
|
||||
}
|
||||
if (dolcnt > 0) {
|
||||
setDolp(*dolnxt++);
|
||||
--dolcnt;
|
||||
goto top;
|
||||
}
|
||||
c = Dredc();
|
||||
if (c == '$' && flag) {
|
||||
Dgetdol();
|
||||
goto top;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
static Char *nulvec[] = {0};
|
||||
static struct varent nulargv = {nulvec, STRargv, { NULL, NULL, NULL }, 0};
|
||||
|
||||
static void
|
||||
dolerror(s)
|
||||
Char *s;
|
||||
{
|
||||
setname(vis_str(s));
|
||||
stderror(ERR_NAME | ERR_RANGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the multitudinous $ expansion forms.
|
||||
* Ugh.
|
||||
*/
|
||||
static void
|
||||
Dgetdol()
|
||||
{
|
||||
Char *np;
|
||||
struct varent *vp = NULL;
|
||||
Char name[4 * MAXVARLEN + 1];
|
||||
int c, sc;
|
||||
int subscr = 0, lwb = 1, upb = 0;
|
||||
bool dimen = 0, bitset = 0;
|
||||
char tnp;
|
||||
Char wbuf[BUFSIZ];
|
||||
static Char *dolbang = NULL;
|
||||
|
||||
dolnmod = dolmcnt = dolwcnt = 0;
|
||||
c = sc = DgetC(0);
|
||||
if (c == '{')
|
||||
c = DgetC(0); /* sc is { to take } later */
|
||||
if ((c & TRIM) == '#')
|
||||
dimen++, c = DgetC(0); /* $# takes dimension */
|
||||
else if (c == '?')
|
||||
bitset++, c = DgetC(0); /* $? tests existence */
|
||||
switch (c) {
|
||||
|
||||
case '!':
|
||||
if (dimen || bitset)
|
||||
stderror(ERR_SYNTAX);
|
||||
if (backpid != 0) {
|
||||
if (dolbang)
|
||||
xfree((ptr_t) dolbang);
|
||||
setDolp(dolbang = putn(backpid));
|
||||
}
|
||||
goto eatbrac;
|
||||
|
||||
case '$':
|
||||
if (dimen || bitset)
|
||||
stderror(ERR_SYNTAX);
|
||||
setDolp(doldol);
|
||||
goto eatbrac;
|
||||
|
||||
case '<' | QUOTE:
|
||||
if (bitset)
|
||||
stderror(ERR_NOTALLOWED, "$?<");
|
||||
if (dimen)
|
||||
stderror(ERR_NOTALLOWED, "$?#");
|
||||
for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
|
||||
*np = (unsigned char) tnp;
|
||||
if (np >= &wbuf[BUFSIZ - 1])
|
||||
stderror(ERR_LTOOLONG);
|
||||
if (tnp == '\n')
|
||||
break;
|
||||
}
|
||||
*np = 0;
|
||||
/*
|
||||
* KLUDGE: dolmod is set here because it will cause setDolp to call
|
||||
* domod and thus to copy wbuf. Otherwise setDolp would use it
|
||||
* directly. If we saved it ourselves, no one would know when to free
|
||||
* it. The actual function of the 'q' causes filename expansion not to
|
||||
* be done on the interpolated value.
|
||||
*/
|
||||
dolmod[dolnmod++] = 'q';
|
||||
dolmcnt = 10000;
|
||||
setDolp(wbuf);
|
||||
goto eatbrac;
|
||||
|
||||
case DEOF:
|
||||
case '\n':
|
||||
stderror(ERR_SYNTAX);
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
|
||||
case '*':
|
||||
(void) Strcpy(name, STRargv);
|
||||
vp = adrof(STRargv);
|
||||
subscr = -1; /* Prevent eating [...] */
|
||||
break;
|
||||
|
||||
default:
|
||||
np = name;
|
||||
if (Isdigit(c)) {
|
||||
if (dimen)
|
||||
stderror(ERR_NOTALLOWED, "$#<num>");
|
||||
subscr = 0;
|
||||
do {
|
||||
subscr = subscr * 10 + c - '0';
|
||||
c = DgetC(0);
|
||||
} while (Isdigit(c));
|
||||
unDredc(c);
|
||||
if (subscr < 0) {
|
||||
dolerror(vp->v_name);
|
||||
return;
|
||||
}
|
||||
if (subscr == 0) {
|
||||
if (bitset) {
|
||||
dolp = ffile ? STR1 : STR0;
|
||||
goto eatbrac;
|
||||
}
|
||||
if (ffile == 0)
|
||||
stderror(ERR_DOLZERO);
|
||||
fixDolMod();
|
||||
setDolp(ffile);
|
||||
goto eatbrac;
|
||||
}
|
||||
if (bitset)
|
||||
stderror(ERR_DOLQUEST);
|
||||
vp = adrof(STRargv);
|
||||
if (vp == 0) {
|
||||
vp = &nulargv;
|
||||
goto eatmod;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!alnum(c))
|
||||
stderror(ERR_VARALNUM);
|
||||
for (;;) {
|
||||
*np++ = c;
|
||||
c = DgetC(0);
|
||||
if (!alnum(c))
|
||||
break;
|
||||
if (np >= &name[MAXVARLEN])
|
||||
stderror(ERR_VARTOOLONG);
|
||||
}
|
||||
*np++ = 0;
|
||||
unDredc(c);
|
||||
vp = adrof(name);
|
||||
}
|
||||
if (bitset) {
|
||||
dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
|
||||
goto eatbrac;
|
||||
}
|
||||
if (vp == 0) {
|
||||
np = str2short(getenv(short2str(name)));
|
||||
if (np) {
|
||||
fixDolMod();
|
||||
setDolp(np);
|
||||
goto eatbrac;
|
||||
}
|
||||
udvar(name);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
c = DgetC(0);
|
||||
upb = blklen(vp->vec);
|
||||
if (dimen == 0 && subscr == 0 && c == '[') {
|
||||
np = name;
|
||||
for (;;) {
|
||||
c = DgetC(DODOL); /* Allow $ expand within [ ] */
|
||||
if (c == ']')
|
||||
break;
|
||||
if (c == '\n' || c == DEOF)
|
||||
stderror(ERR_INCBR);
|
||||
if (np >= &name[sizeof(name) / sizeof(Char) - 2])
|
||||
stderror(ERR_VARTOOLONG);
|
||||
*np++ = c;
|
||||
}
|
||||
*np = 0, np = name;
|
||||
if (dolp || dolcnt) /* $ exp must end before ] */
|
||||
stderror(ERR_EXPORD);
|
||||
if (!*np)
|
||||
stderror(ERR_SYNTAX);
|
||||
if (Isdigit(*np)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
|
||||
continue;
|
||||
if ((i < 0 || i > upb) && !any("-*", *np)) {
|
||||
dolerror(vp->v_name);
|
||||
return;
|
||||
}
|
||||
lwb = i;
|
||||
if (!*np)
|
||||
upb = lwb, np = STRstar;
|
||||
}
|
||||
if (*np == '*')
|
||||
np++;
|
||||
else if (*np != '-')
|
||||
stderror(ERR_MISSING, '-');
|
||||
else {
|
||||
int i = upb;
|
||||
|
||||
np++;
|
||||
if (Isdigit(*np)) {
|
||||
i = 0;
|
||||
while (Isdigit(*np))
|
||||
i = i * 10 + *np++ - '0';
|
||||
if (i < 0 || i > upb) {
|
||||
dolerror(vp->v_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (i < lwb)
|
||||
upb = lwb - 1;
|
||||
else
|
||||
upb = i;
|
||||
}
|
||||
if (lwb == 0) {
|
||||
if (upb != 0) {
|
||||
dolerror(vp->v_name);
|
||||
return;
|
||||
}
|
||||
upb = -1;
|
||||
}
|
||||
if (*np)
|
||||
stderror(ERR_SYNTAX);
|
||||
}
|
||||
else {
|
||||
if (subscr > 0) {
|
||||
if (subscr > upb)
|
||||
lwb = 1, upb = 0;
|
||||
else
|
||||
lwb = upb = subscr;
|
||||
}
|
||||
unDredc(c);
|
||||
}
|
||||
if (dimen) {
|
||||
Char *cp = putn(upb - lwb + 1);
|
||||
|
||||
addla(cp);
|
||||
xfree((ptr_t) cp);
|
||||
}
|
||||
else {
|
||||
eatmod:
|
||||
fixDolMod();
|
||||
dolnxt = &vp->vec[lwb - 1];
|
||||
dolcnt = upb - lwb + 1;
|
||||
}
|
||||
eatbrac:
|
||||
if (sc == '{') {
|
||||
c = Dredc();
|
||||
if (c != '}')
|
||||
stderror(ERR_MISSING, '}');
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fixDolMod()
|
||||
{
|
||||
int c;
|
||||
|
||||
c = DgetC(0);
|
||||
if (c == ':') {
|
||||
do {
|
||||
c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
|
||||
if (c == 'g' || c == 'a') {
|
||||
if (c == 'g')
|
||||
dolmcnt = 10000;
|
||||
else
|
||||
dolwcnt = 10000;
|
||||
c = DgetC(0);
|
||||
}
|
||||
if ((c == 'g' && dolmcnt != 10000) ||
|
||||
(c == 'a' && dolwcnt != 10000)) {
|
||||
if (c == 'g')
|
||||
dolmcnt = 10000;
|
||||
else
|
||||
dolwcnt = 10000;
|
||||
c = DgetC(0);
|
||||
}
|
||||
|
||||
if (c == 's') { /* [eichin:19910926.0755EST] */
|
||||
int delimcnt = 2;
|
||||
int delim = DgetC(0);
|
||||
dolmod[dolnmod++] = c;
|
||||
dolmod[dolnmod++] = delim;
|
||||
|
||||
if (!delim || letter(delim)
|
||||
|| Isdigit(delim) || any(" \t\n", delim)) {
|
||||
seterror(ERR_BADSUBST);
|
||||
break;
|
||||
}
|
||||
while ((c = DgetC(0)) != (-1)) {
|
||||
dolmod[dolnmod++] = c;
|
||||
if(c == delim) delimcnt--;
|
||||
if(!delimcnt) break;
|
||||
}
|
||||
if(delimcnt) {
|
||||
seterror(ERR_BADSUBST);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!any("htrqxes", c))
|
||||
stderror(ERR_BADMOD, c);
|
||||
dolmod[dolnmod++] = c;
|
||||
if (c == 'q')
|
||||
dolmcnt = 10000;
|
||||
}
|
||||
while ((c = DgetC(0)) == ':');
|
||||
unDredc(c);
|
||||
}
|
||||
else
|
||||
unDredc(c);
|
||||
}
|
||||
|
||||
static void
|
||||
setDolp(cp)
|
||||
Char *cp;
|
||||
{
|
||||
Char *dp;
|
||||
int i;
|
||||
|
||||
if (dolnmod == 0 || dolmcnt == 0) {
|
||||
dolp = cp;
|
||||
return;
|
||||
}
|
||||
dp = cp = Strsave(cp);
|
||||
for (i = 0; i < dolnmod; i++) {
|
||||
/* handle s// [eichin:19910926.0510EST] */
|
||||
if(dolmod[i] == 's') {
|
||||
int delim;
|
||||
Char *lhsub, *rhsub, *np;
|
||||
size_t lhlen = 0, rhlen = 0;
|
||||
int didmod = 0;
|
||||
|
||||
delim = dolmod[++i];
|
||||
if (!delim || letter(delim)
|
||||
|| Isdigit(delim) || any(" \t\n", delim)) {
|
||||
seterror(ERR_BADSUBST);
|
||||
break;
|
||||
}
|
||||
lhsub = &dolmod[++i];
|
||||
while(dolmod[i] != delim && dolmod[++i]) {
|
||||
lhlen++;
|
||||
}
|
||||
dolmod[i] = 0;
|
||||
rhsub = &dolmod[++i];
|
||||
while(dolmod[i] != delim && dolmod[++i]) {
|
||||
rhlen++;
|
||||
}
|
||||
dolmod[i] = 0;
|
||||
|
||||
do {
|
||||
dp = Strstr(cp, lhsub);
|
||||
if (dp) {
|
||||
np = (Char *) xmalloc((size_t)
|
||||
((Strlen(cp) + 1 - lhlen + rhlen) *
|
||||
sizeof(Char)));
|
||||
(void) Strncpy(np, cp, dp - cp);
|
||||
(void) Strcpy(np + (dp - cp), rhsub);
|
||||
(void) Strcpy(np + (dp - cp) + rhlen, dp + lhlen);
|
||||
|
||||
xfree((ptr_t) cp);
|
||||
dp = cp = np;
|
||||
didmod = 1;
|
||||
} else {
|
||||
/* should this do a seterror? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (dolwcnt == 10000);
|
||||
/*
|
||||
* restore dolmod for additional words
|
||||
*/
|
||||
dolmod[i] = rhsub[-1] = delim;
|
||||
if (didmod)
|
||||
dolmcnt--;
|
||||
else
|
||||
break;
|
||||
} else {
|
||||
int didmod = 0;
|
||||
|
||||
do {
|
||||
if ((dp = domod(cp, dolmod[i]))) {
|
||||
didmod = 1;
|
||||
if (Strcmp(cp, dp) == 0) {
|
||||
xfree((ptr_t) cp);
|
||||
cp = dp;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
xfree((ptr_t) cp);
|
||||
cp = dp;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (dolwcnt == 10000);
|
||||
dp = cp;
|
||||
if (didmod)
|
||||
dolmcnt--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dp) {
|
||||
addla(dp);
|
||||
xfree((ptr_t) dp);
|
||||
}
|
||||
else
|
||||
addla(cp);
|
||||
|
||||
dolp = STRNULL;
|
||||
if (seterr)
|
||||
stderror(ERR_OLD);
|
||||
}
|
||||
|
||||
static void
|
||||
unDredc(c)
|
||||
int c;
|
||||
{
|
||||
|
||||
Dpeekrd = c;
|
||||
}
|
||||
|
||||
static int
|
||||
Dredc()
|
||||
{
|
||||
int c;
|
||||
|
||||
if ((c = Dpeekrd) != '\0') {
|
||||
Dpeekrd = 0;
|
||||
return (c);
|
||||
}
|
||||
if (Dcp && (c = *Dcp++))
|
||||
return (c & (QUOTE | TRIM));
|
||||
if (*Dvp == 0) {
|
||||
Dcp = 0;
|
||||
return (DEOF);
|
||||
}
|
||||
Dcp = *Dvp++;
|
||||
return (' ');
|
||||
}
|
||||
|
||||
static void
|
||||
Dtestq(c)
|
||||
int c;
|
||||
{
|
||||
|
||||
if (cmap(c, QUOTES))
|
||||
gflag = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Form a shell temporary file (in unit 0) from the words
|
||||
* of the shell input up to EOF or a line the same as "term".
|
||||
* Unit 0 should have been closed before this call.
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
heredoc(term)
|
||||
Char *term;
|
||||
{
|
||||
int c;
|
||||
Char *Dv[2];
|
||||
Char obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ];
|
||||
int ocnt, lcnt, mcnt;
|
||||
Char *lbp, *obp, *mbp;
|
||||
Char **vp;
|
||||
bool quoted;
|
||||
char *tmp;
|
||||
|
||||
if (creat(tmp = short2str(shtemp), 0600) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
(void) close(0);
|
||||
if (open(tmp, O_RDWR) < 0) {
|
||||
int oerrno = errno;
|
||||
|
||||
(void) unlink(tmp);
|
||||
errno = oerrno;
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
}
|
||||
(void) unlink(tmp); /* 0 0 inode! */
|
||||
Dv[0] = term;
|
||||
Dv[1] = NULL;
|
||||
gflag = 0;
|
||||
trim(Dv);
|
||||
rscan(Dv, Dtestq);
|
||||
quoted = gflag;
|
||||
ocnt = BUFSIZ;
|
||||
obp = obuf;
|
||||
for (;;) {
|
||||
/*
|
||||
* Read up a line
|
||||
*/
|
||||
lbp = lbuf;
|
||||
lcnt = BUFSIZ - 4;
|
||||
for (;;) {
|
||||
c = readc(1); /* 1 -> Want EOF returns */
|
||||
if (c < 0 || c == '\n')
|
||||
break;
|
||||
if ((c &= TRIM) != '\0') {
|
||||
*lbp++ = c;
|
||||
if (--lcnt < 0) {
|
||||
setname("<<");
|
||||
stderror(ERR_NAME | ERR_OVERFLOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
*lbp = 0;
|
||||
|
||||
/*
|
||||
* Check for EOF or compare to terminator -- before expansion
|
||||
*/
|
||||
if (c < 0 || eq(lbuf, term)) {
|
||||
(void) write(0, short2str(obuf), (size_t) (BUFSIZ - ocnt));
|
||||
(void) lseek(0, 0l, L_SET);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If term was quoted or -n just pass it on
|
||||
*/
|
||||
if (quoted || noexec) {
|
||||
*lbp++ = '\n';
|
||||
*lbp = 0;
|
||||
for (lbp = lbuf; (c = *lbp++) != '\0';) {
|
||||
*obp++ = c;
|
||||
if (--ocnt == 0) {
|
||||
(void) write(0, short2str(obuf), BUFSIZ);
|
||||
obp = obuf;
|
||||
ocnt = BUFSIZ;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Term wasn't quoted so variable and then command expand the input
|
||||
* line
|
||||
*/
|
||||
Dcp = lbuf;
|
||||
Dvp = Dv + 1;
|
||||
mbp = mbuf;
|
||||
mcnt = BUFSIZ - 4;
|
||||
for (;;) {
|
||||
c = DgetC(DODOL);
|
||||
if (c == DEOF)
|
||||
break;
|
||||
if ((c &= TRIM) == 0)
|
||||
continue;
|
||||
/* \ quotes \ $ ` here */
|
||||
if (c == '\\') {
|
||||
c = DgetC(0);
|
||||
if (!any("$\\`", c))
|
||||
unDgetC(c | QUOTE), c = '\\';
|
||||
else
|
||||
c |= QUOTE;
|
||||
}
|
||||
*mbp++ = c;
|
||||
if (--mcnt == 0) {
|
||||
setname("<<");
|
||||
stderror(ERR_NAME | ERR_OVERFLOW);
|
||||
}
|
||||
}
|
||||
*mbp++ = 0;
|
||||
|
||||
/*
|
||||
* If any ` in line do command substitution
|
||||
*/
|
||||
mbp = mbuf;
|
||||
if (any(short2str(mbp), '`')) {
|
||||
/*
|
||||
* 1 arg to dobackp causes substitution to be literal. Words are
|
||||
* broken only at newlines so that all blanks and tabs are
|
||||
* preserved. Blank lines (null words) are not discarded.
|
||||
*/
|
||||
vp = dobackp(mbuf, 1);
|
||||
}
|
||||
else
|
||||
/* Setup trivial vector similar to return of dobackp */
|
||||
Dv[0] = mbp, Dv[1] = NULL, vp = Dv;
|
||||
|
||||
/*
|
||||
* Resurrect the words from the command substitution each separated by
|
||||
* a newline. Note that the last newline of a command substitution
|
||||
* will have been discarded, but we put a newline after the last word
|
||||
* because this represents the newline after the last input line!
|
||||
*/
|
||||
for (; *vp; vp++) {
|
||||
for (mbp = *vp; *mbp; mbp++) {
|
||||
*obp++ = *mbp & TRIM;
|
||||
if (--ocnt == 0) {
|
||||
(void) write(0, short2str(obuf), BUFSIZ);
|
||||
obp = obuf;
|
||||
ocnt = BUFSIZ;
|
||||
}
|
||||
}
|
||||
*obp++ = '\n';
|
||||
if (--ocnt == 0) {
|
||||
(void) write(0, short2str(obuf), BUFSIZ);
|
||||
obp = obuf;
|
||||
ocnt = BUFSIZ;
|
||||
}
|
||||
}
|
||||
if (pargv)
|
||||
blkfree(pargv), pargv = 0;
|
||||
}
|
||||
}
|
411
bin/csh/err.c
411
bin/csh/err.c
@ -1,411 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
char *seterr = NULL; /* Holds last error if there was one */
|
||||
|
||||
#define ERR_FLAGS 0xf0000000
|
||||
#define ERR_NAME 0x10000000
|
||||
#define ERR_SILENT 0x20000000
|
||||
#define ERR_OLD 0x40000000
|
||||
|
||||
static char *errorlist[] =
|
||||
{
|
||||
#define ERR_SYNTAX 0
|
||||
"Syntax Error",
|
||||
#define ERR_NOTALLOWED 1
|
||||
"%s is not allowed",
|
||||
#define ERR_WTOOLONG 2
|
||||
"Word too long",
|
||||
#define ERR_LTOOLONG 3
|
||||
"$< line too long",
|
||||
#define ERR_DOLZERO 4
|
||||
"No file for $0",
|
||||
#define ERR_DOLQUEST 5
|
||||
"$? not allowed here",
|
||||
#define ERR_INCBR 6
|
||||
"Incomplete [] modifier",
|
||||
#define ERR_EXPORD 7
|
||||
"$ expansion must end before ]",
|
||||
#define ERR_BADMOD 8
|
||||
"Bad : modifier in $ (%c)",
|
||||
#define ERR_SUBSCRIPT 9
|
||||
"Subscript error",
|
||||
#define ERR_BADNUM 10
|
||||
"Badly formed number",
|
||||
#define ERR_NOMORE 11
|
||||
"No more words",
|
||||
#define ERR_FILENAME 12
|
||||
"Missing file name",
|
||||
#define ERR_GLOB 13
|
||||
"Internal glob error",
|
||||
#define ERR_COMMAND 14
|
||||
"Command not found",
|
||||
#define ERR_TOOFEW 15
|
||||
"Too few arguments",
|
||||
#define ERR_TOOMANY 16
|
||||
"Too many arguments",
|
||||
#define ERR_DANGER 17
|
||||
"Too dangerous to alias that",
|
||||
#define ERR_EMPTYIF 18
|
||||
"Empty if",
|
||||
#define ERR_IMPRTHEN 19
|
||||
"Improper then",
|
||||
#define ERR_NOPAREN 20
|
||||
"Words not parenthesized",
|
||||
#define ERR_NOTFOUND 21
|
||||
"%s not found",
|
||||
#define ERR_MASK 22
|
||||
"Improper mask",
|
||||
#define ERR_LIMIT 23
|
||||
"No such limit",
|
||||
#define ERR_TOOLARGE 24
|
||||
"Argument too large",
|
||||
#define ERR_SCALEF 25
|
||||
"Improper or unknown scale factor",
|
||||
#define ERR_UNDVAR 26
|
||||
"Undefined variable",
|
||||
#define ERR_DEEP 27
|
||||
"Directory stack not that deep",
|
||||
#define ERR_BADSIG 28
|
||||
"Bad signal number",
|
||||
#define ERR_UNKSIG 29
|
||||
"Unknown signal; kill -l lists signals",
|
||||
#define ERR_VARBEGIN 30
|
||||
"Variable name must begin with a letter",
|
||||
#define ERR_VARTOOLONG 31
|
||||
"Variable name too long",
|
||||
#define ERR_VARALNUM 32
|
||||
"Variable name must contain alphanumeric characters",
|
||||
#define ERR_JOBCONTROL 33
|
||||
"No job control in this shell",
|
||||
#define ERR_EXPRESSION 34
|
||||
"Expression Syntax",
|
||||
#define ERR_NOHOMEDIR 35
|
||||
"No home directory",
|
||||
#define ERR_CANTCHANGE 36
|
||||
"Can't change to home directory",
|
||||
#define ERR_NULLCOM 37
|
||||
"Invalid null command",
|
||||
#define ERR_ASSIGN 38
|
||||
"Assignment missing expression",
|
||||
#define ERR_UNKNOWNOP 39
|
||||
"Unknown operator",
|
||||
#define ERR_AMBIG 40
|
||||
"Ambiguous",
|
||||
#define ERR_EXISTS 41
|
||||
"%s: File exists",
|
||||
#define ERR_INTR 42
|
||||
"Interrupted",
|
||||
#define ERR_RANGE 43
|
||||
"Subscript out of range",
|
||||
#define ERR_OVERFLOW 44
|
||||
"Line overflow",
|
||||
#define ERR_VARMOD 45
|
||||
"Unknown variable modifier",
|
||||
#define ERR_NOSUCHJOB 46
|
||||
"No such job",
|
||||
#define ERR_TERMINAL 47
|
||||
"Can't from terminal",
|
||||
#define ERR_NOTWHILE 48
|
||||
"Not in while/foreach",
|
||||
#define ERR_NOPROC 49
|
||||
"No more processes",
|
||||
#define ERR_NOMATCH 50
|
||||
"No match",
|
||||
#define ERR_MISSING 51
|
||||
"Missing %c",
|
||||
#define ERR_UNMATCHED 52
|
||||
"Unmatched %c",
|
||||
#define ERR_NOMEM 53
|
||||
"Out of memory",
|
||||
#define ERR_PIPE 54
|
||||
"Can't make pipe",
|
||||
#define ERR_SYSTEM 55
|
||||
"%s: %s",
|
||||
#define ERR_STRING 56
|
||||
"%s",
|
||||
#define ERR_JOBS 57
|
||||
"Usage: jobs [ -l ]",
|
||||
#define ERR_JOBARGS 58
|
||||
"Arguments should be jobs or process id's",
|
||||
#define ERR_JOBCUR 59
|
||||
"No current job",
|
||||
#define ERR_JOBPREV 60
|
||||
"No previous job",
|
||||
#define ERR_JOBPAT 61
|
||||
"No job matches pattern",
|
||||
#define ERR_NESTING 62
|
||||
"Fork nesting > %d; maybe `...` loop",
|
||||
#define ERR_JOBCTRLSUB 63
|
||||
"No job control in subshells",
|
||||
#define ERR_BADPLPS 64
|
||||
"Badly placed ()'s",
|
||||
#define ERR_STOPPED 65
|
||||
"%sThere are suspended jobs",
|
||||
#define ERR_NODIR 66
|
||||
"No other directory",
|
||||
#define ERR_EMPTY 67
|
||||
"Directory stack empty",
|
||||
#define ERR_BADDIR 68
|
||||
"Bad directory",
|
||||
#define ERR_DIRUS 69
|
||||
"Usage: %s [-lvn]%s",
|
||||
#define ERR_HFLAG 70
|
||||
"No operand for -h flag",
|
||||
#define ERR_NOTLOGIN 71
|
||||
"Not a login shell",
|
||||
#define ERR_DIV0 72
|
||||
"Division by 0",
|
||||
#define ERR_MOD0 73
|
||||
"Mod by 0",
|
||||
#define ERR_BADSCALE 74
|
||||
"Bad scaling; did you mean \"%s\"?",
|
||||
#define ERR_SUSPLOG 75
|
||||
"Can't suspend a login shell (yet)",
|
||||
#define ERR_UNKUSER 76
|
||||
"Unknown user: %s",
|
||||
#define ERR_NOHOME 77
|
||||
"No $home variable set",
|
||||
#define ERR_HISTUS 78
|
||||
"Usage: history [-rh] [# number of events]",
|
||||
#define ERR_SPDOLLT 79
|
||||
"$, ! or < not allowed with $# or $?",
|
||||
#define ERR_NEWLINE 80
|
||||
"Newline in variable name",
|
||||
#define ERR_SPSTAR 81
|
||||
"* not allowed with $# or $?",
|
||||
#define ERR_DIGIT 82
|
||||
"$?<digit> or $#<digit> not allowed",
|
||||
#define ERR_VARILL 83
|
||||
"Illegal variable name",
|
||||
#define ERR_NLINDEX 84
|
||||
"Newline in variable index",
|
||||
#define ERR_EXPOVFL 85
|
||||
"Expansion buffer overflow",
|
||||
#define ERR_VARSYN 86
|
||||
"Variable syntax",
|
||||
#define ERR_BADBANG 87
|
||||
"Bad ! form",
|
||||
#define ERR_NOSUBST 88
|
||||
"No previous substitute",
|
||||
#define ERR_BADSUBST 89
|
||||
"Bad substitute",
|
||||
#define ERR_LHS 90
|
||||
"No previous left hand side",
|
||||
#define ERR_RHSLONG 91
|
||||
"Right hand side too long",
|
||||
#define ERR_BADBANGMOD 92
|
||||
"Bad ! modifier: %c",
|
||||
#define ERR_MODFAIL 93
|
||||
"Modifier failed",
|
||||
#define ERR_SUBOVFL 94
|
||||
"Substitution buffer overflow",
|
||||
#define ERR_BADBANGARG 95
|
||||
"Bad ! arg selector",
|
||||
#define ERR_NOSEARCH 96
|
||||
"No prev search",
|
||||
#define ERR_NOEVENT 97
|
||||
"%s: Event not found",
|
||||
#define ERR_TOOMANYRP 98
|
||||
"Too many )'s",
|
||||
#define ERR_TOOMANYLP 99
|
||||
"Too many ('s",
|
||||
#define ERR_BADPLP 100
|
||||
"Badly placed (",
|
||||
#define ERR_MISRED 101
|
||||
"Missing name for redirect",
|
||||
#define ERR_OUTRED 102
|
||||
"Ambiguous output redirect",
|
||||
#define ERR_REDPAR 103
|
||||
"Can't << within ()'s",
|
||||
#define ERR_INRED 104
|
||||
"Ambiguous input redirect",
|
||||
#define ERR_ALIASLOOP 105
|
||||
"Alias loop",
|
||||
#define ERR_HISTLOOP 106
|
||||
"!# History loop",
|
||||
#define ERR_ARCH 107
|
||||
"%s: %s. Wrong Architecture",
|
||||
#define ERR_FILEINQ 108
|
||||
"Malformed file inquiry",
|
||||
#define ERR_SELOVFL 109
|
||||
"Selector overflow",
|
||||
#define ERR_INVALID 110
|
||||
"Invalid Error"
|
||||
};
|
||||
|
||||
/*
|
||||
* The parser and scanner set up errors for later by calling seterr,
|
||||
* which sets the variable err as a side effect; later to be tested,
|
||||
* e.g. in process.
|
||||
*/
|
||||
void
|
||||
#if __STDC__
|
||||
seterror(int id, ...)
|
||||
#else
|
||||
seterror(id, va_alist)
|
||||
int id;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
if (seterr == 0) {
|
||||
char berr[BUFSIZ];
|
||||
va_list va;
|
||||
|
||||
#if __STDC__
|
||||
va_start(va, id);
|
||||
#else
|
||||
va_start(va);
|
||||
#endif
|
||||
if (id < 0 || id > sizeof(errorlist) / sizeof(errorlist[0]))
|
||||
id = ERR_INVALID;
|
||||
vsnprintf(berr, sizeof(berr), errorlist[id], va);
|
||||
va_end(va);
|
||||
|
||||
seterr = strsave(berr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the error with the given id.
|
||||
*
|
||||
* Special ids:
|
||||
* ERR_SILENT: Print nothing.
|
||||
* ERR_OLD: Print the previously set error if one was there.
|
||||
* otherwise return.
|
||||
* ERR_NAME: If this bit is set, print the name of the function
|
||||
* in bname
|
||||
*
|
||||
* This routine always resets or exits. The flag haderr
|
||||
* is set so the routine who catches the unwind can propagate
|
||||
* it if they want.
|
||||
*
|
||||
* Note that any open files at the point of error will eventually
|
||||
* be closed in the routine process in sh.c which is the only
|
||||
* place error unwinds are ever caught.
|
||||
*/
|
||||
void
|
||||
#if __STDC__
|
||||
stderror(int id, ...)
|
||||
#else
|
||||
stderror(id, va_alist)
|
||||
int id;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list va;
|
||||
Char **v;
|
||||
int flags = id & ERR_FLAGS;
|
||||
|
||||
id &= ~ERR_FLAGS;
|
||||
|
||||
if ((flags & ERR_OLD) && seterr == NULL)
|
||||
return;
|
||||
|
||||
if (id < 0 || id > sizeof(errorlist) / sizeof(errorlist[0]))
|
||||
id = ERR_INVALID;
|
||||
|
||||
(void) fflush(cshout);
|
||||
(void) fflush(csherr);
|
||||
haderr = 1; /* Now to diagnostic output */
|
||||
timflg = 0; /* This isn't otherwise reset */
|
||||
|
||||
|
||||
if (!(flags & ERR_SILENT)) {
|
||||
if (flags & ERR_NAME)
|
||||
(void) fprintf(csherr, "%s: ", bname);
|
||||
if ((flags & ERR_OLD))
|
||||
/* Old error. */
|
||||
(void) fprintf(csherr, "%s.\n", seterr);
|
||||
else {
|
||||
#if __STDC__
|
||||
va_start(va, id);
|
||||
#else
|
||||
va_start(va);
|
||||
#endif
|
||||
(void) vfprintf(csherr, errorlist[id], va);
|
||||
va_end(va);
|
||||
(void) fprintf(csherr, ".\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (seterr) {
|
||||
xfree((ptr_t) seterr);
|
||||
seterr = NULL;
|
||||
}
|
||||
|
||||
if ((v = pargv) != NULL)
|
||||
pargv = 0, blkfree(v);
|
||||
if ((v = gargv) != NULL)
|
||||
gargv = 0, blkfree(v);
|
||||
|
||||
(void) fflush(cshout);
|
||||
(void) fflush(csherr);
|
||||
didfds = 0; /* Forget about 0,1,2 */
|
||||
/*
|
||||
* Go away if -e or we are a child shell
|
||||
*/
|
||||
if (exiterr || child)
|
||||
xexit(1);
|
||||
|
||||
/*
|
||||
* Reset the state of the input. This buffered seek to end of file will
|
||||
* also clear the while/foreach stack.
|
||||
*/
|
||||
btoeof();
|
||||
|
||||
set(STRstatus, Strsave(STR1));
|
||||
if (tpgrp > 0)
|
||||
(void) tcsetpgrp(FSHTTY, tpgrp);
|
||||
reset(); /* Unwind */
|
||||
}
|
746
bin/csh/exec.c
746
bin/csh/exec.c
@ -1,746 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* System level search and execute of a command. We look in each directory
|
||||
* for the specified command name. If the name contains a '/' then we
|
||||
* execute only the full path name. If there is no search path then we
|
||||
* execute only full path names.
|
||||
*/
|
||||
extern char **environ;
|
||||
|
||||
/*
|
||||
* As we search for the command we note the first non-trivial error
|
||||
* message for presentation to the user. This allows us often
|
||||
* to show that a file has the wrong mode/no access when the file
|
||||
* is not in the last component of the search path, so we must
|
||||
* go on after first detecting the error.
|
||||
*/
|
||||
static char *exerr; /* Execution error message */
|
||||
static Char *expath; /* Path for exerr */
|
||||
|
||||
/*
|
||||
* Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
|
||||
* to hash execs. If it is allocated (havhash true), then to tell
|
||||
* whether ``name'' is (possibly) present in the i'th component
|
||||
* of the variable path, you look at the bit in xhash indexed by
|
||||
* hash(hashname("name"), i). This is setup automatically
|
||||
* after .login is executed, and recomputed whenever ``path'' is
|
||||
* changed.
|
||||
* The two part hash function is designed to let texec() call the
|
||||
* more expensive hashname() only once and the simple hash() several
|
||||
* times (once for each path component checked).
|
||||
* Byte size is assumed to be 8.
|
||||
*/
|
||||
#define HSHSIZ 8192 /* 1k bytes */
|
||||
#define HSHMASK (HSHSIZ - 1)
|
||||
#define HSHMUL 243
|
||||
static char xhash[HSHSIZ / 8];
|
||||
|
||||
#define hash(a, b) (((a) * HSHMUL + (b)) & HSHMASK)
|
||||
#define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
|
||||
#define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */
|
||||
static int hits, misses;
|
||||
|
||||
/* Dummy search path for just absolute search when no path */
|
||||
static Char *justabs[] = {STRNULL, 0};
|
||||
|
||||
static void pexerr __P((void));
|
||||
static void texec __P((Char *, Char **));
|
||||
static int hashname __P((Char *));
|
||||
static void tellmewhat __P((struct wordent *));
|
||||
static int executable __P((Char *, Char *, bool));
|
||||
static int iscommand __P((Char *));
|
||||
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
doexec(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
Char *dp, **pv, **av, *sav;
|
||||
struct varent *pathv;
|
||||
bool slash;
|
||||
int hashval = 0, hashval1, i;
|
||||
Char *blk[2];
|
||||
|
||||
/*
|
||||
* Glob the command name. We will search $path even if this does something,
|
||||
* as in sh but not in csh. One special case: if there is no PATH, then we
|
||||
* execute only commands which start with '/'.
|
||||
*/
|
||||
blk[0] = t->t_dcom[0];
|
||||
blk[1] = 0;
|
||||
gflag = 0, tglob(blk);
|
||||
if (gflag) {
|
||||
pv = globall(blk);
|
||||
if (pv == 0) {
|
||||
setname(vis_str(blk[0]));
|
||||
stderror(ERR_NAME | ERR_NOMATCH);
|
||||
}
|
||||
gargv = 0;
|
||||
}
|
||||
else
|
||||
pv = saveblk(blk);
|
||||
|
||||
trim(pv);
|
||||
|
||||
exerr = 0;
|
||||
expath = Strsave(pv[0]);
|
||||
Vexpath = expath;
|
||||
|
||||
pathv = adrof(STRpath);
|
||||
if (pathv == 0 && expath[0] != '/') {
|
||||
blkfree(pv);
|
||||
pexerr();
|
||||
}
|
||||
slash = any(short2str(expath), '/');
|
||||
|
||||
/*
|
||||
* Glob the argument list, if necessary. Otherwise trim off the quote bits.
|
||||
*/
|
||||
gflag = 0;
|
||||
av = &t->t_dcom[1];
|
||||
tglob(av);
|
||||
if (gflag) {
|
||||
av = globall(av);
|
||||
if (av == 0) {
|
||||
blkfree(pv);
|
||||
setname(vis_str(expath));
|
||||
stderror(ERR_NAME | ERR_NOMATCH);
|
||||
}
|
||||
gargv = 0;
|
||||
}
|
||||
else
|
||||
av = saveblk(av);
|
||||
|
||||
blkfree(t->t_dcom);
|
||||
t->t_dcom = blkspl(pv, av);
|
||||
xfree((ptr_t) pv);
|
||||
xfree((ptr_t) av);
|
||||
av = t->t_dcom;
|
||||
trim(av);
|
||||
|
||||
if (*av == NULL || **av == '\0')
|
||||
pexerr();
|
||||
|
||||
xechoit(av); /* Echo command if -x */
|
||||
/*
|
||||
* Since all internal file descriptors are set to close on exec, we don't
|
||||
* need to close them explicitly here. Just reorient ourselves for error
|
||||
* messages.
|
||||
*/
|
||||
SHIN = 0;
|
||||
SHOUT = 1;
|
||||
SHERR = 2;
|
||||
OLDSTD = 0;
|
||||
/*
|
||||
* We must do this AFTER any possible forking (like `foo` in glob) so that
|
||||
* this shell can still do subprocesses.
|
||||
*/
|
||||
(void) sigsetmask(0);
|
||||
/*
|
||||
* If no path, no words in path, or a / in the filename then restrict the
|
||||
* command search.
|
||||
*/
|
||||
if (pathv == 0 || pathv->vec[0] == 0 || slash)
|
||||
pv = justabs;
|
||||
else
|
||||
pv = pathv->vec;
|
||||
sav = Strspl(STRslash, *av);/* / command name for postpending */
|
||||
Vsav = sav;
|
||||
if (havhash)
|
||||
hashval = hashname(*av);
|
||||
i = 0;
|
||||
hits++;
|
||||
do {
|
||||
/*
|
||||
* Try to save time by looking at the hash table for where this command
|
||||
* could be. If we are doing delayed hashing, then we put the names in
|
||||
* one at a time, as the user enters them. This is kinda like Korn
|
||||
* Shell's "tracked aliases".
|
||||
*/
|
||||
if (!slash && pv[0][0] == '/' && havhash) {
|
||||
hashval1 = hash(hashval, i);
|
||||
if (!bit(xhash, hashval1))
|
||||
goto cont;
|
||||
}
|
||||
if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
|
||||
texec(*av, av);
|
||||
else {
|
||||
dp = Strspl(*pv, sav);
|
||||
Vdp = dp;
|
||||
texec(dp, av);
|
||||
Vdp = 0;
|
||||
xfree((ptr_t) dp);
|
||||
}
|
||||
misses++;
|
||||
cont:
|
||||
pv++;
|
||||
i++;
|
||||
} while (*pv);
|
||||
hits--;
|
||||
Vsav = 0;
|
||||
xfree((ptr_t) sav);
|
||||
pexerr();
|
||||
}
|
||||
|
||||
static void
|
||||
pexerr()
|
||||
{
|
||||
/* Couldn't find the damn thing */
|
||||
if (expath) {
|
||||
setname(vis_str(expath));
|
||||
Vexpath = 0;
|
||||
xfree((ptr_t) expath);
|
||||
expath = 0;
|
||||
}
|
||||
else
|
||||
setname("");
|
||||
if (exerr)
|
||||
stderror(ERR_NAME | ERR_STRING, exerr);
|
||||
stderror(ERR_NAME | ERR_COMMAND);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute command f, arg list t.
|
||||
* Record error message if not found.
|
||||
* Also do shell scripts here.
|
||||
*/
|
||||
static void
|
||||
texec(sf, st)
|
||||
Char *sf;
|
||||
Char **st;
|
||||
{
|
||||
char **t;
|
||||
char *f;
|
||||
struct varent *v;
|
||||
Char **vp;
|
||||
Char *lastsh[2];
|
||||
int fd;
|
||||
unsigned char c;
|
||||
Char *st0, **ost;
|
||||
|
||||
/* The order for the conversions is significant */
|
||||
t = short2blk(st);
|
||||
f = short2str(sf);
|
||||
Vt = t;
|
||||
errno = 0; /* don't use a previous error */
|
||||
(void) execve(f, t, environ);
|
||||
Vt = 0;
|
||||
blkfree((Char **) t);
|
||||
switch (errno) {
|
||||
|
||||
case ENOEXEC:
|
||||
/*
|
||||
* From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute
|
||||
* it, don't feed it to the shell if it looks like a binary!
|
||||
*/
|
||||
if ((fd = open(f, O_RDONLY)) != -1) {
|
||||
if (read(fd, (char *) &c, 1) == 1) {
|
||||
if (!Isprint(c) && (c != '\n' && c != '\t')) {
|
||||
(void) close(fd);
|
||||
/*
|
||||
* We *know* what ENOEXEC means.
|
||||
*/
|
||||
stderror(ERR_ARCH, f, strerror(errno));
|
||||
}
|
||||
}
|
||||
#ifdef _PATH_BSHELL
|
||||
else
|
||||
c = '#';
|
||||
#endif
|
||||
(void) close(fd);
|
||||
}
|
||||
/*
|
||||
* If there is an alias for shell, then put the words of the alias in
|
||||
* front of the argument list replacing the command name. Note no
|
||||
* interpretation of the words at this point.
|
||||
*/
|
||||
v = adrof1(STRshell, &aliases);
|
||||
if (v == 0) {
|
||||
vp = lastsh;
|
||||
vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH;
|
||||
vp[1] = NULL;
|
||||
#ifdef _PATH_BSHELL
|
||||
if (fd != -1 && c != '#')
|
||||
vp[0] = STR_BSHELL;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
vp = v->vec;
|
||||
st0 = st[0];
|
||||
st[0] = sf;
|
||||
ost = st;
|
||||
st = blkspl(vp, st); /* Splice up the new arglst */
|
||||
ost[0] = st0;
|
||||
sf = *st;
|
||||
/* The order for the conversions is significant */
|
||||
t = short2blk(st);
|
||||
f = short2str(sf);
|
||||
xfree((ptr_t) st);
|
||||
Vt = t;
|
||||
(void) execve(f, t, environ);
|
||||
Vt = 0;
|
||||
blkfree((Char **) t);
|
||||
/* The sky is falling, the sky is falling! */
|
||||
|
||||
case ENOMEM:
|
||||
stderror(ERR_SYSTEM, f, strerror(errno));
|
||||
|
||||
case ENOENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (exerr == 0) {
|
||||
exerr = strerror(errno);
|
||||
if (expath)
|
||||
xfree((ptr_t) expath);
|
||||
expath = Strsave(sf);
|
||||
Vexpath = expath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
execash(t, kp)
|
||||
Char **t;
|
||||
struct command *kp;
|
||||
{
|
||||
int saveIN, saveOUT, saveDIAG, saveSTD;
|
||||
int oSHIN;
|
||||
int oSHOUT;
|
||||
int oSHERR;
|
||||
int oOLDSTD;
|
||||
jmp_buf osetexit;
|
||||
int my_reenter;
|
||||
int odidfds;
|
||||
sig_t osigint, osigquit, osigterm;
|
||||
|
||||
if (chkstop == 0 && setintr)
|
||||
panystop(0);
|
||||
/*
|
||||
* Hmm, we don't really want to do that now because we might
|
||||
* fail, but what is the choice
|
||||
*/
|
||||
rechist();
|
||||
|
||||
osigint = signal(SIGINT, parintr);
|
||||
osigquit = signal(SIGQUIT, parintr);
|
||||
osigterm = signal(SIGTERM, parterm);
|
||||
|
||||
odidfds = didfds;
|
||||
oSHIN = SHIN;
|
||||
oSHOUT = SHOUT;
|
||||
oSHERR = SHERR;
|
||||
oOLDSTD = OLDSTD;
|
||||
|
||||
saveIN = dcopy(SHIN, -1);
|
||||
saveOUT = dcopy(SHOUT, -1);
|
||||
saveDIAG = dcopy(SHERR, -1);
|
||||
saveSTD = dcopy(OLDSTD, -1);
|
||||
|
||||
lshift(kp->t_dcom, 1);
|
||||
|
||||
getexit(osetexit);
|
||||
|
||||
if ((my_reenter = setexit()) == 0) {
|
||||
SHIN = dcopy(0, -1);
|
||||
SHOUT = dcopy(1, -1);
|
||||
SHERR = dcopy(2, -1);
|
||||
didfds = 0;
|
||||
doexec(t, kp);
|
||||
}
|
||||
|
||||
(void) signal(SIGINT, osigint);
|
||||
(void) signal(SIGQUIT, osigquit);
|
||||
(void) signal(SIGTERM, osigterm);
|
||||
|
||||
doneinp = 0;
|
||||
didfds = odidfds;
|
||||
(void) close(SHIN);
|
||||
(void) close(SHOUT);
|
||||
(void) close(SHERR);
|
||||
(void) close(OLDSTD);
|
||||
SHIN = dmove(saveIN, oSHIN);
|
||||
SHOUT = dmove(saveOUT, oSHOUT);
|
||||
SHERR = dmove(saveDIAG, oSHERR);
|
||||
OLDSTD = dmove(saveSTD, oOLDSTD);
|
||||
|
||||
resexit(osetexit);
|
||||
if (my_reenter)
|
||||
stderror(ERR_SILENT);
|
||||
}
|
||||
|
||||
void
|
||||
xechoit(t)
|
||||
Char **t;
|
||||
{
|
||||
if (adrof(STRecho)) {
|
||||
(void) fflush(csherr);
|
||||
blkpr(csherr, t);
|
||||
(void) fputc('\n', csherr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dohash(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
int cnt;
|
||||
int i = 0;
|
||||
struct varent *pathv = adrof(STRpath);
|
||||
Char **pv;
|
||||
int hashval;
|
||||
|
||||
havhash = 1;
|
||||
for (cnt = 0; cnt < sizeof xhash; cnt++)
|
||||
xhash[cnt] = 0;
|
||||
if (pathv == 0)
|
||||
return;
|
||||
for (pv = pathv->vec; *pv; pv++, i++) {
|
||||
if (pv[0][0] != '/')
|
||||
continue;
|
||||
dirp = opendir(short2str(*pv));
|
||||
if (dirp == NULL)
|
||||
continue;
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if (dp->d_ino == 0)
|
||||
continue;
|
||||
if (dp->d_name[0] == '.' &&
|
||||
(dp->d_name[1] == '\0' ||
|
||||
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
|
||||
continue;
|
||||
hashval = hash(hashname(str2short(dp->d_name)), i);
|
||||
bis(xhash, hashval);
|
||||
/* tw_add_comm_name (dp->d_name); */
|
||||
}
|
||||
(void) closedir(dirp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dounhash(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
havhash = 0;
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
hashstat(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
if (hits + misses)
|
||||
(void) fprintf(cshout, "%d hits, %d misses, %d%%\n",
|
||||
hits, misses, 100 * hits / (hits + misses));
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash a command name.
|
||||
*/
|
||||
static int
|
||||
hashname(cp)
|
||||
Char *cp;
|
||||
{
|
||||
long h = 0;
|
||||
|
||||
while (*cp)
|
||||
h = hash(h, *cp++);
|
||||
return ((int) h);
|
||||
}
|
||||
|
||||
static int
|
||||
iscommand(name)
|
||||
Char *name;
|
||||
{
|
||||
Char **pv;
|
||||
Char *sav;
|
||||
struct varent *v;
|
||||
bool slash = any(short2str(name), '/');
|
||||
int hashval = 0, hashval1, i;
|
||||
|
||||
v = adrof(STRpath);
|
||||
if (v == 0 || v->vec[0] == 0 || slash)
|
||||
pv = justabs;
|
||||
else
|
||||
pv = v->vec;
|
||||
sav = Strspl(STRslash, name); /* / command name for postpending */
|
||||
if (havhash)
|
||||
hashval = hashname(name);
|
||||
i = 0;
|
||||
do {
|
||||
if (!slash && pv[0][0] == '/' && havhash) {
|
||||
hashval1 = hash(hashval, i);
|
||||
if (!bit(xhash, hashval1))
|
||||
goto cont;
|
||||
}
|
||||
if (pv[0][0] == 0 || eq(pv[0], STRdot)) { /* don't make ./xxx */
|
||||
if (executable(NULL, name, 0)) {
|
||||
xfree((ptr_t) sav);
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (executable(*pv, sav, 0)) {
|
||||
xfree((ptr_t) sav);
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
cont:
|
||||
pv++;
|
||||
i++;
|
||||
} while (*pv);
|
||||
xfree((ptr_t) sav);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Also by:
|
||||
* Andreas Luik <luik@isaak.isa.de>
|
||||
* I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
|
||||
* Azenberstr. 35
|
||||
* D-7000 Stuttgart 1
|
||||
* West-Germany
|
||||
* is the executable() routine below and changes to iscommand().
|
||||
* Thanks again!!
|
||||
*/
|
||||
|
||||
/*
|
||||
* executable() examines the pathname obtained by concatenating dir and name
|
||||
* (dir may be NULL), and returns 1 either if it is executable by us, or
|
||||
* if dir_ok is set and the pathname refers to a directory.
|
||||
* This is a bit kludgy, but in the name of optimization...
|
||||
*/
|
||||
static int
|
||||
executable(dir, name, dir_ok)
|
||||
Char *dir, *name;
|
||||
bool dir_ok;
|
||||
{
|
||||
struct stat stbuf;
|
||||
Char path[MAXPATHLEN + 1], *dp, *sp;
|
||||
char *strname;
|
||||
|
||||
if (dir && *dir) {
|
||||
for (dp = path, sp = dir; *sp; *dp++ = *sp++)
|
||||
if (dp == &path[MAXPATHLEN + 1]) {
|
||||
*--dp = '\0';
|
||||
break;
|
||||
}
|
||||
for (sp = name; *sp; *dp++ = *sp++)
|
||||
if (dp == &path[MAXPATHLEN + 1]) {
|
||||
*--dp = '\0';
|
||||
break;
|
||||
}
|
||||
*dp = '\0';
|
||||
strname = short2str(path);
|
||||
}
|
||||
else
|
||||
strname = short2str(name);
|
||||
return (stat(strname, &stbuf) != -1 &&
|
||||
((S_ISREG(stbuf.st_mode) &&
|
||||
/* save time by not calling access() in the hopeless case */
|
||||
(stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
|
||||
access(strname, X_OK) == 0) ||
|
||||
(dir_ok && S_ISDIR(stbuf.st_mode))));
|
||||
}
|
||||
|
||||
/* The dowhich() is by:
|
||||
* Andreas Luik <luik@isaak.isa.de>
|
||||
* I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
|
||||
* Azenberstr. 35
|
||||
* D-7000 Stuttgart 1
|
||||
* West-Germany
|
||||
* Thanks!!
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
dowhich(v, c)
|
||||
Char **v;
|
||||
struct command *c;
|
||||
{
|
||||
struct wordent lex[3];
|
||||
struct varent *vp;
|
||||
|
||||
lex[0].next = &lex[1];
|
||||
lex[1].next = &lex[2];
|
||||
lex[2].next = &lex[0];
|
||||
|
||||
lex[0].prev = &lex[2];
|
||||
lex[1].prev = &lex[0];
|
||||
lex[2].prev = &lex[1];
|
||||
|
||||
lex[0].word = STRNULL;
|
||||
lex[2].word = STRret;
|
||||
|
||||
while (*++v) {
|
||||
if ((vp = adrof1(*v, &aliases)) != NULL) {
|
||||
(void) fprintf(cshout, "%s: \t aliased to ", vis_str(*v));
|
||||
blkpr(cshout, vp->vec);
|
||||
(void) fputc('\n', cshout);
|
||||
}
|
||||
else {
|
||||
lex[1].word = *v;
|
||||
tellmewhat(lex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tellmewhat(lex)
|
||||
struct wordent *lex;
|
||||
{
|
||||
int i;
|
||||
struct biltins *bptr;
|
||||
struct wordent *sp = lex->next;
|
||||
bool aliased = 0;
|
||||
Char *s0, *s1, *s2, *cmd;
|
||||
Char qc;
|
||||
|
||||
if (adrof1(sp->word, &aliases)) {
|
||||
alias(lex);
|
||||
sp = lex->next;
|
||||
aliased = 1;
|
||||
}
|
||||
|
||||
s0 = sp->word; /* to get the memory freeing right... */
|
||||
|
||||
/* handle quoted alias hack */
|
||||
if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
|
||||
(sp->word)++;
|
||||
|
||||
/* do quoting, if it hasn't been done */
|
||||
s1 = s2 = sp->word;
|
||||
while (*s2)
|
||||
switch (*s2) {
|
||||
case '\'':
|
||||
case '"':
|
||||
qc = *s2++;
|
||||
while (*s2 && *s2 != qc)
|
||||
*s1++ = *s2++ | QUOTE;
|
||||
if (*s2)
|
||||
s2++;
|
||||
break;
|
||||
case '\\':
|
||||
if (*++s2)
|
||||
*s1++ = *s2++ | QUOTE;
|
||||
break;
|
||||
default:
|
||||
*s1++ = *s2++;
|
||||
}
|
||||
*s1 = '\0';
|
||||
|
||||
for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
|
||||
if (eq(sp->word, str2short(bptr->bname))) {
|
||||
if (aliased)
|
||||
prlex(cshout, lex);
|
||||
(void) fprintf(cshout, "%s: shell built-in command.\n",
|
||||
vis_str(sp->word));
|
||||
sp->word = s0; /* we save and then restore this */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sp->word = cmd = globone(sp->word, G_IGNORE);
|
||||
|
||||
if ((i = iscommand(strip(sp->word))) != 0) {
|
||||
Char **pv;
|
||||
struct varent *v;
|
||||
bool slash = any(short2str(sp->word), '/');
|
||||
|
||||
v = adrof(STRpath);
|
||||
if (v == 0 || v->vec[0] == 0 || slash)
|
||||
pv = justabs;
|
||||
else
|
||||
pv = v->vec;
|
||||
|
||||
while (--i)
|
||||
pv++;
|
||||
if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
|
||||
if (!slash) {
|
||||
sp->word = Strspl(STRdotsl, sp->word);
|
||||
prlex(cshout, lex);
|
||||
xfree((ptr_t) sp->word);
|
||||
} else
|
||||
prlex(cshout, lex);
|
||||
sp->word = s0; /* we save and then restore this */
|
||||
xfree((ptr_t) cmd);
|
||||
return;
|
||||
}
|
||||
s1 = Strspl(*pv, STRslash);
|
||||
sp->word = Strspl(s1, sp->word);
|
||||
xfree((ptr_t) s1);
|
||||
prlex(cshout, lex);
|
||||
xfree((ptr_t) sp->word);
|
||||
}
|
||||
else {
|
||||
if (aliased)
|
||||
prlex(cshout, lex);
|
||||
(void) fprintf(csherr, "%s: Command not found.\n", vis_str(sp->word));
|
||||
}
|
||||
xfree((ptr_t) cmd);
|
||||
sp->word = s0; /* we save and then restore this */
|
||||
}
|
712
bin/csh/exp.c
712
bin/csh/exp.c
@ -1,712 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define IGNORE 1 /* in ignore, it means to ignore value, just parse */
|
||||
#define NOGLOB 2 /* in ignore, it means not to globone */
|
||||
|
||||
#define ADDOP 1
|
||||
#define MULOP 2
|
||||
#define EQOP 4
|
||||
#define RELOP 8
|
||||
#define RESTOP 16
|
||||
#define ANYOP 31
|
||||
|
||||
#define EQEQ 1
|
||||
#define GTR 2
|
||||
#define LSS 4
|
||||
#define NOTEQ 6
|
||||
#define EQMATCH 7
|
||||
#define NOTEQMATCH 8
|
||||
|
||||
static int exp1 __P((Char ***, bool));
|
||||
static int exp2 __P((Char ***, bool));
|
||||
static int exp2a __P((Char ***, bool));
|
||||
static int exp2b __P((Char ***, bool));
|
||||
static int exp2c __P((Char ***, bool));
|
||||
static Char * exp3 __P((Char ***, bool));
|
||||
static Char * exp3a __P((Char ***, bool));
|
||||
static Char * exp4 __P((Char ***, bool));
|
||||
static Char * exp5 __P((Char ***, bool));
|
||||
static Char * exp6 __P((Char ***, bool));
|
||||
static void evalav __P((Char **));
|
||||
static int isa __P((Char *, int));
|
||||
static int egetn __P((Char *));
|
||||
|
||||
#ifdef EDEBUG
|
||||
static void etracc __P((char *, Char *, Char ***));
|
||||
static void etraci __P((char *, int, Char ***));
|
||||
#endif
|
||||
|
||||
int
|
||||
expr(vp)
|
||||
Char ***vp;
|
||||
{
|
||||
return (exp0(vp, 0));
|
||||
}
|
||||
|
||||
int
|
||||
exp0(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int p1 = exp1(vp, ignore);
|
||||
|
||||
#ifdef EDEBUG
|
||||
etraci("exp0 p1", p1, vp);
|
||||
#endif
|
||||
if (**vp && eq(**vp, STRor2)) {
|
||||
int p2;
|
||||
|
||||
(*vp)++;
|
||||
p2 = exp0(vp, (ignore & IGNORE) || p1);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp0 p2", p2, vp);
|
||||
#endif
|
||||
return (p1 || p2);
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static int
|
||||
exp1(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int p1 = exp2(vp, ignore);
|
||||
|
||||
#ifdef EDEBUG
|
||||
etraci("exp1 p1", p1, vp);
|
||||
#endif
|
||||
if (**vp && eq(**vp, STRand2)) {
|
||||
int p2;
|
||||
|
||||
(*vp)++;
|
||||
p2 = exp1(vp, (ignore & IGNORE) || !p1);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp1 p2", p2, vp);
|
||||
#endif
|
||||
return (p1 && p2);
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static int
|
||||
exp2(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int p1 = exp2a(vp, ignore);
|
||||
|
||||
#ifdef EDEBUG
|
||||
etraci("exp3 p1", p1, vp);
|
||||
#endif
|
||||
if (**vp && eq(**vp, STRor)) {
|
||||
int p2;
|
||||
|
||||
(*vp)++;
|
||||
p2 = exp2(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp3 p2", p2, vp);
|
||||
#endif
|
||||
return (p1 | p2);
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static int
|
||||
exp2a(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int p1 = exp2b(vp, ignore);
|
||||
|
||||
#ifdef EDEBUG
|
||||
etraci("exp2a p1", p1, vp);
|
||||
#endif
|
||||
if (**vp && eq(**vp, STRcaret)) {
|
||||
int p2;
|
||||
|
||||
(*vp)++;
|
||||
p2 = exp2a(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp2a p2", p2, vp);
|
||||
#endif
|
||||
return (p1 ^ p2);
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static int
|
||||
exp2b(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int p1 = exp2c(vp, ignore);
|
||||
|
||||
#ifdef EDEBUG
|
||||
etraci("exp2b p1", p1, vp);
|
||||
#endif
|
||||
if (**vp && eq(**vp, STRand)) {
|
||||
int p2;
|
||||
|
||||
(*vp)++;
|
||||
p2 = exp2b(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp2b p2", p2, vp);
|
||||
#endif
|
||||
return (p1 & p2);
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static int
|
||||
exp2c(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
Char *p1 = exp3(vp, ignore);
|
||||
Char *p2;
|
||||
int i;
|
||||
|
||||
#ifdef EDEBUG
|
||||
etracc("exp2c p1", p1, vp);
|
||||
#endif
|
||||
if ((i = isa(**vp, EQOP)) != 0) {
|
||||
(*vp)++;
|
||||
if (i == EQMATCH || i == NOTEQMATCH)
|
||||
ignore |= NOGLOB;
|
||||
p2 = exp3(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp2c p2", p2, vp);
|
||||
#endif
|
||||
if (!(ignore & IGNORE))
|
||||
switch (i) {
|
||||
|
||||
case EQEQ:
|
||||
i = eq(p1, p2);
|
||||
break;
|
||||
|
||||
case NOTEQ:
|
||||
i = !eq(p1, p2);
|
||||
break;
|
||||
|
||||
case EQMATCH:
|
||||
i = Gmatch(p1, p2);
|
||||
break;
|
||||
|
||||
case NOTEQMATCH:
|
||||
i = !Gmatch(p1, p2);
|
||||
break;
|
||||
}
|
||||
xfree((ptr_t) p1);
|
||||
xfree((ptr_t) p2);
|
||||
return (i);
|
||||
}
|
||||
i = egetn(p1);
|
||||
xfree((ptr_t) p1);
|
||||
return (i);
|
||||
}
|
||||
|
||||
static Char *
|
||||
exp3(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
Char *p1, *p2;
|
||||
int i;
|
||||
|
||||
p1 = exp3a(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp3 p1", p1, vp);
|
||||
#endif
|
||||
if ((i = isa(**vp, RELOP)) != 0) {
|
||||
(*vp)++;
|
||||
if (**vp && eq(**vp, STRequal))
|
||||
i |= 1, (*vp)++;
|
||||
p2 = exp3(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp3 p2", p2, vp);
|
||||
#endif
|
||||
if (!(ignore & IGNORE))
|
||||
switch (i) {
|
||||
|
||||
case GTR:
|
||||
i = egetn(p1) > egetn(p2);
|
||||
break;
|
||||
|
||||
case GTR | 1:
|
||||
i = egetn(p1) >= egetn(p2);
|
||||
break;
|
||||
|
||||
case LSS:
|
||||
i = egetn(p1) < egetn(p2);
|
||||
break;
|
||||
|
||||
case LSS | 1:
|
||||
i = egetn(p1) <= egetn(p2);
|
||||
break;
|
||||
}
|
||||
xfree((ptr_t) p1);
|
||||
xfree((ptr_t) p2);
|
||||
return (putn(i));
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static Char *
|
||||
exp3a(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
Char *p1, *p2, *op;
|
||||
int i;
|
||||
|
||||
p1 = exp4(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp3a p1", p1, vp);
|
||||
#endif
|
||||
op = **vp;
|
||||
if (op && any("<>", op[0]) && op[0] == op[1]) {
|
||||
(*vp)++;
|
||||
p2 = exp3a(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp3a p2", p2, vp);
|
||||
#endif
|
||||
if (op[0] == '<')
|
||||
i = egetn(p1) << egetn(p2);
|
||||
else
|
||||
i = egetn(p1) >> egetn(p2);
|
||||
xfree((ptr_t) p1);
|
||||
xfree((ptr_t) p2);
|
||||
return (putn(i));
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static Char *
|
||||
exp4(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
Char *p1, *p2;
|
||||
int i = 0;
|
||||
|
||||
p1 = exp5(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp4 p1", p1, vp);
|
||||
#endif
|
||||
if (isa(**vp, ADDOP)) {
|
||||
Char *op = *(*vp)++;
|
||||
|
||||
p2 = exp4(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp4 p2", p2, vp);
|
||||
#endif
|
||||
if (!(ignore & IGNORE))
|
||||
switch (op[0]) {
|
||||
|
||||
case '+':
|
||||
i = egetn(p1) + egetn(p2);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
i = egetn(p1) - egetn(p2);
|
||||
break;
|
||||
}
|
||||
xfree((ptr_t) p1);
|
||||
xfree((ptr_t) p2);
|
||||
return (putn(i));
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static Char *
|
||||
exp5(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
Char *p1, *p2;
|
||||
int i = 0;
|
||||
|
||||
p1 = exp6(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp5 p1", p1, vp);
|
||||
#endif
|
||||
if (isa(**vp, MULOP)) {
|
||||
Char *op = *(*vp)++;
|
||||
|
||||
p2 = exp5(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp5 p2", p2, vp);
|
||||
#endif
|
||||
if (!(ignore & IGNORE))
|
||||
switch (op[0]) {
|
||||
|
||||
case '*':
|
||||
i = egetn(p1) * egetn(p2);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
i = egetn(p2);
|
||||
if (i == 0)
|
||||
stderror(ERR_DIV0);
|
||||
i = egetn(p1) / i;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
i = egetn(p2);
|
||||
if (i == 0)
|
||||
stderror(ERR_MOD0);
|
||||
i = egetn(p1) % i;
|
||||
break;
|
||||
}
|
||||
xfree((ptr_t) p1);
|
||||
xfree((ptr_t) p2);
|
||||
return (putn(i));
|
||||
}
|
||||
return (p1);
|
||||
}
|
||||
|
||||
static Char *
|
||||
exp6(vp, ignore)
|
||||
Char ***vp;
|
||||
bool ignore;
|
||||
{
|
||||
int ccode, i = 0;
|
||||
Char *cp, *dp, *ep;
|
||||
|
||||
if (**vp == 0)
|
||||
stderror(ERR_NAME | ERR_EXPRESSION);
|
||||
if (eq(**vp, STRbang)) {
|
||||
(*vp)++;
|
||||
cp = exp6(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp6 ! cp", cp, vp);
|
||||
#endif
|
||||
i = egetn(cp);
|
||||
xfree((ptr_t) cp);
|
||||
return (putn(!i));
|
||||
}
|
||||
if (eq(**vp, STRtilde)) {
|
||||
(*vp)++;
|
||||
cp = exp6(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etracc("exp6 ~ cp", cp, vp);
|
||||
#endif
|
||||
i = egetn(cp);
|
||||
xfree((ptr_t) cp);
|
||||
return (putn(~i));
|
||||
}
|
||||
if (eq(**vp, STRLparen)) {
|
||||
(*vp)++;
|
||||
ccode = exp0(vp, ignore);
|
||||
#ifdef EDEBUG
|
||||
etraci("exp6 () ccode", ccode, vp);
|
||||
#endif
|
||||
if (*vp == 0 || **vp == 0 || ***vp != ')')
|
||||
stderror(ERR_NAME | ERR_EXPRESSION);
|
||||
(*vp)++;
|
||||
return (putn(ccode));
|
||||
}
|
||||
if (eq(**vp, STRLbrace)) {
|
||||
Char **v;
|
||||
struct command faket;
|
||||
Char *fakecom[2];
|
||||
|
||||
faket.t_dtyp = NODE_COMMAND;
|
||||
faket.t_dflg = 0;
|
||||
faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
|
||||
faket.t_dcom = fakecom;
|
||||
fakecom[0] = STRfakecom;
|
||||
fakecom[1] = NULL;
|
||||
(*vp)++;
|
||||
v = *vp;
|
||||
for (;;) {
|
||||
if (!**vp)
|
||||
stderror(ERR_NAME | ERR_MISSING, '}');
|
||||
if (eq(*(*vp)++, STRRbrace))
|
||||
break;
|
||||
}
|
||||
if (ignore & IGNORE)
|
||||
return (Strsave(STRNULL));
|
||||
psavejob();
|
||||
if (pfork(&faket, -1) == 0) {
|
||||
*--(*vp) = 0;
|
||||
evalav(v);
|
||||
exitstat();
|
||||
}
|
||||
pwait();
|
||||
prestjob();
|
||||
#ifdef EDEBUG
|
||||
etraci("exp6 {} status", egetn(value(STRstatus)), vp);
|
||||
#endif
|
||||
return (putn(egetn(value(STRstatus)) == 0));
|
||||
}
|
||||
if (isa(**vp, ANYOP))
|
||||
return (Strsave(STRNULL));
|
||||
cp = *(*vp)++;
|
||||
if (*cp == '-' && any("erwxfdzopls", cp[1])) {
|
||||
struct stat stb;
|
||||
|
||||
if (cp[2] != '\0')
|
||||
stderror(ERR_NAME | ERR_FILEINQ);
|
||||
/*
|
||||
* Detect missing file names by checking for operator in the file name
|
||||
* position. However, if an operator name appears there, we must make
|
||||
* sure that there's no file by that name (e.g., "/") before announcing
|
||||
* an error. Even this check isn't quite right, since it doesn't take
|
||||
* globbing into account.
|
||||
*/
|
||||
if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
|
||||
stderror(ERR_NAME | ERR_FILENAME);
|
||||
|
||||
dp = *(*vp)++;
|
||||
if (ignore & IGNORE)
|
||||
return (Strsave(STRNULL));
|
||||
ep = globone(dp, G_ERROR);
|
||||
switch (cp[1]) {
|
||||
|
||||
case 'r':
|
||||
i = !access(short2str(ep), R_OK);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
i = !access(short2str(ep), W_OK);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
i = !access(short2str(ep), X_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (
|
||||
#ifdef S_IFLNK
|
||||
cp[1] == 'l' ? lstat(short2str(ep), &stb) :
|
||||
#endif
|
||||
stat(short2str(ep), &stb)) {
|
||||
xfree((ptr_t) ep);
|
||||
return (Strsave(STR0));
|
||||
}
|
||||
switch (cp[1]) {
|
||||
|
||||
case 'f':
|
||||
i = S_ISREG(stb.st_mode);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
i = S_ISDIR(stb.st_mode);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
#ifdef S_ISFIFO
|
||||
i = S_ISFIFO(stb.st_mode);
|
||||
#else
|
||||
i = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
#ifdef S_ISLNK
|
||||
i = S_ISLNK(stb.st_mode);
|
||||
#else
|
||||
i = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 's':
|
||||
#ifdef S_ISSOCK
|
||||
i = S_ISSOCK(stb.st_mode);
|
||||
#else
|
||||
i = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
i = stb.st_size == 0;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
i = 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
i = stb.st_uid == uid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef EDEBUG
|
||||
etraci("exp6 -? i", i, vp);
|
||||
#endif
|
||||
xfree((ptr_t) ep);
|
||||
return (putn(i));
|
||||
}
|
||||
#ifdef EDEBUG
|
||||
etracc("exp6 default", cp, vp);
|
||||
#endif
|
||||
return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
|
||||
}
|
||||
|
||||
static void
|
||||
evalav(v)
|
||||
Char **v;
|
||||
{
|
||||
struct wordent paraml1;
|
||||
struct wordent *hp = ¶ml1;
|
||||
struct command *t;
|
||||
struct wordent *wdp = hp;
|
||||
|
||||
set(STRstatus, Strsave(STR0));
|
||||
hp->prev = hp->next = hp;
|
||||
hp->word = STRNULL;
|
||||
while (*v) {
|
||||
struct wordent *new =
|
||||
(struct wordent *) xcalloc(1, sizeof *wdp);
|
||||
|
||||
new->prev = wdp;
|
||||
new->next = hp;
|
||||
wdp->next = new;
|
||||
wdp = new;
|
||||
wdp->word = Strsave(*v++);
|
||||
}
|
||||
hp->prev = wdp;
|
||||
alias(¶ml1);
|
||||
t = syntax(paraml1.next, ¶ml1, 0);
|
||||
if (seterr)
|
||||
stderror(ERR_OLD);
|
||||
execute(t, -1, NULL, NULL);
|
||||
freelex(¶ml1), freesyn(t);
|
||||
}
|
||||
|
||||
static int
|
||||
isa(cp, what)
|
||||
Char *cp;
|
||||
int what;
|
||||
{
|
||||
if (cp == 0)
|
||||
return ((what & RESTOP) != 0);
|
||||
if (cp[1] == 0) {
|
||||
if (what & ADDOP && (*cp == '+' || *cp == '-'))
|
||||
return (1);
|
||||
if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
|
||||
return (1);
|
||||
if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
|
||||
*cp == '~' || *cp == '^' || *cp == '"'))
|
||||
return (1);
|
||||
}
|
||||
else if (cp[2] == 0) {
|
||||
if (what & RESTOP) {
|
||||
if (cp[0] == '|' && cp[1] == '&')
|
||||
return (1);
|
||||
if (cp[0] == '<' && cp[1] == '<')
|
||||
return (1);
|
||||
if (cp[0] == '>' && cp[1] == '>')
|
||||
return (1);
|
||||
}
|
||||
if (what & EQOP) {
|
||||
if (cp[0] == '=') {
|
||||
if (cp[1] == '=')
|
||||
return (EQEQ);
|
||||
if (cp[1] == '~')
|
||||
return (EQMATCH);
|
||||
}
|
||||
else if (cp[0] == '!') {
|
||||
if (cp[1] == '=')
|
||||
return (NOTEQ);
|
||||
if (cp[1] == '~')
|
||||
return (NOTEQMATCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (what & RELOP) {
|
||||
if (*cp == '<')
|
||||
return (LSS);
|
||||
if (*cp == '>')
|
||||
return (GTR);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
egetn(cp)
|
||||
Char *cp;
|
||||
{
|
||||
if (*cp && *cp != '-' && !Isdigit(*cp))
|
||||
stderror(ERR_NAME | ERR_EXPRESSION);
|
||||
return (getn(cp));
|
||||
}
|
||||
|
||||
/* Phew! */
|
||||
|
||||
#ifdef EDEBUG
|
||||
static void
|
||||
etraci(str, i, vp)
|
||||
char *str;
|
||||
int i;
|
||||
Char ***vp;
|
||||
{
|
||||
(void) fprintf(csherr, "%s=%d\t", str, i);
|
||||
blkpr(csherr, *vp);
|
||||
(void) fprintf(csherr, "\n");
|
||||
}
|
||||
static void
|
||||
etracc(str, cp, vp)
|
||||
char *str;
|
||||
Char *cp;
|
||||
Char ***vp;
|
||||
{
|
||||
(void) fprintf(csherr, "%s=%s\t", str, vis_str(cp));
|
||||
blkpr(csherr, *vp);
|
||||
(void) fprintf(csherr, "\n");
|
||||
}
|
||||
#endif
|
339
bin/csh/extern.h
339
bin/csh/extern.h
@ -1,339 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* csh.c
|
||||
*/
|
||||
int gethdir __P((Char *));
|
||||
void dosource __P((Char **, struct command *));
|
||||
void exitstat __P((void));
|
||||
void goodbye __P((void));
|
||||
void importpath __P((Char *));
|
||||
void initdesc __P((void));
|
||||
void pintr __P((int));
|
||||
void pintr1 __P((bool));
|
||||
void printprompt __P((void));
|
||||
void process __P((bool));
|
||||
void rechist __P((void));
|
||||
void untty __P((void));
|
||||
int vis_fputc __P((int, FILE *));
|
||||
|
||||
#ifdef PROF
|
||||
void done __P((int));
|
||||
#else
|
||||
void xexit __P((int));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dir.c
|
||||
*/
|
||||
void dinit __P((Char *));
|
||||
void dodirs __P((Char **, struct command *));
|
||||
Char *dcanon __P((Char *, Char *));
|
||||
void dtildepr __P((Char *, Char *));
|
||||
void dtilde __P((void));
|
||||
void dochngd __P((Char **, struct command *));
|
||||
Char *dnormalize __P((Char *));
|
||||
void dopushd __P((Char **, struct command *));
|
||||
void dopopd __P((Char **, struct command *));
|
||||
struct directory;
|
||||
void dfree __P((struct directory *));
|
||||
|
||||
/*
|
||||
* dol.c
|
||||
*/
|
||||
void Dfix __P((struct command *));
|
||||
Char *Dfix1 __P((Char *));
|
||||
void heredoc __P((Char *));
|
||||
|
||||
/*
|
||||
* err.c
|
||||
*/
|
||||
void seterror __P((int, ...));
|
||||
void stderror __P((int, ...));
|
||||
|
||||
/*
|
||||
* exec.c
|
||||
*/
|
||||
void doexec __P((Char **, struct command *));
|
||||
void dohash __P((Char **, struct command *));
|
||||
void dounhash __P((Char **, struct command *));
|
||||
void dowhich __P((Char **, struct command *));
|
||||
void execash __P((Char **, struct command *));
|
||||
void hashstat __P((Char **, struct command *));
|
||||
void xechoit __P((Char **));
|
||||
|
||||
/*
|
||||
* exp.c
|
||||
*/
|
||||
int expr __P((Char ***));
|
||||
int exp0 __P((Char ***, bool));
|
||||
|
||||
/*
|
||||
* file.c
|
||||
*/
|
||||
#ifdef FILEC
|
||||
int tenex __P((Char *, int));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* func.c
|
||||
*/
|
||||
void Setenv __P((Char *, Char *));
|
||||
void doalias __P((Char **, struct command *));
|
||||
void dobreak __P((Char **, struct command *));
|
||||
void docontin __P((Char **, struct command *));
|
||||
void doecho __P((Char **, struct command *));
|
||||
void doelse __P((Char **, struct command *));
|
||||
void doend __P((Char **, struct command *));
|
||||
void doeval __P((Char **, struct command *));
|
||||
void doexit __P((Char **, struct command *));
|
||||
void doforeach __P((Char **, struct command *));
|
||||
void doglob __P((Char **, struct command *));
|
||||
void dogoto __P((Char **, struct command *));
|
||||
void doif __P((Char **, struct command *));
|
||||
void dolimit __P((Char **, struct command *));
|
||||
void dologin __P((Char **, struct command *));
|
||||
void dologout __P((Char **, struct command *));
|
||||
void donohup __P((Char **, struct command *));
|
||||
void doonintr __P((Char **, struct command *));
|
||||
void doprintf __P((Char **, struct command *));
|
||||
void dorepeat __P((Char **, struct command *));
|
||||
void dosetenv __P((Char **, struct command *));
|
||||
void dosuspend __P((Char **, struct command *));
|
||||
void doswbrk __P((Char **, struct command *));
|
||||
void doswitch __P((Char **, struct command *));
|
||||
void doumask __P((Char **, struct command *));
|
||||
void dounlimit __P((Char **, struct command *));
|
||||
void dounsetenv __P((Char **, struct command *));
|
||||
void dowhile __P((Char **, struct command *));
|
||||
void dozip __P((Char **, struct command *));
|
||||
void func __P((struct command *, struct biltins *));
|
||||
struct biltins *
|
||||
isbfunc __P((struct command *));
|
||||
void prvars __P((void));
|
||||
void gotolab __P((Char *));
|
||||
int srchx __P((Char *));
|
||||
void unalias __P((Char **, struct command *));
|
||||
void wfree __P((void));
|
||||
|
||||
/*
|
||||
* glob.c
|
||||
*/
|
||||
Char **dobackp __P((Char *, bool));
|
||||
void Gcat __P((Char *, Char *));
|
||||
Char *globone __P((Char *, int));
|
||||
int Gmatch __P((Char *, Char *));
|
||||
void ginit __P((void));
|
||||
Char **globall __P((Char **));
|
||||
void rscan __P((Char **, void (*)(int)));
|
||||
void tglob __P((Char **));
|
||||
void trim __P((Char **));
|
||||
#ifdef FILEC
|
||||
int sortscmp __P((const ptr_t, const ptr_t));
|
||||
#endif /* FILEC */
|
||||
|
||||
/*
|
||||
* hist.c
|
||||
*/
|
||||
void dohist __P((Char **, struct command *));
|
||||
struct Hist *
|
||||
enthist __P((int, struct wordent *, bool));
|
||||
void savehist __P((struct wordent *));
|
||||
|
||||
/*
|
||||
* lex.c
|
||||
*/
|
||||
void addla __P((Char *));
|
||||
void bseek __P((struct Ain *));
|
||||
void btell __P((struct Ain *));
|
||||
void btoeof __P((void));
|
||||
void copylex __P((struct wordent *, struct wordent *));
|
||||
Char *domod __P((Char *, int));
|
||||
void freelex __P((struct wordent *));
|
||||
int lex __P((struct wordent *));
|
||||
void prlex __P((FILE *, struct wordent *));
|
||||
int readc __P((bool));
|
||||
void settell __P((void));
|
||||
void unreadc __P((int));
|
||||
|
||||
/*
|
||||
* misc.c
|
||||
*/
|
||||
int any __P((char *, int));
|
||||
Char **blkcat __P((Char **, Char **));
|
||||
Char **blkcpy __P((Char **, Char **));
|
||||
Char **blkend __P((Char **));
|
||||
void blkfree __P((Char **));
|
||||
int blklen __P((Char **));
|
||||
void blkpr __P((FILE *, Char **));
|
||||
Char **blkspl __P((Char **, Char **));
|
||||
void closem __P((void));
|
||||
Char **copyblk __P((Char **));
|
||||
int dcopy __P((int, int));
|
||||
int dmove __P((int, int));
|
||||
void donefds __P((void));
|
||||
Char lastchr __P((Char *));
|
||||
void lshift __P((Char **, int));
|
||||
int number __P((Char *));
|
||||
int prefix __P((Char *, Char *));
|
||||
Char **saveblk __P((Char **));
|
||||
void setzero __P((char *, int));
|
||||
Char *strip __P((Char *));
|
||||
char *strsave __P((char *));
|
||||
char *strspl __P((char *, char *));
|
||||
void udvar __P((Char *));
|
||||
|
||||
#ifndef SHORT_STRINGS
|
||||
# ifdef NOTUSED
|
||||
char *strstr __P((const char *, const char *));
|
||||
# endif /* NOTUSED */
|
||||
char *strend __P((char *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* parse.c
|
||||
*/
|
||||
void alias __P((struct wordent *));
|
||||
void freesyn __P((struct command *));
|
||||
struct command *
|
||||
syntax __P((struct wordent *, struct wordent *, int));
|
||||
|
||||
|
||||
/*
|
||||
* proc.c
|
||||
*/
|
||||
void dobg __P((Char **, struct command *));
|
||||
void dobg1 __P((Char **, struct command *));
|
||||
void dofg __P((Char **, struct command *));
|
||||
void dofg1 __P((Char **, struct command *));
|
||||
void dojobs __P((Char **, struct command *));
|
||||
void dokill __P((Char **, struct command *));
|
||||
void donotify __P((Char **, struct command *));
|
||||
void dostop __P((Char **, struct command *));
|
||||
void dowait __P((Char **, struct command *));
|
||||
void palloc __P((int, struct command *));
|
||||
void panystop __P((bool));
|
||||
void pchild __P((int));
|
||||
void pendjob __P((void));
|
||||
struct process *
|
||||
pfind __P((Char *));
|
||||
int pfork __P((struct command *, int));
|
||||
void pgetty __P((int, int));
|
||||
void pjwait __P((struct process *));
|
||||
void pnote __P((void));
|
||||
void prestjob __P((void));
|
||||
void psavejob __P((void));
|
||||
void pstart __P((struct process *, int));
|
||||
void pwait __P((void));
|
||||
|
||||
/*
|
||||
* sem.c
|
||||
*/
|
||||
void execute __P((struct command *, int, int *, int *));
|
||||
void mypipe __P((int *));
|
||||
|
||||
/*
|
||||
* set.c
|
||||
*/
|
||||
struct varent
|
||||
*adrof1 __P((Char *, struct varent *));
|
||||
void doset __P((Char **, struct command *));
|
||||
void dolet __P((Char **, struct command *));
|
||||
Char *putn __P((int));
|
||||
int getn __P((Char *));
|
||||
Char *value1 __P((Char *, struct varent *));
|
||||
void set __P((Char *, Char *));
|
||||
void set1 __P((Char *, Char **, struct varent *));
|
||||
void setq __P((Char *, Char **, struct varent *));
|
||||
void unset __P((Char **, struct command *));
|
||||
void unset1 __P((Char *[], struct varent *));
|
||||
void unsetv __P((Char *));
|
||||
void setNS __P((Char *));
|
||||
void shift __P((Char **, struct command *));
|
||||
void plist __P((struct varent *));
|
||||
|
||||
/*
|
||||
* time.c
|
||||
*/
|
||||
void donice __P((Char **, struct command *));
|
||||
void dotime __P((Char **, struct command *));
|
||||
void prusage __P((struct rusage *, struct rusage *,
|
||||
struct timeval *, struct timeval *));
|
||||
void ruadd __P((struct rusage *, struct rusage *));
|
||||
void settimes __P((void));
|
||||
void tvadd __P((struct timeval *, struct timeval *));
|
||||
void tvsub __P((struct timeval *, struct timeval *, struct timeval *));
|
||||
void pcsecs __P((long));
|
||||
void psecs __P((long));
|
||||
|
||||
/*
|
||||
* alloc.c
|
||||
*/
|
||||
void Free __P((ptr_t));
|
||||
ptr_t Malloc __P((size_t));
|
||||
ptr_t Realloc __P((ptr_t, size_t));
|
||||
ptr_t Calloc __P((size_t, size_t));
|
||||
void showall __P((Char **, struct command *));
|
||||
|
||||
/*
|
||||
* str.c:
|
||||
*/
|
||||
#ifdef SHORT_STRINGS
|
||||
Char *s_strchr __P((Char *, int));
|
||||
Char *s_strrchr __P((Char *, int));
|
||||
Char *s_strcat __P((Char *, Char *));
|
||||
#ifdef NOTUSED
|
||||
Char *s_strncat __P((Char *, Char *, size_t));
|
||||
#endif
|
||||
Char *s_strcpy __P((Char *, Char *));
|
||||
Char *s_strncpy __P((Char *, Char *, size_t));
|
||||
Char *s_strspl __P((Char *, Char *));
|
||||
size_t s_strlen __P((Char *));
|
||||
int s_strcmp __P((Char *, Char *));
|
||||
int s_strncmp __P((Char *, Char *, size_t));
|
||||
Char *s_strsave __P((Char *));
|
||||
Char *s_strend __P((Char *));
|
||||
Char *s_strstr __P((Char *, Char *));
|
||||
Char *str2short __P((char *));
|
||||
Char **blk2short __P((char **));
|
||||
char *short2str __P((Char *));
|
||||
char **short2blk __P((Char **));
|
||||
#endif
|
||||
char *short2qstr __P((Char *));
|
||||
char *vis_str __P((Char *));
|
685
bin/csh/file.c
685
bin/csh/file.c
@ -1,685 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)file.c 8.2 (Berkeley) 3/19/94";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef FILEC
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* Tenex style file name recognition, .. and more.
|
||||
* History:
|
||||
* Author: Ken Greer, Sept. 1975, CMU.
|
||||
* Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
|
||||
*/
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define ESC '\033'
|
||||
|
||||
typedef enum {
|
||||
LIST, RECOGNIZE
|
||||
} COMMAND;
|
||||
|
||||
static void setup_tty __P((int));
|
||||
static void back_to_col_1 __P((void));
|
||||
static void pushback __P((Char *));
|
||||
static void catn __P((Char *, Char *, int));
|
||||
static void copyn __P((Char *, Char *, int));
|
||||
static Char filetype __P((Char *, Char *));
|
||||
static void print_by_column __P((Char *, Char *[], int));
|
||||
static Char *tilde __P((Char *, Char *));
|
||||
static void retype __P((void));
|
||||
static void beep __P((void));
|
||||
static void print_recognized_stuff __P((Char *));
|
||||
static void extract_dir_and_name __P((Char *, Char *, Char *));
|
||||
static Char *getentry __P((DIR *, int));
|
||||
static void free_items __P((Char **));
|
||||
static int tsearch __P((Char *, COMMAND, int));
|
||||
static int recognize __P((Char *, Char *, int, int));
|
||||
static int is_prefix __P((Char *, Char *));
|
||||
static int is_suffix __P((Char *, Char *));
|
||||
static int ignored __P((Char *));
|
||||
|
||||
/*
|
||||
* Put this here so the binary can be patched with adb to enable file
|
||||
* completion by default. Filec controls completion, nobeep controls
|
||||
* ringing the terminal bell on incomplete expansions.
|
||||
*/
|
||||
bool filec = 0;
|
||||
|
||||
static void
|
||||
setup_tty(on)
|
||||
int on;
|
||||
{
|
||||
struct termios tchars;
|
||||
|
||||
(void) tcgetattr(SHIN, &tchars);
|
||||
|
||||
if (on) {
|
||||
tchars.c_cc[VEOL] = ESC;
|
||||
if (tchars.c_lflag & ICANON)
|
||||
on = TCSADRAIN;
|
||||
else {
|
||||
on = TCSAFLUSH;
|
||||
tchars.c_lflag |= ICANON;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tchars.c_cc[VEOL] = _POSIX_VDISABLE;
|
||||
on = TCSADRAIN;
|
||||
}
|
||||
|
||||
(void) tcsetattr(SHIN, on, &tchars);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move back to beginning of current line
|
||||
*/
|
||||
static void
|
||||
back_to_col_1()
|
||||
{
|
||||
struct termios tty, tty_normal;
|
||||
int omask;
|
||||
|
||||
omask = sigblock(sigmask(SIGINT));
|
||||
(void) tcgetattr(SHOUT, &tty);
|
||||
tty_normal = tty;
|
||||
tty.c_iflag &= ~INLCR;
|
||||
tty.c_oflag &= ~ONLCR;
|
||||
(void) tcsetattr(SHOUT, TCSANOW, &tty);
|
||||
(void) write(SHOUT, "\r", 1);
|
||||
(void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push string contents back into tty queue
|
||||
*/
|
||||
static void
|
||||
pushback(string)
|
||||
Char *string;
|
||||
{
|
||||
Char *p;
|
||||
struct termios tty, tty_normal;
|
||||
int omask;
|
||||
char c;
|
||||
|
||||
omask = sigblock(sigmask(SIGINT));
|
||||
(void) tcgetattr(SHOUT, &tty);
|
||||
tty_normal = tty;
|
||||
tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL);
|
||||
(void) tcsetattr(SHOUT, TCSANOW, &tty);
|
||||
|
||||
for (p = string; (c = *p) != '\0'; p++)
|
||||
(void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c);
|
||||
(void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenate src onto tail of des.
|
||||
* Des is a string whose maximum length is count.
|
||||
* Always null terminate.
|
||||
*/
|
||||
static void
|
||||
catn(des, src, count)
|
||||
Char *des, *src;
|
||||
int count;
|
||||
{
|
||||
while (--count >= 0 && *des)
|
||||
des++;
|
||||
while (--count >= 0)
|
||||
if ((*des++ = *src++) == 0)
|
||||
return;
|
||||
*des = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Like strncpy but always leave room for trailing \0
|
||||
* and always null terminate.
|
||||
*/
|
||||
static void
|
||||
copyn(des, src, count)
|
||||
Char *des, *src;
|
||||
int count;
|
||||
{
|
||||
while (--count >= 0)
|
||||
if ((*des++ = *src++) == 0)
|
||||
return;
|
||||
*des = '\0';
|
||||
}
|
||||
|
||||
static Char
|
||||
filetype(dir, file)
|
||||
Char *dir, *file;
|
||||
{
|
||||
Char path[MAXPATHLEN];
|
||||
struct stat statb;
|
||||
|
||||
catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char));
|
||||
if (lstat(short2str(path), &statb) == 0) {
|
||||
switch (statb.st_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
return ('/');
|
||||
|
||||
case S_IFLNK:
|
||||
if (stat(short2str(path), &statb) == 0 && /* follow it out */
|
||||
S_ISDIR(statb.st_mode))
|
||||
return ('>');
|
||||
else
|
||||
return ('@');
|
||||
|
||||
case S_IFSOCK:
|
||||
return ('=');
|
||||
|
||||
default:
|
||||
if (statb.st_mode & 0111)
|
||||
return ('*');
|
||||
}
|
||||
}
|
||||
return (' ');
|
||||
}
|
||||
|
||||
static struct winsize win;
|
||||
|
||||
/*
|
||||
* Print sorted down columns
|
||||
*/
|
||||
static void
|
||||
print_by_column(dir, items, count)
|
||||
Char *dir, *items[];
|
||||
int count;
|
||||
{
|
||||
int i, rows, r, c, maxwidth = 0, columns;
|
||||
|
||||
if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0)
|
||||
win.ws_col = 80;
|
||||
for (i = 0; i < count; i++)
|
||||
maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r;
|
||||
maxwidth += 2; /* for the file tag and space */
|
||||
columns = win.ws_col / maxwidth;
|
||||
if (columns == 0)
|
||||
columns = 1;
|
||||
rows = (count + (columns - 1)) / columns;
|
||||
for (r = 0; r < rows; r++) {
|
||||
for (c = 0; c < columns; c++) {
|
||||
i = c * rows + r;
|
||||
if (i < count) {
|
||||
int w;
|
||||
|
||||
(void) fprintf(cshout, "%s", vis_str(items[i]));
|
||||
(void) fputc(dir ? filetype(dir, items[i]) : ' ', cshout);
|
||||
if (c < columns - 1) { /* last column? */
|
||||
w = Strlen(items[i]) + 1;
|
||||
for (; w < maxwidth; w++)
|
||||
(void) fputc(' ', cshout);
|
||||
}
|
||||
}
|
||||
}
|
||||
(void) fputc('\r', cshout);
|
||||
(void) fputc('\n', cshout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand file name with possible tilde usage
|
||||
* ~person/mumble
|
||||
* expands to
|
||||
* home_directory_of_person/mumble
|
||||
*/
|
||||
static Char *
|
||||
tilde(new, old)
|
||||
Char *new, *old;
|
||||
{
|
||||
Char *o, *p;
|
||||
struct passwd *pw;
|
||||
static Char person[40];
|
||||
|
||||
if (old[0] != '~')
|
||||
return (Strcpy(new, old));
|
||||
|
||||
for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++)
|
||||
continue;
|
||||
*p = '\0';
|
||||
if (person[0] == '\0')
|
||||
(void) Strcpy(new, value(STRhome));
|
||||
else {
|
||||
pw = getpwnam(short2str(person));
|
||||
if (pw == NULL)
|
||||
return (NULL);
|
||||
(void) Strcpy(new, str2short(pw->pw_dir));
|
||||
}
|
||||
(void) Strcat(new, o);
|
||||
return (new);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cause pending line to be printed
|
||||
*/
|
||||
static void
|
||||
retype()
|
||||
{
|
||||
struct termios tty;
|
||||
|
||||
(void) tcgetattr(SHOUT, &tty);
|
||||
tty.c_lflag |= PENDIN;
|
||||
(void) tcsetattr(SHOUT, TCSANOW, &tty);
|
||||
}
|
||||
|
||||
static void
|
||||
beep()
|
||||
{
|
||||
if (adrof(STRnobeep) == 0)
|
||||
(void) write(SHOUT, "\007", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Erase that silly ^[ and
|
||||
* print the recognized part of the string
|
||||
*/
|
||||
static void
|
||||
print_recognized_stuff(recognized_part)
|
||||
Char *recognized_part;
|
||||
{
|
||||
/* An optimized erasing of that silly ^[ */
|
||||
(void) fputc('\b', cshout);
|
||||
(void) fputc('\b', cshout);
|
||||
switch (Strlen(recognized_part)) {
|
||||
|
||||
case 0: /* erase two Characters: ^[ */
|
||||
(void) fputc(' ', cshout);
|
||||
(void) fputc(' ', cshout);
|
||||
(void) fputc('\b', cshout);
|
||||
(void) fputc('\b', cshout);
|
||||
break;
|
||||
|
||||
case 1: /* overstrike the ^, erase the [ */
|
||||
(void) fprintf(cshout, "%s", vis_str(recognized_part));
|
||||
(void) fputc(' ', cshout);
|
||||
(void) fputc('\b', cshout);
|
||||
break;
|
||||
|
||||
default: /* overstrike both Characters ^[ */
|
||||
(void) fprintf(cshout, "%s", vis_str(recognized_part));
|
||||
break;
|
||||
}
|
||||
(void) fflush(cshout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse full path in file into 2 parts: directory and file names
|
||||
* Should leave final slash (/) at end of dir.
|
||||
*/
|
||||
static void
|
||||
extract_dir_and_name(path, dir, name)
|
||||
Char *path, *dir, *name;
|
||||
{
|
||||
Char *p;
|
||||
|
||||
p = Strrchr(path, '/');
|
||||
if (p == NULL) {
|
||||
copyn(name, path, MAXNAMLEN);
|
||||
dir[0] = '\0';
|
||||
}
|
||||
else {
|
||||
copyn(name, ++p, MAXNAMLEN);
|
||||
copyn(dir, path, p - path);
|
||||
}
|
||||
}
|
||||
|
||||
static Char *
|
||||
getentry(dir_fd, looking_for_lognames)
|
||||
DIR *dir_fd;
|
||||
int looking_for_lognames;
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct dirent *dirp;
|
||||
|
||||
if (looking_for_lognames) {
|
||||
if ((pw = getpwent()) == NULL)
|
||||
return (NULL);
|
||||
return (str2short(pw->pw_name));
|
||||
}
|
||||
if ((dirp = readdir(dir_fd)) != NULL)
|
||||
return (str2short(dirp->d_name));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
free_items(items)
|
||||
Char **items;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; items[i]; i++)
|
||||
xfree((ptr_t) items[i]);
|
||||
xfree((ptr_t) items);
|
||||
}
|
||||
|
||||
#define FREE_ITEMS(items) { \
|
||||
int omask;\
|
||||
\
|
||||
omask = sigblock(sigmask(SIGINT));\
|
||||
free_items(items);\
|
||||
items = NULL;\
|
||||
(void) sigsetmask(omask);\
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a RECOGNIZE or LIST command on string "word".
|
||||
*/
|
||||
static int
|
||||
tsearch(word, command, max_word_length)
|
||||
Char *word;
|
||||
COMMAND command;
|
||||
int max_word_length;
|
||||
{
|
||||
static Char **items = NULL;
|
||||
DIR *dir_fd;
|
||||
int numitems = 0, ignoring = TRUE, nignored = 0;
|
||||
int name_length, looking_for_lognames;
|
||||
Char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1];
|
||||
Char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1];
|
||||
Char *entry;
|
||||
|
||||
#define MAXITEMS 1024
|
||||
|
||||
if (items != NULL)
|
||||
FREE_ITEMS(items);
|
||||
|
||||
looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL);
|
||||
if (looking_for_lognames) {
|
||||
setpwent();
|
||||
copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */
|
||||
dir_fd = NULL;
|
||||
}
|
||||
else {
|
||||
extract_dir_and_name(word, dir, name);
|
||||
if (tilde(tilded_dir, dir) == 0)
|
||||
return (0);
|
||||
dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : ".");
|
||||
if (dir_fd == NULL)
|
||||
return (0);
|
||||
}
|
||||
|
||||
again: /* search for matches */
|
||||
name_length = Strlen(name);
|
||||
for (numitems = 0; (entry = getentry(dir_fd, looking_for_lognames)) != NULL;) {
|
||||
if (!is_prefix(name, entry))
|
||||
continue;
|
||||
/* Don't match . files on null prefix match */
|
||||
if (name_length == 0 && entry[0] == '.' &&
|
||||
!looking_for_lognames)
|
||||
continue;
|
||||
if (command == LIST) {
|
||||
if (numitems >= MAXITEMS) {
|
||||
(void) fprintf(csherr, "\nYikes!! Too many %s!!\n",
|
||||
looking_for_lognames ?
|
||||
"names in password file" : "files");
|
||||
break;
|
||||
}
|
||||
if (items == NULL)
|
||||
items = (Char **) xcalloc(sizeof(items[0]), MAXITEMS);
|
||||
items[numitems] = (Char *) xmalloc((size_t) (Strlen(entry) + 1) *
|
||||
sizeof(Char));
|
||||
copyn(items[numitems], entry, MAXNAMLEN);
|
||||
numitems++;
|
||||
}
|
||||
else { /* RECOGNIZE command */
|
||||
if (ignoring && ignored(entry))
|
||||
nignored++;
|
||||
else if (recognize(extended_name,
|
||||
entry, name_length, ++numitems))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignoring && numitems == 0 && nignored > 0) {
|
||||
ignoring = FALSE;
|
||||
nignored = 0;
|
||||
if (looking_for_lognames)
|
||||
setpwent();
|
||||
else
|
||||
rewinddir(dir_fd);
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (looking_for_lognames)
|
||||
(void) endpwent();
|
||||
else
|
||||
(void) closedir(dir_fd);
|
||||
if (numitems == 0)
|
||||
return (0);
|
||||
if (command == RECOGNIZE) {
|
||||
if (looking_for_lognames)
|
||||
copyn(word, STRtilde, 1);
|
||||
else
|
||||
/* put back dir part */
|
||||
copyn(word, dir, max_word_length);
|
||||
/* add extended name */
|
||||
catn(word, extended_name, max_word_length);
|
||||
return (numitems);
|
||||
}
|
||||
else { /* LIST */
|
||||
qsort((ptr_t) items, numitems, sizeof(items[0]),
|
||||
(int (*) __P((const void *, const void *))) sortscmp);
|
||||
print_by_column(looking_for_lognames ? NULL : tilded_dir,
|
||||
items, numitems);
|
||||
if (items != NULL)
|
||||
FREE_ITEMS(items);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Object: extend what user typed up to an ambiguity.
|
||||
* Algorithm:
|
||||
* On first match, copy full entry (assume it'll be the only match)
|
||||
* On subsequent matches, shorten extended_name to the first
|
||||
* Character mismatch between extended_name and entry.
|
||||
* If we shorten it back to the prefix length, stop searching.
|
||||
*/
|
||||
static int
|
||||
recognize(extended_name, entry, name_length, numitems)
|
||||
Char *extended_name, *entry;
|
||||
int name_length, numitems;
|
||||
{
|
||||
if (numitems == 1) /* 1st match */
|
||||
copyn(extended_name, entry, MAXNAMLEN);
|
||||
else { /* 2nd & subsequent matches */
|
||||
Char *x, *ent;
|
||||
int len = 0;
|
||||
|
||||
x = extended_name;
|
||||
for (ent = entry; *x && *x == *ent++; x++, len++)
|
||||
continue;
|
||||
*x = '\0'; /* Shorten at 1st Char diff */
|
||||
if (len == name_length) /* Ambiguous to prefix? */
|
||||
return (-1); /* So stop now and save time */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if check matches initial Chars in template.
|
||||
* This differs from PWB imatch in that if check is null
|
||||
* it matches anything.
|
||||
*/
|
||||
static int
|
||||
is_prefix(check, template)
|
||||
Char *check, *template;
|
||||
{
|
||||
do
|
||||
if (*check == 0)
|
||||
return (TRUE);
|
||||
while (*check++ == *template++);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the Chars in template appear at the
|
||||
* end of check, I.e., are it's suffix.
|
||||
*/
|
||||
static int
|
||||
is_suffix(check, template)
|
||||
Char *check, *template;
|
||||
{
|
||||
Char *c, *t;
|
||||
|
||||
for (c = check; *c++;)
|
||||
continue;
|
||||
for (t = template; *t++;)
|
||||
continue;
|
||||
for (;;) {
|
||||
if (t == template)
|
||||
return 1;
|
||||
if (c == check || *--t != *--c)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tenex(inputline, inputline_size)
|
||||
Char *inputline;
|
||||
int inputline_size;
|
||||
{
|
||||
int numitems, num_read;
|
||||
char tinputline[BUFSIZ];
|
||||
|
||||
|
||||
setup_tty(ON);
|
||||
|
||||
while ((num_read = read(SHIN, tinputline, BUFSIZ)) > 0) {
|
||||
int i;
|
||||
static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<',
|
||||
'>', '(', ')', '|', '^', '%', '\0'};
|
||||
Char *str_end, *word_start, last_Char, should_retype;
|
||||
int space_left;
|
||||
COMMAND command;
|
||||
|
||||
for (i = 0; i < num_read; i++)
|
||||
inputline[i] = (unsigned char) tinputline[i];
|
||||
last_Char = inputline[num_read - 1] & ASCII;
|
||||
|
||||
if (last_Char == '\n' || num_read == inputline_size)
|
||||
break;
|
||||
command = (last_Char == ESC) ? RECOGNIZE : LIST;
|
||||
if (command == LIST)
|
||||
(void) fputc('\n', cshout);
|
||||
str_end = &inputline[num_read];
|
||||
if (last_Char == ESC)
|
||||
--str_end; /* wipeout trailing cmd Char */
|
||||
*str_end = '\0';
|
||||
/*
|
||||
* Find LAST occurence of a delimiter in the inputline. The word start
|
||||
* is one Character past it.
|
||||
*/
|
||||
for (word_start = str_end; word_start > inputline; --word_start)
|
||||
if (Strchr(delims, word_start[-1]))
|
||||
break;
|
||||
space_left = inputline_size - (word_start - inputline) - 1;
|
||||
numitems = tsearch(word_start, command, space_left);
|
||||
|
||||
if (command == RECOGNIZE) {
|
||||
/* print from str_end on */
|
||||
print_recognized_stuff(str_end);
|
||||
if (numitems != 1) /* Beep = No match/ambiguous */
|
||||
beep();
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs in the input line cause trouble after a pushback. tty driver
|
||||
* won't backspace over them because column positions are now
|
||||
* incorrect. This is solved by retyping over current line.
|
||||
*/
|
||||
should_retype = FALSE;
|
||||
if (Strchr(inputline, '\t')) { /* tab Char in input line? */
|
||||
back_to_col_1();
|
||||
should_retype = TRUE;
|
||||
}
|
||||
if (command == LIST) /* Always retype after a LIST */
|
||||
should_retype = TRUE;
|
||||
if (should_retype)
|
||||
printprompt();
|
||||
pushback(inputline);
|
||||
if (should_retype)
|
||||
retype();
|
||||
}
|
||||
setup_tty(OFF);
|
||||
return (num_read);
|
||||
}
|
||||
|
||||
static int
|
||||
ignored(entry)
|
||||
Char *entry;
|
||||
{
|
||||
struct varent *vp;
|
||||
Char **cp;
|
||||
|
||||
if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
|
||||
return (FALSE);
|
||||
for (; *cp != NULL; cp++)
|
||||
if (is_suffix(entry, *cp))
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif /* FILEC */
|
1520
bin/csh/func.c
1520
bin/csh/func.c
File diff suppressed because it is too large
Load Diff
961
bin/csh/glob.c
961
bin/csh/glob.c
@ -1,961 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)glob.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <glob.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int noglob;
|
||||
static int pargsiz, gargsiz;
|
||||
|
||||
/*
|
||||
* Values for gflag
|
||||
*/
|
||||
#define G_NONE 0 /* No globbing needed */
|
||||
#define G_GLOB 1 /* string contains *?[] characters */
|
||||
#define G_CSH 2 /* string contains ~`{ characters */
|
||||
|
||||
#define GLOBSPACE 100 /* Alloc increment */
|
||||
|
||||
#define LBRC '{'
|
||||
#define RBRC '}'
|
||||
#define LBRK '['
|
||||
#define RBRK ']'
|
||||
#define EOS '\0'
|
||||
|
||||
Char **gargv = NULL;
|
||||
long gargc = 0;
|
||||
Char **pargv = NULL;
|
||||
long pargc = 0;
|
||||
|
||||
/*
|
||||
* globbing is now done in two stages. In the first pass we expand
|
||||
* csh globbing idioms ~`{ and then we proceed doing the normal
|
||||
* globbing if needed ?*[
|
||||
*
|
||||
* Csh type globbing is handled in globexpand() and the rest is
|
||||
* handled in glob() which is part of the 4.4BSD libc.
|
||||
*
|
||||
*/
|
||||
static Char *globtilde __P((Char **, Char *));
|
||||
static Char **libglob __P((Char **));
|
||||
static Char **globexpand __P((Char **));
|
||||
static int globbrace __P((Char *, Char *, Char ***));
|
||||
static void expbrace __P((Char ***, Char ***, int));
|
||||
static int pmatch __P((Char *, Char *));
|
||||
static void pword __P((void));
|
||||
static void psave __P((int));
|
||||
static void backeval __P((Char *, bool));
|
||||
static int collate_range_cmp __P((int, int));
|
||||
|
||||
static int collate_range_cmp (c1, c2)
|
||||
int c1, c2;
|
||||
{
|
||||
static char s1[2], s2[2];
|
||||
int ret;
|
||||
|
||||
c1 &= UCHAR_MAX;
|
||||
c2 &= UCHAR_MAX;
|
||||
if (c1 == c2)
|
||||
return (0);
|
||||
s1[0] = c1;
|
||||
s2[0] = c2;
|
||||
if ((ret = strcoll(s1, s2)) != 0)
|
||||
return (ret);
|
||||
return (c1 - c2);
|
||||
}
|
||||
|
||||
static Char *
|
||||
globtilde(nv, s)
|
||||
Char **nv, *s;
|
||||
{
|
||||
Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
|
||||
|
||||
gstart = gbuf;
|
||||
*gstart++ = *s++;
|
||||
u = s;
|
||||
for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
|
||||
*s && *s != '/' && *s != ':' && b < e;
|
||||
*b++ = *s++)
|
||||
continue;
|
||||
*b = EOS;
|
||||
if (gethdir(gstart)) {
|
||||
blkfree(nv);
|
||||
if (*gstart)
|
||||
stderror(ERR_UNKUSER, vis_str(gstart));
|
||||
else
|
||||
stderror(ERR_NOHOME);
|
||||
}
|
||||
b = &gstart[Strlen(gstart)];
|
||||
while (*s)
|
||||
*b++ = *s++;
|
||||
*b = EOS;
|
||||
--u;
|
||||
xfree((ptr_t) u);
|
||||
return (Strsave(gstart));
|
||||
}
|
||||
|
||||
static int
|
||||
globbrace(s, p, bl)
|
||||
Char *s, *p, ***bl;
|
||||
{
|
||||
int i, len;
|
||||
Char *pm, *pe, *lm, *pl;
|
||||
Char **nv, **vl;
|
||||
Char gbuf[MAXPATHLEN];
|
||||
int size = GLOBSPACE;
|
||||
|
||||
nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
|
||||
*vl = NULL;
|
||||
|
||||
len = 0;
|
||||
/* copy part up to the brace */
|
||||
for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
|
||||
continue;
|
||||
|
||||
/* check for balanced braces */
|
||||
for (i = 0, pe = ++p; *pe; pe++)
|
||||
if (*pe == LBRK) {
|
||||
/* Ignore everything between [] */
|
||||
for (++pe; *pe != RBRK && *pe != EOS; pe++)
|
||||
continue;
|
||||
if (*pe == EOS) {
|
||||
blkfree(nv);
|
||||
return (-RBRK);
|
||||
}
|
||||
}
|
||||
else if (*pe == LBRC)
|
||||
i++;
|
||||
else if (*pe == RBRC) {
|
||||
if (i == 0)
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
|
||||
if (i != 0 || *pe == '\0') {
|
||||
blkfree(nv);
|
||||
return (-RBRC);
|
||||
}
|
||||
|
||||
for (i = 0, pl = pm = p; pm <= pe; pm++)
|
||||
switch (*pm) {
|
||||
case LBRK:
|
||||
for (++pm; *pm != RBRK && *pm != EOS; pm++)
|
||||
continue;
|
||||
if (*pm == EOS) {
|
||||
*vl = NULL;
|
||||
blkfree(nv);
|
||||
return (-RBRK);
|
||||
}
|
||||
break;
|
||||
case LBRC:
|
||||
i++;
|
||||
break;
|
||||
case RBRC:
|
||||
if (i) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case ',':
|
||||
if (i && *pm == ',')
|
||||
break;
|
||||
else {
|
||||
Char savec = *pm;
|
||||
|
||||
*pm = EOS;
|
||||
(void) Strcpy(lm, pl);
|
||||
(void) Strcat(gbuf, pe + 1);
|
||||
*pm = savec;
|
||||
*vl++ = Strsave(gbuf);
|
||||
len++;
|
||||
pl = pm + 1;
|
||||
if (vl == &nv[size]) {
|
||||
size += GLOBSPACE;
|
||||
nv = (Char **) xrealloc((ptr_t) nv, (size_t)
|
||||
size * sizeof(Char *));
|
||||
vl = &nv[size - GLOBSPACE];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*vl = NULL;
|
||||
*bl = nv;
|
||||
return (len);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
expbrace(nvp, elp, size)
|
||||
Char ***nvp, ***elp;
|
||||
int size;
|
||||
{
|
||||
Char **vl, **el, **nv, *s;
|
||||
|
||||
vl = nv = *nvp;
|
||||
if (elp != NULL)
|
||||
el = *elp;
|
||||
else
|
||||
for (el = vl; *el; el++)
|
||||
continue;
|
||||
|
||||
for (s = *vl; s; s = *++vl) {
|
||||
Char *b;
|
||||
Char **vp, **bp;
|
||||
|
||||
/* leave {} untouched for find */
|
||||
if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
|
||||
continue;
|
||||
if ((b = Strchr(s, '{')) != NULL) {
|
||||
Char **bl;
|
||||
int len;
|
||||
|
||||
if ((len = globbrace(s, b, &bl)) < 0) {
|
||||
xfree((ptr_t) nv);
|
||||
stderror(ERR_MISSING, -len);
|
||||
}
|
||||
xfree((ptr_t) s);
|
||||
if (len == 1) {
|
||||
*vl-- = *bl;
|
||||
xfree((ptr_t) bl);
|
||||
continue;
|
||||
}
|
||||
len = blklen(bl);
|
||||
if (&el[len] >= &nv[size]) {
|
||||
int l, e;
|
||||
|
||||
l = &el[len] - &nv[size];
|
||||
size += GLOBSPACE > l ? GLOBSPACE : l;
|
||||
l = vl - nv;
|
||||
e = el - nv;
|
||||
nv = (Char **) xrealloc((ptr_t) nv, (size_t)
|
||||
size * sizeof(Char *));
|
||||
vl = nv + l;
|
||||
el = nv + e;
|
||||
}
|
||||
vp = vl--;
|
||||
*vp = *bl;
|
||||
len--;
|
||||
for (bp = el; bp != vp; bp--)
|
||||
bp[len] = *bp;
|
||||
el += len;
|
||||
vp++;
|
||||
for (bp = bl + 1; *bp; *vp++ = *bp++)
|
||||
continue;
|
||||
xfree((ptr_t) bl);
|
||||
}
|
||||
|
||||
}
|
||||
if (elp != NULL)
|
||||
*elp = el;
|
||||
*nvp = nv;
|
||||
}
|
||||
|
||||
static Char **
|
||||
globexpand(v)
|
||||
Char **v;
|
||||
{
|
||||
Char *s;
|
||||
Char **nv, **vl, **el;
|
||||
int size = GLOBSPACE;
|
||||
|
||||
|
||||
nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
|
||||
*vl = NULL;
|
||||
|
||||
/*
|
||||
* Step 1: expand backquotes.
|
||||
*/
|
||||
while ((s = *v++) != NULL) {
|
||||
if (Strchr(s, '`')) {
|
||||
int i;
|
||||
|
||||
(void) dobackp(s, 0);
|
||||
for (i = 0; i < pargc; i++) {
|
||||
*vl++ = pargv[i];
|
||||
if (vl == &nv[size]) {
|
||||
size += GLOBSPACE;
|
||||
nv = (Char **) xrealloc((ptr_t) nv,
|
||||
(size_t) size * sizeof(Char *));
|
||||
vl = &nv[size - GLOBSPACE];
|
||||
}
|
||||
}
|
||||
xfree((ptr_t) pargv);
|
||||
pargv = NULL;
|
||||
}
|
||||
else {
|
||||
*vl++ = Strsave(s);
|
||||
if (vl == &nv[size]) {
|
||||
size += GLOBSPACE;
|
||||
nv = (Char **) xrealloc((ptr_t) nv, (size_t)
|
||||
size * sizeof(Char *));
|
||||
vl = &nv[size - GLOBSPACE];
|
||||
}
|
||||
}
|
||||
}
|
||||
*vl = NULL;
|
||||
|
||||
if (noglob)
|
||||
return (nv);
|
||||
|
||||
/*
|
||||
* Step 2: expand braces
|
||||
*/
|
||||
el = vl;
|
||||
expbrace(&nv, &el, size);
|
||||
|
||||
/*
|
||||
* Step 3: expand ~
|
||||
*/
|
||||
vl = nv;
|
||||
for (s = *vl; s; s = *++vl)
|
||||
if (*s == '~')
|
||||
*vl = globtilde(nv, s);
|
||||
vl = nv;
|
||||
return (vl);
|
||||
}
|
||||
|
||||
static Char *
|
||||
handleone(str, vl, action)
|
||||
Char *str, **vl;
|
||||
int action;
|
||||
{
|
||||
|
||||
Char *cp, **vlp = vl;
|
||||
|
||||
switch (action) {
|
||||
case G_ERROR:
|
||||
setname(vis_str(str));
|
||||
blkfree(vl);
|
||||
stderror(ERR_NAME | ERR_AMBIG);
|
||||
break;
|
||||
case G_APPEND:
|
||||
trim(vlp);
|
||||
str = Strsave(*vlp++);
|
||||
do {
|
||||
cp = Strspl(str, STRspace);
|
||||
xfree((ptr_t) str);
|
||||
str = Strspl(cp, *vlp);
|
||||
xfree((ptr_t) cp);
|
||||
}
|
||||
while (*++vlp);
|
||||
blkfree(vl);
|
||||
break;
|
||||
case G_IGNORE:
|
||||
str = Strsave(strip(*vlp));
|
||||
blkfree(vl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (str);
|
||||
}
|
||||
|
||||
static Char **
|
||||
libglob(vl)
|
||||
Char **vl;
|
||||
{
|
||||
int gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
|
||||
glob_t globv;
|
||||
char *ptr;
|
||||
int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
|
||||
|
||||
if (!vl || !vl[0])
|
||||
return (vl);
|
||||
|
||||
globv.gl_offs = 0;
|
||||
globv.gl_pathv = 0;
|
||||
globv.gl_pathc = 0;
|
||||
|
||||
if (nonomatch)
|
||||
gflgs |= GLOB_NOCHECK;
|
||||
|
||||
do {
|
||||
ptr = short2qstr(*vl);
|
||||
switch (glob(ptr, gflgs, 0, &globv)) {
|
||||
case GLOB_ABEND:
|
||||
setname(vis_str(*vl));
|
||||
stderror(ERR_NAME | ERR_GLOB);
|
||||
/* NOTREACHED */
|
||||
case GLOB_NOSPACE:
|
||||
stderror(ERR_NOMEM);
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (globv.gl_flags & GLOB_MAGCHAR) {
|
||||
match |= (globv.gl_matchc != 0);
|
||||
magic = 1;
|
||||
}
|
||||
gflgs |= GLOB_APPEND;
|
||||
}
|
||||
while (*++vl);
|
||||
vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
|
||||
NULL : blk2short(globv.gl_pathv);
|
||||
globfree(&globv);
|
||||
return (vl);
|
||||
}
|
||||
|
||||
Char *
|
||||
globone(str, action)
|
||||
Char *str;
|
||||
int action;
|
||||
{
|
||||
Char *v[2], **vl, **vo;
|
||||
int gflg;
|
||||
|
||||
noglob = adrof(STRnoglob) != 0;
|
||||
gflag = 0;
|
||||
v[0] = str;
|
||||
v[1] = 0;
|
||||
tglob(v);
|
||||
gflg = gflag;
|
||||
if (gflg == G_NONE)
|
||||
return (strip(Strsave(str)));
|
||||
|
||||
if (gflg & G_CSH) {
|
||||
/*
|
||||
* Expand back-quote, tilde and brace
|
||||
*/
|
||||
vo = globexpand(v);
|
||||
if (noglob || (gflg & G_GLOB) == 0) {
|
||||
if (vo[0] == NULL) {
|
||||
xfree((ptr_t) vo);
|
||||
return (Strsave(STRNULL));
|
||||
}
|
||||
if (vo[1] != NULL)
|
||||
return (handleone(str, vo, action));
|
||||
else {
|
||||
str = strip(vo[0]);
|
||||
xfree((ptr_t) vo);
|
||||
return (str);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (noglob || (gflg & G_GLOB) == 0)
|
||||
return (strip(Strsave(str)));
|
||||
else
|
||||
vo = v;
|
||||
|
||||
vl = libglob(vo);
|
||||
if ((gflg & G_CSH) && vl != vo)
|
||||
blkfree(vo);
|
||||
if (vl == NULL) {
|
||||
setname(vis_str(str));
|
||||
stderror(ERR_NAME | ERR_NOMATCH);
|
||||
}
|
||||
if (vl[0] == NULL) {
|
||||
xfree((ptr_t) vl);
|
||||
return (Strsave(STRNULL));
|
||||
}
|
||||
if (vl[1] != NULL)
|
||||
return (handleone(str, vl, action));
|
||||
else {
|
||||
str = strip(*vl);
|
||||
xfree((ptr_t) vl);
|
||||
return (str);
|
||||
}
|
||||
}
|
||||
|
||||
Char **
|
||||
globall(v)
|
||||
Char **v;
|
||||
{
|
||||
Char **vl, **vo;
|
||||
int gflg = gflag;
|
||||
|
||||
if (!v || !v[0]) {
|
||||
gargv = saveblk(v);
|
||||
gargc = blklen(gargv);
|
||||
return (gargv);
|
||||
}
|
||||
|
||||
noglob = adrof(STRnoglob) != 0;
|
||||
|
||||
if (gflg & G_CSH)
|
||||
/*
|
||||
* Expand back-quote, tilde and brace
|
||||
*/
|
||||
vl = vo = globexpand(v);
|
||||
else
|
||||
vl = vo = saveblk(v);
|
||||
|
||||
if (!noglob && (gflg & G_GLOB)) {
|
||||
vl = libglob(vo);
|
||||
if ((gflg & G_CSH) && vl != vo)
|
||||
blkfree(vo);
|
||||
}
|
||||
else
|
||||
trim(vl);
|
||||
|
||||
gargc = vl ? blklen(vl) : 0;
|
||||
return (gargv = vl);
|
||||
}
|
||||
|
||||
void
|
||||
ginit()
|
||||
{
|
||||
gargsiz = GLOBSPACE;
|
||||
gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
|
||||
gargv[0] = 0;
|
||||
gargc = 0;
|
||||
}
|
||||
|
||||
void
|
||||
rscan(t, f)
|
||||
Char **t;
|
||||
void (*f) __P((int));
|
||||
{
|
||||
Char *p;
|
||||
|
||||
while ((p = *t++) != NULL)
|
||||
while (*p)
|
||||
(*f) (*p++);
|
||||
}
|
||||
|
||||
void
|
||||
trim(t)
|
||||
Char **t;
|
||||
{
|
||||
Char *p;
|
||||
|
||||
while ((p = *t++) != NULL)
|
||||
while (*p)
|
||||
*p++ &= TRIM;
|
||||
}
|
||||
|
||||
void
|
||||
tglob(t)
|
||||
Char **t;
|
||||
{
|
||||
Char *p, c;
|
||||
|
||||
while ((p = *t++) != NULL) {
|
||||
if (*p == '~' || *p == '=')
|
||||
gflag |= G_CSH;
|
||||
else if (*p == '{' &&
|
||||
(p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
|
||||
continue;
|
||||
while ((c = *p++) != '\0') {
|
||||
/*
|
||||
* eat everything inside the matching backquotes
|
||||
*/
|
||||
if (c == '`') {
|
||||
gflag |= G_CSH;
|
||||
while (*p && *p != '`')
|
||||
if (*p++ == '\\') {
|
||||
if (*p) /* Quoted chars */
|
||||
p++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (*p) /* The matching ` */
|
||||
p++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if (c == '{')
|
||||
gflag |= G_CSH;
|
||||
else if (isglob(c))
|
||||
gflag |= G_GLOB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Command substitute cp. If literal, then this is a substitution from a
|
||||
* << redirection, and so we should not crunch blanks and tabs, separating
|
||||
* words only at newlines.
|
||||
*/
|
||||
Char **
|
||||
dobackp(cp, literal)
|
||||
Char *cp;
|
||||
bool literal;
|
||||
{
|
||||
Char *lp, *rp;
|
||||
Char *ep, word[MAXPATHLEN];
|
||||
|
||||
if (pargv) {
|
||||
#ifdef notdef
|
||||
abort();
|
||||
#endif
|
||||
blkfree(pargv);
|
||||
}
|
||||
pargsiz = GLOBSPACE;
|
||||
pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
|
||||
pargv[0] = NULL;
|
||||
pargcp = pargs = word;
|
||||
pargc = 0;
|
||||
pnleft = MAXPATHLEN - 4;
|
||||
for (;;) {
|
||||
for (lp = cp; *lp != '`'; lp++) {
|
||||
if (*lp == 0) {
|
||||
if (pargcp != pargs)
|
||||
pword();
|
||||
return (pargv);
|
||||
}
|
||||
psave(*lp);
|
||||
}
|
||||
lp++;
|
||||
for (rp = lp; *rp && *rp != '`'; rp++)
|
||||
if (*rp == '\\') {
|
||||
rp++;
|
||||
if (!*rp)
|
||||
goto oops;
|
||||
}
|
||||
if (!*rp)
|
||||
oops: stderror(ERR_UNMATCHED, '`');
|
||||
ep = Strsave(lp);
|
||||
ep[rp - lp] = 0;
|
||||
backeval(ep, literal);
|
||||
cp = rp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
backeval(cp, literal)
|
||||
Char *cp;
|
||||
bool literal;
|
||||
{
|
||||
int icnt, c;
|
||||
Char *ip;
|
||||
struct command faket;
|
||||
bool hadnl;
|
||||
int pvec[2], quoted;
|
||||
Char *fakecom[2], ibuf[BUFSIZ];
|
||||
char tibuf[BUFSIZ];
|
||||
|
||||
hadnl = 0;
|
||||
icnt = 0;
|
||||
quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
|
||||
faket.t_dtyp = NODE_COMMAND;
|
||||
faket.t_dflg = 0;
|
||||
faket.t_dlef = 0;
|
||||
faket.t_drit = 0;
|
||||
faket.t_dspr = 0;
|
||||
faket.t_dcom = fakecom;
|
||||
fakecom[0] = STRfakecom1;
|
||||
fakecom[1] = 0;
|
||||
|
||||
/*
|
||||
* We do the psave job to temporarily change the current job so that the
|
||||
* following fork is considered a separate job. This is so that when
|
||||
* backquotes are used in a builtin function that calls glob the "current
|
||||
* job" is not corrupted. We only need one level of pushed jobs as long as
|
||||
* we are sure to fork here.
|
||||
*/
|
||||
psavejob();
|
||||
|
||||
/*
|
||||
* It would be nicer if we could integrate this redirection more with the
|
||||
* routines in sh.sem.c by doing a fake execute on a builtin function that
|
||||
* was piped out.
|
||||
*/
|
||||
mypipe(pvec);
|
||||
if (pfork(&faket, -1) == 0) {
|
||||
struct wordent paraml;
|
||||
struct command *t;
|
||||
|
||||
(void) close(pvec[0]);
|
||||
(void) dmove(pvec[1], 1);
|
||||
(void) dmove(SHERR, 2);
|
||||
initdesc();
|
||||
/*
|
||||
* Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
|
||||
* posted to comp.bugs.4bsd 12 Sep. 1989.
|
||||
*/
|
||||
if (pargv) /* mg, 21.dec.88 */
|
||||
blkfree(pargv), pargv = 0, pargsiz = 0;
|
||||
/* mg, 21.dec.88 */
|
||||
arginp = cp;
|
||||
while (*cp)
|
||||
*cp++ &= TRIM;
|
||||
|
||||
/*
|
||||
* In the child ``forget'' everything about current aliases or
|
||||
* eval vectors.
|
||||
*/
|
||||
alvec = NULL;
|
||||
evalvec = NULL;
|
||||
alvecp = NULL;
|
||||
evalp = NULL;
|
||||
(void) lex(¶ml);
|
||||
if (seterr)
|
||||
stderror(ERR_OLD);
|
||||
alias(¶ml);
|
||||
t = syntax(paraml.next, ¶ml, 0);
|
||||
if (seterr)
|
||||
stderror(ERR_OLD);
|
||||
if (t)
|
||||
t->t_dflg |= F_NOFORK;
|
||||
(void) signal(SIGTSTP, SIG_IGN);
|
||||
(void) signal(SIGTTIN, SIG_IGN);
|
||||
(void) signal(SIGTTOU, SIG_IGN);
|
||||
execute(t, -1, NULL, NULL);
|
||||
exitstat();
|
||||
}
|
||||
xfree((ptr_t) cp);
|
||||
(void) close(pvec[1]);
|
||||
c = 0;
|
||||
ip = NULL;
|
||||
do {
|
||||
int cnt = 0;
|
||||
|
||||
for (;;) {
|
||||
if (icnt == 0) {
|
||||
int i;
|
||||
|
||||
ip = ibuf;
|
||||
do
|
||||
icnt = read(pvec[0], tibuf, BUFSIZ);
|
||||
while (icnt == -1 && errno == EINTR);
|
||||
if (icnt <= 0) {
|
||||
c = -1;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < icnt; i++)
|
||||
ip[i] = (unsigned char) tibuf[i];
|
||||
}
|
||||
if (hadnl)
|
||||
break;
|
||||
--icnt;
|
||||
c = (*ip++ & TRIM);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == '\n') {
|
||||
/*
|
||||
* Continue around the loop one more time, so that we can eat
|
||||
* the last newline without terminating this word.
|
||||
*/
|
||||
hadnl = 1;
|
||||
continue;
|
||||
}
|
||||
if (!quoted && (c == ' ' || c == '\t'))
|
||||
break;
|
||||
cnt++;
|
||||
psave(c | quoted);
|
||||
}
|
||||
/*
|
||||
* Unless at end-of-file, we will form a new word here if there were
|
||||
* characters in the word, or in any case when we take text literally.
|
||||
* If we didn't make empty words here when literal was set then we
|
||||
* would lose blank lines.
|
||||
*/
|
||||
if (c != -1 && (cnt || literal))
|
||||
pword();
|
||||
hadnl = 0;
|
||||
} while (c >= 0);
|
||||
(void) close(pvec[0]);
|
||||
pwait();
|
||||
prestjob();
|
||||
}
|
||||
|
||||
static void
|
||||
psave(c)
|
||||
int c;
|
||||
{
|
||||
if (--pnleft <= 0)
|
||||
stderror(ERR_WTOOLONG);
|
||||
*pargcp++ = c;
|
||||
}
|
||||
|
||||
static void
|
||||
pword()
|
||||
{
|
||||
psave(0);
|
||||
if (pargc == pargsiz - 1) {
|
||||
pargsiz += GLOBSPACE;
|
||||
pargv = (Char **) xrealloc((ptr_t) pargv,
|
||||
(size_t) pargsiz * sizeof(Char *));
|
||||
}
|
||||
pargv[pargc++] = Strsave(pargs);
|
||||
pargv[pargc] = NULL;
|
||||
pargcp = pargs;
|
||||
pnleft = MAXPATHLEN - 4;
|
||||
}
|
||||
|
||||
int
|
||||
Gmatch(string, pattern)
|
||||
Char *string, *pattern;
|
||||
{
|
||||
Char **blk, **p;
|
||||
int gpol = 1, gres = 0;
|
||||
|
||||
if (*pattern == '^') {
|
||||
gpol = 0;
|
||||
pattern++;
|
||||
}
|
||||
|
||||
blk = (Char **) xmalloc(GLOBSPACE * sizeof(Char *));
|
||||
blk[0] = Strsave(pattern);
|
||||
blk[1] = NULL;
|
||||
|
||||
expbrace(&blk, NULL, GLOBSPACE);
|
||||
|
||||
for (p = blk; *p; p++)
|
||||
gres |= pmatch(string, *p);
|
||||
|
||||
blkfree(blk);
|
||||
return(gres == gpol);
|
||||
}
|
||||
|
||||
static int
|
||||
pmatch(string, pattern)
|
||||
Char *string, *pattern;
|
||||
{
|
||||
Char stringc, patternc;
|
||||
int match, negate_range;
|
||||
Char rangec;
|
||||
|
||||
for (;; ++string) {
|
||||
stringc = *string & TRIM;
|
||||
patternc = *pattern++;
|
||||
switch (patternc) {
|
||||
case 0:
|
||||
return (stringc == 0);
|
||||
case '?':
|
||||
if (stringc == 0)
|
||||
return (0);
|
||||
break;
|
||||
case '*':
|
||||
if (!*pattern)
|
||||
return (1);
|
||||
while (*string)
|
||||
if (Gmatch(string++, pattern))
|
||||
return (1);
|
||||
return (0);
|
||||
case '[':
|
||||
match = 0;
|
||||
if ((negate_range = (*pattern == '^')) != 0)
|
||||
pattern++;
|
||||
while ((rangec = *pattern++) != '\0') {
|
||||
if (rangec == ']')
|
||||
break;
|
||||
if (match)
|
||||
continue;
|
||||
if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') {
|
||||
match = ( collate_range_cmp(stringc, *pattern & TRIM) <= 0
|
||||
&& collate_range_cmp(*(pattern-2) & TRIM, stringc) <= 0
|
||||
);
|
||||
pattern++;
|
||||
}
|
||||
else
|
||||
match = (stringc == (rangec & TRIM));
|
||||
}
|
||||
if (rangec == 0)
|
||||
stderror(ERR_NAME | ERR_MISSING, ']');
|
||||
if (match == negate_range)
|
||||
return (0);
|
||||
break;
|
||||
default:
|
||||
if ((patternc & TRIM) != stringc)
|
||||
return (0);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gcat(s1, s2)
|
||||
Char *s1, *s2;
|
||||
{
|
||||
Char *p, *q;
|
||||
int n;
|
||||
|
||||
for (p = s1; *p++;)
|
||||
continue;
|
||||
for (q = s2; *q++;)
|
||||
continue;
|
||||
n = (p - s1) + (q - s2) - 1;
|
||||
if (++gargc >= gargsiz) {
|
||||
gargsiz += GLOBSPACE;
|
||||
gargv = (Char **) xrealloc((ptr_t) gargv,
|
||||
(size_t) gargsiz * sizeof(Char *));
|
||||
}
|
||||
gargv[gargc] = 0;
|
||||
p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
|
||||
for (q = s1; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
for (p--, q = s2; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef FILEC
|
||||
int
|
||||
sortscmp(a, b)
|
||||
const ptr_t a, b;
|
||||
{
|
||||
#if defined(NLS) && !defined(NOSTRCOLL)
|
||||
char buf[2048];
|
||||
#endif
|
||||
|
||||
if (!a) /* check for NULL */
|
||||
return (b ? 1 : 0);
|
||||
if (!b)
|
||||
return (-1);
|
||||
|
||||
if (!*(Char **)a) /* check for NULL */
|
||||
return (*(Char **)b ? 1 : 0);
|
||||
if (!*(Char **)b)
|
||||
return (-1);
|
||||
|
||||
#if defined(NLS) && !defined(NOSTRCOLL)
|
||||
(void) strcpy(buf, short2str(*(Char **)a));
|
||||
return ((int) strcoll(buf, short2str(*(Char **)b)));
|
||||
#else
|
||||
return ((int) Strcmp(*(Char **)a, *(Char **)b));
|
||||
#endif
|
||||
}
|
||||
#endif /* FILEC */
|
188
bin/csh/hist.c
188
bin/csh/hist.c
@ -1,188 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
static void hfree __P((struct Hist *));
|
||||
static void dohist1 __P((struct Hist *, int *, int, int));
|
||||
static void phist __P((struct Hist *, int));
|
||||
|
||||
void
|
||||
savehist(sp)
|
||||
struct wordent *sp;
|
||||
{
|
||||
struct Hist *hp, *np;
|
||||
int histlen = 0;
|
||||
Char *cp;
|
||||
|
||||
/* throw away null lines */
|
||||
if (sp->next->word[0] == '\n')
|
||||
return;
|
||||
cp = value(STRhistory);
|
||||
if (*cp) {
|
||||
Char *p = cp;
|
||||
|
||||
while (*p) {
|
||||
if (!Isdigit(*p)) {
|
||||
histlen = 0;
|
||||
break;
|
||||
}
|
||||
histlen = histlen * 10 + *p++ - '0';
|
||||
}
|
||||
}
|
||||
for (hp = &Histlist; (np = hp->Hnext) != NULL;)
|
||||
if (eventno - np->Href >= histlen || histlen == 0)
|
||||
hp->Hnext = np->Hnext, hfree(np);
|
||||
else
|
||||
hp = np;
|
||||
(void) enthist(++eventno, sp, 1);
|
||||
}
|
||||
|
||||
struct Hist *
|
||||
enthist(event, lp, docopy)
|
||||
int event;
|
||||
struct wordent *lp;
|
||||
bool docopy;
|
||||
{
|
||||
struct Hist *np;
|
||||
|
||||
np = (struct Hist *) xmalloc((size_t) sizeof(*np));
|
||||
np->Hnum = np->Href = event;
|
||||
if (docopy) {
|
||||
copylex(&np->Hlex, lp);
|
||||
}
|
||||
else {
|
||||
np->Hlex.next = lp->next;
|
||||
lp->next->prev = &np->Hlex;
|
||||
np->Hlex.prev = lp->prev;
|
||||
lp->prev->next = &np->Hlex;
|
||||
}
|
||||
np->Hnext = Histlist.Hnext;
|
||||
Histlist.Hnext = np;
|
||||
return (np);
|
||||
}
|
||||
|
||||
static void
|
||||
hfree(hp)
|
||||
struct Hist *hp;
|
||||
{
|
||||
|
||||
freelex(&hp->Hlex);
|
||||
xfree((ptr_t) hp);
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dohist(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
int n, rflg = 0, hflg = 0;
|
||||
|
||||
if (getn(value(STRhistory)) == 0)
|
||||
return;
|
||||
if (setintr)
|
||||
(void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));
|
||||
while (*++v && **v == '-') {
|
||||
Char *vp = *v;
|
||||
|
||||
while (*++vp)
|
||||
switch (*vp) {
|
||||
case 'h':
|
||||
hflg++;
|
||||
break;
|
||||
case 'r':
|
||||
rflg++;
|
||||
break;
|
||||
case '-': /* ignore multiple '-'s */
|
||||
break;
|
||||
default:
|
||||
stderror(ERR_HISTUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*v)
|
||||
n = getn(*v);
|
||||
else {
|
||||
n = getn(value(STRhistory));
|
||||
}
|
||||
dohist1(Histlist.Hnext, &n, rflg, hflg);
|
||||
}
|
||||
|
||||
static void
|
||||
dohist1(hp, np, rflg, hflg)
|
||||
struct Hist *hp;
|
||||
int *np, rflg, hflg;
|
||||
{
|
||||
bool print = (*np) > 0;
|
||||
|
||||
for (; hp != 0; hp = hp->Hnext) {
|
||||
(*np)--;
|
||||
hp->Href++;
|
||||
if (rflg == 0) {
|
||||
dohist1(hp->Hnext, np, rflg, hflg);
|
||||
if (print)
|
||||
phist(hp, hflg);
|
||||
return;
|
||||
}
|
||||
if (*np >= 0)
|
||||
phist(hp, hflg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
phist(hp, hflg)
|
||||
struct Hist *hp;
|
||||
int hflg;
|
||||
{
|
||||
if (hflg == 0)
|
||||
(void) fprintf(cshout, "%6d\t", hp->Hnum);
|
||||
prlex(cshout, &hp->Hlex);
|
||||
}
|
139
bin/csh/init.c
139
bin/csh/init.c
@ -1,139 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
#define INF 1000
|
||||
|
||||
struct biltins bfunc[] =
|
||||
{
|
||||
{ "@", dolet, 0, INF },
|
||||
{ "alias", doalias, 0, INF },
|
||||
{ "alloc", showall, 0, 1 },
|
||||
{ "bg", dobg, 0, INF },
|
||||
{ "break", dobreak, 0, 0 },
|
||||
{ "breaksw", doswbrk, 0, 0 },
|
||||
{ "case", dozip, 0, 1 },
|
||||
{ "cd", dochngd, 0, INF },
|
||||
{ "chdir", dochngd, 0, INF },
|
||||
{ "continue", docontin, 0, 0 },
|
||||
{ "default", dozip, 0, 0 },
|
||||
{ "dirs", dodirs, 0, INF },
|
||||
{ "echo", doecho, 0, INF },
|
||||
{ "else", doelse, 0, INF },
|
||||
{ "end", doend, 0, 0 },
|
||||
{ "endif", dozip, 0, 0 },
|
||||
{ "endsw", dozip, 0, 0 },
|
||||
{ "eval", doeval, 0, INF },
|
||||
{ "exec", execash, 1, INF },
|
||||
{ "exit", doexit, 0, INF },
|
||||
{ "fg", dofg, 0, INF },
|
||||
{ "foreach", doforeach, 3, INF },
|
||||
{ "glob", doglob, 0, INF },
|
||||
{ "goto", dogoto, 1, 1 },
|
||||
{ "hashstat", hashstat, 0, 0 },
|
||||
{ "history", dohist, 0, 2 },
|
||||
{ "if", doif, 1, INF },
|
||||
{ "jobs", dojobs, 0, 1 },
|
||||
{ "kill", dokill, 1, INF },
|
||||
{ "limit", dolimit, 0, 3 },
|
||||
{ "linedit", doecho, 0, INF },
|
||||
{ "login", dologin, 0, 1 },
|
||||
{ "logout", dologout, 0, 0 },
|
||||
{ "nice", donice, 0, INF },
|
||||
{ "nohup", donohup, 0, INF },
|
||||
{ "notify", donotify, 0, INF },
|
||||
{ "onintr", doonintr, 0, 2 },
|
||||
{ "popd", dopopd, 0, INF },
|
||||
{ "printf", doprintf, 1, INF },
|
||||
{ "pushd", dopushd, 0, INF },
|
||||
{ "rehash", dohash, 0, 0 },
|
||||
{ "repeat", dorepeat, 2, INF },
|
||||
{ "set", doset, 0, INF },
|
||||
{ "setenv", dosetenv, 0, 2 },
|
||||
{ "shift", shift, 0, 1 },
|
||||
{ "source", dosource, 1, 2 },
|
||||
{ "stop", dostop, 1, INF },
|
||||
{ "suspend", dosuspend, 0, 0 },
|
||||
{ "switch", doswitch, 1, INF },
|
||||
{ "time", dotime, 0, INF },
|
||||
{ "umask", doumask, 0, 1 },
|
||||
{ "unalias", unalias, 1, INF },
|
||||
{ "unhash", dounhash, 0, 0 },
|
||||
{ "unlimit", dounlimit, 0, INF },
|
||||
{ "unset", unset, 1, INF },
|
||||
{ "unsetenv", dounsetenv, 1, INF },
|
||||
{ "wait", dowait, 0, 0 },
|
||||
{ "which", dowhich, 1, INF },
|
||||
{ "while", dowhile, 1, INF }
|
||||
};
|
||||
int nbfunc = sizeof bfunc / sizeof *bfunc;
|
||||
|
||||
struct srch srchn[] =
|
||||
{
|
||||
{ "@", T_LET },
|
||||
{ "break", T_BREAK },
|
||||
{ "breaksw", T_BRKSW },
|
||||
{ "case", T_CASE },
|
||||
{ "default", T_DEFAULT },
|
||||
{ "else", T_ELSE },
|
||||
{ "end", T_END },
|
||||
{ "endif", T_ENDIF },
|
||||
{ "endsw", T_ENDSW },
|
||||
{ "exit", T_EXIT },
|
||||
{ "foreach", T_FOREACH },
|
||||
{ "goto", T_GOTO },
|
||||
{ "if", T_IF },
|
||||
{ "label", T_LABEL },
|
||||
{ "set", T_SET },
|
||||
{ "switch", T_SWITCH },
|
||||
{ "while", T_WHILE }
|
||||
};
|
||||
int nsrchn = sizeof srchn / sizeof *srchn;
|
||||
|
1643
bin/csh/lex.c
1643
bin/csh/lex.c
File diff suppressed because it is too large
Load Diff
424
bin/csh/misc.c
424
bin/csh/misc.c
@ -1,424 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int renum __P((int, int));
|
||||
|
||||
int
|
||||
any(s, c)
|
||||
char *s;
|
||||
int c;
|
||||
{
|
||||
if (!s)
|
||||
return (0); /* Check for nil pointer */
|
||||
while (*s)
|
||||
if (*s++ == c)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
setzero(cp, i)
|
||||
char *cp;
|
||||
int i;
|
||||
{
|
||||
if (i != 0)
|
||||
do
|
||||
*cp++ = 0;
|
||||
while (--i);
|
||||
}
|
||||
|
||||
char *
|
||||
strsave(s)
|
||||
char *s;
|
||||
{
|
||||
char *n;
|
||||
char *p;
|
||||
|
||||
if (s == NULL)
|
||||
s = "";
|
||||
for (p = s; *p++;)
|
||||
continue;
|
||||
n = p = (char *) xmalloc((size_t) ((p - s) * sizeof(char)));
|
||||
while ((*p++ = *s++) != '\0')
|
||||
continue;
|
||||
return (n);
|
||||
}
|
||||
|
||||
Char **
|
||||
blkend(up)
|
||||
Char **up;
|
||||
{
|
||||
|
||||
while (*up)
|
||||
up++;
|
||||
return (up);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blkpr(fp, av)
|
||||
FILE *fp;
|
||||
Char **av;
|
||||
{
|
||||
|
||||
for (; *av; av++) {
|
||||
(void) fprintf(fp, "%s", vis_str(*av));
|
||||
if (av[1])
|
||||
(void) fprintf(fp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
blklen(av)
|
||||
Char **av;
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (*av++)
|
||||
i++;
|
||||
return (i);
|
||||
}
|
||||
|
||||
Char **
|
||||
blkcpy(oav, bv)
|
||||
Char **oav;
|
||||
Char **bv;
|
||||
{
|
||||
Char **av = oav;
|
||||
|
||||
while ((*av++ = *bv++) != NULL)
|
||||
continue;
|
||||
return (oav);
|
||||
}
|
||||
|
||||
Char **
|
||||
blkcat(up, vp)
|
||||
Char **up, **vp;
|
||||
{
|
||||
|
||||
(void) blkcpy(blkend(up), vp);
|
||||
return (up);
|
||||
}
|
||||
|
||||
void
|
||||
blkfree(av0)
|
||||
Char **av0;
|
||||
{
|
||||
Char **av = av0;
|
||||
|
||||
if (!av0)
|
||||
return;
|
||||
for (; *av; av++)
|
||||
xfree((ptr_t) * av);
|
||||
xfree((ptr_t) av0);
|
||||
}
|
||||
|
||||
Char **
|
||||
saveblk(v)
|
||||
Char **v;
|
||||
{
|
||||
Char **newv =
|
||||
(Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
|
||||
Char **onewv = newv;
|
||||
|
||||
while (*v)
|
||||
*newv++ = Strsave(*v++);
|
||||
return (onewv);
|
||||
}
|
||||
|
||||
#ifdef NOTUSED
|
||||
char *
|
||||
strstr(s, t)
|
||||
char *s, *t;
|
||||
{
|
||||
do {
|
||||
char *ss = s;
|
||||
char *tt = t;
|
||||
|
||||
do
|
||||
if (*tt == '\0')
|
||||
return (s);
|
||||
while (*ss++ == *tt++);
|
||||
} while (*s++ != '\0');
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#endif /* NOTUSED */
|
||||
|
||||
#ifndef SHORT_STRINGS
|
||||
char *
|
||||
strspl(cp, dp)
|
||||
char *cp, *dp;
|
||||
{
|
||||
char *ep;
|
||||
char *p, *q;
|
||||
|
||||
if (!cp)
|
||||
cp = "";
|
||||
if (!dp)
|
||||
dp = "";
|
||||
for (p = cp; *p++;)
|
||||
continue;
|
||||
for (q = dp; *q++;)
|
||||
continue;
|
||||
ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
|
||||
for (p = ep, q = cp; *p++ = *q++;)
|
||||
continue;
|
||||
for (p--, q = dp; *p++ = *q++;)
|
||||
continue;
|
||||
return (ep);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Char **
|
||||
blkspl(up, vp)
|
||||
Char **up, **vp;
|
||||
{
|
||||
Char **wp =
|
||||
(Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
|
||||
sizeof(Char **));
|
||||
|
||||
(void) blkcpy(wp, up);
|
||||
return (blkcat(wp, vp));
|
||||
}
|
||||
|
||||
Char
|
||||
lastchr(cp)
|
||||
Char *cp;
|
||||
{
|
||||
|
||||
if (!cp)
|
||||
return (0);
|
||||
if (!*cp)
|
||||
return (0);
|
||||
while (cp[1])
|
||||
cp++;
|
||||
return (*cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called after an error to close up
|
||||
* any units which may have been left open accidentally.
|
||||
*/
|
||||
void
|
||||
closem()
|
||||
{
|
||||
int f, flimit;
|
||||
|
||||
for (f = 0, flimit = getdtablesize(); f < flimit; f++)
|
||||
if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
|
||||
f != FSHTTY)
|
||||
(void) close(f);
|
||||
}
|
||||
|
||||
void
|
||||
donefds()
|
||||
{
|
||||
(void) close(0);
|
||||
(void) close(1);
|
||||
(void) close(2);
|
||||
|
||||
didfds = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move descriptor i to j.
|
||||
* If j is -1 then we just want to get i to a safe place,
|
||||
* i.e. to a unit > 2. This also happens in dcopy.
|
||||
*/
|
||||
int
|
||||
dmove(i, j)
|
||||
int i, j;
|
||||
{
|
||||
|
||||
if (i == j || i < 0)
|
||||
return (i);
|
||||
if (j >= 0) {
|
||||
(void) dup2(i, j);
|
||||
if (j != i)
|
||||
(void) close(i);
|
||||
return (j);
|
||||
}
|
||||
j = dcopy(i, j);
|
||||
if (j != i)
|
||||
(void) close(i);
|
||||
return (j);
|
||||
}
|
||||
|
||||
int
|
||||
dcopy(i, j)
|
||||
int i, j;
|
||||
{
|
||||
|
||||
if (i == j || i < 0 || (j < 0 && i > 2))
|
||||
return (i);
|
||||
if (j >= 0) {
|
||||
(void) dup2(i, j);
|
||||
return (j);
|
||||
}
|
||||
(void) close(j);
|
||||
return (renum(i, j));
|
||||
}
|
||||
|
||||
static int
|
||||
renum(i, j)
|
||||
int i, j;
|
||||
{
|
||||
int k = dup(i);
|
||||
|
||||
if (k < 0)
|
||||
return (-1);
|
||||
if (j == -1 && k > 2)
|
||||
return (k);
|
||||
if (k != j) {
|
||||
j = renum(k, j);
|
||||
(void) close(k);
|
||||
return (j);
|
||||
}
|
||||
return (k);
|
||||
}
|
||||
|
||||
/*
|
||||
* Left shift a command argument list, discarding
|
||||
* the first c arguments. Used in "shift" commands
|
||||
* as well as by commands like "repeat".
|
||||
*/
|
||||
void
|
||||
lshift(v, c)
|
||||
Char **v;
|
||||
int c;
|
||||
{
|
||||
Char **u;
|
||||
|
||||
for (u = v; *u && --c >= 0; u++)
|
||||
xfree((ptr_t) *u);
|
||||
(void) blkcpy(v, u);
|
||||
}
|
||||
|
||||
int
|
||||
number(cp)
|
||||
Char *cp;
|
||||
{
|
||||
if (!cp)
|
||||
return(0);
|
||||
if (*cp == '-') {
|
||||
cp++;
|
||||
if (!Isdigit(*cp))
|
||||
return (0);
|
||||
cp++;
|
||||
}
|
||||
while (*cp && Isdigit(*cp))
|
||||
cp++;
|
||||
return (*cp == 0);
|
||||
}
|
||||
|
||||
Char **
|
||||
copyblk(v)
|
||||
Char **v;
|
||||
{
|
||||
Char **nv = (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
|
||||
|
||||
return (blkcpy(nv, v));
|
||||
}
|
||||
|
||||
#ifndef SHORT_STRINGS
|
||||
char *
|
||||
strend(cp)
|
||||
char *cp;
|
||||
{
|
||||
if (!cp)
|
||||
return (cp);
|
||||
while (*cp)
|
||||
cp++;
|
||||
return (cp);
|
||||
}
|
||||
|
||||
#endif /* SHORT_STRINGS */
|
||||
|
||||
Char *
|
||||
strip(cp)
|
||||
Char *cp;
|
||||
{
|
||||
Char *dp = cp;
|
||||
|
||||
if (!cp)
|
||||
return (cp);
|
||||
while ((*dp++ &= TRIM) != '\0')
|
||||
continue;
|
||||
return (cp);
|
||||
}
|
||||
|
||||
void
|
||||
udvar(name)
|
||||
Char *name;
|
||||
{
|
||||
|
||||
setname(vis_str(name));
|
||||
stderror(ERR_NAME | ERR_UNDVAR);
|
||||
}
|
||||
|
||||
int
|
||||
prefix(sub, str)
|
||||
Char *sub, *str;
|
||||
{
|
||||
|
||||
for (;;) {
|
||||
if (*sub == 0)
|
||||
return (1);
|
||||
if (*str == 0)
|
||||
return (0);
|
||||
if (*sub++ != *str++)
|
||||
return (0);
|
||||
}
|
||||
}
|
702
bin/csh/parse.c
702
bin/csh/parse.c
@ -1,702 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
static void asyntax __P((struct wordent *, struct wordent *));
|
||||
static void asyn0 __P((struct wordent *, struct wordent *));
|
||||
static void asyn3 __P((struct wordent *, struct wordent *));
|
||||
static struct wordent
|
||||
*freenod __P((struct wordent *, struct wordent *));
|
||||
static struct command
|
||||
*syn0 __P((struct wordent *, struct wordent *, int));
|
||||
static struct command
|
||||
*syn1 __P((struct wordent *, struct wordent *, int));
|
||||
static struct command
|
||||
*syn1a __P((struct wordent *, struct wordent *, int));
|
||||
static struct command
|
||||
*syn1b __P((struct wordent *, struct wordent *, int));
|
||||
static struct command
|
||||
*syn2 __P((struct wordent *, struct wordent *, int));
|
||||
static struct command
|
||||
*syn3 __P((struct wordent *, struct wordent *, int));
|
||||
|
||||
#define ALEFT 21 /* max of 20 alias expansions */
|
||||
#define HLEFT 11 /* max of 10 history expansions */
|
||||
/*
|
||||
* Perform aliasing on the word list lex
|
||||
* Do a (very rudimentary) parse to separate into commands.
|
||||
* If word 0 of a command has an alias, do it.
|
||||
* Repeat a maximum of 20 times.
|
||||
*/
|
||||
static int aleft;
|
||||
extern int hleft;
|
||||
void
|
||||
alias(lex)
|
||||
struct wordent *lex;
|
||||
{
|
||||
jmp_buf osetexit;
|
||||
|
||||
aleft = ALEFT;
|
||||
hleft = HLEFT;
|
||||
getexit(osetexit);
|
||||
(void) setexit();
|
||||
if (haderr) {
|
||||
resexit(osetexit);
|
||||
reset();
|
||||
}
|
||||
if (--aleft == 0)
|
||||
stderror(ERR_ALIASLOOP);
|
||||
asyntax(lex->next, lex);
|
||||
resexit(osetexit);
|
||||
}
|
||||
|
||||
static void
|
||||
asyntax(p1, p2)
|
||||
struct wordent *p1, *p2;
|
||||
{
|
||||
while (p1 != p2)
|
||||
if (any(";&\n", p1->word[0]))
|
||||
p1 = p1->next;
|
||||
else {
|
||||
asyn0(p1, p2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
asyn0(p1, p2)
|
||||
struct wordent *p1;
|
||||
struct wordent *p2;
|
||||
{
|
||||
struct wordent *p;
|
||||
int l = 0;
|
||||
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
if (l < 0)
|
||||
stderror(ERR_TOOMANYRP);
|
||||
continue;
|
||||
|
||||
case '>':
|
||||
if (p->next != p2 && eq(p->next->word, STRand))
|
||||
p = p->next;
|
||||
continue;
|
||||
|
||||
case '&':
|
||||
case '|':
|
||||
case ';':
|
||||
case '\n':
|
||||
if (l != 0)
|
||||
continue;
|
||||
asyn3(p1, p);
|
||||
asyntax(p->next, p2);
|
||||
return;
|
||||
}
|
||||
if (l == 0)
|
||||
asyn3(p1, p2);
|
||||
}
|
||||
|
||||
static void
|
||||
asyn3(p1, p2)
|
||||
struct wordent *p1;
|
||||
struct wordent *p2;
|
||||
{
|
||||
struct varent *ap;
|
||||
struct wordent alout;
|
||||
bool redid;
|
||||
|
||||
if (p1 == p2)
|
||||
return;
|
||||
if (p1->word[0] == '(') {
|
||||
for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
|
||||
if (p2 == p1)
|
||||
return;
|
||||
if (p2 == p1->next)
|
||||
return;
|
||||
asyn0(p1->next, p2);
|
||||
return;
|
||||
}
|
||||
ap = adrof1(p1->word, &aliases);
|
||||
if (ap == 0)
|
||||
return;
|
||||
alhistp = p1->prev;
|
||||
alhistt = p2;
|
||||
alvec = ap->vec;
|
||||
redid = lex(&alout);
|
||||
alhistp = alhistt = 0;
|
||||
alvec = 0;
|
||||
if (seterr) {
|
||||
freelex(&alout);
|
||||
stderror(ERR_OLD);
|
||||
}
|
||||
if (p1->word[0] && eq(p1->word, alout.next->word)) {
|
||||
Char *cp = alout.next->word;
|
||||
|
||||
alout.next->word = Strspl(STRQNULL, cp);
|
||||
xfree((ptr_t) cp);
|
||||
}
|
||||
p1 = freenod(p1, redid ? p2 : p1->next);
|
||||
if (alout.next != &alout) {
|
||||
p1->next->prev = alout.prev->prev;
|
||||
alout.prev->prev->next = p1->next;
|
||||
alout.next->prev = p1;
|
||||
p1->next = alout.next;
|
||||
xfree((ptr_t) alout.prev->word);
|
||||
xfree((ptr_t) (alout.prev));
|
||||
}
|
||||
reset(); /* throw! */
|
||||
}
|
||||
|
||||
static struct wordent *
|
||||
freenod(p1, p2)
|
||||
struct wordent *p1, *p2;
|
||||
{
|
||||
struct wordent *retp = p1->prev;
|
||||
|
||||
while (p1 != p2) {
|
||||
xfree((ptr_t) p1->word);
|
||||
p1 = p1->next;
|
||||
xfree((ptr_t) (p1->prev));
|
||||
}
|
||||
retp->next = p2;
|
||||
p2->prev = retp;
|
||||
return (retp);
|
||||
}
|
||||
|
||||
#define PHERE 1
|
||||
#define PIN 2
|
||||
#define POUT 4
|
||||
#define PERR 8
|
||||
|
||||
/*
|
||||
* syntax
|
||||
* empty
|
||||
* syn0
|
||||
*/
|
||||
struct command *
|
||||
syntax(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
|
||||
while (p1 != p2)
|
||||
if (any(";&\n", p1->word[0]))
|
||||
p1 = p1->next;
|
||||
else
|
||||
return (syn0(p1, p2, flags));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* syn0
|
||||
* syn1
|
||||
* syn1 & syntax
|
||||
*/
|
||||
static struct command *
|
||||
syn0(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p;
|
||||
struct command *t, *t1;
|
||||
int l;
|
||||
|
||||
l = 0;
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
if (l < 0)
|
||||
seterror(ERR_TOOMANYRP);
|
||||
continue;
|
||||
|
||||
case '|':
|
||||
if (p->word[1] == '|')
|
||||
continue;
|
||||
/* fall into ... */
|
||||
|
||||
case '>':
|
||||
if (p->next != p2 && eq(p->next->word, STRand))
|
||||
p = p->next;
|
||||
continue;
|
||||
|
||||
case '&':
|
||||
if (l != 0)
|
||||
break;
|
||||
if (p->word[1] == '&')
|
||||
continue;
|
||||
t1 = syn1(p1, p, flags);
|
||||
if (t1->t_dtyp == NODE_LIST ||
|
||||
t1->t_dtyp == NODE_AND ||
|
||||
t1->t_dtyp == NODE_OR) {
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
t->t_dtyp = NODE_PAREN;
|
||||
t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
|
||||
t->t_dspr = t1;
|
||||
t1 = t;
|
||||
}
|
||||
else
|
||||
t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
t->t_dtyp = NODE_LIST;
|
||||
t->t_dflg = 0;
|
||||
t->t_dcar = t1;
|
||||
t->t_dcdr = syntax(p, p2, flags);
|
||||
return (t);
|
||||
}
|
||||
if (l == 0)
|
||||
return (syn1(p1, p2, flags));
|
||||
seterror(ERR_TOOMANYLP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* syn1
|
||||
* syn1a
|
||||
* syn1a ; syntax
|
||||
*/
|
||||
static struct command *
|
||||
syn1(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p;
|
||||
struct command *t;
|
||||
int l;
|
||||
|
||||
l = 0;
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
continue;
|
||||
|
||||
case ';':
|
||||
case '\n':
|
||||
if (l != 0)
|
||||
break;
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
t->t_dtyp = NODE_LIST;
|
||||
t->t_dcar = syn1a(p1, p, flags);
|
||||
t->t_dcdr = syntax(p->next, p2, flags);
|
||||
if (t->t_dcdr == 0)
|
||||
t->t_dcdr = t->t_dcar, t->t_dcar = 0;
|
||||
return (t);
|
||||
}
|
||||
return (syn1a(p1, p2, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* syn1a
|
||||
* syn1b
|
||||
* syn1b || syn1a
|
||||
*/
|
||||
static struct command *
|
||||
syn1a(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p;
|
||||
struct command *t;
|
||||
int l = 0;
|
||||
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
continue;
|
||||
|
||||
case '|':
|
||||
if (p->word[1] != '|')
|
||||
continue;
|
||||
if (l == 0) {
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
t->t_dtyp = NODE_OR;
|
||||
t->t_dcar = syn1b(p1, p, flags);
|
||||
t->t_dcdr = syn1a(p->next, p2, flags);
|
||||
t->t_dflg = 0;
|
||||
return (t);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return (syn1b(p1, p2, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* syn1b
|
||||
* syn2
|
||||
* syn2 && syn1b
|
||||
*/
|
||||
static struct command *
|
||||
syn1b(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p;
|
||||
struct command *t;
|
||||
int l = 0;
|
||||
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
continue;
|
||||
|
||||
case '&':
|
||||
if (p->word[1] == '&' && l == 0) {
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
t->t_dtyp = NODE_AND;
|
||||
t->t_dcar = syn2(p1, p, flags);
|
||||
t->t_dcdr = syn1b(p->next, p2, flags);
|
||||
t->t_dflg = 0;
|
||||
return (t);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return (syn2(p1, p2, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* syn2
|
||||
* syn3
|
||||
* syn3 | syn2
|
||||
* syn3 |& syn2
|
||||
*/
|
||||
static struct command *
|
||||
syn2(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p, *pn;
|
||||
struct command *t;
|
||||
int l = 0;
|
||||
int f;
|
||||
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
continue;
|
||||
|
||||
case '|':
|
||||
if (l != 0)
|
||||
continue;
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
f = flags | POUT;
|
||||
pn = p->next;
|
||||
if (pn != p2 && pn->word[0] == '&') {
|
||||
f |= PERR;
|
||||
t->t_dflg |= F_STDERR;
|
||||
}
|
||||
t->t_dtyp = NODE_PIPE;
|
||||
t->t_dcar = syn3(p1, p, f);
|
||||
if (pn != p2 && pn->word[0] == '&')
|
||||
p = pn;
|
||||
t->t_dcdr = syn2(p->next, p2, flags | PIN);
|
||||
return (t);
|
||||
}
|
||||
return (syn3(p1, p2, flags));
|
||||
}
|
||||
|
||||
static char RELPAR[] = {'<', '>', '(', ')', '\0'};
|
||||
|
||||
/*
|
||||
* syn3
|
||||
* ( syn0 ) [ < in ] [ > out ]
|
||||
* word word* [ < in ] [ > out ]
|
||||
* KEYWORD ( word* ) word* [ < in ] [ > out ]
|
||||
*
|
||||
* KEYWORD = (@ exit foreach if set switch test while)
|
||||
*/
|
||||
static struct command *
|
||||
syn3(p1, p2, flags)
|
||||
struct wordent *p1, *p2;
|
||||
int flags;
|
||||
{
|
||||
struct wordent *p;
|
||||
struct wordent *lp, *rp;
|
||||
struct command *t;
|
||||
int l;
|
||||
Char **av;
|
||||
int n, c;
|
||||
bool specp = 0;
|
||||
|
||||
if (p1 != p2) {
|
||||
p = p1;
|
||||
again:
|
||||
switch (srchx(p->word)) {
|
||||
|
||||
case T_ELSE:
|
||||
p = p->next;
|
||||
if (p != p2)
|
||||
goto again;
|
||||
break;
|
||||
|
||||
case T_EXIT:
|
||||
case T_FOREACH:
|
||||
case T_IF:
|
||||
case T_LET:
|
||||
case T_SET:
|
||||
case T_SWITCH:
|
||||
case T_WHILE:
|
||||
specp = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
n = 0;
|
||||
l = 0;
|
||||
for (p = p1; p != p2; p = p->next)
|
||||
switch (p->word[0]) {
|
||||
|
||||
case '(':
|
||||
if (specp)
|
||||
n++;
|
||||
l++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
if (specp)
|
||||
n++;
|
||||
l--;
|
||||
continue;
|
||||
|
||||
case '>':
|
||||
case '<':
|
||||
if (l != 0) {
|
||||
if (specp)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if (p->next == p2)
|
||||
continue;
|
||||
if (any(RELPAR, p->next->word[0]))
|
||||
continue;
|
||||
n--;
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (!specp && l != 0)
|
||||
continue;
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
t = (struct command *) xcalloc(1, sizeof(*t));
|
||||
av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
|
||||
t->t_dcom = av;
|
||||
n = 0;
|
||||
if (p2->word[0] == ')')
|
||||
t->t_dflg = F_NOFORK;
|
||||
lp = 0;
|
||||
rp = 0;
|
||||
l = 0;
|
||||
for (p = p1; p != p2; p = p->next) {
|
||||
c = p->word[0];
|
||||
switch (c) {
|
||||
|
||||
case '(':
|
||||
if (l == 0) {
|
||||
if (lp != 0 && !specp)
|
||||
seterror(ERR_BADPLP);
|
||||
lp = p->next;
|
||||
}
|
||||
l++;
|
||||
goto savep;
|
||||
|
||||
case ')':
|
||||
l--;
|
||||
if (l == 0)
|
||||
rp = p;
|
||||
goto savep;
|
||||
|
||||
case '>':
|
||||
if (l != 0)
|
||||
goto savep;
|
||||
if (p->word[1] == '>')
|
||||
t->t_dflg |= F_APPEND;
|
||||
if (p->next != p2 && eq(p->next->word, STRand)) {
|
||||
t->t_dflg |= F_STDERR, p = p->next;
|
||||
if (flags & (POUT | PERR)) {
|
||||
seterror(ERR_OUTRED);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (p->next != p2 && eq(p->next->word, STRbang))
|
||||
t->t_dflg |= F_OVERWRITE, p = p->next;
|
||||
if (p->next == p2) {
|
||||
seterror(ERR_MISRED);
|
||||
continue;
|
||||
}
|
||||
p = p->next;
|
||||
if (any(RELPAR, p->word[0])) {
|
||||
seterror(ERR_MISRED);
|
||||
continue;
|
||||
}
|
||||
if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
|
||||
seterror(ERR_OUTRED);
|
||||
else
|
||||
t->t_drit = Strsave(p->word);
|
||||
continue;
|
||||
|
||||
case '<':
|
||||
if (l != 0)
|
||||
goto savep;
|
||||
if (p->word[1] == '<')
|
||||
t->t_dflg |= F_READ;
|
||||
if (p->next == p2) {
|
||||
seterror(ERR_MISRED);
|
||||
continue;
|
||||
}
|
||||
p = p->next;
|
||||
if (any(RELPAR, p->word[0])) {
|
||||
seterror(ERR_MISRED);
|
||||
continue;
|
||||
}
|
||||
if ((flags & PHERE) && (t->t_dflg & F_READ))
|
||||
seterror(ERR_REDPAR);
|
||||
else if ((flags & PIN) || t->t_dlef)
|
||||
seterror(ERR_INRED);
|
||||
else
|
||||
t->t_dlef = Strsave(p->word);
|
||||
continue;
|
||||
|
||||
savep:
|
||||
if (!specp)
|
||||
continue;
|
||||
default:
|
||||
if (l != 0 && !specp)
|
||||
continue;
|
||||
if (seterr == 0)
|
||||
av[n] = Strsave(p->word);
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (lp != 0 && !specp) {
|
||||
if (n != 0)
|
||||
seterror(ERR_BADPLPS);
|
||||
t->t_dtyp = NODE_PAREN;
|
||||
t->t_dspr = syn0(lp, rp, PHERE);
|
||||
}
|
||||
else {
|
||||
if (n == 0)
|
||||
seterror(ERR_NULLCOM);
|
||||
t->t_dtyp = NODE_COMMAND;
|
||||
}
|
||||
return (t);
|
||||
}
|
||||
|
||||
void
|
||||
freesyn(t)
|
||||
struct command *t;
|
||||
{
|
||||
Char **v;
|
||||
|
||||
if (t == 0)
|
||||
return;
|
||||
switch (t->t_dtyp) {
|
||||
|
||||
case NODE_COMMAND:
|
||||
for (v = t->t_dcom; *v; v++)
|
||||
xfree((ptr_t) * v);
|
||||
xfree((ptr_t) (t->t_dcom));
|
||||
xfree((ptr_t) t->t_dlef);
|
||||
xfree((ptr_t) t->t_drit);
|
||||
break;
|
||||
case NODE_PAREN:
|
||||
freesyn(t->t_dspr);
|
||||
xfree((ptr_t) t->t_dlef);
|
||||
xfree((ptr_t) t->t_drit);
|
||||
break;
|
||||
|
||||
case NODE_AND:
|
||||
case NODE_OR:
|
||||
case NODE_PIPE:
|
||||
case NODE_LIST:
|
||||
freesyn(t->t_dcar), freesyn(t->t_dcdr);
|
||||
break;
|
||||
}
|
||||
xfree((ptr_t) t);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define _PATH_BIN "/bin"
|
||||
#define _PATH_DOTCSHRC "/etc/csh.cshrc"
|
||||
#define _PATH_DOTLOGIN "/etc/csh.login"
|
||||
#define _PATH_DOTLOGOUT "/etc/csh.logout"
|
||||
#define _PATH_LOGIN "/usr/bin/login"
|
||||
#define _PATH_USRBIN "/usr/bin"
|
1362
bin/csh/proc.c
1362
bin/csh/proc.c
File diff suppressed because it is too large
Load Diff
102
bin/csh/proc.h
102
bin/csh/proc.h
@ -1,102 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)proc.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure for each process the shell knows about:
|
||||
* allocated and filled by pcreate.
|
||||
* flushed by pflush; freeing always happens at top level
|
||||
* so the interrupt level has less to worry about.
|
||||
* processes are related to "friends" when in a pipeline;
|
||||
* p_friends links makes a circular list of such jobs
|
||||
*/
|
||||
struct process {
|
||||
struct process *p_next; /* next in global "proclist" */
|
||||
struct process *p_friends; /* next in job list (or self) */
|
||||
struct directory *p_cwd; /* cwd of the job (only in head) */
|
||||
short unsigned p_flags; /* various job status flags */
|
||||
char p_reason; /* reason for entering this state */
|
||||
int p_index; /* shorthand job index */
|
||||
int p_pid;
|
||||
int p_jobid; /* pid of job leader */
|
||||
/* if a job is stopped/background p_jobid gives its pgrp */
|
||||
struct timeval p_btime; /* begin time */
|
||||
struct timeval p_etime; /* end time */
|
||||
struct rusage p_rusage;
|
||||
Char *p_command; /* first PMAXLEN chars of command */
|
||||
};
|
||||
|
||||
/* flag values for p_flags */
|
||||
#define PRUNNING (1<<0) /* running */
|
||||
#define PSTOPPED (1<<1) /* stopped */
|
||||
#define PNEXITED (1<<2) /* normally exited */
|
||||
#define PAEXITED (1<<3) /* abnormally exited */
|
||||
#define PSIGNALED (1<<4) /* terminated by a signal != SIGINT */
|
||||
|
||||
#define PALLSTATES (PRUNNING|PSTOPPED|PNEXITED|PAEXITED|PSIGNALED|PINTERRUPTED)
|
||||
#define PNOTIFY (1<<5) /* notify async when done */
|
||||
#define PTIME (1<<6) /* job times should be printed */
|
||||
#define PAWAITED (1<<7) /* top level is waiting for it */
|
||||
#define PFOREGND (1<<8) /* started in shells pgrp */
|
||||
#define PDUMPED (1<<9) /* process dumped core */
|
||||
#define PERR (1<<10) /* diagnostic output also piped out */
|
||||
#define PPOU (1<<11) /* piped output */
|
||||
#define PREPORTED (1<<12) /* status has been reported */
|
||||
#define PINTERRUPTED (1<<13) /* job stopped via interrupt signal */
|
||||
#define PPTIME (1<<14) /* time individual process */
|
||||
#define PNEEDNOTE (1<<15) /* notify as soon as practical */
|
||||
|
||||
#define PMAXLEN 80
|
||||
|
||||
/* defines for arguments to pprint */
|
||||
#define NUMBER 01
|
||||
#define NAME 02
|
||||
#define REASON 04
|
||||
#define AMPERSAND 010
|
||||
#define FANCY 020
|
||||
#define SHELLDIR 040 /* print shell's dir if not the same */
|
||||
#define JOBDIR 0100 /* print job's dir if not the same */
|
||||
#define AREASON 0200
|
||||
|
||||
struct process proclist; /* list head of all processes */
|
||||
bool pnoprocesses; /* pchild found nothing to wait for */
|
||||
|
||||
struct process *pholdjob; /* one level stack of current jobs */
|
||||
|
||||
struct process *pcurrjob; /* current job */
|
||||
struct process *pcurrent; /* current job in table */
|
||||
struct process *pprevious; /* previous job in table */
|
||||
|
||||
int pmaxindex; /* current maximum job index */
|
650
bin/csh/sem.c
650
bin/csh/sem.c
@ -1,650 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)sem.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "proc.h"
|
||||
#include "extern.h"
|
||||
|
||||
static void vffree __P((int));
|
||||
static Char *splicepipe __P((struct command *t, Char *));
|
||||
static void doio __P((struct command *t, int *, int *));
|
||||
static void chkclob __P((char *));
|
||||
|
||||
void
|
||||
execute(t, wanttty, pipein, pipeout)
|
||||
struct command *t;
|
||||
int wanttty, *pipein, *pipeout;
|
||||
{
|
||||
bool forked = 0;
|
||||
struct biltins *bifunc;
|
||||
int pid = 0;
|
||||
int pv[2];
|
||||
|
||||
static int csigmask;
|
||||
|
||||
static int ocsigmask;
|
||||
static int onosigchld = 0;
|
||||
static int nosigchld = 0;
|
||||
|
||||
UNREGISTER(forked);
|
||||
UNREGISTER(bifunc);
|
||||
UNREGISTER(wanttty);
|
||||
|
||||
if (t == 0)
|
||||
return;
|
||||
|
||||
if (t->t_dflg & F_AMPERSAND)
|
||||
wanttty = 0;
|
||||
switch (t->t_dtyp) {
|
||||
|
||||
case NODE_COMMAND:
|
||||
if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
|
||||
(void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
|
||||
if ((t->t_dflg & F_REPEAT) == 0)
|
||||
Dfix(t); /* $ " ' \ */
|
||||
if (t->t_dcom[0] == 0)
|
||||
return;
|
||||
/* fall into... */
|
||||
|
||||
case NODE_PAREN:
|
||||
if (t->t_dflg & F_PIPEOUT)
|
||||
mypipe(pipeout);
|
||||
/*
|
||||
* Must do << early so parent will know where input pointer should be.
|
||||
* If noexec then this is all we do.
|
||||
*/
|
||||
if (t->t_dflg & F_READ) {
|
||||
(void) close(0);
|
||||
heredoc(t->t_dlef);
|
||||
if (noexec)
|
||||
(void) close(0);
|
||||
}
|
||||
|
||||
set(STRstatus, Strsave(STR0));
|
||||
|
||||
/*
|
||||
* This mess is the necessary kludge to handle the prefix builtins:
|
||||
* nice, nohup, time. These commands can also be used by themselves,
|
||||
* and this is not handled here. This will also work when loops are
|
||||
* parsed.
|
||||
*/
|
||||
while (t->t_dtyp == NODE_COMMAND)
|
||||
if (eq(t->t_dcom[0], STRnice))
|
||||
if (t->t_dcom[1])
|
||||
if (strchr("+-", t->t_dcom[1][0]))
|
||||
if (t->t_dcom[2]) {
|
||||
setname("nice");
|
||||
t->t_nice =
|
||||
getn(t->t_dcom[1]);
|
||||
lshift(t->t_dcom, 2);
|
||||
t->t_dflg |= F_NICE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
else {
|
||||
t->t_nice = 4;
|
||||
lshift(t->t_dcom, 1);
|
||||
t->t_dflg |= F_NICE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
else if (eq(t->t_dcom[0], STRnohup))
|
||||
if (t->t_dcom[1]) {
|
||||
t->t_dflg |= F_NOHUP;
|
||||
lshift(t->t_dcom, 1);
|
||||
}
|
||||
else
|
||||
break;
|
||||
else if (eq(t->t_dcom[0], STRtime))
|
||||
if (t->t_dcom[1]) {
|
||||
t->t_dflg |= F_TIME;
|
||||
lshift(t->t_dcom, 1);
|
||||
}
|
||||
else
|
||||
break;
|
||||
else
|
||||
break;
|
||||
|
||||
/* is it a command */
|
||||
if (t->t_dtyp == NODE_COMMAND) {
|
||||
/*
|
||||
* Check if we have a builtin function and remember which one.
|
||||
*/
|
||||
bifunc = isbfunc(t);
|
||||
if (noexec) {
|
||||
/*
|
||||
* Continue for builtins that are part of the scripting language
|
||||
*/
|
||||
if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin &&
|
||||
bifunc->bfunct != doelse && bifunc->bfunct != doend &&
|
||||
bifunc->bfunct != doforeach && bifunc->bfunct != dogoto &&
|
||||
bifunc->bfunct != doif && bifunc->bfunct != dorepeat &&
|
||||
bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch &&
|
||||
bifunc->bfunct != dowhile && bifunc->bfunct != dozip)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* not a command */
|
||||
bifunc = NULL;
|
||||
if (noexec)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We fork only if we are timed, or are not the end of a parenthesized
|
||||
* list and not a simple builtin function. Simple meaning one that is
|
||||
* not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
|
||||
* fork in some of these cases.
|
||||
*/
|
||||
/*
|
||||
* Prevent forking cd, pushd, popd, chdir cause this will cause the
|
||||
* shell not to change dir!
|
||||
*/
|
||||
if (bifunc && (bifunc->bfunct == dochngd ||
|
||||
bifunc->bfunct == dopushd ||
|
||||
bifunc->bfunct == dopopd))
|
||||
t->t_dflg &= ~(F_NICE);
|
||||
if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
|
||||
(!bifunc || t->t_dflg &
|
||||
(F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
|
||||
/*
|
||||
* We have to fork for eval too.
|
||||
*/
|
||||
(bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 &&
|
||||
bifunc->bfunct == doeval)) {
|
||||
if (t->t_dtyp == NODE_PAREN ||
|
||||
t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
|
||||
forked++;
|
||||
/*
|
||||
* We need to block SIGCHLD here, so that if the process does
|
||||
* not die before we can set the process group
|
||||
*/
|
||||
if (wanttty >= 0 && !nosigchld) {
|
||||
csigmask = sigblock(sigmask(SIGCHLD));
|
||||
nosigchld = 1;
|
||||
}
|
||||
|
||||
pid = pfork(t, wanttty);
|
||||
if (pid == 0 && nosigchld) {
|
||||
(void) sigsetmask(csigmask);
|
||||
nosigchld = 0;
|
||||
}
|
||||
else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
|
||||
backpid = pid;
|
||||
|
||||
}
|
||||
else {
|
||||
int ochild, osetintr, ohaderr, odidfds;
|
||||
int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
|
||||
int omask;
|
||||
|
||||
/*
|
||||
* Prepare for the vfork by saving everything that the child
|
||||
* corrupts before it exec's. Note that in some signal
|
||||
* implementations which keep the signal info in user space
|
||||
* (e.g. Sun's) it will also be necessary to save and restore
|
||||
* the current sigvec's for the signals the child touches
|
||||
* before it exec's.
|
||||
*/
|
||||
if (wanttty >= 0 && !nosigchld && !noexec) {
|
||||
csigmask = sigblock(sigmask(SIGCHLD));
|
||||
nosigchld = 1;
|
||||
}
|
||||
omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT));
|
||||
ochild = child;
|
||||
osetintr = setintr;
|
||||
ohaderr = haderr;
|
||||
odidfds = didfds;
|
||||
oSHIN = SHIN;
|
||||
oSHOUT = SHOUT;
|
||||
oSHERR = SHERR;
|
||||
oOLDSTD = OLDSTD;
|
||||
otpgrp = tpgrp;
|
||||
ocsigmask = csigmask;
|
||||
onosigchld = nosigchld;
|
||||
Vsav = Vdp = 0;
|
||||
Vexpath = 0;
|
||||
Vt = 0;
|
||||
pid = vfork();
|
||||
|
||||
if (pid < 0) {
|
||||
(void) sigsetmask(omask);
|
||||
stderror(ERR_NOPROC);
|
||||
}
|
||||
forked++;
|
||||
if (pid) { /* parent */
|
||||
child = ochild;
|
||||
setintr = osetintr;
|
||||
haderr = ohaderr;
|
||||
didfds = odidfds;
|
||||
SHIN = oSHIN;
|
||||
SHOUT = oSHOUT;
|
||||
SHERR = oSHERR;
|
||||
OLDSTD = oOLDSTD;
|
||||
tpgrp = otpgrp;
|
||||
csigmask = ocsigmask;
|
||||
nosigchld = onosigchld;
|
||||
|
||||
xfree((ptr_t) Vsav);
|
||||
Vsav = 0;
|
||||
xfree((ptr_t) Vdp);
|
||||
Vdp = 0;
|
||||
xfree((ptr_t) Vexpath);
|
||||
Vexpath = 0;
|
||||
blkfree((Char **) Vt);
|
||||
Vt = 0;
|
||||
/* this is from pfork() */
|
||||
palloc(pid, t);
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
else { /* child */
|
||||
/* this is from pfork() */
|
||||
int pgrp;
|
||||
bool ignint = 0;
|
||||
|
||||
if (nosigchld) {
|
||||
(void) sigsetmask(csigmask);
|
||||
nosigchld = 0;
|
||||
}
|
||||
|
||||
if (setintr)
|
||||
ignint =
|
||||
(tpgrp == -1 &&
|
||||
(t->t_dflg & F_NOINTERRUPT))
|
||||
|| (gointr && eq(gointr, STRminus));
|
||||
pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
|
||||
child++;
|
||||
if (setintr) {
|
||||
setintr = 0;
|
||||
if (ignint) {
|
||||
(void) signal(SIGINT, SIG_IGN);
|
||||
(void) signal(SIGQUIT, SIG_IGN);
|
||||
}
|
||||
else {
|
||||
(void) signal(SIGINT, vffree);
|
||||
(void) signal(SIGQUIT, SIG_DFL);
|
||||
}
|
||||
|
||||
if (wanttty >= 0) {
|
||||
(void) signal(SIGTSTP, SIG_DFL);
|
||||
(void) signal(SIGTTIN, SIG_DFL);
|
||||
(void) signal(SIGTTOU, SIG_DFL);
|
||||
}
|
||||
|
||||
(void) signal(SIGTERM, parterm);
|
||||
}
|
||||
else if (tpgrp == -1 &&
|
||||
(t->t_dflg & F_NOINTERRUPT)) {
|
||||
(void) signal(SIGINT, SIG_IGN);
|
||||
(void) signal(SIGQUIT, SIG_IGN);
|
||||
}
|
||||
|
||||
pgetty(wanttty, pgrp);
|
||||
if (t->t_dflg & F_NOHUP)
|
||||
(void) signal(SIGHUP, SIG_IGN);
|
||||
if (t->t_dflg & F_NICE)
|
||||
(void) setpriority(PRIO_PROCESS, 0, t->t_nice);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (pid != 0) {
|
||||
/*
|
||||
* It would be better if we could wait for the whole job when we
|
||||
* knew the last process had been started. Pwait, in fact, does
|
||||
* wait for the whole job anyway, but this test doesn't really
|
||||
* express our intentions.
|
||||
*/
|
||||
if (didfds == 0 && t->t_dflg & F_PIPEIN) {
|
||||
(void) close(pipein[0]);
|
||||
(void) close(pipein[1]);
|
||||
}
|
||||
if ((t->t_dflg & F_PIPEOUT) == 0) {
|
||||
if (nosigchld) {
|
||||
(void) sigsetmask(csigmask);
|
||||
nosigchld = 0;
|
||||
}
|
||||
if ((t->t_dflg & F_AMPERSAND) == 0)
|
||||
pwait();
|
||||
}
|
||||
break;
|
||||
}
|
||||
doio(t, pipein, pipeout);
|
||||
if (t->t_dflg & F_PIPEOUT) {
|
||||
(void) close(pipeout[0]);
|
||||
(void) close(pipeout[1]);
|
||||
}
|
||||
/*
|
||||
* Perform a builtin function. If we are not forked, arrange for
|
||||
* possible stopping
|
||||
*/
|
||||
if (bifunc) {
|
||||
func(t, bifunc);
|
||||
if (forked)
|
||||
exitstat();
|
||||
break;
|
||||
}
|
||||
if (t->t_dtyp != NODE_PAREN) {
|
||||
doexec(NULL, t);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
/*
|
||||
* For () commands must put new 0,1,2 in FSH* and recurse
|
||||
*/
|
||||
OLDSTD = dcopy(0, FOLDSTD);
|
||||
SHOUT = dcopy(1, FSHOUT);
|
||||
SHERR = dcopy(2, FSHERR);
|
||||
(void) close(SHIN);
|
||||
SHIN = -1;
|
||||
didfds = 0;
|
||||
wanttty = -1;
|
||||
t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
|
||||
execute(t->t_dspr, wanttty, NULL, NULL);
|
||||
exitstat();
|
||||
|
||||
case NODE_PIPE:
|
||||
t->t_dcar->t_dflg |= F_PIPEOUT |
|
||||
(t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
|
||||
execute(t->t_dcar, wanttty, pipein, pv);
|
||||
t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
|
||||
(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
|
||||
if (wanttty > 0)
|
||||
wanttty = 0; /* got tty already */
|
||||
execute(t->t_dcdr, wanttty, pv, pipeout);
|
||||
break;
|
||||
|
||||
case NODE_LIST:
|
||||
if (t->t_dcar) {
|
||||
t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
|
||||
execute(t->t_dcar, wanttty, NULL, NULL);
|
||||
/*
|
||||
* In strange case of A&B make a new job after A
|
||||
*/
|
||||
if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
|
||||
(t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
|
||||
pendjob();
|
||||
}
|
||||
if (t->t_dcdr) {
|
||||
t->t_dcdr->t_dflg |= t->t_dflg &
|
||||
(F_NOFORK | F_NOINTERRUPT);
|
||||
execute(t->t_dcdr, wanttty, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_OR:
|
||||
case NODE_AND:
|
||||
if (t->t_dcar) {
|
||||
t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
|
||||
execute(t->t_dcar, wanttty, NULL, NULL);
|
||||
if ((getn(value(STRstatus)) == 0) !=
|
||||
(t->t_dtyp == NODE_AND))
|
||||
return;
|
||||
}
|
||||
if (t->t_dcdr) {
|
||||
t->t_dcdr->t_dflg |= t->t_dflg &
|
||||
(F_NOFORK | F_NOINTERRUPT);
|
||||
execute(t->t_dcdr, wanttty, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Fall through for all breaks from switch
|
||||
*
|
||||
* If there will be no more executions of this command, flush all file
|
||||
* descriptors. Places that turn on the F_REPEAT bit are responsible for
|
||||
* doing donefds after the last re-execution
|
||||
*/
|
||||
if (didfds && !(t->t_dflg & F_REPEAT))
|
||||
donefds();
|
||||
}
|
||||
|
||||
static void
|
||||
vffree(i)
|
||||
int i;
|
||||
{
|
||||
Char **v;
|
||||
|
||||
if ((v = gargv) != NULL) {
|
||||
gargv = 0;
|
||||
xfree((ptr_t) v);
|
||||
}
|
||||
if ((v = pargv) != NULL) {
|
||||
pargv = 0;
|
||||
xfree((ptr_t) v);
|
||||
}
|
||||
_exit(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand and glob the words after an i/o redirection.
|
||||
* If more than one word is generated, then update the command vector.
|
||||
*
|
||||
* This is done differently in all the shells:
|
||||
* 1. in the Bourne shell and ksh globbing is not performed
|
||||
* 2. Bash/csh say ambiguous
|
||||
* 3. zsh does i/o to/from all the files
|
||||
* 4. itcsh concatenates the words.
|
||||
*
|
||||
* I don't know what is best to do. I think that Ambiguous is better
|
||||
* than restructuring the command vector, because the user can get
|
||||
* unexpected results. In any case, the command vector restructuring
|
||||
* code is present and the user can choose it by setting noambiguous
|
||||
*/
|
||||
static Char *
|
||||
splicepipe(t, cp)
|
||||
struct command *t;
|
||||
Char *cp; /* word after < or > */
|
||||
{
|
||||
Char *blk[2];
|
||||
|
||||
if (adrof(STRnoambiguous)) {
|
||||
Char **pv;
|
||||
|
||||
blk[0] = Dfix1(cp); /* expand $ */
|
||||
blk[1] = NULL;
|
||||
|
||||
gflag = 0, tglob(blk);
|
||||
if (gflag) {
|
||||
pv = globall(blk);
|
||||
if (pv == NULL) {
|
||||
setname(vis_str(blk[0]));
|
||||
xfree((ptr_t) blk[0]);
|
||||
stderror(ERR_NAME | ERR_NOMATCH);
|
||||
}
|
||||
gargv = NULL;
|
||||
if (pv[1] != NULL) { /* we need to fix the command vector */
|
||||
Char **av = blkspl(t->t_dcom, &pv[1]);
|
||||
xfree((ptr_t) t->t_dcom);
|
||||
t->t_dcom = av;
|
||||
}
|
||||
xfree((ptr_t) blk[0]);
|
||||
blk[0] = pv[0];
|
||||
xfree((ptr_t) pv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR);
|
||||
xfree((ptr_t) blk[1]);
|
||||
}
|
||||
return(blk[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform io redirection.
|
||||
* We may or maynot be forked here.
|
||||
*/
|
||||
static void
|
||||
doio(t, pipein, pipeout)
|
||||
struct command *t;
|
||||
int *pipein, *pipeout;
|
||||
{
|
||||
int fd;
|
||||
Char *cp;
|
||||
int flags = t->t_dflg;
|
||||
|
||||
if (didfds || (flags & F_REPEAT))
|
||||
return;
|
||||
if ((flags & F_READ) == 0) {/* F_READ already done */
|
||||
if (t->t_dlef) {
|
||||
char tmp[MAXPATHLEN+1];
|
||||
|
||||
/*
|
||||
* so < /dev/std{in,out,err} work
|
||||
*/
|
||||
(void) dcopy(SHIN, 0);
|
||||
(void) dcopy(SHOUT, 1);
|
||||
(void) dcopy(SHERR, 2);
|
||||
cp = splicepipe(t, t->t_dlef);
|
||||
(void) strncpy(tmp, short2str(cp), MAXPATHLEN);
|
||||
tmp[MAXPATHLEN] = '\0';
|
||||
xfree((ptr_t) cp);
|
||||
if ((fd = open(tmp, O_RDONLY)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
(void) dmove(fd, 0);
|
||||
}
|
||||
else if (flags & F_PIPEIN) {
|
||||
(void) close(0);
|
||||
(void) dup(pipein[0]);
|
||||
(void) close(pipein[0]);
|
||||
(void) close(pipein[1]);
|
||||
}
|
||||
else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
|
||||
(void) close(0);
|
||||
(void) open(_PATH_DEVNULL, O_RDONLY);
|
||||
}
|
||||
else {
|
||||
(void) close(0);
|
||||
(void) dup(OLDSTD);
|
||||
(void) ioctl(0, FIONCLEX, NULL);
|
||||
}
|
||||
}
|
||||
if (t->t_drit) {
|
||||
char tmp[MAXPATHLEN+1];
|
||||
|
||||
cp = splicepipe(t, t->t_drit);
|
||||
(void) strncpy(tmp, short2str(cp), MAXPATHLEN);
|
||||
tmp[MAXPATHLEN] = '\0';
|
||||
xfree((ptr_t) cp);
|
||||
/*
|
||||
* so > /dev/std{out,err} work
|
||||
*/
|
||||
(void) dcopy(SHOUT, 1);
|
||||
(void) dcopy(SHERR, 2);
|
||||
if ((flags & F_APPEND) &&
|
||||
#ifdef O_APPEND
|
||||
(fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
|
||||
#else
|
||||
(fd = open(tmp, O_WRONLY)) >= 0)
|
||||
(void) lseek(1, (off_t) 0, L_XTND);
|
||||
#endif
|
||||
else {
|
||||
if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
|
||||
if (flags & F_APPEND)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
chkclob(tmp);
|
||||
}
|
||||
if ((fd = creat(tmp, 0666)) < 0)
|
||||
stderror(ERR_SYSTEM, tmp, strerror(errno));
|
||||
}
|
||||
(void) dmove(fd, 1);
|
||||
}
|
||||
else if (flags & F_PIPEOUT) {
|
||||
(void) close(1);
|
||||
(void) dup(pipeout[1]);
|
||||
}
|
||||
else {
|
||||
(void) close(1);
|
||||
(void) dup(SHOUT);
|
||||
(void) ioctl(1, FIONCLEX, NULL);
|
||||
}
|
||||
|
||||
(void) close(2);
|
||||
if (flags & F_STDERR) {
|
||||
(void) dup(1);
|
||||
}
|
||||
else {
|
||||
(void) dup(SHERR);
|
||||
(void) ioctl(2, FIONCLEX, NULL);
|
||||
}
|
||||
didfds = 1;
|
||||
}
|
||||
|
||||
void
|
||||
mypipe(pv)
|
||||
int *pv;
|
||||
{
|
||||
|
||||
if (pipe(pv) < 0)
|
||||
goto oops;
|
||||
pv[0] = dmove(pv[0], -1);
|
||||
pv[1] = dmove(pv[1], -1);
|
||||
if (pv[0] >= 0 && pv[1] >= 0)
|
||||
return;
|
||||
oops:
|
||||
stderror(ERR_PIPE);
|
||||
}
|
||||
|
||||
static void
|
||||
chkclob(cp)
|
||||
char *cp;
|
||||
{
|
||||
struct stat stb;
|
||||
|
||||
if (stat(cp, &stb) < 0)
|
||||
return;
|
||||
if (S_ISCHR(stb.st_mode))
|
||||
return;
|
||||
stderror(ERR_EXISTS, cp);
|
||||
}
|
847
bin/csh/set.c
847
bin/csh/set.c
@ -1,847 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)set.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
static Char *getinx __P((Char *, int *));
|
||||
static void asx __P((Char *, int, Char *));
|
||||
static struct varent
|
||||
*getvx __P((Char *, int));
|
||||
static Char *xset __P((Char *, Char ***));
|
||||
static Char *operate __P((int, Char *, Char *));
|
||||
static void putn1 __P((int));
|
||||
static struct varent
|
||||
*madrof __P((Char *, struct varent *));
|
||||
static void unsetv1 __P((struct varent *));
|
||||
static void exportpath __P((Char **));
|
||||
static void balance __P((struct varent *, int, int));
|
||||
|
||||
|
||||
/*
|
||||
* C Shell
|
||||
*/
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
doset(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
Char *p;
|
||||
Char *vp, op;
|
||||
Char **vecp;
|
||||
bool hadsub;
|
||||
int subscr;
|
||||
|
||||
v++;
|
||||
p = *v++;
|
||||
if (p == 0) {
|
||||
prvars();
|
||||
return;
|
||||
}
|
||||
do {
|
||||
hadsub = 0;
|
||||
vp = p;
|
||||
if (letter(*p))
|
||||
for (; alnum(*p); p++)
|
||||
continue;
|
||||
if (vp == p || !letter(*vp))
|
||||
stderror(ERR_NAME | ERR_VARBEGIN);
|
||||
if ((p - vp) > MAXVARLEN) {
|
||||
stderror(ERR_NAME | ERR_VARTOOLONG);
|
||||
return;
|
||||
}
|
||||
if (*p == '[') {
|
||||
hadsub++;
|
||||
p = getinx(p, &subscr);
|
||||
}
|
||||
if ((op = *p) != '\0') {
|
||||
*p++ = 0;
|
||||
if (*p == 0 && *v && **v == '(')
|
||||
p = *v++;
|
||||
}
|
||||
else if (*v && eq(*v, STRequal)) {
|
||||
op = '=', v++;
|
||||
if (*v)
|
||||
p = *v++;
|
||||
}
|
||||
if (op && op != '=')
|
||||
stderror(ERR_NAME | ERR_SYNTAX);
|
||||
if (eq(p, STRLparen)) {
|
||||
Char **e = v;
|
||||
|
||||
if (hadsub)
|
||||
stderror(ERR_NAME | ERR_SYNTAX);
|
||||
for (;;) {
|
||||
if (!*e)
|
||||
stderror(ERR_NAME | ERR_MISSING, ')');
|
||||
if (**e == ')')
|
||||
break;
|
||||
e++;
|
||||
}
|
||||
p = *e;
|
||||
*e = 0;
|
||||
vecp = saveblk(v);
|
||||
set1(vp, vecp, &shvhed);
|
||||
*e = p;
|
||||
v = e + 1;
|
||||
}
|
||||
else if (hadsub)
|
||||
asx(vp, subscr, Strsave(p));
|
||||
else
|
||||
set(vp, Strsave(p));
|
||||
if (eq(vp, STRpath)) {
|
||||
exportpath(adrof(STRpath)->vec);
|
||||
dohash(NULL, NULL);
|
||||
}
|
||||
else if (eq(vp, STRhistchars)) {
|
||||
Char *pn = value(STRhistchars);
|
||||
|
||||
HIST = *pn++;
|
||||
HISTSUB = *pn;
|
||||
}
|
||||
else if (eq(vp, STRuser)) {
|
||||
Setenv(STRUSER, value(vp));
|
||||
Setenv(STRLOGNAME, value(vp));
|
||||
}
|
||||
else if (eq(vp, STRwordchars)) {
|
||||
word_chars = value(vp);
|
||||
}
|
||||
else if (eq(vp, STRterm))
|
||||
Setenv(STRTERM, value(vp));
|
||||
else if (eq(vp, STRhome)) {
|
||||
Char *cp;
|
||||
|
||||
cp = Strsave(value(vp)); /* get the old value back */
|
||||
|
||||
/*
|
||||
* convert to canonical pathname (possibly resolving symlinks)
|
||||
*/
|
||||
cp = dcanon(cp, cp);
|
||||
|
||||
set(vp, Strsave(cp)); /* have to save the new val */
|
||||
|
||||
/* and now mirror home with HOME */
|
||||
Setenv(STRHOME, cp);
|
||||
/* fix directory stack for new tilde home */
|
||||
dtilde();
|
||||
xfree((ptr_t) cp);
|
||||
}
|
||||
#ifdef FILEC
|
||||
else if (eq(vp, STRfilec))
|
||||
filec = 1;
|
||||
#endif
|
||||
} while ((p = *v++) != NULL);
|
||||
}
|
||||
|
||||
static Char *
|
||||
getinx(cp, ip)
|
||||
Char *cp;
|
||||
int *ip;
|
||||
{
|
||||
|
||||
*ip = 0;
|
||||
*cp++ = 0;
|
||||
while (*cp && Isdigit(*cp))
|
||||
*ip = *ip * 10 + *cp++ - '0';
|
||||
if (*cp++ != ']')
|
||||
stderror(ERR_NAME | ERR_SUBSCRIPT);
|
||||
return (cp);
|
||||
}
|
||||
|
||||
static void
|
||||
asx(vp, subscr, p)
|
||||
Char *vp;
|
||||
int subscr;
|
||||
Char *p;
|
||||
{
|
||||
struct varent *v = getvx(vp, subscr);
|
||||
|
||||
xfree((ptr_t) v->vec[subscr - 1]);
|
||||
v->vec[subscr - 1] = globone(p, G_APPEND);
|
||||
}
|
||||
|
||||
static struct varent *
|
||||
getvx(vp, subscr)
|
||||
Char *vp;
|
||||
int subscr;
|
||||
{
|
||||
struct varent *v = adrof(vp);
|
||||
|
||||
if (v == 0)
|
||||
udvar(vp);
|
||||
if (subscr < 1 || subscr > blklen(v->vec))
|
||||
stderror(ERR_NAME | ERR_RANGE);
|
||||
return (v);
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dolet(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
Char *p;
|
||||
Char *vp, c, op;
|
||||
bool hadsub;
|
||||
int subscr;
|
||||
|
||||
v++;
|
||||
p = *v++;
|
||||
if (p == 0) {
|
||||
prvars();
|
||||
return;
|
||||
}
|
||||
do {
|
||||
hadsub = 0;
|
||||
vp = p;
|
||||
if (letter(*p))
|
||||
for (; alnum(*p); p++)
|
||||
continue;
|
||||
if (vp == p || !letter(*vp))
|
||||
stderror(ERR_NAME | ERR_VARBEGIN);
|
||||
if ((p - vp) > MAXVARLEN)
|
||||
stderror(ERR_NAME | ERR_VARTOOLONG);
|
||||
if (*p == '[') {
|
||||
hadsub++;
|
||||
p = getinx(p, &subscr);
|
||||
}
|
||||
if (*p == 0 && *v)
|
||||
p = *v++;
|
||||
if ((op = *p) != '\0')
|
||||
*p++ = 0;
|
||||
else
|
||||
stderror(ERR_NAME | ERR_ASSIGN);
|
||||
|
||||
if (*p == '\0' && *v == NULL)
|
||||
stderror(ERR_NAME | ERR_ASSIGN);
|
||||
|
||||
vp = Strsave(vp);
|
||||
if (op == '=') {
|
||||
c = '=';
|
||||
p = xset(p, &v);
|
||||
}
|
||||
else {
|
||||
c = *p++;
|
||||
if (any("+-", c)) {
|
||||
if (c != op || *p)
|
||||
stderror(ERR_NAME | ERR_UNKNOWNOP);
|
||||
p = Strsave(STR1);
|
||||
}
|
||||
else {
|
||||
if (any("<>", op)) {
|
||||
if (c != op)
|
||||
stderror(ERR_NAME | ERR_UNKNOWNOP);
|
||||
c = *p++;
|
||||
stderror(ERR_NAME | ERR_SYNTAX);
|
||||
}
|
||||
if (c != '=')
|
||||
stderror(ERR_NAME | ERR_UNKNOWNOP);
|
||||
p = xset(p, &v);
|
||||
}
|
||||
}
|
||||
if (op == '=')
|
||||
if (hadsub)
|
||||
asx(vp, subscr, p);
|
||||
else
|
||||
set(vp, p);
|
||||
else if (hadsub) {
|
||||
struct varent *gv = getvx(vp, subscr);
|
||||
|
||||
asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
|
||||
}
|
||||
else
|
||||
set(vp, operate(op, value(vp), p));
|
||||
if (eq(vp, STRpath)) {
|
||||
exportpath(adrof(STRpath)->vec);
|
||||
dohash(NULL, NULL);
|
||||
}
|
||||
xfree((ptr_t) vp);
|
||||
if (c != '=')
|
||||
xfree((ptr_t) p);
|
||||
} while ((p = *v++) != NULL);
|
||||
}
|
||||
|
||||
static Char *
|
||||
xset(cp, vp)
|
||||
Char *cp, ***vp;
|
||||
{
|
||||
Char *dp;
|
||||
|
||||
if (*cp) {
|
||||
dp = Strsave(cp);
|
||||
--(*vp);
|
||||
xfree((ptr_t) ** vp);
|
||||
**vp = dp;
|
||||
}
|
||||
return (putn(expr(vp)));
|
||||
}
|
||||
|
||||
static Char *
|
||||
operate(op, vp, p)
|
||||
int op;
|
||||
Char *vp, *p;
|
||||
{
|
||||
Char opr[2];
|
||||
Char *vec[5];
|
||||
Char **v = vec;
|
||||
Char **vecp = v;
|
||||
int i;
|
||||
|
||||
if (op != '=') {
|
||||
if (*vp)
|
||||
*v++ = vp;
|
||||
opr[0] = op;
|
||||
opr[1] = 0;
|
||||
*v++ = opr;
|
||||
if (op == '<' || op == '>')
|
||||
*v++ = opr;
|
||||
}
|
||||
*v++ = p;
|
||||
*v++ = 0;
|
||||
i = expr(&vecp);
|
||||
if (*vecp)
|
||||
stderror(ERR_NAME | ERR_EXPRESSION);
|
||||
return (putn(i));
|
||||
}
|
||||
|
||||
static Char *putp;
|
||||
|
||||
Char *
|
||||
putn(n)
|
||||
int n;
|
||||
{
|
||||
int num;
|
||||
static Char number[15];
|
||||
|
||||
putp = number;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
*putp++ = '-';
|
||||
}
|
||||
num = 2; /* confuse lint */
|
||||
if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
|
||||
*putp++ = '3';
|
||||
n = 2768;
|
||||
#ifdef pdp11
|
||||
}
|
||||
#else
|
||||
}
|
||||
else {
|
||||
num = 4; /* confuse lint */
|
||||
if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
|
||||
*putp++ = '2';
|
||||
n = 147483648;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
putn1(n);
|
||||
*putp = 0;
|
||||
return (Strsave(number));
|
||||
}
|
||||
|
||||
static void
|
||||
putn1(n)
|
||||
int n;
|
||||
{
|
||||
if (n > 9)
|
||||
putn1(n / 10);
|
||||
*putp++ = n % 10 + '0';
|
||||
}
|
||||
|
||||
int
|
||||
getn(cp)
|
||||
Char *cp;
|
||||
{
|
||||
int n;
|
||||
int sign;
|
||||
|
||||
sign = 0;
|
||||
if (cp[0] == '+' && cp[1])
|
||||
cp++;
|
||||
if (*cp == '-') {
|
||||
sign++;
|
||||
cp++;
|
||||
if (!Isdigit(*cp))
|
||||
stderror(ERR_NAME | ERR_BADNUM);
|
||||
}
|
||||
n = 0;
|
||||
while (Isdigit(*cp))
|
||||
n = n * 10 + *cp++ - '0';
|
||||
if (*cp)
|
||||
stderror(ERR_NAME | ERR_BADNUM);
|
||||
return (sign ? -n : n);
|
||||
}
|
||||
|
||||
Char *
|
||||
value1(var, head)
|
||||
Char *var;
|
||||
struct varent *head;
|
||||
{
|
||||
struct varent *vp;
|
||||
|
||||
vp = adrof1(var, head);
|
||||
return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
|
||||
}
|
||||
|
||||
static struct varent *
|
||||
madrof(pat, vp)
|
||||
Char *pat;
|
||||
struct varent *vp;
|
||||
{
|
||||
struct varent *vp1;
|
||||
|
||||
for (; vp; vp = vp->v_right) {
|
||||
if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
|
||||
return vp1;
|
||||
if (Gmatch(vp->v_name, pat))
|
||||
return vp;
|
||||
}
|
||||
return vp;
|
||||
}
|
||||
|
||||
struct varent *
|
||||
adrof1(name, v)
|
||||
Char *name;
|
||||
struct varent *v;
|
||||
{
|
||||
int cmp;
|
||||
|
||||
v = v->v_left;
|
||||
while (v && ((cmp = *name - *v->v_name) ||
|
||||
(cmp = Strcmp(name, v->v_name))))
|
||||
if (cmp < 0)
|
||||
v = v->v_left;
|
||||
else
|
||||
v = v->v_right;
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller is responsible for putting value in a safe place
|
||||
*/
|
||||
void
|
||||
set(var, val)
|
||||
Char *var, *val;
|
||||
{
|
||||
Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
|
||||
|
||||
vec[0] = val;
|
||||
vec[1] = 0;
|
||||
set1(var, vec, &shvhed);
|
||||
}
|
||||
|
||||
void
|
||||
set1(var, vec, head)
|
||||
Char *var, **vec;
|
||||
struct varent *head;
|
||||
{
|
||||
Char **oldv = vec;
|
||||
|
||||
gflag = 0;
|
||||
tglob(oldv);
|
||||
if (gflag) {
|
||||
vec = globall(oldv);
|
||||
if (vec == 0) {
|
||||
blkfree(oldv);
|
||||
stderror(ERR_NAME | ERR_NOMATCH);
|
||||
return;
|
||||
}
|
||||
blkfree(oldv);
|
||||
gargv = 0;
|
||||
}
|
||||
setq(var, vec, head);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
setq(name, vec, p)
|
||||
Char *name, **vec;
|
||||
struct varent *p;
|
||||
{
|
||||
struct varent *c;
|
||||
int f;
|
||||
|
||||
f = 0; /* tree hangs off the header's left link */
|
||||
while ((c = p->v_link[f]) != NULL) {
|
||||
if ((f = *name - *c->v_name) == 0 &&
|
||||
(f = Strcmp(name, c->v_name)) == 0) {
|
||||
blkfree(c->vec);
|
||||
goto found;
|
||||
}
|
||||
p = c;
|
||||
f = f > 0;
|
||||
}
|
||||
p->v_link[f] = c = (struct varent *) xmalloc((size_t) sizeof(struct varent));
|
||||
c->v_name = Strsave(name);
|
||||
c->v_bal = 0;
|
||||
c->v_left = c->v_right = 0;
|
||||
c->v_parent = p;
|
||||
balance(p, f, 0);
|
||||
found:
|
||||
trim(c->vec = vec);
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
unset(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
unset1(v, &shvhed);
|
||||
#ifdef FILEC
|
||||
if (adrof(STRfilec) == 0)
|
||||
filec = 0;
|
||||
#endif
|
||||
if (adrof(STRhistchars) == 0) {
|
||||
HIST = '!';
|
||||
HISTSUB = '^';
|
||||
}
|
||||
if (adrof(STRwordchars) == 0)
|
||||
word_chars = STR_WORD_CHARS;
|
||||
}
|
||||
|
||||
void
|
||||
unset1(v, head)
|
||||
Char *v[];
|
||||
struct varent *head;
|
||||
{
|
||||
struct varent *vp;
|
||||
int cnt;
|
||||
|
||||
while (*++v) {
|
||||
cnt = 0;
|
||||
while ((vp = madrof(*v, head->v_left)) != NULL)
|
||||
unsetv1(vp), cnt++;
|
||||
if (cnt == 0)
|
||||
setname(vis_str(*v));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unsetv(var)
|
||||
Char *var;
|
||||
{
|
||||
struct varent *vp;
|
||||
|
||||
if ((vp = adrof1(var, &shvhed)) == 0)
|
||||
udvar(var);
|
||||
unsetv1(vp);
|
||||
}
|
||||
|
||||
static void
|
||||
unsetv1(p)
|
||||
struct varent *p;
|
||||
{
|
||||
struct varent *c, *pp;
|
||||
int f;
|
||||
|
||||
/*
|
||||
* Free associated memory first to avoid complications.
|
||||
*/
|
||||
blkfree(p->vec);
|
||||
xfree((ptr_t) p->v_name);
|
||||
/*
|
||||
* If p is missing one child, then we can move the other into where p is.
|
||||
* Otherwise, we find the predecessor of p, which is guaranteed to have no
|
||||
* right child, copy it into p, and move it's left child into it.
|
||||
*/
|
||||
if (p->v_right == 0)
|
||||
c = p->v_left;
|
||||
else if (p->v_left == 0)
|
||||
c = p->v_right;
|
||||
else {
|
||||
for (c = p->v_left; c->v_right; c = c->v_right)
|
||||
continue;
|
||||
p->v_name = c->v_name;
|
||||
p->vec = c->vec;
|
||||
p = c;
|
||||
c = p->v_left;
|
||||
}
|
||||
/*
|
||||
* Move c into where p is.
|
||||
*/
|
||||
pp = p->v_parent;
|
||||
f = pp->v_right == p;
|
||||
if ((pp->v_link[f] = c) != NULL)
|
||||
c->v_parent = pp;
|
||||
/*
|
||||
* Free the deleted node, and rebalance.
|
||||
*/
|
||||
xfree((ptr_t) p);
|
||||
balance(pp, f, 1);
|
||||
}
|
||||
|
||||
void
|
||||
setNS(cp)
|
||||
Char *cp;
|
||||
{
|
||||
set(cp, Strsave(STRNULL));
|
||||
}
|
||||
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
shift(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
struct varent *argv;
|
||||
Char *name;
|
||||
|
||||
v++;
|
||||
name = *v;
|
||||
if (name == 0)
|
||||
name = STRargv;
|
||||
else
|
||||
(void) strip(name);
|
||||
argv = adrof(name);
|
||||
if (argv == 0)
|
||||
udvar(name);
|
||||
if (argv->vec[0] == 0)
|
||||
stderror(ERR_NAME | ERR_NOMORE);
|
||||
lshift(argv->vec, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
exportpath(val)
|
||||
Char **val;
|
||||
{
|
||||
Char exppath[BUFSIZ];
|
||||
|
||||
exppath[0] = 0;
|
||||
if (val)
|
||||
while (*val) {
|
||||
if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ) {
|
||||
(void) fprintf(csherr,
|
||||
"Warning: ridiculously long PATH truncated\n");
|
||||
break;
|
||||
}
|
||||
if (**val != '/' && (euid == 0 || uid == 0) &&
|
||||
(intact || (intty && isatty(SHOUT))))
|
||||
(void) fprintf(csherr,
|
||||
"Warning: exported path contains relative components.\n");
|
||||
(void) Strcat(exppath, *val++);
|
||||
if (*val == 0 || eq(*val, STRRparen))
|
||||
break;
|
||||
(void) Strcat(exppath, STRcolon);
|
||||
}
|
||||
Setenv(STRPATH, exppath);
|
||||
}
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
* Lint thinks these have null effect
|
||||
*/
|
||||
/* macros to do single rotations on node p */
|
||||
#define rright(p) (\
|
||||
t = (p)->v_left,\
|
||||
(t)->v_parent = (p)->v_parent,\
|
||||
((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
|
||||
(t->v_right = (p))->v_parent = t,\
|
||||
(p) = t)
|
||||
#define rleft(p) (\
|
||||
t = (p)->v_right,\
|
||||
(t)->v_parent = (p)->v_parent,\
|
||||
((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
|
||||
(t->v_left = (p))->v_parent = t,\
|
||||
(p) = t)
|
||||
#else
|
||||
struct varent *
|
||||
rleft(p)
|
||||
struct varent *p;
|
||||
{
|
||||
return (p);
|
||||
}
|
||||
struct varent *
|
||||
rright(p)
|
||||
struct varent *p;
|
||||
{
|
||||
return (p);
|
||||
}
|
||||
|
||||
#endif /* ! lint */
|
||||
|
||||
|
||||
/*
|
||||
* Rebalance a tree, starting at p and up.
|
||||
* F == 0 means we've come from p's left child.
|
||||
* D == 1 means we've just done a delete, otherwise an insert.
|
||||
*/
|
||||
static void
|
||||
balance(p, f, d)
|
||||
struct varent *p;
|
||||
int f, d;
|
||||
{
|
||||
struct varent *pp;
|
||||
|
||||
#ifndef lint
|
||||
struct varent *t; /* used by the rotate macros */
|
||||
|
||||
#endif
|
||||
int ff;
|
||||
|
||||
/*
|
||||
* Ok, from here on, p is the node we're operating on; pp is it's parent; f
|
||||
* is the branch of p from which we have come; ff is the branch of pp which
|
||||
* is p.
|
||||
*/
|
||||
for (; (pp = p->v_parent) != NULL; p = pp, f = ff) {
|
||||
ff = pp->v_right == p;
|
||||
if (f ^ d) { /* right heavy */
|
||||
switch (p->v_bal) {
|
||||
case -1: /* was left heavy */
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
case 0: /* was balanced */
|
||||
p->v_bal = 1;
|
||||
break;
|
||||
case 1: /* was already right heavy */
|
||||
switch (p->v_right->v_bal) {
|
||||
case 1: /* single rotate */
|
||||
pp->v_link[ff] = rleft(p);
|
||||
p->v_left->v_bal = 0;
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
case 0: /* single rotate */
|
||||
pp->v_link[ff] = rleft(p);
|
||||
p->v_left->v_bal = 1;
|
||||
p->v_bal = -1;
|
||||
break;
|
||||
case -1: /* double rotate */
|
||||
(void) rright(p->v_right);
|
||||
pp->v_link[ff] = rleft(p);
|
||||
p->v_left->v_bal =
|
||||
p->v_bal < 1 ? 0 : -1;
|
||||
p->v_right->v_bal =
|
||||
p->v_bal > -1 ? 0 : 1;
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* left heavy */
|
||||
switch (p->v_bal) {
|
||||
case 1: /* was right heavy */
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
case 0: /* was balanced */
|
||||
p->v_bal = -1;
|
||||
break;
|
||||
case -1: /* was already left heavy */
|
||||
switch (p->v_left->v_bal) {
|
||||
case -1: /* single rotate */
|
||||
pp->v_link[ff] = rright(p);
|
||||
p->v_right->v_bal = 0;
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
case 0: /* single rotate */
|
||||
pp->v_link[ff] = rright(p);
|
||||
p->v_right->v_bal = -1;
|
||||
p->v_bal = 1;
|
||||
break;
|
||||
case 1: /* double rotate */
|
||||
(void) rleft(p->v_left);
|
||||
pp->v_link[ff] = rright(p);
|
||||
p->v_left->v_bal =
|
||||
p->v_bal < 1 ? 0 : -1;
|
||||
p->v_right->v_bal =
|
||||
p->v_bal > -1 ? 0 : 1;
|
||||
p->v_bal = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If from insert, then we terminate when p is balanced. If from
|
||||
* delete, then we terminate when p is unbalanced.
|
||||
*/
|
||||
if ((p->v_bal == 0) ^ d)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plist(p)
|
||||
struct varent *p;
|
||||
{
|
||||
struct varent *c;
|
||||
int len;
|
||||
|
||||
if (setintr)
|
||||
(void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));
|
||||
|
||||
for (;;) {
|
||||
while (p->v_left)
|
||||
p = p->v_left;
|
||||
x:
|
||||
if (p->v_parent == 0) /* is it the header? */
|
||||
return;
|
||||
len = blklen(p->vec);
|
||||
(void) fprintf(cshout, "%s\t", short2str(p->v_name));
|
||||
if (len != 1)
|
||||
(void) fputc('(', cshout);
|
||||
blkpr(cshout, p->vec);
|
||||
if (len != 1)
|
||||
(void) fputc(')', cshout);
|
||||
(void) fputc('\n', cshout);
|
||||
if (p->v_right) {
|
||||
p = p->v_right;
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
c = p;
|
||||
p = p->v_parent;
|
||||
} while (p->v_right == c);
|
||||
goto x;
|
||||
}
|
||||
}
|
472
bin/csh/str.c
472
bin/csh/str.c
@ -1,472 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#define MALLOC_INCR 128
|
||||
|
||||
/*
|
||||
* tc.str.c: Short string package
|
||||
* This has been a lesson of how to write buggy code!
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
#include <vis.h>
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef SHORT_STRINGS
|
||||
|
||||
Char **
|
||||
blk2short(src)
|
||||
char **src;
|
||||
{
|
||||
size_t n;
|
||||
Char **sdst, **dst;
|
||||
|
||||
/*
|
||||
* Count
|
||||
*/
|
||||
for (n = 0; src[n] != NULL; n++)
|
||||
continue;
|
||||
sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *)));
|
||||
|
||||
for (; *src != NULL; src++)
|
||||
*dst++ = SAVE(*src);
|
||||
*dst = NULL;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
char **
|
||||
short2blk(src)
|
||||
Char **src;
|
||||
{
|
||||
size_t n;
|
||||
char **sdst, **dst;
|
||||
|
||||
/*
|
||||
* Count
|
||||
*/
|
||||
for (n = 0; src[n] != NULL; n++)
|
||||
continue;
|
||||
sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *)));
|
||||
|
||||
for (; *src != NULL; src++)
|
||||
*dst++ = strsave(short2str(*src));
|
||||
*dst = NULL;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
Char *
|
||||
str2short(src)
|
||||
char *src;
|
||||
{
|
||||
static Char *sdst;
|
||||
static size_t dstsize = 0;
|
||||
Char *dst, *edst;
|
||||
|
||||
if (src == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sdst == (NULL)) {
|
||||
dstsize = MALLOC_INCR;
|
||||
sdst = (Char *) xmalloc((size_t) dstsize * sizeof(Char));
|
||||
}
|
||||
|
||||
dst = sdst;
|
||||
edst = &dst[dstsize];
|
||||
while (*src) {
|
||||
*dst++ = (Char) ((unsigned char) *src++);
|
||||
if (dst == edst) {
|
||||
dstsize += MALLOC_INCR;
|
||||
sdst = (Char *) xrealloc((ptr_t) sdst,
|
||||
(size_t) dstsize * sizeof(Char));
|
||||
edst = &sdst[dstsize];
|
||||
dst = &edst[-MALLOC_INCR];
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
char *
|
||||
short2str(src)
|
||||
Char *src;
|
||||
{
|
||||
static char *sdst = NULL;
|
||||
static size_t dstsize = 0;
|
||||
char *dst, *edst;
|
||||
|
||||
if (src == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sdst == NULL) {
|
||||
dstsize = MALLOC_INCR;
|
||||
sdst = (char *) xmalloc((size_t) dstsize * sizeof(char));
|
||||
}
|
||||
dst = sdst;
|
||||
edst = &dst[dstsize];
|
||||
while (*src) {
|
||||
*dst++ = (char) *src++;
|
||||
if (dst == edst) {
|
||||
dstsize += MALLOC_INCR;
|
||||
sdst = (char *) xrealloc((ptr_t) sdst,
|
||||
(size_t) dstsize * sizeof(char));
|
||||
edst = &sdst[dstsize];
|
||||
dst = &edst[-MALLOC_INCR];
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strcpy(dst, src)
|
||||
Char *dst, *src;
|
||||
{
|
||||
Char *sdst;
|
||||
|
||||
sdst = dst;
|
||||
while ((*dst++ = *src++) != '\0')
|
||||
continue;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strncpy(dst, src, n)
|
||||
Char *dst, *src;
|
||||
size_t n;
|
||||
{
|
||||
Char *sdst;
|
||||
|
||||
if (n == 0)
|
||||
return(dst);
|
||||
|
||||
sdst = dst;
|
||||
do
|
||||
if ((*dst++ = *src++) == '\0') {
|
||||
while (--n != 0)
|
||||
*dst++ = '\0';
|
||||
return(sdst);
|
||||
}
|
||||
while (--n != 0);
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strcat(dst, src)
|
||||
Char *dst, *src;
|
||||
{
|
||||
short *sdst;
|
||||
|
||||
sdst = dst;
|
||||
while (*dst++)
|
||||
continue;
|
||||
--dst;
|
||||
while ((*dst++ = *src++) != '\0')
|
||||
continue;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
#ifdef NOTUSED
|
||||
Char *
|
||||
s_strncat(dst, src, n)
|
||||
Char *dst, *src;
|
||||
size_t n;
|
||||
{
|
||||
Char *sdst;
|
||||
|
||||
if (n == 0)
|
||||
return (dst);
|
||||
|
||||
sdst = dst;
|
||||
|
||||
while (*dst++)
|
||||
continue;
|
||||
--dst;
|
||||
|
||||
do
|
||||
if ((*dst++ = *src++) == '\0')
|
||||
return(sdst);
|
||||
while (--n != 0)
|
||||
continue;
|
||||
|
||||
*dst = '\0';
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Char *
|
||||
s_strchr(str, ch)
|
||||
Char *str;
|
||||
int ch;
|
||||
{
|
||||
do
|
||||
if (*str == ch)
|
||||
return (str);
|
||||
while (*str++);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strrchr(str, ch)
|
||||
Char *str;
|
||||
int ch;
|
||||
{
|
||||
Char *rstr;
|
||||
|
||||
rstr = NULL;
|
||||
do
|
||||
if (*str == ch)
|
||||
rstr = str;
|
||||
while (*str++);
|
||||
return (rstr);
|
||||
}
|
||||
|
||||
size_t
|
||||
s_strlen(str)
|
||||
Char *str;
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; *str++; n++)
|
||||
continue;
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
s_strcmp(str1, str2)
|
||||
Char *str1, *str2;
|
||||
{
|
||||
for (; *str1 && *str1 == *str2; str1++, str2++)
|
||||
continue;
|
||||
/*
|
||||
* The following case analysis is necessary so that characters which look
|
||||
* negative collate low against normal characters but high against the
|
||||
* end-of-string NUL.
|
||||
*/
|
||||
if (*str1 == '\0' && *str2 == '\0')
|
||||
return (0);
|
||||
else if (*str1 == '\0')
|
||||
return (-1);
|
||||
else if (*str2 == '\0')
|
||||
return (1);
|
||||
else
|
||||
return (*str1 - *str2);
|
||||
}
|
||||
|
||||
int
|
||||
s_strncmp(str1, str2, n)
|
||||
Char *str1, *str2;
|
||||
size_t n;
|
||||
{
|
||||
if (n == 0)
|
||||
return (0);
|
||||
do {
|
||||
if (*str1 != *str2) {
|
||||
/*
|
||||
* The following case analysis is necessary so that characters
|
||||
* which look negative collate low against normal characters
|
||||
* but high against the end-of-string NUL.
|
||||
*/
|
||||
if (*str1 == '\0')
|
||||
return (-1);
|
||||
else if (*str2 == '\0')
|
||||
return (1);
|
||||
else
|
||||
return (*str1 - *str2);
|
||||
break;
|
||||
}
|
||||
if (*str1 == '\0')
|
||||
return(0);
|
||||
str1++, str2++;
|
||||
} while (--n != 0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strsave(s)
|
||||
Char *s;
|
||||
{
|
||||
Char *n;
|
||||
Char *p;
|
||||
|
||||
if (s == 0)
|
||||
s = STRNULL;
|
||||
for (p = s; *p++;)
|
||||
continue;
|
||||
n = p = (Char *) xmalloc((size_t) ((p - s) * sizeof(Char)));
|
||||
while ((*p++ = *s++) != '\0')
|
||||
continue;
|
||||
return (n);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strspl(cp, dp)
|
||||
Char *cp, *dp;
|
||||
{
|
||||
Char *ep;
|
||||
Char *p, *q;
|
||||
|
||||
if (!cp)
|
||||
cp = STRNULL;
|
||||
if (!dp)
|
||||
dp = STRNULL;
|
||||
for (p = cp; *p++;)
|
||||
continue;
|
||||
for (q = dp; *q++;)
|
||||
continue;
|
||||
ep = (Char *) xmalloc((size_t)
|
||||
(((p - cp) + (q - dp) - 1) * sizeof(Char)));
|
||||
for (p = ep, q = cp; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
for (p--, q = dp; (*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
return (ep);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strend(cp)
|
||||
Char *cp;
|
||||
{
|
||||
if (!cp)
|
||||
return (cp);
|
||||
while (*cp)
|
||||
cp++;
|
||||
return (cp);
|
||||
}
|
||||
|
||||
Char *
|
||||
s_strstr(s, t)
|
||||
Char *s, *t;
|
||||
{
|
||||
do {
|
||||
Char *ss = s;
|
||||
Char *tt = t;
|
||||
|
||||
do
|
||||
if (*tt == '\0')
|
||||
return (s);
|
||||
while (*ss++ == *tt++);
|
||||
} while (*s++ != '\0');
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* SHORT_STRINGS */
|
||||
|
||||
char *
|
||||
short2qstr(src)
|
||||
Char *src;
|
||||
{
|
||||
static char *sdst = NULL;
|
||||
static size_t dstsize = 0;
|
||||
char *dst, *edst;
|
||||
|
||||
if (src == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sdst == NULL) {
|
||||
dstsize = MALLOC_INCR;
|
||||
sdst = (char *) xmalloc((size_t) dstsize * sizeof(char));
|
||||
}
|
||||
dst = sdst;
|
||||
edst = &dst[dstsize];
|
||||
while (*src) {
|
||||
if (*src & QUOTE) {
|
||||
*dst++ = '\\';
|
||||
if (dst == edst) {
|
||||
dstsize += MALLOC_INCR;
|
||||
sdst = (char *) xrealloc((ptr_t) sdst,
|
||||
(size_t) dstsize * sizeof(char));
|
||||
edst = &sdst[dstsize];
|
||||
dst = &edst[-MALLOC_INCR];
|
||||
}
|
||||
}
|
||||
*dst++ = (char) *src++;
|
||||
if (dst == edst) {
|
||||
dstsize += MALLOC_INCR;
|
||||
sdst = (char *) xrealloc((ptr_t) sdst,
|
||||
(size_t) dstsize * sizeof(char));
|
||||
edst = &sdst[dstsize];
|
||||
dst = &edst[-MALLOC_INCR];
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return (sdst);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: Should we worry about QUOTE'd chars?
|
||||
*/
|
||||
char *
|
||||
vis_str(cp)
|
||||
Char *cp;
|
||||
{
|
||||
static char *sdst = NULL;
|
||||
static size_t dstsize = 0;
|
||||
size_t n;
|
||||
Char *dp;
|
||||
|
||||
if (cp == NULL)
|
||||
return (NULL);
|
||||
|
||||
for (dp = cp; *dp++;)
|
||||
continue;
|
||||
n = ((dp - cp) << 2) + 1; /* 4 times + NULL */
|
||||
if (dstsize < n) {
|
||||
sdst = (char *) (dstsize ?
|
||||
xrealloc(sdst, (size_t) n * sizeof(char)) :
|
||||
xmalloc((size_t) n * sizeof(char)));
|
||||
dstsize = n;
|
||||
}
|
||||
/*
|
||||
* XXX: When we are in AsciiOnly we want all characters >= 0200 to
|
||||
* be encoded, but currently there is no way in vis to do that.
|
||||
*/
|
||||
(void) strvis(sdst, short2str(cp), VIS_NOSLASH);
|
||||
return (sdst);
|
||||
}
|
||||
|
2709
bin/csh/tc.defs.c
Normal file
2709
bin/csh/tc.defs.c
Normal file
File diff suppressed because it is too large
Load Diff
321
bin/csh/time.c
321
bin/csh/time.c
@ -1,321 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#if __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "csh.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* C Shell - routines handling process timing and niceing
|
||||
*/
|
||||
static void pdeltat __P((struct timeval *, struct timeval *));
|
||||
|
||||
void
|
||||
settimes()
|
||||
{
|
||||
struct rusage ruch;
|
||||
|
||||
(void) gettimeofday(&time0, NULL);
|
||||
(void) getrusage(RUSAGE_SELF, &ru0);
|
||||
(void) getrusage(RUSAGE_CHILDREN, &ruch);
|
||||
ruadd(&ru0, &ruch);
|
||||
}
|
||||
|
||||
/*
|
||||
* dotime is only called if it is truly a builtin function and not a
|
||||
* prefix to another command
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
dotime(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
struct timeval timedol;
|
||||
struct rusage ru1, ruch;
|
||||
|
||||
(void) getrusage(RUSAGE_SELF, &ru1);
|
||||
(void) getrusage(RUSAGE_CHILDREN, &ruch);
|
||||
ruadd(&ru1, &ruch);
|
||||
(void) gettimeofday(&timedol, NULL);
|
||||
prusage(&ru0, &ru1, &timedol, &time0);
|
||||
}
|
||||
|
||||
/*
|
||||
* donice is only called when it on the line by itself or with a +- value
|
||||
*/
|
||||
void
|
||||
/*ARGSUSED*/
|
||||
donice(v, t)
|
||||
Char **v;
|
||||
struct command *t;
|
||||
{
|
||||
Char *cp;
|
||||
int nval = 0;
|
||||
|
||||
v++, cp = *v++;
|
||||
if (cp == 0)
|
||||
nval = 4;
|
||||
else if (*v == 0 && any("+-", cp[0]))
|
||||
nval = getn(cp);
|
||||
(void) setpriority(PRIO_PROCESS, 0, nval);
|
||||
}
|
||||
|
||||
void
|
||||
ruadd(ru, ru2)
|
||||
struct rusage *ru, *ru2;
|
||||
{
|
||||
tvadd(&ru->ru_utime, &ru2->ru_utime);
|
||||
tvadd(&ru->ru_stime, &ru2->ru_stime);
|
||||
if (ru2->ru_maxrss > ru->ru_maxrss)
|
||||
ru->ru_maxrss = ru2->ru_maxrss;
|
||||
|
||||
ru->ru_ixrss += ru2->ru_ixrss;
|
||||
ru->ru_idrss += ru2->ru_idrss;
|
||||
ru->ru_isrss += ru2->ru_isrss;
|
||||
ru->ru_minflt += ru2->ru_minflt;
|
||||
ru->ru_majflt += ru2->ru_majflt;
|
||||
ru->ru_nswap += ru2->ru_nswap;
|
||||
ru->ru_inblock += ru2->ru_inblock;
|
||||
ru->ru_oublock += ru2->ru_oublock;
|
||||
ru->ru_msgsnd += ru2->ru_msgsnd;
|
||||
ru->ru_msgrcv += ru2->ru_msgrcv;
|
||||
ru->ru_nsignals += ru2->ru_nsignals;
|
||||
ru->ru_nvcsw += ru2->ru_nvcsw;
|
||||
ru->ru_nivcsw += ru2->ru_nivcsw;
|
||||
}
|
||||
|
||||
void
|
||||
prusage(r0, r1, e, b)
|
||||
struct rusage *r0, *r1;
|
||||
struct timeval *e, *b;
|
||||
{
|
||||
time_t t =
|
||||
(r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
|
||||
(r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
|
||||
(r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
|
||||
(r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
|
||||
char *cp;
|
||||
long i;
|
||||
struct varent *vp = adrof(STRtime);
|
||||
|
||||
int ms =
|
||||
(e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
|
||||
|
||||
cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
|
||||
|
||||
if (vp && vp->vec[0] && vp->vec[1])
|
||||
cp = short2str(vp->vec[1]);
|
||||
|
||||
for (; *cp; cp++)
|
||||
if (*cp != '%')
|
||||
(void) fputc(*cp, cshout);
|
||||
else if (cp[1])
|
||||
switch (*++cp) {
|
||||
|
||||
case 'U': /* user CPU time used */
|
||||
pdeltat(&r1->ru_utime, &r0->ru_utime);
|
||||
break;
|
||||
|
||||
case 'S': /* system CPU time used */
|
||||
pdeltat(&r1->ru_stime, &r0->ru_stime);
|
||||
break;
|
||||
|
||||
case 'E': /* elapsed (wall-clock) time */
|
||||
pcsecs((long) ms);
|
||||
break;
|
||||
|
||||
case 'P': /* percent time spent running */
|
||||
/* check if it did not run at all */
|
||||
i = (ms == 0) ? 0 : (t * 1000 / ms);
|
||||
/* nn.n% */
|
||||
(void) fprintf(cshout, "%ld.%01ld%%", i / 10, i % 10);
|
||||
break;
|
||||
|
||||
case 'W': /* number of swaps */
|
||||
i = r1->ru_nswap - r0->ru_nswap;
|
||||
(void) fprintf(cshout, "%ld", i);
|
||||
break;
|
||||
|
||||
case 'X': /* (average) shared text size */
|
||||
(void) fprintf(cshout, "%ld", t == 0 ? 0L :
|
||||
(r1->ru_ixrss - r0->ru_ixrss) / t);
|
||||
break;
|
||||
|
||||
case 'D': /* (average) unshared data size */
|
||||
(void) fprintf(cshout, "%ld", t == 0 ? 0L :
|
||||
(r1->ru_idrss + r1->ru_isrss -
|
||||
(r0->ru_idrss + r0->ru_isrss)) / t);
|
||||
break;
|
||||
|
||||
case 'K': /* (average) total data memory used */
|
||||
(void) fprintf(cshout, "%ld", t == 0 ? 0L :
|
||||
((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
|
||||
(r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
|
||||
break;
|
||||
|
||||
case 'M': /* max. Resident Set Size */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
|
||||
break;
|
||||
|
||||
case 'F': /* page faults */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
|
||||
break;
|
||||
|
||||
case 'R': /* page reclaims */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
|
||||
break;
|
||||
|
||||
case 'I': /* FS blocks in */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
|
||||
break;
|
||||
|
||||
case 'O': /* FS blocks out */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
|
||||
break;
|
||||
|
||||
case 'r': /* socket messages received */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
|
||||
break;
|
||||
|
||||
case 's': /* socket messages sent */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
|
||||
break;
|
||||
|
||||
case 'k': /* number of signals received */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
|
||||
break;
|
||||
|
||||
case 'w': /* num. voluntary context switches (waits) */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
|
||||
break;
|
||||
|
||||
case 'c': /* num. involuntary context switches */
|
||||
(void) fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
|
||||
break;
|
||||
}
|
||||
(void) fputc('\n', cshout);
|
||||
}
|
||||
|
||||
static void
|
||||
pdeltat(t1, t0)
|
||||
struct timeval *t1, *t0;
|
||||
{
|
||||
struct timeval td;
|
||||
|
||||
tvsub(&td, t1, t0);
|
||||
(void) fprintf(cshout, "%ld.%01ld", td.tv_sec, td.tv_usec / 100000L);
|
||||
}
|
||||
|
||||
void
|
||||
tvadd(tsum, t0)
|
||||
struct timeval *tsum, *t0;
|
||||
{
|
||||
|
||||
tsum->tv_sec += t0->tv_sec;
|
||||
tsum->tv_usec += t0->tv_usec;
|
||||
if (tsum->tv_usec >= 1000000)
|
||||
tsum->tv_sec++, tsum->tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
void
|
||||
tvsub(tdiff, t1, t0)
|
||||
struct timeval *tdiff, *t1, *t0;
|
||||
{
|
||||
|
||||
tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
|
||||
tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
|
||||
if (tdiff->tv_usec < 0)
|
||||
tdiff->tv_sec--, tdiff->tv_usec += 1000000;
|
||||
}
|
||||
|
||||
#define P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
|
||||
|
||||
void
|
||||
psecs(l)
|
||||
long l;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = l / 3600;
|
||||
if (i) {
|
||||
(void) fprintf(cshout, "%d:", i);
|
||||
i = l % 3600;
|
||||
P2DIG(i / 60);
|
||||
goto minsec;
|
||||
}
|
||||
i = l;
|
||||
(void) fprintf(cshout, "%d", i / 60);
|
||||
minsec:
|
||||
i %= 60;
|
||||
(void) fputc(':', cshout);
|
||||
P2DIG(i);
|
||||
}
|
||||
|
||||
void
|
||||
pcsecs(l) /* PWP: print mm:ss.dd, l is in sec*100 */
|
||||
long l;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = l / 360000;
|
||||
if (i) {
|
||||
(void) fprintf(cshout, "%d:", i);
|
||||
i = (l % 360000) / 100;
|
||||
P2DIG(i / 60);
|
||||
goto minsec;
|
||||
}
|
||||
i = l / 100;
|
||||
(void) fprintf(cshout, "%d", i / 60);
|
||||
minsec:
|
||||
i %= 60;
|
||||
(void) fputc(':', cshout);
|
||||
P2DIG(i);
|
||||
(void) fputc('.', cshout);
|
||||
P2DIG((int) (l % 100));
|
||||
}
|
Loading…
Reference in New Issue
Block a user