Ejemplo n.º 1
0
static int
herein(struct ioword *iop, char **resbuf)
{
	int fd = -1;
	struct shf *shf;
	struct temp *h;
	int i;

	/* ksh -c 'cat <<EOF' can cause this... */
	if (iop->heredoc == NULL && !(iop->ioflag & IOHERESTR)) {
		warningf(true, "%s missing", "here document");
		/* special to iosetup(): don't print error */
		return (-2);
	}

	/* lexer substitution flags */
	i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;

	/* skip all the fd setup if we just want the value */
	if (resbuf != NULL)
		return (hereinval(iop, i, resbuf, NULL));

	/*
	 * 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 = binopen3(h->tffn, O_RDONLY, 0)) < 0) {
		i = errno;
		warningf(true, "can't %s temporary file %s: %s",
		    !shf ? "create" : "open", h->tffn, cstrerror(i));
		if (shf)
			shf_close(shf);
		/* special to iosetup(): don't print error */
		return (-2);
	}

	if (hereinval(iop, i, NULL, shf) == -2) {
		close(fd);
		/* special to iosetup(): don't print error */
		return (-2);
	}

	if (shf_close(shf) == -1) {
		i = errno;
		close(fd);
		warningf(true, "can't %s temporary file %s: %s",
		    "write", h->tffn, cstrerror(i));
		/* special to iosetup(): don't print error */
		return (-2);
	}

	return (fd);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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->ioname;
	int iotype = iop->ioflag & 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.ioname = (iotype == IOHERE) ? NULL : cp;
	iotmp.ioflag |= IONAMEXP;

	if (Flag(FXTRACE)) {
		change_xtrace(2, false);
		fptreef(shl_xtrace, 0, "%R", &iotmp);
		change_xtrace(1, false);
	}

	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->ioflag & 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 (ksh_isdash(cp)) {
			/* prevent error return below */
			u = 1009;
			do_close = true;
		} else if ((u = check_fd(cp,
		    X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
		    &emsg)) < 0) {
			char *sp;

			warningf(true, "%s: %s",
			    (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg);
			afree(sp, ATEMP);
			return (-1);
		}
		if (u == (int)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 = binopen3(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 == (int)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 != (int)iop->unit) {
		if (ksh_dup2(u, iop->unit, true) < 0) {
			int eno;
			char *sp;

			eno = errno;
			warningf(true, "%s %s: %s",
			    "can't finish (dup) redirection",
			    (sp = snptreef(NULL, 32, "%R", &iotmp)),
			    cstrerror(eno));
			afree(sp, ATEMP);
			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->ioflag & 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);
}