1 /* $OpenBSD: cl_read.c,v 1.18 2009/10/27 23:59:47 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1993, 1994, 1995, 1996 7 * Keith Bostic. All rights reserved. 8 * 9 * See the LICENSE file for redistribution information. 10 */ 11 12 #include "config.h" 13 14 #include <sys/types.h> 15 #include <sys/queue.h> 16 #include <sys/time.h> 17 18 #include <bitstring.h> 19 #include <curses.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <poll.h> 23 #include <signal.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <termios.h> 28 #include <unistd.h> 29 30 #include "../common/common.h" 31 #include "../ex/script.h" 32 #include "cl.h" 33 34 static input_t cl_read(SCR *, 35 u_int32_t, CHAR_T *, size_t, int *, struct timeval *); 36 static int cl_resize(SCR *, size_t, size_t); 37 38 /* 39 * cl_event -- 40 * Return a single event. 41 * 42 * PUBLIC: int cl_event(SCR *, EVENT *, u_int32_t, int); 43 */ 44 int 45 cl_event(sp, evp, flags, ms) 46 SCR *sp; 47 EVENT *evp; 48 u_int32_t flags; 49 int ms; 50 { 51 struct timeval t, *tp; 52 CL_PRIVATE *clp; 53 size_t lines, columns; 54 int changed, nr; 55 56 /* 57 * Queue signal based events. We never clear SIGHUP or SIGTERM events, 58 * so that we just keep returning them until the editor dies. 59 */ 60 clp = CLP(sp); 61 retest: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) { 62 if (F_ISSET(clp, CL_SIGINT)) { 63 F_CLR(clp, CL_SIGINT); 64 evp->e_event = E_INTERRUPT; 65 } else 66 evp->e_event = E_TIMEOUT; 67 return (0); 68 } 69 if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) { 70 if (F_ISSET(clp, CL_SIGHUP)) { 71 evp->e_event = E_SIGHUP; 72 return (0); 73 } 74 if (F_ISSET(clp, CL_SIGTERM)) { 75 evp->e_event = E_SIGTERM; 76 return (0); 77 } 78 if (F_ISSET(clp, CL_SIGWINCH)) { 79 F_CLR(clp, CL_SIGWINCH); 80 if (cl_ssize(sp, 1, &lines, &columns, &changed)) 81 return (1); 82 if (changed) { 83 (void)cl_resize(sp, lines, columns); 84 evp->e_event = E_WRESIZE; 85 return (0); 86 } 87 /* No real change, ignore the signal. */ 88 } 89 } 90 91 /* Set timer. */ 92 if (ms == 0) 93 tp = NULL; 94 else { 95 t.tv_sec = ms / 1000; 96 t.tv_usec = (ms % 1000) * 1000; 97 tp = &t; 98 } 99 100 /* Read input characters. */ 101 switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW), 102 clp->ibuf, sizeof(clp->ibuf), &nr, tp)) { 103 case INP_OK: 104 evp->e_csp = clp->ibuf; 105 evp->e_len = nr; 106 evp->e_event = E_STRING; 107 break; 108 case INP_EOF: 109 evp->e_event = E_EOF; 110 break; 111 case INP_ERR: 112 evp->e_event = E_ERR; 113 break; 114 case INP_INTR: 115 goto retest; 116 case INP_TIMEOUT: 117 evp->e_event = E_TIMEOUT; 118 break; 119 default: 120 abort(); 121 } 122 return (0); 123 } 124 125 /* 126 * cl_read -- 127 * Read characters from the input. 128 */ 129 static input_t 130 cl_read(sp, flags, bp, blen, nrp, tp) 131 SCR *sp; 132 u_int32_t flags; 133 CHAR_T *bp; 134 size_t blen; 135 int *nrp; 136 struct timeval *tp; 137 { 138 struct termios term1, term2; 139 CL_PRIVATE *clp; 140 GS *gp; 141 struct pollfd pfd[1]; 142 input_t rval; 143 int nr, term_reset, timeout; 144 145 gp = sp->gp; 146 clp = CLP(sp); 147 term_reset = 0; 148 149 /* 150 * 1: A read from a file or a pipe. In this case, the reads 151 * never timeout regardless. This means that we can hang 152 * when trying to complete a map, but we're going to hang 153 * on the next read anyway. 154 */ 155 if (!F_ISSET(clp, CL_STDIN_TTY)) { 156 switch (nr = read(STDIN_FILENO, bp, blen)) { 157 case 0: 158 return (INP_EOF); 159 case -1: 160 goto err; 161 default: 162 *nrp = nr; 163 return (INP_OK); 164 } 165 /* NOTREACHED */ 166 } 167 168 /* 169 * 2: A read with an associated timeout, e.g., trying to complete 170 * a map sequence. If input exists, we fall into #3. 171 */ 172 tty_retry: 173 if (tp != NULL) { 174 pfd[0].fd = STDIN_FILENO; 175 pfd[0].events = POLLIN; 176 timeout = tp ? (tp->tv_sec * 1000) + (tp->tv_usec / 1000) : 0; 177 switch (poll(pfd, 1, timeout)) { 178 case 0: 179 return (INP_TIMEOUT); 180 case -1: 181 goto err; 182 default: 183 break; 184 } 185 } 186 187 /* 188 * The user can enter a key in the editor to quote a character. If we 189 * get here and the next key is supposed to be quoted, do what we can. 190 * Reset the tty so that the user can enter a ^C, ^Q, ^S. There's an 191 * obvious race here, when the key has already been entered, but there's 192 * nothing that we can do to fix that problem. 193 * 194 * The editor can ask for the next literal character even thought it's 195 * generally running in line-at-a-time mode. Do what we can. 196 */ 197 if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) { 198 term_reset = 1; 199 if (LF_ISSET(EC_QUOTED)) { 200 term2 = term1; 201 term2.c_lflag &= ~ISIG; 202 term2.c_iflag &= ~(IXON | IXOFF); 203 (void)tcsetattr(STDIN_FILENO, 204 TCSASOFT | TCSADRAIN, &term2); 205 } else 206 (void)tcsetattr(STDIN_FILENO, 207 TCSASOFT | TCSADRAIN, &clp->vi_enter); 208 } 209 210 /* 211 * 3: Wait for input. 212 * 213 * Select on the command input and scripting window file descriptors. 214 * It's ugly that we wait on scripting file descriptors here, but it's 215 * the only way to keep from locking out scripting windows. 216 */ 217 if (F_ISSET(gp, G_SCRWIN)) { 218 if (sscr_check_input(sp)) 219 goto err; 220 } 221 222 /* 223 * 4: Read the input. 224 * 225 * !!! 226 * What's going on here is some scary stuff. Ex runs the terminal in 227 * canonical mode. So, the <newline> character terminating a line of 228 * input is returned in the buffer, but a trailing <EOF> character is 229 * not similarly included. As ex uses 0<EOF> and ^<EOF> as autoindent 230 * commands, it has to see the trailing <EOF> characters to determine 231 * the difference between the user entering "0ab" and "0<EOF>ab". We 232 * leave an extra slot in the buffer, so that we can add a trailing 233 * <EOF> character if the buffer isn't terminated by a <newline>. We 234 * lose if the buffer is too small for the line and exactly N characters 235 * are entered followed by an <EOF> character. 236 */ 237 #define ONE_FOR_EOF 1 238 switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) { 239 case 0: /* EOF. */ 240 /* 241 * ^D in canonical mode returns a read of 0, i.e. EOF. EOF is 242 * a valid command, but we don't want to loop forever because 243 * the terminal driver is returning EOF because the user has 244 * disconnected. The editor will almost certainly try to write 245 * something before this fires, which should kill us, but You 246 * Never Know. 247 */ 248 if (++clp->eof_count < 50) { 249 bp[0] = clp->orig.c_cc[VEOF]; 250 *nrp = 1; 251 rval = INP_OK; 252 253 } else 254 rval = INP_EOF; 255 break; 256 case -1: /* Error or interrupt. */ 257 err: if (errno == EINTR) 258 rval = INP_INTR; 259 else if (errno == EAGAIN) 260 goto tty_retry; 261 else { 262 rval = INP_ERR; 263 msgq(sp, M_SYSERR, "input"); 264 } 265 break; 266 default: /* Input characters. */ 267 if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n') 268 bp[nr++] = clp->orig.c_cc[VEOF]; 269 *nrp = nr; 270 clp->eof_count = 0; 271 rval = INP_OK; 272 break; 273 } 274 275 /* Restore the terminal state if it was modified. */ 276 if (term_reset) 277 (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1); 278 return (rval); 279 } 280 281 /* 282 * cl_resize -- 283 * Reset the options for a resize event. 284 */ 285 static int 286 cl_resize(sp, lines, columns) 287 SCR *sp; 288 size_t lines, columns; 289 { 290 ARGS *argv[2], a, b; 291 char b1[1024]; 292 293 a.bp = b1; 294 b.bp = NULL; 295 a.len = b.len = 0; 296 argv[0] = &a; 297 argv[1] = &b; 298 299 (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines); 300 a.len = strlen(b1); 301 if (opts_set(sp, argv, NULL)) 302 return (1); 303 (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns); 304 a.len = strlen(b1); 305 if (opts_set(sp, argv, NULL)) 306 return (1); 307 return (0); 308 } 309