MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
read.c
1 /* $NetBSD: read.c,v 1.67 2011/08/16 16:25:15 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1992, 1993
5  * The Regents of the University of California. All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell 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  * 3. Neither the name of the University nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
39 #else
40 #endif
41 #endif /* not lint && not SCCSID */
42 
43 /*
44  * read.c: Clean this junk up! This is horrible code.
45  * Terminal read functions
46  */
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <limits.h>
52 #include "el.h"
53 
54 #define OKCMD -1 /* must be -1! */
55 
56 private int read__fixio(int, int);
57 private int read_preread(EditLine *);
58 private int read_char(EditLine *, Char *);
59 private int read_getcmd(EditLine *, el_action_t *, Char *);
60 private void read_pop(c_macro_t *);
61 
62 /* read_init():
63  * Initialize the read stuff
64  */
65 protected int
66 read_init(EditLine *el)
67 {
68  /* builtin read_char */
69  el->el_read.read_char = read_char;
70  return 0;
71 }
72 
73 
74 /* el_read_setfn():
75  * Set the read char function to the one provided.
76  * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
77  */
78 protected int
79 el_read_setfn(EditLine *el, el_rfunc_t rc)
80 {
81  el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
82  return 0;
83 }
84 
85 
86 /* el_read_getfn():
87  * return the current read char function, or EL_BUILTIN_GETCFN
88  * if it is the default one
89  */
90 protected el_rfunc_t
91 el_read_getfn(EditLine *el)
92 {
93  return el->el_read.read_char == read_char ?
94  EL_BUILTIN_GETCFN : el->el_read.read_char;
95 }
96 
97 
98 #ifndef MIN
99 #define MIN(A,B) ((A) < (B) ? (A) : (B))
100 #endif
101 
102 #ifdef DEBUG_EDIT
103 private void
104 read_debug(EditLine *el)
105 {
106 
107  if (el->el_line.cursor > el->el_line.lastchar)
108  (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
109  if (el->el_line.cursor < el->el_line.buffer)
110  (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
111  if (el->el_line.cursor > el->el_line.limit)
112  (void) fprintf(el->el_errfile, "cursor > limit\r\n");
113  if (el->el_line.lastchar > el->el_line.limit)
114  (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
115  if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
116  (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
117 }
118 #endif /* DEBUG_EDIT */
119 
120 
121 /* read__fixio():
122  * Try to recover from a read error
123  */
124 /* ARGSUSED */
125 private int
126 read__fixio(int fd __attribute__((__unused__)), int e)
127 {
128 
129  switch (e) {
130  case -1: /* Make sure that the code is reachable */
131 
132 #ifdef EWOULDBLOCK
133  case EWOULDBLOCK:
134 #ifndef TRY_AGAIN
135 #define TRY_AGAIN
136 #endif
137 #endif /* EWOULDBLOCK */
138 
139 #if defined(POSIX) && defined(EAGAIN)
140 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
141  case EAGAIN:
142 #ifndef TRY_AGAIN
143 #define TRY_AGAIN
144 #endif
145 #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
146 #endif /* POSIX && EAGAIN */
147 
148  e = 0;
149 #ifdef TRY_AGAIN
150 #if defined(F_SETFL) && defined(O_NDELAY)
151  if ((e = fcntl(fd, F_GETFL, 0)) == -1)
152  return -1;
153 
154  if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
155  return -1;
156  else
157  e = 1;
158 #endif /* F_SETFL && O_NDELAY */
159 
160 #ifdef FIONBIO
161  {
162  int zero = 0;
163 
164  if (ioctl(fd, FIONBIO, &zero) == -1)
165  return -1;
166  else
167  e = 1;
168  }
169 #endif /* FIONBIO */
170 
171 #endif /* TRY_AGAIN */
172  return e ? 0 : -1;
173 
174  case EINTR:
175  return 0;
176 
177  default:
178  return -1;
179  }
180 }
181 
182 
183 /* read_preread():
184  * Try to read the stuff in the input queue;
185  */
186 private int
187 read_preread(EditLine *el)
188 {
189  int chrs = 0;
190 
191  if (el->el_tty.t_mode == ED_IO)
192  return 0;
193 
194 #ifndef WIDECHAR
195 /* FIONREAD attempts to buffer up multiple bytes, and to make that work
196  * properly with partial wide/UTF-8 characters would need some careful work. */
197 #ifdef FIONREAD
198  (void) ioctl(el->el_infd, FIONREAD, &chrs);
199  if (chrs > 0) {
200  char buf[EL_BUFSIZ];
201 
202  chrs = read(el->el_infd, buf,
203  (size_t) MIN(chrs, EL_BUFSIZ - 1));
204  if (chrs > 0) {
205  buf[chrs] = '\0';
206  el_push(el, buf);
207  }
208  }
209 #endif /* FIONREAD */
210 #endif
211  return chrs > 0;
212 }
213 
214 
215 /* el_push():
216  * Push a macro
217  */
218 public void
219 FUN(el,push)(EditLine *el, const Char *str)
220 {
221  c_macro_t *ma = &el->el_chared.c_macro;
222 
223  if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
224  ma->level++;
225  if ((ma->macro[ma->level] = Strdup(str)) != NULL)
226  return;
227  ma->level--;
228  }
229  terminal_beep(el);
230  terminal__flush(el);
231 }
232 
233 
234 /* read_getcmd():
235  * Return next command from the input stream.
236  * Character values > 255 are not looked up in the map, but inserted.
237  */
238 private int
239 read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
240 {
241  el_action_t cmd;
242  int num;
243 
244  el->el_errno = 0;
245  do {
246  if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */
247  el->el_errno = num == 0 ? 0 : errno;
248  return num;
249  }
250 
251 #ifdef KANJI
252  if ((*ch & 0200)) {
253  el->el_state.metanext = 0;
254  cmd = CcViMap[' '];
255  break;
256  } else
257 #endif /* KANJI */
258 
259  if (el->el_state.metanext) {
260  el->el_state.metanext = 0;
261  *ch |= 0200;
262  }
263 #ifdef WIDECHAR
264  if (*ch >= N_KEYS)
265  cmd = ED_INSERT;
266  else
267 #endif
268  cmd = el->el_map.current[(unsigned char) *ch];
269  if (cmd == ED_SEQUENCE_LEAD_IN) {
270  keymacro_value_t val;
271  switch (keymacro_get(el, ch, &val)) {
272  case XK_CMD:
273  cmd = val.cmd;
274  break;
275  case XK_STR:
276  FUN(el,push)(el, val.str);
277  break;
278 #ifdef notyet
279  case XK_EXE:
280  /* XXX: In the future to run a user function */
281  RunCommand(val.str);
282  break;
283 #endif
284  default:
285  EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
286  break;
287  }
288  }
289  if (el->el_map.alt == NULL)
290  el->el_map.current = el->el_map.key;
291  } while (cmd == ED_SEQUENCE_LEAD_IN);
292  *cmdnum = cmd;
293  return OKCMD;
294 }
295 
296 /* read_char():
297  * Read a character from the tty.
298  */
299 private int
300 read_char(EditLine *el, Char *cp)
301 {
302  ssize_t num_read;
303  int tried = 0;
304  char cbuf[MB_LEN_MAX];
305  size_t cbp = 0;
306  int bytes = 0;
307 
308 #ifdef WIDECHAR
309 static mbstate_t state, temp_state;
310 memset(&state, 0, sizeof(mbstate_t));
311 #endif
312 
313  again:
314  el->el_signal->sig_no = 0;
315  while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) {
316  switch (el->el_signal->sig_no) {
317  case SIGCONT:
318  FUN(el,set)(el, EL_REFRESH);
319  /*FALLTHROUGH*/
320  case SIGWINCH:
321  sig_set(el);
322  goto again;
323  default:
324  break;
325  }
326  if (!tried && read__fixio(el->el_infd, errno) == 0)
327  tried = 1;
328  else {
329  *cp = '\0';
330  return -1;
331  }
332  }
333 
334 #ifdef WIDECHAR
335  ++cbp;
336  if (cbp > (size_t) MB_CUR_MAX) { /* "shouldn't happen" */
337  *cp = '\0';
338  return (-1);
339  }
340 
341  temp_state= state;
342 
343  if ((bytes = mbrtowc(cp, cbuf, cbp, &state)) == -2)
344  {
345  /* Incomplete sequence, restore the state and scan more bytes. */
346  state= temp_state;
347  goto again;
348  }
349  else if (bytes == -1)
350  {
351  /* Invalid sequence, reset the state and continue. */
352  cbp= 0;
353  memset(&state, 0, sizeof(mbstate_t));
354  goto again;
355  }
356  /* We successfully read one single or multi-byte character */
357 #else
358  *cp = (unsigned char)cbuf[0];
359 #endif
360 
361 #if 0
362  if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) {
363  cbp = 0; /* skip this character */
364  goto again;
365  }
366 #endif
367 
368  return (int)num_read;
369 }
370 
371 /* read_pop():
372  * Pop a macro from the stack
373  */
374 private void
375 read_pop(c_macro_t *ma)
376 {
377  int i;
378 
379  el_free(ma->macro[0]);
380  for (i = 0; i < ma->level; i++)
381  ma->macro[i] = ma->macro[i + 1];
382  ma->level--;
383  ma->offset = 0;
384 }
385 
386 /* el_getc():
387  * Read a character
388  */
389 public int
390 FUN(el,getc)(EditLine *el, Char *cp)
391 {
392  int num_read;
393  c_macro_t *ma = &el->el_chared.c_macro;
394 
395  terminal__flush(el);
396  for (;;) {
397  if (ma->level < 0) {
398  if (!read_preread(el))
399  break;
400  }
401 
402  if (ma->level < 0)
403  break;
404 
405  if (ma->macro[0][ma->offset] == '\0') {
406  read_pop(ma);
407  continue;
408  }
409 
410  *cp = ma->macro[0][ma->offset++];
411 
412  if (ma->macro[0][ma->offset] == '\0') {
413  /* Needed for QuoteMode On */
414  read_pop(ma);
415  }
416 
417  return 1;
418  }
419 
420 #ifdef DEBUG_READ
421  (void) fprintf(el->el_errfile, "Turning raw mode on\n");
422 #endif /* DEBUG_READ */
423  if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
424  return 0;
425 
426 #ifdef DEBUG_READ
427  (void) fprintf(el->el_errfile, "Reading a character\n");
428 #endif /* DEBUG_READ */
429  num_read = (*el->el_read.read_char)(el, cp);
430 #ifdef WIDECHAR
431  if (el->el_flags & NARROW_READ)
432  *cp = *(char *)(void *)cp;
433 #endif
434 #ifdef DEBUG_READ
435  (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
436 #endif /* DEBUG_READ */
437  return num_read;
438 }
439 
440 protected void
441 read_prepare(EditLine *el)
442 {
443  if (el->el_flags & HANDLE_SIGNALS)
444  sig_set(el);
445  if (el->el_flags & NO_TTY)
446  return;
447  if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
448  tty_rawmode(el);
449 
450  /* This is relatively cheap, and things go terribly wrong if
451  we have the wrong size. */
452  el_resize(el);
453  re_clear_display(el); /* reset the display stuff */
454  ch_reset(el, 0);
455  re_refresh(el); /* print the prompt */
456 
457  if (el->el_flags & UNBUFFERED)
458  terminal__flush(el);
459 }
460 
461 protected void
462 read_finish(EditLine *el)
463 {
464  if ((el->el_flags & UNBUFFERED) == 0)
465  (void) tty_cookedmode(el);
466  if (el->el_flags & HANDLE_SIGNALS)
467  sig_clr(el);
468 }
469 
470 public const Char *
471 FUN(el,gets)(EditLine *el, int *nread)
472 {
473  int retval;
474  el_action_t cmdnum = 0;
475  int num; /* how many chars we have read at NL */
476  Char ch, *cp;
477  int crlf = 0;
478  int nrb;
479 #ifdef FIONREAD
480  c_macro_t *ma = &el->el_chared.c_macro;
481 #endif /* FIONREAD */
482 
483  if (nread == NULL)
484  nread = &nrb;
485  *nread = 0;
486 
487  if (el->el_flags & NO_TTY) {
488  size_t idx;
489 
490  cp = el->el_line.buffer;
491  while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
492  /* make sure there is space for next character */
493  if (cp + 1 >= el->el_line.limit) {
494  idx = (size_t)(cp - el->el_line.buffer);
495  if (!ch_enlargebufs(el, (size_t)2))
496  break;
497  cp = &el->el_line.buffer[idx];
498  }
499  cp++;
500  if (el->el_flags & UNBUFFERED)
501  break;
502  if (cp[-1] == '\r' || cp[-1] == '\n')
503  break;
504  }
505  if (num == -1) {
506  if (errno == EINTR)
507  cp = el->el_line.buffer;
508  el->el_errno = errno;
509  }
510 
511  goto noedit;
512  }
513 
514 
515 #ifdef FIONREAD
516  if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
517  long chrs = 0;
518 
519  (void) ioctl(el->el_infd, FIONREAD, &chrs);
520  if (chrs == 0) {
521  if (tty_rawmode(el) < 0) {
522  errno = 0;
523  *nread = 0;
524  return NULL;
525  }
526  }
527  }
528 #endif /* FIONREAD */
529 
530  if ((el->el_flags & UNBUFFERED) == 0)
531  read_prepare(el);
532 
533  if (el->el_flags & EDIT_DISABLED) {
534  size_t idx;
535 
536  if ((el->el_flags & UNBUFFERED) == 0)
537  cp = el->el_line.buffer;
538  else
539  cp = el->el_line.lastchar;
540 
541  terminal__flush(el);
542 
543  while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
544  /* make sure there is space next character */
545  if (cp + 1 >= el->el_line.limit) {
546  idx = (size_t)(cp - el->el_line.buffer);
547  if (!ch_enlargebufs(el, (size_t)2))
548  break;
549  cp = &el->el_line.buffer[idx];
550  }
551  cp++;
552  crlf = cp[-1] == '\r' || cp[-1] == '\n';
553  if (el->el_flags & UNBUFFERED)
554  break;
555  if (crlf)
556  break;
557  }
558 
559  if (num == -1) {
560  if (errno == EINTR)
561  cp = el->el_line.buffer;
562  el->el_errno = errno;
563  }
564 
565  goto noedit;
566  }
567 
568  for (num = OKCMD; num == OKCMD;) { /* while still editing this
569  * line */
570 #ifdef DEBUG_EDIT
571  read_debug(el);
572 #endif /* DEBUG_EDIT */
573  /* if EOF or error */
574  if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
575 #ifdef DEBUG_READ
576  (void) fprintf(el->el_errfile,
577  "Returning from el_gets %d\n", num);
578 #endif /* DEBUG_READ */
579  break;
580  }
581  if (el->el_errno == EINTR) {
582  el->el_line.buffer[0] = '\0';
583  el->el_line.lastchar =
584  el->el_line.cursor = el->el_line.buffer;
585  break;
586  }
587  if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) { /* BUG CHECK command */
588 #ifdef DEBUG_EDIT
589  (void) fprintf(el->el_errfile,
590  "ERROR: illegal command from key 0%o\r\n", ch);
591 #endif /* DEBUG_EDIT */
592  continue; /* try again */
593  }
594  /* now do the real command */
595 #ifdef DEBUG_READ
596  {
597  el_bindings_t *b;
598  for (b = el->el_map.help; b->name; b++)
599  if (b->func == cmdnum)
600  break;
601  if (b->name)
602  (void) fprintf(el->el_errfile,
603  "Executing %s\n", b->name);
604  else
605  (void) fprintf(el->el_errfile,
606  "Error command = %d\n", cmdnum);
607  }
608 #endif /* DEBUG_READ */
609  /* vi redo needs these way down the levels... */
610  el->el_state.thiscmd = cmdnum;
611  el->el_state.thisch = ch;
612  if (el->el_map.type == MAP_VI &&
613  el->el_map.current == el->el_map.key &&
614  el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
615  if (cmdnum == VI_DELETE_PREV_CHAR &&
616  el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
617  && Isprint(el->el_chared.c_redo.pos[-1]))
618  el->el_chared.c_redo.pos--;
619  else
620  *el->el_chared.c_redo.pos++ = ch;
621  }
622  retval = (*el->el_map.func[cmdnum]) (el, ch);
623 #ifdef DEBUG_READ
624  (void) fprintf(el->el_errfile,
625  "Returned state %d\n", retval );
626 #endif /* DEBUG_READ */
627 
628  /* save the last command here */
629  el->el_state.lastcmd = cmdnum;
630 
631  /* use any return value */
632  switch (retval) {
633  case CC_CURSOR:
634  re_refresh_cursor(el);
635  break;
636 
637  case CC_REDISPLAY:
638  re_clear_lines(el);
639  re_clear_display(el);
640  /* FALLTHROUGH */
641 
642  case CC_REFRESH:
643  re_refresh(el);
644  break;
645 
646  case CC_REFRESH_BEEP:
647  re_refresh(el);
648  terminal_beep(el);
649  break;
650 
651  case CC_NORM: /* normal char */
652  break;
653 
654  case CC_ARGHACK: /* Suggested by Rich Salz */
655  /* <rsalz@pineapple.bbn.com> */
656  continue; /* keep going... */
657 
658  case CC_EOF: /* end of file typed */
659  if ((el->el_flags & UNBUFFERED) == 0)
660  num = 0;
661  else if (num == -1) {
662  *el->el_line.lastchar++ = CONTROL('d');
663  el->el_line.cursor = el->el_line.lastchar;
664  num = 1;
665  }
666  break;
667 
668  case CC_NEWLINE: /* normal end of line */
669  num = (int)(el->el_line.lastchar - el->el_line.buffer);
670  break;
671 
672  case CC_FATAL: /* fatal error, reset to known state */
673 #ifdef DEBUG_READ
674  (void) fprintf(el->el_errfile,
675  "*** editor fatal ERROR ***\r\n\n");
676 #endif /* DEBUG_READ */
677  /* put (real) cursor in a known place */
678  re_clear_display(el); /* reset the display stuff */
679  ch_reset(el, 1); /* reset the input pointers */
680  re_refresh(el); /* print the prompt again */
681  break;
682 
683  case CC_ERROR:
684  default: /* functions we don't know about */
685 #ifdef DEBUG_READ
686  (void) fprintf(el->el_errfile,
687  "*** editor ERROR ***\r\n\n");
688 #endif /* DEBUG_READ */
689  terminal_beep(el);
690  terminal__flush(el);
691  break;
692  }
693  el->el_state.argument = 1;
694  el->el_state.doingarg = 0;
695  el->el_chared.c_vcmd.action = NOP;
696  if (el->el_flags & UNBUFFERED)
697  break;
698  }
699 
700  terminal__flush(el); /* flush any buffered output */
701  /* make sure the tty is set up correctly */
702  if ((el->el_flags & UNBUFFERED) == 0) {
703  read_finish(el);
704  *nread = num != -1 ? num : 0;
705  } else {
706  *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
707  }
708  goto done;
709 noedit:
710  el->el_line.cursor = el->el_line.lastchar = cp;
711  *cp = '\0';
712  *nread = (int)(el->el_line.cursor - el->el_line.buffer);
713 done:
714  if (*nread == 0) {
715  if (num == -1) {
716  *nread = -1;
717  errno = el->el_errno;
718  }
719  return NULL;
720  } else
721  return el->el_line.buffer;
722 }