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); }
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); }
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; }