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
12 /* This file contains the routines that interface to termcap and stty/gtty.
14 * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
16 * I put in code to turn on the TOSTOP bit while top was running, but I
17 * didn't really like the results. If you desire it, turn on the
18 * preprocessor variable "TOStop". --wnl
21 #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 warnx("can't open termcap file");
101 warnx("no termcap entry for a `%s' terminal", term_name
);
104 /* pretend it's dumb and proceed */
105 smart_terminal
= false;
109 /* "hardcopy" immediately indicates a very stupid terminal */
112 smart_terminal
= false;
116 /* set up common terminal capabilities */
117 if ((screen_length
= tgetnum("li")) <= 0)
119 screen_length
= smart_terminal
= 0;
123 /* screen_width is a little different */
124 if ((screen_width
= tgetnum("co")) == -1)
133 /* terminals that overstrike need special attention */
134 overstrike
= tgetflag("os");
136 /* initialize the pointer into the termcap string buffer */
137 bufptr
= string_buffer
;
139 /* get "ce", clear to end */
142 clear_line
= tgetstr("ce", &bufptr
);
145 /* get necessary capabilities */
146 if ((clear_screen
= tgetstr("cl", &bufptr
)) == NULL
||
147 (cursor_motion
= tgetstr("cm", &bufptr
)) == NULL
)
149 smart_terminal
= false;
153 /* get some more sophisticated stuff -- these are optional */
154 clear_to_end
= tgetstr("cd", &bufptr
);
155 terminal_init
= tgetstr("ti", &bufptr
);
156 terminal_end
= tgetstr("te", &bufptr
);
157 start_standout
= tgetstr("so", &bufptr
);
158 end_standout
= tgetstr("se", &bufptr
);
161 PC
= (PCptr
= tgetstr("pc", &bufptr
)) ? *PCptr
: 0;
163 /* set convenience strings */
164 strncpy(home
, tgoto(cursor_motion
, 0, 0), sizeof(home
) - 1);
165 home
[sizeof(home
) - 1] = '\0';
166 /* (lower_left is set in get_screensize) */
168 /* get the actual screen size with an ioctl, if needed */
169 /* This may change screen_width and screen_length, and it always
173 /* if stdout is not a terminal, pretend we are a dumb terminal */
174 if (tcgetattr(STDOUT_FILENO
, &old_settings
) == -1)
176 smart_terminal
= false;
183 /* get the old settings for safe keeping */
184 if (tcgetattr(STDOUT_FILENO
, &old_settings
) != -1)
186 /* copy the settings so we can modify them */
187 new_settings
= old_settings
;
189 /* turn off ICANON, character echo and tab expansion */
190 new_settings
.c_lflag
&= ~(ICANON
|ECHO
);
191 new_settings
.c_oflag
&= ~(TAB3
);
192 new_settings
.c_cc
[VMIN
] = 1;
193 new_settings
.c_cc
[VTIME
] = 0;
194 tcsetattr(STDOUT_FILENO
, TCSADRAIN
, &new_settings
);
196 /* remember the erase and kill characters */
197 ch_erase
= old_settings
.c_cc
[VERASE
];
198 ch_kill
= old_settings
.c_cc
[VKILL
];
200 /* remember that it really is a terminal */
201 is_a_terminal
= true;
203 /* send the termcap initialization string */
204 putcap(terminal_init
);
209 /* not a terminal at all---consider it dumb */
210 smart_terminal
= false;
217 /* move to the lower left, clear the line and send "te" */
223 putcap(terminal_end
);
226 /* if we have settings to reset, then do so */
229 tcsetattr(STDOUT_FILENO
, TCSADRAIN
, &old_settings
);
236 /* install our settings if it is a terminal */
239 tcsetattr(STDOUT_FILENO
, TCSADRAIN
, &new_settings
);
242 /* send init string */
245 putcap(terminal_init
);
254 if (ioctl (1, TIOCGWINSZ
, &ws
) != -1)
258 screen_length
= ws
.ws_row
;
262 screen_width
= ws
.ws_col
- 1;
267 (void) strncpy(lower_left
, tgoto(cursor_motion
, 0, screen_length
- 1),
268 sizeof(lower_left
) - 1);
269 lower_left
[sizeof(lower_left
) - 1] = '\0';
273 top_standout(const char *msg
)
277 putcap(start_standout
);
279 putcap(end_standout
);
292 putcap(clear_screen
);
299 if (smart_terminal
&& !overstrike
&& len
> 0)