1 /* $OpenBSD: screen.c,v 1.22 2019/10/08 07:26:59 kn Exp $ */ 2 3 /* 4 * Top users/processes display for Unix 5 * Version 3 6 * 7 * Copyright (c) 1984, 1989, William LeFebvre, Rice University 8 * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR OR HIS EMPLOYER BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * This file contains the routines that interface to termcap and stty/gtty. 33 * 34 * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty. 35 * 36 * I put in code to turn on the TOSTOP bit while top was running, but I didn't 37 * really like the results. If you desire it, turn on the preprocessor 38 * variable "TOStop". --wnl 39 */ 40 41 #include <sys/types.h> 42 #include <sys/ioctl.h> 43 #include <curses.h> 44 #include <err.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <term.h> 48 #include <unistd.h> 49 #include <stdbool.h> 50 51 #include "top.h" 52 #include "screen.h" 53 #include "layout.h" 54 55 int screen_length, screen_width; 56 char ch_erase, ch_kill, smart_terminal; 57 58 static struct termios old_settings, new_settings; 59 static char is_a_terminal = false; 60 61 void 62 init_termcap(int interactive) 63 { 64 char *term_name; 65 int status; 66 67 /* set defaults in case we aren't smart */ 68 screen_width = MAX_COLS; 69 screen_length = 0; 70 71 if (!interactive) { 72 /* pretend we have a dumb terminal */ 73 smart_terminal = false; 74 return; 75 } 76 /* assume we have a smart terminal until proven otherwise */ 77 smart_terminal = true; 78 79 /* get the terminal name */ 80 term_name = getenv("TERM"); 81 82 /* if there is no TERM, assume it's a dumb terminal */ 83 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */ 84 if (term_name == NULL) { 85 smart_terminal = false; 86 return; 87 } 88 89 /* now get the termcap entry */ 90 if ((status = tgetent(NULL, term_name)) != 1) { 91 if (status == -1) 92 warnx("can't open termcap file"); 93 else 94 warnx("no termcap entry for a `%s' terminal", term_name); 95 96 /* pretend it's dumb and proceed */ 97 smart_terminal = false; 98 return; 99 } 100 101 /* "hardcopy" immediately indicates a very stupid terminal */ 102 if (tgetflag("hc")) { 103 smart_terminal = false; 104 return; 105 } 106 107 /* set up common terminal capabilities */ 108 if ((screen_length = tgetnum("li")) <= y_procs) { 109 screen_length = smart_terminal = 0; 110 return; 111 } 112 113 /* screen_width is a little different */ 114 if ((screen_width = tgetnum("co")) == -1) 115 screen_width = 79; 116 else 117 screen_width -= 1; 118 119 /* get necessary capabilities */ 120 if (tgetstr("cl", NULL) == NULL || tgetstr("cm", NULL) == NULL) { 121 smart_terminal = false; 122 return; 123 } 124 125 /* get the actual screen size with an ioctl, if needed */ 126 /* 127 * This may change screen_width and screen_length, and it always sets 128 * lower_left. 129 */ 130 get_screensize(); 131 132 /* if stdout is not a terminal, pretend we are a dumb terminal */ 133 if (tcgetattr(STDOUT_FILENO, &old_settings) == -1) 134 smart_terminal = false; 135 } 136 137 void 138 init_screen(void) 139 { 140 /* get the old settings for safe keeping */ 141 if (tcgetattr(STDOUT_FILENO, &old_settings) != -1) { 142 /* copy the settings so we can modify them */ 143 new_settings = old_settings; 144 /* turn off ICANON, character echo and tab expansion */ 145 new_settings.c_lflag &= ~(ICANON | ECHO); 146 new_settings.c_oflag &= ~(OXTABS); 147 new_settings.c_cc[VMIN] = 1; 148 new_settings.c_cc[VTIME] = 0; 149 150 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings); 151 /* remember the erase and kill characters */ 152 ch_erase = old_settings.c_cc[VERASE]; 153 ch_kill = old_settings.c_cc[VKILL]; 154 155 is_a_terminal = true; 156 #if 0 157 /* send the termcap initialization string */ 158 putcap(terminal_init); 159 #endif 160 } 161 if (!is_a_terminal) { 162 /* not a terminal at all---consider it dumb */ 163 smart_terminal = false; 164 } 165 166 if (smart_terminal) 167 initscr(); 168 } 169 170 void 171 end_screen(void) 172 { 173 if (smart_terminal) { 174 move(screen_length-1, 0); 175 clrtoeol(); 176 refresh(); 177 endwin(); 178 } 179 if (is_a_terminal) 180 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings); 181 } 182 183 void 184 reinit_screen(void) 185 { 186 #if 0 187 /* install our settings if it is a terminal */ 188 if (is_a_terminal) 189 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings); 190 191 /* send init string */ 192 if (smart_terminal) 193 putcap(terminal_init); 194 #endif 195 } 196 197 void 198 get_screensize(void) 199 { 200 struct winsize ws; 201 202 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) { 203 if (ws.ws_row != 0) 204 screen_length = ws.ws_row; 205 if (ws.ws_col != 0) 206 screen_width = ws.ws_col - 1; 207 } 208 } 209 210 void 211 go_home(void) 212 { 213 if (smart_terminal) { 214 move(0, 0); 215 refresh(); 216 } 217 } 218