1*3be6ef06SEitan Adler /* 2*3be6ef06SEitan Adler * Top users/processes display for Unix 3*3be6ef06SEitan Adler * Version 3 4*3be6ef06SEitan Adler * 5*3be6ef06SEitan Adler * This program may be freely redistributed, 6*3be6ef06SEitan Adler * but this entire comment MUST remain intact. 7*3be6ef06SEitan Adler * 8*3be6ef06SEitan Adler * Copyright (c) 1984, 1989, William LeFebvre, Rice University 9*3be6ef06SEitan Adler * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University 10*3be6ef06SEitan Adler * 11*3be6ef06SEitan Adler * $FreeBSD$ 12*3be6ef06SEitan Adler */ 13*3be6ef06SEitan Adler 14*3be6ef06SEitan Adler /* 15*3be6ef06SEitan Adler * This file contains the routines that implement some of the interactive 16*3be6ef06SEitan Adler * mode commands. Note that some of the commands are implemented in-line 17*3be6ef06SEitan Adler * in "main". This is necessary because they change the global state of 18*3be6ef06SEitan Adler * "top" (i.e.: changing the number of processes to display). 19*3be6ef06SEitan Adler */ 20*3be6ef06SEitan Adler 21*3be6ef06SEitan Adler #include "os.h" 22*3be6ef06SEitan Adler 23*3be6ef06SEitan Adler #include <sys/time.h> 24*3be6ef06SEitan Adler #include <sys/resource.h> 25*3be6ef06SEitan Adler 26*3be6ef06SEitan Adler #include <ctype.h> 27*3be6ef06SEitan Adler #include <errno.h> 28*3be6ef06SEitan Adler #include <signal.h> 29*3be6ef06SEitan Adler #include <unistd.h> 30*3be6ef06SEitan Adler 31*3be6ef06SEitan Adler #include "commands.h" 32*3be6ef06SEitan Adler #include "sigdesc.h" /* generated automatically */ 33*3be6ef06SEitan Adler #include "top.h" 34*3be6ef06SEitan Adler #include "boolean.h" 35*3be6ef06SEitan Adler #include "utils.h" 36*3be6ef06SEitan Adler #include "machine.h" 37*3be6ef06SEitan Adler 38*3be6ef06SEitan Adler extern int errno; 39*3be6ef06SEitan Adler 40*3be6ef06SEitan Adler extern char *copyright; 41*3be6ef06SEitan Adler 42*3be6ef06SEitan Adler /* imported from screen.c */ 43*3be6ef06SEitan Adler extern int overstrike; 44*3be6ef06SEitan Adler 45*3be6ef06SEitan Adler int err_compar(); 46*3be6ef06SEitan Adler char *err_string(); 47*3be6ef06SEitan Adler static int str_adderr(char *str, int len, int err); 48*3be6ef06SEitan Adler static int str_addarg(char *str, int len, char *arg, int first); 49*3be6ef06SEitan Adler 50*3be6ef06SEitan Adler /* 51*3be6ef06SEitan Adler * show_help() - display the help screen; invoked in response to 52*3be6ef06SEitan Adler * either 'h' or '?'. 53*3be6ef06SEitan Adler */ 54*3be6ef06SEitan Adler 55*3be6ef06SEitan Adler void 56*3be6ef06SEitan Adler show_help() 57*3be6ef06SEitan Adler 58*3be6ef06SEitan Adler { 59*3be6ef06SEitan Adler printf("Top version %s, %s\n", version_string(), copyright); 60*3be6ef06SEitan Adler fputs("\n\n\ 61*3be6ef06SEitan Adler A top users display for Unix\n\ 62*3be6ef06SEitan Adler \n\ 63*3be6ef06SEitan Adler These single-character commands are available:\n\ 64*3be6ef06SEitan Adler \n\ 65*3be6ef06SEitan Adler ^L - redraw screen\n\ 66*3be6ef06SEitan Adler q - quit\n\ 67*3be6ef06SEitan Adler h or ? - help; show this text\n", stdout); 68*3be6ef06SEitan Adler 69*3be6ef06SEitan Adler /* not all commands are availalbe with overstrike terminals */ 70*3be6ef06SEitan Adler if (overstrike) 71*3be6ef06SEitan Adler { 72*3be6ef06SEitan Adler fputs("\n\ 73*3be6ef06SEitan Adler Other commands are also available, but this terminal is not\n\ 74*3be6ef06SEitan Adler sophisticated enough to handle those commands gracefully.\n\n", stdout); 75*3be6ef06SEitan Adler } 76*3be6ef06SEitan Adler else 77*3be6ef06SEitan Adler { 78*3be6ef06SEitan Adler fputs("\ 79*3be6ef06SEitan Adler C - toggle the displaying of weighted CPU percentage\n\ 80*3be6ef06SEitan Adler d - change number of displays to show\n\ 81*3be6ef06SEitan Adler e - list errors generated by last \"kill\" or \"renice\" command\n\ 82*3be6ef06SEitan Adler H - toggle the displaying of threads\n\ 83*3be6ef06SEitan Adler i or I - toggle the displaying of idle processes\n\ 84*3be6ef06SEitan Adler j - toggle the displaying of jail ID\n\ 85*3be6ef06SEitan Adler J - display processes for only one jail (+ selects all jails)\n\ 86*3be6ef06SEitan Adler k - kill processes; send a signal to a list of processes\n\ 87*3be6ef06SEitan Adler m - toggle the display between 'cpu' and 'io' modes\n\ 88*3be6ef06SEitan Adler n or # - change number of processes to display\n", stdout); 89*3be6ef06SEitan Adler #ifdef ORDER 90*3be6ef06SEitan Adler if (displaymode == DISP_CPU) 91*3be6ef06SEitan Adler fputs("\ 92*3be6ef06SEitan Adler o - specify sort order (pri, size, res, cpu, time, threads, jid, pid)\n", 93*3be6ef06SEitan Adler stdout); 94*3be6ef06SEitan Adler else 95*3be6ef06SEitan Adler fputs("\ 96*3be6ef06SEitan Adler o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid, pid)\n", 97*3be6ef06SEitan Adler stdout); 98*3be6ef06SEitan Adler #endif 99*3be6ef06SEitan Adler fputs("\ 100*3be6ef06SEitan Adler P - toggle the displaying of per-CPU statistics\n\ 101*3be6ef06SEitan Adler r - renice a process\n\ 102*3be6ef06SEitan Adler s - change number of seconds to delay between updates\n\ 103*3be6ef06SEitan Adler S - toggle the displaying of system processes\n\ 104*3be6ef06SEitan Adler a - toggle the displaying of process titles\n\ 105*3be6ef06SEitan Adler t - toggle the display of this process\n\ 106*3be6ef06SEitan Adler u - display processes for only one user (+ selects all users)\n\ 107*3be6ef06SEitan Adler w - toggle the display of swap use for each process\n\ 108*3be6ef06SEitan Adler z - toggle the displaying of the system idle process\n\ 109*3be6ef06SEitan Adler \n\ 110*3be6ef06SEitan Adler \n", stdout); 111*3be6ef06SEitan Adler } 112*3be6ef06SEitan Adler } 113*3be6ef06SEitan Adler 114*3be6ef06SEitan Adler /* 115*3be6ef06SEitan Adler * Utility routines that help with some of the commands. 116*3be6ef06SEitan Adler */ 117*3be6ef06SEitan Adler 118*3be6ef06SEitan Adler char *next_field(str) 119*3be6ef06SEitan Adler 120*3be6ef06SEitan Adler register char *str; 121*3be6ef06SEitan Adler 122*3be6ef06SEitan Adler { 123*3be6ef06SEitan Adler if ((str = strchr(str, ' ')) == NULL) 124*3be6ef06SEitan Adler { 125*3be6ef06SEitan Adler return(NULL); 126*3be6ef06SEitan Adler } 127*3be6ef06SEitan Adler *str = '\0'; 128*3be6ef06SEitan Adler while (*++str == ' ') /* loop */; 129*3be6ef06SEitan Adler 130*3be6ef06SEitan Adler /* if there is nothing left of the string, return NULL */ 131*3be6ef06SEitan Adler /* This fix is dedicated to Greg Earle */ 132*3be6ef06SEitan Adler return(*str == '\0' ? NULL : str); 133*3be6ef06SEitan Adler } 134*3be6ef06SEitan Adler 135*3be6ef06SEitan Adler int 136*3be6ef06SEitan Adler scanint(str, intp) 137*3be6ef06SEitan Adler 138*3be6ef06SEitan Adler char *str; 139*3be6ef06SEitan Adler int *intp; 140*3be6ef06SEitan Adler 141*3be6ef06SEitan Adler { 142*3be6ef06SEitan Adler register int val = 0; 143*3be6ef06SEitan Adler register char ch; 144*3be6ef06SEitan Adler 145*3be6ef06SEitan Adler /* if there is nothing left of the string, flag it as an error */ 146*3be6ef06SEitan Adler /* This fix is dedicated to Greg Earle */ 147*3be6ef06SEitan Adler if (*str == '\0') 148*3be6ef06SEitan Adler { 149*3be6ef06SEitan Adler return(-1); 150*3be6ef06SEitan Adler } 151*3be6ef06SEitan Adler 152*3be6ef06SEitan Adler while ((ch = *str++) != '\0') 153*3be6ef06SEitan Adler { 154*3be6ef06SEitan Adler if (isdigit(ch)) 155*3be6ef06SEitan Adler { 156*3be6ef06SEitan Adler val = val * 10 + (ch - '0'); 157*3be6ef06SEitan Adler } 158*3be6ef06SEitan Adler else if (isspace(ch)) 159*3be6ef06SEitan Adler { 160*3be6ef06SEitan Adler break; 161*3be6ef06SEitan Adler } 162*3be6ef06SEitan Adler else 163*3be6ef06SEitan Adler { 164*3be6ef06SEitan Adler return(-1); 165*3be6ef06SEitan Adler } 166*3be6ef06SEitan Adler } 167*3be6ef06SEitan Adler *intp = val; 168*3be6ef06SEitan Adler return(0); 169*3be6ef06SEitan Adler } 170*3be6ef06SEitan Adler 171*3be6ef06SEitan Adler /* 172*3be6ef06SEitan Adler * Some of the commands make system calls that could generate errors. 173*3be6ef06SEitan Adler * These errors are collected up in an array of structures for later 174*3be6ef06SEitan Adler * contemplation and display. Such routines return a string containing an 175*3be6ef06SEitan Adler * error message, or NULL if no errors occurred. The next few routines are 176*3be6ef06SEitan Adler * for manipulating and displaying these errors. We need an upper limit on 177*3be6ef06SEitan Adler * the number of errors, so we arbitrarily choose 20. 178*3be6ef06SEitan Adler */ 179*3be6ef06SEitan Adler 180*3be6ef06SEitan Adler #define ERRMAX 20 181*3be6ef06SEitan Adler 182*3be6ef06SEitan Adler struct errs /* structure for a system-call error */ 183*3be6ef06SEitan Adler { 184*3be6ef06SEitan Adler int errnum; /* value of errno (that is, the actual error) */ 185*3be6ef06SEitan Adler char *arg; /* argument that caused the error */ 186*3be6ef06SEitan Adler }; 187*3be6ef06SEitan Adler 188*3be6ef06SEitan Adler static struct errs errs[ERRMAX]; 189*3be6ef06SEitan Adler static int errcnt; 190*3be6ef06SEitan Adler static char *err_toomany = " too many errors occurred"; 191*3be6ef06SEitan Adler static char *err_listem = 192*3be6ef06SEitan Adler " Many errors occurred. Press `e' to display the list of errors."; 193*3be6ef06SEitan Adler 194*3be6ef06SEitan Adler /* These macros get used to reset and log the errors */ 195*3be6ef06SEitan Adler #define ERR_RESET errcnt = 0 196*3be6ef06SEitan Adler #define ERROR(p, e) if (errcnt >= ERRMAX) \ 197*3be6ef06SEitan Adler { \ 198*3be6ef06SEitan Adler return(err_toomany); \ 199*3be6ef06SEitan Adler } \ 200*3be6ef06SEitan Adler else \ 201*3be6ef06SEitan Adler { \ 202*3be6ef06SEitan Adler errs[errcnt].arg = (p); \ 203*3be6ef06SEitan Adler errs[errcnt++].errnum = (e); \ 204*3be6ef06SEitan Adler } 205*3be6ef06SEitan Adler 206*3be6ef06SEitan Adler /* 207*3be6ef06SEitan Adler * err_string() - return an appropriate error string. This is what the 208*3be6ef06SEitan Adler * command will return for displaying. If no errors were logged, then 209*3be6ef06SEitan Adler * return NULL. The maximum length of the error string is defined by 210*3be6ef06SEitan Adler * "STRMAX". 211*3be6ef06SEitan Adler */ 212*3be6ef06SEitan Adler 213*3be6ef06SEitan Adler #define STRMAX 80 214*3be6ef06SEitan Adler 215*3be6ef06SEitan Adler char *err_string() 216*3be6ef06SEitan Adler 217*3be6ef06SEitan Adler { 218*3be6ef06SEitan Adler register struct errs *errp; 219*3be6ef06SEitan Adler register int cnt = 0; 220*3be6ef06SEitan Adler register int first = Yes; 221*3be6ef06SEitan Adler register int currerr = -1; 222*3be6ef06SEitan Adler int stringlen; /* characters still available in "string" */ 223*3be6ef06SEitan Adler static char string[STRMAX]; 224*3be6ef06SEitan Adler 225*3be6ef06SEitan Adler /* if there are no errors, return NULL */ 226*3be6ef06SEitan Adler if (errcnt == 0) 227*3be6ef06SEitan Adler { 228*3be6ef06SEitan Adler return(NULL); 229*3be6ef06SEitan Adler } 230*3be6ef06SEitan Adler 231*3be6ef06SEitan Adler /* sort the errors */ 232*3be6ef06SEitan Adler qsort((char *)errs, errcnt, sizeof(struct errs), err_compar); 233*3be6ef06SEitan Adler 234*3be6ef06SEitan Adler /* need a space at the front of the error string */ 235*3be6ef06SEitan Adler string[0] = ' '; 236*3be6ef06SEitan Adler string[1] = '\0'; 237*3be6ef06SEitan Adler stringlen = STRMAX - 2; 238*3be6ef06SEitan Adler 239*3be6ef06SEitan Adler /* loop thru the sorted list, building an error string */ 240*3be6ef06SEitan Adler while (cnt < errcnt) 241*3be6ef06SEitan Adler { 242*3be6ef06SEitan Adler errp = &(errs[cnt++]); 243*3be6ef06SEitan Adler if (errp->errnum != currerr) 244*3be6ef06SEitan Adler { 245*3be6ef06SEitan Adler if (currerr != -1) 246*3be6ef06SEitan Adler { 247*3be6ef06SEitan Adler if ((stringlen = str_adderr(string, stringlen, currerr)) < 2) 248*3be6ef06SEitan Adler { 249*3be6ef06SEitan Adler return(err_listem); 250*3be6ef06SEitan Adler } 251*3be6ef06SEitan Adler (void) strcat(string, "; "); /* we know there's more */ 252*3be6ef06SEitan Adler } 253*3be6ef06SEitan Adler currerr = errp->errnum; 254*3be6ef06SEitan Adler first = Yes; 255*3be6ef06SEitan Adler } 256*3be6ef06SEitan Adler if ((stringlen = str_addarg(string, stringlen, errp->arg, first)) ==0) 257*3be6ef06SEitan Adler { 258*3be6ef06SEitan Adler return(err_listem); 259*3be6ef06SEitan Adler } 260*3be6ef06SEitan Adler first = No; 261*3be6ef06SEitan Adler } 262*3be6ef06SEitan Adler 263*3be6ef06SEitan Adler /* add final message */ 264*3be6ef06SEitan Adler stringlen = str_adderr(string, stringlen, currerr); 265*3be6ef06SEitan Adler 266*3be6ef06SEitan Adler /* return the error string */ 267*3be6ef06SEitan Adler return(stringlen == 0 ? err_listem : string); 268*3be6ef06SEitan Adler } 269*3be6ef06SEitan Adler 270*3be6ef06SEitan Adler /* 271*3be6ef06SEitan Adler * str_adderr(str, len, err) - add an explanation of error "err" to 272*3be6ef06SEitan Adler * the string "str". 273*3be6ef06SEitan Adler */ 274*3be6ef06SEitan Adler 275*3be6ef06SEitan Adler static int 276*3be6ef06SEitan Adler str_adderr(str, len, err) 277*3be6ef06SEitan Adler 278*3be6ef06SEitan Adler char *str; 279*3be6ef06SEitan Adler int len; 280*3be6ef06SEitan Adler int err; 281*3be6ef06SEitan Adler 282*3be6ef06SEitan Adler { 283*3be6ef06SEitan Adler register char *msg; 284*3be6ef06SEitan Adler register int msglen; 285*3be6ef06SEitan Adler 286*3be6ef06SEitan Adler msg = err == 0 ? "Not a number" : errmsg(err); 287*3be6ef06SEitan Adler msglen = strlen(msg) + 2; 288*3be6ef06SEitan Adler if (len <= msglen) 289*3be6ef06SEitan Adler { 290*3be6ef06SEitan Adler return(0); 291*3be6ef06SEitan Adler } 292*3be6ef06SEitan Adler (void) strcat(str, ": "); 293*3be6ef06SEitan Adler (void) strcat(str, msg); 294*3be6ef06SEitan Adler return(len - msglen); 295*3be6ef06SEitan Adler } 296*3be6ef06SEitan Adler 297*3be6ef06SEitan Adler /* 298*3be6ef06SEitan Adler * str_addarg(str, len, arg, first) - add the string argument "arg" to 299*3be6ef06SEitan Adler * the string "str". This is the first in the group when "first" 300*3be6ef06SEitan Adler * is set (indicating that a comma should NOT be added to the front). 301*3be6ef06SEitan Adler */ 302*3be6ef06SEitan Adler 303*3be6ef06SEitan Adler static int 304*3be6ef06SEitan Adler str_addarg(str, len, arg, first) 305*3be6ef06SEitan Adler 306*3be6ef06SEitan Adler char *str; 307*3be6ef06SEitan Adler int len; 308*3be6ef06SEitan Adler char *arg; 309*3be6ef06SEitan Adler int first; 310*3be6ef06SEitan Adler 311*3be6ef06SEitan Adler { 312*3be6ef06SEitan Adler register int arglen; 313*3be6ef06SEitan Adler 314*3be6ef06SEitan Adler arglen = strlen(arg); 315*3be6ef06SEitan Adler if (!first) 316*3be6ef06SEitan Adler { 317*3be6ef06SEitan Adler arglen += 2; 318*3be6ef06SEitan Adler } 319*3be6ef06SEitan Adler if (len <= arglen) 320*3be6ef06SEitan Adler { 321*3be6ef06SEitan Adler return(0); 322*3be6ef06SEitan Adler } 323*3be6ef06SEitan Adler if (!first) 324*3be6ef06SEitan Adler { 325*3be6ef06SEitan Adler (void) strcat(str, ", "); 326*3be6ef06SEitan Adler } 327*3be6ef06SEitan Adler (void) strcat(str, arg); 328*3be6ef06SEitan Adler return(len - arglen); 329*3be6ef06SEitan Adler } 330*3be6ef06SEitan Adler 331*3be6ef06SEitan Adler /* 332*3be6ef06SEitan Adler * err_compar(p1, p2) - comparison routine used by "qsort" 333*3be6ef06SEitan Adler * for sorting errors. 334*3be6ef06SEitan Adler */ 335*3be6ef06SEitan Adler 336*3be6ef06SEitan Adler int 337*3be6ef06SEitan Adler err_compar(p1, p2) 338*3be6ef06SEitan Adler 339*3be6ef06SEitan Adler register struct errs *p1, *p2; 340*3be6ef06SEitan Adler 341*3be6ef06SEitan Adler { 342*3be6ef06SEitan Adler register int result; 343*3be6ef06SEitan Adler 344*3be6ef06SEitan Adler if ((result = p1->errnum - p2->errnum) == 0) 345*3be6ef06SEitan Adler { 346*3be6ef06SEitan Adler return(strcmp(p1->arg, p2->arg)); 347*3be6ef06SEitan Adler } 348*3be6ef06SEitan Adler return(result); 349*3be6ef06SEitan Adler } 350*3be6ef06SEitan Adler 351*3be6ef06SEitan Adler /* 352*3be6ef06SEitan Adler * error_count() - return the number of errors currently logged. 353*3be6ef06SEitan Adler */ 354*3be6ef06SEitan Adler 355*3be6ef06SEitan Adler int 356*3be6ef06SEitan Adler error_count() 357*3be6ef06SEitan Adler 358*3be6ef06SEitan Adler { 359*3be6ef06SEitan Adler return(errcnt); 360*3be6ef06SEitan Adler } 361*3be6ef06SEitan Adler 362*3be6ef06SEitan Adler /* 363*3be6ef06SEitan Adler * show_errors() - display on stdout the current log of errors. 364*3be6ef06SEitan Adler */ 365*3be6ef06SEitan Adler 366*3be6ef06SEitan Adler void 367*3be6ef06SEitan Adler show_errors() 368*3be6ef06SEitan Adler 369*3be6ef06SEitan Adler { 370*3be6ef06SEitan Adler register int cnt = 0; 371*3be6ef06SEitan Adler register struct errs *errp = errs; 372*3be6ef06SEitan Adler 373*3be6ef06SEitan Adler printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s"); 374*3be6ef06SEitan Adler while (cnt++ < errcnt) 375*3be6ef06SEitan Adler { 376*3be6ef06SEitan Adler printf("%5s: %s\n", errp->arg, 377*3be6ef06SEitan Adler errp->errnum == 0 ? "Not a number" : errmsg(errp->errnum)); 378*3be6ef06SEitan Adler errp++; 379*3be6ef06SEitan Adler } 380*3be6ef06SEitan Adler } 381*3be6ef06SEitan Adler 382*3be6ef06SEitan Adler /* 383*3be6ef06SEitan Adler * kill_procs(str) - send signals to processes, much like the "kill" 384*3be6ef06SEitan Adler * command does; invoked in response to 'k'. 385*3be6ef06SEitan Adler */ 386*3be6ef06SEitan Adler 387*3be6ef06SEitan Adler char *kill_procs(str) 388*3be6ef06SEitan Adler 389*3be6ef06SEitan Adler char *str; 390*3be6ef06SEitan Adler 391*3be6ef06SEitan Adler { 392*3be6ef06SEitan Adler register char *nptr; 393*3be6ef06SEitan Adler int signum = SIGTERM; /* default */ 394*3be6ef06SEitan Adler int procnum; 395*3be6ef06SEitan Adler struct sigdesc *sigp; 396*3be6ef06SEitan Adler int uid; 397*3be6ef06SEitan Adler 398*3be6ef06SEitan Adler /* reset error array */ 399*3be6ef06SEitan Adler ERR_RESET; 400*3be6ef06SEitan Adler 401*3be6ef06SEitan Adler /* remember our uid */ 402*3be6ef06SEitan Adler uid = getuid(); 403*3be6ef06SEitan Adler 404*3be6ef06SEitan Adler /* skip over leading white space */ 405*3be6ef06SEitan Adler while (isspace(*str)) str++; 406*3be6ef06SEitan Adler 407*3be6ef06SEitan Adler if (str[0] == '-') 408*3be6ef06SEitan Adler { 409*3be6ef06SEitan Adler /* explicit signal specified */ 410*3be6ef06SEitan Adler if ((nptr = next_field(str)) == NULL) 411*3be6ef06SEitan Adler { 412*3be6ef06SEitan Adler return(" kill: no processes specified"); 413*3be6ef06SEitan Adler } 414*3be6ef06SEitan Adler 415*3be6ef06SEitan Adler if (isdigit(str[1])) 416*3be6ef06SEitan Adler { 417*3be6ef06SEitan Adler (void) scanint(str + 1, &signum); 418*3be6ef06SEitan Adler if (signum <= 0 || signum >= NSIG) 419*3be6ef06SEitan Adler { 420*3be6ef06SEitan Adler return(" invalid signal number"); 421*3be6ef06SEitan Adler } 422*3be6ef06SEitan Adler } 423*3be6ef06SEitan Adler else 424*3be6ef06SEitan Adler { 425*3be6ef06SEitan Adler /* translate the name into a number */ 426*3be6ef06SEitan Adler for (sigp = sigdesc; sigp->name != NULL; sigp++) 427*3be6ef06SEitan Adler { 428*3be6ef06SEitan Adler if (strcmp(sigp->name, str + 1) == 0) 429*3be6ef06SEitan Adler { 430*3be6ef06SEitan Adler signum = sigp->number; 431*3be6ef06SEitan Adler break; 432*3be6ef06SEitan Adler } 433*3be6ef06SEitan Adler } 434*3be6ef06SEitan Adler 435*3be6ef06SEitan Adler /* was it ever found */ 436*3be6ef06SEitan Adler if (sigp->name == NULL) 437*3be6ef06SEitan Adler { 438*3be6ef06SEitan Adler return(" bad signal name"); 439*3be6ef06SEitan Adler } 440*3be6ef06SEitan Adler } 441*3be6ef06SEitan Adler /* put the new pointer in place */ 442*3be6ef06SEitan Adler str = nptr; 443*3be6ef06SEitan Adler } 444*3be6ef06SEitan Adler 445*3be6ef06SEitan Adler /* loop thru the string, killing processes */ 446*3be6ef06SEitan Adler do 447*3be6ef06SEitan Adler { 448*3be6ef06SEitan Adler if (scanint(str, &procnum) == -1) 449*3be6ef06SEitan Adler { 450*3be6ef06SEitan Adler ERROR(str, 0); 451*3be6ef06SEitan Adler } 452*3be6ef06SEitan Adler else 453*3be6ef06SEitan Adler { 454*3be6ef06SEitan Adler /* check process owner if we're not root */ 455*3be6ef06SEitan Adler if (uid && (uid != proc_owner(procnum))) 456*3be6ef06SEitan Adler { 457*3be6ef06SEitan Adler ERROR(str, EACCES); 458*3be6ef06SEitan Adler } 459*3be6ef06SEitan Adler /* go in for the kill */ 460*3be6ef06SEitan Adler else if (kill(procnum, signum) == -1) 461*3be6ef06SEitan Adler { 462*3be6ef06SEitan Adler /* chalk up an error */ 463*3be6ef06SEitan Adler ERROR(str, errno); 464*3be6ef06SEitan Adler } 465*3be6ef06SEitan Adler } 466*3be6ef06SEitan Adler } while ((str = next_field(str)) != NULL); 467*3be6ef06SEitan Adler 468*3be6ef06SEitan Adler /* return appropriate error string */ 469*3be6ef06SEitan Adler return(err_string()); 470*3be6ef06SEitan Adler } 471*3be6ef06SEitan Adler 472*3be6ef06SEitan Adler /* 473*3be6ef06SEitan Adler * renice_procs(str) - change the "nice" of processes, much like the 474*3be6ef06SEitan Adler * "renice" command does; invoked in response to 'r'. 475*3be6ef06SEitan Adler */ 476*3be6ef06SEitan Adler 477*3be6ef06SEitan Adler char *renice_procs(str) 478*3be6ef06SEitan Adler 479*3be6ef06SEitan Adler char *str; 480*3be6ef06SEitan Adler 481*3be6ef06SEitan Adler { 482*3be6ef06SEitan Adler register char negate; 483*3be6ef06SEitan Adler int prio; 484*3be6ef06SEitan Adler int procnum; 485*3be6ef06SEitan Adler int uid; 486*3be6ef06SEitan Adler 487*3be6ef06SEitan Adler ERR_RESET; 488*3be6ef06SEitan Adler uid = getuid(); 489*3be6ef06SEitan Adler 490*3be6ef06SEitan Adler /* allow for negative priority values */ 491*3be6ef06SEitan Adler if ((negate = (*str == '-')) != 0) 492*3be6ef06SEitan Adler { 493*3be6ef06SEitan Adler /* move past the minus sign */ 494*3be6ef06SEitan Adler str++; 495*3be6ef06SEitan Adler } 496*3be6ef06SEitan Adler 497*3be6ef06SEitan Adler /* use procnum as a temporary holding place and get the number */ 498*3be6ef06SEitan Adler procnum = scanint(str, &prio); 499*3be6ef06SEitan Adler 500*3be6ef06SEitan Adler /* negate if necessary */ 501*3be6ef06SEitan Adler if (negate) 502*3be6ef06SEitan Adler { 503*3be6ef06SEitan Adler prio = -prio; 504*3be6ef06SEitan Adler } 505*3be6ef06SEitan Adler 506*3be6ef06SEitan Adler #if defined(PRIO_MIN) && defined(PRIO_MAX) 507*3be6ef06SEitan Adler /* check for validity */ 508*3be6ef06SEitan Adler if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX) 509*3be6ef06SEitan Adler { 510*3be6ef06SEitan Adler return(" bad priority value"); 511*3be6ef06SEitan Adler } 512*3be6ef06SEitan Adler #endif 513*3be6ef06SEitan Adler 514*3be6ef06SEitan Adler /* move to the first process number */ 515*3be6ef06SEitan Adler if ((str = next_field(str)) == NULL) 516*3be6ef06SEitan Adler { 517*3be6ef06SEitan Adler return(" no processes specified"); 518*3be6ef06SEitan Adler } 519*3be6ef06SEitan Adler 520*3be6ef06SEitan Adler /* loop thru the process numbers, renicing each one */ 521*3be6ef06SEitan Adler do 522*3be6ef06SEitan Adler { 523*3be6ef06SEitan Adler if (scanint(str, &procnum) == -1) 524*3be6ef06SEitan Adler { 525*3be6ef06SEitan Adler ERROR(str, 0); 526*3be6ef06SEitan Adler } 527*3be6ef06SEitan Adler 528*3be6ef06SEitan Adler /* check process owner if we're not root */ 529*3be6ef06SEitan Adler else if (uid && (uid != proc_owner(procnum))) 530*3be6ef06SEitan Adler { 531*3be6ef06SEitan Adler ERROR(str, EACCES); 532*3be6ef06SEitan Adler } 533*3be6ef06SEitan Adler else if (setpriority(PRIO_PROCESS, procnum, prio) == -1) 534*3be6ef06SEitan Adler { 535*3be6ef06SEitan Adler ERROR(str, errno); 536*3be6ef06SEitan Adler } 537*3be6ef06SEitan Adler } while ((str = next_field(str)) != NULL); 538*3be6ef06SEitan Adler 539*3be6ef06SEitan Adler /* return appropriate error string */ 540*3be6ef06SEitan Adler return(err_string()); 541*3be6ef06SEitan Adler } 542*3be6ef06SEitan Adler 543