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