/* * spy v1.0 - by Brendan Kehoe (brendan@cs.widener.edu) * * Show a quick screen-based representation of running processes on the * system. This was fashioned after a similar program written in Macro * assembly for VMS, thus the support for Sunlink DNI. Hitting any key * makes it stop. If you're not running DNI, it'll display the hostname. * It'll give the username, pid, base & current priority, and command * with argument list for each interactive process (by default). * Link it with the kvm, curses, and termlib libraries. It should be * installed set-gid kmem, and only works on BSD systems. Ports to * System V are welcome. (Or for compatability with other systems.) * Why use it? It's handy when you want a quick display of the system, * but don't want the overhead of top and more info than that given by w. * 'Tis but a hack a couple of years old. :-) No man page, doesn't use * getopt(), a bunch of other things could be improved. No energy. :-) * * Options are: * -n .. display without expanding usernames to full names * -a .. display non-interactive, non-root process in add'n to the * normal interactive ones * -A .. display every process (this goes a few screens per cycle) */ #include #include #include #include #include #include #include #include #include #include #include #include /* For DNI v6.0 etc. */ /*#define OFFSET 26L*/ /* For DNI v7.0. */ #define OFFSET 42L /* Where the info is stored. */ #define DNIFILE "/etc/sunlink/dni/permsnt.dat" #define SWID (stdscr->_maxx) #define SLEN (stdscr->_maxy) #define DATEPOS (SWID-25) #define NONAME 1 #define ALLUSER 2 #define ALL 4 #define SLEEP 8 int kb; main (argc, argv) int argc; char **argv; { int last = -1, decnet = 0; char **arguments, *arglin; int flags, i, pa, curproc, exlen, action = 0; /* ALLUSER; */ char *ps, *buf, *minus, name[100]; char *mstr[5] = {"AWAKE", "ACTIVE", "ALL", "DIRECTORY", "OPEN_FILES"}, *mode; struct proc *proc; struct user *user; struct passwd *p; time_t t; FILE *dnifile; static kvm_t *kd; void clean (), exusage (); signal (SIGINT, clean); mode = mstr[0]; while (--argc) if (**(argv + argc) == '-') { i = 0; while (*(*(argv + argc) + (++i))) { switch (*(*(argv + argc) + i)) { case 'n': action |= NONAME; break; case 'a': action |= ALL; mode = mstr[2]; break; case 'A': action |= ALLUSER; mode = mstr[1]; break; default: exusage (*argv); } } } if (((dnifile = fopen (DNIFILE, "r")) != (FILE *) NULL)) { fseek (dnifile, OFFSET, 0); fgets (name, 7, dnifile); fclose (dnifile); decnet = 1; } else gethostname (name, 100); initscr (); clear (); cbreak (); noecho (); if (!(minus = malloc (SWID + 1))) { perror ("malloc minus"); clean (); } ps = minus; for (i = 0; i < SWID - 1; i++) *ps++ = '-'; *ps = '\0'; mvaddstr (0, 0, minus); mvprintw (1, 0, " SUN/SPY %s %s%s\tMode: %s", decnet ? "Node:" : "Host:", name, decnet ? "::" : "", mode); mvaddstr (2, 0, minus); mvaddstr (3, 0, "Username"); if (action & NONAME) { pa = 10; exlen = SWID - 27; } else { mvaddstr (3, 10, "Real Name"); pa = 32; exlen = SWID - 51; } mvaddstr (3, pa, "PID BP CP Exec"); mvaddstr (3, DATEPOS, "(Press any key to quit)"); mvaddstr (4, 0, minus); time (&t); mvaddstr (1, DATEPOS, ctime (&t)); move (1, 0); refresh (); if ((kb = open ("/dev/tty", O_RDONLY)) == -1) { perror ("opening tty"); clean (); } if ((flags = fcntl (kb, F_GETFL, 0)) == -1) { perror ("fcntl get"); clean (); } if (fcntl (kb, F_SETFL, flags | O_NDELAY) == -1) { perror ("fcntl set"); clean (); } if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY, "rpoll.rpc")) == NULL) { fprintf (stderr, "%s: couldn't open the kernel\n", argv[0]); clean (); } if (!(arglin = malloc (2000))) { perror ("malloc"); clean (); } if (!(buf = malloc (100))) { perror ("malloc 2"); clean (); } while (1) { if (read (kb, buf, 1) > 0) clean (); kvm_setproc (kd); curproc = 0; last = -1; kvm_nextproc (kd); while ((proc = kvm_nextproc (kd))) { if (((proc->p_stat != SZOMB) && (proc->p_uid != 0)) || (action & ALL)) { if (!(user = kvm_getu (kd, proc))) continue; if (kvm_getcmd (kd, proc, user, &arguments, NULL) == 0) { if ((**arguments == '-') && (!((action & ALLUSER) || (action & ALL)))) continue; i = 0; *arglin = '\0'; while (arguments[i]) { strcat (arglin, arguments[i]); strcat (arglin, " "); i++; } /* argument and env using code here */ free (arguments); if (strlen (arglin) > exlen) *(arglin + exlen + 1) = '\0'; } if (curproc == (SLEN - 6)) { time (&t); mvaddstr (1, DATEPOS, ctime (&t)); mvaddstr (4 + curproc, 0, minus); move (1, 0); refresh (); sleep (2); /* see if they hit a key while we slept */ if (read (kb, buf, 1) > 0) clean (); curproc = 0; last = -1; } p = getpwuid (proc->p_uid); if (action & NONAME) { mvprintw (5 + (curproc++), 0, "%*s %-06d %3d %3d %s", -8, p->pw_name, proc->p_pid, proc->p_usrpri, proc->p_pri, arglin); } else { /* no use to repeat the same name over & over again */ if (last == p->pw_uid) p->pw_gecos = "\" \" "; else last = p->pw_uid; mvprintw (5 + (curproc++), 0, "%*s %*s %-06d %3d %3d %s", -8, p->pw_name, -20, p->pw_gecos, proc->p_pid, proc->p_usrpri, proc->p_pri, arglin); } clrtoeol (); } /* end root own test */ } mvaddstr (5 + curproc, 0, minus); clrtobot (); time (&t); mvaddstr (1, DATEPOS, ctime (&t)); move (1, 0); refresh (); sleep (1); } } void clean () { int flags; signal (SIGINT, SIG_IGN); if ((flags = fcntl (kb, F_GETFL, 0)) == -1) { perror ("fcntl get"); exit (1); } if (fcntl (kb, F_SETFL, flags & ~O_NDELAY) == -1) { perror ("fcntl set"); exit (1); } clear (); cbreak (); echo (); refresh (); endwin (); exit (0); } void exusage (cmd) char *cmd; { fprintf (stderr, "usage: %s [-Aan]\n", cmd); exit (0); } in mva M mva M mva M mva M mva M mva M mva M mva M mva M mva