xref: /minix3/external/bsd/top/dist/commands.c (revision e1cdaee10649323af446eb1a74571984b2ab3181)
1b89261baSDavid van Moolenbroek /*
2b89261baSDavid van Moolenbroek  * Copyright (c) 1984 through 2008, William LeFebvre
3b89261baSDavid van Moolenbroek  * All rights reserved.
4b89261baSDavid van Moolenbroek  *
5b89261baSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6b89261baSDavid van Moolenbroek  * modification, are permitted provided that the following conditions are met:
7b89261baSDavid van Moolenbroek  *
8b89261baSDavid van Moolenbroek  *     * Redistributions of source code must retain the above copyright
9b89261baSDavid van Moolenbroek  * notice, this list of conditions and the following disclaimer.
10b89261baSDavid van Moolenbroek  *
11b89261baSDavid van Moolenbroek  *     * Redistributions in binary form must reproduce the above
12b89261baSDavid van Moolenbroek  * copyright notice, this list of conditions and the following disclaimer
13b89261baSDavid van Moolenbroek  * in the documentation and/or other materials provided with the
14b89261baSDavid van Moolenbroek  * distribution.
15b89261baSDavid van Moolenbroek  *
16b89261baSDavid van Moolenbroek  *     * Neither the name of William LeFebvre nor the names of other
17b89261baSDavid van Moolenbroek  * contributors may be used to endorse or promote products derived from
18b89261baSDavid van Moolenbroek  * this software without specific prior written permission.
19b89261baSDavid van Moolenbroek  *
20b89261baSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21b89261baSDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22b89261baSDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23b89261baSDavid van Moolenbroek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24b89261baSDavid van Moolenbroek  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25b89261baSDavid van Moolenbroek  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26b89261baSDavid van Moolenbroek  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27b89261baSDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28b89261baSDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29b89261baSDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30b89261baSDavid van Moolenbroek  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31b89261baSDavid van Moolenbroek  */
32b89261baSDavid van Moolenbroek 
33b89261baSDavid van Moolenbroek /*
34b89261baSDavid van Moolenbroek  *  Top users/processes display for Unix
35b89261baSDavid van Moolenbroek  *  Version 3
36b89261baSDavid van Moolenbroek  */
37b89261baSDavid van Moolenbroek 
38b89261baSDavid van Moolenbroek /*
39b89261baSDavid van Moolenbroek  *  This file contains the routines that implement some of the interactive
40b89261baSDavid van Moolenbroek  *  mode commands.  Note that some of the commands are implemented in-line
41b89261baSDavid van Moolenbroek  *  in "main".  This is necessary because they change the global state of
42b89261baSDavid van Moolenbroek  *  "top" (i.e.:  changing the number of processes to display).
43b89261baSDavid van Moolenbroek  */
44b89261baSDavid van Moolenbroek 
45b89261baSDavid van Moolenbroek #include "os.h"
46b89261baSDavid van Moolenbroek #include <ctype.h>
47b89261baSDavid van Moolenbroek #include <signal.h>
48b89261baSDavid van Moolenbroek #include <stdarg.h>
49b89261baSDavid van Moolenbroek #include <unistd.h>
50b89261baSDavid van Moolenbroek #include <color.h>
51b89261baSDavid van Moolenbroek #include <errno.h>
52b89261baSDavid van Moolenbroek #ifdef HAVE_SYS_RESOURCE_H
53b89261baSDavid van Moolenbroek #include <sys/resource.h>
54b89261baSDavid van Moolenbroek #endif
55b89261baSDavid van Moolenbroek 
56b89261baSDavid van Moolenbroek #if defined(HAVE_DECL_SYS_SIGLIST) & defined(HAVE_STRCASECMP)
57b89261baSDavid van Moolenbroek #define USE_SYS_SIGLIST
58b89261baSDavid van Moolenbroek #endif
59b89261baSDavid van Moolenbroek 
60b89261baSDavid van Moolenbroek #ifdef USE_SYS_SIGLIST
61b89261baSDavid van Moolenbroek extern const char * const sys_siglist[];
62b89261baSDavid van Moolenbroek extern const char * const sys_signame[];
63b89261baSDavid van Moolenbroek #else
64b89261baSDavid van Moolenbroek #include "sigdesc.h"		/* generated automatically */
65b89261baSDavid van Moolenbroek #endif
66b89261baSDavid van Moolenbroek #include "top.h"
67b89261baSDavid van Moolenbroek #include "machine.h"
68b89261baSDavid van Moolenbroek #include "globalstate.h"
69b89261baSDavid van Moolenbroek #include "boolean.h"
70b89261baSDavid van Moolenbroek #include "color.h"
71b89261baSDavid van Moolenbroek #include "commands.h"
72b89261baSDavid van Moolenbroek #include "display.h"
73b89261baSDavid van Moolenbroek #include "screen.h"
74b89261baSDavid van Moolenbroek #include "username.h"
75b89261baSDavid van Moolenbroek #include "utils.h"
76b89261baSDavid van Moolenbroek #include "version.h"
77b89261baSDavid van Moolenbroek 
78b89261baSDavid van Moolenbroek extern char *copyright;
79b89261baSDavid van Moolenbroek 
80b89261baSDavid van Moolenbroek typedef struct command {
81b89261baSDavid van Moolenbroek     int ch;
82b89261baSDavid van Moolenbroek     int (*cmd_func)(globalstate *);
83b89261baSDavid van Moolenbroek     const char *help;
84b89261baSDavid van Moolenbroek } command;
85b89261baSDavid van Moolenbroek 
86b89261baSDavid van Moolenbroek /*
87b89261baSDavid van Moolenbroek  *  Some of the commands make system calls that could generate errors.
88b89261baSDavid van Moolenbroek  *  These errors are collected up in an array of structures for later
89b89261baSDavid van Moolenbroek  *  contemplation and display.  Such routines return a string containing an
90b89261baSDavid van Moolenbroek  *  error message, or NULL if no errors occurred.  We need an upper limit on
91b89261baSDavid van Moolenbroek  *  the number of errors, so we arbitrarily choose 20.
92b89261baSDavid van Moolenbroek  */
93b89261baSDavid van Moolenbroek 
94b89261baSDavid van Moolenbroek #define ERRMAX 20
95b89261baSDavid van Moolenbroek 
96b89261baSDavid van Moolenbroek struct errs		/* structure for a system-call error */
97b89261baSDavid van Moolenbroek {
98b89261baSDavid van Moolenbroek     int  errnum;	/* value of errno (that is, the actual error) */
99b89261baSDavid van Moolenbroek     char *arg;		/* argument that caused the error */
100b89261baSDavid van Moolenbroek };
101b89261baSDavid van Moolenbroek 
102b89261baSDavid van Moolenbroek static struct errs errs[ERRMAX];
103b89261baSDavid van Moolenbroek static int errcnt;
104b89261baSDavid van Moolenbroek 
105b89261baSDavid van Moolenbroek /* These macros get used to reset and log the errors */
106b89261baSDavid van Moolenbroek #define ERR_RESET   errcnt = 0
107b89261baSDavid van Moolenbroek #define ERROR(p, e) if (errcnt < ERRMAX) \
108b89261baSDavid van Moolenbroek 		    { \
109b89261baSDavid van Moolenbroek 			errs[errcnt].arg = (p); \
110b89261baSDavid van Moolenbroek 			errs[errcnt++].errnum = (e); \
111b89261baSDavid van Moolenbroek 		    }
112b89261baSDavid van Moolenbroek 
113b89261baSDavid van Moolenbroek /*
114b89261baSDavid van Moolenbroek  *  err_compar(p1, p2) - comparison routine used by "qsort"
115b89261baSDavid van Moolenbroek  *	for sorting errors.
116b89261baSDavid van Moolenbroek  */
117b89261baSDavid van Moolenbroek 
118b89261baSDavid van Moolenbroek static int
err_compar(const void * p1,const void * p2)119b89261baSDavid van Moolenbroek err_compar(const void *p1, const void *p2)
120b89261baSDavid van Moolenbroek 
121b89261baSDavid van Moolenbroek {
122b89261baSDavid van Moolenbroek     register int result;
123b89261baSDavid van Moolenbroek 
124b89261baSDavid van Moolenbroek     if ((result = ((const struct errs *)p1)->errnum -
125b89261baSDavid van Moolenbroek 	 ((const struct errs *)p2)->errnum) == 0)
126b89261baSDavid van Moolenbroek     {
127b89261baSDavid van Moolenbroek 	return(strcmp(((const struct errs *)p1)->arg,
128b89261baSDavid van Moolenbroek 		      ((const struct errs *)p2)->arg));
129b89261baSDavid van Moolenbroek     }
130b89261baSDavid van Moolenbroek     return(result);
131b89261baSDavid van Moolenbroek }
132b89261baSDavid van Moolenbroek 
133b89261baSDavid van Moolenbroek /*
134b89261baSDavid van Moolenbroek  *  str_adderr(str, len, err) - add an explanation of error "err" to
135b89261baSDavid van Moolenbroek  *	the string "str" without overflowing length "len".  return
136b89261baSDavid van Moolenbroek  *      number of characters remaining in str, or 0 if overflowed.
137b89261baSDavid van Moolenbroek  */
138b89261baSDavid van Moolenbroek 
139b89261baSDavid van Moolenbroek static int
str_adderr(char * str,int len,int err)140b89261baSDavid van Moolenbroek str_adderr(char *str, int len, int err)
141b89261baSDavid van Moolenbroek 
142b89261baSDavid van Moolenbroek {
143b89261baSDavid van Moolenbroek     register const char *msg;
144b89261baSDavid van Moolenbroek     register int  msglen;
145b89261baSDavid van Moolenbroek 
146b89261baSDavid van Moolenbroek     msg = err == 0 ? "Not a number" : errmsg(err);
147b89261baSDavid van Moolenbroek     msglen = strlen(msg) + 2;
148b89261baSDavid van Moolenbroek     if (len <= msglen)
149b89261baSDavid van Moolenbroek     {
150b89261baSDavid van Moolenbroek 	return(0);
151b89261baSDavid van Moolenbroek     }
152b89261baSDavid van Moolenbroek     (void) strcat(str, ": ");
153b89261baSDavid van Moolenbroek     (void) strcat(str, msg);
154b89261baSDavid van Moolenbroek     return(len - msglen);
155b89261baSDavid van Moolenbroek }
156b89261baSDavid van Moolenbroek 
157b89261baSDavid van Moolenbroek /*
158b89261baSDavid van Moolenbroek  *  str_addarg(str, len, arg, first) - add the string argument "arg" to
159b89261baSDavid van Moolenbroek  *	the string "str" without overflowing length "len".  This is the
160b89261baSDavid van Moolenbroek  *      first in the group when "first" is set (indicating that a comma
161b89261baSDavid van Moolenbroek  *      should NOT be added to the front).  Return number of characters
162b89261baSDavid van Moolenbroek  *      remaining in str, or 0 if overflowed.
163b89261baSDavid van Moolenbroek  */
164b89261baSDavid van Moolenbroek 
165b89261baSDavid van Moolenbroek static int
str_addarg(char * str,int len,char * arg,int first)166b89261baSDavid van Moolenbroek str_addarg(char *str, int len, char *arg, int first)
167b89261baSDavid van Moolenbroek 
168b89261baSDavid van Moolenbroek {
169b89261baSDavid van Moolenbroek     register int arglen;
170b89261baSDavid van Moolenbroek 
171b89261baSDavid van Moolenbroek     arglen = strlen(arg);
172b89261baSDavid van Moolenbroek     if (!first)
173b89261baSDavid van Moolenbroek     {
174b89261baSDavid van Moolenbroek 	arglen += 2;
175b89261baSDavid van Moolenbroek     }
176b89261baSDavid van Moolenbroek     if (len <= arglen)
177b89261baSDavid van Moolenbroek     {
178b89261baSDavid van Moolenbroek 	return(0);
179b89261baSDavid van Moolenbroek     }
180b89261baSDavid van Moolenbroek     if (!first)
181b89261baSDavid van Moolenbroek     {
182b89261baSDavid van Moolenbroek 	(void) strcat(str, ", ");
183b89261baSDavid van Moolenbroek     }
184b89261baSDavid van Moolenbroek     (void) strcat(str, arg);
185b89261baSDavid van Moolenbroek     return(len - arglen);
186b89261baSDavid van Moolenbroek }
187b89261baSDavid van Moolenbroek 
188b89261baSDavid van Moolenbroek /*
189b89261baSDavid van Moolenbroek  * void err_string()
190b89261baSDavid van Moolenbroek  *
191b89261baSDavid van Moolenbroek  * Use message_error to log errors in the errs array.  This function
192b89261baSDavid van Moolenbroek  * will combine identical errors to make the message short, but if
193b89261baSDavid van Moolenbroek  * there is more than one type of error it will call message_error
194b89261baSDavid van Moolenbroek  * for each one.
195b89261baSDavid van Moolenbroek  */
196b89261baSDavid van Moolenbroek 
197b89261baSDavid van Moolenbroek #define STRMAX 80
198b89261baSDavid van Moolenbroek 
199b89261baSDavid van Moolenbroek static void
err_string(void)200b89261baSDavid van Moolenbroek err_string(void)
201b89261baSDavid van Moolenbroek 
202b89261baSDavid van Moolenbroek {
203b89261baSDavid van Moolenbroek     register struct errs *errp;
204b89261baSDavid van Moolenbroek     register int  cnt = 0;
205b89261baSDavid van Moolenbroek     register int  first = Yes;
206b89261baSDavid van Moolenbroek     register int  currerr = -1;
207b89261baSDavid van Moolenbroek     int stringlen = 0;		/* characters still available in "string" */
208b89261baSDavid van Moolenbroek     char string[STRMAX];
209b89261baSDavid van Moolenbroek 
210b89261baSDavid van Moolenbroek     /* if there are no errors, our job is easy */
211b89261baSDavid van Moolenbroek     if (errcnt == 0)
212b89261baSDavid van Moolenbroek     {
213b89261baSDavid van Moolenbroek 	return;
214b89261baSDavid van Moolenbroek     }
215b89261baSDavid van Moolenbroek 
216b89261baSDavid van Moolenbroek     /* sort the errors */
217b89261baSDavid van Moolenbroek     qsort((char *)errs, errcnt, sizeof(struct errs), err_compar);
218b89261baSDavid van Moolenbroek 
219b89261baSDavid van Moolenbroek     /* initialize the buffer (probably not necessary) */
220b89261baSDavid van Moolenbroek     string[0] = '\0';
221b89261baSDavid van Moolenbroek     stringlen = STRMAX - 1;
222b89261baSDavid van Moolenbroek 
223b89261baSDavid van Moolenbroek     /* loop thru the sorted list, logging errors */
224b89261baSDavid van Moolenbroek     while (cnt < errcnt)
225b89261baSDavid van Moolenbroek     {
226b89261baSDavid van Moolenbroek 	/* point to the current error */
227b89261baSDavid van Moolenbroek 	errp = &(errs[cnt++]);
228b89261baSDavid van Moolenbroek 
229b89261baSDavid van Moolenbroek 	/* note that on overflow "stringlen" will become 0 and all
230b89261baSDavid van Moolenbroek 	   subsequent calls to str_addarg or str_adderr will return 0 */
231b89261baSDavid van Moolenbroek 
232b89261baSDavid van Moolenbroek 	/* if the error number is different then add the error string */
233b89261baSDavid van Moolenbroek 	if (errp->errnum != currerr)
234b89261baSDavid van Moolenbroek 	{
235b89261baSDavid van Moolenbroek 	    if (currerr != -1)
236b89261baSDavid van Moolenbroek 	    {
237b89261baSDavid van Moolenbroek 		/* add error string and log the error */
238b89261baSDavid van Moolenbroek 		stringlen = str_adderr(string, stringlen, currerr);
239b89261baSDavid van Moolenbroek 		message_error(" %s", string);
240b89261baSDavid van Moolenbroek 
241b89261baSDavid van Moolenbroek 	    }
242b89261baSDavid van Moolenbroek 	    /* reset the buffer */
243b89261baSDavid van Moolenbroek 	    string[0] = '\0';
244b89261baSDavid van Moolenbroek 	    stringlen = STRMAX - 1;
245b89261baSDavid van Moolenbroek 
246b89261baSDavid van Moolenbroek 	    /* move to next error num */
247b89261baSDavid van Moolenbroek 	    currerr = errp->errnum;
248b89261baSDavid van Moolenbroek 	    first = Yes;
249b89261baSDavid van Moolenbroek 	}
250b89261baSDavid van Moolenbroek 
251b89261baSDavid van Moolenbroek 	/* add this arg */
252b89261baSDavid van Moolenbroek 	stringlen = str_addarg(string, stringlen, errp->arg, first);
253b89261baSDavid van Moolenbroek 	first = No;
254b89261baSDavid van Moolenbroek     }
255b89261baSDavid van Moolenbroek 
256b89261baSDavid van Moolenbroek     /* add final message */
257b89261baSDavid van Moolenbroek     stringlen = str_adderr(string, stringlen, currerr);
258b89261baSDavid van Moolenbroek 
259b89261baSDavid van Moolenbroek     /* write the error string */
260b89261baSDavid van Moolenbroek     message_error(" %s", string);
261b89261baSDavid van Moolenbroek }
262b89261baSDavid van Moolenbroek 
263b89261baSDavid van Moolenbroek /*
264b89261baSDavid van Moolenbroek  *  Utility routines that help with some of the commands.
265b89261baSDavid van Moolenbroek  */
266b89261baSDavid van Moolenbroek 
267b89261baSDavid van Moolenbroek static char *
next_field(char * str)268b89261baSDavid van Moolenbroek next_field(char *str)
269b89261baSDavid van Moolenbroek 
270b89261baSDavid van Moolenbroek 
271b89261baSDavid van Moolenbroek {
272b89261baSDavid van Moolenbroek     if ((str = strchr(str, ' ')) == NULL)
273b89261baSDavid van Moolenbroek     {
274b89261baSDavid van Moolenbroek 	return(NULL);
275b89261baSDavid van Moolenbroek     }
276b89261baSDavid van Moolenbroek     *str = '\0';
277b89261baSDavid van Moolenbroek     while (*++str == ' ') /* loop */;
278b89261baSDavid van Moolenbroek 
279b89261baSDavid van Moolenbroek     /* if there is nothing left of the string, return NULL */
280b89261baSDavid van Moolenbroek     /* This fix is dedicated to Greg Earle */
281b89261baSDavid van Moolenbroek     return(*str == '\0' ? NULL : str);
282b89261baSDavid van Moolenbroek }
283b89261baSDavid van Moolenbroek 
284b89261baSDavid van Moolenbroek static int
scanint(char * str,int * intp)285b89261baSDavid van Moolenbroek scanint(char *str, int *intp)
286b89261baSDavid van Moolenbroek 
287b89261baSDavid van Moolenbroek {
288b89261baSDavid van Moolenbroek     register int val = 0;
289b89261baSDavid van Moolenbroek     register int ch;
290b89261baSDavid van Moolenbroek 
291b89261baSDavid van Moolenbroek     /* if there is nothing left of the string, flag it as an error */
292b89261baSDavid van Moolenbroek     /* This fix is dedicated to Greg Earle */
293b89261baSDavid van Moolenbroek     if (*str == '\0')
294b89261baSDavid van Moolenbroek     {
295b89261baSDavid van Moolenbroek 	return(-1);
296b89261baSDavid van Moolenbroek     }
297b89261baSDavid van Moolenbroek 
298b89261baSDavid van Moolenbroek     while ((ch = *str++) != '\0')
299b89261baSDavid van Moolenbroek     {
300b89261baSDavid van Moolenbroek 	if (isdigit(ch))
301b89261baSDavid van Moolenbroek 	{
302b89261baSDavid van Moolenbroek 	    val = val * 10 + (ch - '0');
303b89261baSDavid van Moolenbroek 	}
304b89261baSDavid van Moolenbroek 	else if (isspace(ch))
305b89261baSDavid van Moolenbroek 	{
306b89261baSDavid van Moolenbroek 	    break;
307b89261baSDavid van Moolenbroek 	}
308b89261baSDavid van Moolenbroek 	else
309b89261baSDavid van Moolenbroek 	{
310b89261baSDavid van Moolenbroek 	    return(-1);
311b89261baSDavid van Moolenbroek 	}
312b89261baSDavid van Moolenbroek     }
313b89261baSDavid van Moolenbroek     *intp = val;
314b89261baSDavid van Moolenbroek     return(0);
315b89261baSDavid van Moolenbroek }
316b89261baSDavid van Moolenbroek 
317b89261baSDavid van Moolenbroek #ifdef notdef
318b89261baSDavid van Moolenbroek /*
319b89261baSDavid van Moolenbroek  *  error_count() - return the number of errors currently logged.
320b89261baSDavid van Moolenbroek  */
321b89261baSDavid van Moolenbroek 
322b89261baSDavid van Moolenbroek static int
error_count(void)323b89261baSDavid van Moolenbroek error_count(void)
324b89261baSDavid van Moolenbroek 
325b89261baSDavid van Moolenbroek {
326b89261baSDavid van Moolenbroek     return(errcnt);
327b89261baSDavid van Moolenbroek }
328b89261baSDavid van Moolenbroek 
329b89261baSDavid van Moolenbroek /*
330b89261baSDavid van Moolenbroek  *  show_errors() - display on stdout the current log of errors.
331b89261baSDavid van Moolenbroek  */
332b89261baSDavid van Moolenbroek 
333b89261baSDavid van Moolenbroek static void
show_errors(void)334b89261baSDavid van Moolenbroek show_errors(void)
335b89261baSDavid van Moolenbroek 
336b89261baSDavid van Moolenbroek {
337b89261baSDavid van Moolenbroek     register int cnt = 0;
338b89261baSDavid van Moolenbroek     register struct errs *errp = errs;
339b89261baSDavid van Moolenbroek 
340b89261baSDavid van Moolenbroek     printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
341b89261baSDavid van Moolenbroek     while (cnt++ < errcnt)
342b89261baSDavid van Moolenbroek     {
343b89261baSDavid van Moolenbroek 	printf("%5s: %s\n", errp->arg,
344b89261baSDavid van Moolenbroek 	    errp->errnum == 0 ? "Not a number" : errmsg(errp->errnum));
345b89261baSDavid van Moolenbroek 	errp++;
346b89261baSDavid van Moolenbroek     }
347b89261baSDavid van Moolenbroek }
348b89261baSDavid van Moolenbroek #endif
349b89261baSDavid van Moolenbroek 
350b89261baSDavid van Moolenbroek /*
351b89261baSDavid van Moolenbroek  *  kill_procs(str) - send signals to processes, much like the "kill"
352b89261baSDavid van Moolenbroek  *		command does; invoked in response to 'k'.
353b89261baSDavid van Moolenbroek  */
354b89261baSDavid van Moolenbroek 
355b89261baSDavid van Moolenbroek static void
kill_procs(char * str)356b89261baSDavid van Moolenbroek kill_procs(char *str)
357b89261baSDavid van Moolenbroek 
358b89261baSDavid van Moolenbroek {
359b89261baSDavid van Moolenbroek     register char *nptr;
360b89261baSDavid van Moolenbroek     int signum = SIGTERM;	/* default */
361b89261baSDavid van Moolenbroek     int procnum;
362b89261baSDavid van Moolenbroek     int uid;
363b89261baSDavid van Moolenbroek     int owner;
364b89261baSDavid van Moolenbroek #ifndef USE_SYS_SIGLIST
365b89261baSDavid van Moolenbroek     struct sigdesc *sigp;
366b89261baSDavid van Moolenbroek #endif
367b89261baSDavid van Moolenbroek 
368b89261baSDavid van Moolenbroek     /* reset error array */
369b89261baSDavid van Moolenbroek     ERR_RESET;
370b89261baSDavid van Moolenbroek 
371b89261baSDavid van Moolenbroek     /* remember our uid */
372b89261baSDavid van Moolenbroek     uid = getuid();
373b89261baSDavid van Moolenbroek 
374b89261baSDavid van Moolenbroek     /* skip over leading white space */
375b89261baSDavid van Moolenbroek     while (isspace((int)*str)) str++;
376b89261baSDavid van Moolenbroek 
377b89261baSDavid van Moolenbroek     if (str[0] == '-')
378b89261baSDavid van Moolenbroek     {
379b89261baSDavid van Moolenbroek 	/* explicit signal specified */
380b89261baSDavid van Moolenbroek 	if ((nptr = next_field(str)) == NULL)
381b89261baSDavid van Moolenbroek 	{
382b89261baSDavid van Moolenbroek 	    message_error(" kill: no processes specified");
383b89261baSDavid van Moolenbroek 	    return;
384b89261baSDavid van Moolenbroek 	}
385b89261baSDavid van Moolenbroek 
386b89261baSDavid van Moolenbroek 	str++;
387b89261baSDavid van Moolenbroek 	if (isdigit((int)str[0]))
388b89261baSDavid van Moolenbroek 	{
389b89261baSDavid van Moolenbroek 	    (void) scanint(str, &signum);
390b89261baSDavid van Moolenbroek 	    if (signum <= 0 || signum >= NSIG)
391b89261baSDavid van Moolenbroek 	    {
392b89261baSDavid van Moolenbroek 		message_error(" kill: invalid signal number");
393b89261baSDavid van Moolenbroek 		return;
394b89261baSDavid van Moolenbroek 	    }
395b89261baSDavid van Moolenbroek 	}
396b89261baSDavid van Moolenbroek 	else
397b89261baSDavid van Moolenbroek 	{
398b89261baSDavid van Moolenbroek 	    /* translate the name into a number */
399b89261baSDavid van Moolenbroek #ifdef USE_SYS_SIGLIST
400b89261baSDavid van Moolenbroek 	    for (signum = 1; signum < NSIG; signum++)
401b89261baSDavid van Moolenbroek 	    {
402b89261baSDavid van Moolenbroek 		if (strcasecmp(sys_signame[signum], str) == 0)
403b89261baSDavid van Moolenbroek 		{
404b89261baSDavid van Moolenbroek 		    break;
405b89261baSDavid van Moolenbroek 		}
406b89261baSDavid van Moolenbroek 	    }
407b89261baSDavid van Moolenbroek 	    if (signum == NSIG)
408b89261baSDavid van Moolenbroek 	    {
409b89261baSDavid van Moolenbroek 		message_error(" kill: bad signal name");
410b89261baSDavid van Moolenbroek 		return;
411b89261baSDavid van Moolenbroek 	    }
412b89261baSDavid van Moolenbroek #else
413b89261baSDavid van Moolenbroek 	    for (sigp = sigdesc; sigp->name != NULL; sigp++)
414b89261baSDavid van Moolenbroek 	    {
415b89261baSDavid van Moolenbroek #ifdef HAVE_STRCASECMP
416b89261baSDavid van Moolenbroek 		if (strcasecmp(sigp->name, str) == 0)
417b89261baSDavid van Moolenbroek #else
418b89261baSDavid van Moolenbroek 		if (strcmp(sigp->name, str) == 0)
419b89261baSDavid van Moolenbroek #endif
420b89261baSDavid van Moolenbroek 		{
421b89261baSDavid van Moolenbroek 		    signum = sigp->number;
422b89261baSDavid van Moolenbroek 		    break;
423b89261baSDavid van Moolenbroek 		}
424b89261baSDavid van Moolenbroek 	    }
425b89261baSDavid van Moolenbroek 
426b89261baSDavid van Moolenbroek 	    /* was it ever found */
427b89261baSDavid van Moolenbroek 	    if (sigp->name == NULL)
428b89261baSDavid van Moolenbroek 	    {
429b89261baSDavid van Moolenbroek 		message_error(" kill: bad signal name");
430b89261baSDavid van Moolenbroek 		return;
431b89261baSDavid van Moolenbroek 	    }
432b89261baSDavid van Moolenbroek #endif
433b89261baSDavid van Moolenbroek 	}
434b89261baSDavid van Moolenbroek 	/* put the new pointer in place */
435b89261baSDavid van Moolenbroek 	str = nptr;
436b89261baSDavid van Moolenbroek     }
437b89261baSDavid van Moolenbroek 
438b89261baSDavid van Moolenbroek     /* loop thru the string, killing processes */
439b89261baSDavid van Moolenbroek     do
440b89261baSDavid van Moolenbroek     {
441b89261baSDavid van Moolenbroek 	if (scanint(str, &procnum) == -1)
442b89261baSDavid van Moolenbroek 	{
443b89261baSDavid van Moolenbroek 	    ERROR(str, 0);
444b89261baSDavid van Moolenbroek 	}
445b89261baSDavid van Moolenbroek 	else
446b89261baSDavid van Moolenbroek 	{
447b89261baSDavid van Moolenbroek 	    /* check process owner if we're not root */
448b89261baSDavid van Moolenbroek 	    owner = proc_owner(procnum);
449b89261baSDavid van Moolenbroek 	    if (uid && (uid != owner))
450b89261baSDavid van Moolenbroek 	    {
451b89261baSDavid van Moolenbroek 		ERROR(str, owner == -1 ? ESRCH : EACCES);
452b89261baSDavid van Moolenbroek 	    }
453b89261baSDavid van Moolenbroek 	    /* go in for the kill */
454b89261baSDavid van Moolenbroek 	    else if (kill(procnum, signum) == -1)
455b89261baSDavid van Moolenbroek 	    {
456b89261baSDavid van Moolenbroek 		/* chalk up an error */
457b89261baSDavid van Moolenbroek 		ERROR(str, errno);
458b89261baSDavid van Moolenbroek 	    }
459b89261baSDavid van Moolenbroek 	}
460b89261baSDavid van Moolenbroek     } while ((str = next_field(str)) != NULL);
461b89261baSDavid van Moolenbroek 
462b89261baSDavid van Moolenbroek     /* process errors */
463b89261baSDavid van Moolenbroek     err_string();
464b89261baSDavid van Moolenbroek }
465b89261baSDavid van Moolenbroek 
466b89261baSDavid van Moolenbroek /*
467b89261baSDavid van Moolenbroek  *  renice_procs(str) - change the "nice" of processes, much like the
468b89261baSDavid van Moolenbroek  *		"renice" command does; invoked in response to 'r'.
469b89261baSDavid van Moolenbroek  */
470b89261baSDavid van Moolenbroek 
471b89261baSDavid van Moolenbroek static void
renice_procs(char * str)472b89261baSDavid van Moolenbroek renice_procs(char *str)
473b89261baSDavid van Moolenbroek 
474b89261baSDavid van Moolenbroek {
475b89261baSDavid van Moolenbroek     register char negate;
476b89261baSDavid van Moolenbroek     int prio;
477b89261baSDavid van Moolenbroek     int procnum;
478b89261baSDavid van Moolenbroek     int uid;
479b89261baSDavid van Moolenbroek 
480*e1cdaee1SLionel Sambuc #if defined(__minix)
481*e1cdaee1SLionel Sambuc     /* LSC: -Werror=maybe-uninitialized while compiling with -O3. */
482*e1cdaee1SLionel Sambuc     prio = 0;
483*e1cdaee1SLionel Sambuc #endif /* defined(__minix) */
484b89261baSDavid van Moolenbroek     ERR_RESET;
485b89261baSDavid van Moolenbroek     uid = getuid();
486b89261baSDavid van Moolenbroek 
487b89261baSDavid van Moolenbroek     /* allow for negative priority values */
488b89261baSDavid van Moolenbroek     if ((negate = (*str == '-')) != 0)
489b89261baSDavid van Moolenbroek     {
490b89261baSDavid van Moolenbroek 	/* move past the minus sign */
491b89261baSDavid van Moolenbroek 	str++;
492b89261baSDavid van Moolenbroek     }
493b89261baSDavid van Moolenbroek 
494b89261baSDavid van Moolenbroek     /* use procnum as a temporary holding place and get the number */
495b89261baSDavid van Moolenbroek     procnum = scanint(str, &prio);
496b89261baSDavid van Moolenbroek 
497b89261baSDavid van Moolenbroek     /* negate if necessary */
498b89261baSDavid van Moolenbroek     if (negate)
499b89261baSDavid van Moolenbroek     {
500b89261baSDavid van Moolenbroek 	prio = -prio;
501b89261baSDavid van Moolenbroek     }
502b89261baSDavid van Moolenbroek 
503b89261baSDavid van Moolenbroek #if defined(PRIO_MIN) && defined(PRIO_MAX)
504b89261baSDavid van Moolenbroek     /* check for validity */
505b89261baSDavid van Moolenbroek     if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX)
506b89261baSDavid van Moolenbroek     {
507b89261baSDavid van Moolenbroek 	message_error(" renice: bad priority value");
508b89261baSDavid van Moolenbroek 	return;
509b89261baSDavid van Moolenbroek     }
510b89261baSDavid van Moolenbroek #endif
511b89261baSDavid van Moolenbroek 
512b89261baSDavid van Moolenbroek     /* move to the first process number */
513b89261baSDavid van Moolenbroek     if ((str = next_field(str)) == NULL)
514b89261baSDavid van Moolenbroek     {
515b89261baSDavid van Moolenbroek 	message_error(" remice: no processes specified");
516b89261baSDavid van Moolenbroek 	return;
517b89261baSDavid van Moolenbroek     }
518b89261baSDavid van Moolenbroek 
519b89261baSDavid van Moolenbroek #ifdef HAVE_SETPRIORITY
520b89261baSDavid van Moolenbroek     /* loop thru the process numbers, renicing each one */
521b89261baSDavid van Moolenbroek     do
522b89261baSDavid van Moolenbroek     {
523b89261baSDavid van Moolenbroek 	if (scanint(str, &procnum) == -1)
524b89261baSDavid van Moolenbroek 	{
525b89261baSDavid van Moolenbroek 	    ERROR(str, 0);
526b89261baSDavid van Moolenbroek 	}
527b89261baSDavid van Moolenbroek 
528b89261baSDavid van Moolenbroek 	/* check process owner if we're not root */
529b89261baSDavid van Moolenbroek 	else if (uid && (uid != proc_owner(procnum)))
530b89261baSDavid van Moolenbroek 	{
531b89261baSDavid van Moolenbroek 	    ERROR(str, EACCES);
532b89261baSDavid van Moolenbroek 	}
533b89261baSDavid van Moolenbroek 	else if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
534b89261baSDavid van Moolenbroek 	{
535b89261baSDavid van Moolenbroek 	    ERROR(str, errno);
536b89261baSDavid van Moolenbroek 	}
537b89261baSDavid van Moolenbroek     } while ((str = next_field(str)) != NULL);
538b89261baSDavid van Moolenbroek     err_string();
539b89261baSDavid van Moolenbroek #else
540b89261baSDavid van Moolenbroek     message_error(" renice operation not supported");
541b89261baSDavid van Moolenbroek #endif
542b89261baSDavid van Moolenbroek }
543b89261baSDavid van Moolenbroek 
544b89261baSDavid van Moolenbroek /* COMMAND ROUTINES */
545b89261baSDavid van Moolenbroek 
546b89261baSDavid van Moolenbroek /*
547b89261baSDavid van Moolenbroek  * Each command routine is called by command_process and is passed a
548b89261baSDavid van Moolenbroek  * pointer to the current global state.  Command routines are free
549b89261baSDavid van Moolenbroek  * to change anything in the global state, although changes to the
550b89261baSDavid van Moolenbroek  * statics structure are discouraged.  Whatever a command routine
551b89261baSDavid van Moolenbroek  * returns will be returned by command_process.
552b89261baSDavid van Moolenbroek  */
553b89261baSDavid van Moolenbroek 
554b89261baSDavid van Moolenbroek static void
cmd_quit(globalstate * gstate)555b89261baSDavid van Moolenbroek cmd_quit(globalstate *gstate)
556b89261baSDavid van Moolenbroek 
557b89261baSDavid van Moolenbroek {
558b89261baSDavid van Moolenbroek     quit(EX_OK);
559b89261baSDavid van Moolenbroek     /*NOTREACHED*/
560b89261baSDavid van Moolenbroek }
561b89261baSDavid van Moolenbroek 
562b89261baSDavid van Moolenbroek static int
cmd_update(globalstate * gstate)563b89261baSDavid van Moolenbroek cmd_update(globalstate *gstate)
564b89261baSDavid van Moolenbroek 
565b89261baSDavid van Moolenbroek {
566b89261baSDavid van Moolenbroek     /* go home for visual feedback */
567b89261baSDavid van Moolenbroek     screen_home();
568b89261baSDavid van Moolenbroek     fflush(stdout);
569b89261baSDavid van Moolenbroek     message_expire();
570b89261baSDavid van Moolenbroek     return CMD_REFRESH;
571b89261baSDavid van Moolenbroek }
572b89261baSDavid van Moolenbroek 
573b89261baSDavid van Moolenbroek static int
cmd_redraw(globalstate * gstate)574b89261baSDavid van Moolenbroek cmd_redraw(globalstate *gstate)
575b89261baSDavid van Moolenbroek 
576b89261baSDavid van Moolenbroek {
577b89261baSDavid van Moolenbroek     gstate->fulldraw = Yes;
578b89261baSDavid van Moolenbroek     return CMD_REFRESH;
579b89261baSDavid van Moolenbroek }
580b89261baSDavid van Moolenbroek 
581b89261baSDavid van Moolenbroek static int
cmd_color(globalstate * gstate)582b89261baSDavid van Moolenbroek cmd_color(globalstate *gstate)
583b89261baSDavid van Moolenbroek 
584b89261baSDavid van Moolenbroek {
585b89261baSDavid van Moolenbroek     gstate->use_color = color_activate(-1);
586b89261baSDavid van Moolenbroek     gstate->fulldraw = Yes;
587b89261baSDavid van Moolenbroek     return CMD_REFRESH;
588b89261baSDavid van Moolenbroek }
589b89261baSDavid van Moolenbroek 
590b89261baSDavid van Moolenbroek static int
cmd_number(globalstate * gstate)591b89261baSDavid van Moolenbroek cmd_number(globalstate *gstate)
592b89261baSDavid van Moolenbroek 
593b89261baSDavid van Moolenbroek {
594b89261baSDavid van Moolenbroek     int newval;
595b89261baSDavid van Moolenbroek     char tmpbuf[20];
596b89261baSDavid van Moolenbroek 
597b89261baSDavid van Moolenbroek     message_prompt("Number of processes to show: ");
598b89261baSDavid van Moolenbroek     newval = readline(tmpbuf, 8, Yes);
599b89261baSDavid van Moolenbroek     if (newval > -1)
600b89261baSDavid van Moolenbroek     {
601b89261baSDavid van Moolenbroek 	if (newval > gstate->max_topn)
602b89261baSDavid van Moolenbroek 	{
603b89261baSDavid van Moolenbroek 	    message_error(" This terminal can only display %d processes",
604b89261baSDavid van Moolenbroek 			  gstate->max_topn);
605b89261baSDavid van Moolenbroek 	}
606b89261baSDavid van Moolenbroek 
607b89261baSDavid van Moolenbroek 	if (newval == 0)
608b89261baSDavid van Moolenbroek 	{
609b89261baSDavid van Moolenbroek 	    /* inhibit the header */
610b89261baSDavid van Moolenbroek 	    display_header(No);
611b89261baSDavid van Moolenbroek 	}
612b89261baSDavid van Moolenbroek 
613b89261baSDavid van Moolenbroek 	else if (gstate->topn == 0)
614b89261baSDavid van Moolenbroek 	{
615b89261baSDavid van Moolenbroek 	    display_header(Yes);
616b89261baSDavid van Moolenbroek 	}
617b89261baSDavid van Moolenbroek 
618b89261baSDavid van Moolenbroek 	gstate->topn = newval;
619b89261baSDavid van Moolenbroek     }
620b89261baSDavid van Moolenbroek     return CMD_REFRESH;
621b89261baSDavid van Moolenbroek }
622b89261baSDavid van Moolenbroek 
623b89261baSDavid van Moolenbroek static int
cmd_delay(globalstate * gstate)624b89261baSDavid van Moolenbroek cmd_delay(globalstate *gstate)
625b89261baSDavid van Moolenbroek 
626b89261baSDavid van Moolenbroek {
627b89261baSDavid van Moolenbroek     double newval;
628b89261baSDavid van Moolenbroek     char tmpbuf[20];
629b89261baSDavid van Moolenbroek 
630b89261baSDavid van Moolenbroek     message_prompt("Seconds to delay: ");
631b89261baSDavid van Moolenbroek     if (readline(tmpbuf, 8, No) > 0)
632b89261baSDavid van Moolenbroek     {
633b89261baSDavid van Moolenbroek 	newval = atof(tmpbuf);
634b89261baSDavid van Moolenbroek 	if (newval == 0 && getuid() != 0)
635b89261baSDavid van Moolenbroek 	{
636b89261baSDavid van Moolenbroek 	    gstate->delay = 1;
637b89261baSDavid van Moolenbroek 	}
638b89261baSDavid van Moolenbroek 	else
639b89261baSDavid van Moolenbroek 	{
640b89261baSDavid van Moolenbroek 	    gstate->delay = newval;
641b89261baSDavid van Moolenbroek 	}
642b89261baSDavid van Moolenbroek     }
643b89261baSDavid van Moolenbroek     return CMD_REFRESH;
644b89261baSDavid van Moolenbroek }
645b89261baSDavid van Moolenbroek 
646b89261baSDavid van Moolenbroek static int
cmd_idle(globalstate * gstate)647b89261baSDavid van Moolenbroek cmd_idle(globalstate *gstate)
648b89261baSDavid van Moolenbroek 
649b89261baSDavid van Moolenbroek {
650b89261baSDavid van Moolenbroek     gstate->pselect.idle = !gstate->pselect.idle;
651b89261baSDavid van Moolenbroek     message_error(" %sisplaying idle processes.",
652b89261baSDavid van Moolenbroek 		  gstate->pselect.idle ? "D" : "Not d");
653b89261baSDavid van Moolenbroek     return CMD_REFRESH;
654b89261baSDavid van Moolenbroek }
655b89261baSDavid van Moolenbroek 
656b89261baSDavid van Moolenbroek static int
cmd_displays(globalstate * gstate)657b89261baSDavid van Moolenbroek cmd_displays(globalstate *gstate)
658b89261baSDavid van Moolenbroek 
659b89261baSDavid van Moolenbroek {
660b89261baSDavid van Moolenbroek     int i;
661b89261baSDavid van Moolenbroek     char tmpbuf[20];
662b89261baSDavid van Moolenbroek 
663b89261baSDavid van Moolenbroek     message_prompt("Displays to show (currently %s): ",
664b89261baSDavid van Moolenbroek 		   gstate->displays == -1 ? "infinite" :
665b89261baSDavid van Moolenbroek 		   itoa(gstate->displays));
666b89261baSDavid van Moolenbroek 
667b89261baSDavid van Moolenbroek     if ((i = readline(tmpbuf, 10, Yes)) > 0)
668b89261baSDavid van Moolenbroek     {
669b89261baSDavid van Moolenbroek 	gstate->displays = i;
670b89261baSDavid van Moolenbroek     }
671b89261baSDavid van Moolenbroek     else if (i == 0)
672b89261baSDavid van Moolenbroek     {
673b89261baSDavid van Moolenbroek 	quit(EX_OK);
674b89261baSDavid van Moolenbroek 	/*NOTREACHED*/
675b89261baSDavid van Moolenbroek     }
676b89261baSDavid van Moolenbroek     return CMD_OK;
677b89261baSDavid van Moolenbroek }
678b89261baSDavid van Moolenbroek 
679b89261baSDavid van Moolenbroek static int
cmd_cmdline(globalstate * gstate)680b89261baSDavid van Moolenbroek cmd_cmdline(globalstate *gstate)
681b89261baSDavid van Moolenbroek 
682b89261baSDavid van Moolenbroek {
683b89261baSDavid van Moolenbroek     if (gstate->statics->flags.fullcmds)
684b89261baSDavid van Moolenbroek     {
685b89261baSDavid van Moolenbroek 	gstate->pselect.fullcmd = !gstate->pselect.fullcmd;
686b89261baSDavid van Moolenbroek 	message_error(" %sisplaying full command lines.",
687b89261baSDavid van Moolenbroek 		      gstate->pselect.fullcmd ? "D" : "Not d");
688b89261baSDavid van Moolenbroek 	return CMD_REFRESH;
689b89261baSDavid van Moolenbroek     }
690b89261baSDavid van Moolenbroek     message_error(" Full command display not supported.");
691b89261baSDavid van Moolenbroek     return CMD_OK;
692b89261baSDavid van Moolenbroek }
693b89261baSDavid van Moolenbroek 
694b89261baSDavid van Moolenbroek static int
cmd_order(globalstate * gstate)695b89261baSDavid van Moolenbroek cmd_order(globalstate *gstate)
696b89261baSDavid van Moolenbroek 
697b89261baSDavid van Moolenbroek {
698b89261baSDavid van Moolenbroek     char tmpbuf[MAX_COLS];
699b89261baSDavid van Moolenbroek     int i;
700b89261baSDavid van Moolenbroek 
701b89261baSDavid van Moolenbroek     if (gstate->statics->order_names != NULL)
702b89261baSDavid van Moolenbroek     {
703b89261baSDavid van Moolenbroek 	message_prompt("Column to sort: ");
704b89261baSDavid van Moolenbroek 	if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
705b89261baSDavid van Moolenbroek 	{
706b89261baSDavid van Moolenbroek 	    if ((i = string_index(tmpbuf, gstate->statics->order_names)) == -1)
707b89261baSDavid van Moolenbroek 	    {
708b89261baSDavid van Moolenbroek 		message_error(" Sort order \"%s\" not recognized", tmpbuf);
709b89261baSDavid van Moolenbroek 	    }
710b89261baSDavid van Moolenbroek 	    else
711b89261baSDavid van Moolenbroek 	    {
712b89261baSDavid van Moolenbroek 		gstate->order_index = i;
713b89261baSDavid van Moolenbroek 		return CMD_REFRESH;
714b89261baSDavid van Moolenbroek 	    }
715b89261baSDavid van Moolenbroek 	}
716b89261baSDavid van Moolenbroek     }
717b89261baSDavid van Moolenbroek     return CMD_OK;
718b89261baSDavid van Moolenbroek }
719b89261baSDavid van Moolenbroek 
720b89261baSDavid van Moolenbroek static int
cmd_order_x(globalstate * gstate,const char * name,...)721b89261baSDavid van Moolenbroek cmd_order_x(globalstate *gstate, const char *name, ...)
722b89261baSDavid van Moolenbroek 
723b89261baSDavid van Moolenbroek {
724b89261baSDavid van Moolenbroek     va_list ap;
725b89261baSDavid van Moolenbroek     char *p;
726b89261baSDavid van Moolenbroek     const char **names;
727b89261baSDavid van Moolenbroek     int i;
728b89261baSDavid van Moolenbroek 
729b89261baSDavid van Moolenbroek     names = gstate->statics->order_names;
730b89261baSDavid van Moolenbroek     if (names != NULL)
731b89261baSDavid van Moolenbroek     {
732b89261baSDavid van Moolenbroek 	if ((i = string_index(name, names)) == -1)
733b89261baSDavid van Moolenbroek 	{
734b89261baSDavid van Moolenbroek 	    /* check the alternate list */
735b89261baSDavid van Moolenbroek 	    va_start(ap, name);
736b89261baSDavid van Moolenbroek 	    p = va_arg(ap, char *);
737b89261baSDavid van Moolenbroek 	    while (p != NULL)
738b89261baSDavid van Moolenbroek 	    {
739b89261baSDavid van Moolenbroek 		if ((i = string_index(p, names)) != -1)
740b89261baSDavid van Moolenbroek 		{
741b89261baSDavid van Moolenbroek 		    gstate->order_index = i;
742b89261baSDavid van Moolenbroek 		    return CMD_REFRESH;
743b89261baSDavid van Moolenbroek 		}
744b89261baSDavid van Moolenbroek 		p = va_arg(ap, char *);
745b89261baSDavid van Moolenbroek 	    }
746b89261baSDavid van Moolenbroek 	    message_error(" Sort order not recognized");
747b89261baSDavid van Moolenbroek 	}
748b89261baSDavid van Moolenbroek 	else
749b89261baSDavid van Moolenbroek 	{
750b89261baSDavid van Moolenbroek 	    gstate->order_index = i;
751b89261baSDavid van Moolenbroek 	    return CMD_REFRESH;
752b89261baSDavid van Moolenbroek 	}
753b89261baSDavid van Moolenbroek     }
754b89261baSDavid van Moolenbroek     return CMD_OK;
755b89261baSDavid van Moolenbroek }
756b89261baSDavid van Moolenbroek 
757b89261baSDavid van Moolenbroek static int
cmd_order_cpu(globalstate * gstate)758b89261baSDavid van Moolenbroek cmd_order_cpu(globalstate *gstate)
759b89261baSDavid van Moolenbroek 
760b89261baSDavid van Moolenbroek {
761b89261baSDavid van Moolenbroek     return cmd_order_x(gstate, "cpu", NULL);
762b89261baSDavid van Moolenbroek }
763b89261baSDavid van Moolenbroek 
764b89261baSDavid van Moolenbroek static int
cmd_order_pid(globalstate * gstate)765b89261baSDavid van Moolenbroek cmd_order_pid(globalstate *gstate)
766b89261baSDavid van Moolenbroek 
767b89261baSDavid van Moolenbroek {
768b89261baSDavid van Moolenbroek     return cmd_order_x(gstate, "pid", NULL);
769b89261baSDavid van Moolenbroek }
770b89261baSDavid van Moolenbroek 
771b89261baSDavid van Moolenbroek static int
cmd_order_mem(globalstate * gstate)772b89261baSDavid van Moolenbroek cmd_order_mem(globalstate *gstate)
773b89261baSDavid van Moolenbroek 
774b89261baSDavid van Moolenbroek {
775b89261baSDavid van Moolenbroek     return cmd_order_x(gstate, "mem", "size", NULL);
776b89261baSDavid van Moolenbroek }
777b89261baSDavid van Moolenbroek 
778b89261baSDavid van Moolenbroek static int
cmd_order_time(globalstate * gstate)779b89261baSDavid van Moolenbroek cmd_order_time(globalstate *gstate)
780b89261baSDavid van Moolenbroek 
781b89261baSDavid van Moolenbroek {
782b89261baSDavid van Moolenbroek     return cmd_order_x(gstate, "time");
783b89261baSDavid van Moolenbroek }
784b89261baSDavid van Moolenbroek 
785b89261baSDavid van Moolenbroek #ifdef ENABLE_KILL
786b89261baSDavid van Moolenbroek 
787b89261baSDavid van Moolenbroek static int
cmd_kill(globalstate * gstate)788b89261baSDavid van Moolenbroek cmd_kill(globalstate *gstate)
789b89261baSDavid van Moolenbroek 
790b89261baSDavid van Moolenbroek {
791b89261baSDavid van Moolenbroek     char tmpbuf[MAX_COLS];
792b89261baSDavid van Moolenbroek 
793b89261baSDavid van Moolenbroek     message_prompt_plain("kill ");
794b89261baSDavid van Moolenbroek     if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
795b89261baSDavid van Moolenbroek     {
796b89261baSDavid van Moolenbroek 	kill_procs(tmpbuf);
797b89261baSDavid van Moolenbroek     }
798b89261baSDavid van Moolenbroek     return CMD_OK;
799b89261baSDavid van Moolenbroek }
800b89261baSDavid van Moolenbroek 
801b89261baSDavid van Moolenbroek static int
cmd_renice(globalstate * gstate)802b89261baSDavid van Moolenbroek cmd_renice(globalstate *gstate)
803b89261baSDavid van Moolenbroek 
804b89261baSDavid van Moolenbroek {
805b89261baSDavid van Moolenbroek     char tmpbuf[MAX_COLS];
806b89261baSDavid van Moolenbroek 
807b89261baSDavid van Moolenbroek     message_prompt_plain("renice ");
808b89261baSDavid van Moolenbroek     if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
809b89261baSDavid van Moolenbroek     {
810b89261baSDavid van Moolenbroek 	renice_procs(tmpbuf);
811b89261baSDavid van Moolenbroek     }
812b89261baSDavid van Moolenbroek     return CMD_OK;
813b89261baSDavid van Moolenbroek }
814b89261baSDavid van Moolenbroek 
815b89261baSDavid van Moolenbroek #endif
816b89261baSDavid van Moolenbroek 
817b89261baSDavid van Moolenbroek static int
cmd_pid(globalstate * gstate)818b89261baSDavid van Moolenbroek cmd_pid(globalstate *gstate)
819b89261baSDavid van Moolenbroek 
820b89261baSDavid van Moolenbroek {
821b89261baSDavid van Moolenbroek     char tmpbuf[MAX_COLS];
822b89261baSDavid van Moolenbroek 
823b89261baSDavid van Moolenbroek     message_prompt_plain("select pid ");
824b89261baSDavid van Moolenbroek     gstate->pselect.pid = -1;
825b89261baSDavid van Moolenbroek     if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
826b89261baSDavid van Moolenbroek     {
827b89261baSDavid van Moolenbroek 	int pid;
828b89261baSDavid van Moolenbroek 	if (scanint(tmpbuf, &pid) == 0)
829b89261baSDavid van Moolenbroek 	    gstate->pselect.pid = pid;
830b89261baSDavid van Moolenbroek     }
831b89261baSDavid van Moolenbroek     return CMD_OK;
832b89261baSDavid van Moolenbroek }
833b89261baSDavid van Moolenbroek 
834b89261baSDavid van Moolenbroek static int
cmd_user(globalstate * gstate)835b89261baSDavid van Moolenbroek cmd_user(globalstate *gstate)
836b89261baSDavid van Moolenbroek 
837b89261baSDavid van Moolenbroek {
838b89261baSDavid van Moolenbroek     char linebuf[MAX_COLS];
839b89261baSDavid van Moolenbroek     int i;
840b89261baSDavid van Moolenbroek     int ret = CMD_OK;
841b89261baSDavid van Moolenbroek 
842b89261baSDavid van Moolenbroek     message_prompt("Username to show: ");
843b89261baSDavid van Moolenbroek     if (readline(linebuf, sizeof(linebuf), No) > 0)
844b89261baSDavid van Moolenbroek     {
845b89261baSDavid van Moolenbroek 	if (linebuf[0] == '+' &&
846b89261baSDavid van Moolenbroek 	    linebuf[1] == '\0')
847b89261baSDavid van Moolenbroek 	{
848b89261baSDavid van Moolenbroek 	    gstate->pselect.uid = -1;
849b89261baSDavid van Moolenbroek 	    ret = CMD_REFRESH;
850b89261baSDavid van Moolenbroek 	}
851b89261baSDavid van Moolenbroek 	else if ((i = userid(linebuf)) == -1)
852b89261baSDavid van Moolenbroek 	{
853b89261baSDavid van Moolenbroek 	    message_error(" %s: unknown user", linebuf);
854b89261baSDavid van Moolenbroek 	}
855b89261baSDavid van Moolenbroek 	else
856b89261baSDavid van Moolenbroek 	{
857b89261baSDavid van Moolenbroek 	    gstate->pselect.uid = i;
858b89261baSDavid van Moolenbroek 	    ret = CMD_REFRESH;
859b89261baSDavid van Moolenbroek 	}
860b89261baSDavid van Moolenbroek     }
861b89261baSDavid van Moolenbroek     return ret;
862b89261baSDavid van Moolenbroek }
863b89261baSDavid van Moolenbroek 
864b89261baSDavid van Moolenbroek static int
cmd_command(globalstate * gstate)865b89261baSDavid van Moolenbroek cmd_command(globalstate *gstate)
866b89261baSDavid van Moolenbroek 
867b89261baSDavid van Moolenbroek {
868b89261baSDavid van Moolenbroek     char linebuf[MAX_COLS];
869b89261baSDavid van Moolenbroek 
870b89261baSDavid van Moolenbroek     if (gstate->pselect.command != NULL)
871b89261baSDavid van Moolenbroek     {
872b89261baSDavid van Moolenbroek 	free(gstate->pselect.command);
873b89261baSDavid van Moolenbroek 	gstate->pselect.command = NULL;
874b89261baSDavid van Moolenbroek     }
875b89261baSDavid van Moolenbroek 
876b89261baSDavid van Moolenbroek     message_prompt("Command to show: ");
877b89261baSDavid van Moolenbroek     if (readline(linebuf, sizeof(linebuf), No) > 0)
878b89261baSDavid van Moolenbroek     {
879b89261baSDavid van Moolenbroek 	if (linebuf[0] != '\0')
880b89261baSDavid van Moolenbroek 	{
881b89261baSDavid van Moolenbroek 	    gstate->pselect.command = estrdup(linebuf);
882b89261baSDavid van Moolenbroek 	}
883b89261baSDavid van Moolenbroek     }
884b89261baSDavid van Moolenbroek     return CMD_REFRESH;
885b89261baSDavid van Moolenbroek }
886b89261baSDavid van Moolenbroek 
887b89261baSDavid van Moolenbroek static int
cmd_useruid(globalstate * gstate)888b89261baSDavid van Moolenbroek cmd_useruid(globalstate *gstate)
889b89261baSDavid van Moolenbroek 
890b89261baSDavid van Moolenbroek {
891b89261baSDavid van Moolenbroek     gstate->pselect.usernames = !gstate->pselect.usernames;
892b89261baSDavid van Moolenbroek     display_header(2);
893b89261baSDavid van Moolenbroek     return CMD_REFRESH;
894b89261baSDavid van Moolenbroek }
895b89261baSDavid van Moolenbroek 
896b89261baSDavid van Moolenbroek static int
cmd_mode(globalstate * gstate)897b89261baSDavid van Moolenbroek cmd_mode(globalstate *gstate)
898b89261baSDavid van Moolenbroek 
899b89261baSDavid van Moolenbroek {
900b89261baSDavid van Moolenbroek     if (gstate->statics->modemax <= 1)
901b89261baSDavid van Moolenbroek     {
902b89261baSDavid van Moolenbroek 	return CMD_NA;
903b89261baSDavid van Moolenbroek     }
904b89261baSDavid van Moolenbroek     gstate->pselect.mode = (gstate->pselect.mode + 1) % gstate->statics->modemax;
905b89261baSDavid van Moolenbroek     display_header(2);
906b89261baSDavid van Moolenbroek     return CMD_REFRESH;
907b89261baSDavid van Moolenbroek }
908b89261baSDavid van Moolenbroek 
909b89261baSDavid van Moolenbroek static int
cmd_system(globalstate * gstate)910b89261baSDavid van Moolenbroek cmd_system(globalstate *gstate)
911b89261baSDavid van Moolenbroek 
912b89261baSDavid van Moolenbroek {
913b89261baSDavid van Moolenbroek     gstate->pselect.system = !gstate->pselect.system;
914b89261baSDavid van Moolenbroek     display_header(2);
915b89261baSDavid van Moolenbroek     return CMD_REFRESH;
916b89261baSDavid van Moolenbroek }
917b89261baSDavid van Moolenbroek 
918b89261baSDavid van Moolenbroek static int
cmd_threads(globalstate * gstate)919b89261baSDavid van Moolenbroek cmd_threads(globalstate *gstate)
920b89261baSDavid van Moolenbroek 
921b89261baSDavid van Moolenbroek {
922b89261baSDavid van Moolenbroek     if (gstate->statics->flags.threads)
923b89261baSDavid van Moolenbroek     {
924b89261baSDavid van Moolenbroek 	gstate->pselect.threads = !gstate->pselect.threads;
925b89261baSDavid van Moolenbroek 	display_header(2);
926b89261baSDavid van Moolenbroek 	return CMD_REFRESH;
927b89261baSDavid van Moolenbroek     }
928b89261baSDavid van Moolenbroek     return CMD_NA;
929b89261baSDavid van Moolenbroek }
930b89261baSDavid van Moolenbroek 
931b89261baSDavid van Moolenbroek static int
cmd_percpustates(globalstate * gstate)932b89261baSDavid van Moolenbroek cmd_percpustates(globalstate *gstate)
933b89261baSDavid van Moolenbroek {
934b89261baSDavid van Moolenbroek 	gstate->percpustates = !gstate->percpustates;
935b89261baSDavid van Moolenbroek 	gstate->fulldraw = Yes;
936b89261baSDavid van Moolenbroek 	gstate->max_topn += display_setmulti(gstate->percpustates);
937b89261baSDavid van Moolenbroek 	return CMD_REFRESH;
938b89261baSDavid van Moolenbroek }
939b89261baSDavid van Moolenbroek 
940b89261baSDavid van Moolenbroek 
941b89261baSDavid van Moolenbroek /* forward reference for cmd_help, as it needs to see the command_table */
942b89261baSDavid van Moolenbroek int cmd_help(globalstate *gstate);
943b89261baSDavid van Moolenbroek 
944b89261baSDavid van Moolenbroek /* command table */
945b89261baSDavid van Moolenbroek command command_table[] = {
946b89261baSDavid van Moolenbroek     { '\014', cmd_redraw, "redraw screen" },
947b89261baSDavid van Moolenbroek     { ' ', cmd_update, "update screen" },
948b89261baSDavid van Moolenbroek     { '?', cmd_help, "help; show this text" },
949b89261baSDavid van Moolenbroek     { 'h', cmd_help, NULL },
950b89261baSDavid van Moolenbroek     { '1', cmd_percpustates, "toggle the display of cpu states per cpu" },
951b89261baSDavid van Moolenbroek     { 'C', cmd_color, "toggle the use of color" },
952b89261baSDavid van Moolenbroek     { 'H', cmd_threads, "toggle the display of individual threads" },
953b89261baSDavid van Moolenbroek     { 't', cmd_threads, NULL },
954b89261baSDavid van Moolenbroek     { 'M', cmd_order_mem, "sort by memory usage" },
955b89261baSDavid van Moolenbroek     { 'N', cmd_order_pid, "sort by process id" },
956b89261baSDavid van Moolenbroek     { 'P', cmd_order_cpu, "sort by CPU usage" },
957b89261baSDavid van Moolenbroek     { 'S', cmd_system, "toggle the display of system processes" },
958b89261baSDavid van Moolenbroek     { 'T', cmd_order_time, "sort by CPU time" },
959b89261baSDavid van Moolenbroek     { 'U', cmd_useruid, "toggle the display of usernames or uids" },
960b89261baSDavid van Moolenbroek     { 'c', cmd_command, "display processes by command name" },
961b89261baSDavid van Moolenbroek     { 'd', cmd_displays, "change number of displays to show" },
962b89261baSDavid van Moolenbroek     { 'f', cmd_cmdline, "toggle the display of full command paths" },
963b89261baSDavid van Moolenbroek     { 'i', cmd_idle, "toggle the displaying of idle processes" },
964b89261baSDavid van Moolenbroek     { 'I', cmd_idle, NULL },
965b89261baSDavid van Moolenbroek #ifdef ENABLE_KILL
966b89261baSDavid van Moolenbroek     { 'k', cmd_kill, "kill processes; send a signal to a list of processes" },
967b89261baSDavid van Moolenbroek #endif
968b89261baSDavid van Moolenbroek     { 'm', cmd_mode, "toggle between display modes" },
969b89261baSDavid van Moolenbroek     { 'n', cmd_number, "change number of processes to display" },
970b89261baSDavid van Moolenbroek     { '#', cmd_number, NULL },
971b89261baSDavid van Moolenbroek     { 'o', cmd_order, "specify sort order (see below)" },
972b89261baSDavid van Moolenbroek     { 'p', cmd_pid, "select a single pid" },
973b89261baSDavid van Moolenbroek     { 'q', (int (*)(globalstate *))cmd_quit, "quit" },
974b89261baSDavid van Moolenbroek #ifdef ENABLE_KILL
975b89261baSDavid van Moolenbroek     { 'r', cmd_renice, "renice a process" },
976b89261baSDavid van Moolenbroek #endif
977b89261baSDavid van Moolenbroek     { 's', cmd_delay, "change number of seconds to delay between updates" },
978b89261baSDavid van Moolenbroek     { 'u', cmd_user, "display processes for only one user (+ selects all users)" },
979b89261baSDavid van Moolenbroek     { '\0', NULL, NULL },
980b89261baSDavid van Moolenbroek };
981b89261baSDavid van Moolenbroek 
982b89261baSDavid van Moolenbroek int
cmd_help(globalstate * gstate)983b89261baSDavid van Moolenbroek cmd_help(globalstate *gstate)
984b89261baSDavid van Moolenbroek 
985b89261baSDavid van Moolenbroek {
986b89261baSDavid van Moolenbroek     command *c;
987b89261baSDavid van Moolenbroek     char buf[12];
988b89261baSDavid van Moolenbroek     char *p;
989b89261baSDavid van Moolenbroek     const char *help;
990b89261baSDavid van Moolenbroek 
991b89261baSDavid van Moolenbroek     display_pagerstart();
992b89261baSDavid van Moolenbroek 
993b89261baSDavid van Moolenbroek     display_pager("Top version %s, %s\n", version_string(), copyright);
994b89261baSDavid van Moolenbroek     display_pager("Platform module: %s\n\n", MODULE);
995b89261baSDavid van Moolenbroek     display_pager("A top users display for Unix\n\n");
996b89261baSDavid van Moolenbroek     display_pager("These single-character commands are available:\n\n");
997b89261baSDavid van Moolenbroek 
998b89261baSDavid van Moolenbroek     c = command_table;
999b89261baSDavid van Moolenbroek     while (c->cmd_func != NULL)
1000b89261baSDavid van Moolenbroek     {
1001b89261baSDavid van Moolenbroek 	/* skip null help strings */
1002b89261baSDavid van Moolenbroek 	if ((help = c->help) == NULL)
1003b89261baSDavid van Moolenbroek 	{
1004b89261baSDavid van Moolenbroek 	    continue;
1005b89261baSDavid van Moolenbroek 	}
1006b89261baSDavid van Moolenbroek 
1007b89261baSDavid van Moolenbroek 	/* translate character in to something readable */
1008b89261baSDavid van Moolenbroek 	if (c->ch < ' ')
1009b89261baSDavid van Moolenbroek 	{
1010b89261baSDavid van Moolenbroek 	    buf[0] = '^';
1011b89261baSDavid van Moolenbroek 	    buf[1] = c->ch + '@';
1012b89261baSDavid van Moolenbroek 	    buf[2] = '\0';
1013b89261baSDavid van Moolenbroek 	}
1014b89261baSDavid van Moolenbroek 	else if (c->ch == ' ')
1015b89261baSDavid van Moolenbroek 	{
1016b89261baSDavid van Moolenbroek 	    strcpy(buf, "<sp>");
1017b89261baSDavid van Moolenbroek 	}
1018b89261baSDavid van Moolenbroek 	else
1019b89261baSDavid van Moolenbroek 	{
1020b89261baSDavid van Moolenbroek 	    buf[0] = c->ch;
1021b89261baSDavid van Moolenbroek 	    buf[1] = '\0';
1022b89261baSDavid van Moolenbroek 	}
1023b89261baSDavid van Moolenbroek 
1024b89261baSDavid van Moolenbroek 	/* if the next command is the same, fold them onto one line */
1025b89261baSDavid van Moolenbroek 	if ((c+1)->cmd_func == c->cmd_func)
1026b89261baSDavid van Moolenbroek 	{
1027b89261baSDavid van Moolenbroek 	    strcat(buf, " or ");
1028b89261baSDavid van Moolenbroek 	    p = buf + strlen(buf);
1029b89261baSDavid van Moolenbroek 	    *p++ = (c+1)->ch;
1030b89261baSDavid van Moolenbroek 	    *p = '\0';
1031b89261baSDavid van Moolenbroek 	    c++;
1032b89261baSDavid van Moolenbroek 	}
1033b89261baSDavid van Moolenbroek 
1034b89261baSDavid van Moolenbroek 	display_pager("%-7s - %s\n", buf, help);
1035b89261baSDavid van Moolenbroek 	c++;
1036b89261baSDavid van Moolenbroek     }
1037b89261baSDavid van Moolenbroek 
1038b89261baSDavid van Moolenbroek     display_pager("\nNot all commands are available on all systems.\n\n");
1039b89261baSDavid van Moolenbroek     display_pager("Available sort orders: %s\n", gstate->order_namelist);
1040b89261baSDavid van Moolenbroek     display_pagerend();
1041b89261baSDavid van Moolenbroek     gstate->fulldraw = Yes;
1042b89261baSDavid van Moolenbroek     return CMD_REFRESH;
1043b89261baSDavid van Moolenbroek }
1044b89261baSDavid van Moolenbroek 
1045b89261baSDavid van Moolenbroek /*
1046b89261baSDavid van Moolenbroek  * int command_process(globalstate *gstate, int cmd)
1047b89261baSDavid van Moolenbroek  *
1048b89261baSDavid van Moolenbroek  * Process the single-character command "cmd".  The global state may
1049b89261baSDavid van Moolenbroek  * be modified by the command to alter the output.  Returns CMD_ERROR
1050b89261baSDavid van Moolenbroek  * if there was a serious error that requires an immediate exit, CMD_OK
1051b89261baSDavid van Moolenbroek  * to indicate success, CMD_REFRESH to indicate that the screen needs
1052b89261baSDavid van Moolenbroek  * to be refreshed immediately, CMD_UNKNOWN when the command is not known,
1053b89261baSDavid van Moolenbroek  * and CMD_NA when the command is not available.  Error messages for
1054b89261baSDavid van Moolenbroek  * CMD_NA and CMD_UNKNOWN must be handled by the caller.
1055b89261baSDavid van Moolenbroek  */
1056b89261baSDavid van Moolenbroek 
1057b89261baSDavid van Moolenbroek int
command_process(globalstate * gstate,int cmd)1058b89261baSDavid van Moolenbroek command_process(globalstate *gstate, int cmd)
1059b89261baSDavid van Moolenbroek 
1060b89261baSDavid van Moolenbroek {
1061b89261baSDavid van Moolenbroek     command *c;
1062b89261baSDavid van Moolenbroek 
1063b89261baSDavid van Moolenbroek     c = command_table;
1064b89261baSDavid van Moolenbroek     while (c->cmd_func != NULL)
1065b89261baSDavid van Moolenbroek     {
1066b89261baSDavid van Moolenbroek 	if (c->ch == cmd)
1067b89261baSDavid van Moolenbroek 	{
1068b89261baSDavid van Moolenbroek 	    return (c->cmd_func)(gstate);
1069b89261baSDavid van Moolenbroek 	}
1070b89261baSDavid van Moolenbroek 	c++;
1071b89261baSDavid van Moolenbroek     }
1072b89261baSDavid van Moolenbroek 
1073b89261baSDavid van Moolenbroek     return CMD_UNKNOWN;
1074b89261baSDavid van Moolenbroek }
1075