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

📄 exec.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
				     ".com", ".bat", (char *) 0				   };	static char *rsuffixes[] = { ".ksh", ".", ".sh", ".cmd", ".bat",				      (char *) 0				   };	int i;	char *mpath = (char *) path;	char *tp = mpath + strlen(mpath);	char *p;	char **sfx; 	/* If a suffix has been specified, check if it is one of the	 * suffixes that indicate the file is executable - if so, change	 * the access test to R_OK...	 * This code assumes OS/2 files can have only one suffix...	 */	if ((p = strrchr((p = ksh_strrchr_dirsep(mpath)) ? p : mpath, '.'))) {		if (mode == X_OK) 			mode = R_OK;		return search_access1(mpath, mode, errnop);	}	/* Try appending the various suffixes.  Different suffixes for	 * read and execute 'cause we don't want to read an executable...	 */	sfx = mode == R_OK ? rsuffixes : xsuffixes;	for (i = 0; sfx[i]; i++) {		strcpy(tp, p = sfx[i]);		if (search_access1(mpath, R_OK, errnop) == 0)			return 0;		*tp = '\0';	}	return -1;#endif /* !OS2 */}#ifdef OS2static intsearch_access1(path, mode, errnop)	const char *path;	int mode;	int *errnop;		/* set if candidate found, but not suitable */{	int ret, err = 0;	struct stat statb;	if (stat(path, &statb) < 0)		return -1;	ret = eaccess(path, mode);	if (ret < 0)		err = errno; /* File exists, but we can't access it */	else if (!S_ISREG(statb.st_mode)) {		ret = -1;		err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;	}	if (err && errnop && !*errnop)		*errnop = err;	return ret;}#endif /* OS2 *//* * search for command with PATH */char *search(name, path, mode, errnop)	const char *name;	const char *path;	int mode;		/* R_OK or X_OK */	int *errnop;		/* set if candidate found, but not suitable */{	const char *sp, *p;	char *xp;	XString xs;	int namelen;	if (errnop)		*errnop = 0;#ifdef OS2	/* Xinit() allocates 8 additional bytes, so appended suffixes won't	 * overflow the memory.	 */	namelen = strlen(name) + 1;	Xinit(xs, xp, namelen, ATEMP);	memcpy(Xstring(xs, xp), name, namelen); 	if (ksh_strchr_dirsep(name)) {		if (search_access(Xstring(xs, xp), mode, errnop) >= 0)			return Xstring(xs, xp); /* not Xclose() - see above */		Xfree(xs, xp);		return NULL;	}	/* Look in current context always. (os2 style) */	if (search_access(Xstring(xs, xp), mode, errnop) == 0) 		return Xstring(xs, xp); /* not Xclose() - xp may be wrong */#else /* OS2 */	if (ksh_strchr_dirsep(name)) {		if (search_access(name, mode, errnop) == 0)			return (char *) name;		return NULL;	}	namelen = strlen(name) + 1;	Xinit(xs, xp, 128, ATEMP);#endif /* OS2 */	sp = path;	while (sp != NULL) {		xp = Xstring(xs, xp);		if (!(p = strchr(sp, PATHSEP)))			p = sp + strlen(sp);		if (p != sp) {			XcheckN(xs, xp, p - sp);			memcpy(xp, sp, p - sp);			xp += p - sp;			*xp++ = DIRSEP;		}		sp = p;		XcheckN(xs, xp, namelen);		memcpy(xp, name, namelen); 		if (search_access(Xstring(xs, xp), mode, errnop) == 0)#ifdef OS2 			return Xstring(xs, xp); /* Not Xclose() - see above */#else /* OS2 */			return Xclose(xs, xp + namelen);#endif /* OS2 */		if (*sp++ == '\0')			sp = NULL;	}	Xfree(xs, xp);	return NULL;}static intcall_builtin(tp, wp)	struct tbl *tp;	char **wp;{	int rv;	builtin_argv0 = wp[0];	builtin_flag = tp->flag;	shf_reopen(1, SHF_WR, shl_stdout);	shl_stdout_ok = 1;	ksh_getopt_reset(&builtin_opt, GF_ERROR);	rv = (*tp->val.f)(wp);	shf_flush(shl_stdout);	shl_stdout_ok = 0;	builtin_flag = 0;	builtin_argv0 = (char *) 0;	return rv;}/* * set up redirection, saving old fd's in e->savefd */static intiosetup(iop, tp)	register struct ioword *iop;	struct tbl *tp;{	register int u = -1;	char *cp = iop->name;	int iotype = iop->flag & IOTYPE;	int do_open = 1, do_close = 0, UNINITIALIZED(flags);	struct ioword iotmp;	struct stat statb;	if (iotype != IOHERE)		cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));	/* Used for tracing and error messages to print expanded cp */	iotmp = *iop;	iotmp.name = (iotype == IOHERE) ? (char *) 0 : cp;	iotmp.flag |= IONAMEXP;	if (Flag(FXTRACE))		shellf("%s%s\n",			PS4_SUBSTITUTE(str_val(global("PS4"))),			snptreef((char *) 0, 32, "%R", &iotmp));	switch (iotype) {	  case IOREAD:		flags = O_RDONLY;		break;	  case IOCAT:		flags = O_WRONLY | O_APPEND | O_CREAT;		break;	  case IOWRITE:		flags = O_WRONLY | O_CREAT | O_TRUNC;		/* The stat() is here to allow redirections to		 * things like /dev/null without error.		 */		if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB)		    && (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))			flags |= O_EXCL;		break;	  case IORDWR:		flags = O_RDWR | O_CREAT;		break;	  case IOHERE:		do_open = 0;		/* herein() returns -2 if error has been printed */		u = herein(iop->heredoc, iop->flag & IOEVAL);		/* cp may have wrong name */		break;	  case IODUP:	  {		const char *emsg;		do_open = 0;		if (*cp == '-' && !cp[1]) {			u = 1009;	 /* prevent error return below */			do_close = 1;		} else if ((u = check_fd(cp,				X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),				&emsg)) < 0)		{			warningf(TRUE, "%s: %s",				snptreef((char *) 0, 32, "%R", &iotmp), emsg);			return -1;		}		break;	  }	}	if (do_open) {		if (Flag(FRESTRICTED) && (flags & O_CREAT)) {			warningf(TRUE, "%s: restricted", cp);			return -1;		}		u = open(cp, flags, 0666);#ifdef OS2		if (u < 0 && strcmp(cp, "/dev/null") == 0)			u = open("nul", flags, 0666);#endif /* OS2 */	}	if (u < 0) {		/* herein() may already have printed message */		if (u == -1)			warningf(TRUE, "cannot %s %s: %s",			       iotype == IODUP ? "dup"				: (iotype == IOREAD || iotype == IOHERE) ?				    "open" : "create", cp, strerror(errno));		return -1;	}	/* Do not save if it has already been redirected (i.e. "cat >x >y"). */	if (e->savefd[iop->unit] == 0)		/* c_exec() assumes e->savefd[fd] set for any redirections.		 * Ask savefd() not to close iop->unit - allows error messages		 * to be seen if iop->unit is 2; also means we can't lose		 * the fd (eg, both dup2 below and dup2 in restfd() failing).		 */		e->savefd[iop->unit] = savefd(iop->unit, 1);	if (do_close)		close(iop->unit);	else if (u != iop->unit) {		if (ksh_dup2(u, iop->unit, TRUE) < 0) {			warningf(TRUE,				"could not finish (dup) redirection %s: %s",				snptreef((char *) 0, 32, "%R", &iotmp),				strerror(errno));			if (iotype != IODUP)				close(u);			return -1;		}		if (iotype != IODUP)			close(u);#ifdef KSH		/* Touching any co-process fd in an empty exec		 * causes the shell to close its copies		 */		else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {			if (iop->flag & IORDUP)	/* possible exec <&p */				coproc_read_close(u);			else			/* possible exec >&p */				coproc_write_close(u);		}#endif /* KSH */	}	if (u == 2) /* Clear any write errors */		shf_reopen(2, SHF_WR, shl_out);	return 0;}/* * open here document temp file. * if unquoted here, expand here temp file into second temp file. */static intherein(content, sub)	const char *content;	int sub;{	volatile int fd = -1;	struct source *s, *volatile osource;	struct shf *volatile shf;	struct temp *h;	int i;	/* ksh -c 'cat << EOF' can cause this... */	if (content == (char *) 0) {		warningf(TRUE, "here document missing");		return -2; /* special to iosetup(): don't print error */	}	/* Create temp file to hold content (done before newenv so temp	 * doesn't get removed too soon).	 */	h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);	if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {		warningf(TRUE, "can't %s temporary file %s: %s",			!shf ? "create" : "open",			h->name, strerror(errno));		if (shf)			shf_close(shf);		return -2 /* special to iosetup(): don't print error */;	}	osource = source;	newenv(E_ERRH);	i = ksh_sigsetjmp(e->jbuf, 0);	if (i) {		source = osource;		quitenv();		shf_close(shf);	/* after quitenv */		close(fd);		return -2; /* special to iosetup(): don't print error */	}	if (sub) {		/* Do substitutions on the content of heredoc */		s = pushs(SSTRING, ATEMP);		s->start = s->str = content;		source = s;		if (yylex(ONEWORD) != LWORD)			internal_errorf(1, "herein: yylex");		source = osource;		shf_puts(evalstr(yylval.cp, 0), shf);	} else		shf_puts(content, shf);	quitenv();	if (shf_close(shf) == EOF) {		close(fd);		warningf(TRUE, "error writing %s: %s", h->name,			strerror(errno));		return -2; /* special to iosetup(): don't print error */	}	return fd;}#ifdef KSH/* *	ksh special - the select command processing section *	print the args in column form - assuming that we can */static char *do_selectargs(ap, print_menu)	register char **ap;	bool_t print_menu;{	static const char *const read_args[] = {					"read", "-r", "REPLY", (char *) 0				    };	char *s;	int i, argct;	for (argct = 0; ap[argct]; argct++)		;	while (1) {		/* Menu is printed if		 *	- this is the first time around the select loop		 *	- the user enters a blank line		 *	- the REPLY parameter is empty		 */		if (print_menu || !*str_val(global("REPLY")))			pr_menu(ap);		shellf("%s", str_val(global("PS3")));		if (call_builtin(findcom("read", FC_BI), (char **) read_args))			return (char *) 0;		s = str_val(global("REPLY"));		if (*s) {			i = atoi(s);			return (i >= 1 && i <= argct) ? ap[i - 1] : null;		}		print_menu = 1;	}}struct select_menu_info {	char	*const *args;	int	arg_width;	int	num_width;} info;static char *select_fmt_entry ARGS((void *arg, int i, char *buf, int buflen));/* format a single select menu item */static char *select_fmt_entry(arg, i, buf, buflen)	void *arg;	int i;	char *buf;	int buflen;{	struct select_menu_info *smi = (struct select_menu_info *) arg;	shf_snprintf(buf, buflen, "%*d) %s",		smi->num_width, i + 1, smi->args[i]);	return buf;}/* *	print a select style menu */intpr_menu(ap)	char *const *ap;{	struct select_menu_info smi;	char *const *pp;	int nwidth, dwidth;	int i, n;	/* Width/column calculations were done once and saved, but this	 * means select can't be used recursively so we re-calculate each	 * time (could save in a structure that is returned, but its probably	 * not worth the bother).	 */	/*	 * get dimensions of the list	 */	for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) {		i = strlen(*pp);		nwidth = (i > nwidth) ? i : nwidth;	}	/*	 * we will print an index of the form	 *	%d)	 * in front of each entry	 * get the max width of this	 */	for (i = n, dwidth = 1; i >= 10; i /= 10)		dwidth++;	smi.args = ap;	smi.arg_width = nwidth;	smi.num_width = dwidth;	print_columns(shl_out, n, select_fmt_entry, (void *) &smi,		dwidth + nwidth + 2);	return n;}#endif /* KSH */#ifdef KSH/* *	[[ ... ]] evaluation routines */extern const char *const dbtest_tokens[];extern const char db_close[];/* Test if the current token is a whatever.  Accepts the current token if * it is.  Returns 0 if it is not, non-zero if it is (in the case of * TM_UNOP and TM_BINOP, the returned value is a Test_op). */static intdbteste_isa(te, meta)	Test_env *te;	Test_meta meta;{	int ret = 0;	int uqword;	char *p;	if (!*te->pos.wp)		return meta == TM_END;	/* unquoted word? */	for (p = *te->pos.wp; *p == CHAR; p += 2)		;	uqword = *p == EOS;	if (meta == TM_UNOP || meta == TM_BINOP) {		if (uqword) {			char buf[8];	/* longer than the longest operator */			char *q = buf;			for (p = *te->pos.wp; *p == CHAR					      && q < &buf[sizeof(buf) - 1];					      p += 2)				*q++ = p[1];			*q = '\0';			ret = (int) test_isop(te, meta, buf);		}	} else if (meta == TM_END)		ret = 0;	else		ret = uqword			&& strcmp(*te->pos.wp, dbtest_tokens[(int) meta]) == 0;	/* Accept the token? */	if (ret)		te->pos.wp++;	return ret;}static const char *dbteste_getopnd(te, op, do_eval)	Test_env *te;	Test_op op;	int do_eval;{	char *s = *te->pos.wp;	if (!s)		return (char *) 0;	te->pos.wp++;	if (!do_eval)		return null;	if (op == TO_STEQL || op == TO_STNEQ)		s = evalstr(s, DOTILDE | DOPAT);	else		s = evalstr(s, DOTILDE);	return s;}static intdbteste_eval(te, op, opnd1, opnd2, do_eval)	Test_env *te;	Test_op op;	const char *opnd1;	const char *opnd2;	int do_eval;{	return test_eval(te, op, opnd1, opnd2, do_eval);}static voiddbteste_error(te, offset, msg)	Test_env *te;	int offset;	const char *msg;{	te->flags |= TEF_ERROR;	internal_errorf(0, "dbteste_error: %s (offset %d)", msg, offset);}#endif /* KSH */

⌨️ 快捷键说明

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