static char* temp(char* buf, int* fdp) { char* s; char* d; int n; size_t len; len = strlen(buf); if (s = strrchr(buf, '/')) { *s++ = 0; d = buf; } else { s = buf; d = ""; } if ((n = strlen(s)) < 6 || strcmp(s + n - 6, "XXXXXX")) *buf = 0; else { *(s + n - 6) = 0; if (!pathtemp(buf, len, d, s, fdp)) *buf = 0; } return buf; }
extern char* tmpnam(char* s) { static char buf[L_tmpnam]; return pathtemp(s ? s : buf, L_tmpnam, NiL, "tn", NiL); }
int b_mktemp(int argc, char** argv, Shbltin_t* context) { mode_t mode = 0; mode_t mask; int fd; int i; int quiet = 0; int unsafe = 0; int* fdp = &fd; char* dir = ""; char* pfx; char* t; char path[PATH_MAX]; cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY); for (;;) { switch (optget(argv, usage)) { case 'd': fdp = 0; continue; case 'm': mode = strperm(pfx = opt_info.arg, &opt_info.arg, S_IRWXU); if (*opt_info.arg) error(ERROR_exit(0), "%s: invalid mode", pfx); continue; case 'p': if ((t = getenv("TMPDIR")) && *t) dir = 0; else dir = opt_info.arg; continue; case 'q': quiet = 1; continue; case 't': dir = 0; continue; case 'u': unsafe = 1; fdp = 0; continue; case 'R': if (!pathtemp(NiL, 0, opt_info.arg, "/seed", NiL)) error(2, "%s: regression test initializtion failed", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } argv += opt_info.index; if (error_info.errors || (pfx = *argv++) && *argv) error(ERROR_usage(2), "%s", optusage(NiL)); mask = umask(0); if (!mode) mode = (fdp ? (S_IRUSR|S_IWUSR) : S_IRWXU) & ~mask; umask(~mode & (S_IRWXU|S_IRWXG|S_IRWXO)); if (!pfx) { pfx = "tmp_"; if (dir && !*dir) dir = 0; } if (t = strrchr(pfx, '/')) { i = ++t - pfx; dir = fmtbuf(i); memcpy(dir, pfx, i); dir[i] = 0; pfx = t; } for (;;) { if (!pathtemp(path, sizeof(path), dir, pfx, fdp)) { if (quiet) error_info.errors++; else error(ERROR_SYSTEM|2, "cannot create temporary path"); break; } if (fdp || unsafe || !mkdir(path, mode)) { if (fdp) close(*fdp); sfputr(sfstdout, path, '\n'); break; } if (sh_checksig(context)) { error_info.errors++; break; } } umask(mask); return error_info.errors != 0; }
static void shell(void) { register char* s; register char* f = 0; register int c; if (ed.given) squeeze(ed.dol > ed.zero); s = getrec(ed.buffer.line, '\n', 0); if (s[0] == '!' && !s[1]) { if (!*sfstrbase(ed.buffer.shell)) error(2, "no saved shell command"); f = sfstrbase(ed.buffer.file); } else if (!s[0]) error(2, "empty shell command"); else SWP(ed.buffer.shell, ed.buffer.line); s = sfstrbase(ed.buffer.shell); sfstrseek(ed.buffer.line, 0, SEEK_SET); sfputc(ed.buffer.line, '!'); while (c = *s++) { if (c == '\\') { if (*s != '%') sfputc(ed.buffer.line, c); sfputc(ed.buffer.line, *s++); } else if (c == '%') sfputr(ed.buffer.line, f = sfstrbase(ed.buffer.file), -1); else sfputc(ed.buffer.line, c); } if (ed.given) { if (!ed.tmpfile && !(ed.tmpfile = pathtemp(NiL, 0, NiL, error_info.id, NiL))) error(ERROR_SYSTEM|2, "cannot generate temp file name"); if (!(ed.iop = sfopen(NiL, ed.tmpfile, "w"))) error(ERROR_SYSTEM|2, "%s: cannot create temp file", ed.tmpfile); error_info.file = ed.tmpfile; if (ed.dol > ed.zero) putfile(); exfile(); ed.bytes = 0; ed.lines = 0; sfprintf(ed.buffer.line, " < %s", ed.tmpfile); if (!(s = sfstruse(ed.buffer.line))) error(ERROR_SYSTEM|3, "out of space"); if (!(ed.iop = sfpopen(NiL, s + 1, "r"))) error(ERROR_SYSTEM|2, "%s: cannot execute shell command", s); error_info.file = s; rdelete(ed.addr1, ed.addr2); append(getfile, ed.dot, NiL); exfile(); remove(ed.tmpfile); } else { if (!(s = sfstruse(ed.buffer.line))) error(ERROR_SYSTEM|3, "out of space"); s++; if (f) putrec(s); if (!(ed.iop = sfpopen(NiL, s, ""))) error(ERROR_SYSTEM|2, "%s: cannot execute shell command", s); if (sfclose(ed.iop)) { ed.iop = 0; error(ERROR_SYSTEM|2, "%s: shell command exit error", s); } if (ed.verbose) putrec("!"); } }
int main(int argc, char** argv) { register Mc_t* mc; register char* s; register char* t; register int c; register int q; register int i; int num; char* b; char* e; char* catfile; char* msgfile; Sfio_t* sp; Sfio_t* mp; Sfio_t* tp; Xl_t* px; Xl_t* bp; Xl_t* xp = 0; int format = 0; int list = 0; int set = 0; NoP(argc); error_info.id = "msggen"; for (;;) { switch (optget(argv, usage)) { case 'f': format = list = 1; continue; case 'l': list = 1; continue; case 's': set = 1; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; if (error_info.errors || !(catfile = *argv++)) error(ERROR_USAGE|4, "%s", optusage(NiL)); /* * set and list only need catfile */ if (set) { sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL)); return error_info.errors != 0; } else if (list) { if (!(sp = sfopen(NiL, catfile, "r"))) error(ERROR_SYSTEM|3, "%s: cannot read catalog", catfile); if (!(mc = mcopen(sp))) error(ERROR_SYSTEM|3, "%s: catalog content error", catfile); sfclose(sp); if (format) { for (set = 1; set <= mc->num; set++) if (mc->set[set].num) { sfprintf(sfstdout, "$set %d\n", set); for (num = 1; num <= mc->set[set].num; num++) if (s = mc->set[set].msg[num]) sfprintf(sfstdout, "%d \"%s\"\n", num, fmtfmt(s)); } } else { if (*mc->translation) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$translation "); sfprintf(sfstdout, "%s", mc->translation); ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n"); } ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote \"\n"); for (set = 1; set <= mc->num; set++) if (mc->set[set].num) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$set %d\n", set); for (num = 1; num <= mc->set[set].num; num++) if (s = mc->set[set].msg[num]) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "%d \"", num); while (c = *s++) { /*INDENT...*/ switch (c) { case 0x22: /* " */ case 0x5C: /* \ */ sfputc(sfstdout, 0x5C); break; case 0x07: /* \a */ c = 0x61; sfputc(sfstdout, 0x5C); break; case 0x08: /* \b */ c = 0x62; sfputc(sfstdout, 0x5C); break; case 0x0A: /* \n */ c = 0x6E; sfputc(sfstdout, 0x5C); break; case 0x0B: /* \v */ c = 0x76; sfputc(sfstdout, 0x5C); break; case 0x0C: /* \f */ c = 0x66; sfputc(sfstdout, 0x5C); break; case 0x0D: /* \r */ c = 0x72; sfputc(sfstdout, 0x5C); break; } /*...UNDENT*/ sfputc(sfstdout, c); } ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\"\n"); } } } mcclose(mc); return error_info.errors != 0; } else if (!(msgfile = *argv++) || *argv) error(3, "exactly one message file must be specified"); /* * open the files and handles */ if (!(tp = sfstropen())) error(ERROR_SYSTEM|3, "out of space [string stream]"); if (!(mp = sfopen(NiL, msgfile, "r"))) error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile); sp = sfopen(NiL, catfile, "r"); if (!(mc = mcopen(sp))) error(ERROR_SYSTEM|3, "%s: catalog content error", catfile); if (sp) sfclose(sp); xp = translation(xp, mc->translation); /* * read the message file */ q = 0; set = 1; error_info.file = msgfile; while (s = sfgetr(mp, '\n', 1)) { error_info.line++; if (!*s) continue; if (*s == '$') { if (!*++s || isspace(*s)) continue; for (t = s; *s && !isspace(*s); s++); if (*s) *s++ = 0; if (streq(t, "delset")) { while (isspace(*s)) s++; num = (int)strtol(s, NiL, 0); if (num < mc->num && mc->set[num].num) for (i = 1; i <= mc->set[num].num; i++) mcput(mc, num, i, NiL); } else if (streq(t, "quote")) q = *s ? *s : 0; else if (streq(t, "set")) { while (isspace(*s)) s++; num = (int)strtol(s, &e, 0); if (e != s) set = num; else error(2, "set number expected"); } else if (streq(t, "translation")) xp = translation(xp, s); } else { t = s + sfvalue(mp); num = (int)strtol(s, &e, 0); if (e != s) { s = e; if (!*s) { if (mcput(mc, set, num, NiL)) error(2, "(%d,%d): cannot delete message", set, num); } else if (isspace(*s++)) { if (t > (s + 1) && *(t -= 2) == '\\') { sfwrite(tp, s, t - s); while (s = sfgetr(mp, '\n', 0)) { error_info.line++; t = s + sfvalue(mp); if (t <= (s + 1) || *(t -= 2) != '\\') break; sfwrite(tp, s, t - s); } if (!(s = sfstruse(tp))) error(ERROR_SYSTEM|3, "out of space"); } if (q) { if (*s++ != q) { error(2, "(%d,%d): %c quote expected", set, num, q); continue; } b = t = s; while (c = *s++) { if (c == '\\') { c = chresc(s - 1, &e); s = e; if (c) *t++ = c; else error(1, "nul character ignored"); } else if (c == q) break; else *t++ = c; } if (*s) { error(2, "(%d,%d): characters after quote not expected", set, num); continue; } *t = 0; s = b; } if (mcput(mc, set, num, s)) error(2, "(%d,%d): cannot add message", set, num); } else error(2, "message text expected"); } else error(2, "message number expected"); } } error_info.file = 0; error_info.line = 0; /* * fix up the translation record */ if (xp) { t = ""; for (;;) { for (bp = 0, px = xp; px; px = px->next) if (px->date && (!bp || strcoll(bp->date, px->date) < 0)) bp = px; if (!bp) break; sfprintf(tp, "%s%s %s", t, bp->name, bp->date); t = ", "; bp->date = 0; } if (!(mc->translation = sfstruse(tp))) error(ERROR_SYSTEM|3, "out of space"); } /* * dump the catalog to a local temporary * rename if no errors */ if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = sfopen(NiL, s, "w"))) error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile); if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp)) { remove(s); error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", s); } remove(catfile); if (rename(s, catfile)) error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog file %s", catfile, s); return error_info.errors != 0; }
static void execute(register Joblist_t* job) { register List_t* p; char* s; char* t; int flags; Rule_t* r; Var_t* v; Sfio_t* tmp; Sfio_t* att; Sfio_t* sp; att = sfstropen(); tmp = sfstropen(); restore(job, tmp, att); job->status = RUNNING; job->target->mark &= ~M_waiting; if (state.targetcontext || state.maxview && !state.fsview && *job->target->name != '/' && (!(job->target->dynamic & D_regular) || job->target->view)) commit(job, job->target->name); if ((state.mam.dynamic || state.mam.regress) && state.user && !(job->target->property & (P_after|P_before|P_dontcare|P_make|P_state|P_virtual))) sfprintf(state.mam.out, "%sinit %s %s\n", state.mam.label, mamname(job->target), timefmt(NiL, CURTIME)); t = sfstruse(tmp); if (!(job->flags & CO_ALWAYS)) { if (state.touch) { if (state.virtualdot) { state.virtualdot = 0; lockstate(1); } if (!(job->target->property & (P_attribute|P_virtual))) { acceptrule(job->target); if ((job->target->property & (P_joint|P_target)) == (P_joint|P_target)) for (p = job->target->prereqs->rule->prereqs; p; p = p->next) if (p->rule != job->target) acceptrule(p->rule); } } else if (*t && (!state.silent || state.mam.regress)) dumpaction(state.mam.out ? state.mam.out : sfstdout, NiL, t, NiL); done(job, 0, NiL); } else { if (state.virtualdot && !notfile(job->target)) { state.virtualdot = 0; lockstate(1); } if (!state.coshell) { sp = sfstropen(); sfprintf(sp, "label=%s", idname); expand(sp, " $(" CO_ENV_OPTIONS ")"); flags = CO_ANY; if (state.cross) flags |= CO_CROSS; if (state.serialize && state.jobs > 1) flags |= CO_SERIALIZE; if (!(state.coshell = coopen(getval(CO_ENV_SHELL, VAL_PRIMARY), flags, sfstruse(sp)))) error(ERROR_SYSTEM|3, "coshell open error"); sfstrclose(sp); } if (p = internal.exports->prereqs) { Sfio_t* exp; exp = sfstropen(); do { if (v = getvar(p->rule->name)) { expand(exp, v->value); coexport(state.coshell, p->rule->name, sfstruse(exp)); } else if (s = strchr(p->rule->name, '=')) { *s = 0; expand(exp, s + 1); coexport(state.coshell, p->rule->name, sfstruse(exp)); *s = '='; } } while (p = p->next); sfstrclose(exp); #if 0 freelist(internal.exports->prereqs); #endif internal.exports->prereqs = 0; } if (job->flags & CO_DATAFILE) { static char* dot; static char* tmp; if (job->target->property & P_read) { if (!dot) dot = pathtemp(NiL, 0, null, idname, NiL); state.tmpfile = dot; } else { if (!tmp) tmp = pathtemp(NiL, 0, NiL, idname, NiL); state.tmpfile = tmp; } } #if !_HUH_1992_02_29 /* i386 and ftx m68k dump without this statement -- help */ message((-99, "execute: %s: t=0x%08x &t=0x%08x", job->target->name, t, &t)); #endif if (state.mam.out) dumpaction(state.mam.out, MAMNAME(job->target), t, NiL); if (r = getrule(external.makerun)) maketop(r, P_dontcare|P_foreground, NiL); if (!(job->cojob = coexec(state.coshell, t, job->flags, state.tmpfile, NiL, sfstruse(att)))) error(3, "%s: cannot send action to coshell", job->target->name); job->cojob->local = (void*)job; /* * grab semaphores */ if (job->target->dynamic & D_hassemaphore) { job->flags |= CO_SEMAPHORES; for (p = job->prereqs; p; p = p->next) if (p->rule->semaphore && --p->rule->semaphore == 1) p->rule->status = MAKING; } /* * check status and sync */ if (job->target->dynamic & D_hasafter) save(job); if (job->flags & (CO_DATAFILE|CO_FOREGROUND)) { complete(job->target, NiL, NiL, 0); if (job->target->property & (P_functional|P_read)) { if (sp = sfopen(NiL, state.tmpfile, "r")) { remove(state.tmpfile); if (job->target->property & P_read) parse(sp, NiL, job->target->name, NiL); else { char* e; sfmove(sp, tmp, SF_UNBOUND, -1); t = sfstrbase(tmp); e = sfstrseek(tmp, 0, SEEK_CUR); while (e > t && *(e - 1) == '\n') e--; sfstrseek(tmp, e - t, SEEK_SET); setvar(job->target->name, sfstruse(tmp), 0); } sfclose(sp); } else error(2, "%s: cannot read temporary data output file %s", job->target->name, state.tmpfile); state.tmpfile = 0; } } } sfstrclose(att); sfstrclose(tmp); }
static void* aso_init_fcntl(void* data, const char* details) { APL_t* apl = (APL_t*)data; char* path; char* opt; size_t size; size_t references; int n; int fd; int drop; int perm; struct flock lock; char buf[PATH_MAX]; char tmp[64]; if (apl) { lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = apl->size; lock.l_len = sizeof(references); if (fcntl(apl->fd, F_SETLKW, &lock) >= 0) { if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size) references = 0; else if (read(apl->fd, &references, sizeof(references)) != sizeof(references)) references = 0; else if (references > 0) { references--; if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size) references = 0; else if (write(apl->fd, &references, sizeof(references)) != sizeof(references)) references = 0; } lock.l_type = F_UNLCK; fcntl(apl->fd, F_SETLK, &lock); if (!references) remove(apl->path); } close(apl->fd); free(apl); return 0; } fd = -1; perm = S_IRUSR|S_IWUSR; drop = 0; size = 32 * 1024 - sizeof(references); if (path = (char*)details) while (opt = strchr(path, ',')) { if (strneq(path, "perm=", 5)) { if ((n = opt - (path + 5)) >= sizeof(tmp)) n = sizeof(tmp) - 1; memcpy(tmp, path + 5, n); tmp[n] = 0; perm = strperm(tmp, NiL, perm); } else if (strneq(path, "size=", 5)) { size = strtoul(path + 5, NiL, 0); if (size <= sizeof(references)) goto bad; size -= sizeof(references); } path = opt + 1; } if (!path || !*path) { if (!(path = pathtemp(buf, sizeof(buf), NiL, "aso", &fd))) return 0; drop = 1; } if (!(apl = newof(0, APL_t, 1, strlen(path)))) goto bad; if (fd >= 0 || (fd = open(path, O_RDWR)) < 0 && (fd = open(path, O_CREAT|O_RDWR, perm)) >= 0) { if (lseek(fd, size, SEEK_SET) != size) goto bad; references = 1; if (write(fd, &references, sizeof(references)) != sizeof(references)) goto bad; } else { if ((size = lseek(fd, 0, SEEK_END)) <= sizeof(references)) goto bad; size -= sizeof(references); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = sizeof(references); if (fcntl(fd, F_SETLKW, &lock) < 0) goto bad; if (lseek(fd, size, SEEK_SET) != size) goto bad; if (read(fd, &references, sizeof(references)) != sizeof(references)) goto bad; references++; if (lseek(fd, size, SEEK_SET) != size) goto bad; if (write(fd, &references, sizeof(references)) != sizeof(references)) goto bad; lock.l_type = F_UNLCK; fcntl(fd, F_SETLK, &lock); } apl->fd = fd; apl->size = size; strcpy(apl->path, path); return apl; bad: if (apl) free(apl); if (fd >= 0) close(fd); if (drop) remove(path); return 0; }