summaryrefslogtreecommitdiff
path: root/usr/src/tools/cw/cw.c
diff options
context:
space:
mode:
authorwesolows <none@none>2006-04-11 13:06:32 -0700
committerwesolows <none@none>2006-04-11 13:06:32 -0700
commit1912d2c422eed6478ec6b9816050f890fb12ab72 (patch)
treef5892f7f148bf240e821f8d2ff919c50e00dfdc6 /usr/src/tools/cw/cw.c
parent7ff1e9f5d4f5770ee7f13fb603026ed2b07bd99b (diff)
downloadillumos-joyent-1912d2c422eed6478ec6b9816050f890fb12ab72.tar.gz
6406661 nightly doesn't tell about the shadow compiler
6406667 cw should tell you its version 6409965 cw waitpid and gcc writing to stderr can deadlock
Diffstat (limited to 'usr/src/tools/cw/cw.c')
-rw-r--r--usr/src/tools/cw/cw.c102
1 files changed, 77 insertions, 25 deletions
diff --git a/usr/src/tools/cw/cw.c b/usr/src/tools/cw/cw.c
index 7cf7bcf15c..2d68311ce7 100644
--- a/usr/src/tools/cw/cw.c
+++ b/usr/src/tools/cw/cw.c
@@ -302,6 +302,7 @@
#define CW_F_EXEC 0x04
#define CW_F_ECHO 0x08
#define CW_F_XLATE 0x10
+#define CW_F_PROG 0x20
typedef enum cw_compiler {
CW_C_CC = 0,
@@ -348,8 +349,8 @@ typedef struct cw_ictx {
int i_oldargc;
char **i_oldargv;
pid_t i_pid;
- int i_fd[2];
char i_discard[MAXPATHLEN];
+ char *i_stderr;
} cw_ictx_t;
static const char *progname;
@@ -578,6 +579,11 @@ do_gcc(cw_ictx_t *ctx)
cw_op_t op = CW_O_LINK;
char *model = NULL;
+ if (ctx->i_flags & CW_F_PROG) {
+ newae(ctx->i_ae, "--version");
+ return;
+ }
+
newae(ctx->i_ae, "-fident");
newae(ctx->i_ae, "-finline");
newae(ctx->i_ae, "-fno-inline-functions");
@@ -1328,6 +1334,11 @@ do_cc(cw_ictx_t *ctx)
int in_output = 0, seen_o = 0;
cw_op_t op = CW_O_LINK;
+ if (ctx->i_flags & CW_F_PROG) {
+ newae(ctx->i_ae, "-V");
+ return;
+ }
+
while (--ctx->i_oldargc > 0) {
char *arg = *++ctx->i_oldargv;
@@ -1411,6 +1422,12 @@ prepctx(cw_ictx_t *ctx)
newae(ctx->i_ae, program);
+ if (ctx->i_flags & CW_F_PROG) {
+ (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
+ "shadow" : "primary", program);
+ (void) fflush(stdout);
+ }
+
if (!(ctx->i_flags & CW_F_XLATE))
return;
@@ -1475,38 +1492,47 @@ invoke(cw_ictx_t *ctx)
static int
reap(cw_ictx_t *ctx)
{
- int stat, ret = 0;
+ int status, ret = 0;
char buf[1024];
struct stat s;
do {
- (void) waitpid(ctx->i_pid, &stat, 0);
- if (stat != 0) {
- if (WIFSIGNALED(stat)) {
- ret = -WTERMSIG(stat);
+ (void) waitpid(ctx->i_pid, &status, 0);
+ if (status != 0) {
+ if (WIFSIGNALED(status)) {
+ ret = -WTERMSIG(status);
break;
- } else if (WIFEXITED(stat)) {
- ret = WEXITSTATUS(stat);
+ } else if (WIFEXITED(status)) {
+ ret = WEXITSTATUS(status);
break;
}
}
- } while (!WIFEXITED(stat) && !WIFSIGNALED(stat));
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
(void) unlink(ctx->i_discard);
- if (fstat(ctx->i_fd[0], &s) < 0) {
+ if (stat(ctx->i_stderr, &s) < 0) {
cw_perror("stat failed on child cleanup");
return (-1);
}
if (s.st_size != 0) {
- FILE *f = fdopen(ctx->i_fd[0], "r");
+ FILE *f;
- while (fgets(buf, sizeof (buf), f))
- (void) fprintf(stderr, "%s", buf);
- (void) fflush(stderr);
- (void) fclose(f);
+ if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
+ while (fgets(buf, sizeof (buf), f))
+ (void) fprintf(stderr, "%s", buf);
+ (void) fflush(stderr);
+ (void) fclose(f);
+ }
}
- (void) close(ctx->i_fd[0]);
+ (void) unlink(ctx->i_stderr);
+ free(ctx->i_stderr);
+
+ /*
+ * cc returns an error code when given -V; we want that to succeed.
+ */
+ if (ctx->i_flags & CW_F_PROG)
+ return (0);
return (ret);
}
@@ -1528,19 +1554,26 @@ exec_ctx(cw_ictx_t *ctx, int block)
(void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
free(file);
- if (pipe(ctx->i_fd) < 0) {
- cw_perror("pipe creation failed");
+ if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
+ nomem();
return (-1);
}
if ((ctx->i_pid = fork()) == 0) {
- (void) close(ctx->i_fd[0]);
+ int fd;
+
(void) fclose(stderr);
- if (dup2(ctx->i_fd[1], 2) < 0) {
+ if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
+ 0666)) < 0) {
+ cw_perror("open failed for standard error");
+ exit(1);
+ }
+ if (dup2(fd, 2) < 0) {
cw_perror("dup2 failed for standard error");
exit(1);
}
- (void) close(ctx->i_fd[1]);
+ if (fd != 2)
+ (void) close(fd);
if (freopen("/dev/fd/2", "w", stderr) == NULL) {
cw_perror("freopen failed for /dev/fd/2");
exit(1);
@@ -1553,7 +1586,6 @@ exec_ctx(cw_ictx_t *ctx, int block)
cw_perror("fork failed");
return (1);
}
- (void) close(ctx->i_fd[1]);
if (block)
return (reap(ctx));
@@ -1643,9 +1675,9 @@ main(int argc, char **argv)
ctx->i_compiler = CW_C_GCC;
}
- ctx->i_oldargc = argc;
- ctx->i_oldargv = argv;
-
+ /*
+ * -_compiler - tell us the path to the primary compiler only
+ */
if (argc > 1 && strcmp(argv[1], "-_compiler") == 0) {
ctx->i_flags &= ~CW_F_XLATE;
prepctx(ctx);
@@ -1653,6 +1685,26 @@ main(int argc, char **argv)
return (0);
}
+ /*
+ * -_versions - tell us the cw version, paths to all compilers, and
+ * ask each for its version if we know how.
+ */
+ if (argc > 1 && strcmp(argv[1], "-_versions") == 0) {
+ (void) printf("%s", "cw version %I%");
+ if (!do_shadow)
+ (void) printf(" (SHADOW MODE DISABLED)");
+ (void) printf("\n");
+ (void) fflush(stdout);
+ ctx->i_flags &= ~CW_F_ECHO;
+ ctx->i_flags |= CW_F_PROG|CW_F_EXEC;
+ argc--;
+ argv++;
+ do_serial = 1;
+ }
+
+ ctx->i_oldargc = argc;
+ ctx->i_oldargv = argv;
+
ret |= exec_ctx(ctx, do_serial);
if (do_shadow) {