Sat Jun 9 15:37:57 2018 UTC ()
Pull up following revision(s) (requested by kamil in ticket #871):

	external/bsd/top/dist/top.c: revision 1.10

Fix unitialized signal mask passed to sigaction(2) in top(1)

Detected with Memory Sanitizer during the integration of sanitizers with
the NetBSD basesystem.

Reported by <Yang Zheng>


(martin)
diff -r1.9 -r1.9.24.1 src/external/bsd/top/dist/top.c

cvs diff -r1.9 -r1.9.24.1 src/external/bsd/top/dist/top.c (switch to unified diff)

--- src/external/bsd/top/dist/top.c 2012/03/23 14:46:05 1.9
+++ src/external/bsd/top/dist/top.c 2018/06/09 15:37:57 1.9.24.1
@@ -1,996 +1,997 @@ @@ -1,996 +1,997 @@
1/* 1/*
2 * Copyright (c) 1984 through 2008, William LeFebvre 2 * Copyright (c) 1984 through 2008, William LeFebvre
3 * All rights reserved. 3 * All rights reserved.
4 *  4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 *  7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 *  10 *
11 * * Redistributions in binary form must reproduce the above 11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer 12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the 13 * in the documentation and/or other materials provided with the
14 * distribution. 14 * distribution.
15 *  15 *
16 * * Neither the name of William LeFebvre nor the names of other 16 * * Neither the name of William LeFebvre nor the names of other
17 * contributors may be used to endorse or promote products derived from 17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission. 18 * this software without specific prior written permission.
19 *  19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33const char *copyright = 33const char *copyright =
34 "Copyright (c) 1984 through 2008, William LeFebvre"; 34 "Copyright (c) 1984 through 2008, William LeFebvre";
35 35
36/* 36/*
37 * Changes to other files that we can do at the same time: 37 * Changes to other files that we can do at the same time:
38 * screen.c:init_termcap: get rid of the "interactive" argument and have it 38 * screen.c:init_termcap: get rid of the "interactive" argument and have it
39 * pass back something meaningful (such as success/failure/error). 39 * pass back something meaningful (such as success/failure/error).
40 */ 40 */
41 41
42#include "os.h" 42#include "os.h"
43#include <signal.h> 43#include <signal.h>
44#include <setjmp.h> 44#include <setjmp.h>
45#include <ctype.h> 45#include <ctype.h>
46#include <sys/types.h> 46#include <sys/types.h>
47#include <sys/uio.h> 47#include <sys/uio.h>
48#include <unistd.h> 48#include <unistd.h>
49 49
50#ifdef HAVE_SYS_UTSNAME_H 50#ifdef HAVE_SYS_UTSNAME_H
51#include <sys/utsname.h> 51#include <sys/utsname.h>
52#endif 52#endif
53 53
54#ifdef HAVE_GETOPT_H 54#ifdef HAVE_GETOPT_H
55#include <getopt.h> 55#include <getopt.h>
56#endif 56#endif
57 57
58/* definitions */ 58/* definitions */
59#ifndef STDIN_FILENO 59#ifndef STDIN_FILENO
60#define STDIN_FILENO 0 60#define STDIN_FILENO 0
61#endif 61#endif
62 62
63/* determine which type of signal functions to use */ 63/* determine which type of signal functions to use */
64/* cant have sigaction without sigprocmask */ 64/* cant have sigaction without sigprocmask */
65#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGPROCMASK) 65#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGPROCMASK)
66#undef HAVE_SIGACTION 66#undef HAVE_SIGACTION
67#endif 67#endif
68/* always use sigaction when it is available */ 68/* always use sigaction when it is available */
69#ifdef HAVE_SIGACTION 69#ifdef HAVE_SIGACTION
70#undef HAVE_SIGHOLD 70#undef HAVE_SIGHOLD
71#else 71#else
72/* use sighold/sigrelse, otherwise use old fashioned BSD signals */ 72/* use sighold/sigrelse, otherwise use old fashioned BSD signals */
73#if !defined(HAVE_SIGHOLD) || !defined(HAVE_SIGRELSE) 73#if !defined(HAVE_SIGHOLD) || !defined(HAVE_SIGRELSE)
74#define BSD_SIGNALS 74#define BSD_SIGNALS
75#endif 75#endif
76#endif 76#endif
77 77
78/* if FD_SET and friends aren't present, then fake something up */ 78/* if FD_SET and friends aren't present, then fake something up */
79#ifndef FD_SET 79#ifndef FD_SET
80typedef int fd_set; 80typedef int fd_set;
81#define FD_ZERO(x) (*(x) = 0) 81#define FD_ZERO(x) (*(x) = 0)
82#define FD_SET(f, x) (*(x) = 1<<f) 82#define FD_SET(f, x) (*(x) = 1<<f)
83#endif 83#endif
84 84
85/* includes specific to top */ 85/* includes specific to top */
86 86
87#include "top.h" 87#include "top.h"
88#include "machine.h" 88#include "machine.h"
89#include "globalstate.h" 89#include "globalstate.h"
90#include "commands.h" 90#include "commands.h"
91#include "display.h" 91#include "display.h"
92#include "screen.h" 92#include "screen.h"
93#include "boolean.h" 93#include "boolean.h"
94#include "username.h" 94#include "username.h"
95#include "utils.h" 95#include "utils.h"
96#include "version.h" 96#include "version.h"
97#ifdef ENABLE_COLOR 97#ifdef ENABLE_COLOR
98#include "color.h" 98#include "color.h"
99#endif 99#endif
100 100
101/* definitions */ 101/* definitions */
102#define BUFFERSIZE 4096 102#define BUFFERSIZE 4096
103#define JMP_RESUME 1 103#define JMP_RESUME 1
104#define JMP_RESIZE 2 104#define JMP_RESIZE 2
105 105
106/* externs for getopt: */ 106/* externs for getopt: */
107extern int optind; 107extern int optind;
108extern char *optarg; 108extern char *optarg;
109 109
110/* statics */ 110/* statics */
111static char stdoutbuf[BUFFERSIZE]; 111static char stdoutbuf[BUFFERSIZE];
112static jmp_buf jmp_int; 112static jmp_buf jmp_int;
113 113
114/* globals */ 114/* globals */
115char *myname; 115char *myname;
116 116
117void 117void
118quit(int status) 118quit(int status)
119 119
120{ 120{
121 screen_end(); 121 screen_end();
122 chdir("/tmp"); 122 chdir("/tmp");
123 exit(status); 123 exit(status);
124 /* NOTREACHED */ 124 /* NOTREACHED */
125} 125}
126 126
127/* 127/*
128 * signal handlers 128 * signal handlers
129 */ 129 */
130 130
131static void 131static void
132set_signal(int sig, RETSIGTYPE (*handler)(int)) 132set_signal(int sig, RETSIGTYPE (*handler)(int))
133 133
134{ 134{
135#ifdef HAVE_SIGACTION 135#ifdef HAVE_SIGACTION
136 struct sigaction action; 136 struct sigaction action;
137 137
 138 sigemptyset(&action.sa_mask);
138 action.sa_handler = handler; 139 action.sa_handler = handler;
139 action.sa_flags = 0; 140 action.sa_flags = 0;
140 (void) sigaction(sig, &action, NULL); 141 (void) sigaction(sig, &action, NULL);
141#else 142#else
142 (void) signal(sig, handler); 143 (void) signal(sig, handler);
143#endif 144#endif
144} 145}
145 146
146static void 147static void
147release_signal(int sig) 148release_signal(int sig)
148 149
149{ 150{
150#ifdef HAVE_SIGACTION 151#ifdef HAVE_SIGACTION
151 sigset_t set; 152 sigset_t set;
152 sigemptyset(&set); 153 sigemptyset(&set);
153 sigaddset(&set, sig); 154 sigaddset(&set, sig);
154 sigprocmask(SIG_UNBLOCK, &set, NULL); 155 sigprocmask(SIG_UNBLOCK, &set, NULL);
155#endif 156#endif
156 157
157#ifdef HAVE_SIGHOLD 158#ifdef HAVE_SIGHOLD
158 sigrelse(sig); 159 sigrelse(sig);
159#endif 160#endif
160 161
161#ifdef BSD_SIGNALS 162#ifdef BSD_SIGNALS
162 (void) sigsetmask(sigblock(0) & ~(sigmask(sig))); 163 (void) sigsetmask(sigblock(0) & ~(sigmask(sig)));
163#endif 164#endif
164} 165}
165 166
166static RETSIGTYPE 167static RETSIGTYPE
167sig_leave(int i) /* exit under normal conditions -- INT handler */ 168sig_leave(int i) /* exit under normal conditions -- INT handler */
168 169
169{ 170{
170 screen_end(); 171 screen_end();
171 exit(EX_OK); 172 exit(EX_OK);
172} 173}
173 174
174static RETSIGTYPE 175static RETSIGTYPE
175sig_tstop(int i) /* SIGTSTP handler */ 176sig_tstop(int i) /* SIGTSTP handler */
176 177
177{ 178{
178 /* move to the lower left */ 179 /* move to the lower left */
179 screen_end(); 180 screen_end();
180 fflush(stdout); 181 fflush(stdout);
181 182
182 /* default the signal handler action */ 183 /* default the signal handler action */
183 set_signal(SIGTSTP, SIG_DFL); 184 set_signal(SIGTSTP, SIG_DFL);
184 185
185 /* unblock the TSTP signal */ 186 /* unblock the TSTP signal */
186 release_signal(SIGTSTP); 187 release_signal(SIGTSTP);
187 188
188 /* send ourselves a TSTP to stop the process */ 189 /* send ourselves a TSTP to stop the process */
189 (void) kill(0, SIGTSTP); 190 (void) kill(0, SIGTSTP);
190 191
191 /* reset the signal handler */ 192 /* reset the signal handler */
192 set_signal(SIGTSTP, sig_tstop); 193 set_signal(SIGTSTP, sig_tstop);
193 194
194 /* reinit screen */ 195 /* reinit screen */
195 screen_reinit(); 196 screen_reinit();
196 197
197 /* jump back to a known place in the main loop */ 198 /* jump back to a known place in the main loop */
198 longjmp(jmp_int, JMP_RESUME); 199 longjmp(jmp_int, JMP_RESUME);
199 200
200 /* NOTREACHED */ 201 /* NOTREACHED */
201} 202}
202 203
203#ifdef SIGWINCH 204#ifdef SIGWINCH
204static RETSIGTYPE 205static RETSIGTYPE
205sig_winch(int i) /* SIGWINCH handler */ 206sig_winch(int i) /* SIGWINCH handler */
206 207
207{ 208{
208 /* reascertain the screen dimensions */ 209 /* reascertain the screen dimensions */
209 screen_getsize(); 210 screen_getsize();
210 211
211 /* jump back to a known place in the main loop */ 212 /* jump back to a known place in the main loop */
212 longjmp(jmp_int, JMP_RESIZE); 213 longjmp(jmp_int, JMP_RESIZE);
213} 214}
214#endif 215#endif
215 216
216#ifdef HAVE_SIGACTION 217#ifdef HAVE_SIGACTION
217static sigset_t signalset; 218static sigset_t signalset;
218#endif 219#endif
219 220
220static void * 221static void *
221hold_signals(void) 222hold_signals(void)
222 223
223{ 224{
224#ifdef HAVE_SIGACTION 225#ifdef HAVE_SIGACTION
225 sigemptyset(&signalset); 226 sigemptyset(&signalset);
226 sigaddset(&signalset, SIGINT); 227 sigaddset(&signalset, SIGINT);
227 sigaddset(&signalset, SIGQUIT); 228 sigaddset(&signalset, SIGQUIT);
228 sigaddset(&signalset, SIGTSTP); 229 sigaddset(&signalset, SIGTSTP);
229#ifdef SIGWINCH 230#ifdef SIGWINCH
230 sigaddset(&signalset, SIGWINCH); 231 sigaddset(&signalset, SIGWINCH);
231#endif 232#endif
232 sigprocmask(SIG_BLOCK, &signalset, NULL); 233 sigprocmask(SIG_BLOCK, &signalset, NULL);
233 return (void *)(&signalset); 234 return (void *)(&signalset);
234#endif 235#endif
235 236
236#ifdef HAVE_SIGHOLD 237#ifdef HAVE_SIGHOLD
237 sighold(SIGINT); 238 sighold(SIGINT);
238 sighold(SIGQUIT); 239 sighold(SIGQUIT);
239 sighold(SIGTSTP); 240 sighold(SIGTSTP);
240#ifdef SIGWINCH 241#ifdef SIGWINCH
241 sighold(SIGWINCH); 242 sighold(SIGWINCH);
242 return NULL; 243 return NULL;
243#endif 244#endif
244#endif 245#endif
245 246
246#ifdef BSD_SIGNALS 247#ifdef BSD_SIGNALS
247 int mask; 248 int mask;
248#ifdef SIGWINCH 249#ifdef SIGWINCH
249 mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | 250 mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) |
250 sigmask(SIGTSTP) | sigmask(SIGWINCH)); 251 sigmask(SIGTSTP) | sigmask(SIGWINCH));
251#else 252#else
252 mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTSTP)); 253 mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTSTP));
253 return (void *)mask; 254 return (void *)mask;
254#endif 255#endif
255#endif 256#endif
256 257
257} 258}
258 259
259static void 260static void
260set_signals(void) 261set_signals(void)
261 262
262{ 263{
263 (void) set_signal(SIGINT, sig_leave); 264 (void) set_signal(SIGINT, sig_leave);
264 (void) set_signal(SIGQUIT, sig_leave); 265 (void) set_signal(SIGQUIT, sig_leave);
265 (void) set_signal(SIGTSTP, sig_tstop); 266 (void) set_signal(SIGTSTP, sig_tstop);
266#ifdef SIGWINCH 267#ifdef SIGWINCH
267 (void) set_signal(SIGWINCH, sig_winch); 268 (void) set_signal(SIGWINCH, sig_winch);
268#endif 269#endif
269} 270}
270 271
271static void 272static void
272release_signals(void *parm) 273release_signals(void *parm)
273 274
274{ 275{
275#ifdef HAVE_SIGACTION 276#ifdef HAVE_SIGACTION
276 sigprocmask(SIG_UNBLOCK, (sigset_t *)parm, NULL); 277 sigprocmask(SIG_UNBLOCK, (sigset_t *)parm, NULL);
277#endif 278#endif
278 279
279#ifdef HAVE_SIGHOLD 280#ifdef HAVE_SIGHOLD
280 sigrelse(SIGINT); 281 sigrelse(SIGINT);
281 sigrelse(SIGQUIT); 282 sigrelse(SIGQUIT);
282 sigrelse(SIGTSTP); 283 sigrelse(SIGTSTP);
283#ifdef SIGWINCH 284#ifdef SIGWINCH
284 sigrelse(SIGWINCH); 285 sigrelse(SIGWINCH);
285#endif 286#endif
286#endif 287#endif
287 288
288#ifdef BSD_SIGNALS 289#ifdef BSD_SIGNALS
289 (void) sigsetmask((int)parm); 290 (void) sigsetmask((int)parm);
290#endif 291#endif
291} 292}
292 293
293/* 294/*
294 * void do_arguments(globalstate *gstate, int ac, char **av) 295 * void do_arguments(globalstate *gstate, int ac, char **av)
295 * 296 *
296 * Arguments processing. gstate points to the global state, 297 * Arguments processing. gstate points to the global state,
297 * ac and av are the arguments to process. This can be called 298 * ac and av are the arguments to process. This can be called
298 * multiple times with different sets of arguments. 299 * multiple times with different sets of arguments.
299 */ 300 */
300 301
301#ifdef HAVE_GETOPT_LONG 302#ifdef HAVE_GETOPT_LONG
302static struct option longopts[] = { 303static struct option longopts[] = {
303 { "percpustates", no_argument, NULL, '1' }, 304 { "percpustates", no_argument, NULL, '1' },
304 { "color", no_argument, NULL, 'C' }, 305 { "color", no_argument, NULL, 'C' },
305 { "debug", no_argument, NULL, 'D' }, 306 { "debug", no_argument, NULL, 'D' },
306 { "system-procs", no_argument, NULL, 'S' }, 307 { "system-procs", no_argument, NULL, 'S' },
307 { "idle-procs", no_argument, NULL, 'I' }, 308 { "idle-procs", no_argument, NULL, 'I' },
308 { "tag-names", no_argument, NULL, 'T' }, 309 { "tag-names", no_argument, NULL, 'T' },
309 { "all", no_argument, NULL, 'a' }, 310 { "all", no_argument, NULL, 'a' },
310 { "batch", no_argument, NULL, 'b' }, 311 { "batch", no_argument, NULL, 'b' },
311 { "full-commands", no_argument, NULL, 'c' }, 312 { "full-commands", no_argument, NULL, 'c' },
312 { "interactive", no_argument, NULL, 'i' }, 313 { "interactive", no_argument, NULL, 'i' },
313 { "quick", no_argument, NULL, 'q' }, 314 { "quick", no_argument, NULL, 'q' },
314 { "threads", no_argument, NULL, 't' }, 315 { "threads", no_argument, NULL, 't' },
315 { "uids", no_argument, NULL, 'u' }, 316 { "uids", no_argument, NULL, 'u' },
316 { "version", no_argument, NULL, 'v' }, 317 { "version", no_argument, NULL, 'v' },
317 { "delay", required_argument, NULL, 's' }, 318 { "delay", required_argument, NULL, 's' },
318 { "displays", required_argument, NULL, 'd' }, 319 { "displays", required_argument, NULL, 'd' },
319 { "user", required_argument, NULL, 'U' }, 320 { "user", required_argument, NULL, 'U' },
320 { "sort-order", required_argument, NULL, 'o' }, 321 { "sort-order", required_argument, NULL, 'o' },
321 { "pid", required_argument, NULL, 'p' }, 322 { "pid", required_argument, NULL, 'p' },
322 { "display-mode", required_argument, NULL, 'm' }, 323 { "display-mode", required_argument, NULL, 'm' },
323 { NULL, 0, NULL, 0 }, 324 { NULL, 0, NULL, 0 },
324}; 325};
325#endif 326#endif
326 327
327 328
328static void 329static void
329do_arguments(globalstate *gstate, int ac, char **av) 330do_arguments(globalstate *gstate, int ac, char **av)
330 331
331{ 332{
332 int i; 333 int i;
333 double f; 334 double f;
334 335
335 /* this appears to keep getopt happy */ 336 /* this appears to keep getopt happy */
336 optind = 1; 337 optind = 1;
337 338
338#ifdef HAVE_GETOPT_LONG 339#ifdef HAVE_GETOPT_LONG
339 while ((i = getopt_long(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:", longopts, NULL)) != -1) 340 while ((i = getopt_long(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:", longopts, NULL)) != -1)
340#else 341#else
341 while ((i = getopt(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:")) != EOF) 342 while ((i = getopt(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:")) != EOF)
342#endif 343#endif
343 { 344 {
344 switch(i) 345 switch(i)
345 { 346 {
346 case '1': 347 case '1':
347 gstate->percpustates = !gstate->percpustates; 348 gstate->percpustates = !gstate->percpustates;
348 break; 349 break;
349#ifdef ENABLE_COLOR 350#ifdef ENABLE_COLOR
350 case 'C': 351 case 'C':
351 gstate->use_color = !gstate->use_color; 352 gstate->use_color = !gstate->use_color;
352 break; 353 break;
353#endif 354#endif
354 355
355 case 'D': 356 case 'D':
356 debug_set(1); 357 debug_set(1);
357 break; 358 break;
358 359
359 case 'v': 360 case 'v':
360 fprintf(stderr, "%s: version %s\n", myname, version_string()); 361 fprintf(stderr, "%s: version %s\n", myname, version_string());
361 exit(EX_OK); 362 exit(EX_OK);
362 break; 363 break;
363 364
364 case 'b': 365 case 'b':
365 case 'n': 366 case 'n':
366 gstate->interactive = No; 367 gstate->interactive = No;
367 break; 368 break;
368 369
369 case 'a': 370 case 'a':
370 gstate->displays = Infinity; 371 gstate->displays = Infinity;
371 gstate->topn = Infinity; 372 gstate->topn = Infinity;
372 break; 373 break;
373 374
374 case 'i': 375 case 'i':
375 gstate->interactive = Yes; 376 gstate->interactive = Yes;
376 break; 377 break;
377 378
378 case 'o': 379 case 'o':
379 gstate->order_name = optarg; 380 gstate->order_name = optarg;
380 break; 381 break;
381 382
382 case 'd': 383 case 'd':
383 i = atoiwi(optarg); 384 i = atoiwi(optarg);
384 if (i == Invalid || i == 0) 385 if (i == Invalid || i == 0)
385 { 386 {
386 message_error(" Bad display count"); 387 message_error(" Bad display count");
387 } 388 }
388 else 389 else
389 { 390 {
390 gstate->displays = i; 391 gstate->displays = i;
391 } 392 }
392 break; 393 break;
393 394
394 case 's': 395 case 's':
395 f = atof(optarg); 396 f = atof(optarg);
396 if (f < 0 || (f == 0 && getuid() != 0)) 397 if (f < 0 || (f == 0 && getuid() != 0))
397 { 398 {
398 message_error(" Bad seconds delay"); 399 message_error(" Bad seconds delay");
399 } 400 }
400 else 401 else
401 { 402 {
402 gstate->delay = f; 403 gstate->delay = f;
403 } 404 }
404 break; 405 break;
405 406
406 case 'u': 407 case 'u':
407 gstate->show_usernames = !gstate->show_usernames; 408 gstate->show_usernames = !gstate->show_usernames;
408 break; 409 break;
409 410
410 case 'U': 411 case 'U':
411 i = userid(optarg); 412 i = userid(optarg);
412 if (i == -1) 413 if (i == -1)
413 { 414 {
414 message_error(" Unknown user '%s'", optarg); 415 message_error(" Unknown user '%s'", optarg);
415 } 416 }
416 else 417 else
417 { 418 {
418 gstate->pselect.uid = i; 419 gstate->pselect.uid = i;
419 } 420 }
420 break; 421 break;
421 422
422 case 'm': 423 case 'm':
423 i = atoi(optarg); 424 i = atoi(optarg);
424 gstate->pselect.mode = i; 425 gstate->pselect.mode = i;
425 break; 426 break;
426 427
427 case 'S': 428 case 'S':
428 gstate->pselect.system = !gstate->pselect.system; 429 gstate->pselect.system = !gstate->pselect.system;
429 break; 430 break;
430 431
431 case 'I': 432 case 'I':
432 gstate->pselect.idle = !gstate->pselect.idle; 433 gstate->pselect.idle = !gstate->pselect.idle;
433 break; 434 break;
434 435
435#ifdef ENABLE_COLOR 436#ifdef ENABLE_COLOR
436 case 'T': 437 case 'T':
437 gstate->show_tags = 1; 438 gstate->show_tags = 1;
438 break; 439 break;
439#endif 440#endif
440 441
441 case 'c': 442 case 'c':
442 gstate->pselect.fullcmd = !gstate->pselect.fullcmd; 443 gstate->pselect.fullcmd = !gstate->pselect.fullcmd;
443 break; 444 break;
444 445
445 case 't': 446 case 't':
446 gstate->pselect.threads = !gstate->pselect.threads; 447 gstate->pselect.threads = !gstate->pselect.threads;
447 break; 448 break;
448 449
449 case 'p': 450 case 'p':
450 gstate->pselect.pid = atoi(optarg); 451 gstate->pselect.pid = atoi(optarg);
451 break; 452 break;
452 453
453 case 'q': /* be quick about it */ 454 case 'q': /* be quick about it */
454 /* only allow this if user is really root */ 455 /* only allow this if user is really root */
455 if (getuid() == 0) 456 if (getuid() == 0)
456 { 457 {
457 /* be very un-nice! */ 458 /* be very un-nice! */
458 (void) nice(-20); 459 (void) nice(-20);
459 } 460 }
460 else 461 else
461 { 462 {
462 message_error(" Option -q can only be used by root"); 463 message_error(" Option -q can only be used by root");
463 } 464 }
464 break; 465 break;
465 466
466 default: 467 default:
467 fprintf(stderr, "\ 468 fprintf(stderr, "\
468Top version %s\n\ 469Top version %s\n\
469Usage: %s [-1CISTabcinqtuv] [-d count] [-m mode] [-o field] [-p pid]\n\ 470Usage: %s [-1CISTabcinqtuv] [-d count] [-m mode] [-o field] [-p pid]\n\
470 [-s time] [-U username] [number]\n", 471 [-s time] [-U username] [number]\n",
471 version_string(), myname); 472 version_string(), myname);
472 exit(EX_USAGE); 473 exit(EX_USAGE);
473 } 474 }
474 } 475 }
475 476
476 /* get count of top processes to display */ 477 /* get count of top processes to display */
477 if (optind < ac && *av[optind]) 478 if (optind < ac && *av[optind])
478 { 479 {
479 if ((i = atoiwi(av[optind])) == Invalid) 480 if ((i = atoiwi(av[optind])) == Invalid)
480 { 481 {
481 message_error(" Process count not a number"); 482 message_error(" Process count not a number");
482 } 483 }
483 else 484 else
484 { 485 {
485 gstate->topn = i; 486 gstate->topn = i;
486 } 487 }
487 } 488 }
488} 489}
489 490
490static void 491static void
491do_display(globalstate *gstate) 492do_display(globalstate *gstate)
492 493
493{ 494{
494 int active_procs; 495 int active_procs;
495 int i; 496 int i;
496 time_t curr_time; 497 time_t curr_time;
497 caddr_t processes; 498 caddr_t processes;
498 struct system_info system_info; 499 struct system_info system_info;
499 char *hdr; 500 char *hdr;
500 501
501 /* get the time */ 502 /* get the time */
502 time_mark(&(gstate->now)); 503 time_mark(&(gstate->now));
503 curr_time = (time_t)(gstate->now.tv_sec); 504 curr_time = (time_t)(gstate->now.tv_sec);
504 505
505 /* get the current stats */ 506 /* get the current stats */
506 get_system_info(&system_info); 507 get_system_info(&system_info);
507 508
508 /* get the current processes */ 509 /* get the current processes */
509 processes = get_process_info(&system_info, &(gstate->pselect), gstate->order_index); 510 processes = get_process_info(&system_info, &(gstate->pselect), gstate->order_index);
510 511
511 /* determine number of processes to actually display */ 512 /* determine number of processes to actually display */
512 if (gstate->topn > 0) 513 if (gstate->topn > 0)
513 { 514 {
514 /* this number will be the smallest of: active processes, 515 /* this number will be the smallest of: active processes,
515 number user requested, number current screen accomodates */ 516 number user requested, number current screen accomodates */
516 active_procs = system_info.P_ACTIVE; 517 active_procs = system_info.P_ACTIVE;
517 if (active_procs > gstate->topn) 518 if (active_procs > gstate->topn)
518 { 519 {
519 active_procs = gstate->topn; 520 active_procs = gstate->topn;
520 } 521 }
521 if (active_procs > gstate->max_topn) 522 if (active_procs > gstate->max_topn)
522 { 523 {
523 active_procs = gstate->max_topn; 524 active_procs = gstate->max_topn;
524 } 525 }
525 } 526 }
526 else 527 else
527 { 528 {
528 /* dont show any */ 529 /* dont show any */
529 active_procs = 0; 530 active_procs = 0;
530 } 531 }
531 532
532#ifdef HAVE_FORMAT_PROCESS_HEADER 533#ifdef HAVE_FORMAT_PROCESS_HEADER
533 /* get the process header to use */ 534 /* get the process header to use */
534 hdr = format_process_header(&(gstate->pselect), processes, active_procs); 535 hdr = format_process_header(&(gstate->pselect), processes, active_procs);
535#else 536#else
536 hdr = gstate->header_text; 537 hdr = gstate->header_text;
537#endif 538#endif
538 539
539 /* full screen or update? */ 540 /* full screen or update? */
540 if (gstate->fulldraw) 541 if (gstate->fulldraw)
541 { 542 {
542 display_clear(); 543 display_clear();
543 i_loadave(system_info.last_pid, system_info.load_avg); 544 i_loadave(system_info.last_pid, system_info.load_avg);
544 i_uptime(&(gstate->statics->boottime), &curr_time); 545 i_uptime(&(gstate->statics->boottime), &curr_time);
545 i_timeofday(&curr_time); 546 i_timeofday(&curr_time);
546 i_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads); 547 i_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads);
547 if (gstate->show_cpustates) 548 if (gstate->show_cpustates)
548 { 549 {
549 i_cpustates(system_info.cpustates); 550 i_cpustates(system_info.cpustates);
550 } 551 }
551 else 552 else
552 { 553 {
553 if (smart_terminal) 554 if (smart_terminal)
554 { 555 {
555 z_cpustates(); 556 z_cpustates();
556 } 557 }
557 gstate->show_cpustates = Yes; 558 gstate->show_cpustates = Yes;
558 } 559 }
559 i_kernel(system_info.kernel); 560 i_kernel(system_info.kernel);
560 i_memory(system_info.memory); 561 i_memory(system_info.memory);
561 i_swap(system_info.swap); 562 i_swap(system_info.swap);
562 i_message(&(gstate->now)); 563 i_message(&(gstate->now));
563 i_header(hdr); 564 i_header(hdr);
564 for (i = 0; i < active_procs; i++) 565 for (i = 0; i < active_procs; i++)
565 { 566 {
566 i_process(i, format_next_process(processes, gstate->get_userid)); 567 i_process(i, format_next_process(processes, gstate->get_userid));
567 } 568 }
568 i_endscreen(); 569 i_endscreen();
569 if (gstate->smart_terminal) 570 if (gstate->smart_terminal)
570 { 571 {
571 gstate->fulldraw = No; 572 gstate->fulldraw = No;
572 } 573 }
573 } 574 }
574 else 575 else
575 { 576 {
576 u_loadave(system_info.last_pid, system_info.load_avg); 577 u_loadave(system_info.last_pid, system_info.load_avg);
577 u_uptime(&(gstate->statics->boottime), &curr_time); 578 u_uptime(&(gstate->statics->boottime), &curr_time);
578 i_timeofday(&curr_time); 579 i_timeofday(&curr_time);
579 u_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads); 580 u_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads);
580 u_cpustates(system_info.cpustates); 581 u_cpustates(system_info.cpustates);
581 u_kernel(system_info.kernel); 582 u_kernel(system_info.kernel);
582 u_memory(system_info.memory); 583 u_memory(system_info.memory);
583 u_swap(system_info.swap); 584 u_swap(system_info.swap);
584 u_message(&(gstate->now)); 585 u_message(&(gstate->now));
585 u_header(hdr); 586 u_header(hdr);
586 for (i = 0; i < active_procs; i++) 587 for (i = 0; i < active_procs; i++)
587 { 588 {
588 u_process(i, format_next_process(processes, gstate->get_userid)); 589 u_process(i, format_next_process(processes, gstate->get_userid));
589 } 590 }
590 u_endscreen(); 591 u_endscreen();
591 } 592 }
592} 593}
593 594
594#ifdef DEBUG 595#ifdef DEBUG
595void 596void
596timeval_xdprint(char *s, struct timeval tv) 597timeval_xdprint(char *s, struct timeval tv)
597 598
598{ 599{
599 xdprintf("%s %d.%06d\n", s, tv.tv_sec, tv.tv_usec); 600 xdprintf("%s %d.%06d\n", s, tv.tv_sec, tv.tv_usec);
600} 601}
601#endif 602#endif
602 603
603static void 604static void
604do_wait(globalstate *gstate) 605do_wait(globalstate *gstate)
605 606
606{ 607{
607 struct timeval wait; 608 struct timeval wait;
608 609
609 double2tv(&wait, gstate->delay); 610 double2tv(&wait, gstate->delay);
610 select(0, NULL, NULL, NULL, &wait); 611 select(0, NULL, NULL, NULL, &wait);
611} 612}
612 613
613static void 614static void
614do_command(globalstate *gstate) 615do_command(globalstate *gstate)
615 616
616{ 617{
617 int status; 618 int status;
618 struct timeval wait = {0, 0}; 619 struct timeval wait = {0, 0};
619 struct timeval now; 620 struct timeval now;
620 fd_set readfds; 621 fd_set readfds;
621 unsigned char ch; 622 unsigned char ch;
622 623
623 /* calculate new refresh time */ 624 /* calculate new refresh time */
624 gstate->refresh = gstate->now; 625 gstate->refresh = gstate->now;
625 double2tv(&now, gstate->delay); 626 double2tv(&now, gstate->delay);
626 timeradd(&now, &gstate->refresh, &gstate->refresh); 627 timeradd(&now, &gstate->refresh, &gstate->refresh);
627 time_get(&now); 628 time_get(&now);
628 629
629 /* loop waiting for time to expire */ 630 /* loop waiting for time to expire */
630 do { 631 do {
631 /* calculate time to wait */ 632 /* calculate time to wait */
632 if (gstate->delay > 0) 633 if (gstate->delay > 0)
633 { 634 {
634 wait = gstate->refresh; 635 wait = gstate->refresh;
635 wait.tv_usec -= now.tv_usec; 636 wait.tv_usec -= now.tv_usec;
636 if (wait.tv_usec < 0) 637 if (wait.tv_usec < 0)
637 { 638 {
638 wait.tv_usec += 1000000; 639 wait.tv_usec += 1000000;
639 wait.tv_sec--; 640 wait.tv_sec--;
640 } 641 }
641 wait.tv_sec -= now.tv_sec; 642 wait.tv_sec -= now.tv_sec;
642 } 643 }
643 644
644 /* set up arguments for select on stdin (0) */ 645 /* set up arguments for select on stdin (0) */
645 FD_ZERO(&readfds); 646 FD_ZERO(&readfds);
646 FD_SET(STDIN_FILENO, &readfds); 647 FD_SET(STDIN_FILENO, &readfds);
647 648
648 /* wait for something to read or time out */ 649 /* wait for something to read or time out */
649 if (select(32, &readfds, NULL, NULL, &wait) > 0) 650 if (select(32, &readfds, NULL, NULL, &wait) > 0)
650 { 651 {
651 /* read it */ 652 /* read it */
652 if (read(STDIN_FILENO, &ch, 1) != 1) 653 if (read(STDIN_FILENO, &ch, 1) != 1)
653 { 654 {
654 /* read error */ 655 /* read error */
655 message_error(" Read error on stdin"); 656 message_error(" Read error on stdin");
656 quit(EX_DATAERR); 657 quit(EX_DATAERR);
657 /*NOTREACHED*/ 658 /*NOTREACHED*/
658 } 659 }
659 660
660 /* mark pending messages as old */ 661 /* mark pending messages as old */
661 message_mark(); 662 message_mark();
662 663
663 /* dispatch */ 664 /* dispatch */
664 status = command_process(gstate, (int)ch); 665 status = command_process(gstate, (int)ch);
665 switch(status) 666 switch(status)
666 { 667 {
667 case CMD_ERROR: 668 case CMD_ERROR:
668 quit(EX_SOFTWARE); 669 quit(EX_SOFTWARE);
669 /*NOTREACHED*/ 670 /*NOTREACHED*/
670  671
671 case CMD_REFRESH: 672 case CMD_REFRESH:
672 return; 673 return;
673 674
674 case CMD_UNKNOWN: 675 case CMD_UNKNOWN:
675 message_error(" Unknown command"); 676 message_error(" Unknown command");
676 break; 677 break;
677 678
678 case CMD_NA: 679 case CMD_NA:
679 message_error(" Command not available"); 680 message_error(" Command not available");
680 } 681 }
681 } 682 }
682 683
683 /* get new time */ 684 /* get new time */
684 time_get(&now); 685 time_get(&now);
685 } while (timercmp(&now, &(gstate->refresh), < )); 686 } while (timercmp(&now, &(gstate->refresh), < ));
686} 687}
687 688
688static void 689static void
689do_minidisplay(globalstate *gstate) 690do_minidisplay(globalstate *gstate)
690 691
691{ 692{
692 double real_delay; 693 double real_delay;
693 struct system_info si; 694 struct system_info si;
694 695
695 /* save the real delay and substitute 1 second */ 696 /* save the real delay and substitute 1 second */
696 real_delay = gstate->delay; 697 real_delay = gstate->delay;
697 gstate->delay = 1; 698 gstate->delay = 1;
698 699
699 /* wait 1 second for a command */ 700 /* wait 1 second for a command */
700 time_mark(&(gstate->now)); 701 time_mark(&(gstate->now));
701 do_command(gstate); 702 do_command(gstate);
702 703
703 /* do a mini update that only updates the cpustates */ 704 /* do a mini update that only updates the cpustates */
704 get_system_info(&si); 705 get_system_info(&si);
705 u_cpustates(si.cpustates); 706 u_cpustates(si.cpustates);
706 707
707 /* restore the delay time */ 708 /* restore the delay time */
708 gstate->delay = real_delay; 709 gstate->delay = real_delay;
709 710
710 /* done */ 711 /* done */
711 i_endscreen(); 712 i_endscreen();
712} 713}
713 714
714int 715int
715main(int argc, char *argv[]) 716main(int argc, char *argv[])
716 717
717{ 718{
718 char *env_top; 719 char *env_top;
719 char **preset_argv; 720 char **preset_argv;
720 int preset_argc = 0; 721 int preset_argc = 0;
721 void *mask; 722 void *mask;
722 volatile int need_mini = 1; 723 volatile int need_mini = 1;
723 static char top[] = "top"; 724 static char top[] = "top";
724 725
725 struct statics statics; 726 struct statics statics;
726 globalstate *gstate; 727 globalstate *gstate;
727 728
728 /* get our name */ 729 /* get our name */
729 if (argc > 0) 730 if (argc > 0)
730 { 731 {
731 if ((myname = strrchr(argv[0], '/')) == 0) 732 if ((myname = strrchr(argv[0], '/')) == 0)
732 { 733 {
733 myname = argv[0]; 734 myname = argv[0];
734 } 735 }
735 else 736 else
736 { 737 {
737 myname++; 738 myname++;
738 } 739 }
739 } else 740 } else
740 myname = top; 741 myname = top;
741 742
742 743
743 /* binary compatibility check */ 744 /* binary compatibility check */
744#ifdef HAVE_UNAME 745#ifdef HAVE_UNAME
745 { 746 {
746 struct utsname uts; 747 struct utsname uts;
747 748
748 if (uname(&uts) == 0) 749 if (uname(&uts) == 0)
749 { 750 {
750 if (strcmp(uts.machine, UNAME_HARDWARE) != 0) 751 if (strcmp(uts.machine, UNAME_HARDWARE) != 0)
751 { 752 {
752 fprintf(stderr, "%s: incompatible hardware platform\n", 753 fprintf(stderr, "%s: incompatible hardware platform\n",
753 myname); 754 myname);
754 exit(EX_UNAVAILABLE); 755 exit(EX_UNAVAILABLE);
755 } 756 }
756 } 757 }
757 } 758 }
758#endif 759#endif
759 760
760 /* initialization */ 761 /* initialization */
761 gstate = ecalloc(1, sizeof(globalstate)); 762 gstate = ecalloc(1, sizeof(globalstate));
762 gstate->statics = &statics; 763 gstate->statics = &statics;
763 time_mark(NULL); 764 time_mark(NULL);
764 765
765 /* preset defaults for various options */ 766 /* preset defaults for various options */
766 gstate->show_usernames = Yes; 767 gstate->show_usernames = Yes;
767 gstate->topn = DEFAULT_TOPN; 768 gstate->topn = DEFAULT_TOPN;
768 gstate->delay = DEFAULT_DELAY; 769 gstate->delay = DEFAULT_DELAY;
769 gstate->fulldraw = Yes; 770 gstate->fulldraw = Yes;
770 gstate->use_color = Yes; 771 gstate->use_color = Yes;
771 gstate->interactive = Maybe; 772 gstate->interactive = Maybe;
772 gstate->percpustates = No; 773 gstate->percpustates = No;
773 774
774 /* preset defaults for process selection */ 775 /* preset defaults for process selection */
775 gstate->pselect.idle = Yes; 776 gstate->pselect.idle = Yes;
776 gstate->pselect.system = Yes; 777 gstate->pselect.system = Yes;
777 gstate->pselect.fullcmd = No; 778 gstate->pselect.fullcmd = No;
778 gstate->pselect.command = NULL; 779 gstate->pselect.command = NULL;
779 gstate->pselect.uid = -1; 780 gstate->pselect.uid = -1;
780 gstate->pselect.pid = -1; 781 gstate->pselect.pid = -1;
781 gstate->pselect.mode = 0; 782 gstate->pselect.mode = 0;
782 783
783 /* use a large buffer for stdout */ 784 /* use a large buffer for stdout */
784#ifdef HAVE_SETVBUF 785#ifdef HAVE_SETVBUF
785 setvbuf(stdout, stdoutbuf, _IOFBF, BUFFERSIZE); 786 setvbuf(stdout, stdoutbuf, _IOFBF, BUFFERSIZE);
786#else 787#else
787#ifdef HAVE_SETBUFFER 788#ifdef HAVE_SETBUFFER
788 setbuffer(stdout, stdoutbuf, BUFFERSIZE); 789 setbuffer(stdout, stdoutbuf, BUFFERSIZE);
789#endif 790#endif
790#endif 791#endif
791 792
792 /* get preset options from the environment */ 793 /* get preset options from the environment */
793 if ((env_top = getenv("TOP")) != NULL) 794 if ((env_top = getenv("TOP")) != NULL)
794 { 795 {
795 preset_argv = argparse(env_top, &preset_argc); 796 preset_argv = argparse(env_top, &preset_argc);
796 preset_argv[0] = myname; 797 preset_argv[0] = myname;
797 do_arguments(gstate, preset_argc, preset_argv); 798 do_arguments(gstate, preset_argc, preset_argv);
798 } 799 }
799 800
800 /* process arguments */ 801 /* process arguments */
801 do_arguments(gstate, argc, argv); 802 do_arguments(gstate, argc, argv);
802 803
803#ifdef ENABLE_COLOR 804#ifdef ENABLE_COLOR
804 /* If colour has been turned on read in the settings. */ 805 /* If colour has been turned on read in the settings. */
805 env_top = getenv("TOPCOLOURS"); 806 env_top = getenv("TOPCOLOURS");
806 if (!env_top) 807 if (!env_top)
807 { 808 {
808 env_top = getenv("TOPCOLORS"); 809 env_top = getenv("TOPCOLORS");
809 } 810 }
810 /* must do something about error messages */ 811 /* must do something about error messages */
811 color_env_parse(env_top); 812 color_env_parse(env_top);
812 color_activate(gstate->use_color); 813 color_activate(gstate->use_color);
813#endif 814#endif
814 815
815 /* in order to support forward compatability, we have to ensure that 816 /* in order to support forward compatability, we have to ensure that
816 the entire statics structure is set to a known value before we call 817 the entire statics structure is set to a known value before we call
817 machine_init. This way fields that a module does not know about 818 machine_init. This way fields that a module does not know about
818 will retain their default values */ 819 will retain their default values */
819 memzero((void *)&statics, sizeof(statics)); 820 memzero((void *)&statics, sizeof(statics));
820 statics.boottime = -1; 821 statics.boottime = -1;
821 822
822 /* call the platform-specific init */ 823 /* call the platform-specific init */
823 if (machine_init(&statics) == -1) 824 if (machine_init(&statics) == -1)
824 { 825 {
825 exit(EX_SOFTWARE); 826 exit(EX_SOFTWARE);
826 } 827 }
827 828
828 /* create a helper list of sort order names */ 829 /* create a helper list of sort order names */
829 gstate->order_namelist = string_list(statics.order_names); 830 gstate->order_namelist = string_list(statics.order_names);
830 831
831 /* look up chosen sorting order */ 832 /* look up chosen sorting order */
832 if (gstate->order_name != NULL) 833 if (gstate->order_name != NULL)
833 { 834 {
834 int i; 835 int i;
835 836
836 if (statics.order_names == NULL) 837 if (statics.order_names == NULL)
837 { 838 {
838 message_error(" This platform does not support arbitrary ordering"); 839 message_error(" This platform does not support arbitrary ordering");
839 } 840 }
840 else if ((i = string_index(gstate->order_name, 841 else if ((i = string_index(gstate->order_name,
841 statics.order_names)) == -1) 842 statics.order_names)) == -1)
842 { 843 {
843 message_error(" Sort order `%s' not recognized", gstate->order_name); 844 message_error(" Sort order `%s' not recognized", gstate->order_name);
844 message_error(" Recognized sort orders: %s", gstate->order_namelist); 845 message_error(" Recognized sort orders: %s", gstate->order_namelist);
845 } 846 }
846 else 847 else
847 { 848 {
848 gstate->order_index = i; 849 gstate->order_index = i;
849 } 850 }
850 } 851 }
851 852
852 /* initialize extensions */ 853 /* initialize extensions */
853 init_username(); 854 init_username();
854 855
855 /* initialize termcap */ 856 /* initialize termcap */
856 gstate->smart_terminal = screen_readtermcap(gstate->interactive); 857 gstate->smart_terminal = screen_readtermcap(gstate->interactive);
857 858
858 /* determine interactive state */ 859 /* determine interactive state */
859 if (gstate->interactive == Maybe) 860 if (gstate->interactive == Maybe)
860 { 861 {
861 gstate->interactive = smart_terminal; 862 gstate->interactive = smart_terminal;
862 } 863 }
863 864
864 /* if displays were not specified, choose an appropriate default */ 865 /* if displays were not specified, choose an appropriate default */
865 if (gstate->displays == 0) 866 if (gstate->displays == 0)
866 { 867 {
867 gstate->displays = gstate->smart_terminal ? Infinity: 1; 868 gstate->displays = gstate->smart_terminal ? Infinity: 1;
868 } 869 }
869 870
870 /* we don't need a mini display when delay is less than 2 871 /* we don't need a mini display when delay is less than 2
871 seconds or when we are not on a smart terminal */ 872 seconds or when we are not on a smart terminal */
872 if (gstate->delay <= 1 || !smart_terminal) 873 if (gstate->delay <= 1 || !smart_terminal)
873 { 874 {
874 need_mini = 0; 875 need_mini = 0;
875 } 876 }
876 877
877#ifndef HAVE_FORMAT_PROCESS_HEADER 878#ifndef HAVE_FORMAT_PROCESS_HEADER
878 /* set constants for username/uid display */ 879 /* set constants for username/uid display */
879 if (gstate->show_usernames) 880 if (gstate->show_usernames)
880 { 881 {
881 gstate->header_text = format_header("USERNAME"); 882 gstate->header_text = format_header("USERNAME");
882 gstate->get_userid = username; 883 gstate->get_userid = username;
883 } 884 }
884 else 885 else
885 { 886 {
886 gstate->header_text = format_header(" UID "); 887 gstate->header_text = format_header(" UID ");
887 gstate->get_userid = itoa7; 888 gstate->get_userid = itoa7;
888 } 889 }
889#endif 890#endif
890 gstate->pselect.usernames = gstate->show_usernames; 891 gstate->pselect.usernames = gstate->show_usernames;
891 892
892 /* initialize display */ 893 /* initialize display */
893 if ((gstate->max_topn = display_init(&statics, gstate->percpustates)) == -1) 894 if ((gstate->max_topn = display_init(&statics, gstate->percpustates)) == -1)
894 { 895 {
895 fprintf(stderr, "%s: display too small\n", myname); 896 fprintf(stderr, "%s: display too small\n", myname);
896 exit(EX_OSERR); 897 exit(EX_OSERR);
897 } 898 }
898 899
899 /* check for infinity and for overflowed screen */ 900 /* check for infinity and for overflowed screen */
900 if (gstate->topn == Infinity) 901 if (gstate->topn == Infinity)
901 { 902 {
902 gstate->topn = INT_MAX; 903 gstate->topn = INT_MAX;
903 } 904 }
904 else if (gstate->topn > gstate->max_topn) 905 else if (gstate->topn > gstate->max_topn)
905 { 906 {
906 message_error(" This terminal can only display %d processes", 907 message_error(" This terminal can only display %d processes",
907 gstate->max_topn); 908 gstate->max_topn);
908 } 909 }
909 910
910#ifdef ENABLE_COLOR 911#ifdef ENABLE_COLOR
911 /* producing a list of color tags is easy */ 912 /* producing a list of color tags is easy */
912 if (gstate->show_tags) 913 if (gstate->show_tags)
913 { 914 {
914 color_dump(stdout); 915 color_dump(stdout);
915 exit(EX_OK); 916 exit(EX_OK);
916 } 917 }
917#endif 918#endif
918 919
919 /* hold all signals while we initialize the screen */ 920 /* hold all signals while we initialize the screen */
920 mask = hold_signals(); 921 mask = hold_signals();
921 screen_init(); 922 screen_init();
922 923
923 /* set the signal handlers */ 924 /* set the signal handlers */
924 set_signals(); 925 set_signals();
925 926
926 /* longjmp re-entry point */ 927 /* longjmp re-entry point */
927 /* set the jump buffer for long jumps out of signal handlers */ 928 /* set the jump buffer for long jumps out of signal handlers */
928 if (setjmp(jmp_int) != 0) 929 if (setjmp(jmp_int) != 0)
929 { 930 {
930 /* this is where we end up after processing sigwinch or sigtstp */ 931 /* this is where we end up after processing sigwinch or sigtstp */
931 932
932 /* tell display to resize its buffers, and get the new length */ 933 /* tell display to resize its buffers, and get the new length */
933 if ((gstate->max_topn = display_resize()) == -1) 934 if ((gstate->max_topn = display_resize()) == -1)
934 { 935 {
935 /* thats bad */ 936 /* thats bad */
936 quit(EX_OSERR); 937 quit(EX_OSERR);
937 /*NOTREACHED*/ 938 /*NOTREACHED*/
938 } 939 }
939 940
940 /* set up for a full redraw, and get the current line count */ 941 /* set up for a full redraw, and get the current line count */
941 gstate->fulldraw = Yes; 942 gstate->fulldraw = Yes;
942 943
943 /* safe to release the signals now */ 944 /* safe to release the signals now */
944 release_signals(mask); 945 release_signals(mask);
945 } 946 }
946 else 947 else
947 { 948 {
948 /* release the signals */ 949 /* release the signals */
949 release_signals(mask); 950 release_signals(mask);
950 951
951 /* some systems require a warmup */ 952 /* some systems require a warmup */
952 /* always do a warmup for batch mode */ 953 /* always do a warmup for batch mode */
953 if (gstate->interactive == 0 || statics.flags.warmup) 954 if (gstate->interactive == 0 || statics.flags.warmup)
954 { 955 {
955 struct system_info system_info; 956 struct system_info system_info;
956 struct timeval timeout; 957 struct timeval timeout;
957 958
958 time_mark(&(gstate->now)); 959 time_mark(&(gstate->now));
959 get_system_info(&system_info); 960 get_system_info(&system_info);
960 (void)get_process_info(&system_info, &gstate->pselect, 0); 961 (void)get_process_info(&system_info, &gstate->pselect, 0);
961 timeout.tv_sec = 1; 962 timeout.tv_sec = 1;
962 timeout.tv_usec = 0; 963 timeout.tv_usec = 0;
963 select(0, NULL, NULL, NULL, &timeout); 964 select(0, NULL, NULL, NULL, &timeout);
964 965
965 /* if we've warmed up, then we can show good states too */ 966 /* if we've warmed up, then we can show good states too */
966 gstate->show_cpustates = Yes; 967 gstate->show_cpustates = Yes;
967 need_mini = 0; 968 need_mini = 0;
968 } 969 }
969 } 970 }
970 971
971 /* main loop */ 972 /* main loop */
972 while ((gstate->displays == -1) || (--gstate->displays > 0)) 973 while ((gstate->displays == -1) || (--gstate->displays > 0))
973 { 974 {
974 do_display(gstate); 975 do_display(gstate);
975 if (gstate->interactive) 976 if (gstate->interactive)
976 { 977 {
977 if (need_mini) 978 if (need_mini)
978 { 979 {
979 do_minidisplay(gstate); 980 do_minidisplay(gstate);
980 need_mini = 0; 981 need_mini = 0;
981 } 982 }
982 do_command(gstate); 983 do_command(gstate);
983 } 984 }
984 else 985 else
985 { 986 {
986 do_wait(gstate); 987 do_wait(gstate);
987 } 988 }
988 } 989 }
989 990
990 /* do one last display */ 991 /* do one last display */
991 do_display(gstate); 992 do_display(gstate);
992 993
993 quit(EX_OK); 994 quit(EX_OK);
994 /* NOTREACHED */ 995 /* NOTREACHED */
995 return 1; /* Keep compiler quiet. */ 996 return 1; /* Keep compiler quiet. */
996} 997}