static char * prwhat(int why, int what) { static char buf[32]; char *str; switch (why) { case PR_SIGNALLED: case PR_JOBCONTROL: str = proc_signame(what, buf, sizeof (buf)); break; case PR_SYSENTRY: case PR_SYSEXIT: str = proc_sysname(what, buf, sizeof (buf)); break; case PR_FAULTED: str = proc_fltname(what, buf, sizeof (buf)); break; default: (void) sprintf(str = buf, "%d", what); break; } return (str); }
/*ARGSUSED*/ static void prochandler(struct ps_prochandle *P, const char *msg, void *arg) { #if !defined(__APPLE__) const psinfo_t *prp = Ppsinfo(P); int pid = Pstatus(P)->pr_pid; char name[SIG2STR_MAX]; #else #define SIG2STR_MAX 32 /* Not referenced so long as prp just below is NULL. */ #define proc_signame(x,y,z) "Unknown" /* Not referenced so long as prp just below is NULL. */ typedef struct psinfo { int pr_wstat; } psinfo_t; const psinfo_t *prp = NULL; int pid = Pstatus(P)->pr_pid; #endif /* __APPLE__ */ if (msg != NULL) { notice("pid %d: %s\n", pid, msg); return; } switch (Pstate(P)) { case PS_UNDEAD: /* * Ideally we would like to always report pr_wstat here, but it * isn't possible given current /proc semantics. If we grabbed * the process, Ppsinfo() will either fail or return a zeroed * psinfo_t depending on how far the parent is in reaping it. * When /proc provides a stable pr_wstat in the status file, * this code can be improved by examining this new pr_wstat. */ if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) { notice("pid %d terminated by %s\n", pid, proc_signame(WTERMSIG(prp->pr_wstat), name, sizeof (name))); } else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) { notice("pid %d exited with status %d\n", pid, WEXITSTATUS(prp->pr_wstat)); } else { notice("pid %d has exited\n", pid); } g_exited = 1; break; case PS_LOST: #if !defined(__APPLE__) notice("pid %d exec'd a set-id or unobservable program\n", pid); #else notice("pid %d has exited\n", pid); #endif g_exited = 1; break; } }
/*ARGSUSED*/ static void prochandler(struct ps_prochandle *P, const char *msg, void *arg) { #if defined(sun) const psinfo_t *prp = Ppsinfo(P); int pid = Pstatus(P)->pr_pid; char name[SIG2STR_MAX]; #else int wstatus = proc_getwstat(P); int pid = proc_getpid(P); #endif if (msg != NULL) { notice("pid %d: %s\n", pid, msg); return; } #if defined(sun) switch (Pstate(P)) { #else switch (proc_state(P)) { #endif case PS_UNDEAD: #if defined(sun) /* * Ideally we would like to always report pr_wstat here, but it * isn't possible given current /proc semantics. If we grabbed * the process, Ppsinfo() will either fail or return a zeroed * psinfo_t depending on how far the parent is in reaping it. * When /proc provides a stable pr_wstat in the status file, * this code can be improved by examining this new pr_wstat. */ if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) { notice("pid %d terminated by %s\n", pid, proc_signame(WTERMSIG(prp->pr_wstat), name, sizeof (name))); #else if (WIFSIGNALED(wstatus)) { notice("pid %d terminated by %d\n", pid, WTERMSIG(wstatus)); #endif #if defined(sun) } else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) { notice("pid %d exited with status %d\n", pid, WEXITSTATUS(prp->pr_wstat)); #else } else if (WEXITSTATUS(wstatus) != 0) { notice("pid %d exited with status %d\n", pid, WEXITSTATUS(wstatus)); #endif } else { notice("pid %d has exited\n", pid); } g_pslive--; break; case PS_LOST: notice("pid %d exec'd a set-id or unobservable program\n", pid); g_pslive--; break; } } /*ARGSUSED*/ static int errhandler(const dtrace_errdata_t *data, void *arg) { error(data->dteda_msg); return (DTRACE_HANDLE_OK); } /*ARGSUSED*/ static int drophandler(const dtrace_dropdata_t *data, void *arg) { error(data->dtdda_msg); return (DTRACE_HANDLE_OK); }
static int lwplook(look_arg_t *arg, const lwpstatus_t *psp, const lwpsinfo_t *pip) { int flags; uint32_t sighold, sighold1, sighold2; uint32_t sigpend, sigpend1, sigpend2; int cursig; char buf[32]; if (!proc_lwp_in_set(arg->lwps, pip->pr_lwpid)) return (0); arg->count++; if (psp == NULL) return (lwplook_zombie(pip)); /* * PR_PCINVAL is just noise if the lwp is not stopped. * Don't bother reporting it unless the lwp is stopped. */ flags = psp->pr_flags & LWPFLAGS; if (!(flags & PR_STOPPED)) flags &= ~PR_PCINVAL; (void) printf(" /%d:\tflags = %s", (int)psp->pr_lwpid, prflags(flags)); if ((flags & PR_ASLEEP) || (psp->pr_syscall && !(arg->pflags & PR_ISSYS))) { if (flags & PR_ASLEEP) { if ((flags & ~PR_ASLEEP) != 0) (void) printf("|"); (void) printf("ASLEEP"); } if (psp->pr_syscall && !(arg->pflags & PR_ISSYS)) { uint_t i; (void) printf(" %s(", proc_sysname(psp->pr_syscall, buf, sizeof (buf))); for (i = 0; i < psp->pr_nsysarg; i++) { if (i != 0) (void) printf(","); (void) printf("0x%lx", psp->pr_sysarg[i]); } (void) printf(")"); } } (void) printf("\n"); if (flags & PR_STOPPED) { (void) printf("\twhy = %s", prwhy(psp->pr_why)); if (psp->pr_why != PR_REQUESTED && psp->pr_why != PR_SUSPENDED) (void) printf(" what = %s", prwhat(psp->pr_why, psp->pr_what)); (void) printf("\n"); } #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */ sighold = *((uint32_t *)&psp->pr_lwphold); sighold1 = *((uint32_t *)&psp->pr_lwphold + 1); sighold2 = *((uint32_t *)&psp->pr_lwphold + 2); sigpend = *((uint32_t *)&psp->pr_lwppend); sigpend1 = *((uint32_t *)&psp->pr_lwppend + 1); sigpend2 = *((uint32_t *)&psp->pr_lwppend + 2); #else #error "fix me: MAXSIG out of bounds" #endif cursig = psp->pr_cursig; if (sighold | sighold1 | sighold2) (void) printf("\tsigmask = 0x%.8x,0x%.8x,0x%.8x\n", sighold, sighold1, sighold2); if (sigpend | sigpend1 | sigpend2) (void) printf("\tlwppend = 0x%.8x,0x%.8x,0x%.8x\n", sigpend, sigpend1, sigpend2); if (cursig) (void) printf("\tcursig = %s\n", proc_signame(cursig, buf, sizeof (buf))); if (rflag) { if (Pstate(Pr) == PS_DEAD || (arg->pflags & PR_STOPPED)) { #if defined(__sparc) && defined(_ILP32) /* * If we're SPARC/32-bit, see if we can get extra * register state for this lwp. If it's a v8plus * program, print the 64-bit register values. */ prxregset_t prx; if (Plwp_getxregs(Pr, psp->pr_lwpid, &prx) == 0 && prx.pr_type == XR_TYPE_V8P) dumpregs_v8p(psp->pr_reg, &prx, is64); else #endif /* __sparc && _ILP32 */ dumpregs(psp->pr_reg, is64); } else (void) printf("\tNot stopped, can't show registers\n"); } return (0); }
int main(int argc, char **argv) { int opt, exit; pid_t pid; struct siginfo info; int status; int gret; struct ps_prochandle *Pr; if ((command = strrchr(argv[0], '/')) != NULL) command++; else command = argv[0]; while ((opt = getopt(argc, argv, "Fhmp:")) != EOF) { switch (opt) { case 'F': /* force grabbing (no O_EXCL) */ Fflag = PGRAB_FORCE; break; case 'm': /* microstate accounting */ mflag = 1; break; case 'p': pflag = 1; pidarg = optarg; break; default: errflg = 1; break; } } argc -= optind; argv += optind; if (((pidarg != NULL) ^ (argc < 1)) || errflg) { (void) fprintf(stderr, "usage:\t%s [-mh] [-p pidlist | command [ args ... ]]\n", command); (void) fprintf(stderr, " (time a command using microstate accounting)\n"); return (1); } if (pflag) { char *pp; exit = 0; (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); pp = strtok(pidarg, ", "); if (pp == NULL) { (void) fprintf(stderr, "%s: invalid argument for -p\n", command); return (1); } exit = ptime_pid(pp); while ((pp = strtok(NULL, ", ")) != NULL) { exit |= ptime_pid(pp); } return (exit); } if ((Pr = Pcreate(argv[0], &argv[0], &gret, NULL, 0)) == NULL) { (void) fprintf(stderr, "%s: failed to exec %s: %s\n", command, argv[0], Pcreate_error(gret)); return (1); } if (Psetrun(Pr, 0, 0) == -1) { (void) fprintf(stderr, "%s: failed to set running %s: " "%s\n", command, argv[0], strerror(errno)); return (1); } pid = Pstatus(Pr)->pr_pid; (void) sprintf(procname, "%d", (int)pid); /* for perr() */ (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); (void) waitid(P_PID, pid, &info, WEXITED | WNOWAIT); (void) look(pid); (void) waitpid(pid, &status, 0); if (WIFEXITED(status)) return (WEXITSTATUS(status)); if (WIFSIGNALED(status)) { int sig = WTERMSIG(status); char name[SIG2STR_MAX]; (void) fprintf(stderr, "%s: command terminated " "abnormally by %s\n", command, proc_signame(sig, name, sizeof (name))); } return (status | WCOREFLG); /* see time(1) */ }