⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sh1.c

📁 操作系统源代码
💻 C
字号:
#define Extern extern#include <sys/types.h>#include <signal.h>#include <errno.h>#include <setjmp.h>#include "sh.h"/* -------- sh.c -------- *//* * shell *//* #include "sh.h" */int	intr;int	inparse;char	flags['z'-'a'+1];char	*flag = flags-'a';char	*elinep = line+sizeof(line)-5;char	*null	= "";int	heedint =1;struct	env	e ={line, iostack, iostack-1,		    (xint *)NULL, FDBASE, (struct env *)NULL};extern	char	**environ;	/* environment pointer *//* * default shell, search rules */char	shellname[] = "/bin/sh";char	search[] = ":/bin:/usr/bin";_PROTOTYPE(void (*qflag), (int)) = SIG_IGN;_PROTOTYPE(int main, (int argc, char **argv ));_PROTOTYPE(int newfile, (char *s ));_PROTOTYPE(static char *findeq, (char *cp ));_PROTOTYPE(static char *cclass, (char *p, int sub ));_PROTOTYPE(void initarea, (void));int main(argc, argv)int argc;register char **argv;{	register int f;	register char *s;	int cflag;	char *name, **ap;	int (*iof)();	initarea();	if ((ap = environ) != NULL) {		while (*ap)			assign(*ap++, !COPYV);		for (ap = environ; *ap;)			export(lookup(*ap++));	}	closeall();	areanum = 1;	shell = lookup("SHELL");	if (shell->value == null)		setval(shell, shellname);	export(shell);	homedir = lookup("HOME");	if (homedir->value == null)		setval(homedir, "/");	export(homedir);	setval(lookup("$"), itoa(getpid(), 5));	path = lookup("PATH");	if (path->value == null)		setval(path, search);	export(path);	ifs = lookup("IFS");	if (ifs->value == null)		setval(ifs, " \t\n");	prompt = lookup("PS1");	if (prompt->value == null)#ifndef UNIXSHELL		setval(prompt, "$ ");#else		setval(prompt, "% ");#endif	if (geteuid() == 0) {		setval(prompt, "# ");		prompt->status &= ~EXPORT;	}	cprompt = lookup("PS2");	if (cprompt->value == null)		setval(cprompt, "> ");	iof = filechar;	cflag = 0;	name = *argv++;	if (--argc >= 1) {		if(argv[0][0] == '-' && argv[0][1] != '\0') {			for (s = argv[0]+1; *s; s++)				switch (*s) {				case 'c':					prompt->status &= ~EXPORT;					cprompt->status &= ~EXPORT;					setval(prompt, "");					setval(cprompt, "");					cflag = 1;					if (--argc > 0)						PUSHIO(aword, *++argv, iof = nlchar);					break;					case 'q':					qflag = SIG_DFL;					break;				case 's':					/* standard input */					break;				case 't':					prompt->status &= ~EXPORT;					setval(prompt, "");					iof = linechar;					break;					case 'i':					talking++;				default:					if (*s>='a' && *s<='z')						flag[*s]++;				}		} else {			argv--;			argc++;		}		if (iof == filechar && --argc > 0) {			setval(prompt, "");			setval(cprompt, "");			prompt->status &= ~EXPORT;			cprompt->status &= ~EXPORT;			if (newfile(name = *++argv))				exit(1);		}	}	setdash();	if (e.iop < iostack) {		PUSHIO(afile, 0, iof);		if (isatty(0) && isatty(1) && !cflag)			talking++;	}	signal(SIGQUIT, qflag);	if (name && name[0] == '-') {		talking++;		if ((f = open(".profile", 0)) >= 0)			next(remap(f));		if ((f = open("/etc/profile", 0)) >= 0)			next(remap(f));	}	if (talking)		signal(SIGTERM, sig);	if (signal(SIGINT, SIG_IGN) != SIG_IGN)		signal(SIGINT, onintr);	dolv = argv;	dolc = argc;	dolv[0] = name;	if (dolc > 1)		for (ap = ++argv; --argc > 0;)			if (assign(*ap = *argv++, !COPYV))				dolc--;	/* keyword */			else				ap++;	setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));	for (;;) {		if (talking && e.iop <= iostack)			prs(prompt->value);		onecommand();	}}voidsetdash(){	register char *cp, c;	char m['z'-'a'+1];	cp = m;	for (c='a'; c<='z'; c++)		if (flag[c])			*cp++ = c;	*cp = 0;	setval(lookup("-"), m);}intnewfile(s)register char *s;{	register f;	if (strcmp(s, "-") != 0) {		f = open(s, 0);		if (f < 0) {			prs(s);			err(": cannot open");			return(1);		}	} else		f = 0;	next(remap(f));	return(0);}voidonecommand(){	register i;	jmp_buf m1;	while (e.oenv)		quitenv();	areanum = 1;	freehere(areanum);	freearea(areanum);	garbage();	wdlist = 0;	iolist = 0;	e.errpt = 0;	e.linep = line;	yynerrs = 0;	multiline = 0;	inparse = 1;	intr = 0;	execflg = 0;	setjmp(failpt = m1);	/* Bruce Evans' fix */	if (setjmp(failpt = m1) || yyparse() || intr) {		while (e.oenv)			quitenv();		scraphere();		if (!talking && intr)			leave();		inparse = 0;		intr = 0;		return;	}	inparse = 0;	brklist = 0;	intr = 0;	execflg = 0;	if (!flag['n'])		execute(outtree, NOPIPE, NOPIPE, 0);	if (!talking && intr) {		execflg = 0;		leave();	}	if ((i = trapset) != 0) {		trapset = 0;		runtrap(i);	}}voidfail(){	longjmp(failpt, 1);	/* NOTREACHED */}voidleave(){	if (execflg)		fail();	scraphere();	freehere(1);	runtrap(0);	exit(exstat);	/* NOTREACHED */}voidwarn(s)register char *s;{	if(*s) {		prs(s);		exstat = -1;	}	prs("\n");	if (flag['e'])		leave();}voiderr(s)char *s;{	warn(s);	if (flag['n'])		return;	if (!talking)		leave();	if (e.errpt)		longjmp(e.errpt, 1);	closeall();	e.iop = e.iobase = iostack;}intnewenv(f)int f;{	register struct env *ep;	if (f) {		quitenv();		return(1);	}	ep = (struct env *) space(sizeof(*ep));	if (ep == NULL) {		while (e.oenv)			quitenv();		fail();	}	*ep = e;	e.oenv = ep;	e.errpt = errpt;	return(0);}voidquitenv(){	register struct env *ep;	register fd;	if ((ep = e.oenv) != NULL) {		fd = e.iofd;		e = *ep;		/* should close `'d files */		DELETE(ep);		while (--fd >= e.iofd)			close(fd);	}}/* * Is any character from s1 in s2? */intanys(s1, s2)register char *s1, *s2;{	while (*s1)		if (any(*s1++, s2))			return(1);	return(0);}/* * Is character c in s? */intany(c, s)register int c;register char *s;{	while (*s)		if (*s++ == c)			return(1);	return(0);}char *putn(n)register int n;{	return(itoa(n, -1));}char *itoa(u, n)register unsigned u;int n;{	register char *cp;	static char s[20];	int m;	m = 0;	if (n < 0 && (int) u < 0) {		m++;		u = -u;	}	cp = s+sizeof(s);	*--cp = 0;	do {		*--cp = u%10 + '0';		u /= 10;	} while (--n > 0 || u);	if (m)		*--cp = '-';	return(cp);}voidnext(f)int f;{	PUSHIO(afile, f, filechar);}voidonintr(s)int s;				/* ANSI C requires a parameter */{	signal(SIGINT, onintr);	intr = 1;	if (talking) {		if (inparse) {			prs("\n");			fail();		}	}	else if (heedint) {		execflg = 0;		leave();	}}intletter(c)register c;{	return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');}intdigit(c)register c;{	return(c >= '0' && c <= '9');}intletnum(c)register c;{	return(letter(c) || digit(c));}char *space(n)int n;{	register char *cp;	if ((cp = getcell(n)) == 0)		err("out of string space");	return(cp);}char *strsave(s, a)register char *s;int a;{	register char *cp, *xp;	if ((cp = space(strlen(s)+1)) != NULL) {		setarea((char *)cp, a);		for (xp = cp; (*xp++ = *s++) != '\0';)			;		return(cp);	}	return("");}voidxfree(s)register char *s;{	DELETE(s);}/* * trap handling */voidsig(i)register int i;{	trapset = i;	signal(i, sig);}void runtrap(i)int i;{	char *trapstr;	if ((trapstr = trap[i]) == NULL)		return;	if (i == 0)		trap[i] = 0;	RUN(aword, trapstr, nlchar);}/* -------- var.c -------- *//* #include "sh.h" *//* * Find the given name in the dictionary * and return its value.  If the name was * not previously there, enter it now and * return a null value. */struct var *lookup(n)register char *n;{	register struct var *vp;	register char *cp;	register int c;	static struct var dummy;	if (digit(*n)) {		dummy.name = n;		for (c = 0; digit(*n) && c < 1000; n++)			c = c*10 + *n-'0';		dummy.status = RONLY;		dummy.value = c <= dolc? dolv[c]: null;		return(&dummy);	}	for (vp = vlist; vp; vp = vp->next)		if (eqname(vp->name, n))			return(vp);	cp = findeq(n);	vp = (struct var *)space(sizeof(*vp));	if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) {		dummy.name = dummy.value = "";		return(&dummy);	}	for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++)		;	if (*cp == 0)		*cp = '=';	*++cp = 0;	setarea((char *)vp, 0);	setarea((char *)vp->name, 0);	vp->value = null;	vp->next = vlist;	vp->status = GETCELL;	vlist = vp;	return(vp);}/* * give variable at `vp' the value `val'. */voidsetval(vp, val)struct var *vp;char *val;{	nameval(vp, val, (char *)NULL);}/* * if name is not NULL, it must be * a prefix of the space `val', * and end with `='. * this is all so that exporting * values is reasonably painless. */voidnameval(vp, val, name)register struct var *vp;char *val, *name;{	register char *cp, *xp;	char *nv;	int fl;	if (vp->status & RONLY) {		for (xp = vp->name; *xp && *xp != '=';)			putc(*xp++);		err(" is read-only");		return;	}	fl = 0;	if (name == NULL) {		xp = space(strlen(vp->name)+strlen(val)+2);		if (xp == 0)			return;		/* make string:  name=value */		setarea((char *)xp, 0);		name = xp;		for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++)			;		if (*xp++ == 0)			xp[-1] = '=';		nv = xp;		for (cp = val; (*xp++ = *cp++) != '\0';)			;		val = nv;		fl = GETCELL;	}	if (vp->status & GETCELL)		xfree(vp->name);	/* form new string `name=value' */	vp->name = name;	vp->value = val;	vp->status |= fl;}voidexport(vp)struct var *vp;{	vp->status |= EXPORT;}voidronly(vp)struct var *vp;{	if (letter(vp->name[0]))	/* not an internal symbol ($# etc) */		vp->status |= RONLY;}intisassign(s)register char *s;{	if (!letter((int)*s))		return(0);	for (; *s != '='; s++)		if (*s == 0 || !letnum(*s))			return(0);	return(1);}intassign(s, cf)register char *s;int cf;{	register char *cp;	struct var *vp;	if (!letter(*s))		return(0);	for (cp = s; *cp != '='; cp++)		if (*cp == 0 || !letnum(*cp))			return(0);	vp = lookup(s);	nameval(vp, ++cp, cf == COPYV? (char *)NULL: s);	if (cf != COPYV)		vp->status &= ~GETCELL;	return(1);}intcheckname(cp)register char *cp;{	if (!letter(*cp++))		return(0);	while (*cp)		if (!letnum(*cp++))			return(0);	return(1);}voidputvlist(f, out)register int f, out;{	register struct var *vp;	for (vp = vlist; vp; vp = vp->next)		if (vp->status & f && letter(*vp->name)) {			if (vp->status & EXPORT)				write(out, "export ", 7);			if (vp->status & RONLY)				write(out, "readonly ", 9);			write(out, vp->name, (int)(findeq(vp->name) - vp->name));			write(out, "\n", 1);		}}inteqname(n1, n2)register char *n1, *n2;{	for (; *n1 != '=' && *n1 != 0; n1++)		if (*n2++ != *n1)			return(0);	return(*n2 == 0 || *n2 == '=');}static char *findeq(cp)register char *cp;{	while (*cp != '\0' && *cp != '=')		cp++;	return(cp);}/* -------- gmatch.c -------- *//* * int gmatch(string, pattern) * char *string, *pattern; * * Match a pattern as in sh(1). */#define	CMASK	0377#define	QUOTE	0200#define	QMASK	(CMASK&~QUOTE)#define	NOT	'!'	/* might use ^ */intgmatch(s, p)register char *s, *p;{	register int sc, pc;	if (s == NULL || p == NULL)		return(0);	while ((pc = *p++ & CMASK) != '\0') {		sc = *s++ & QMASK;		switch (pc) {		case '[':			if ((p = cclass(p, sc)) == NULL)				return(0);			break;		case '?':			if (sc == 0)				return(0);			break;		case '*':			s--;			do {				if (*p == '\0' || gmatch(s, p))					return(1);			} while (*s++ != '\0');			return(0);		default:			if (sc != (pc&~QUOTE))				return(0);		}	}	return(*s == 0);}static char *cclass(p, sub)register char *p;register int sub;{	register int c, d, not, found;	if ((not = *p == NOT) != 0)		p++;	found = not;	do {		if (*p == '\0')			return((char *)NULL);		c = *p & CMASK;		if (p[1] == '-' && p[2] != ']') {			d = p[2] & CMASK;			p++;		} else			d = c;		if (c == sub || (c <= sub && sub <= d))			found = !not;	} while (*++p != ']');	return(found? p+1: (char *)NULL);}/* -------- area.c -------- */#define	REGSIZE		sizeof(struct region)#define GROWBY		256#undef	SHRINKBY	64#define FREE 32767#define BUSY 0#define	ALIGN (sizeof(int)-1)/* #include "area.h" */struct region {	struct	region *next;	int	area;};/* * All memory between (char *)areabot and (char *)(areatop+1) is * exclusively administered by the area management routines. * It is assumed that sbrk() and brk() manipulate the high end. */static	struct region *areabot;		/* bottom of area */static	struct region *areatop;		/* top of area */static	struct region *areanxt;		/* starting point of scan */voidinitarea(){	while ((int)sbrk(0) & ALIGN)		sbrk(1);	areabot = (struct region *)sbrk(REGSIZE);	areabot->next = areabot;	areabot->area = BUSY;	areatop = areabot;	areanxt = areabot;}char *getcell(nbytes)unsigned nbytes;{	register int nregio;	register struct region *p, *q;	register i;	if (nbytes == 0)		abort();	/* silly and defeats the algorithm */	/*	 * round upwards and add administration area	 */	nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1;	for (p = areanxt;;) {		if (p->area > areanum) {			/*			 * merge free cells			 */			while ((q = p->next)->area > areanum && q != areanxt)				p->next = q->next;			/*			 * exit loop if cell big enough			 */			if (q >= p + nregio)				goto found;		}		p = p->next;		if (p == areanxt)			break;	}	i = nregio >= GROWBY ? nregio : GROWBY;	p = (struct region *)sbrk(i * REGSIZE);	if (p == (struct region *)-1)		return((char *)NULL);	p--;	if (p != areatop)		abort();	/* allocated areas are contiguous */	q = p + i;	p->next = q;	p->area = FREE;	q->next = areabot;	q->area = BUSY;	areatop = q;found:	/*	 * we found a FREE area big enough, pointed to by 'p', and up to 'q'	 */	areanxt = p + nregio;	if (areanxt < q) {		/*		 * split into requested area and rest		 */		if (areanxt+1 > q)			abort();	/* insufficient space left for admin */		areanxt->next = q;		areanxt->area = FREE;		p->next = areanxt;	}	p->area = areanum;	return((char *)(p+1));}voidfreecell(cp)char *cp;{	register struct region *p;	if ((p = (struct region *)cp) != NULL) {		p--;		if (p < areanxt)			areanxt = p;		p->area = FREE;	}}voidfreearea(a)register int a;{	register struct region *p, *top;	top = areatop;	for (p = areabot; p != top; p = p->next)		if (p->area >= a)			p->area = FREE;}voidsetarea(cp,a)char *cp;int a;{	register struct region *p;	if ((p = (struct region *)cp) != NULL)		(p-1)->area = a;}intgetarea(cp)char *cp;{	return ((struct region*)cp-1)->area;}voidgarbage(){	register struct region *p, *q, *top;	top = areatop;	for (p = areabot; p != top; p = p->next) {		if (p->area > areanum) {			while ((q = p->next)->area > areanum)				p->next = q->next;			areanxt = p;		}	}#ifdef SHRINKBY	if (areatop >= q + SHRINKBY && q->area > areanum) {		brk((char *)(q+1));		q->next = areabot;		q->area = BUSY;		areatop = q;	}#endif}

⌨️ 快捷键说明

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