/* truss on solaris doesn't print timestamps on its output... which is pretty annoying/useless. This is a hack wrapper which adds timestamps to every line of input. -djg */ #include #include #include #include #include #include #include #include pid_t truss_child; void sigthing(int sig) { kill(truss_child, sig); exit(1); } int stamp(int fd_in, FILE *f_out) { char buf[4096]; int i; struct timeval now; char fmtnow[100]; int j; int after_nl; after_nl = 1; for (;;) { i = read(fd_in, buf, sizeof(buf)); if (i <= 0) break; gettimeofday(&now, 0); sprintf(fmtnow, "%lu.%06lu ", now.tv_sec, now.tv_usec); for (j = 0; j < i; ++j) { if (after_nl) { fputs(fmtnow, f_out); after_nl = 0; } fputc(buf[j], f_out); if (buf[j] == '\n') { after_nl = 1; } } } return i != 0; } int main(int argc, char **argv) { char **new_argv; int i, j; FILE *f_out; int err_pipe[2]; setvbuf(stderr, NULL, _IOLBF, BUFSIZ); f_out = stderr; new_argv = malloc(sizeof(char *) * (argc + 1)); new_argv[0] = "truss"; j = 1; for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 't': case 'v': case 'x': case 's': case 'm': case 'r': case 'w': new_argv[j++] = argv[i++]; new_argv[j++] = argv[i]; break; case 'p': goto copy_rest; case 'o': ++i; f_out = fopen(argv[i], "w"); if (f_out == NULL) { perror("unable to open output file"); exit(1); } break; default: new_argv[j++] = argv[i]; break; } } else { copy_rest: while (i < argc) { new_argv[j++] = argv[i++]; } break; } } new_argv[j] = NULL; signal(SIGTERM, sigthing); signal(SIGINT, sigthing); /*signal(SIGCHLD, sigthing);*/ signal(SIGPIPE, SIG_IGN); if (pipe(err_pipe) != 0) { perror("pipe"); exit(1); } truss_child = fork(); if (truss_child == 0) { close(err_pipe[0]); close(2); if (dup2(err_pipe[1], 2) < 0) { perror("dup2"); exit(1); } execvp("truss", new_argv); perror("execvp"); exit(1); } if (truss_child == -1) { perror("fork"); } close(err_pipe[1]); return stamp(err_pipe[0], f_out); }