예제 #1
0
static void
pioact(struct shf *shf, int indent, struct ioword *iop)
{
	int flag = iop->flag;
	int type = flag & IOTYPE;
	int expected;

	expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
	    (type == IOCAT || type == IOWRITE) ? 1 :
	    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
	    iop->unit + 1;
	if (iop->unit != expected)
		shf_fprintf(shf, "%d", iop->unit);

	switch (type) {
	case IOREAD:
		shf_puts("<", shf);
		break;
	case IOHERE:
		shf_puts(flag & IOSKIP ? "<<-" : "<<", shf);
		break;
	case IOCAT:
		shf_puts(">>", shf);
		break;
	case IOWRITE:
		shf_puts(flag & IOCLOB ? ">|" : ">", shf);
		break;
	case IORDWR:
		shf_puts("<>", shf);
		break;
	case IODUP:
		shf_puts(flag & IORDUP ? "<&" : ">&", shf);
		break;
	}
	/* name/delim are NULL when printing syntax errors */
	if (type == IOHERE) {
		if (iop->delim)
			wdvarput(shf, iop->delim, 0, WDS_TPUTS);
		if (iop->flag & IOHERESTR)
			shf_putc(' ', shf);
	} else if (iop->name)
		fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
		    iop->name);
	prevent_semicolon = false;
}
예제 #2
0
파일: tree.c 프로젝트: Distrotech/mksh
/*
 * print a command tree
 */
static void
ptree(struct op *t, int indent, struct shf *shf)
{
	const char **w;
	struct ioword **ioact;
	struct op *t1;
	int i;

 Chain:
	if (t == NULL)
		return;
	switch (t->type) {
	case TCOM:
		prevent_semicolon = false;
		/*
		 * special-case 'var=<<EOF' (rough; see
		 * exec.c:execute() for full code)
		 */
		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) {
			fptreef(shf, indent, "%S", t->vars[0]);
			break;
		}

		if (t->vars) {
			w = (const char **)t->vars;
			while (*w)
				fptreef(shf, indent, "%S ", *w++);
		} else
			shf_puts("#no-vars# ", shf);
		if (t->args) {
			w = t->args;
			while (*w)
				fptreef(shf, indent, "%S ", *w++);
		} else
			shf_puts("#no-args# ", shf);
		break;
	case TEXEC:
		t = t->left;
		goto Chain;
	case TPAREN:
		fptreef(shf, indent + 2, "( %T) ", t->left);
		break;
	case TPIPE:
		fptreef(shf, indent, "%T| ", t->left);
		t = t->right;
		goto Chain;
	case TLIST:
		fptreef(shf, indent, "%T%;", t->left);
		t = t->right;
		goto Chain;
	case TOR:
	case TAND:
		fptreef(shf, indent, "%T%s %T",
		    t->left, (t->type == TOR) ? "||" : "&&", t->right);
		break;
	case TBANG:
		shf_puts("! ", shf);
		prevent_semicolon = false;
		t = t->right;
		goto Chain;
	case TDBRACKET:
		w = t->args;
		shf_puts("[[", shf);
		while (*w)
			fptreef(shf, indent, " %S", *w++);
		shf_puts(" ]] ", shf);
		break;
	case TSELECT:
	case TFOR:
		fptreef(shf, indent, "%s %s ",
		    (t->type == TFOR) ? "for" : Tselect, t->str);
		if (t->vars != NULL) {
			shf_puts("in ", shf);
			w = (const char **)t->vars;
			while (*w)
				fptreef(shf, indent, "%S ", *w++);
			fptreef(shf, indent, "%;");
		}
		fptreef(shf, indent + INDENT, "do%N%T", t->left);
		fptreef(shf, indent, "%;done ");
		break;
	case TCASE:
		fptreef(shf, indent, "case %S in", t->str);
		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
			fptreef(shf, indent, "%N(");
			w = (const char **)t1->vars;
			while (*w) {
				fptreef(shf, indent, "%S%c", *w,
				    (w[1] != NULL) ? '|' : ')');
				++w;
			}
			fptreef(shf, indent + INDENT, "%N%T%N;%c", t1->left,
			    t1->u.charflag);
		}
		fptreef(shf, indent, "%Nesac ");
		break;
#ifdef DEBUG
	case TELIF:
		internal_errorf("TELIF in tree.c:ptree() unexpected");
		/* FALLTHROUGH */
#endif
	case TIF:
		i = 2;
		t1 = t;
		goto process_TIF;
		do {
			t1 = t1->right;
			i = 0;
			fptreef(shf, indent, "%;");
 process_TIF:
			/* 5 == strlen("elif ") */
			fptreef(shf, indent + 5 - i, Telif_pT + i, t1->left);
			t1 = t1->right;
			if (t1->left != NULL) {
				fptreef(shf, indent, "%;");
				fptreef(shf, indent + INDENT, "%s%N%T",
				    "then", t1->left);
			}
		} while (t1->right && t1->right->type == TELIF);
		if (t1->right != NULL) {
			fptreef(shf, indent, "%;");
			fptreef(shf, indent + INDENT, "%s%N%T",
			    "else", t1->right);
		}
		fptreef(shf, indent, "%;fi ");
		break;
	case TWHILE:
	case TUNTIL:
		/* 6 == strlen("while "/"until ") */
		fptreef(shf, indent + 6, "%s %T",
		    (t->type == TWHILE) ? "while" : "until",
		    t->left);
		fptreef(shf, indent, "%;");
		fptreef(shf, indent + INDENT, "do%N%T", t->right);
		fptreef(shf, indent, "%;done ");
		break;
	case TBRACE:
		fptreef(shf, indent + INDENT, "{%N%T", t->left);
		fptreef(shf, indent, "%;} ");
		break;
	case TCOPROC:
		fptreef(shf, indent, "%T|& ", t->left);
		prevent_semicolon = true;
		break;
	case TASYNC:
		fptreef(shf, indent, "%T& ", t->left);
		prevent_semicolon = true;
		break;
	case TFUNCT:
		fpFUNCTf(shf, indent, tobool(t->u.ksh_func), t->str, t->left);
		break;
	case TTIME:
		fptreef(shf, indent, "%s %T", "time", t->left);
		break;
	default:
		shf_puts("<botch>", shf);
		prevent_semicolon = false;
		break;
	}
	if ((ioact = t->ioact) != NULL) {
		bool need_nl = false;

		while (*ioact != NULL)
			pioact(shf, *ioact++);
		/* Print here documents after everything else... */
		ioact = t->ioact;
		while (*ioact != NULL) {
			struct ioword *iop = *ioact++;

			/* heredoc is NULL when tracing (set -x) */
			if ((iop->flag & (IOTYPE | IOHERESTR)) == IOHERE &&
			    iop->heredoc) {
				shf_putc('\n', shf);
				shf_puts(iop->heredoc, shf);
				fptreef(shf, indent, "%s",
				    iop->flag & IONDELIM ? "<<" :
				    evalstr(iop->delim, 0));
				need_nl = true;
			}
		}
		/*
		 * Last delimiter must be followed by a newline (this
		 * often leads to an extra blank line, but it's not
		 * worth worrying about)
		 */
		if (need_nl) {
			shf_putc('\n', shf);
			prevent_semicolon = true;
		}
	}
}
예제 #3
0
파일: tree.c 프로젝트: aalm/obsd-src
static void
ptree(struct op *t, int indent, struct shf *shf)
{
	char **w;
	struct ioword **ioact;
	struct op *t1;

 Chain:
	if (t == NULL)
		return;
	switch (t->type) {
	case TCOM:
		if (t->vars)
			for (w = t->vars; *w != NULL; )
				fptreef(shf, indent, "%S ", *w++);
		else
			fptreef(shf, indent, "#no-vars# ");
		if (t->args)
			for (w = t->args; *w != NULL; )
				fptreef(shf, indent, "%S ", *w++);
		else
			fptreef(shf, indent, "#no-args# ");
		break;
	case TEXEC:
#if 0 /* ?not useful - can't be called? */
		/* Print original vars */
		if (t->left->vars)
			for (w = t->left->vars; *w != NULL; )
				fptreef(shf, indent, "%S ", *w++);
		else
			fptreef(shf, indent, "#no-vars# ");
		/* Print expanded vars */
		if (t->args)
			for (w = t->args; *w != NULL; )
				fptreef(shf, indent, "%s ", *w++);
		else
			fptreef(shf, indent, "#no-args# ");
		/* Print original io */
		t = t->left;
#else
		t = t->left;
		goto Chain;
#endif
	case TPAREN:
		fptreef(shf, indent + 2, "( %T) ", t->left);
		break;
	case TPIPE:
		fptreef(shf, indent, "%T| ", t->left);
		t = t->right;
		goto Chain;
	case TLIST:
		fptreef(shf, indent, "%T%;", t->left);
		t = t->right;
		goto Chain;
	case TOR:
	case TAND:
		fptreef(shf, indent, "%T%s %T",
		    t->left, (t->type==TOR) ? "||" : "&&", t->right);
		break;
	case TBANG:
		fptreef(shf, indent, "! ");
		t = t->right;
		goto Chain;
	case TDBRACKET:
	  {
		int i;

		fptreef(shf, indent, "[[");
		for (i = 0; t->args[i]; i++)
			fptreef(shf, indent, " %S", t->args[i]);
		fptreef(shf, indent, " ]] ");
		break;
	  }
	case TSELECT:
		fptreef(shf, indent, "select %s ", t->str);
		/* FALLTHROUGH */
	case TFOR:
		if (t->type == TFOR)
			fptreef(shf, indent, "for %s ", t->str);
		if (t->vars != NULL) {
			fptreef(shf, indent, "in ");
			for (w = t->vars; *w; )
				fptreef(shf, indent, "%S ", *w++);
			fptreef(shf, indent, "%;");
		}
		fptreef(shf, indent + INDENT, "do%N%T", t->left);
		fptreef(shf, indent, "%;done ");
		break;
	case TCASE:
		fptreef(shf, indent, "case %S in", t->str);
		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
			fptreef(shf, indent, "%N(");
			for (w = t1->vars; *w != NULL; w++)
				fptreef(shf, indent, "%S%c", *w,
				    (w[1] != NULL) ? '|' : ')');
			fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left);
		}
		fptreef(shf, indent, "%Nesac ");
		break;
	case TIF:
	case TELIF:
		/* 3 == strlen("if ") */
		fptreef(shf, indent + 3, "if %T", t->left);
		for (;;) {
			t = t->right;
			if (t->left != NULL) {
				fptreef(shf, indent, "%;");
				fptreef(shf, indent + INDENT, "then%N%T",
				    t->left);
			}
			if (t->right == NULL || t->right->type != TELIF)
				break;
			t = t->right;
			fptreef(shf, indent, "%;");
			/* 5 == strlen("elif ") */
			fptreef(shf, indent + 5, "elif %T", t->left);
		}
		if (t->right != NULL) {
			fptreef(shf, indent, "%;");
			fptreef(shf, indent + INDENT, "else%;%T", t->right);
		}
		fptreef(shf, indent, "%;fi ");
		break;
	case TWHILE:
	case TUNTIL:
		/* 6 == strlen("while"/"until") */
		fptreef(shf, indent + 6, "%s %T",
		    (t->type==TWHILE) ? "while" : "until",
		    t->left);
		fptreef(shf, indent, "%;do");
		fptreef(shf, indent + INDENT, "%;%T", t->right);
		fptreef(shf, indent, "%;done ");
		break;
	case TBRACE:
		fptreef(shf, indent + INDENT, "{%;%T", t->left);
		fptreef(shf, indent, "%;} ");
		break;
	case TCOPROC:
		fptreef(shf, indent, "%T|& ", t->left);
		break;
	case TASYNC:
		fptreef(shf, indent, "%T& ", t->left);
		break;
	case TFUNCT:
		fptreef(shf, indent,
		    t->u.ksh_func ? "function %s %T" : "%s() %T",
		    t->str, t->left);
		break;
	case TTIME:
		fptreef(shf, indent, "time %T", t->left);
		break;
	default:
		fptreef(shf, indent, "<botch>");
		break;
	}
	if ((ioact = t->ioact) != NULL) {
		int	need_nl = 0;

		while (*ioact != NULL)
			pioact(shf, indent, *ioact++);
		/* Print here documents after everything else... */
		for (ioact = t->ioact; *ioact != NULL; ) {
			struct ioword *iop = *ioact++;

			/* heredoc is 0 when tracing (set -x) */
			if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) {
				tputc('\n', shf);
				shf_puts(iop->heredoc, shf);
				fptreef(shf, indent, "%s",
				    evalstr(iop->delim, 0));
				need_nl = 1;
			}
		}
		/* Last delimiter must be followed by a newline (this often
		 * leads to an extra blank line, but its not worth worrying
		 * about)
		 */
		if (need_nl)
			tputc('\n', shf);
	}
}
예제 #4
0
파일: tree.c 프로젝트: aalm/obsd-src
static void
pioact(struct shf *shf, int indent, struct ioword *iop)
{
	int flag = iop->flag;
	int type = flag & IOTYPE;
	int expected;

	expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
	    (type == IOCAT || type == IOWRITE) ? 1 :
	    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
	    iop->unit + 1;
	if (iop->unit != expected)
		tputc('0' + iop->unit, shf);

	switch (type) {
	case IOREAD:
		fptreef(shf, indent, "< ");
		break;
	case IOHERE:
		if (flag&IOSKIP)
			fptreef(shf, indent, "<<- ");
		else
			fptreef(shf, indent, "<< ");
		break;
	case IOCAT:
		fptreef(shf, indent, ">> ");
		break;
	case IOWRITE:
		if (flag&IOCLOB)
			fptreef(shf, indent, ">| ");
		else
			fptreef(shf, indent, "> ");
		break;
	case IORDWR:
		fptreef(shf, indent, "<> ");
		break;
	case IODUP:
		if (flag & IORDUP)
			fptreef(shf, indent, "<&");
		else
			fptreef(shf, indent, ">&");
		break;
	}
	/* name/delim are 0 when printing syntax errors */
	if (type == IOHERE) {
		if (iop->delim)
			fptreef(shf, indent, "%S ", iop->delim);
	} else if (iop->name)
		fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
		    iop->name);
}
예제 #5
0
파일: tree.c 프로젝트: MIPS/external-mksh
/*
 * print a command tree
 */
static void
ptree(struct op *t, int indent, struct shf *shf)
{
	const char **w;
	struct ioword **ioact;
	struct op *t1;
	int i;
	const char *ccp;

 Chain:
	if (t == NULL)
		return;
	switch (t->type) {
	case TCOM:
		prevent_semicolon = false;
		/* special-case 'var=<<EOF' (cf. exec.c:execute) */
		if (t->args &&
		    /* we have zero arguments, i.e. no program 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]->ioflag & 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) ||
		    /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
		    ccp[3] == '=' && ccp[4] == EOS))) {
			fptreef(shf, indent, Tf_S, t->vars[0]);
			break;
		}

		if (t->vars) {
			w = (const char **)t->vars;
			while (*w)
				fptreef(shf, indent, Tf_S_, *w++);
		} else
			shf_puts("#no-vars# ", shf);
		if (t->args) {
			w = t->args;
			if (*w && **w == CHAR) {
				char *cp = wdstrip(*w++, WDS_TPUTS);

				if (valid_alias_name(cp))
					shf_putc('\\', shf);
				shf_puts(cp, shf);
				shf_putc(' ', shf);
				afree(cp, ATEMP);
			}
			while (*w)
				fptreef(shf, indent, Tf_S_, *w++);
		} else
			shf_puts("#no-args# ", shf);
		break;
	case TEXEC:
		t = t->left;
		goto Chain;
	case TPAREN:
		fptreef(shf, indent + 2, "( %T) ", t->left);
		break;
	case TPIPE:
		fptreef(shf, indent, "%T| ", t->left);
		t = t->right;
		goto Chain;
	case TLIST:
		fptreef(shf, indent, "%T%;", t->left);
		t = t->right;
		goto Chain;
	case TOR:
	case TAND:
		fptreef(shf, indent, "%T%s %T",
		    t->left, (t->type == TOR) ? "||" : "&&", t->right);
		break;
	case TBANG:
		shf_puts("! ", shf);
		prevent_semicolon = false;
		t = t->right;
		goto Chain;
	case TDBRACKET:
		w = t->args;
		shf_puts("[[", shf);
		while (*w)
			fptreef(shf, indent, Tf__S, *w++);
		shf_puts(" ]] ", shf);
		break;
	case TSELECT:
	case TFOR:
		fptreef(shf, indent, "%s %s ",
		    (t->type == TFOR) ? "for" : Tselect, t->str);
		if (t->vars != NULL) {
			shf_puts("in ", shf);
			w = (const char **)t->vars;
			while (*w)
				fptreef(shf, indent, Tf_S_, *w++);
			fptreef(shf, indent, Tft_end);
		}
		fptreef(shf, indent + INDENT, "do%N%T", t->left);
		fptreef(shf, indent, "%;done ");
		break;
	case TCASE:
		fptreef(shf, indent, "case %S in", t->str);
		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
			fptreef(shf, indent, "%N(");
			w = (const char **)t1->vars;
			while (*w) {
				fptreef(shf, indent, "%S%c", *w,
				    (w[1] != NULL) ? '|' : ')');
				++w;
			}
			fptreef(shf, indent + INDENT, "%N%T%N;%c", t1->left,
			    t1->u.charflag);
		}
		fptreef(shf, indent, "%Nesac ");
		break;
	case TELIF:
		internal_errorf(TELIF_unexpected);
		/* FALLTHROUGH */
	case TIF:
		i = 2;
		t1 = t;
		goto process_TIF;
		do {
			t1 = t1->right;
			i = 0;
			fptreef(shf, indent, Tft_end);
 process_TIF:
			/* 5 == strlen("elif ") */
			fptreef(shf, indent + 5 - i, Telif_pT + i, t1->left);
			t1 = t1->right;
			if (t1->left != NULL) {
				fptreef(shf, indent, Tft_end);
				fptreef(shf, indent + INDENT, "%s%N%T",
				    "then", t1->left);
			}
		} while (t1->right && t1->right->type == TELIF);
		if (t1->right != NULL) {
			fptreef(shf, indent, Tft_end);
			fptreef(shf, indent + INDENT, "%s%N%T",
			    "else", t1->right);
		}
		fptreef(shf, indent, "%;fi ");
		break;
	case TWHILE:
	case TUNTIL:
		/* 6 == strlen("while "/"until ") */
		fptreef(shf, indent + 6, Tf_s_T,
		    (t->type == TWHILE) ? "while" : "until",
		    t->left);
		fptreef(shf, indent, Tft_end);
		fptreef(shf, indent + INDENT, "do%N%T", t->right);
		fptreef(shf, indent, "%;done ");
		break;
	case TBRACE:
		fptreef(shf, indent + INDENT, "{%N%T", t->left);
		fptreef(shf, indent, "%;} ");
		break;
	case TCOPROC:
		fptreef(shf, indent, "%T|& ", t->left);
		prevent_semicolon = true;
		break;
	case TASYNC:
		fptreef(shf, indent, "%T& ", t->left);
		prevent_semicolon = true;
		break;
	case TFUNCT:
		fpFUNCTf(shf, indent, tobool(t->u.ksh_func), t->str, t->left);
		break;
	case TTIME:
		fptreef(shf, indent, Tf_s_T, Ttime, t->left);
		break;
	default:
		shf_puts("<botch>", shf);
		prevent_semicolon = false;
		break;
	}
	if ((ioact = t->ioact) != NULL) {
		bool need_nl = false;

		while (*ioact != NULL)
			pioact(shf, *ioact++);
		/* Print here documents after everything else... */
		ioact = t->ioact;
		while (*ioact != NULL) {
			struct ioword *iop = *ioact++;

			/* heredoc is NULL when tracing (set -x) */
			if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
			    iop->heredoc) {
				shf_putc('\n', shf);
				shf_puts(iop->heredoc, shf);
				fptreef(shf, indent, Tf_s,
				    evalstr(iop->delim, 0));
				need_nl = true;
			}
		}
		/*
		 * Last delimiter must be followed by a newline (this
		 * often leads to an extra blank line, but it's not
		 * worth worrying about)
		 */
		if (need_nl) {
			shf_putc('\n', shf);
			prevent_semicolon = true;
		}
	}
}
예제 #6
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)) {
		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->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) {
			char *sp;

			warningf(true, "%s: %s",
			    (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg);
			afree(sp, ATEMP);
			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 | O_BINARY, 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;
			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->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);
}