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
26 #include <sys/ioctl.h>
39 #if defined(TERMIO) || defined(TERMIOS)
65 char termcap_buf[1024];
66 char string_buffer[1024];
79 static struct sgttyb old_settings;
80 static struct sgttyb new_settings;
83 static struct termio old_settings;
84 static struct termio new_settings;
87 static struct termios old_settings;
88 static struct termios new_settings;
90 static char is_a_terminal = No;
101 init_termcap(interactive)
112 /* set defaults in case we aren't smart */
113 screen_width = MAX_COLS;
118 /* pretend we have a dumb terminal */
123 /* assume we have a smart terminal until proven otherwise */
124 smart_terminal = Yes;
126 /* get the terminal name */
127 term_name = getenv("TERM");
129 /* if there is no TERM, assume it's a dumb terminal */
130 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
131 if (term_name == NULL)
137 /* now get the termcap entry */
138 if ((status = tgetent(termcap_buf, term_name)) != 1)
142 fprintf(stderr, "%s: can't open termcap file\n", myname);
146 fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
150 /* pretend it's dumb and proceed */
155 /* "hardcopy" immediately indicates a very stupid terminal */
162 /* set up common terminal capabilities */
163 if ((screen_length = tgetnum("li")) <= 0)
165 screen_length = smart_terminal = 0;
169 /* screen_width is a little different */
170 if ((screen_width = tgetnum("co")) == -1)
179 /* terminals that overstrike need special attention */
180 overstrike = tgetflag("os");
182 /* initialize the pointer into the termcap string buffer */
183 bufptr = string_buffer;
185 /* get "ce", clear to end */
188 clear_line = tgetstr("ce", &bufptr);
191 /* get necessary capabilities */
192 if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
193 (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
199 /* get some more sophisticated stuff -- these are optional */
200 clear_to_end = tgetstr("cd", &bufptr);
201 terminal_init = tgetstr("ti", &bufptr);
202 terminal_end = tgetstr("te", &bufptr);
203 start_standout = tgetstr("so", &bufptr);
204 end_standout = tgetstr("se", &bufptr);
207 PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
209 /* set convenience strings */
210 (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
211 home[sizeof(home) - 1] = '\0';
212 /* (lower_left is set in get_screensize) */
214 /* get the actual screen size with an ioctl, if needed */
215 /* This may change screen_width and screen_length, and it always
219 /* if stdout is not a terminal, pretend we are a dumb terminal */
221 if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
227 if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
233 if (tcgetattr(STDOUT, &old_settings) == -1)
244 /* get the old settings for safe keeping */
246 if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
248 /* copy the settings so we can modify them */
249 new_settings = old_settings;
251 /* turn on CBREAK and turn off character echo and tab expansion */
252 new_settings.sg_flags |= CBREAK;
253 new_settings.sg_flags &= ~(ECHO|XTABS);
254 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
256 /* remember the erase and kill characters */
257 ch_erase = old_settings.sg_erase;
258 ch_kill = old_settings.sg_kill;
261 /* get the local mode word */
262 (void) ioctl(STDOUT, TIOCLGET, &old_lword);
265 new_lword = old_lword | LTOSTOP;
266 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
268 /* remember that it really is a terminal */
271 /* send the termcap initialization string */
272 putcap(terminal_init);
276 if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
278 /* copy the settings so we can modify them */
279 new_settings = old_settings;
281 /* turn off ICANON, character echo and tab expansion */
282 new_settings.c_lflag &= ~(ICANON|ECHO);
283 new_settings.c_oflag &= ~(TAB3);
284 new_settings.c_cc[VMIN] = 1;
285 new_settings.c_cc[VTIME] = 0;
286 (void) ioctl(STDOUT, TCSETA, &new_settings);
288 /* remember the erase and kill characters */
289 ch_erase = old_settings.c_cc[VERASE];
290 ch_kill = old_settings.c_cc[VKILL];
292 /* remember that it really is a terminal */
295 /* send the termcap initialization string */
296 putcap(terminal_init);
300 if (tcgetattr(STDOUT, &old_settings) != -1)
302 /* copy the settings so we can modify them */
303 new_settings = old_settings;
305 /* turn off ICANON, character echo and tab expansion */
306 new_settings.c_lflag &= ~(ICANON|ECHO);
307 new_settings.c_oflag &= ~(TAB3);
308 new_settings.c_cc[VMIN] = 1;
309 new_settings.c_cc[VTIME] = 0;
310 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
312 /* remember the erase and kill characters */
313 ch_erase = old_settings.c_cc[VERASE];
314 ch_kill = old_settings.c_cc[VKILL];
316 /* remember that it really is a terminal */
319 /* send the termcap initialization string */
320 putcap(terminal_init);
326 /* not a terminal at all---consider it dumb */
335 /* move to the lower left, clear the line and send "te" */
341 putcap(terminal_end);
344 /* if we have settings to reset, then do so */
348 (void) ioctl(STDOUT, TIOCSETP, &old_settings);
350 (void) ioctl(STDOUT, TIOCLSET, &old_lword);
354 (void) ioctl(STDOUT, TCSETA, &old_settings);
357 (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
366 /* install our settings if it is a terminal */
370 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
372 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
376 (void) ioctl(STDOUT, TCSETA, &new_settings);
379 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
383 /* send init string */
386 putcap(terminal_init);
399 if (ioctl (1, TIOCGWINSZ, &ws) != -1)
403 screen_length = ws.ws_row;
407 screen_width = ws.ws_col - 1;
416 if (ioctl (1, TIOCGSIZE, &ts) != -1)
418 if (ts.ts_lines != 0)
420 screen_length = ts.ts_lines;
424 screen_width = ts.ts_cols - 1;
428 #endif /* TIOCGSIZE */
429 #endif /* TIOCGWINSZ */
431 (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
432 sizeof(lower_left) - 1);
433 lower_left[sizeof(lower_left) - 1] = '\0';
437 top_standout(char *msg)
441 putcap(start_standout);
443 putcap(end_standout);
456 putcap(clear_screen);
463 if (smart_terminal && !overstrike && len > 0)
492 /* This has to be defined as a subroutine for tputs (instead of a macro) */