Пример #1
0
void
openpipe(int *pv)
{
	int lpv[2];

	if (pipe(lpv) < 0)
		errorf("can't create pipe - try again");
	pv[0] = savefd(lpv[0]);
	if (pv[0] != lpv[0])
		close(lpv[0]);
	pv[1] = savefd(lpv[1]);
	if (pv[1] != lpv[1])
		close(lpv[1]);
}
Пример #2
0
void
openpipe(int *pv)
{
	int lpv[2];

	if (pipe(lpv) < 0)
		errorf("can't create pipe - try again");
	pv[0] = savefd(lpv[0]);
	if (pv[0] != lpv[0])
		close(lpv[0]);
	pv[1] = savefd(lpv[1]);
	if (pv[1] != lpv[1])
		close(lpv[1]);
#ifdef __OS2__
	setmode(pv[0], O_BINARY);
	setmode(pv[1], O_BINARY);
#endif
}
Пример #3
0
void
setjobctl(int on)
{
	int fd;
	int pgrp;

	if (on == jobctl || rootshell == 0)
		return;
	if (on) {
		int ofd;
		ofd = fd = open(_PATH_TTY, O_RDWR);
		if (fd < 0) {
			fd += 3;
			while (!isatty(fd))
				if (--fd < 0)
					goto out;
		}
		fd = savefd(fd, ofd);
		do { /* while we are in the background */
			if ((pgrp = tcgetpgrp(fd)) < 0) {
out:
				sh_warnx("can't access tty; job control turned off");
				mflag = on = 0;
				goto close;
			}
			if (pgrp == getpgrp())
				break;
			killpg(0, SIGTTIN);
		} while (1);
		initialpgrp = pgrp;

		setsignal(SIGTSTP);
		setsignal(SIGTTOU);
		setsignal(SIGTTIN);
		pgrp = rootpid;
		setpgid(0, pgrp);
		xtcsetpgrp(fd, pgrp);
	} else {
		/* turning job control off */
		fd = ttyfd;
		pgrp = initialpgrp;
		xtcsetpgrp(fd, pgrp);
		setpgid(0, pgrp);
		setsignal(SIGTSTP);
		setsignal(SIGTTOU);
		setsignal(SIGTTIN);
close:
		close(fd);
		fd = -1;
	}
	ttyfd = fd;
	jobctl = on;
}
Пример #4
0
int
setinputfile(const char *fname, int flags)
{
	int fd;

	INTOFF;
	if ((fd = open(fname, O_RDONLY)) < 0) {
		if (flags & INPUT_NOFILE_OK)
			goto out;
		exitstatus = 127;
		exerror(EXERROR, "Can't open %s", fname);
	}
	if (fd < 10)
		fd = savefd(fd, fd);
	setinputfd(fd, flags & INPUT_PUSH_FILE);
out:
	INTON;
	return fd;
}
Пример #5
0
void
change_xtrace(unsigned char newval, bool dosnapshot)
{
	static bool in_xtrace;

	if (in_xtrace)
		return;

	if (!dosnapshot && newval == Flag(FXTRACE))
		return;

	if (Flag(FXTRACE) == 2) {
		shf_putc('\n', shl_xtrace);
		Flag(FXTRACE) = 1;
		shf_flush(shl_xtrace);
	}

	if (!dosnapshot && Flag(FXTRACE) == 1)
		switch (newval) {
		case 1:
			return;
		case 2:
			goto changed_xtrace;
		}

	shf_flush(shl_xtrace);
	if (shl_xtrace->fd != 2)
		close(shl_xtrace->fd);
	if (!newval || (shl_xtrace->fd = savefd(2)) == -1)
		shl_xtrace->fd = 2;

 changed_xtrace:
	if ((Flag(FXTRACE) = newval) == 2) {
		in_xtrace = true;
		Flag(FXTRACE) = 0;
		shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace);
		Flag(FXTRACE) = 2;
		in_xtrace = false;
	}
}
Пример #6
0
/*
 * execute command tree
 */
int
execute(struct op * volatile t,
    /* if XEXEC don't fork */
    volatile int flags,
    volatile int * volatile xerrok)
{
	int i;
	volatile int rv = 0, dummy = 0;
	int pv[2];
	const char ** volatile ap = NULL;
	char ** volatile up;
	const char *s, *ccp;
	struct ioword **iowp;
	struct tbl *tp = NULL;
	char *cp;

	if (t == NULL)
		return (0);

	/* Caller doesn't care if XERROK should propagate. */
	if (xerrok == NULL)
		xerrok = &dummy;

	if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
		/* run in sub-process */
		return (exchild(t, flags & ~XTIME, xerrok, -1));

	newenv(E_EXEC);
	if (trap)
		runtraps(0);

	/* we want to run an executable, do some variance checks */
	if (t->type == TCOM) {
		/* check if this is 'var=<<EOF' */
		if (
		    /* we have zero arguments, i.e. no programme to run */
		    t->args[0] == NULL &&
		    /* we have exactly one variable assignment */
		    t->vars[0] != NULL && t->vars[1] == NULL &&
		    /* we have exactly one I/O redirection */
		    t->ioact != NULL && t->ioact[0] != NULL &&
		    t->ioact[1] == NULL &&
		    /* of type "here document" (or "here string") */
		    (t->ioact[0]->flag & IOTYPE) == IOHERE &&
		    /* the variable assignment begins with a valid varname */
		    (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
		    /* and has no right-hand side (i.e. "varname=") */
		    ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
		    /* plus we can have a here document content */
		    herein(t->ioact[0], &cp) == 0 && cp && *cp) {
			char *sp = cp, *dp;
			size_t n = ccp - t->vars[0] + 2, z;

			/* drop redirection (will be garbage collected) */
			t->ioact = NULL;

			/* set variable to its expanded value */
			z = strlen(cp) + 1;
			if (notoktomul(z, 2) || notoktoadd(z * 2, n))
				internal_errorf(Toomem, (unsigned long)-1);
			dp = alloc(z * 2 + n, ATEMP);
			memcpy(dp, t->vars[0], n);
			t->vars[0] = dp;
			dp += n;
			while (*sp) {
				*dp++ = QCHAR;
				*dp++ = *sp++;
			}
			*dp = EOS;
			/* free the expanded value */
			afree(cp, APERM);
		}

		/*
		 * Clear subst_exstat before argument expansion. Used by
		 * null commands (see comexec() and c_eval()) and by c_set().
		 */
		subst_exstat = 0;

		/* for $LINENO */
		current_lineno = t->lineno;

		/*
		 * POSIX says expand command words first, then redirections,
		 * and assignments last..
		 */
		up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
		if (flags & XTIME)
			/* Allow option parsing (bizarre, but POSIX) */
			timex_hook(t, &up);
		ap = (const char **)up;
		if (Flag(FXTRACE) && ap[0]) {
			shf_puts(substitute(str_val(global("PS4")), 0),
			    shl_out);
			for (i = 0; ap[i]; i++)
				shf_fprintf(shl_out, "%s%c", ap[i],
				    ap[i + 1] ? ' ' : '\n');
			shf_flush(shl_out);
		}
		if (ap[0])
			tp = findcom(ap[0], FC_BI|FC_FUNC);
	}
	flags &= ~XTIME;

	if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) {
		e->savefd = alloc2(NUFILE, sizeof(short), ATEMP);
		/* initialise to not redirected */
		memset(e->savefd, 0, NUFILE * sizeof(short));
	}

	/* mark for replacement later (unless TPIPE) */
	vp_pipest->flag |= INT_L;

	/* do redirection, to be restored in quitenv() */
	if (t->ioact != NULL)
		for (iowp = t->ioact; *iowp != NULL; iowp++) {
			if (iosetup(*iowp, tp) < 0) {
				exstat = rv = 1;
				/*
				 * Redirection failures for special commands
				 * cause (non-interactive) shell to exit.
				 */
				if (tp && tp->type == CSHELL &&
				    (tp->flag & SPEC_BI))
					errorfz();
				/* Deal with FERREXIT, quitenv(), etc. */
				goto Break;
			}
		}

	switch (t->type) {
	case TCOM:
		rv = comexec(t, tp, (const char **)ap, flags, xerrok);
		break;

	case TPAREN:
		rv = execute(t->left, flags | XFORK, xerrok);
		break;

	case TPIPE:
		flags |= XFORK;
		flags &= ~XEXEC;
		e->savefd[0] = savefd(0);
		e->savefd[1] = savefd(1);
		while (t->type == TPIPE) {
			openpipe(pv);
			/* stdout of curr */
			ksh_dup2(pv[1], 1, false);
			/**
			 * Let exchild() close pv[0] in child
			 * (if this isn't done, commands like
			 *	(: ; cat /etc/termcap) | sleep 1
			 * will hang forever).
			 */
			exchild(t->left, flags | XPIPEO | XCCLOSE,
			    NULL, pv[0]);
			/* stdin of next */
			ksh_dup2(pv[0], 0, false);
			closepipe(pv);
			flags |= XPIPEI;
			t = t->right;
		}
		/* stdout of last */
		restfd(1, e->savefd[1]);
		/* no need to re-restore this */
		e->savefd[1] = 0;
		/* Let exchild() close 0 in parent, after fork, before wait */
		i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0);
		if (!(flags&XBGND) && !(flags&XXCOM))
			rv = i;
		break;

	case TLIST:
		while (t->type == TLIST) {
			execute(t->left, flags & XERROK, NULL);
			t = t->right;
		}
		rv = execute(t, flags & XERROK, xerrok);
		break;

	case TCOPROC: {
#ifndef MKSH_NOPROSPECTOFWORK
		sigset_t omask;

		/*
		 * Block sigchild as we are using things changed in the
		 * signal handler
		 */
		sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
		e->type = E_ERRH;
		if ((i = kshsetjmp(e->jbuf))) {
			sigprocmask(SIG_SETMASK, &omask, NULL);
			quitenv(NULL);
			unwind(i);
			/* NOTREACHED */
		}
#endif
		/* Already have a (live) co-process? */
		if (coproc.job && coproc.write >= 0)
			errorf("coprocess already exists");

		/* Can we re-use the existing co-process pipe? */
		coproc_cleanup(true);

		/* do this before opening pipes, in case these fail */
		e->savefd[0] = savefd(0);
		e->savefd[1] = savefd(1);

		openpipe(pv);
		if (pv[0] != 0) {
			ksh_dup2(pv[0], 0, false);
			close(pv[0]);
		}
		coproc.write = pv[1];
		coproc.job = NULL;

		if (coproc.readw >= 0)
			ksh_dup2(coproc.readw, 1, false);
		else {
			openpipe(pv);
			coproc.read = pv[0];
			ksh_dup2(pv[1], 1, false);
			/* closed before first read */
			coproc.readw = pv[1];
			coproc.njobs = 0;
			/* create new coprocess id */
			++coproc.id;
		}
#ifndef MKSH_NOPROSPECTOFWORK
		sigprocmask(SIG_SETMASK, &omask, NULL);
		/* no more need for error handler */
		e->type = E_EXEC;
#endif

		/*
		 * exchild() closes coproc.* in child after fork,
		 * will also increment coproc.njobs when the
		 * job is actually created.
		 */
		flags &= ~XEXEC;
		exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE,
		    NULL, coproc.readw);
		break;
	}

	case TASYNC:
		/*
		 * XXX non-optimal, I think - "(foo &)", forks for (),
		 * forks again for async... parent should optimise
		 * this to "foo &"...
		 */
		rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok);
		break;

	case TOR:
	case TAND:
		rv = execute(t->left, XERROK, xerrok);
		if ((rv == 0) == (t->type == TAND))
			rv = execute(t->right, XERROK, xerrok);
		flags |= XERROK;
		if (xerrok)
			*xerrok = 1;
		break;

	case TBANG:
		rv = !execute(t->right, XERROK, xerrok);
		flags |= XERROK;
		if (xerrok)
			*xerrok = 1;
		break;

	case TDBRACKET: {
		Test_env te;

		te.flags = TEF_DBRACKET;
		te.pos.wp = t->args;
		te.isa = dbteste_isa;
		te.getopnd = dbteste_getopnd;
		te.eval = test_eval;
		te.error = dbteste_error;

		rv = test_parse(&te);
		break;
	}

	case TFOR:
	case TSELECT: {
		volatile bool is_first = true;
		ap = (t->vars == NULL) ? e->loc->argv + 1 :
		    (const char **)eval((const char **)t->vars,
		    DOBLANK | DOGLOB | DOTILDE);
		e->type = E_LOOP;
		while ((i = kshsetjmp(e->jbuf))) {
			if ((e->flags&EF_BRKCONT_PASS) ||
			    (i != LBREAK && i != LCONTIN)) {
				quitenv(NULL);
				unwind(i);
			} else if (i == LBREAK) {
				rv = 0;
				goto Break;
			}
		}
		/* in case of a continue */
		rv = 0;
		if (t->type == TFOR) {
			while (*ap != NULL) {
				setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
				rv = execute(t->left, flags & XERROK, xerrok);
			}
		} else {
			/* TSELECT */
			for (;;) {
				if (!(ccp = do_selectargs(ap, is_first))) {
					rv = 1;
					break;
				}
				is_first = false;
				setstr(global(t->str), ccp, KSH_UNWIND_ERROR);
				execute(t->left, flags & XERROK, xerrok);
			}
		}
		break;
	}

	case TWHILE:
	case TUNTIL:
		e->type = E_LOOP;
		while ((i = kshsetjmp(e->jbuf))) {
			if ((e->flags&EF_BRKCONT_PASS) ||
			    (i != LBREAK && i != LCONTIN)) {
				quitenv(NULL);
				unwind(i);
			} else if (i == LBREAK) {
				rv = 0;
				goto Break;
			}
		}
		/* in case of a continue */
		rv = 0;
		while ((execute(t->left, XERROK, NULL) == 0) ==
		    (t->type == TWHILE))
			rv = execute(t->right, flags & XERROK, xerrok);
		break;

	case TIF:
	case TELIF:
		if (t->right == NULL)
			/* should be error */
			break;
		rv = execute(t->left, XERROK, NULL) == 0 ?
		    execute(t->right->left, flags & XERROK, xerrok) :
		    execute(t->right->right, flags & XERROK, xerrok);
		break;

	case TCASE:
		i = 0;
		ccp = evalstr(t->str, DOTILDE);
		for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
			for (ap = (const char **)t->vars; *ap; ap++) {
				if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
				    gmatchx(ccp, s, false))) {
					rv = execute(t->left, flags & XERROK,
					    xerrok);
					i = 0;
					switch (t->u.charflag) {
					case '&':
						i = 1;
						/* FALLTHROUGH */
					case '|':
						goto TCASE_next;
					}
					goto TCASE_out;
				}
			}
			i = 0;
 TCASE_next:
			/* empty */;
		}
 TCASE_out:
		break;

	case TBRACE:
		rv = execute(t->left, flags & XERROK, xerrok);
		break;

	case TFUNCT:
		rv = define(t->str, t);
		break;

	case TTIME:
		/*
		 * Clear XEXEC so nested execute() call doesn't exit
		 * (allows "ls -l | time grep foo").
		 */
		rv = timex(t, flags & ~XEXEC, xerrok);
		break;

	case TEXEC:
		/* an eval'd TCOM */
		s = t->args[0];
		up = makenv();
		restoresigs();
		cleanup_proc_env();
		{
			union mksh_ccphack cargs;

			cargs.ro = t->args;
			execve(t->str, cargs.rw, up);
			rv = errno;
		}
		if (rv == ENOEXEC)
			scriptexec(t, (const char **)up);
		else
			errorf("%s: %s", s, cstrerror(rv));
	}
 Break:
	exstat = rv & 0xFF;
	if (vp_pipest->flag & INT_L) {
		unset(vp_pipest, 1);
		vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
		    ARRAY | INT_U;
		vp_pipest->val.i = rv;
	}

	/* restores IO */
	quitenv(NULL);
	if ((flags&XEXEC))
		/* exit child */
		unwind(LEXIT);
	if (rv != 0 && !(flags & XERROK) &&
	    (xerrok == NULL || !*xerrok)) {
		if (Flag(FERREXIT) & 0x80) {
			/* inside eval */
			Flag(FERREXIT) = 0;
		} else {
			trapsig(ksh_SIGERR);
			if (Flag(FERREXIT))
				unwind(LERROR);
		}
	}
	return (rv);
}
Пример #7
0
/*
 * set up redirection, saving old fds in e->savefd
 */
static int
iosetup(struct ioword *iop, struct tbl *tp)
{
	int u = -1;
	char *cp = iop->name;
	int iotype = iop->flag & IOTYPE;
	bool do_open = true, do_close = false;
	int flags = 0;
	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) ? NULL : cp;
	iotmp.flag |= IONAMEXP;

	if (Flag(FXTRACE))
		shellf("%s%s\n",
		    substitute(str_val(global("PS4")), 0),
		    snptreef(NULL, 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 = false;
		/* herein() returns -2 if error has been printed */
		u = herein(iop, NULL);
		/* cp may have wrong name */
		break;

	case IODUP: {
		const char *emsg;

		do_open = false;
		if (*cp == '-' && !cp[1]) {
			/* prevent error return below */
			u = 1009;
			do_close = true;
		} else if ((u = check_fd(cp,
		    X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
		    &emsg)) < 0) {
			warningf(true, "%s: %s",
			    snptreef(NULL, 32, "%R", &iotmp), emsg);
			return (-1);
		}
		if (u == iop->unit)
			/* "dup from" == "dup to" */
			return (0);
		break;
	    }
	}

	if (do_open) {
		if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
			warningf(true, "%s: %s", cp, "restricted");
			return (-1);
		}
		u = open(cp, flags, 0666);
	}
	if (u < 0) {
		/* herein() may already have printed message */
		if (u == -1) {
			u = errno;
			warningf(true, "can't %s %s: %s",
			    iotype == IODUP ? "dup" :
			    (iotype == IOREAD || iotype == IOHERE) ?
			    "open" : "create", cp, cstrerror(u));
		}
		return (-1);
	}
	/* Do not save if it has already been redirected (i.e. "cat >x >y"). */
	if (e->savefd[iop->unit] == 0) {
		/* If these are the same, it means unit was previously closed */
		if (u == iop->unit)
			e->savefd[iop->unit] = -1;
		else
			/*
			 * c_exec() assumes e->savefd[fd] set for any
			 * redirections. Ask savefd() not to close iop->unit;
			 * this 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);
	}

	if (do_close)
		close(iop->unit);
	else if (u != iop->unit) {
		if (ksh_dup2(u, iop->unit, true) < 0) {
			int eno;

			eno = errno;
			warningf(true, "%s %s %s",
			    "can't finish (dup) redirection",
			    snptreef(NULL, 32, "%R", &iotmp),
			    cstrerror(eno));
			if (iotype != IODUP)
				close(u);
			return (-1);
		}
		if (iotype != IODUP)
			close(u);
		/*
		 * 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);
		}
	}
	if (u == 2)
		/* Clear any write errors */
		shf_reopen(2, SHF_WR, shl_out);
	return (0);
}
Пример #8
0
struct temp *
maketemp(Area *ap, Temp_type type, struct temp **tlist)
{
	char *cp;
	size_t len;
	int i, j;
	struct temp *tp;
	const char *dir;
	struct stat sb;

	dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR;
	/* add "/shXXXXXX.tmp" plus NUL */
	len = strlen(dir);
	checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14);
	tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap);

	tp->shf = NULL;
	tp->pid = procpid;
	tp->type = type;

	if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) {
		tp->tffn[0] = '\0';
		goto maketemp_out;
	}

	cp = (void *)tp;
	cp += offsetof(struct temp, tffn[0]);
	memcpy(cp, dir, len);
	cp += len;
	memcpy(cp, "/shXXXXXX.tmp", 14);
	/* point to the first of six Xes */
	cp += 3;

	/* cyclically attempt to open a temporary file */
	do {
		/* generate random part of filename */
		len = 0;
		do {
			cp[len++] = digits_lc[rndget() % 36];
		} while (len < 6);

		/* check if this one works */
		if ((i = binopen3(tp->tffn, O_CREAT | O_EXCL | O_RDWR,
		    0600)) < 0 && errno != EEXIST)
			goto maketemp_out;
	} while (i < 0);

	if (type == TT_FUNSUB) {
		/* map us high and mark as close-on-exec */
		if ((j = savefd(i)) != i) {
			close(i);
			i = j;
		}

		/* operation mode for the shf */
		j = SHF_RD;
	} else
		j = SHF_WR;

	/* shf_fdopen cannot fail, so no fd leak */
	tp->shf = shf_fdopen(i, j, NULL);

 maketemp_out:
	tp->next = *tlist;
	*tlist = tp;
	return (tp);
}
Пример #9
0
struct temp *
maketemp(Area *ap, Temp_type type, struct temp **tlist)
{
	char *cp;
	size_t len;
	int i, j;
	struct temp *tp;
	const char *dir;
	struct stat sb;

	dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR;
	/* add "/shXXXXXX.tmp" plus NUL */
	len = strlen(dir);
	checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14);
	tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap);

	tp->shf = NULL;
	tp->pid = procpid;
	tp->type = type;

	if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) {
		tp->tffn[0] = '\0';
		goto maketemp_out;
	}

	cp = (void *)tp;
	cp += offsetof(struct temp, tffn[0]);
	memcpy(cp, dir, len);
	cp += len;
	memcpy(cp, "/shXXXXXX.tmp", 14);
	/* point to the first of six Xes */
	cp += 3;
	/* generate random part of filename */
	len = -1;
	do {
		i = rndget() % 36;
		cp[++len] = i < 26 ? 'a' + i : '0' + i - 26;
	} while (len < 5);

	/* cyclically attempt to open a temporary file */
	while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
	    0600)) < 0) {
		if (errno != EEXIST)
			goto maketemp_out;
		/* count down from z to a then from 9 to 0 */
		while (cp[len] == '0')
			if (!len--)
				goto maketemp_out;
		if (cp[len] == 'a')
			cp[len] = '9';
		else
			--cp[len];
		/* do another cycle */
	}

	if (type == TT_FUNSUB) {
		/* map us high and mark as close-on-exec */
		if ((j = savefd(i)) != i) {
			close(i);
			i = j;
		}

		/* operation mode for the shf */
		j = SHF_RD;
	} else
		j = SHF_WR;

	/* shf_fdopen cannot fail, so no fd leak */
	tp->shf = shf_fdopen(i, j, NULL);

 maketemp_out:
	tp->next = *tlist;
	*tlist = tp;
	return (tp);
}
Пример #10
0
/*
 * service routines for `execute'
 */
short
initio(struct ionod *iop, int save)
{
	unsigned char	*ion;
	int	iof, fd;
	int		ioufd;
	short	lastfd;
	int	newmode;

	lastfd = topfd;
	while (iop) {
		iof = iop->iofile;
		ion = mactrim(iop->ioname);
		ioufd = iof & IOUFD;

		if (*ion && (flags&noexec) == 0) {
			if (save) {
				fdmap[topfd].org_fd = ioufd;
				fdmap[topfd++].dup_fd = savefd(ioufd);
			}

			if (iof & IODOC) {
				struct tempblk tb;

				subst(chkopen(ion, 0), (fd = tmpfil(&tb)));

				/*
				 * pushed in tmpfil() --
				 * bug fix for problem with
				 * in-line scripts
				 */
				poptemp();

				fd = chkopen(tmpout, 0);
				unlink((const char *)tmpout);
			} else if (iof & IOMOV) {
				if (eq(minus, ion)) {
					fd = -1;
					close(ioufd);
				} else if ((fd = stoi(ion)) >= USERIO) {
					failed(ion, badfile);
				}
				else
					fd = dup(fd);
			} else if (((iof & IOPUT) == 0) && ((iof & IORDW) == 0))
				fd = chkopen(ion, 0);
			else if (iof & IORDW) /* For <> */ {
				newmode = O_RDWR|O_CREAT;
				fd = chkopen(ion, newmode);
			} else if (flags & rshflg) {
				failed(ion, restricted);
			} else if (iof & IOAPP &&
			    (fd = open((char *)ion, 1)) >= 0) {
				lseek(fd, (off_t)0, SEEK_END);
			} else {
				fd = create(ion);
			}
			if (fd >= 0)
				renamef(fd, ioufd);
		}

		iop = iop->ionxt;
	}
	return (lastfd);
}