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

📄 simple.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * Maybe `simple' is a misnomer. */#include "rc.h"#include "getflags.h"#include "exec.h"#include "io.h"#include "fns.h"/* * Search through the following code to see if we're just going to exit. */exitnext(void){	union code *c=&runq->code[runq->pc];	while(c->f==Xpopredir) c++;	return c->f==Xexit;}voidXsimple(void){	word *a;	thread *p = runq;	var *v;	struct builtin *bp;	int pid;	globlist();	a = runq->argv->words;	if(a==0){		Xerror1("empty argument list");		return;	}	if(flag['x'])		pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */	v = gvlook(a->word);	if(v->fn)		execfunc(v);	else{		if(strcmp(a->word, "builtin")==0){			if(count(a)==1){				pfmt(err, "builtin: empty argument list\n");				setstatus("empty arg list");				poplist();				return;			}			a = a->next;			popword();		}		for(bp = Builtin;bp->name;bp++)			if(strcmp(a->word, bp->name)==0){				(*bp->fnc)();				return;			}		if(exitnext()){			/* fork and wait is redundant */			pushword("exec");			execexec();			Xexit();		}		else{			flush(err);			Updenv();	/* necessary so changes don't go out again */			if((pid = execforkexec()) < 0){				Xerror("try again");				return;			}			/* interrupts don't get us out */			poplist();			while(Waitfor(pid, 1) < 0)				;		}	}}struct word nullpath = { "", 0};voiddoredir(redir *rp){	if(rp){		doredir(rp->next);		switch(rp->type){		case ROPEN:			if(rp->from!=rp->to){				Dup(rp->from, rp->to);				close(rp->from);			}			break;		case RDUP:			Dup(rp->from, rp->to);			break;		case RCLOSE:			close(rp->from);			break;		}	}}word*searchpath(char *w){	word *path;	if(strncmp(w, "/", 1)==0	|| strncmp(w, "#", 1)==0	|| strncmp(w, "./", 2)==0	|| strncmp(w, "../", 3)==0	|| (path = vlook("path")->val)==0)		path=&nullpath;	return path;}voidexecexec(void){	popword();	/* "exec" */	if(runq->argv->words==0){		Xerror1("empty argument list");		return;	}	doredir(runq->redir);	Execute(runq->argv->words, searchpath(runq->argv->words->word));	poplist();}voidexecfunc(var *func){	word *starval;	popword();	starval = runq->argv->words;	runq->argv->words = 0;	poplist();	start(func->fn, func->pc, (struct var *)0);	runq->local = newvar(strdup("*"), runq->local);	runq->local->val = starval;	runq->local->changed = 1;}intdochdir(char *word){	/* report to /dev/wdir if it exists and we're interactive */	static int wdirfd = -2;	if(chdir(word)<0) return -1;	if(flag['i']!=0){		if(wdirfd==-2)	/* try only once */			wdirfd = open("/dev/wdir", OWRITE|OCEXEC);		if(wdirfd>=0)			write(wdirfd, word, strlen(word));	}	return 1;}voidexeccd(void){	word *a = runq->argv->words;	word *cdpath;	char dir[512];	setstatus("can't cd");	cdpath = vlook("cdpath")->val;	switch(count(a)){	default:		pfmt(err, "Usage: cd [directory]\n");		break;	case 2:		if(a->next->word[0]=='/' || cdpath==0)			cdpath=&nullpath;		for(;cdpath;cdpath = cdpath->next){			strcpy(dir, cdpath->word);			if(dir[0])				strcat(dir, "/");			strcat(dir, a->next->word);			if(dochdir(dir)>=0){				if(strlen(cdpath->word)				&& strcmp(cdpath->word, ".")!=0)					pfmt(err, "%s\n", dir);				setstatus("");				break;			}		}		if(cdpath==0)			pfmt(err, "Can't cd %s: %r\n", a->next->word);		break;	case 1:		a = vlook("home")->val;		if(count(a)>=1){			if(dochdir(a->word)>=0)				setstatus("");			else				pfmt(err, "Can't cd %s: %r\n", a->word);		}		else			pfmt(err, "Can't cd -- $home empty\n");		break;	}	poplist();}voidexecexit(void){	switch(count(runq->argv->words)){	default:		pfmt(err, "Usage: exit [status]\nExiting anyway\n");	case 2:		setstatus(runq->argv->words->next->word);	case 1:	Xexit();	}}voidexecshift(void){	int n;	word *a;	var *star;	switch(count(runq->argv->words)){	default:		pfmt(err, "Usage: shift [n]\n");		setstatus("shift usage");		poplist();		return;	case 2:		n = atoi(runq->argv->words->next->word);		break;	case 1:		n = 1;		break;	}	star = vlook("*");	for(;n && star->val;--n){		a = star->val->next;		efree(star->val->word);		efree((char *)star->val);		star->val = a;		star->changed = 1;	}	setstatus("");	poplist();}intoctal(char *s){	int n = 0;	while(*s==' ' || *s=='\t' || *s=='\n') s++;	while('0'<=*s && *s<='7') n = n*8+*s++-'0';	return n;}intmapfd(int fd){	redir *rp;	for(rp = runq->redir;rp;rp = rp->next){		switch(rp->type){		case RCLOSE:			if(rp->from==fd)				fd=-1;			break;		case RDUP:		case ROPEN:			if(rp->to==fd)				fd = rp->from;			break;		}	}	return fd;}union code rdcmds[4];voidexeccmds(io *f){	static int first = 1;	if(first){		rdcmds[0].i = 1;		rdcmds[1].f = Xrdcmds;		rdcmds[2].f = Xreturn;		first = 0;	}	start(rdcmds, 1, runq->local);	runq->cmdfd = f;	runq->iflast = 0;}voidexeceval(void){	char *cmdline, *s, *t;	int len = 0;	word *ap;	if(count(runq->argv->words)<=1){		Xerror1("Usage: eval cmd ...");		return;	}	eflagok = 1;	for(ap = runq->argv->words->next;ap;ap = ap->next)		len+=1+strlen(ap->word);	cmdline = emalloc(len);	s = cmdline;	for(ap = runq->argv->words->next;ap;ap = ap->next){		for(t = ap->word;*t;) *s++=*t++;		*s++=' ';	}	s[-1]='\n';	poplist();	execcmds(opencore(cmdline, len));	efree(cmdline);}union code dotcmds[14];voidexecdot(void){	int iflag = 0;	int fd;	list *av;	thread *p = runq;	char *zero;	static int first = 1;	char file[512];	word *path;	if(first){		dotcmds[0].i = 1;		dotcmds[1].f = Xmark;		dotcmds[2].f = Xword;		dotcmds[3].s="0";		dotcmds[4].f = Xlocal;		dotcmds[5].f = Xmark;		dotcmds[6].f = Xword;		dotcmds[7].s="*";		dotcmds[8].f = Xlocal;		dotcmds[9].f = Xrdcmds;		dotcmds[10].f = Xunlocal;		dotcmds[11].f = Xunlocal;		dotcmds[12].f = Xreturn;		first = 0;	}	else		eflagok = 1;	popword();	if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){		iflag = 1;		popword();	}	/* get input file */	if(p->argv->words==0){		Xerror1("Usage: . [-i] file [arg ...]");		return;	}	zero = strdup(p->argv->words->word);	popword();	fd=-1;	for(path = searchpath(zero);path;path = path->next){		strcpy(file, path->word);		if(file[0])			strcat(file, "/");		strcat(file, zero);		if((fd = open(file, 0))>=0) break;		if(strcmp(file, "/dev/stdin")==0){	/* for sun & ucb */			fd = Dup1(0);			if(fd>=0)				break;		}	}	if(fd<0){		pfmt(err, "%s: ", zero);		setstatus("can't open");		Xerror(".: can't open");		return;	}	/* set up for a new command loop */	start(dotcmds, 1, (struct var *)0);	pushredir(RCLOSE, fd, 0);	runq->cmdfile = zero;	runq->cmdfd = openfd(fd);	runq->iflag = iflag;	runq->iflast = 0;	/* push $* value */	pushlist();	runq->argv->words = p->argv->words;	/* free caller's copy of $* */	av = p->argv;	p->argv = av->next;	efree((char *)av);	/* push $0 value */	pushlist();	pushword(zero);	ndot++;}voidexecflag(void){	char *letter, *val;	switch(count(runq->argv->words)){	case 2:		setstatus(flag[runq->argv->words->next->word[0]]?"":"flag not set");		break;	case 3:		letter = runq->argv->words->next->word;		val = runq->argv->words->next->next->word;		if(strlen(letter)==1){			if(strcmp(val, "+")==0){				flag[letter[0]] = flagset;				break;			}			if(strcmp(val, "-")==0){				flag[letter[0]] = 0;				break;			}		}	default:		Xerror1("Usage: flag [letter] [+-]");		return;	}	poplist();}voidexecwhatis(void){	/* mildly wrong -- should fork before writing */	word *a, *b, *path;	var *v;	struct builtin *bp;	char file[512];	struct io out[1];	int found, sep;	a = runq->argv->words->next;	if(a==0){		Xerror1("Usage: whatis name ...");		return;	}	setstatus("");	out->fd = mapfd(1);	out->bufp = out->buf;	out->ebuf = &out->buf[NBUF];	out->strp = 0;	for(;a;a = a->next){		v = vlook(a->word);		if(v->val){			pfmt(out, "%s=", a->word);			if(v->val->next==0)				pfmt(out, "%q\n", v->val->word);			else{				sep='(';				for(b = v->val;b && b->word;b = b->next){					pfmt(out, "%c%q", sep, b->word);					sep=' ';				}				pfmt(out, ")\n");			}			found = 1;		}		else			found = 0;		v = gvlook(a->word);		if(v->fn)			pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);		else{			for(bp = Builtin;bp->name;bp++)				if(strcmp(a->word, bp->name)==0){					pfmt(out, "builtin %s\n", a->word);					break;				}			if(!bp->name){				for(path = searchpath(a->word);path;path = path->next){					strcpy(file, path->word);					if(file[0])						strcat(file, "/");					strcat(file, a->word);					if(Executable(file)){						pfmt(out, "%s\n", file);						break;					}				}				if(!path && !found){					pfmt(err, "%s: not found\n", a->word);					setstatus("not found");				}			}		}	}	poplist();	flush(err);}voidexecwait(void){	switch(count(runq->argv->words)){	default:		Xerror1("Usage: wait [pid]");		return;	case 2:		Waitfor(atoi(runq->argv->words->next->word), 0);		break;	case 1:		Waitfor(-1, 0);		break;	}	poplist();}

⌨️ 快捷键说明

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