/* AND auto nice daemon - renice programs according to their CPU usage. Copyright (C) 1999-2001 Patrick Schemitz http://and.sourceforge.net/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __FreeBSD__ #include #endif #include "and.h" /* AND -- auto-nice daemon/OpenBSD version. OpenBSD-specific AND version. Makes excessive use of the OpenBSD kernel memory interface, kvm, but also works for FreeBSD. 2000, 2002 Patrick Schemitz, http://and.sourceforge.net/ */ static kvm_t *openbsd_kvm = NULL; static struct kinfo_proc *openbsd_pt = NULL; static int openbsd_nproc = 0; static int openbsd_next = 0; static long openbsd_hz = -1; static struct and_procent openbsd_proc; static int openbsd_init () { struct nlist nlst [] = { { "_hz" }, { 0 } }; kvm_nlist(openbsd_kvm,nlst); if (nlst[0].n_type == 0) { and_printf(0,"KVM: nlist failed. Aborting.\n"); abort(); } if (kvm_read(openbsd_kvm,nlst[0].n_value,(char*)(&openbsd_hz), sizeof(openbsd_hz)) != sizeof(openbsd_hz)) { and_printf(0,"KVM: hz symbol empty. Aborting.\n"); abort(); } return 1; } struct and_procent *openbsd_getnext () { if (!openbsd_pt) { and_printf(0,"KVM: no process table (late detection). Aborting.\n"); abort(); } if (openbsd_next >= openbsd_nproc) return NULL; #if defined(__FreeBSD__) && __FreeBSD_version >= 500014 /* Skip kernel threads */ while((openbsd_pt[openbsd_next].ki_flag & P_KTHREAD) && openbsd_next < openbsd_nproc) openbsd_next++; if (openbsd_next >= openbsd_nproc) return NULL; strncpy(openbsd_proc.command,openbsd_pt[openbsd_next].ki_comm,1023); openbsd_proc.command[1023] = 0; openbsd_proc.pid = openbsd_pt[openbsd_next].ki_pid; openbsd_proc.nice = openbsd_pt[openbsd_next].ki_nice-20; openbsd_proc.uid = openbsd_pt[openbsd_next].ki_ruid; openbsd_proc.gid = openbsd_pt[openbsd_next].ki_rgid; openbsd_proc.utime = (openbsd_pt[openbsd_next].ki_runtime+500000)/1000000; #else strncpy(openbsd_proc.command,openbsd_pt[openbsd_next].kp_proc.p_comm,1023); openbsd_proc.command[1023] = 0; openbsd_proc.pid = openbsd_pt[openbsd_next].kp_proc.p_pid; openbsd_proc.nice = openbsd_pt[openbsd_next].kp_proc.p_nice-20; openbsd_proc.uid = openbsd_pt[openbsd_next].kp_eproc.e_pcred.p_ruid; openbsd_proc.gid = openbsd_pt[openbsd_next].kp_eproc.e_pcred.p_rgid; /* Adapted from top(1) port, as found in the misc@openbsd.org archive */ openbsd_proc.utime = (openbsd_pt[openbsd_next].kp_proc.p_uticks + openbsd_pt[openbsd_next].kp_proc.p_sticks + openbsd_pt[openbsd_next].kp_proc.p_iticks) / openbsd_hz; #endif /* printf("%-20s %5i %3i %i\n",openbsd_proc.command,openbsd_proc.pid, openbsd_proc.nice,openbsd_proc.utime); */ and_printf(3, "OpenBSD: process %s pid: %d ppid: %d\n", openbsd_proc.command, openbsd_proc.pid, openbsd_proc.ppid); openbsd_next++; return &openbsd_proc; } struct and_procent *openbsd_getfirst () { char errmsg [_POSIX2_LINE_MAX]; if (!openbsd_kvm) { openbsd_kvm = kvm_openfiles(NULL,NULL,NULL,O_RDONLY,errmsg); if (!openbsd_kvm) { and_printf(0,"KVM: cannot open (\"%s\"). Aborting.\n",errmsg); abort(); } openbsd_init(); } openbsd_pt = kvm_getprocs(openbsd_kvm,KERN_PROC_ALL,0,&openbsd_nproc); if (!openbsd_pt) { and_printf(0,"KVM: cannot retrieve process table. Aborting.\n"); abort(); } openbsd_next = 0; return openbsd_getnext(); } int main (int argc, char** argv) { and_setprocreader(&openbsd_getfirst,&openbsd_getnext); return and_main(argc,argv); }