sh.func.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,362 行 · 第 1/2 页

C
1,362
字号
#ifndef lintstatic char *sccsid = "@(#)sh.func.c	4.2  (ULTRIX)        8/13/90";#endif/************************************************************************ *                                                                      * *                      Copyright (c) 1988 by                           * *              Digital Equipment Corporation, Maynard, MA              * *                      All rights reserved.                            * *                                                                      * *   This software is furnished under a license and may be used and     * *   copied  only  in accordance with the terms of such license and     * *   with the  inclusion  of  the  above  copyright  notice.   This     * *   software  or  any  other copies thereof may not be provided or     * *   otherwise made available to any other person.  No title to and     * *   ownership of the software is hereby transferred.                   * *                                                                      * *   The information in this software is subject to change  without     * *   notice  and should not be construed as a commitment by Digital     * *   Equipment Corporation.                                             * *                                                                      * *   Digital assumes no responsibility for the use  or  reliability     * *   of its software on equipment which is not supplied by Digital.     * *                                                                      * ************************************************************************//* ------------------------------------------------------------------ *//* | Copyright Unpublished, MIPS Computer Systems, Inc.  All Rights | *//* | Reserved.  This software contains proprietary and confidential | *//* | information of MIPS and its suppliers.  Use, disclosure or     | *//* | reproduction is prohibited without the prior express written   | *//* | consent of MIPS.                                               | *//* ------------------------------------------------------------------ *//* $Header: sh.func.c,v 1.6 87/04/06 20:52:18 dce Exp $ */#include "sh.h"#include <sys/ioctl.h>/* * C shell * * Modification History * 003 - Bob Fontaine - Fri Jun 22 09:53:01 EDT 1990 *	 Changed call to internal printf  routine to csh_printf to avoid *	 conflict with stdio library call. * * 002 - Gary A. Gaudet - Tue Jan  2 11:29:20 EST 1990 *	added a declaration of geteuid() *	added a return value test for ioctl() *	changed environ from common to extern * * 01 Sat Aug 13 15:28:57 EDT 1988, Gary A. Gaudet *	merging mips & ultrix for 8 bit clean and bug fixes */struct biltins *isbfunc(t)	struct command *t;{	register char *cp = t->t_dcom[0];	register struct biltins *bp, *bp1, *bp2;	int dolabel(), dofg1(), dobg1();	static struct biltins label = { "", dolabel, 0, 0 };	static struct biltins foregnd = { "%job", dofg1, 0, 0 };	static struct biltins backgnd = { "%job &", dobg1, 0, 0 };	if (lastchr(cp) == ':') {		label.bname = cp;		return (&label);	}	if (*cp == '%') {		if (t->t_dflg & FAND) {			t->t_dflg &= ~FAND;			backgnd.bname = cp;			return (&backgnd);		}		foregnd.bname = cp;		return (&foregnd);	}	/*	 * Binary search	 * Bp1 is the beginning of the current search range.	 * Bp2 is one past the end.	 */	for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {		register i;		bp = bp1 + (bp2 - bp1 >> 1);		if ((i = *cp - *bp->bname) == 0 &&		    (i = strcmp(cp, bp->bname)) == 0)			return bp;		if (i < 0)			bp2 = bp;		else			bp1 = bp + 1;	}	return (0);}func(t, bp)	register struct command *t;	register struct biltins *bp;{	int i;	xechoit(t->t_dcom);	setname(bp->bname);	i = blklen(t->t_dcom) - 1;	if (i < bp->minargs)		bferr("Too few arguments");	if (i > bp->maxargs)		bferr("Too many arguments");	(*bp->bfunct)(t->t_dcom, t);}dolabel(){}doonintr(v)	char **v;{	register char *cp;	register char *vv = v[1];	if (parintr == SIG_IGN)		return;	if (setintr && intty)		bferr("Can't from terminal");	cp = gointr, gointr = 0, xfree(cp);	if (vv == 0) {		if (setintr)			(void) sigblock(sigmask(SIGINT));		else			(void) signal(SIGINT, SIG_DFL);		gointr = 0;	} else if (eq((vv = strip(vv)), "-")) {		(void) signal(SIGINT, SIG_IGN);		gointr = "-";	} else {		gointr = savestr(vv);		(void) signal(SIGINT, pintr);	}}donohup(){	if (intty)		bferr("Can't from terminal");	if (setintr == 0) {		(void) signal(SIGHUP, SIG_IGN);#ifdef CC		submit(getpid());#endif	}}dozip(){	;}prvars(){	plist(&shvhed);}doalias(v)	register char **v;{	register struct varent *vp;	register char *p;	v++;	p = *v++;	if (p == 0)		plist(&aliases);	else if (*v == 0) {		vp = adrof1(strip(p), &aliases);		if (vp)			blkpr(vp->vec), csh_printf("\n");	/* 003 RNF */	} else {		if (eq(p, "alias") || eq(p, "unalias")) {			setname(p);			bferr("Too dangerous to alias that");		}		set1(strip(p), saveblk(v), &aliases);	}}unalias(v)	char **v;{	unset1(v, &aliases);}dologout(){	islogin();	goodbye();}dologin(v)	char **v;{	islogin();	rechist();	(void) signal(SIGTERM, parterm);	execl("/bin/login", "login", v[1], 0);	/*	 * Since ports may be in high demand, it is much nicer to give the	 * user the choice rather than drop them cause the exec failed.	 */	csh_printf("execl of /bin/login failed, logout and re-login!\n");	/* 003 RNF */}#ifdef NEWGRPdonewgrp(v)	char **v;{	if (chkstop == 0 && setintr)		panystop(0);	(void) signal(SIGTERM, parterm);	execl("/bin/newgrp", "newgrp", v[1], 0);	execl("/usr/bin/newgrp", "newgrp", v[1], 0);	untty();	exit(1);}#endifislogin(){	if (chkstop == 0 && setintr)		panystop(0);	if (loginsh)		return;	error("Not login shell");}doif(v, kp)	char **v;	struct command *kp;{	register int i;	register char **vv;	v++;	i = exp(&v);	vv = v;	if (*vv == NOSTR)		bferr("Empty if");	if (eq(*vv, "then")) {		if (*++vv)			bferr("Improper then");		setname("then");		/*		 * If expression was zero, then scan to else,		 * otherwise just fall into following code.		 */		if (!i)			search(ZIF, 0);		return;	}	/*	 * Simple command attached to this if.	 * Left shift the node in this tree, munging it	 * so we can reexecute it.	 */	if (i) {		lshift(kp->t_dcom, vv - kp->t_dcom);		reexecute(kp);		donefds();	}}/* * Reexecute a command, being careful not * to redo i/o redirection, which is already set up. */reexecute(kp)	register struct command *kp;{	kp->t_dflg &= FSAVE;	kp->t_dflg |= FREDO;	/*	 * If tty is still ours to arbitrate, arbitrate it;	 * otherwise dont even set pgrp's as the jobs would	 * then have no way to get the tty (we can't give it	 * to them, and our parent wouldn't know their pgrp, etc.	 */	execute(kp, tpgrp > 0 ? tpgrp : -1);}doelse(){	search(ZELSE, 0);}dogoto(v)	char **v;{	register struct whyle *wp;	char *lp;	/*	 * While we still can, locate any unknown ends of existing loops.	 * This obscure code is the WORST result of the fact that we	 * don't really parse.	 */	for (wp = whyles; wp; wp = wp->w_next)		if (wp->w_end == 0) {			search(ZBREAK, 0);			wp->w_end = btell();		} else			bseek(wp->w_end);	search(ZGOTO, 0, lp = globone(v[1]));	xfree(lp);	/*	 * Eliminate loops which were exited.	 */	wfree();}doswitch(v)	register char **v;{	register char *cp, *lp;	v++;	if (!*v || *(*v++) != '(')		goto syntax;	cp = **v == ')' ? "" : *v++;	if (*(*v++) != ')')		v--;	if (*v)syntax:		error("Syntax error");	search(ZSWITCH, 0, lp = globone(cp));	xfree(lp);}dobreak(){	if (whyles)		toend();	else		bferr("Not in while/foreach");}doexit(v)	char **v;{	if (chkstop == 0)		panystop(0);	/*	 * Don't DEMAND parentheses here either.	 */	v++;	if (*v) {		set("status", putn(exp(&v)));		if (*v)			bferr("Expression syntax");	}	btoeof();	if (intty)		(void) close(SHIN);}doforeach(v)	register char **v;{	register char *cp;	register struct whyle *nwp;	v++;	cp = strip(*v);	/*	 GT01:	 The variable must have a valid alphanumeric form, with	 a leading alphabetic to be accepted.	*/	if (!letter(*cp++))		bferr("Invalid variable: no leading alphabetic");	while (*cp && alnum(*cp))		cp++;	if (*cp)		bferr ("Invalid variable: bad characters");	if (strlen(*v) >= 20)		bferr("Invalid variable: too long");	cp = *v++;	if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')		bferr("Words not ()'ed");	v++;	gflag = 0, tglob(v);	v = glob(v);	if (v == 0)		bferr("No match");	nwp = (struct whyle *) calloc(1, sizeof *nwp);	nwp->w_fe = nwp->w_fe0 = v; gargv = 0;	nwp->w_start = btell();	nwp->w_fename = savestr(cp);	nwp->w_next = whyles;	whyles = nwp;	/*	 * Pre-read the loop so as to be more	 * comprehensible to a terminal user.	 */	if (intty)		preread();	doagain();}dowhile(v)	char **v;{	register int status;	register bool again = whyles != 0 && whyles->w_start == lineloc &&	    whyles->w_fename == 0;	v++;	/*	 * Implement prereading here also, taking care not to	 * evaluate the expression before the loop has been read up	 * from a terminal.	 */	if (intty && !again)		status = !exp0(&v, 1);	else		status = !exp(&v);	if (*v)		bferr("Expression syntax");	if (!again) {		register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp));		nwp->w_start = lineloc;		nwp->w_end = 0;		nwp->w_next = whyles;		whyles = nwp;		if (intty) {			/*			 * The tty preread			 */			preread();			doagain();			return;		}	}	if (status)		/* We ain't gonna loop no more, no more! */		toend();}preread(){	whyles->w_end = -1;	if (setintr)		(void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));	search(ZBREAK, 0);	if (setintr)		(void) sigblock(sigmask(SIGINT));	whyles->w_end = btell();}doend(){	if (!whyles)		bferr("Not in while/foreach");	whyles->w_end = btell();	doagain();}docontin(){	if (!whyles)		bferr("Not in while/foreach");	doagain();}doagain(){	/* Repeating a while is simple */	if (whyles->w_fename == 0) {		bseek(whyles->w_start);		return;	}	/*	 * The foreach variable list actually has a spurious word	 * ")" at the end of the w_fe list.  Thus we are at the	 * of the list if one word beyond this is 0.	 */	if (!whyles->w_fe[1]) {		dobreak();		return;	}	set(whyles->w_fename, savestr(*whyles->w_fe++));	bseek(whyles->w_start);}dorepeat(v, kp)	char **v;	struct command *kp;{	register int i, omask;	i = getn(v[1]);	if (setintr)		omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);	lshift(v, 2);	while (i > 0) {		if (setintr)			(void) sigsetmask(omask);		reexecute(kp);		--i;	}	donefds();	if (setintr)		(void) sigsetmask(omask);}doswbrk(){	search(ZBRKSW, 0);}srchx(cp)	register char *cp;{	register struct srch *sp, *sp1, *sp2;	register i;	/*	 * Binary search	 * Sp1 is the beginning of the current search range.	 * Sp2 is one past the end.	 */	for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {		sp = sp1 + (sp2 - sp1 >> 1);		if ((i = *cp - *sp->s_name) == 0 &&		    (i = strcmp(cp, sp->s_name)) == 0)			return sp->s_value;		if (i < 0)			sp2 = sp;		else			sp1 = sp + 1;	}	return (-1);}char	Stype;char	*Sgoal;/*VARARGS2*/search(type, level, goal)	int type;	register int level;	char *goal;{	char wordbuf[BUFSIZ];	register char *aword = wordbuf;	register char *cp;	Stype = type; Sgoal = goal;	if (type == ZGOTO)		bseek((off_t)0);	do {		if (intty && fseekp == feobp)			csh_printf("? "), flush();		/* 003 RNF */		aword[0] = 0;		(void) getword(aword);		switch (srchx(aword)) {		case ZELSE:			if (level == 0 && type == ZIF)				return;			break;		case ZIF:			while (getword(aword))				continue;			if ((type == ZIF || type == ZELSE) && eq(aword, "then"))				level++;			break;		case ZENDIF:			if (type == ZIF || type == ZELSE)				level--;			break;		case ZFOREACH:		case ZWHILE:			if (type == ZBREAK)				level++;			break;		case ZEND:			if (type == ZBREAK)				level--;			break;		case ZSWITCH:			if (type == ZSWITCH || type == ZBRKSW)				level++;			break;		case ZENDSW:			if (type == ZSWITCH || type == ZBRKSW)				level--;			break;		case ZLABEL:			if (type == ZGOTO && getword(aword) && eq(aword, goal))				level = -1;			break;		default:			if (type != ZGOTO && (type != ZSWITCH || level != 0))				break;			if (lastchr(aword) != ':')				break;			aword[strlen(aword) - 1] = 0;			if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default"))				level = -1;			break;		case ZCASE:			if (type != ZSWITCH || level != 0)				break;			(void) getword(aword);			if (lastchr(aword) == ':')				aword[strlen(aword) - 1] = 0;			cp = strip(Dfix1(aword));			if (Gmatch(goal, cp))				level = -1;			xfree(cp);			break;		case ZDEFAULT:			if (type == ZSWITCH && level == 0)				level = -1;			break;		}		(void) getword(NOSTR);	} while (level >= 0);}getword(wp)	register char *wp;{	register int found = 0;	register int c, d;	c = readc(1);	d = 0;	do {		while (c == ' ' || c == '\t' || c == '(')			c = readc(1);		if (c == '#')			do				c = readc(1);			while (c >= 0 && c != '\n');		if (c < 0)			goto past;		if (c == '\n') {			if (wp)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?