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

📄 main.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif /* KSH */	} else		Flag(FTRACKALL) = 1;	/* set after ENV */	shell(s, TRUE);	/* doesn't return */	return 0;}intinclude(name, argc, argv, intr_ok)	const char *name;	int argc;	char **argv;	int intr_ok;{	register Source *volatile s = NULL;	Source *volatile sold;	struct shf *shf;	char **volatile old_argv;	volatile int old_argc;	int i;	shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);	if (shf == NULL)		return -1;	if (argv) {		old_argv = e->loc->argv;		old_argc = e->loc->argc;	} else {		old_argv = (char **) 0;		old_argc = 0;	}	sold = source;	newenv(E_INCL);	i = ksh_sigsetjmp(e->jbuf, 0);	if (i) {		source = sold;		if (s) /* Do this before quitenv(), which frees the memory */			shf_close(s->u.shf);		quitenv();		if (old_argv) {			e->loc->argv = old_argv;			e->loc->argc = old_argc;		}		switch (i) {		  case LRETURN:		  case LERROR:			return exstat & 0xff; /* see below */		  case LINTR:			/* intr_ok is set if we are including .profile or $ENV.			 * If user ^C's out, we don't want to kill the shell...			 */			if (intr_ok && (exstat - 128) != SIGTERM)				return 1;			/* fall through... */		  case LEXIT:		  case LLEAVE:		  case LSHELL:			unwind(i);			/*NOREACHED*/		  default:			internal_errorf(1, "include: %d", i);			/*NOREACHED*/		}	}	if (argv) {		e->loc->argv = argv;		e->loc->argc = argc;	}	s = pushs(SFILE, ATEMP);	s->u.shf = shf;	s->file = str_save(name, ATEMP);	i = shell(s, FALSE);	source = sold;	shf_close(s->u.shf);	quitenv();	if (old_argv) {		e->loc->argv = old_argv;		e->loc->argc = old_argc;	}	return i & 0xff;	/* & 0xff to ensure value not -1 */}intcommand(comm)	const char *comm;{	register Source *s;	s = pushs(SSTRING, ATEMP);	s->start = s->str = comm;	return shell(s, FALSE);}/* * run the commands from the input source, returning status. */intshell(s, toplevel)	Source *volatile s;		/* input source */	int volatile toplevel;{	struct op *t;	volatile int wastty = s->flags & SF_TTY;	volatile int attempts = 13;	volatile int interactive = Flag(FTALKING) && toplevel;	int i;	newenv(E_PARSE);	if (interactive)		really_exit = 0;	i = ksh_sigsetjmp(e->jbuf, 0);	if (i) {		s->start = s->str = null;		switch (i) {		  case LINTR: /* we get here if SIGINT not caught or ignored */		  case LERROR:		  case LSHELL:			if (interactive) {				if (i == LINTR)					shellf(newline);				/* Reset any eof that was read as part of a				 * multiline command.				 */				if (Flag(FIGNOREEOF) && s->type == SEOF				    && wastty)					s->type = SSTDIN;				/* Used by exit command to get back to				 * top level shell.  Kind of strange since				 * interactive is set if we are reading from				 * a tty, but to have stopped jobs, one only				 * needs FMONITOR set (not FTALKING/SF_TTY)...				 */				break;			}			/* fall through... */		  case LEXIT:		  case LLEAVE:		  case LRETURN:			quitenv();			unwind(i);	/* keep on going */			/*NOREACHED*/		  default:			quitenv();			internal_errorf(1, "shell: %d", i);			/*NOREACHED*/		}	}	while (1) {		if (trap)			runtraps(0);		if (s->next == NULL)			if (Flag(FVERBOSE))				s->flags |= SF_ECHO;			else				s->flags &= ~SF_ECHO;		if (interactive) {			j_notify();#ifdef KSH			mcheck();#endif /* KSH */			set_prompt(PS1, s);		}		t = compile(s);		if (t != NULL && t->type == TEOF) {			if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {				shellf("Use `exit' to leave ksh\n");				s->type = SSTDIN;			} else if (wastty && !really_exit				   && j_stopped_running())			{				really_exit = 1;				s->type = SSTDIN;			} else {				/* this for POSIX, which says EXIT traps				 * shall be taken in the environment				 * immediately after the last command				 * executed.				 */				if (toplevel)					unwind(LEXIT);				break;			}		}		if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY)))			exstat = execute(t, 0);		if (t != NULL && t->type != TEOF && interactive && really_exit)			really_exit = 0;		reclaim();	}	quitenv();	return exstat;}/* return to closest error handler or shell(), exit if none found */voidunwind(i)	int i;{	/* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */	if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR)			   && sigtraps[SIGEXIT_].trap))	{		runtrap(&sigtraps[SIGEXIT_]);		i = LLEAVE;	} else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) {		runtrap(&sigtraps[SIGERR_]);		i = LLEAVE;	}	while (1) {		switch (e->type) {		  case E_PARSE:		  case E_FUNC:		  case E_INCL:		  case E_LOOP:		  case E_ERRH:			ksh_siglongjmp(e->jbuf, i);			/*NOTREACHED*/		  case E_NONE:			if (i == LINTR)				e->flags |= EF_FAKE_SIGDIE;			/* Fall through... */		  default:			quitenv();		}	}}voidnewenv(type)	int type;{	register struct env *ep;	ep = (struct env *) alloc(sizeof(*ep), ATEMP);	ep->type = type;	ep->flags = 0;	ainit(&ep->area);	ep->loc = e->loc;	ep->savefd = NULL;	ep->oenv = e;	ep->temps = NULL;	e = ep;}voidquitenv(){	register struct env *ep = e;	register int fd;	if (ep->oenv && ep->oenv->loc != ep->loc)		popblock();	if (ep->savefd != NULL) {		for (fd = 0; fd < NUFILE; fd++)			/* if ep->savefd[fd] < 0, means fd was closed */			if (ep->savefd[fd])				restfd(fd, ep->savefd[fd]);		if (ep->savefd[2]) /* Clear any write errors */			shf_reopen(2, SHF_WR, shl_out);	}	reclaim();	/* Bottom of the stack.	 * Either main shell is exiting or cleanup_parents_env() was called.	 */	if (ep->oenv == NULL) {		if (ep->type == E_NONE) {	/* Main shell exiting? */			if (Flag(FTALKING))				hist_finish();			j_exit();			if (ep->flags & EF_FAKE_SIGDIE) {				int sig = exstat - 128;				/* ham up our death a bit (at&t ksh				 * only seems to do this for SIGTERM)				 * Don't do it for SIGQUIT, since we'd				 * dump a core..				 */				if (sig == SIGINT || sig == SIGTERM) {					setsig(&sigtraps[sig], SIG_DFL,						SS_RESTORE_CURR|SS_FORCE);					kill(0, sig);				}			}#ifdef MEM_DEBUG			chmem_allfree();#endif /* MEM_DEBUG */		}		exit(exstat);	}	e = e->oenv;	afree(ep, ATEMP);}/* Called after a fork to cleanup stuff left over from parents environment */voidcleanup_parents_env(){	struct env *ep;	int fd;	/* Don't clean up temporary files - parent will probably need them.	 * Also, can't easily reclaim memory since variables, etc. could be	 * anywyere.	 */	/* close all file descriptors hiding in savefd */	for (ep = e; ep; ep = ep->oenv) {		if (ep->savefd) {			for (fd = 0; fd < NUFILE; fd++)				if (ep->savefd[fd] > 0)					close(ep->savefd[fd]);			afree(ep->savefd, &ep->area);			ep->savefd = (short *) 0;		}	}	e->oenv = (struct env *) 0;}/* Called just before an execve cleanup stuff temporary files */voidcleanup_proc_env(){	struct env *ep;	for (ep = e; ep; ep = ep->oenv)		remove_temps(ep->temps);}/* remove temp files and free ATEMP Area */static voidreclaim(){	remove_temps(e->temps);	e->temps = NULL;	afreeall(&e->area);}static voidremove_temps(tp)	struct temp *tp;{#ifdef OS2	static struct temp *delayed_remove;	struct temp *t, **tprev;	if (delayed_remove) {		for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev)			/* No need to check t->pid here... */			if (unlink(t->name) >= 0 || errno == ENOENT) {				*tprev = t->next;				afree(t, APERM);			} else				tprev = &t->next;	}#endif /* OS2 */	for (; tp != NULL; tp = tp->next)		if (tp->pid == procpid) {#ifdef OS2			/* OS/2 (and dos) do not allow files that are currently			 * open to be removed, so we cache it away for future			 * removal.			 * XXX should only do this if errno			 *     is Efile-still-open-can't-remove			 *     (but I don't know what that is...)			 */			if (unlink(tp->name) < 0 && errno != ENOENT) {				t = (struct temp *) alloc(				    sizeof(struct temp) + strlen(tp->name) + 1,				    APERM);				memset(t, 0, sizeof(struct temp));				t->name = (char *) &t[1];				strcpy(t->name, tp->name);				t->next = delayed_remove;				delayed_remove = t;			}#else /* OS2 */			unlink(tp->name);#endif /* OS2 */		}}/* Returns true if name refers to a restricted shell */static intis_restricted(name)	char *name;{	char *p;	/* this silly function prevents you running a command called runconf.sh. */	/* we don't care about restricted shells, which aren't very restricted anyway */	/* and introduce a false sense of security */	return 0;#ifdef dumbidea	if ((p = ksh_strrchr_dirsep(name)))		name = p;	/* accepts rsh, rksh, rpdksh, pdrksh, etc. */	return (p = strchr(name, 'r')) && strstr(p, "sh");#endif}voidaerror(ap, msg)	Area *ap;	const char *msg;{	internal_errorf(1, "alloc: %s", msg);	errorf(null); /* this is never executed - keeps gcc quiet */	/*NOTREACHED*/}

⌨️ 快捷键说明

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