2 * Top users/processes display for Unix
5 * This program may be freely redistributed,
6 * but this entire comment MUST remain intact.
8 * Copyright (c) 1984, 1989, William LeFebvre, Rice University
9 * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
14 /* This file contains the routines that interface to termcap and stty/gtty.
16 * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
18 * I put in code to turn on the TOSTOP bit while top was running, but I
19 * didn't really like the results. If you desire it, turn on the
20 * preprocessor variable "TOStop". --wnl
23 #include <sys/ioctl.h>
40 static char termcap_buf[1024];
41 static char string_buffer[1024];
43 static char lower_left[15];
45 static char *clear_screen;
48 static char *start_standout;
49 static char *end_standout;
50 static char *terminal_init;
51 static char *terminal_end;
53 static struct termios old_settings;
54 static struct termios new_settings;
55 static char is_a_terminal = false;
57 #define NON_INTERACTIVE_MODE_VIRTUAL_SCREEN_WIDTH 1024
60 init_termcap(bool interactive)
72 /* pretend we have a dumb terminal */
73 screen_width = NON_INTERACTIVE_MODE_VIRTUAL_SCREEN_WIDTH;
74 smart_terminal = false;
78 /* assume we have a smart terminal until proven otherwise */
79 smart_terminal = true;
81 /* get the terminal name */
82 term_name = getenv("TERM");
84 /* if there is no TERM, assume it's a dumb terminal */
85 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
86 if (term_name == NULL)
88 smart_terminal = false;
92 /* now get the termcap entry */
93 if ((status = tgetent(termcap_buf, term_name)) != 1)
97 fprintf(stderr, "%s: can't open termcap file\n", myname);
101 fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
105 /* pretend it's dumb and proceed */
106 smart_terminal = false;
110 /* "hardcopy" immediately indicates a very stupid terminal */
113 smart_terminal = false;
117 /* set up common terminal capabilities */
118 if ((screen_length = tgetnum("li")) <= 0)
120 screen_length = smart_terminal = 0;
124 /* screen_width is a little different */
125 if ((screen_width = tgetnum("co")) == -1)
134 /* terminals that overstrike need special attention */
135 overstrike = tgetflag("os");
137 /* initialize the pointer into the termcap string buffer */
138 bufptr = string_buffer;
140 /* get "ce", clear to end */
143 clear_line = tgetstr("ce", &bufptr);
146 /* get necessary capabilities */
147 if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
148 (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
150 smart_terminal = false;
154 /* get some more sophisticated stuff -- these are optional */
155 clear_to_end = tgetstr("cd", &bufptr);
156 terminal_init = tgetstr("ti", &bufptr);
157 terminal_end = tgetstr("te", &bufptr);
158 start_standout = tgetstr("so", &bufptr);
159 end_standout = tgetstr("se", &bufptr);
162 PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
164 /* set convenience strings */
165 strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
166 home[sizeof(home) - 1] = '\0';
167 /* (lower_left is set in get_screensize) */
169 /* get the actual screen size with an ioctl, if needed */
170 /* This may change screen_width and screen_length, and it always
174 /* if stdout is not a terminal, pretend we are a dumb terminal */
175 if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
177 smart_terminal = false;
184 /* get the old settings for safe keeping */
185 if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
187 /* copy the settings so we can modify them */
188 new_settings = old_settings;
190 /* turn off ICANON, character echo and tab expansion */
191 new_settings.c_lflag &= ~(ICANON|ECHO);
192 new_settings.c_oflag &= ~(TAB3);
193 new_settings.c_cc[VMIN] = 1;
194 new_settings.c_cc[VTIME] = 0;
195 tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
197 /* remember the erase and kill characters */
198 ch_erase = old_settings.c_cc[VERASE];
199 ch_kill = old_settings.c_cc[VKILL];
201 /* remember that it really is a terminal */
202 is_a_terminal = true;
204 /* send the termcap initialization string */
205 putcap(terminal_init);
210 /* not a terminal at all---consider it dumb */
211 smart_terminal = false;
218 /* move to the lower left, clear the line and send "te" */
224 putcap(terminal_end);
227 /* if we have settings to reset, then do so */
230 tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
237 /* install our settings if it is a terminal */
240 tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
243 /* send init string */
246 putcap(terminal_init);
255 if (ioctl (1, TIOCGWINSZ, &ws) != -1)
259 screen_length = ws.ws_row;
263 screen_width = ws.ws_col - 1;
268 (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
269 sizeof(lower_left) - 1);
270 lower_left[sizeof(lower_left) - 1] = '\0';
274 top_standout(const char *msg)
278 putcap(start_standout);
280 putcap(end_standout);
293 putcap(clear_screen);
300 if (smart_terminal && !overstrike && len > 0)