#!/usr/sbin/dtrace -s /* * shellsnoop.d - A program to print read/write details from shells, * such as keystrokes and command outputs. * Written in DTrace (Solaris 10 build 51). * * NOTE: This version is deprecated. See "shellsnoop", * http://www.brendangregg.com/dtrace.html * * 05-May-2004, ver 0.71. * * * USAGE: ./shellsnoop.d * * This program is somewhat experimental. * * * FIELDS: * PID process ID * PPID parent process ID * CMD command name * DIR direction (R read, W write) * TEXT text contained in the read/write * * Standard Disclaimer: This is freeware, use at your own risk. * * 28-Mar-2004 Brendan Gregg Created this. * */ #pragma D option quiet #pragma D option strsize=2048 inline int DEBUG = 0; /* extra debug output */ dtrace:::BEGIN { /* print header */ printf("%5s %5s %8s %3s %s\n","PID","PPID","CMD","DIR","TEXT"); } syscall::exec:entry, syscall::exece:entry /execname == "sh" || execname == "ksh" || execname == "csh" || execname == "tcsh" || execname == "zsh" || execname == "bash"/ { /* * Remember that this PID was invoked by a shell */ child[pid] = 1; /* debug */ this->parent = (char *)curthread->t_procp->p_parent->p_user.u_comm; DEBUG == 1 ? printf("PID %d CMD %s started. (%s)\n", pid,execname, stringof(this->parent)) : 1; } syscall::write:entry, syscall::read:entry /execname == "sh" || execname == "ksh" || execname == "csh" || execname == "tcsh" || execname == "zsh" || execname == "bash"/ { self->buf = arg1; self->len = arg2; } syscall::write:return, syscall::read:return /child[pid] == 0 && self->buf != NULL/ { /* * Print shell keystrokes */ this->text = (char *)copyin(self->buf, self->len); printf("%5d %5d %8s %3s %s\n", pid, curpsinfo->pr_ppid, execname, probefunc == "read" ? "R" : "W", stringof(this->text)); self->buf = NULL; self->len = 0; } syscall::write:entry, syscall::read:entry /child[pid] == 1 && (arg0 == 1 || arg0 == 2)/ { self->buf = arg1; self->len = arg2; } syscall::write:return, syscall::read:return /self->buf != NULL/ { /* * Print command output */ this->text = (char *)copyin(self->buf, self->len); printf("%5d %5d %8s %3s %s", pid, curpsinfo->pr_ppid, execname, probefunc == "read" ? "R" : "W", stringof(this->text)); /* here we check if a newline is needed */ this->length = strlen(this->text); printf("%s", this->text[this->length - 1] == '\n' ? "" : "\n"); self->buf = NULL; self->len = 0; } fbt:genunix:exit:entry { /* * Forget this PID */ child[pid] = 0; /* debug */ this->parent = (char *)curthread->t_procp->p_parent->p_user.u_comm; DEBUG == 1 ? printf("PID %d CMD %s exited. (%s)\n", pid,execname, stringof(this->parent)) : 1; }