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)
64 char termcap_buf[1024];
65 char string_buffer[1024];
78 static struct sgttyb old_settings;
79 static struct sgttyb new_settings;
82 static struct termio old_settings;
83 static struct termio new_settings;
86 static struct termios old_settings;
87 static struct termios new_settings;
89 static char is_a_terminal = No;
99 init_termcap(interactive)
110 /* set defaults in case we aren't smart */
111 screen_width = MAX_COLS;
116 /* pretend we have a dumb terminal */
121 /* assume we have a smart terminal until proven otherwise */
122 smart_terminal = Yes;
124 /* get the terminal name */
125 term_name = getenv("TERM");
127 /* if there is no TERM, assume it's a dumb terminal */
128 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
129 if (term_name == NULL)
135 /* now get the termcap entry */
136 if ((status = tgetent(termcap_buf, term_name)) != 1)
140 fprintf(stderr, "%s: can't open termcap file\n", myname);
144 fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
148 /* pretend it's dumb and proceed */
153 /* "hardcopy" immediately indicates a very stupid terminal */
160 /* set up common terminal capabilities */
161 if ((screen_length = tgetnum("li")) <= 0)
163 screen_length = smart_terminal = 0;
167 /* screen_width is a little different */
168 if ((screen_width = tgetnum("co")) == -1)
177 /* terminals that overstrike need special attention */
178 overstrike = tgetflag("os");
180 /* initialize the pointer into the termcap string buffer */
181 bufptr = string_buffer;
183 /* get "ce", clear to end */
186 clear_line = tgetstr("ce", &bufptr);
189 /* get necessary capabilities */
190 if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
191 (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
197 /* get some more sophisticated stuff -- these are optional */
198 clear_to_end = tgetstr("cd", &bufptr);
199 terminal_init = tgetstr("ti", &bufptr);
200 terminal_end = tgetstr("te", &bufptr);
201 start_standout = tgetstr("so", &bufptr);
202 end_standout = tgetstr("se", &bufptr);
205 PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
207 /* set convenience strings */
208 (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
209 home[sizeof(home) - 1] = '\0';
210 /* (lower_left is set in get_screensize) */
212 /* get the actual screen size with an ioctl, if needed */
213 /* This may change screen_width and screen_length, and it always
217 /* if stdout is not a terminal, pretend we are a dumb terminal */
219 if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
225 if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
231 if (tcgetattr(STDOUT, &old_settings) == -1)
241 /* get the old settings for safe keeping */
243 if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
245 /* copy the settings so we can modify them */
246 new_settings = old_settings;
248 /* turn on CBREAK and turn off character echo and tab expansion */
249 new_settings.sg_flags |= CBREAK;
250 new_settings.sg_flags &= ~(ECHO|XTABS);
251 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
253 /* remember the erase and kill characters */
254 ch_erase = old_settings.sg_erase;
255 ch_kill = old_settings.sg_kill;
258 /* get the local mode word */
259 (void) ioctl(STDOUT, TIOCLGET, &old_lword);
262 new_lword = old_lword | LTOSTOP;
263 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
265 /* remember that it really is a terminal */
268 /* send the termcap initialization string */
269 putcap(terminal_init);
273 if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
275 /* copy the settings so we can modify them */
276 new_settings = old_settings;
278 /* turn off ICANON, character echo and tab expansion */
279 new_settings.c_lflag &= ~(ICANON|ECHO);
280 new_settings.c_oflag &= ~(TAB3);
281 new_settings.c_cc[VMIN] = 1;
282 new_settings.c_cc[VTIME] = 0;
283 (void) ioctl(STDOUT, TCSETA, &new_settings);
285 /* remember the erase and kill characters */
286 ch_erase = old_settings.c_cc[VERASE];
287 ch_kill = old_settings.c_cc[VKILL];
289 /* remember that it really is a terminal */
292 /* send the termcap initialization string */
293 putcap(terminal_init);
297 if (tcgetattr(STDOUT, &old_settings) != -1)
299 /* copy the settings so we can modify them */
300 new_settings = old_settings;
302 /* turn off ICANON, character echo and tab expansion */
303 new_settings.c_lflag &= ~(ICANON|ECHO);
304 new_settings.c_oflag &= ~(TAB3);
305 new_settings.c_cc[VMIN] = 1;
306 new_settings.c_cc[VTIME] = 0;
307 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
309 /* remember the erase and kill characters */
310 ch_erase = old_settings.c_cc[VERASE];
311 ch_kill = old_settings.c_cc[VKILL];
313 /* remember that it really is a terminal */
316 /* send the termcap initialization string */
317 putcap(terminal_init);
323 /* not a terminal at all---consider it dumb */
331 /* move to the lower left, clear the line and send "te" */
337 putcap(terminal_end);
340 /* if we have settings to reset, then do so */
344 (void) ioctl(STDOUT, TIOCSETP, &old_settings);
346 (void) ioctl(STDOUT, TIOCLSET, &old_lword);
350 (void) ioctl(STDOUT, TCSETA, &old_settings);
353 (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
361 /* install our settings if it is a terminal */
365 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
367 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
371 (void) ioctl(STDOUT, TCSETA, &new_settings);
374 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
378 /* send init string */
381 putcap(terminal_init);
393 if (ioctl (1, TIOCGWINSZ, &ws) != -1)
397 screen_length = ws.ws_row;
401 screen_width = ws.ws_col - 1;
410 if (ioctl (1, TIOCGSIZE, &ts) != -1)
412 if (ts.ts_lines != 0)
414 screen_length = ts.ts_lines;
418 screen_width = ts.ts_cols - 1;
422 #endif /* TIOCGSIZE */
423 #endif /* TIOCGWINSZ */
425 (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
426 sizeof(lower_left) - 1);
427 lower_left[sizeof(lower_left) - 1] = '\0';
437 putcap(start_standout);
439 putcap(end_standout);
452 putcap(clear_screen);
461 if (smart_terminal && !overstrike && len > 0)
489 /* This has to be defined as a subroutine for tputs (instead of a macro) */