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);
}
Exemple #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);
}
Exemple #3
0
static void
getspec(struct tbl *vp)
{
	mksh_ari_u num;
	int st;
	struct timeval tv;

	switch ((st = special(vp->name))) {
	case V_COLUMNS:
	case V_LINES:
		/*
		 * Do NOT export COLUMNS/LINES. Many applications
		 * check COLUMNS/LINES before checking ws.ws_col/row,
		 * so if the app is started with C/L in the environ
		 * and the window is then resized, the app won't
		 * see the change cause the environ doesn't change.
		 */
		if (got_winch)
			change_winsz();
		break;
	}
	switch (st) {
	case V_BASHPID:
		num.u = (mksh_uari_t)procpid;
		break;
	case V_COLUMNS:
		num.i = x_cols;
		break;
	case V_HISTSIZE:
		num.i = histsize;
		break;
	case V_LINENO:
		num.u = (mksh_uari_t)current_lineno + user_lineno;
		break;
	case V_LINES:
		num.i = x_lins;
		break;
	case V_EPOCHREALTIME: {
		/* 10(%u) + 1(.) + 6 + NUL */
		char buf[18];

		vp->flag &= ~SPECIAL;
		mksh_TIME(tv);
		shf_snprintf(buf, sizeof(buf), "%u.%06u",
		    (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
		setstr(vp, buf, KSH_RETURN_ERROR | 0x4);
		vp->flag |= SPECIAL;
		return;
	}
	case V_OPTIND:
		num.i = user_opt.uoptind;
		break;
	case V_RANDOM:
		num.i = rndget();
		break;
	case V_SECONDS:
		/*
		 * On start up the value of SECONDS is used before
		 * it has been set - don't do anything in this case
		 * (see initcoms[] in main.c).
		 */
		if (vp->flag & ISSET) {
			mksh_TIME(tv);
			num.i = tv.tv_sec - seconds;
		} else
			return;
		break;
	default:
		/* do nothing, do not touch vp at all */
		return;
	}
	vp->flag &= ~SPECIAL;
	setint_n(vp, num.i, 0);
	vp->flag |= SPECIAL;
}