13be6ef06SEitan Adler /* 23be6ef06SEitan Adler * Top users/processes display for Unix 3*51c834c4SEitan Adler * Version 3 43be6ef06SEitan Adler * 53be6ef06SEitan Adler * This program may be freely redistributed, 63be6ef06SEitan Adler * but this entire comment MUST remain intact. 73be6ef06SEitan Adler * 83be6ef06SEitan Adler * Copyright (c) 1984, 1989, William LeFebvre, Rice University 93be6ef06SEitan Adler * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University 103be6ef06SEitan Adler * 113be6ef06SEitan Adler * $FreeBSD$ 123be6ef06SEitan Adler */ 133be6ef06SEitan Adler 143be6ef06SEitan Adler /* 153be6ef06SEitan Adler * This file contains the routines that implement some of the interactive 163be6ef06SEitan Adler * mode commands. Note that some of the commands are implemented in-line 173be6ef06SEitan Adler * in "main". This is necessary because they change the global state of 183be6ef06SEitan Adler * "top" (i.e.: changing the number of processes to display). 193be6ef06SEitan Adler */ 203be6ef06SEitan Adler 213be6ef06SEitan Adler #include <sys/resource.h> 228d0d2676SEitan Adler #include <sys/signal.h> 233be6ef06SEitan Adler 243be6ef06SEitan Adler #include <ctype.h> 253be6ef06SEitan Adler #include <errno.h> 263be6ef06SEitan Adler #include <signal.h> 270b2f6ed1SEitan Adler #include <stdbool.h> 28caee4883SEitan Adler #include <stdlib.h> 29caee4883SEitan Adler #include <stdio.h> 30caee4883SEitan Adler #include <string.h> 313be6ef06SEitan Adler #include <unistd.h> 323be6ef06SEitan Adler 333be6ef06SEitan Adler #include "commands.h" 343be6ef06SEitan Adler #include "top.h" 353be6ef06SEitan Adler #include "machine.h" 363be6ef06SEitan Adler 37b3c88c28SEitan Adler static int err_compar(const void *p1, const void *p2); 38b3c88c28SEitan Adler 39b3c88c28SEitan Adler struct errs /* structure for a system-call error */ 40b3c88c28SEitan Adler { 41b3c88c28SEitan Adler int errnum; /* value of errno (that is, the actual error) */ 42b3c88c28SEitan Adler char *arg; /* argument that caused the error */ 43b3c88c28SEitan Adler }; 44b3c88c28SEitan Adler 45419fab3bSEitan Adler static char *err_string(void); 463be6ef06SEitan Adler static int str_adderr(char *str, int len, int err); 47d0bb69dcSEitan Adler static int str_addarg(char *str, int len, char *arg, bool first); 483be6ef06SEitan Adler 493be6ef06SEitan Adler /* 503be6ef06SEitan Adler * show_help() - display the help screen; invoked in response to 513be6ef06SEitan Adler * either 'h' or '?'. 523be6ef06SEitan Adler */ 533be6ef06SEitan Adler 54c8aa5e52SEitan Adler const struct command all_commands[] = 55b26cf3d0SEitan Adler { 56c8aa5e52SEitan Adler {'C', "toggle the displaying of weighted CPU percentage", false, CMD_wcputog}, 57c8aa5e52SEitan Adler {'d', "change number of displays to show", false, CMD_displays}, 58c8aa5e52SEitan Adler {'e', "list errors generated by last \"kill\" or \"renice\" command", false, CMD_errors}, 59c8aa5e52SEitan Adler {'H', "toggle the displaying of threads", false, CMD_thrtog}, 60c8aa5e52SEitan Adler {'h', "show this help text", true, CMD_help}, 61e7cb1c07SEitan Adler {'?', NULL, true, CMD_help}, 62c8aa5e52SEitan Adler {'i', "toggle the displaying of idle processes", false, CMD_idletog}, 63e7cb1c07SEitan Adler {'I', NULL, false, CMD_idletog}, 64c8aa5e52SEitan Adler {'j', "toggle the displaying of jail ID", false, CMD_jidtog}, 65c8aa5e52SEitan Adler {'J', "display processes for only one jail (+ selects all jails)", false, CMD_jail}, 66c8aa5e52SEitan Adler {'k', "kill processes; send a signal to a list of processes", false, CMD_kill}, 67c8aa5e52SEitan Adler {'q', "quit" , true, CMD_quit}, 68c8aa5e52SEitan Adler {'m', "toggle the display between 'cpu' and 'io' modes", false, CMD_viewtog}, 69c8aa5e52SEitan Adler {'n', "change number of processes to display", false, CMD_number}, 70e7cb1c07SEitan Adler {'#', NULL, false, CMD_number}, 71c8aa5e52SEitan Adler {'o', "specify the sort order", false, CMD_order}, 72c8aa5e52SEitan Adler {'p', "display one process (+ selects all processes)", false, CMD_pid}, 73c8aa5e52SEitan Adler {'P', "toggle the displaying of per-CPU statistics", false, CMD_pcputog}, 74c8aa5e52SEitan Adler {'r', "renice a process", false, CMD_renice}, 75c8aa5e52SEitan Adler {'s', "change number of seconds to delay between updates", false, CMD_delay}, 76c8aa5e52SEitan Adler {'S', "toggle the displaying of system processes", false, CMD_viewsys}, 77c8aa5e52SEitan Adler {'a', "toggle the displaying of process titles", false, CMD_showargs}, 78c8aa5e52SEitan Adler {'T', "toggle the displaying of thread IDs", false, CMD_toggletid}, 79c8aa5e52SEitan Adler {'t', "toggle the display of this process", false, CMD_selftog}, 80c8aa5e52SEitan Adler {'u', "display processes for only one user (+ selects all users)", false, CMD_user}, 81c8aa5e52SEitan Adler {'w', "toggle the display of swap use for each process", false, CMD_swaptog}, 82c8aa5e52SEitan Adler {'z', "toggle the displaying of the system idle process", false, CMD_kidletog}, 83c8aa5e52SEitan Adler {' ', "update the display", false, CMD_update}, 84c8aa5e52SEitan Adler {0, NULL, true, CMD_NONE} 85b26cf3d0SEitan Adler }; 86b26cf3d0SEitan Adler 873be6ef06SEitan Adler void 88f6234b51SEitan Adler show_help(void) 893be6ef06SEitan Adler { 90e7cb1c07SEitan Adler const struct command *curcmd, *nextcmd; 91e7cb1c07SEitan Adler char keys[8] = ""; 92e7cb1c07SEitan Adler _Static_assert(sizeof(keys) >= sizeof("a or b"), "keys right size"); 933be6ef06SEitan Adler 94b26cf3d0SEitan Adler printf("Top version FreeBSD, %s\n", copyright); 95b26cf3d0SEitan Adler curcmd = all_commands; 96b26cf3d0SEitan Adler while (curcmd->c != 0) { 97b26cf3d0SEitan Adler if (overstrike && !curcmd->available_to_dumb) { 98b26cf3d0SEitan Adler ++curcmd; 99b26cf3d0SEitan Adler continue; 100b26cf3d0SEitan Adler } 101e7cb1c07SEitan Adler if (curcmd->desc == NULL) { 102e7cb1c07SEitan Adler /* we already printed this */ 103e7cb1c07SEitan Adler ++curcmd; 104e7cb1c07SEitan Adler continue; 105e7cb1c07SEitan Adler } 106e7cb1c07SEitan Adler nextcmd = curcmd + 1; 107e7cb1c07SEitan Adler if (nextcmd->desc == NULL && nextcmd->c != '\0') { 108e7cb1c07SEitan Adler sprintf(keys, "%c or %c", curcmd->c, nextcmd->c); 109e7cb1c07SEitan Adler } else if (curcmd->c == ' '){ 110e7cb1c07SEitan Adler /* special case space rather than introducing a "display string" to 111e7cb1c07SEitan Adler * the struct */ 112e7cb1c07SEitan Adler sprintf(keys, "SPC"); 113e7cb1c07SEitan Adler } else { 114e7cb1c07SEitan Adler sprintf(keys, "%c", curcmd->c); 115e7cb1c07SEitan Adler } 116e7cb1c07SEitan Adler printf("%s\t- %s\n", keys, curcmd->desc); 117b26cf3d0SEitan Adler ++curcmd; 118b26cf3d0SEitan Adler } 1193be6ef06SEitan Adler if (overstrike) 1203be6ef06SEitan Adler { 121b26cf3d0SEitan Adler fputs("\ 1223be6ef06SEitan Adler Other commands are also available, but this terminal is not\n\ 123b26cf3d0SEitan Adler sophisticated enough to handle those commands gracefully.\n", stdout); 1243be6ef06SEitan Adler } 1253be6ef06SEitan Adler } 1263be6ef06SEitan Adler 1273be6ef06SEitan Adler /* 1283be6ef06SEitan Adler * Utility routines that help with some of the commands. 1293be6ef06SEitan Adler */ 1303be6ef06SEitan Adler 131b3c88c28SEitan Adler static char * 132b3c88c28SEitan Adler next_field(char *str) 1333be6ef06SEitan Adler { 1343be6ef06SEitan Adler if ((str = strchr(str, ' ')) == NULL) 1353be6ef06SEitan Adler { 1363be6ef06SEitan Adler return(NULL); 1373be6ef06SEitan Adler } 1383be6ef06SEitan Adler *str = '\0'; 1393be6ef06SEitan Adler while (*++str == ' ') /* loop */; 1403be6ef06SEitan Adler 1413be6ef06SEitan Adler /* if there is nothing left of the string, return NULL */ 1423be6ef06SEitan Adler /* This fix is dedicated to Greg Earle */ 1433be6ef06SEitan Adler return(*str == '\0' ? NULL : str); 1443be6ef06SEitan Adler } 1453be6ef06SEitan Adler 146b3c88c28SEitan Adler static int 147bc875b45SEitan Adler scanint(char *str, int *intp) 1483be6ef06SEitan Adler { 14998c299e0SEitan Adler int val = 0; 15098c299e0SEitan Adler char ch; 1513be6ef06SEitan Adler 1523be6ef06SEitan Adler /* if there is nothing left of the string, flag it as an error */ 1533be6ef06SEitan Adler /* This fix is dedicated to Greg Earle */ 1543be6ef06SEitan Adler if (*str == '\0') 1553be6ef06SEitan Adler { 1563be6ef06SEitan Adler return(-1); 1573be6ef06SEitan Adler } 1583be6ef06SEitan Adler 1593be6ef06SEitan Adler while ((ch = *str++) != '\0') 1603be6ef06SEitan Adler { 1613be6ef06SEitan Adler if (isdigit(ch)) 1623be6ef06SEitan Adler { 1633be6ef06SEitan Adler val = val * 10 + (ch - '0'); 1643be6ef06SEitan Adler } 1653be6ef06SEitan Adler else if (isspace(ch)) 1663be6ef06SEitan Adler { 1673be6ef06SEitan Adler break; 1683be6ef06SEitan Adler } 1693be6ef06SEitan Adler else 1703be6ef06SEitan Adler { 1713be6ef06SEitan Adler return(-1); 1723be6ef06SEitan Adler } 1733be6ef06SEitan Adler } 1743be6ef06SEitan Adler *intp = val; 1753be6ef06SEitan Adler return(0); 1763be6ef06SEitan Adler } 1773be6ef06SEitan Adler 1783be6ef06SEitan Adler /* 1793be6ef06SEitan Adler * Some of the commands make system calls that could generate errors. 1803be6ef06SEitan Adler * These errors are collected up in an array of structures for later 1813be6ef06SEitan Adler * contemplation and display. Such routines return a string containing an 1823be6ef06SEitan Adler * error message, or NULL if no errors occurred. The next few routines are 1833be6ef06SEitan Adler * for manipulating and displaying these errors. We need an upper limit on 1843be6ef06SEitan Adler * the number of errors, so we arbitrarily choose 20. 1853be6ef06SEitan Adler */ 1863be6ef06SEitan Adler 1873be6ef06SEitan Adler #define ERRMAX 20 1883be6ef06SEitan Adler 1893be6ef06SEitan Adler static struct errs errs[ERRMAX]; 1903be6ef06SEitan Adler static int errcnt; 1913c9ec0a5SEitan Adler static char err_toomany[] = " too many errors occurred"; 1923c9ec0a5SEitan Adler static char err_listem[] = 1933be6ef06SEitan Adler " Many errors occurred. Press `e' to display the list of errors."; 1943be6ef06SEitan Adler 1953be6ef06SEitan Adler /* These macros get used to reset and log the errors */ 1963be6ef06SEitan Adler #define ERR_RESET errcnt = 0 1973be6ef06SEitan Adler #define ERROR(p, e) if (errcnt >= ERRMAX) \ 1983be6ef06SEitan Adler { \ 1993be6ef06SEitan Adler return(err_toomany); \ 2003be6ef06SEitan Adler } \ 2013be6ef06SEitan Adler else \ 2023be6ef06SEitan Adler { \ 2033be6ef06SEitan Adler errs[errcnt].arg = (p); \ 2043be6ef06SEitan Adler errs[errcnt++].errnum = (e); \ 2053be6ef06SEitan Adler } 2063be6ef06SEitan Adler 2073be6ef06SEitan Adler /* 2083be6ef06SEitan Adler * err_string() - return an appropriate error string. This is what the 2093be6ef06SEitan Adler * command will return for displaying. If no errors were logged, then 2103be6ef06SEitan Adler * return NULL. The maximum length of the error string is defined by 2113be6ef06SEitan Adler * "STRMAX". 2123be6ef06SEitan Adler */ 2133be6ef06SEitan Adler 2143be6ef06SEitan Adler #define STRMAX 80 2153be6ef06SEitan Adler 216ccf22059SEitan Adler char * 217ccf22059SEitan Adler err_string(void) 2183be6ef06SEitan Adler { 21998c299e0SEitan Adler struct errs *errp; 22098c299e0SEitan Adler int cnt = 0; 221d0bb69dcSEitan Adler bool first = true; 22298c299e0SEitan Adler int currerr = -1; 2233be6ef06SEitan Adler int stringlen; /* characters still available in "string" */ 2243be6ef06SEitan Adler static char string[STRMAX]; 2253be6ef06SEitan Adler 2263be6ef06SEitan Adler /* if there are no errors, return NULL */ 2273be6ef06SEitan Adler if (errcnt == 0) 2283be6ef06SEitan Adler { 2293be6ef06SEitan Adler return(NULL); 2303be6ef06SEitan Adler } 2313be6ef06SEitan Adler 2323be6ef06SEitan Adler /* sort the errors */ 2333be6ef06SEitan Adler qsort((char *)errs, errcnt, sizeof(struct errs), err_compar); 2343be6ef06SEitan Adler 2353be6ef06SEitan Adler /* need a space at the front of the error string */ 2363be6ef06SEitan Adler string[0] = ' '; 2373be6ef06SEitan Adler string[1] = '\0'; 2383be6ef06SEitan Adler stringlen = STRMAX - 2; 2393be6ef06SEitan Adler 2403be6ef06SEitan Adler /* loop thru the sorted list, building an error string */ 2413be6ef06SEitan Adler while (cnt < errcnt) 2423be6ef06SEitan Adler { 2433be6ef06SEitan Adler errp = &(errs[cnt++]); 2443be6ef06SEitan Adler if (errp->errnum != currerr) 2453be6ef06SEitan Adler { 246aa9d9bfaSAlan Somers if (currerr >= 0) 2473be6ef06SEitan Adler { 2483be6ef06SEitan Adler if ((stringlen = str_adderr(string, stringlen, currerr)) < 2) 2493be6ef06SEitan Adler { 2503be6ef06SEitan Adler return(err_listem); 2513be6ef06SEitan Adler } 252419fab3bSEitan Adler strcat(string, "; "); /* we know there's more */ 2533be6ef06SEitan Adler } 2543be6ef06SEitan Adler currerr = errp->errnum; 2550b2f6ed1SEitan Adler first = true; 2563be6ef06SEitan Adler } 2573be6ef06SEitan Adler if ((stringlen = str_addarg(string, stringlen, errp->arg, first)) ==0) 2583be6ef06SEitan Adler { 2593be6ef06SEitan Adler return(err_listem); 2603be6ef06SEitan Adler } 2610b2f6ed1SEitan Adler first = false; 2623be6ef06SEitan Adler } 2633be6ef06SEitan Adler 2643be6ef06SEitan Adler /* add final message */ 2653be6ef06SEitan Adler stringlen = str_adderr(string, stringlen, currerr); 2663be6ef06SEitan Adler 2673be6ef06SEitan Adler /* return the error string */ 2683be6ef06SEitan Adler return(stringlen == 0 ? err_listem : string); 2693be6ef06SEitan Adler } 2703be6ef06SEitan Adler 2713be6ef06SEitan Adler /* 2723be6ef06SEitan Adler * str_adderr(str, len, err) - add an explanation of error "err" to 2733be6ef06SEitan Adler * the string "str". 2743be6ef06SEitan Adler */ 2753be6ef06SEitan Adler 2763be6ef06SEitan Adler static int 277419fab3bSEitan Adler str_adderr(char *str, int len, int err) 2783be6ef06SEitan Adler { 279419fab3bSEitan Adler const char *msg; 28098c299e0SEitan Adler int msglen; 2813be6ef06SEitan Adler 282b3c88c28SEitan Adler msg = err == 0 ? "Not a number" : strerror(err); 2833be6ef06SEitan Adler msglen = strlen(msg) + 2; 2843be6ef06SEitan Adler if (len <= msglen) 2853be6ef06SEitan Adler { 2863be6ef06SEitan Adler return(0); 2873be6ef06SEitan Adler } 288419fab3bSEitan Adler strcat(str, ": "); 289419fab3bSEitan Adler strcat(str, msg); 2903be6ef06SEitan Adler return(len - msglen); 2913be6ef06SEitan Adler } 2923be6ef06SEitan Adler 2933be6ef06SEitan Adler /* 2943be6ef06SEitan Adler * str_addarg(str, len, arg, first) - add the string argument "arg" to 2953be6ef06SEitan Adler * the string "str". This is the first in the group when "first" 2963be6ef06SEitan Adler * is set (indicating that a comma should NOT be added to the front). 2973be6ef06SEitan Adler */ 2983be6ef06SEitan Adler 2993be6ef06SEitan Adler static int 300d0bb69dcSEitan Adler str_addarg(char str[], int len, char arg[], bool first) 3013be6ef06SEitan Adler { 30298c299e0SEitan Adler int arglen; 3033be6ef06SEitan Adler 3043be6ef06SEitan Adler arglen = strlen(arg); 3053be6ef06SEitan Adler if (!first) 3063be6ef06SEitan Adler { 3073be6ef06SEitan Adler arglen += 2; 3083be6ef06SEitan Adler } 3093be6ef06SEitan Adler if (len <= arglen) 3103be6ef06SEitan Adler { 3113be6ef06SEitan Adler return(0); 3123be6ef06SEitan Adler } 3133be6ef06SEitan Adler if (!first) 3143be6ef06SEitan Adler { 315419fab3bSEitan Adler strcat(str, ", "); 3163be6ef06SEitan Adler } 317419fab3bSEitan Adler strcat(str, arg); 3183be6ef06SEitan Adler return(len - arglen); 3193be6ef06SEitan Adler } 3203be6ef06SEitan Adler 3213be6ef06SEitan Adler /* 3223be6ef06SEitan Adler * err_compar(p1, p2) - comparison routine used by "qsort" 3233be6ef06SEitan Adler * for sorting errors. 3243be6ef06SEitan Adler */ 3253be6ef06SEitan Adler 326b3c88c28SEitan Adler static int 327b3c88c28SEitan Adler err_compar(const void *p1, const void *p2) 3283be6ef06SEitan Adler { 32998c299e0SEitan Adler int result; 330a5ca08edSEitan Adler const struct errs * const g1 = (const struct errs * const)p1; 331a5ca08edSEitan Adler const struct errs * const g2 = (const struct errs * const)p2; 3323be6ef06SEitan Adler 333b3c88c28SEitan Adler 334b3c88c28SEitan Adler 335b3c88c28SEitan Adler if ((result = g1->errnum - g2->errnum) == 0) 3363be6ef06SEitan Adler { 337b3c88c28SEitan Adler return(strcmp(g1->arg, g2->arg)); 3383be6ef06SEitan Adler } 3393be6ef06SEitan Adler return(result); 3403be6ef06SEitan Adler } 3413be6ef06SEitan Adler 3423be6ef06SEitan Adler /* 3433be6ef06SEitan Adler * error_count() - return the number of errors currently logged. 3443be6ef06SEitan Adler */ 3453be6ef06SEitan Adler 3463be6ef06SEitan Adler int 347f6234b51SEitan Adler error_count(void) 3483be6ef06SEitan Adler { 3493be6ef06SEitan Adler return(errcnt); 3503be6ef06SEitan Adler } 3513be6ef06SEitan Adler 3523be6ef06SEitan Adler /* 3533be6ef06SEitan Adler * show_errors() - display on stdout the current log of errors. 3543be6ef06SEitan Adler */ 3553be6ef06SEitan Adler 3563be6ef06SEitan Adler void 357f6234b51SEitan Adler show_errors(void) 3583be6ef06SEitan Adler { 35998c299e0SEitan Adler int cnt = 0; 36098c299e0SEitan Adler struct errs *errp = errs; 3613be6ef06SEitan Adler 3623be6ef06SEitan Adler printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s"); 3633be6ef06SEitan Adler while (cnt++ < errcnt) 3643be6ef06SEitan Adler { 3653be6ef06SEitan Adler printf("%5s: %s\n", errp->arg, 366b3c88c28SEitan Adler errp->errnum == 0 ? "Not a number" : strerror(errp->errnum)); 3673be6ef06SEitan Adler errp++; 3683be6ef06SEitan Adler } 3693be6ef06SEitan Adler } 3703be6ef06SEitan Adler 371b26cf3d0SEitan Adler static const char no_proc_specified[] = " no processes specified"; 372b26cf3d0SEitan Adler static const char invalid_signal_number[] = " invalid_signal_number"; 373b26cf3d0SEitan Adler static const char bad_signal_name[] = " bad signal name"; 374b26cf3d0SEitan Adler static const char bad_pri_value[] = " bad priority value"; 3753c9ec0a5SEitan Adler 376561b0720SEitan Adler static int 377561b0720SEitan Adler signame_to_signum(const char * sig) 378561b0720SEitan Adler { 379561b0720SEitan Adler int n; 380561b0720SEitan Adler 381561b0720SEitan Adler if (strncasecmp(sig, "SIG", 3) == 0) 382561b0720SEitan Adler sig += 3; 383561b0720SEitan Adler for (n = 1; n < sys_nsig; n++) { 384561b0720SEitan Adler if (!strcasecmp(sys_signame[n], sig)) 385561b0720SEitan Adler return (n); 386561b0720SEitan Adler } 387561b0720SEitan Adler return (-1); 388561b0720SEitan Adler } 389561b0720SEitan Adler 3903be6ef06SEitan Adler /* 3913be6ef06SEitan Adler * kill_procs(str) - send signals to processes, much like the "kill" 3923be6ef06SEitan Adler * command does; invoked in response to 'k'. 3933be6ef06SEitan Adler */ 3943be6ef06SEitan Adler 395b26cf3d0SEitan Adler const char * 396b3c88c28SEitan Adler kill_procs(char *str) 3973be6ef06SEitan Adler { 39898c299e0SEitan Adler char *nptr; 3993be6ef06SEitan Adler int signum = SIGTERM; /* default */ 4003be6ef06SEitan Adler int procnum; 4013be6ef06SEitan Adler 4023be6ef06SEitan Adler /* reset error array */ 4033be6ef06SEitan Adler ERR_RESET; 4043be6ef06SEitan Adler 4053be6ef06SEitan Adler /* skip over leading white space */ 4063be6ef06SEitan Adler while (isspace(*str)) str++; 4073be6ef06SEitan Adler 4083be6ef06SEitan Adler if (str[0] == '-') 4093be6ef06SEitan Adler { 4103be6ef06SEitan Adler /* explicit signal specified */ 4113be6ef06SEitan Adler if ((nptr = next_field(str)) == NULL) 4123be6ef06SEitan Adler { 4133c9ec0a5SEitan Adler return(no_proc_specified); 4143be6ef06SEitan Adler } 4153be6ef06SEitan Adler 4163be6ef06SEitan Adler if (isdigit(str[1])) 4173be6ef06SEitan Adler { 418419fab3bSEitan Adler scanint(str + 1, &signum); 4193be6ef06SEitan Adler if (signum <= 0 || signum >= NSIG) 4203be6ef06SEitan Adler { 4213c9ec0a5SEitan Adler return(invalid_signal_number); 4223be6ef06SEitan Adler } 4233be6ef06SEitan Adler } 4243be6ef06SEitan Adler else 4253be6ef06SEitan Adler { 426561b0720SEitan Adler signum = signame_to_signum(str + 1); 4273be6ef06SEitan Adler 4283be6ef06SEitan Adler /* was it ever found */ 429561b0720SEitan Adler if (signum == -1 ) 4303be6ef06SEitan Adler { 4313c9ec0a5SEitan Adler return(bad_signal_name); 4323be6ef06SEitan Adler } 4333be6ef06SEitan Adler } 4343be6ef06SEitan Adler /* put the new pointer in place */ 4353be6ef06SEitan Adler str = nptr; 4363be6ef06SEitan Adler } 4373be6ef06SEitan Adler 4383be6ef06SEitan Adler /* loop thru the string, killing processes */ 4393be6ef06SEitan Adler do 4403be6ef06SEitan Adler { 4413be6ef06SEitan Adler if (scanint(str, &procnum) == -1) 4423be6ef06SEitan Adler { 4433be6ef06SEitan Adler ERROR(str, 0); 4443be6ef06SEitan Adler } 4453be6ef06SEitan Adler else 4463be6ef06SEitan Adler { 4473be6ef06SEitan Adler /* go in for the kill */ 448a0116099SEitan Adler if (kill(procnum, signum) == -1) 4493be6ef06SEitan Adler { 4503be6ef06SEitan Adler /* chalk up an error */ 4513be6ef06SEitan Adler ERROR(str, errno); 4523be6ef06SEitan Adler } 4533be6ef06SEitan Adler } 4543be6ef06SEitan Adler } while ((str = next_field(str)) != NULL); 4553be6ef06SEitan Adler 4563be6ef06SEitan Adler /* return appropriate error string */ 4573be6ef06SEitan Adler return(err_string()); 4583be6ef06SEitan Adler } 4593be6ef06SEitan Adler 4603be6ef06SEitan Adler /* 4613be6ef06SEitan Adler * renice_procs(str) - change the "nice" of processes, much like the 4623be6ef06SEitan Adler * "renice" command does; invoked in response to 'r'. 4633be6ef06SEitan Adler */ 4643be6ef06SEitan Adler 465b26cf3d0SEitan Adler const char * 466b3c88c28SEitan Adler renice_procs(char *str) 4673be6ef06SEitan Adler { 46898c299e0SEitan Adler char negate; 4693be6ef06SEitan Adler int prio; 4703be6ef06SEitan Adler int procnum; 4713be6ef06SEitan Adler 4723be6ef06SEitan Adler ERR_RESET; 4733be6ef06SEitan Adler 4743be6ef06SEitan Adler /* allow for negative priority values */ 4753be6ef06SEitan Adler if ((negate = (*str == '-')) != 0) 4763be6ef06SEitan Adler { 4773be6ef06SEitan Adler /* move past the minus sign */ 4783be6ef06SEitan Adler str++; 4793be6ef06SEitan Adler } 4803be6ef06SEitan Adler 4813be6ef06SEitan Adler /* use procnum as a temporary holding place and get the number */ 4823be6ef06SEitan Adler procnum = scanint(str, &prio); 4833be6ef06SEitan Adler 4843be6ef06SEitan Adler /* negate if necessary */ 4853be6ef06SEitan Adler if (negate) 4863be6ef06SEitan Adler { 4873be6ef06SEitan Adler prio = -prio; 4883be6ef06SEitan Adler } 4893be6ef06SEitan Adler 4903be6ef06SEitan Adler /* check for validity */ 4913be6ef06SEitan Adler if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX) 4923be6ef06SEitan Adler { 4933c9ec0a5SEitan Adler return(bad_pri_value); 4943be6ef06SEitan Adler } 4953be6ef06SEitan Adler 4963be6ef06SEitan Adler /* move to the first process number */ 4973be6ef06SEitan Adler if ((str = next_field(str)) == NULL) 4983be6ef06SEitan Adler { 4993c9ec0a5SEitan Adler return(no_proc_specified); 5003be6ef06SEitan Adler } 5013be6ef06SEitan Adler 5023be6ef06SEitan Adler /* loop thru the process numbers, renicing each one */ 5033be6ef06SEitan Adler do 5043be6ef06SEitan Adler { 5053be6ef06SEitan Adler if (scanint(str, &procnum) == -1) 5063be6ef06SEitan Adler { 5073be6ef06SEitan Adler ERROR(str, 0); 5083be6ef06SEitan Adler } 5093be6ef06SEitan Adler 510a0116099SEitan Adler if (setpriority(PRIO_PROCESS, procnum, prio) == -1) 5113be6ef06SEitan Adler { 5123be6ef06SEitan Adler ERROR(str, errno); 5133be6ef06SEitan Adler } 5143be6ef06SEitan Adler } while ((str = next_field(str)) != NULL); 5153be6ef06SEitan Adler 5163be6ef06SEitan Adler /* return appropriate error string */ 5173be6ef06SEitan Adler return(err_string()); 5183be6ef06SEitan Adler } 5193be6ef06SEitan Adler 520