|
|
1.1 ! root 1: /* unix.c */ ! 2: ! 3: /* Author: ! 4: * Steve Kirkendall ! 5: * 14407 SW Teal Blvd. #C ! 6: * Beaverton, OR 97005 ! 7: * [email protected] ! 8: */ ! 9: ! 10: ! 11: /* This file contains the unix-specific versions the ttyread() functions. ! 12: * There are actually three versions of ttyread() defined here, because ! 13: * BSD, SysV, and V7 all need quite different implementations. ! 14: */ ! 15: ! 16: #include "config.h" ! 17: #if ANY_UNIX ! 18: # include "vi.h" ! 19: ! 20: # if BSD ! 21: /* For BSD, we use select() to wait for characters to become available, ! 22: * and then do a read() to actually get the characters. We also try to ! 23: * handle SIGWINCH -- if the signal arrives during the select() call, then ! 24: * we adjust the o_columns and o_lines variables, and fake a control-L. ! 25: */ ! 26: # include <sys/types.h> ! 27: # include <sys/time.h> ! 28: int ttyread(buf, len, time) ! 29: char *buf; /* where to store the gotten characters */ ! 30: int len; /* maximum number of characters to read */ ! 31: int time; /* maximum time to allow for reading */ ! 32: { ! 33: fd_set rd; /* the file descriptors that we want to read from */ ! 34: static tty; /* 'y' if reading from tty, or 'n' if not a tty */ ! 35: int i; ! 36: struct timeval t; ! 37: struct timeval *tp; ! 38: ! 39: ! 40: /* do we know whether this is a tty or not? */ ! 41: if (!tty) ! 42: { ! 43: tty = (isatty(0) ? 'y' : 'n'); ! 44: } ! 45: ! 46: /* compute the timeout value */ ! 47: if (time) ! 48: { ! 49: t.tv_sec = time / 10; ! 50: t.tv_usec = (time % 10) * 100000L; ! 51: tp = &t; ! 52: } ! 53: else ! 54: { ! 55: tp = (struct timeval *)0; ! 56: } ! 57: ! 58: /* loop until we get characters or a definite EOF */ ! 59: for (;;) ! 60: { ! 61: if (tty == 'y') ! 62: { ! 63: /* wait until timeout or characters are available */ ! 64: FD_ZERO(&rd); ! 65: FD_SET(0, &rd); ! 66: i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp); ! 67: } ! 68: else ! 69: { ! 70: /* if reading from a file or pipe, never timeout! ! 71: * (This also affects the way that EOF is detected) ! 72: */ ! 73: i = 1; ! 74: } ! 75: ! 76: /* react accordingly... */ ! 77: switch (i) ! 78: { ! 79: case -1: /* assume we got an EINTR because of SIGWINCH */ ! 80: if (*o_lines != LINES || *o_columns != COLS) ! 81: { ! 82: #ifndef CRUNCH ! 83: *o_nearscroll = ! 84: #endif ! 85: *o_lines = LINES; ! 86: *o_columns = COLS; ! 87: #ifndef CRUNCH ! 88: if (!wset) ! 89: { ! 90: *o_window = LINES - 1; ! 91: } ! 92: #endif ! 93: if (mode != MODE_EX) ! 94: { ! 95: /* pretend the user hit ^L */ ! 96: *buf = ctrl('L'); ! 97: return 1; ! 98: } ! 99: } ! 100: break; ! 101: ! 102: case 0: /* timeout */ ! 103: return 0; ! 104: ! 105: default: /* characters available */ ! 106: return read(0, buf, len); ! 107: } ! 108: } ! 109: } ! 110: # else ! 111: ! 112: # if M_SYSV || COHERENT ! 113: /* For System-V or Coherent, we use VMIN/VTIME to implement the timeout. ! 114: * For no timeout, VMIN should be 1 and VTIME should be 0; for timeout, ! 115: * VMIN should be 0 and VTIME should be the timeout value. ! 116: */ ! 117: # include <termio.h> ! 118: int ttyread(buf, len, time) ! 119: char *buf; /* where to store the gotten characters */ ! 120: unsigned len; /* maximum number of characters to read */ ! 121: int time; /* maximum time to allow for reading */ ! 122: { ! 123: struct termio tio; ! 124: int bytes; /* number of bytes actually read */ ! 125: ! 126: /* arrange for timeout */ ! 127: ioctl(0, TCGETA, &tio); ! 128: if (time) ! 129: { ! 130: tio.c_cc[VMIN] = 0; ! 131: tio.c_cc[VTIME] = time; ! 132: } ! 133: else ! 134: { ! 135: tio.c_cc[VMIN] = 1; ! 136: tio.c_cc[VTIME] = 0; ! 137: } ! 138: ioctl(0, TCSETA, &tio); ! 139: ! 140: /* Perform the read. Loop if EINTR error happens */ ! 141: while ((bytes = read(0, buf, len)) < 0) ! 142: { ! 143: /* probably EINTR error because a SIGWINCH was received */ ! 144: if (*o_lines != LINES || *o_columns != COLS) ! 145: { ! 146: *o_lines = LINES; ! 147: *o_columns = COLS; ! 148: #ifndef CRUNCH ! 149: if (!wset) ! 150: { ! 151: *o_nearscroll = *o_window = LINES - 1; ! 152: } ! 153: #endif ! 154: if (mode != MODE_EX) ! 155: { ! 156: /* pretend the user hit ^L */ ! 157: *buf = ctrl('L'); ! 158: return 1; ! 159: } ! 160: } ! 161: } ! 162: ! 163: /* return the number of bytes read */ ! 164: return bytes; ! 165: ! 166: /* NOTE: The terminal may be left in a timeout-mode after this function ! 167: * returns. This shouldn't be a problem since Elvis *NEVER* tries to ! 168: * read from the keyboard except through this function. ! 169: */ ! 170: } ! 171: ! 172: # else /* any other version of UNIX, assume it is V7 compatible */ ! 173: ! 174: /* For V7 UNIX (including Minix) we set an alarm() before doing a blocking ! 175: * read(), and assume that the SIGALRM signal will cause the read() function ! 176: * to give up. ! 177: */ ! 178: ! 179: #include <setjmp.h> ! 180: ! 181: static jmp_buf env; ! 182: ! 183: /*ARGSUSED*/ ! 184: int dummy(signo) ! 185: int signo; ! 186: { ! 187: longjmp(env, 1); ! 188: } ! 189: int ttyread(buf, len, time) ! 190: char *buf; /* where to store the gotten characters */ ! 191: int len; /* maximum number of characters to read */ ! 192: int time; /* maximum time to allow for reading */ ! 193: { ! 194: /* arrange for timeout */ ! 195: #if __GNUC__ ! 196: signal(SIGALRM, (void (*)()) dummy); ! 197: #else ! 198: signal(SIGALRM, dummy); ! 199: #endif ! 200: alarm(time); ! 201: ! 202: /* perform the blocking read */ ! 203: if (setjmp(env) == 0) ! 204: { ! 205: len = read(0, buf, len); ! 206: } ! 207: else /* I guess we timed out */ ! 208: { ! 209: len = 0; ! 210: } ! 211: ! 212: /* cancel the alarm */ ! 213: signal(SIGALRM, dummy); /* <-- to work around a bug in Minix */ ! 214: alarm(0); ! 215: ! 216: /* return the number of bytes read */ ! 217: if (len < 0) ! 218: len = 0; ! 219: return len; ! 220: } ! 221: ! 222: # endif /* !(M_SYSV || COHERENT) */ ! 223: # endif /* !BSD */ ! 224: ! 225: #endif /* ANY_UNIX */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.