Print this page
9899 cw(1onbld) should shadow more compilation

*** 260,269 **** --- 260,270 ---- #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> + #include <dirent.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/utsname.h>
*** 309,319 **** struct aelist *i_ae; uint32_t i_flags; int i_oldargc; char **i_oldargv; pid_t i_pid; ! char i_discard[MAXPATHLEN]; char *i_stderr; } cw_ictx_t; /* * Status values to indicate which Studio compiler and associated --- 310,320 ---- struct aelist *i_ae; uint32_t i_flags; int i_oldargc; char **i_oldargv; pid_t i_pid; ! char *i_tmpdir; char *i_stderr; } cw_ictx_t; /* * Status values to indicate which Studio compiler and associated
*** 554,563 **** --- 555,601 ---- newae(h, *table); table++; } } + /* + * The compiler wants the output file to end in appropriate extension. If + * we're generating a name from whole cloth (path == NULL), we assume that + * extension to be .o, otherwise we match the extension of the caller. + */ + static char * + discard_file_name(cw_ictx_t *ctx, const char *path) + { + char *ret, *ext; + char tmpl[] = "cwXXXXXX"; + + if (path == NULL) { + ext = ".o"; + } else { + ext = strrchr(path, '.'); + } + + /* + * We need absolute control over where the temporary file goes, since + * we rely on it for cleanup so tempnam(3C) and tmpnam(3C) are + * inappropriate (they use TMPDIR, preferentially). + * + * mkstemp(3C) doesn't actually help us, since the temporary file + * isn't used by us, only its name. + */ + if (mktemp(tmpl) == NULL) + nomem(); + + (void) asprintf(&ret, "%s/%s%s", ctx->i_tmpdir, tmpl, + (ext != NULL) ? ext : ""); + + if (ret == NULL) + nomem(); + + return (ret); + } + static void do_gcc(cw_ictx_t *ctx) { int c; int nolibc = 0;
*** 631,644 **** * Otherwise, filenames and partial arguments * are passed through for gcc to chew on. However, * output is always discarded for the secondary * compiler. */ ! if ((ctx->i_flags & CW_F_SHADOW) && in_output) ! newae(ctx->i_ae, ctx->i_discard); ! else newae(ctx->i_ae, arg); in_output = 0; continue; } if (ctx->i_flags & CW_F_CXX) { --- 669,683 ---- * Otherwise, filenames and partial arguments * are passed through for gcc to chew on. However, * output is always discarded for the secondary * compiler. */ ! if ((ctx->i_flags & CW_F_SHADOW) && in_output) { ! newae(ctx->i_ae, discard_file_name(ctx, arg)); ! } else { newae(ctx->i_ae, arg); + } in_output = 0; continue; } if (ctx->i_flags & CW_F_CXX) {
*** 750,760 **** if (arglen == 1) { in_output = 1; newae(ctx->i_ae, arg); } else if (ctx->i_flags & CW_F_SHADOW) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, ctx->i_discard); } else { newae(ctx->i_ae, arg); } break; case 'D': --- 789,799 ---- if (arglen == 1) { in_output = 1; newae(ctx->i_ae, arg); } else if (ctx->i_flags & CW_F_SHADOW) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, discard_file_name(ctx, arg)); } else { newae(ctx->i_ae, arg); } break; case 'D':
*** 1188,1199 **** } } free(nameflag); ! if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) && ! op != CW_O_PREPROCESS) { errx(2, "multiple source files are " "allowed only with -E or -P"); } /* --- 1227,1246 ---- } } free(nameflag); ! /* ! * When compiling multiple source files in a single invocation some ! * compilers output objects into the current directory with ! * predictable and conventional names. ! * ! * We prevent any attempt to compile multiple files at once so that ! * any such objects created by a shadow can't escape into a later ! * link-edit. ! */ ! if (c_files > 1 && op != CW_O_PREPROCESS) { errx(2, "multiple source files are " "allowed only with -E or -P"); } /*
*** 1257,1277 **** (void) fprintf(stderr, "Incompatible -xarch= and/or -m32/-m64 options used.\n"); exit(2); } ! if ((op == CW_O_LINK || op == CW_O_PREPROCESS) && ! (ctx->i_flags & CW_F_SHADOW)) exit(0); if (model != NULL) newae(ctx->i_ae, model); if (!nolibc) newae(ctx->i_ae, "-lc"); if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, ctx->i_discard); } } static void do_smatch(cw_ictx_t *ctx) --- 1304,1327 ---- (void) fprintf(stderr, "Incompatible -xarch= and/or -m32/-m64 options used.\n"); exit(2); } ! if (ctx->i_flags & CW_F_SHADOW) { ! if (op == CW_O_PREPROCESS) ! exit(0); ! else if (op == CW_O_LINK && c_files == 0) exit(0); + } if (model != NULL) newae(ctx->i_ae, model); if (!nolibc) newae(ctx->i_ae, "-lc"); if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, discard_file_name(ctx, NULL)); } } static void do_smatch(cw_ictx_t *ctx)
*** 1300,1310 **** } static void do_cc(cw_ictx_t *ctx) { ! int in_output = 0, seen_o = 0; cw_op_t op = CW_O_LINK; char *nameflag; if (ctx->i_flags & CW_F_PROG) { newae(ctx->i_ae, "-V"); --- 1350,1360 ---- } static void do_cc(cw_ictx_t *ctx) { ! int in_output = 0, seen_o = 0, c_files = 0; cw_op_t op = CW_O_LINK; char *nameflag; if (ctx->i_flags & CW_F_PROG) { newae(ctx->i_ae, "-V");
*** 1314,1335 **** if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1) nomem(); while (--ctx->i_oldargc > 0) { char *arg = *++ctx->i_oldargv; if (strncmp(arg, "-_CC=", 5) == 0) { newae(ctx->i_ae, strchr(arg, '=') + 1); continue; } if (*arg != '-') { if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, arg); } else { in_output = 0; ! newae(ctx->i_ae, ctx->i_discard); } continue; } switch (*(arg + 1)) { case '_': --- 1364,1392 ---- if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1) nomem(); while (--ctx->i_oldargc > 0) { char *arg = *++ctx->i_oldargv; + size_t arglen = strlen(arg); if (strncmp(arg, "-_CC=", 5) == 0) { newae(ctx->i_ae, strchr(arg, '=') + 1); continue; } if (*arg != '-') { + if (!in_output && arglen > 2 && + arg[arglen - 2] == '.' && + (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' || + arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i')) + c_files++; + if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, arg); } else { in_output = 0; ! newae(ctx->i_ae, discard_file_name(ctx, arg)); } continue; } switch (*(arg + 1)) { case '_':
*** 1349,1359 **** if (strlen(arg) == 2) { in_output = 1; newae(ctx->i_ae, arg); } else if (ctx->i_flags & CW_F_SHADOW) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, ctx->i_discard); } else { newae(ctx->i_ae, arg); } break; case 'c': --- 1406,1416 ---- if (strlen(arg) == 2) { in_output = 1; newae(ctx->i_ae, arg); } else if (ctx->i_flags & CW_F_SHADOW) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, discard_file_name(ctx, arg)); } else { newae(ctx->i_ae, arg); } break; case 'c':
*** 1372,1388 **** } } free(nameflag); ! if ((op == CW_O_LINK || op == CW_O_PREPROCESS) && ! (ctx->i_flags & CW_F_SHADOW)) exit(0); if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, ctx->i_discard); } } static void prepctx(cw_ictx_t *ctx) --- 1429,1454 ---- } } free(nameflag); ! /* See the comment on this same code in do_gcc() */ ! if (c_files > 1 && op != CW_O_PREPROCESS) { ! errx(2, "multiple source files are " ! "allowed only with -E or -P"); ! } ! ! if (ctx->i_flags & CW_F_SHADOW) { ! if (op == CW_O_PREPROCESS) exit(0); + else if (op == CW_O_LINK && c_files == 0) + exit(0); + } if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) { newae(ctx->i_ae, "-o"); ! newae(ctx->i_ae, discard_file_name(ctx, NULL)); } } static void prepctx(cw_ictx_t *ctx)
*** 1489,1500 **** break; } } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); - (void) unlink(ctx->i_discard); - if (stat(ctx->i_stderr, &s) < 0) { warn("stat failed on child cleanup"); return (-1); } if (s.st_size != 0) { --- 1555,1564 ----
*** 1520,1544 **** } static int exec_ctx(cw_ictx_t *ctx, int block) { ! char *file; ! ! /* ! * To avoid offending cc's sensibilities, the name of its output ! * file must end in '.o'. ! */ ! if ((file = tempnam(NULL, ".cw")) == NULL) { ! nomem(); ! return (-1); ! } ! (void) strlcpy(ctx->i_discard, file, MAXPATHLEN); ! (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN); ! free(file); ! ! if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) { nomem(); return (-1); } if ((ctx->i_pid = fork()) == 0) { --- 1584,1594 ---- } static int exec_ctx(cw_ictx_t *ctx, int block) { ! if ((ctx->i_stderr = tempnam(ctx->i_tmpdir, "cw")) == NULL) { nomem(); return (-1); } if ((ctx->i_pid = fork()) == 0) {
*** 1605,1614 **** --- 1655,1706 ---- if (tspec != NULL) errx(1, "Excess tokens in compiler: %s", spec); } + static void + cleanup(cw_ictx_t *ctx) + { + DIR *dirp; + struct dirent *dp; + char buf[MAXPATHLEN]; + + if ((dirp = opendir(ctx->i_tmpdir)) == NULL) { + if (errno != ENOENT) { + err(1, "couldn't open temp directory: %s", + ctx->i_tmpdir); + } else { + return; + } + } + + errno = 0; + while ((dp = readdir(dirp)) != NULL) { + (void) snprintf(buf, MAXPATHLEN, "%s/%s", ctx->i_tmpdir, + dp->d_name); + + if (strncmp(dp->d_name, ".", strlen(dp->d_name)) == 0 || + strncmp(dp->d_name, "..", strlen(dp->d_name)) == 0) + continue; + + if (unlink(buf) == -1) + err(1, "failed to unlink temp file: %s", dp->d_name); + errno = 0; + } + + if (errno != 0) { + err(1, "failed to read temporary directory: %s", + ctx->i_tmpdir); + } + + (void) closedir(dirp); + if (rmdir(ctx->i_tmpdir) != 0) { + err(1, "failed to unlink temporary directory: %s", + ctx->i_tmpdir); + } + } + int main(int argc, char **argv) { int ch; cw_compiler_t primary = { NULL, NULL, 0 };
*** 1619,1628 **** --- 1711,1721 ---- boolean_t do_exec = B_FALSE; boolean_t vflg = B_FALSE; boolean_t Cflg = B_FALSE; boolean_t cflg = B_FALSE; boolean_t nflg = B_FALSE; + char *tmpdir; cw_ictx_t *main_ctx; static struct option longopts[] = { { "compiler", no_argument, NULL, 'c' },
*** 1706,1725 **** main_ctx->i_flags &= ~CW_F_ECHO; main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC; do_serial = 1; } ret |= exec_ctx(main_ctx, do_serial); for (int i = 0; i < nshadows; i++) { int r; cw_ictx_t *shadow_ctx; if ((shadow_ctx = newictx()) == NULL) nomem(); ! memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t)); shadow_ctx->i_flags |= CW_F_SHADOW; shadow_ctx->i_compiler = &shadows[i]; r = exec_ctx(shadow_ctx, do_serial); --- 1799,1828 ---- main_ctx->i_flags &= ~CW_F_ECHO; main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC; do_serial = 1; } + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + + if (asprintf(&main_ctx->i_tmpdir, "%s/cw.XXXXXX", tmpdir) == -1) + nomem(); + + if ((main_ctx->i_tmpdir = mkdtemp(main_ctx->i_tmpdir)) == NULL) + errx(1, "failed to create temporary directory"); + ret |= exec_ctx(main_ctx, do_serial); for (int i = 0; i < nshadows; i++) { int r; cw_ictx_t *shadow_ctx; if ((shadow_ctx = newictx()) == NULL) nomem(); ! (void) memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t)); shadow_ctx->i_flags |= CW_F_SHADOW; shadow_ctx->i_compiler = &shadows[i]; r = exec_ctx(shadow_ctx, do_serial);
*** 1737,1743 **** --- 1840,1847 ---- next = next->i_next; ret |= reap(toreap); } } + cleanup(main_ctx); return (ret); }