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