Skill Version 3.6, Patch #3 [affects Ultrix 4.x, Linux, Mach 3] - [Ultrix 4.x] Fixes compilation warning in machdep module. - Support for Linux 1.0 through 1-2. - Misc fixes for Mach 3 support. Thanks to Andreas Zins for the Ultrix fix, and Chuck L Blake for Linux support. To apply this patch, "cd" to your skill source directory and run: patch -p0 --- 1,6 ---- #!/bin/sh # ! # $Header: Config,v 1.16 1994/11/12 20:33:45 forys Exp $ # # Configure - edit skill Makefile filling in OSTYPE, COPTS, and LIBS. # Contributed by: Ric Anderson *************** *** 57,62 **** --- 57,66 ---- hpux*) OSTYPE=hpux-70 COPTS=-DNO_UID_T + ;; + + linux*) + OSTYPE=linux-1 COPTS=-O3 LIBS="-s -N" ;; mach2) *** 1.13 1994/08/21 22:19:48 --- GuessOS 1994/11/13 20:22:42 *************** *** 1,6 **** #!/bin/sh # ! # $Header: GuessOS,v 1.13 1994/08/21 22:19:48 forys Exp $ # # GuessOS - guess the OS type for skill. # Contributed by: Ric Anderson --- 1,6 ---- #!/bin/sh # ! # $Header: GuessOS,v 1.14 1994/11/13 19:59:23 forys Exp $ # # GuessOS - guess the OS type for skill. # Contributed by: Ric Anderson *************** *** 84,91 **** OS=unknown ;; esac ! elif [ -f /sbin/uname ]; then ! case "`exec 2>/dev/null; /bin/uname -r`" in 3.*) OS=svr3 ;; --- 84,91 ---- OS=unknown ;; esac ! elif [ -f /sbin/uname -o -f /bin/uname ]; then ! case "`exec 2>/dev/null; uname -r`" in 3.*) OS=svr3 ;; *************** *** 93,99 **** OS=svr4 ;; *) ! OS=svrx ;; esac elif [ -d /etc/aix -o -d /etc/aixdwm ]; then --- 93,106 ---- OS=svr4 ;; *) ! case "`exec 2>/dev/null; uname`" in ! Linux) ! OS=linux ! ;; ! *) ! OS=svrx ! ;; ! esac ;; esac elif [ -d /etc/aix -o -d /etc/aixdwm ]; then *** 1.10 1994/08/23 02:38:57 --- skill.1 1994/11/13 20:23:00 *************** *** 1,5 **** .\" ! .\" $Header: skill.1,v 1.10 1994/08/23 02:38:57 forys Exp $ .\" .\" skill - send signals to processes by tty, user name, command or proc id. .\" skill - change process priorities by tty, user name, command or proc id. --- 1,5 ---- .\" ! .\" $Header: skill.1,v 1.11 1994/11/13 20:17:46 forys Exp $ .\" .\" skill - send signals to processes by tty, user name, command or proc id. .\" skill - change process priorities by tty, user name, command or proc id. *************** *** 9,15 **** .\" .\" Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us) .\" ! .TH SKILL 1 "August 22, 1994" "" "Local UNIX Programmer's Manual" .UC 4 .SH NAME skill, snice \- signal or reprioritize specified processes --- 9,15 ---- .\" .\" Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us) .\" ! .TH SKILL 1 "November 13, 1994" "" "Local UNIX Programmer's Manual" .UC 4 .SH NAME skill, snice \- signal or reprioritize specified processes *************** *** 152,157 **** --- 152,159 ---- David Sharnoff Greg Earle Christos Zoulas .br Gorodecki Tom Mike Hibler Ric Anderson + .br + Chuck L Blake Lee Duncan Allan E Johannesen .SH "BUGS" Things change while these programs execute, occasionally processes will be missed (the `-w' flag displays these). *** 1.26 1994/08/21 22:29:21 --- README 1994/11/13 20:23:22 *************** *** 1,4 **** ! $Header: README,v 1.26 1994/08/21 22:29:21 forys Exp $ `skill' is a program which sends signals to processes given any combination of user names, ttys, commands, and pids. `snice' is --- 1,4 ---- ! $Header: README,v 1.27 1994/11/13 20:18:00 forys Exp $ `skill' is a program which sends signals to processes given any combination of user names, ttys, commands, and pids. `snice' is *************** *** 22,27 **** --- 22,28 ---- HP-UX 6.5, 7.0, 8.0, 9.0-1 IBM AIX 3.1-2 IBM AOS 4.3 + Linux 1.0-2 (tty-based selection will not work under 1.0) MIPS UMIPS 2.1 NeXT OS 1.0, 2.1 Pyramid OSx 4.0 *************** *** 184,186 **** --- 185,196 ---- Jay Lepreau - Gave me 4 days to polish up Version 3. + + Lee Duncan + - Fixes for signal display and Solaris. + + Allan E Johannesen + - Fixes for OSF/1. + + Chuck L. Blake + - Linux support. *** 1.22 1994/08/21 22:18:21 --- Makefile 1994/11/13 20:23:39 *************** *** 1,5 **** # ! # $Header: Makefile,v 1.22 1994/08/21 22:18:21 forys Exp $ # # First, find the CONFIGURE comments and set up the "BIN*" and "MAN*" # defines according to local customs. Next, if your operating system --- 1,5 ---- # ! # $Header: Makefile,v 1.23 1994/11/13 20:18:19 forys Exp $ # # First, find the CONFIGURE comments and set up the "BIN*" and "MAN*" # defines according to local customs. Next, if your operating system *************** *** 27,32 **** --- 27,33 ---- # HP HP-UX 8.0-9.1 hpux-90 # IBM AIX 3.2 aix-3 # IBM AOS 4.3 aos-43 + # Linux Linux 1.0-2 linux-1 COPTS=-O3 LIBS=-s -N # MIPS UMIPS 2.1 umips-21 LIBS= -lmld # NeXT NeXT OS 1.0 mach-26 # NeXT NeXT OS 2.1 next-2 *** 1.16 1994/08/23 02:43:54 --- main.c 1994/11/13 20:23:52 *************** *** 1,18 **** #ifndef lint ! static char rcsid[] = "$Header: main.c,v 1.16 1994/08/23 02:43:54 forys Exp $"; /* * SCCS version release number is manually updated (for what(1), etc). ! * If you use SCCS, please use last extension for version (e.g. "3.6.3.1"). */ static char sccsid[] = ! "@(#)skill 3.6.3.0 (jeff@forys.cranbury.nj.us) 8/22/94"; #endif /* ** skill - send signals to processes by tty, user name, command or proc id. ** snice - change process priorities by tty, user name, command or proc id. ** ! ** Version 3.6.3 ** ** This program may be freely redistributed for noncommercial purposes. ** This entire comment MUST remain intact. --- 1,18 ---- #ifndef lint ! static char rcsid[] = "$Header: main.c,v 1.17 1994/11/13 20:20:40 forys Exp $"; /* * SCCS version release number is manually updated (for what(1), etc). ! * If you use SCCS, please use last extension for version (e.g. "3.6.4.1"). */ static char sccsid[] = ! "@(#)skill 3.6.4.0 (jeff@forys.cranbury.nj.us) 11/13/94"; #endif /* ** skill - send signals to processes by tty, user name, command or proc id. ** snice - change process priorities by tty, user name, command or proc id. ** ! ** Version 3.6.4 ** ** This program may be freely redistributed for noncommercial purposes. ** This entire comment MUST remain intact. *************** *** 221,227 **** static uid_T uidcache = ROOTUID; /* user id */ struct passwd *pp; ! if (uid == ROOTUID) /* be consistant w/ROOTUID */ return(ROOTUSR); if (uid == uidcache) /* lucky break: same person */ --- 221,227 ---- static uid_T uidcache = ROOTUID; /* user id */ struct passwd *pp; ! if (uid == ROOTUID) /* be consistent w/ROOTUID */ return(ROOTUSR); if (uid == uidcache) /* lucky break: same person */ *** 1.6 1994/06/26 04:16:59 --- machdep/ultrix-4.c 1994/11/12 20:23:16 *************** *** 1,5 **** #ifndef lint ! static char rcsid[] = "$Header: ultrix-4.c,v 1.6 1994/06/26 04:16:59 forys Exp $"; #endif /* --- 1,5 ---- #ifndef lint ! static char rcsid[] = "$Header: ultrix-4.c,v 1.7 1994/11/12 19:57:21 forys Exp $"; #endif /* *************** *** 357,363 **** * Read in word at `loc' from kernel virtual memory. * If an error occurs, call exit(2) with EX_SERR. */ ! static int GetWord(loc) off_t loc; { --- 357,363 ---- * Read in word at `loc' from kernel virtual memory. * If an error occurs, call exit(2) with EX_SERR. */ ! int GetWord(loc) off_t loc; { *** /dev/null Sun Nov 13 15:11:48 1994 --- machdep/linux-1.c Sat Nov 12 15:23:06 1994 *************** *** 0 **** --- 1,215 ---- + #ifndef lint + static char rcsid[] = "$Header: linux-1.c,v 1.1 1994/11/12 20:21:04 forys Exp $"; + #endif + + /* + ** This program may be freely redistributed for noncommercial purposes. + ** This entire comment MUST remain intact. + ** + ** Linux support by Chuck L. Blake (chuckb@Alice.Wonderland.Caltech.EDU) + ** + ** Copyright 1994 by Jeff Forys (jeff@forys.cranbury.nj.us) + */ + + #define NO_MEXTERN + #include "conf.h" + #undef NO_MEXTERN + + #include + #include /* for [get|set]priority() */ + #include /* for MINOR() macro */ + + #include + #include + #include + #include + #include + + extern int MissedProcCnt; + + /* + * Define SigNames, NSig, and TtyDevDir here; they are used by other + * routines and must be global. Everyone seems to have their own + * idea as to what NSIG should be. Here, `NSig' is the number of + * signals available, not counting zero. + */ + + char *SigMap[] = { + "0", + "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", /* 1 - 6 */ + "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", /* 7 - 12 */ + "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", /* 13 - 18 */ + "STOP", "TSTP", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ + "XFSZ", "VTALRM", "PROF", "WINCH", "LOST", "PWR", /* 25 - 30 */ + "UNUSED" + }; + + int NSig = 31; + + #define SETCMD(dst,src,maxlen) { \ + extern char *strrchr(); \ + if (maxlen > 0) src[maxlen] = '\0'; \ + dst = (dst = strrchr(src, '/')) ? ++dst: src; \ + } + + static char *TtyDevDir = "/dev"; + + int Skill; /* set 1 if running `skill', 0 if `snice' */ + int PrioMin, PrioMax; /* min and max process priorities */ + int SigPri; /* signal to send or priority to set */ + pid_T MyPid; /* pid of this process */ + uid_T MyUid; /* uid of this process */ + char *ProgName; /* program name */ + + /* + * This is the machine-dependent initialization routine. + * + * - The following global variables must be initialized: + * MyPid, MyUid, ProgName, Skill, PrioMin, PrioMax, SigPri + * - The working directory will be changed to that which contains the + * tty devices (`TtyDevDir'); this makes argument parsing go faster. + * - If possible, this routine should raise the priority of this process. + */ + + void skill_getpri(int *low, int *high); + + void + MdepInit(pname) + char *pname; + { + extern char *rindex(), *SysErr(); + + MyPid = (pid_T) getpid(); + MyUid = (uid_T) getuid(); + SETCMD(ProgName, pname, 0) + + /* + * If we are running as root, raise our priority to better + * catch runaway processes. + */ + if (MyUid == ROOTUID) + (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN); + + /* + * Determine what we are doing to processes we find. We will + * either send them a signal (skill), or renice them (snice). + */ + Skill = (strstr(ProgName, "snice") == NULL); + + /* + * Set up minimum and maximum process priorities. + * Initialize SigPri to either default signal (`skill') or + * default priority (`snice'). + */ + PrioMin = PRIO_MIN; + PrioMax = PRIO_MAX; + SigPri = Skill ? SIGTERM : 4; + + /* + * chdir to `TtyDevDir' to speed up tty argument parsing. + */ + if (chdir(TtyDevDir) < 0) { + fprintf(stderr, "%s: chdir(%s): %s\n", ProgName, TtyDevDir, + SysErr()); + exit(EX_SERR); + } + } + + /* + * Carry out an action on a particular process. If this is `skill', + * then send the process a signal, otherwise this is `snice' so change + * it's priority. + * + * If 0 is returned, the operation was successful, otherwise -1 is + * returned and `errno' set. + */ + int + MdepAction(pid) + pid_T pid; + { + if (Skill) + return(kill((int)pid, SigPri)); + else + return(setpriority(PRIO_PROCESS, (int)pid, SigPri)); + } + + /* + * Now, set up everything we need to write a GetProc() routine. + */ + + #include + char *SysErr(); + + static char *ProcDir = "/proc"; /* proc directory */ + static char *ProcFil = "/proc/%s/stat"; /* name of only needed file */ + + #define MXBUF 1024 + static char buf[MXBUF]; /* primary storage for file io */ + /* + * GetProc() + * + * Fill in and return a `struct ProcInfo' with information about the + * next process. If no processes are left, return NULL. + */ + struct ProcInfo * + GetProc() + { + static struct ProcInfo procinfo; + static DIR *dirfp = NULL; + struct dirent *dp; + char flnm[FILENAME_MAX]; + int fd; + + int n; /* first for length of buf[], then as a loop counter */ + char* tmp; /* pointer into buf[] */ + struct stat sb; /* stat() buffer, used to get UID */ + + /* + * If this is our first time here, open the proc directory,... + */ + if (dirfp == NULL && (dirfp=opendir(ProcDir)) == NULL) { + fprintf(stderr, "%s: %s: %s\n", ProgName, ProcDir, SysErr()); + exit(EX_SERR); + } + + while ((dp = readdir(dirfp)) != NULL) { + if (dp->d_name[0] < '0' || dp->d_name[0] > '9') + continue; + (void) sprintf(flnm, ProcFil, dp->d_name); + if ((fd = open(flnm, O_RDONLY)) < 0) { + MissedProcCnt++; + continue; /* ignore procs we can't read */ + } + + fstat(fd, &sb); /* uid = owner-id of /proc/PID/stat */ + procinfo.pi_uid = sb.st_uid; + + if ((n = read(fd, buf, MXBUF-1)) == -1) + continue; + buf[n] = '\0'; /* terminate the string */ + (void) close(fd); + + /* Split buf into "PID (cmd)" and "state ppid pgrp sess tty ... 28 more" */ + /* This contortion is necessary because cmd could have any no. of embedded */ + /* whitespace characters, while everything after (cmd) is well-defined. */ + + tmp = buf + n; /* start tmp at end of buf */ + for(n = 33; n; n--) /* move tmp to spc following (cmd) */ + while (*--tmp != ' ') + ; + tmp[-1]='\0'; /* ')' --> '\0' */ + + procinfo.pi_pid = atoi(buf); /* atoi("123 (cmd)") works. :-) */ + procinfo.pi_cmd = strchr(buf, '(') + 1; /* 1st char past '(' */ + for(n = 4; n; n--) /* move tmp to tty field */ + while (*++tmp != ' ') + ; + procinfo.pi_tty = atoi(tmp); + + return(&procinfo); + } + + (void) closedir(dirfp); + dirfp = NULL; + return((struct ProcInfo *)NULL); + } *** 1.1 1994/08/21 22:13:45 --- machdep/mach-3.c 1994/10/06 21:15:53 *************** *** 1,5 **** #ifndef lint ! static char rcsid[] = "$Header: mach-3.c,v 1.1 1994/08/21 22:13:45 forys Exp $"; #endif /* --- 1,5 ---- #ifndef lint ! static char rcsid[] = "$Header: mach-3.c,v 1.2 1994/10/06 21:15:16 forys Exp $"; #endif /* *************** *** 127,133 **** #include ! #define NPROCS 512 /* size of `procs' struct (if too small, use calloc) */ /* * GetProc() --- 127,134 ---- #include ! #define PROCSLOP 32 /* as an aid in catching run-away processes */ ! #define NPROCS (480+PROCSLOP) /* size of `procs' struct (or use calloc()) */ /* * GetProc() *************** *** 140,151 **** { extern int errno; extern char *SysErr(); ! static struct tbl_procinfo procs[NPROCS], *procsp, *procsidxp; static struct ProcInfo procinfo; register struct tbl_procinfo *aproc; static int procindx = 0; static int thisproc = 0; static int maxnproc = 0; /* * If this is the first time through, determine how many processes --- 141,153 ---- { extern int errno; extern char *SysErr(); ! static struct tbl_procinfo procs[NPROCS], *procsp; static struct ProcInfo procinfo; register struct tbl_procinfo *aproc; static int procindx = 0; static int thisproc = 0; static int maxnproc = 0; + static int readonce = 1; /* * If this is the first time through, determine how many processes *************** *** 154,161 **** * fails, we'll have to resort to NPROCS at-a-time. */ if (maxnproc == 0) { ! maxnproc = table(TBL_PROCINFO, 0, (char *)NULL, INT_MAX, 0); ! if (maxnproc > NPROCS) { /* * We have more then NPROCS processes running * on this machine. Ideally, one should bump --- 156,163 ---- * fails, we'll have to resort to NPROCS at-a-time. */ if (maxnproc == 0) { ! if ((maxnproc = table(TBL_PROCINFO, 0, (char *)NULL, INT_MAX, ! 0) + PROCSLOP) > NPROCS) { /* * We have more then NPROCS processes running * on this machine. Ideally, one should bump *************** *** 169,197 **** */ procsp = (struct tbl_procinfo *) calloc(maxnproc, sizeof(struct tbl_procinfo)); ! if (procsp == NULL) maxnproc = NPROCS; } else maxnproc = NPROCS; } /* ! * Read in `maxnproc' structures at-a-time. Decrement `nproc' ! * by the number of proc structures we have read; when it reaches ! * zero, we are finished (return NULL). */ do { if (thisproc == 0) { if (maxnproc <= NPROCS) procsp = procs; thisproc = table(TBL_PROCINFO, procindx, (char *)procsp, maxnproc, sizeof(struct tbl_procinfo)); /* * For now, we must be setuid root up to this point. * Relinquish root here; this will screw us if the ! * calloc() fails, but we have no choice. */ (void) seteuid(getuid()); --- 171,217 ---- */ procsp = (struct tbl_procinfo *) calloc(maxnproc, sizeof(struct tbl_procinfo)); ! if (procsp == NULL) { maxnproc = NPROCS; + readonce = 0; + } } else maxnproc = NPROCS; } /* ! * This is a little convoluted due to the table() system call. ! * We have the total number of processes we can read at-a-time ! * in `maxnproc'. We do not care about the actual count of ! * existing processes because: ! * 1) The count may change by time we actually read them, ! * 2) We may be unable to read them all at once, anyway. ! * ! * So, if we *know* we have enough memory ("readonce" is set), ! * just do the read once and hope we get everything; we have ! * provided for some additional processes (via PROCSLOP). ! * Alternately, continually read in blocks of processes until ! * table() returns EINVAL (since we can never be sure of the ! * actual number of active processes in this situation). ! * ! * At any rate, return NULL when all processes have been read. */ do { if (thisproc == 0) { if (maxnproc <= NPROCS) procsp = procs; + if (readonce && ++readonce == 3) + return((struct ProcInfo *)NULL); + thisproc = table(TBL_PROCINFO, procindx, (char *)procsp, maxnproc, sizeof(struct tbl_procinfo)); /* * For now, we must be setuid root up to this point. * Relinquish root here; this will screw us if the ! * calloc() fails and we are not the superuser, but ! * we have no choice. */ (void) seteuid(getuid());