/* ** Copyright (c) 1986, 1994, 1996, 2000, 2002 ** Jeff Forys (jeffware@marjum.com). All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that: (1) Redistributions of ** source code must retain the above copyright notice, this list of ** conditions and the following disclaimer, (2) Redistributions in ** binary form must reproduce the above copyright notice, this list ** of conditions and the following disclaimer in the documentation ** and/or other materials provided with the distribution, (3) All ** advertising materials mentioning features or use of this software ** must display the following acknowledgment: ``This product includes ** software developed by Jeff Forys (jeffware@marjum.com).'', (4) ** The name of the author may not be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** HP-UX 10 support by Aaron Denney and Jeff Forys. */ #ifndef lint static char rcsid[] = "$Id: hpux-10.c,v 1.11 2005/04/06 23:49:34 forys Exp $"; #endif #define _XPG4_EXTENDED /* 3/22/05 * * The 32-bit 'pst_status' struct returned by pstat_getproc(2) is not * always large enough for 64-bit HP-UX values and the system call fails * with errno set to EOVERFLOW. The solution is to define _PSTAT64 to * use the 64-bit sized structure. * * This change was tested on IA-64 superdome (11.23), PA-RISC 2.0 (11.11) * and (32-bit) PA-RISC 1.1 (11.11). * * Thanks to Jerry Grooms for finding this problem and * for the resources to resolve it! */ #define _PSTAT64 #define NO_MEXTERN #include "conf.h" #undef NO_MEXTERN #include #include #include #include /* ** Note: HP-UX finally supports setpriority(2); snice has been changed to ** use this, rather than rtprio(2). If you need the old behavior, you can ** #define OLD_RTPRIO. */ #ifdef OLD_RTPRIO #include #endif /* * 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 */ "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ "PIPE", "ALRM", "TERM", "USR1", "USR2", "CHLD", /* 13 - 18 */ "PWR", "VTALRM", "PROF", "IO", "WINCH", "STOP", /* 19 - 24 */ "TSTP", "CONT", "TTIN", "TTOU", "URG", "LOST", /* 25 - 30 */ "31", "32", "CPU", "FSZ", "CANCEL", "GFAULT", /* 31 - 36 */ "RTMIN", "RTMIN+1", "RTMIN+2", "RTMIN+3", "RTMAX-3", /* 37 - 41 */ "RTMAX-2", "RTMAX-1", "RTMAX" /* 42 - 44 */ }; int NSig = NSIG-1; #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 */ static const char *nomemmsg = "%s: %s: out of memory (wanted %u bytes)\n"; /* * 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 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) #ifdef OLD_RTPRIO (void) rtprio(MyPid, RTPRIO_MIN); #else (void) setpriority(PRIO_PROCESS, MyPid, PRIO_MIN); #endif /* * 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); /* * 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); } /* * Set up minimum and maximum process priorities. * Initialize SigPri to either default signal (`skill') or * default priority (`snice'). */ #ifdef OLD_RTPRIO PrioMin = RTPRIO_MIN; PrioMax = RTPRIO_MAX; SigPri = Skill? SIGTERM: RTPRIO_RTOFF; #else PrioMin = PRIO_MIN; PrioMax = PRIO_MAX; SigPri = Skill? SIGTERM: 4; #endif } /* * 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 #ifdef OLD_RTPRIO return(rtprio((int)pid, SigPri)); #else return(setpriority(PRIO_PROCESS, (int)pid, SigPri)); #endif } /* OS supports POSIX-style regular expressions */ #include REAL_REGEX_FUNCS /* * Now, set up everything we need to write a GetProc() routine. */ #include #define PROCSLOP 256 /* additional process slots to alloc */ /* * GetProc() * * Fill in and return a `struct ProcInfo' with information about the * next process. If no processes are left, return NULL. */ struct ProcInfo * GetProc() { extern char *SysErr(); static struct ProcInfo procinfo; static struct pst_status *proclist = NULL, *aproc, *e_proclist; struct pst_dynamic pdyn; if (proclist == NULL) { register int pret; int nprocs; if ((pret = pstat_getdynamic(&pdyn, sizeof(pdyn), 1, 0)) < 0) { fprintf(stderr, "%s: pstat_getdynamic: %s\n", ProgName, SysErr()); exit(2); } nprocs = pdyn.psd_activeprocs + PROCSLOP; if ((proclist = (struct pst_status *) calloc(nprocs, sizeof(*aproc))) == NULL) { fprintf(stderr, "%s: calloc: can't alloc %d proc tables\n", ProgName, nprocs); exit(2); } if ((pret=pstat_getproc(proclist,sizeof(*aproc),nprocs,0)) < 0){ #ifndef _PSTAT64 extern int errno; int saverrno = errno; #endif fprintf(stderr, "%s: pstat_getproc: %s\n", ProgName, SysErr()); #ifndef _PSTAT64 if (saverrno == 72) /* EOVERFLOW tweak */ fprintf(stderr, "%s: recompile with \"-D_PSTAT64\"\n", ProgName); #endif exit(2); } aproc = proclist; e_proclist = proclist + pret; } if (aproc == e_proclist) { free(proclist); proclist = NULL; return NULL; } procinfo.pi_cmd = aproc->pst_ucomm; procinfo.pi_pid = aproc->pst_pid; procinfo.pi_uid = aproc->pst_uid; procinfo.pi_flags = 0; /* * If parent proc is pid 0, ask user for confirmation. */ if (aproc->pst_ppid == 0) procinfo.pi_flags |= PI_ASKUSR; if (aproc->pst_term.psd_major != -1) { procinfo.pi_flags |= PI_CTLTTY; procinfo.pi_tty = makedev(aproc->pst_term.psd_major, aproc->pst_term.psd_minor); } else { procinfo.pi_tty = (tty_T)-2; } if (aproc->pst_stat == PS_ZOMBIE) procinfo.pi_flags |= PI_ZOMBIE; /* * N.B. PS_OTHER pst_stat can be either forking or exiting. * Since there is apparently no way to differentiate, we * ignore ths flag rather than risk a misclassification. */ aproc++; return(&procinfo); }