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