xref: /freebsd/usr.bin/top/commands.c (revision 3be6ef06596a345558f15b91721a9021f3aeefba)
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