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 + -
显示快捷键?