/* * Put the chars in the from queue on the end of the to queue. */ static void tty_catq(struct tty_queue *from, struct tty_queue *to) { int c; while ((c = tty_getc(from)) != -1) tty_putc(c, to); }
/* * Get command from the client. * return < 0: error * return >= 0: size of buffer */ int get_nntp(char *buf, int max) { int c, len; len = 0; memset(buf, 0, sizeof(buf)); while (TRUE) { c = tty_getc(180); if (c <= 0) { if (c == -2) { /* * Timeout */ send_nntp("400 Service discontinued, timeout"); } Syslog('+', "Receiver status %s", ttystat[- c]); return c; } if ((c == '\r') || (c == '\n')) { rcvdbytes += (len + 1); return len; } else { buf[len] = c; len++; buf[len] = '\0'; } if (len >= max) { WriteError("Input buffer full"); return len; } } return 0; /* Not reached */ }
/* * Start TTY output operation. */ static void serial_start(struct tty *tp) { struct serial_softc *sc = device_private(tp->t_dev); struct serial_port *port = sc->port; int c; while ((c = tty_getc(&tp->t_outq)) >= 0) sc->ops->xmt_char(port, c); }
/* * Flush tty read and/or write queues, notifying anyone waiting. */ static void tty_flush(struct tty *tp, int rw) { DPRINTF(TTYDB_CORE, ("tty_flush rw=%d\n", rw)); if (rw & FREAD) { while (tty_getc(&tp->t_canq) != -1) continue; while (tty_getc(&tp->t_rawq) != -1) continue; sem_post(&tp->t_input); } if (rw & FWRITE) { tp->t_state &= ~TS_TTSTOP; tty_start(tp); } }
/* * Process a read call on a tty device. */ int tty_read(struct tty *tp, struct uio *uio, size_t *size) { unsigned char *cc; struct tty_queue *qp; int rc, tmp; u_char c; tcflag_t lflag; DPRINTF(TTYDB_CORE, ("tty_read\n")); lflag = tp->t_lflag; cc = tp->t_cc; qp = (lflag & ICANON) ? &tp->t_canq : &tp->t_rawq; size_t total = 0; for (int i = 0; i < uio->iovcnt; ++i) { /* If there is no input, wait it */ while (ttyq_empty(qp)) { rc = sem_wait(&tp->t_input); if ((rc != 0 && errno == EINTR) || tp->t_state & TS_ISIG) { tp->t_state &= ~TS_ISIG; return -EINTR; } } size_t count = 0; char *buf = uio->iov[i].iov_base; size_t nbyte = uio->iov[i].iov_len; while (count < nbyte) { if ((tmp = tty_getc(qp)) == -1) break; c = (u_char)tmp; if (c == cc[VEOF] && (lflag & ICANON)) break; ++count; if (copyout(&c, buf, 1)) return -EFAULT; if ((lflag & ICANON) && (c == '\n' || c == cc[VEOL])) break; ++buf; } total += count; } *size = total; return 0; }
// // Read characters into a buffer, terminated by a '\n' character // Note: the '\n' character is not stored // int tty_getline(int chan, char *buf) { char c; int len = 0; while (((c = tty_getc(chan)) != '\n') && (c != '\r')) { tty_putc(chan, c); *buf++ = c; len++; } *buf = '\0'; return len; }
int tty_expect(char *what,int timeout) { time_t t1; int to=timeout,got=0,p=0,ch; calling=0; while(!got&&to>0) { t1=t_start(); ch=tty_getc(to); if(ch<0)return ch; to-=t_time(t1); if(ch==what[p])p++; else p=0; if(!what[p])got=1; } return got?OK:TIMEOUT; }
int tty_gets(char *what,size_t n,int timeout) { time_t t1; int to=timeout,p=0,ch=0; *what=0; while(to>0&&p<n-1&&ch!='\r'&&ch!='\n') { t1=t_start(); ch=tty_getc(to); if(NOTTO(ch))return ch; to-=t_time(t1); if(ch>=0)what[p++]=ch; } what[p>0?--p:0]=0; if(p>0)DEBUG(('M',1,"<< %s",what)); if(ch=='\r'||ch=='\n') { DEBUG(('M',5,"tty_gets: completed")); return OK; } else if(to<=0) { DEBUG(('M',3,"tty_gets: timed out")); } else DEBUG(('M',3,"tty_gets: line too long")); return TIMEOUT; }
int get_key(char *buf, size_t size, size_t *nread) { static struct { union { const char *s; char c; } input; size_t length; int key; } keys[] = { { { (char *)8 }, 1, DEL }, { { (char *)10 }, 1, ENTER }, { { (char *)127 }, 1, DEL }, { { (char *)CTRL('A') }, 1, CTRL_A }, { { (char *)CTRL('B') }, 1, LEFT }, { { (char *)CTRL('D') }, 1, CTRL_D }, { { (char *)CTRL('E') }, 1, CTRL_E }, { { (char *)CTRL('F') }, 1, RIGHT }, { { (char *)CTRL('K') }, 1, CTRL_K }, { { (char *)CTRL('N') }, 1, DOWN }, { { (char *)CTRL('P') }, 1, UP }, { { (char *)CTRL('U') }, 1, CTRL_U }, { { (char *)CTRL('W') }, 1, CTRL_W }, { { "\033\n" }, 2, ALT_ENTER }, { { "\033[A" }, 3, UP }, { { "\033OA" }, 3, UP }, { { "\033[B" }, 3, DOWN }, { { "\033OB" }, 3, DOWN }, { { "\033[C" }, 3, RIGHT }, { { "\033OC" }, 3, RIGHT }, { { "\033[D" }, 3, LEFT }, { { "\033OD" }, 3, LEFT }, { { NULL }, 0, 0 }, }; const char *input; int i; *nread = 0; getc: buf[(*nread)++] = tty_getc(); size--; for (i = 0; keys[i].input.s; i++) { input = keys[i].length > 1 ? keys[i].input.s : &keys[i].input.c; if (*nread > keys[i].length || strncmp(buf, input, *nread)) continue; if (*nread == keys[i].length) return keys[i].key; /* Partial match found, continue reading. */ if (size > 0) goto getc; } if (*nread > 1 && buf[0] == '\033' && (buf[1] == '[' || buf[1] == 'O')) /* * A escape sequence which is not a supported key is being read. * Ensure the whole sequence is read. */ while ((buf[*nread - 1] < '@' || buf[*nread - 1] > '~') && size-- > 0) buf[(*nread)++] = tty_getc(); if (!isu8start(buf[0])) return UNKNOWN; /* * Ensure a whole Unicode character is read. The number of MSBs in the * first octet of a Unicode character is equal to the number of octets * the character consists of, followed by a zero. Therefore, as long as * the MSB is not zero there is still bytes left to read. */ while (((buf[0] << *nread) & 0x80) == 0x80 && size-- > 0) buf[(*nread)++] = tty_getc(); return UNKNOWN; }