/*
** 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 <wnoise@ugcs.caltech.edu> 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 <grooms@uky.edu> for finding this problem and
* for the resources to resolve it!
*/
#define _PSTAT64
#define NO_MEXTERN
#include "conf.h"
#undef NO_MEXTERN
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
/*
** 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 <sys/rtprio.h>
#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 <regex.h>
REAL_REGEX_FUNCS
/*
* Now, set up everything we need to write a GetProc() routine.
*/
#include <sys/pstat.h>
#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);
}
syntax highlighted by Code2HTML, v. 0.9.1