Print this page
But keep the Xamode() removal
Revert "9899 cw(1onbld) should shadow more compilation" (leaks object files)
This reverts commit d0843a33a8ba49c316537132aa23e7df6d6fc64b.


 291 
 292 typedef enum {
 293         GNU,
 294         SUN
 295 } compiler_style_t;
 296 
 297 typedef struct {
 298         char *c_name;
 299         char *c_path;
 300         compiler_style_t c_style;
 301 } cw_compiler_t;
 302 
 303 typedef struct cw_ictx {
 304         struct cw_ictx  *i_next;
 305         cw_compiler_t   *i_compiler;
 306         struct aelist   *i_ae;
 307         uint32_t        i_flags;
 308         int             i_oldargc;
 309         char            **i_oldargv;
 310         pid_t           i_pid;
 311         char            *i_discard;
 312         char            *i_stderr;
 313 } cw_ictx_t;
 314 
 315 /*
 316  * Status values to indicate which Studio compiler and associated
 317  * flags are being used.
 318  */
 319 #define M32             0x01    /* -m32 - only on Studio 12 */
 320 #define M64             0x02    /* -m64 - only on Studio 12 */
 321 #define SS11            0x100   /* Studio 11 */
 322 #define SS12            0x200   /* Studio 12 */
 323 
 324 #define TRANS_ENTRY     5
 325 /*
 326  * Translation table definition for the -xarch= flag. The "x_arg"
 327  * value is translated into the appropriate gcc flags according
 328  * to the values in x_trans[n]. The x_flags indicates what compiler
 329  * is being used and what flags have been set via the use of
 330  * "x_arg".
 331  */


 536 static void
 537 xlate(struct aelist *h, const char *xarg, const char **table)
 538 {
 539         while (*table != NULL && strcmp(xarg, *table) != 0) {
 540                 while (*table != NULL)
 541                         table++;
 542                 table++;
 543         }
 544 
 545         if (*table == NULL)
 546                 error(xarg);
 547 
 548         table++;
 549 
 550         while (*table != NULL) {
 551                 newae(h, *table);
 552                 table++;
 553         }
 554 }
 555 
 556 /*
 557  * The compiler wants the output file to end in appropriate extension.  If
 558  * we're generating a name from whole cloth (path == NULL), we assume that
 559  * extension to be .o, otherwise we match the extension of the caller.
 560  */
 561 static char *
 562 discard_file_name(const char *path)
 563 {
 564         char *ret, *ext, *file;
 565 
 566         if (path == NULL) {
 567                 ext = ".o";
 568         } else {
 569                 ext = strrchr(path, '.');
 570         }
 571 
 572         if ((ret = calloc(MAXPATHLEN, sizeof (char))) == NULL)
 573                 nomem();
 574 
 575         if ((file = tempnam(NULL, ".cw")) == NULL)
 576                 nomem();
 577 
 578         (void) strlcpy(ret, file, MAXPATHLEN);
 579         if (ext != NULL)
 580                 (void) strlcat(ret, ext, MAXPATHLEN);
 581         free(file);
 582         return (ret);
 583 }
 584 
 585 static void
 586 do_gcc(cw_ictx_t *ctx)
 587 {
 588         int c;
 589         int nolibc = 0;
 590         int in_output = 0, seen_o = 0, c_files = 0;
 591         cw_op_t op = CW_O_LINK;
 592         char *model = NULL;
 593         char *nameflag;
 594         int mflag = 0;
 595 
 596         if (ctx->i_flags & CW_F_PROG) {
 597                 newae(ctx->i_ae, "--version");
 598                 return;
 599         }
 600 
 601         newae(ctx->i_ae, "-fident");
 602         newae(ctx->i_ae, "-finline");
 603         newae(ctx->i_ae, "-fno-inline-functions");
 604         newae(ctx->i_ae, "-fno-builtin");


 642                 } else {
 643                         /*
 644                          * Discard inline files that gcc doesn't grok
 645                          */
 646                         if (!in_output && arglen > 3 &&
 647                             strcmp(arg + arglen - 3, ".il") == 0)
 648                                 continue;
 649 
 650                         if (!in_output && arglen > 2 &&
 651                             arg[arglen - 2] == '.' &&
 652                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 653                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 654                                 c_files++;
 655 
 656                         /*
 657                          * Otherwise, filenames and partial arguments
 658                          * are passed through for gcc to chew on.  However,
 659                          * output is always discarded for the secondary
 660                          * compiler.
 661                          */
 662                         if ((ctx->i_flags & CW_F_SHADOW) && in_output) {
 663                                 ctx->i_discard = discard_file_name(arg);
 664                                 newae(ctx->i_ae, ctx->i_discard);
 665                         } else {
 666                                 newae(ctx->i_ae, arg);
 667                         }
 668                         in_output = 0;
 669                         continue;
 670                 }
 671 
 672                 if (ctx->i_flags & CW_F_CXX) {
 673                         if (strncmp(arg, "-_g++=", 6) == 0) {
 674                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
 675                                 continue;
 676                         }
 677                         if (strncmp(arg, "-compat=", 8) == 0) {
 678                                 /* discard -compat=4 and -compat=5 */
 679                                 continue;
 680                         }
 681                         if (strcmp(arg, "-Qoption") == 0) {
 682                                 /* discard -Qoption and its two arguments */
 683                                 if (ctx->i_oldargc < 3)
 684                                         error(arg);
 685                                 ctx->i_oldargc -= 2;
 686                                 ctx->i_oldargv += 2;
 687                                 continue;


 763                         break;
 764                 case 'A':
 765                 case 'h':
 766                 case 'I':
 767                 case 'i':
 768                 case 'L':
 769                 case 'l':
 770                 case 'R':
 771                 case 'U':
 772                 case 'u':
 773                 case 'w':
 774                         newae(ctx->i_ae, arg);
 775                         break;
 776                 case 'o':
 777                         seen_o = 1;
 778                         if (arglen == 1) {
 779                                 in_output = 1;
 780                                 newae(ctx->i_ae, arg);
 781                         } else if (ctx->i_flags & CW_F_SHADOW) {
 782                                 newae(ctx->i_ae, "-o");
 783                                 ctx->i_discard = discard_file_name(arg);
 784                                 newae(ctx->i_ae, ctx->i_discard);
 785                         } else {
 786                                 newae(ctx->i_ae, arg);
 787                         }
 788                         break;
 789                 case 'D':
 790                         newae(ctx->i_ae, arg);
 791                         /*
 792                          * XXX  Clearly a hack ... do we need _KADB too?
 793                          */
 794                         if (strcmp(arg, "-D_KERNEL") == 0 ||
 795                             strcmp(arg, "-D_BOOT") == 0)
 796                                 newae(ctx->i_ae, "-ffreestanding");
 797                         break;
 798                 case 'd':
 799                         if (arglen == 2) {
 800                                 if (strcmp(arg, "-dy") == 0) {
 801                                         newae(ctx->i_ae, "-Wl,-dy");
 802                                         break;
 803                                 }


1202                                 s[1] = 'I';
1203                                 newae(ctx->i_ae, "-nostdinc");
1204                                 newae(ctx->i_ae, s);
1205                                 free(s);
1206                                 break;
1207                         }
1208                         error(arg);
1209                         break;
1210                 case 'Q':
1211                         /*
1212                          * We could map -Qy into -Wl,-Qy etc.
1213                          */
1214                 default:
1215                         error(arg);
1216                         break;
1217                 }
1218         }
1219 
1220         free(nameflag);
1221 
1222         /*
1223          * When compiling multiple source files in a single invocation some
1224          * compilers output objects into the current directory with
1225          * predictable and conventional names.
1226          *
1227          * We prevent any attempt to compile multiple files at once so that
1228          * any such objects created by a shadow can't escape into a later
1229          * link-edit.
1230          */
1231         if (c_files > 1 && op != CW_O_PREPROCESS) {
1232                 errx(2, "multiple source files are "
1233                     "allowed only with -E or -P");
1234         }
1235 
1236         /*
1237          * Make sure that we do not have any unintended interactions between
1238          * the xarch options passed in and the version of the Studio compiler
1239          * used.
1240          */
1241         if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1242                 errx(2,
1243                     "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1244         }
1245 
1246         switch (mflag) {
1247         case 0:
1248                 /* FALLTHROUGH */
1249         case M32:
1250 #if defined(__sparc)
1251                 /*


1279                 break;
1280         case (SS12|M32):
1281 #if defined(__sparc)
1282                 /*
1283                  * Need to add in further 32 bit options because with SS12
1284                  * the xarch=sparcvis option can be applied to 32 or 64
1285                  * bit, and so the translatation table (xtbl) cannot handle
1286                  * that.
1287                  */
1288                 newae(ctx->i_ae, "-mv8plus");
1289 #endif
1290                 break;
1291         case (SS12|M64):
1292                 break;
1293         default:
1294                 (void) fprintf(stderr,
1295                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1296                 exit(2);
1297         }
1298 
1299         if (ctx->i_flags & CW_F_SHADOW) {
1300                 if (op == CW_O_PREPROCESS)
1301                         exit(0);
1302                 else if (op == CW_O_LINK && c_files == 0)
1303                         exit(0);
1304         }
1305 
1306         if (model != NULL)
1307                 newae(ctx->i_ae, model);
1308         if (!nolibc)
1309                 newae(ctx->i_ae, "-lc");
1310         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1311                 ctx->i_discard = discard_file_name(NULL);
1312                 newae(ctx->i_ae, "-o");
1313                 newae(ctx->i_ae, ctx->i_discard);
1314         }
1315 }
1316 
1317 static void
1318 do_cc(cw_ictx_t *ctx)
1319 {
1320         int in_output = 0, seen_o = 0, c_files = 0;
1321         cw_op_t op = CW_O_LINK;
1322         char *nameflag;
1323 
1324         if (ctx->i_flags & CW_F_PROG) {
1325                 newae(ctx->i_ae, "-V");
1326                 return;
1327         }
1328 
1329         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1330                 nomem();
1331 
1332         while (--ctx->i_oldargc > 0) {
1333                 char *arg = *++ctx->i_oldargv;
1334                 size_t arglen = strlen(arg);
1335 
1336                 if (strncmp(arg, "-_CC=", 5) == 0) {
1337                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1338                         continue;
1339                 }
1340 
1341                 if (*arg != '-') {
1342                         if (!in_output && arglen > 2 &&
1343                             arg[arglen - 2] == '.' &&
1344                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
1345                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
1346                                 c_files++;
1347 
1348                         if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1349                                 newae(ctx->i_ae, arg);
1350                         } else {
1351                                 in_output = 0;
1352                                 ctx->i_discard = discard_file_name(arg);
1353                                 newae(ctx->i_ae, ctx->i_discard);
1354                         }
1355                         continue;
1356                 }
1357                 switch (*(arg + 1)) {
1358                 case '_':
1359                         if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1360                             (strncmp(arg, "-_cc=", 5) == 0) ||
1361                             (strncmp(arg, "-_sun=", 6) == 0)) {
1362                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
1363                         }
1364                         break;
1365 
1366                 case 'V':
1367                         ctx->i_flags &= ~CW_F_ECHO;
1368                         newae(ctx->i_ae, arg);
1369                         break;
1370                 case 'o':
1371                         seen_o = 1;
1372                         if (strlen(arg) == 2) {
1373                                 in_output = 1;
1374                                 newae(ctx->i_ae, arg);
1375                         } else if (ctx->i_flags & CW_F_SHADOW) {
1376                                 newae(ctx->i_ae, "-o");
1377                                 ctx->i_discard = discard_file_name(arg);
1378                                 newae(ctx->i_ae, ctx->i_discard);
1379                         } else {
1380                                 newae(ctx->i_ae, arg);
1381                         }
1382                         break;
1383                 case 'c':
1384                 case 'S':
1385                         if (strlen(arg) == 2)
1386                                 op = CW_O_COMPILE;
1387                         newae(ctx->i_ae, arg);
1388                         break;
1389                 case 'E':
1390                 case 'P':
1391                         if (strlen(arg) == 2)
1392                                 op = CW_O_PREPROCESS;
1393                 /*FALLTHROUGH*/
1394                 default:
1395                         newae(ctx->i_ae, arg);
1396                 }
1397         }
1398 
1399         free(nameflag);
1400 
1401         /* See the comment on this same code in do_gcc() */
1402         if (c_files > 1 && op != CW_O_PREPROCESS) {
1403                 errx(2, "multiple source files are "
1404                     "allowed only with -E or -P");
1405         }
1406 
1407         if (ctx->i_flags & CW_F_SHADOW) {
1408                 if (op == CW_O_PREPROCESS)
1409                         exit(0);
1410                 else if (op == CW_O_LINK && c_files == 0)
1411                         exit(0);
1412         }
1413 
1414         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1415                 newae(ctx->i_ae, "-o");
1416                 ctx->i_discard = discard_file_name(NULL);
1417                 newae(ctx->i_ae, ctx->i_discard);
1418         }
1419 }
1420 
1421 static void
1422 prepctx(cw_ictx_t *ctx)
1423 {
1424         newae(ctx->i_ae, ctx->i_compiler->c_path);
1425 
1426         if (ctx->i_flags & CW_F_PROG) {
1427                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1428                     "shadow" : "primary", ctx->i_compiler->c_path);
1429                 (void) fflush(stdout);
1430         }
1431 
1432         if (!(ctx->i_flags & CW_F_XLATE))
1433                 return;
1434 
1435         switch (ctx->i_compiler->c_style) {
1436         case SUN:


1506         if (ctx->i_pid <= 0)
1507                 return (-1);
1508 
1509         do {
1510                 if (waitpid(ctx->i_pid, &status, 0) < 0) {
1511                         warn("cannot reap child");
1512                         return (-1);
1513                 }
1514                 if (status != 0) {
1515                         if (WIFSIGNALED(status)) {
1516                                 ret = -WTERMSIG(status);
1517                                 break;
1518                         } else if (WIFEXITED(status)) {
1519                                 ret = WEXITSTATUS(status);
1520                                 break;
1521                         }
1522                 }
1523         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1524 
1525         (void) unlink(ctx->i_discard);
1526         free(ctx->i_discard);
1527 
1528         if (stat(ctx->i_stderr, &s) < 0) {
1529                 warn("stat failed on child cleanup");
1530                 return (-1);
1531         }
1532         if (s.st_size != 0) {
1533                 FILE *f;
1534 
1535                 if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1536                         while (fgets(buf, sizeof (buf), f))
1537                                 (void) fprintf(stderr, "%s", buf);
1538                         (void) fflush(stderr);
1539                         (void) fclose(f);
1540                 }
1541         }
1542         (void) unlink(ctx->i_stderr);
1543         free(ctx->i_stderr);
1544 
1545         /*
1546          * cc returns an error code when given -V; we want that to succeed.
1547          */
1548         if (ctx->i_flags & CW_F_PROG)
1549                 return (0);
1550 
1551         return (ret);
1552 }
1553 
1554 static int
1555 exec_ctx(cw_ictx_t *ctx, int block)
1556 {














1557         if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
1558                 nomem();
1559                 return (-1);
1560         }
1561 
1562         if ((ctx->i_pid = fork()) == 0) {
1563                 int fd;
1564 
1565                 (void) fclose(stderr);
1566                 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1567                     0666)) < 0) {
1568                         err(1, "open failed for standard error");
1569                 }
1570                 if (dup2(fd, 2) < 0) {
1571                         err(1, "dup2 failed for standard error");
1572                 }
1573                 if (fd != 2)
1574                         (void) close(fd);
1575                 if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1576                         err(1, "freopen failed for /dev/fd/2");




 291 
 292 typedef enum {
 293         GNU,
 294         SUN
 295 } compiler_style_t;
 296 
 297 typedef struct {
 298         char *c_name;
 299         char *c_path;
 300         compiler_style_t c_style;
 301 } cw_compiler_t;
 302 
 303 typedef struct cw_ictx {
 304         struct cw_ictx  *i_next;
 305         cw_compiler_t   *i_compiler;
 306         struct aelist   *i_ae;
 307         uint32_t        i_flags;
 308         int             i_oldargc;
 309         char            **i_oldargv;
 310         pid_t           i_pid;
 311         char            i_discard[MAXPATHLEN];
 312         char            *i_stderr;
 313 } cw_ictx_t;
 314 
 315 /*
 316  * Status values to indicate which Studio compiler and associated
 317  * flags are being used.
 318  */
 319 #define M32             0x01    /* -m32 - only on Studio 12 */
 320 #define M64             0x02    /* -m64 - only on Studio 12 */
 321 #define SS11            0x100   /* Studio 11 */
 322 #define SS12            0x200   /* Studio 12 */
 323 
 324 #define TRANS_ENTRY     5
 325 /*
 326  * Translation table definition for the -xarch= flag. The "x_arg"
 327  * value is translated into the appropriate gcc flags according
 328  * to the values in x_trans[n]. The x_flags indicates what compiler
 329  * is being used and what flags have been set via the use of
 330  * "x_arg".
 331  */


 536 static void
 537 xlate(struct aelist *h, const char *xarg, const char **table)
 538 {
 539         while (*table != NULL && strcmp(xarg, *table) != 0) {
 540                 while (*table != NULL)
 541                         table++;
 542                 table++;
 543         }
 544 
 545         if (*table == NULL)
 546                 error(xarg);
 547 
 548         table++;
 549 
 550         while (*table != NULL) {
 551                 newae(h, *table);
 552                 table++;
 553         }
 554 }
 555 





























 556 static void
 557 do_gcc(cw_ictx_t *ctx)
 558 {
 559         int c;
 560         int nolibc = 0;
 561         int in_output = 0, seen_o = 0, c_files = 0;
 562         cw_op_t op = CW_O_LINK;
 563         char *model = NULL;
 564         char *nameflag;
 565         int     mflag = 0;
 566 
 567         if (ctx->i_flags & CW_F_PROG) {
 568                 newae(ctx->i_ae, "--version");
 569                 return;
 570         }
 571 
 572         newae(ctx->i_ae, "-fident");
 573         newae(ctx->i_ae, "-finline");
 574         newae(ctx->i_ae, "-fno-inline-functions");
 575         newae(ctx->i_ae, "-fno-builtin");


 613                 } else {
 614                         /*
 615                          * Discard inline files that gcc doesn't grok
 616                          */
 617                         if (!in_output && arglen > 3 &&
 618                             strcmp(arg + arglen - 3, ".il") == 0)
 619                                 continue;
 620 
 621                         if (!in_output && arglen > 2 &&
 622                             arg[arglen - 2] == '.' &&
 623                             (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 624                             arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 625                                 c_files++;
 626 
 627                         /*
 628                          * Otherwise, filenames and partial arguments
 629                          * are passed through for gcc to chew on.  However,
 630                          * output is always discarded for the secondary
 631                          * compiler.
 632                          */
 633                         if ((ctx->i_flags & CW_F_SHADOW) && in_output)

 634                                 newae(ctx->i_ae, ctx->i_discard);
 635                         else
 636                                 newae(ctx->i_ae, arg);

 637                         in_output = 0;
 638                         continue;
 639                 }
 640 
 641                 if (ctx->i_flags & CW_F_CXX) {
 642                         if (strncmp(arg, "-_g++=", 6) == 0) {
 643                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
 644                                 continue;
 645                         }
 646                         if (strncmp(arg, "-compat=", 8) == 0) {
 647                                 /* discard -compat=4 and -compat=5 */
 648                                 continue;
 649                         }
 650                         if (strcmp(arg, "-Qoption") == 0) {
 651                                 /* discard -Qoption and its two arguments */
 652                                 if (ctx->i_oldargc < 3)
 653                                         error(arg);
 654                                 ctx->i_oldargc -= 2;
 655                                 ctx->i_oldargv += 2;
 656                                 continue;


 732                         break;
 733                 case 'A':
 734                 case 'h':
 735                 case 'I':
 736                 case 'i':
 737                 case 'L':
 738                 case 'l':
 739                 case 'R':
 740                 case 'U':
 741                 case 'u':
 742                 case 'w':
 743                         newae(ctx->i_ae, arg);
 744                         break;
 745                 case 'o':
 746                         seen_o = 1;
 747                         if (arglen == 1) {
 748                                 in_output = 1;
 749                                 newae(ctx->i_ae, arg);
 750                         } else if (ctx->i_flags & CW_F_SHADOW) {
 751                                 newae(ctx->i_ae, "-o");

 752                                 newae(ctx->i_ae, ctx->i_discard);
 753                         } else {
 754                                 newae(ctx->i_ae, arg);
 755                         }
 756                         break;
 757                 case 'D':
 758                         newae(ctx->i_ae, arg);
 759                         /*
 760                          * XXX  Clearly a hack ... do we need _KADB too?
 761                          */
 762                         if (strcmp(arg, "-D_KERNEL") == 0 ||
 763                             strcmp(arg, "-D_BOOT") == 0)
 764                                 newae(ctx->i_ae, "-ffreestanding");
 765                         break;
 766                 case 'd':
 767                         if (arglen == 2) {
 768                                 if (strcmp(arg, "-dy") == 0) {
 769                                         newae(ctx->i_ae, "-Wl,-dy");
 770                                         break;
 771                                 }


1170                                 s[1] = 'I';
1171                                 newae(ctx->i_ae, "-nostdinc");
1172                                 newae(ctx->i_ae, s);
1173                                 free(s);
1174                                 break;
1175                         }
1176                         error(arg);
1177                         break;
1178                 case 'Q':
1179                         /*
1180                          * We could map -Qy into -Wl,-Qy etc.
1181                          */
1182                 default:
1183                         error(arg);
1184                         break;
1185                 }
1186         }
1187 
1188         free(nameflag);
1189 
1190         if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1191             op != CW_O_PREPROCESS) {








1192                 errx(2, "multiple source files are "
1193                     "allowed only with -E or -P");
1194         }
1195 
1196         /*
1197          * Make sure that we do not have any unintended interactions between
1198          * the xarch options passed in and the version of the Studio compiler
1199          * used.
1200          */
1201         if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1202                 errx(2,
1203                     "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1204         }
1205 
1206         switch (mflag) {
1207         case 0:
1208                 /* FALLTHROUGH */
1209         case M32:
1210 #if defined(__sparc)
1211                 /*


1239                 break;
1240         case (SS12|M32):
1241 #if defined(__sparc)
1242                 /*
1243                  * Need to add in further 32 bit options because with SS12
1244                  * the xarch=sparcvis option can be applied to 32 or 64
1245                  * bit, and so the translatation table (xtbl) cannot handle
1246                  * that.
1247                  */
1248                 newae(ctx->i_ae, "-mv8plus");
1249 #endif
1250                 break;
1251         case (SS12|M64):
1252                 break;
1253         default:
1254                 (void) fprintf(stderr,
1255                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1256                 exit(2);
1257         }
1258 
1259         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1260             (ctx->i_flags & CW_F_SHADOW))
1261                 exit(0);



1262 
1263         if (model != NULL)
1264                 newae(ctx->i_ae, model);
1265         if (!nolibc)
1266                 newae(ctx->i_ae, "-lc");
1267         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {

1268                 newae(ctx->i_ae, "-o");
1269                 newae(ctx->i_ae, ctx->i_discard);
1270         }
1271 }
1272 
1273 static void
1274 do_cc(cw_ictx_t *ctx)
1275 {
1276         int in_output = 0, seen_o = 0;
1277         cw_op_t op = CW_O_LINK;
1278         char *nameflag;
1279 
1280         if (ctx->i_flags & CW_F_PROG) {
1281                 newae(ctx->i_ae, "-V");
1282                 return;
1283         }
1284 
1285         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1286                 nomem();
1287 
1288         while (--ctx->i_oldargc > 0) {
1289                 char *arg = *++ctx->i_oldargv;

1290 
1291                 if (strncmp(arg, "-_CC=", 5) == 0) {
1292                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1293                         continue;
1294                 }
1295 
1296                 if (*arg != '-') {






1297                         if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1298                                 newae(ctx->i_ae, arg);
1299                         } else {
1300                                 in_output = 0;

1301                                 newae(ctx->i_ae, ctx->i_discard);
1302                         }
1303                         continue;
1304                 }
1305                 switch (*(arg + 1)) {
1306                 case '_':
1307                         if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1308                             (strncmp(arg, "-_cc=", 5) == 0) ||
1309                             (strncmp(arg, "-_sun=", 6) == 0)) {
1310                                 newae(ctx->i_ae, strchr(arg, '=') + 1);
1311                         }
1312                         break;
1313 
1314                 case 'V':
1315                         ctx->i_flags &= ~CW_F_ECHO;
1316                         newae(ctx->i_ae, arg);
1317                         break;
1318                 case 'o':
1319                         seen_o = 1;
1320                         if (strlen(arg) == 2) {
1321                                 in_output = 1;
1322                                 newae(ctx->i_ae, arg);
1323                         } else if (ctx->i_flags & CW_F_SHADOW) {
1324                                 newae(ctx->i_ae, "-o");

1325                                 newae(ctx->i_ae, ctx->i_discard);
1326                         } else {
1327                                 newae(ctx->i_ae, arg);
1328                         }
1329                         break;
1330                 case 'c':
1331                 case 'S':
1332                         if (strlen(arg) == 2)
1333                                 op = CW_O_COMPILE;
1334                         newae(ctx->i_ae, arg);
1335                         break;
1336                 case 'E':
1337                 case 'P':
1338                         if (strlen(arg) == 2)
1339                                 op = CW_O_PREPROCESS;
1340                 /*FALLTHROUGH*/
1341                 default:
1342                         newae(ctx->i_ae, arg);
1343                 }
1344         }
1345 
1346         free(nameflag);
1347 
1348         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1349             (ctx->i_flags & CW_F_SHADOW))






1350                 exit(0);



1351 
1352         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1353                 newae(ctx->i_ae, "-o");

1354                 newae(ctx->i_ae, ctx->i_discard);
1355         }
1356 }
1357 
1358 static void
1359 prepctx(cw_ictx_t *ctx)
1360 {
1361         newae(ctx->i_ae, ctx->i_compiler->c_path);
1362 
1363         if (ctx->i_flags & CW_F_PROG) {
1364                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1365                     "shadow" : "primary", ctx->i_compiler->c_path);
1366                 (void) fflush(stdout);
1367         }
1368 
1369         if (!(ctx->i_flags & CW_F_XLATE))
1370                 return;
1371 
1372         switch (ctx->i_compiler->c_style) {
1373         case SUN:


1443         if (ctx->i_pid <= 0)
1444                 return (-1);
1445 
1446         do {
1447                 if (waitpid(ctx->i_pid, &status, 0) < 0) {
1448                         warn("cannot reap child");
1449                         return (-1);
1450                 }
1451                 if (status != 0) {
1452                         if (WIFSIGNALED(status)) {
1453                                 ret = -WTERMSIG(status);
1454                                 break;
1455                         } else if (WIFEXITED(status)) {
1456                                 ret = WEXITSTATUS(status);
1457                                 break;
1458                         }
1459                 }
1460         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1461 
1462         (void) unlink(ctx->i_discard);

1463 
1464         if (stat(ctx->i_stderr, &s) < 0) {
1465                 warn("stat failed on child cleanup");
1466                 return (-1);
1467         }
1468         if (s.st_size != 0) {
1469                 FILE *f;
1470 
1471                 if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1472                         while (fgets(buf, sizeof (buf), f))
1473                                 (void) fprintf(stderr, "%s", buf);
1474                         (void) fflush(stderr);
1475                         (void) fclose(f);
1476                 }
1477         }
1478         (void) unlink(ctx->i_stderr);
1479         free(ctx->i_stderr);
1480 
1481         /*
1482          * cc returns an error code when given -V; we want that to succeed.
1483          */
1484         if (ctx->i_flags & CW_F_PROG)
1485                 return (0);
1486 
1487         return (ret);
1488 }
1489 
1490 static int
1491 exec_ctx(cw_ictx_t *ctx, int block)
1492 {
1493         char *file;
1494 
1495         /*
1496          * To avoid offending cc's sensibilities, the name of its output
1497          * file must end in '.o'.
1498          */
1499         if ((file = tempnam(NULL, ".cw")) == NULL) {
1500                 nomem();
1501                 return (-1);
1502         }
1503         (void) strlcpy(ctx->i_discard, file, MAXPATHLEN);
1504         (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
1505         free(file);
1506 
1507         if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
1508                 nomem();
1509                 return (-1);
1510         }
1511 
1512         if ((ctx->i_pid = fork()) == 0) {
1513                 int fd;
1514 
1515                 (void) fclose(stderr);
1516                 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1517                     0666)) < 0) {
1518                         err(1, "open failed for standard error");
1519                 }
1520                 if (dup2(fd, 2) < 0) {
1521                         err(1, "dup2 failed for standard error");
1522                 }
1523                 if (fd != 2)
1524                         (void) close(fd);
1525                 if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1526                         err(1, "freopen failed for /dev/fd/2");