Ejemplo n.º 1
0
STATIC void
expbackq(shinstance *psh, union node *cmd, int quoted, int flag)
{
	struct backcmd in;
	int i;
	char buf[128];
	char *p;
	char *dest = psh->expdest;
	struct ifsregion saveifs, *savelastp;
	struct nodelist *saveargbackq;
	char lastc;
	int startloc = (int)(dest - stackblock(psh));
	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
	int saveherefd;
	int quotes = flag & (EXP_FULL | EXP_CASE);
#ifdef SH_DEAL_WITH_CRLF
	int pending_cr = 0;
#endif

	INTOFF;
	saveifs = psh->ifsfirst;
	savelastp = psh->ifslastp;
	saveargbackq = psh->argbackq;
	saveherefd = psh->herefd;
	psh->herefd = -1;
	p = grabstackstr(psh, dest);
	evalbackcmd(psh, cmd, &in);
	ungrabstackstr(psh, p, dest);
	psh->ifsfirst = saveifs;
	psh->ifslastp = savelastp;
	psh->argbackq = saveargbackq;
	psh->herefd = saveherefd;

	p = in.buf;
	lastc = '\0';
	for (;;) {
		if (--in.nleft < 0) {
			if (in.fd < 0)
				break;
			while ((i = shfile_read(&psh->fdtab, in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
			TRACE((psh, "expbackq: read returns %d\n", i));
			if (i <= 0)
				break;
			p = buf;
			in.nleft = i - 1;
		}
		lastc = *p++;
#ifdef SH_DEAL_WITH_CRLF
		if (pending_cr) {
			pending_cr = 0;
			if (lastc != '\n') {
				if (quotes && syntax[(int)'\r'] == CCTL)
					STPUTC(psh, CTLESC, dest);
				STPUTC(psh, '\r', dest);
			}
		}
		if (lastc == '\r')
			pending_cr = '\r';
		else
#endif
		if (lastc != '\0') {
			if (quotes && syntax[(int)lastc] == CCTL)
				STPUTC(psh, CTLESC, dest);
			STPUTC(psh, lastc, dest);
		}
	}
#ifdef SH_DEAL_WITH_CRLF
	if (pending_cr) {
		if (quotes && syntax[(int)'\r'] == CCTL)
			STPUTC(psh, CTLESC, dest);
		STPUTC(psh, '\r', dest);
	}
#endif

	/* Eat all trailing newlines */
	p = stackblock(psh) + startloc;
	while (dest > p && dest[-1] == '\n')
		STUNPUTC(psh, dest);

	if (in.fd >= 0)
		shfile_close(&psh->fdtab, in.fd);
	if (in.buf)
		ckfree(psh, in.buf);
	if (in.jp)
		psh->back_exitstatus = waitforjob(psh, in.jp);
	if (quoted == 0)
		recordregion(psh, startloc, (int)(dest - stackblock(psh)), 0);
	TRACE((psh, "evalbackq: size=%d: \"%.*s\"\n",
		(dest - stackblock(psh)) - startloc,
		(dest - stackblock(psh)) - startloc,
		stackblock(psh) + startloc));
	psh->expdest = dest;
	INTON;
}
Ejemplo n.º 2
0
int
readcmd(shinstance *psh, int argc, char **argv)
{
	char **ap;
	char c;
	int rflag;
	char *prompt;
	const char *ifs;
	char *p;
	int startword;
	int status;
	int i;
	int is_ifs;
	int saveall = 0;

	rflag = 0;
	prompt = NULL;
	while ((i = nextopt(psh, "p:r")) != '\0') {
		if (i == 'p')
			prompt = psh->optionarg;
		else
			rflag = 1;
	}

	if (prompt && shfile_isatty(&psh->fdtab, 0)) {
		out2str(psh, prompt);
		output_flushall(psh);
	}

	if (*(ap = psh->argptr) == NULL)
		error(psh, "arg count");

	if ((ifs = bltinlookup(psh, "IFS", 1)) == NULL)
		ifs = " \t\n";

	status = 0;
	startword = 2;
	STARTSTACKSTR(psh, p);
	for (;;) {
		if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) {
			status = 1;
			break;
		}
		if (c == '\0')
			continue;
		if (c == '\\' && !rflag) {
			if (shfile_read(&psh->fdtab, 0, &c, 1) != 1) {
				status = 1;
				break;
			}
			if (c != '\n')
				STPUTC(psh, c, p);
			continue;
		}
		if (c == '\n')
			break;
		if (strchr(ifs, c))
			is_ifs = strchr(" \t\n", c) ? 1 : 2;
		else
			is_ifs = 0;

		if (startword != 0) {
			if (is_ifs == 1) {
				/* Ignore leading IFS whitespace */
				if (saveall)
					STPUTC(psh, c, p);
				continue;
			}
			if (is_ifs == 2 && startword == 1) {
				/* Only one non-whitespace IFS per word */
				startword = 2;
				if (saveall)
					STPUTC(psh, c, p);
				continue;
			}
		}

		if (is_ifs == 0) {
			/* append this character to the current variable */
			startword = 0;
			if (saveall)
				/* Not just a spare terminator */
				saveall++;
			STPUTC(psh, c, p);
			continue;
		}

		/* end of variable... */
		startword = is_ifs;

		if (ap[1] == NULL) {
			/* Last variable needs all IFS chars */
			saveall++;
			STPUTC(psh, c, p);
			continue;
		}

		STACKSTRNUL(psh, p);
		setvar(psh, *ap, stackblock(psh), 0);
		ap++;
		STARTSTACKSTR(psh, p);
	}
	STACKSTRNUL(psh, p);

	/* Remove trailing IFS chars */
	for (; stackblock(psh) <= --p; *p = 0) {
		if (!strchr(ifs, *p))
			break;
		if (strchr(" \t\n", *p))
			/* Always remove whitespace */
			continue;
		if (saveall > 1)
			/* Don't remove non-whitespace unless it was naked */
			break;
	}
	setvar(psh, *ap, stackblock(psh), 0);

	/* Set any remaining args to "" */
	while (*++ap != NULL)
		setvar(psh, *ap, nullstr, 0);
	return status;
}