📄 exec.c
字号:
".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 + -