/* execsnoop.c - snoop process execution. Uses DTrace for Solaris 10. * This program was written as a short demostration of libdtrace. * * 09-May-2005, ver 0.10 (first release. check for newer versions) * * COMPILE: cc -ldtrace -o execsnoop execsnoop.c * * NOTE! libdtrace is currently a private interface, and not intended * for public use. Check the man pages libdtrace(3LIB) and dtrace(7D). * Currently the dtrace(1M) compiler is the only supported interface. * * Standard Disclaimer: This is freeware, use at your own risk. * * 09-May-2005 Brendan Gregg Created this. */ #include #include #include #include #include #include #include #include #include #include #include /* * Global varibles */ static int g_debug = 0; /* debugging output */ static dtrace_hdl_t *g_dtp; /* dtrace handler */ static FILE *g_ofp = stdout; /* dtrace output filedes */ static int g_intr = 0; /* interrupt flag */ static int g_status = 0; /* dtrace status */ /* * The DTrace script */ static const char *g_prog = "syscall::exece:return" "{" " printf(\"\%5d \%5d \%5d \%s\\n\",uid,pid,ppid,curpsinfo->pr_psargs);" "}"; /* * Functions */ /* print header */ static void doheader() { fprintf(g_ofp,"%5s %5s %5s %s\n","UID","PID","PPID","ARGS"); } /* customised error exit */ static int die(int code, const char *fmt, const char *msg) { fprintf(stderr,fmt,msg); exit(code); } /* interrupt trap */ static void trapintr(int signo) { g_intr++; } /* process probe */ static int doprobe(const dtrace_probedata_t *data, void *arg) { dtrace_probedesc_t *pd = data->dtpda_pdesc; if (g_debug) fprintf(stderr,"debug2: %s:%s:%s:%s\n",pd->dtpd_provider, pd->dtpd_mod, pd->dtpd_func,pd->dtpd_name); return (DTRACE_CONSUME_THIS); } /* process record */ static int dorec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) { dtrace_actkind_t act; uintptr_t addr; if (rec == NULL) return (DTRACE_CONSUME_NEXT); act = rec->dtrd_action; addr = (uintptr_t)data->dtpda_data; if (act == DTRACEACT_EXIT) { g_status = *((uint32_t *)addr); return (DTRACE_CONSUME_NEXT); } return (DTRACE_CONSUME_THIS); } /* * Main program */ int main(int argc, char *argv[]) { /* Variable declerations */ dtrace_prog_t *dpp; dtrace_proginfo_t dpi; struct sigaction act; int err,status,done; done = 0; /* Trap Ctrl-C */ (void) sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = trapintr; (void) sigaction(SIGINT, &act, NULL); /* open dtrace */ if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) die(1,"ERROR1: opening dtrace: %s\n",dtrace_errmsg(NULL,err)); /* set buffer size */ (void) dtrace_setopt(g_dtp, "bufsize", "4m"); /* compile dtrace script */ if ((dpp = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) die(2,"ERROR2: bad program: %s\n",dtrace_errmsg(NULL,err)); /* enable dtrace probes */ if (dtrace_program_exec(g_dtp, dpp, &dpi) == -1) die(3,"ERROR3: enabling probes",NULL); if (g_debug) fprintf(stderr,"debug1: matched %u probes\n",dpi.dpi_matches); if (dtrace_go(g_dtp) != 0) die(4,"ERROR4: dtrace go: %s\n",dtrace_errmsg(NULL,err)); /* print header */ doheader(); /* main loop */ do { dtrace_sleep(g_dtp); status = dtrace_work(g_dtp, g_ofp, doprobe, dorec, NULL); if (status == DTRACE_WORKSTATUS_DONE) done = 1; if (fflush(g_ofp) == EOF) clearerr(g_ofp); } while (!done && !g_intr); /* close dtrace */ if (g_debug) fprintf(stderr,"debug3: goodbye.\n"); dtrace_stop(g_dtp); dtrace_close(g_dtp); return(0); }