static void stop(char cmdc) { mode(0); (void)signal(SIGCHLD, SIG_IGN); (void)kill(CCEQ(deftty.c_cc[VSUSP], cmdc) ? 0 : getpid(), SIGTSTP); (void)signal(SIGCHLD, catch_child); mode(1); sigwinch(0); /* check for size changes */ }
/* * writer: write to remote: 0 -> line. * ~. terminate * ~^Z suspend rlogin process. * ~<delayed-suspend char> suspend rlogin process, but leave reader alone. */ static void writer(void) { int bol, local, n; char c; bol = 1; /* beginning of line */ local = 0; for (;;) { n = read(STDIN_FILENO, &c, 1); if (n <= 0) { if (n < 0 && errno == EINTR) continue; break; } /* * If we're at the beginning of the line and recognize a * command character, then we echo locally. Otherwise, * characters are echo'd remotely. If the command character * is doubled, this acts as a force and local echo is * suppressed. */ if (bol) { bol = 0; if (!noescape && c == escapechar) { local = 1; continue; } } else if (local) { local = 0; if (c == '.' || CCEQ(deftty.c_cc[VEOF], c)) { echo(c); break; } if (CCEQ(deftty.c_cc[VSUSP], c) || CCEQ(deftty.c_cc[VDSUSP], c)) { bol = 1; echo(c); stop(c); continue; } if (c != escapechar) (void)write(rem, &escapechar, 1); } if (write(rem, &c, 1) == 0) { msg("line gone"); break; } bol = CCEQ(deftty.c_cc[VKILL], c) || CCEQ(deftty.c_cc[VEOF], c) || CCEQ(deftty.c_cc[VINTR], c) || CCEQ(deftty.c_cc[VSUSP], c) || c == '\r' || c == '\n'; } }
/* * Process read */ void ttread(RP rp, TTY tp, char far* bp, int nb) { USHORT lflag = tp->t_lflag; CQ qp = &tp->inq; int cnt = 0; int eof = 1; int c; /* read chars from queue */ while (nb != 0) { c = getc(qp,NOPEEK); if (c < 0) break; /* simplified ICANON processing */ if (ISSET(lflag,ICANON)) { if (CCEQ(tp->t_cc[VEOF],c)) { eof = 1; break; } } bp[cnt++] = (char)c; nb--; eof = 0; if (ISSET(lflag,ICANON) && CCEQ(tp->t_cc[VEOL],c)) break; } RWCNT(rp) = cnt; if (ISSET(lflag,ICANON) && eof) handle_eof(rp, tp, bp); return; }
/* * Perform OPOST processing, queue character into outq, * return -1 if outq full */ int ttoutput(int c, TTY tp) { CQ qp = &tp->outq; USHORT oflag = tp->t_oflag; if (ISSET(oflag, OPOST)) { /* OPOST: do tab expansion */ if (c==TAB && ISSET(oflag,OXTABS) && ISCLR(tp->t_lflag,EXTPROC)) { for (c = 8-(tp->ocol & 7); c>0; c--) if (putc(' ',qp) < 0) break; tp->ocol += 8-(tp->ocol & 7)-c; return c ? -1 : TAB; } if (CCEQ(tp->t_cc[VEOF],c) && ISSET(oflag,ONOEOT)) return c; if (c == LF && ISSET(oflag,ONLCR)) { tp->ocol = 0; if (putc(CR,qp) < 0) return -1; return putc(LF,qp) < 0 ? -1 : c; } if (c == CR && ISSET(oflag,OCRNL)) { tp->ocol = 0; return putc(LF,qp) < 0 ? -1 : c; } if (c >= 'a' && c <= 'z' && ISSET(oflag,OLCUC)) c -= ('a'-'A'); } if (putc(c,qp) < 0) return -1; tp->ocol++; return c; }
/*ARGSUSED*/ int ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; u_char *cc = tp->t_cc; int stop, error; /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in the outq. */ if (cmd == TIOCEXT) { /* * When the EXTPROC bit is being toggled, we need * to send an TIOCPKT_IOCTL if the packet driver * is turned on. */ if (*(int *)data) { if (pti->pt_flags & PF_PKT) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag |= EXTPROC; } else { if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag &= ~EXTPROC; } return(0); } else if (cdevsw[major(dev)].d_open == ptcopen) switch (cmd) { case TIOCGPGRP: #ifdef COMPAT_SUNOS { /* * I'm not sure about SunOS TIOCGPGRP semantics * on PTYs, but it's something like this: */ extern struct emul emul_sunos; if (p->p_emul == &emul_sunos) { if (tp->t_pgrp == 0) return (EIO); *(int *)data = tp->t_pgrp->pg_id; return (0); } } #endif /* * We avoid calling ttioctl on the controller since, * in that case, tp must be the controlling terminal. */ *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; return (0); case TIOCPKT: if (*(int *)data) { if (pti->pt_flags & PF_UCNTL) return (EINVAL); pti->pt_flags |= PF_PKT; } else pti->pt_flags &= ~PF_PKT; return (0); case TIOCUCNTL: if (*(int *)data) { if (pti->pt_flags & PF_PKT) return (EINVAL); pti->pt_flags |= PF_UCNTL; } else pti->pt_flags &= ~PF_UCNTL; return (0); case TIOCREMOTE: if (*(int *)data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); return (0); #ifdef COMPAT_OLDTTY case TIOCSETP: case TIOCSETN: #endif case TIOCSETD: case TIOCSETA: case TIOCSETAW: case TIOCSETAF: ndflush(&tp->t_outq, tp->t_outq.c_cc); break; case TIOCSIG: if (*(unsigned int *)data >= NSIG || *(unsigned int *)data == 0) return(EINVAL); if ((tp->t_lflag&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); if ((*(unsigned int *)data == SIGINFO) && ((tp->t_lflag&NOKERNINFO) == 0)) ttyinfo(tp); return(0); } error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error < 0) error = ttioctl(tp, cmd, data, flag, p); if (error < 0) { if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) { if (cmd & 0xff) { pti->pt_ucntl = (u_char)cmd; ptcwakeup(tp, FREAD); } return (0); } error = ENOTTY; } /* * If external processing and packet mode send ioctl packet. */ if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { switch (cmd) { case TIOCSETA: case TIOCSETAW: case TIOCSETAF: #ifdef COMPAT_OLDTTY case TIOCSETP: case TIOCSETN: case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: #endif pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } return (error); }
/* Place newly input character C on the input queue. If all remaining pending input characters should be dropped, return 1; else return 0. */ int input_character (int c) { int lflag = termstate.c_lflag; int iflag = termstate.c_iflag; int cflag = termstate.c_cflag; cc_t *cc = termstate.c_cc; struct queue **qp = (lflag & ICANON) ? &rawq : &inputq; int flush = 0; /* Handle parity errors */ if ((iflag & INPCK) && ((cflag & PARODD) ? checkoddpar (c) : checkevenpar (c))) { if (iflag & IGNPAR) goto alldone; else if (iflag & PARMRK) { enqueue_quote (qp, CHAR_USER_QUOTE); enqueue_quote (qp, '\0'); enqueue_quote (qp, c); goto alldone; } else c = 0; } /* Check to see if we should send IXOFF */ if ((iflag & IXOFF) && !qavail (*qp) && (cc[VSTOP] != _POSIX_VDISABLE)) { poutput (cc[VSTOP]); termflags |= SENT_VSTOP; } /* Character mutations */ if (!(iflag & ISTRIP) && (iflag & PARMRK) && (c == CHAR_USER_QUOTE)) enqueue_quote (qp, CHAR_USER_QUOTE); /* cause doubling */ if (iflag & ISTRIP) c &= 0x7f; /* Handle LNEXT right away */ if (!external_processing && (termflags & LAST_LNEXT)) { enqueue_quote (qp, c); echo_char (c, 0, 1); termflags &= ~LAST_LNEXT; goto alldone; } /* Mutate ILCASE */ if (!external_processing && (iflag & ILCASE) && isalpha(c)) { if (termflags & LAST_SLASH) erase_1 (0); /* remove the slash from input */ else c = isupper(c) ? tolower (c) : c; } /* IEXTEN control chars */ if (!external_processing && (lflag & IEXTEN)) { if (CCEQ (cc[VLNEXT], c)) { if (lflag & ECHO) { poutput ('^'); poutput ('\b'); } termflags |= LAST_LNEXT; goto alldone; } if (CCEQ (cc[VDISCARD], c)) { if (termflags & FLUSH_OUTPUT) termflags &= ~FLUSH_OUTPUT; else { drop_output (); poutput (cc[VDISCARD]); termflags |= FLUSH_OUTPUT; } goto alldone; } } /* Signals */ if (!external_processing && (lflag & ISIG)) { if (CCEQ (cc[VINTR], c) || CCEQ (cc[VQUIT], c)) { if (!(lflag & NOFLSH)) { drop_output (); clear_queue (inputq); clear_queue (rawq); flush = 1; } echo_char (c, 0, 0); echo_qsize = 0; echo_pstart = output_psize; send_signal (CCEQ (cc[VINTR], c) ? SIGINT : SIGQUIT); goto alldone; } if (CCEQ (cc[VSUSP], c)) { if (!(lflag & NOFLSH)) { flush = 1; clear_queue (inputq); clear_queue (rawq); } echo_char (c, 0, 0); echo_qsize = 0; echo_pstart = output_psize; send_signal (SIGTSTP); goto alldone; } } /* IXON */ if (!external_processing && (iflag & IXON)) { if (CCEQ (cc[VSTOP], c)) { if (CCEQ(cc[VSTART], c) && (termflags & USER_OUTPUT_SUSP)) /* Toggle if VSTART == VSTOP. Alldone code always turns off USER_OUTPUT_SUSP. */ goto alldone; termflags |= USER_OUTPUT_SUSP; (*bottom->suspend_physical_output) (); return flush; } if (CCEQ (cc[VSTART], c)) goto alldone; } if (!external_processing) { /* Newline and carriage-return frobbing */ if (c == '\r') { if (iflag & ICRNL) c = '\n'; else if (iflag & IGNCR) goto alldone; } else if ((c == '\n') && (iflag & INLCR)) c = '\r'; } /* Canonical mode processing */ if (!external_processing && (lflag & ICANON)) { if (CCEQ (cc[VERASE], c)) { if (qsize(rawq)) erase_1 (c); if (!(termflags & LAST_SLASH) || !(lflag & IEXTEN)) goto alldone; } if (CCEQ (cc[VKILL], c)) { if (!(termflags & LAST_SLASH) || !(lflag & IEXTEN)) { if ((lflag & ECHOKE) && !(lflag & ECHOPRT) && (echo_qsize == qsize (rawq))) { while (output_psize > echo_pstart) write_erase_sequence (); } else { echo_char (c, 0, 0); if ((lflag & ECHOK) || (lflag & ECHOKE)) echo_char ('\n', 0, 0); } clear_queue (rawq); echo_qsize = 0; echo_pstart = output_psize; termflags &= ~(LAST_SLASH|LAST_LNEXT|INSIDE_HDERASE); goto alldone; } else erase_1 (0); /* remove \ */ } if (CCEQ (cc[VWERASE], c)) { /* If we are not going to echo the erase, then echo a WERASE character right now. (If we passed it to erase_1; it would echo it multiple times.) */ if (!(lflag & (ECHOPRT|ECHOE))) echo_char (cc[VWERASE], 0, 1); /* Erase whitespace */ while (qsize (rawq) && isblank (unquote_char (rawq->ce[-1]))) erase_1 (0); /* Erase word. */ if (lflag & ALTWERASE) /* For ALTWERASE, we erase back to the first blank */ while (qsize (rawq) && !isblank (unquote_char (rawq->ce[-1]))) erase_1 (0); else /* For regular WERASE, we erase back to the first nonalpha/_ */ while (qsize (rawq) && !isblank (unquote_char (rawq->ce[-1])) && (isalnum (unquote_char (rawq->ce[-1])) || (unquote_char (rawq->ce[-1]) != '_'))) erase_1 (0); goto alldone; } if (CCEQ (cc[VREPRINT], c) && (lflag & IEXTEN)) { reprint_line (); goto alldone; } if (CCEQ (cc[VSTATUS], c) && (lflag & ISIG) && (lflag & IEXTEN)) { send_signal (SIGINFO); goto alldone; } } /* Now we have a character intended as input. See if it will fit. */ if (!qavail (*qp)) { if (iflag & IMAXBEL) poutput ('\a'); else { /* Drop everything */ drop_output (); clear_queue (inputq); clear_queue (rawq); echo_pstart = 0; echo_qsize = 0; flush = 1; } goto alldone; } /* Echo */ echo_char (c, 0, 0); if (CCEQ (cc[VEOF], c) && (lflag & ECHO)) { /* Special bizarre echo processing for VEOF character. */ int n; n = echo_double (c, 0) ? 2 : output_width (c, output_psize); while (n--) poutput ('\b'); } /* Put character on input queue */ enqueue (qp, c); /* Check for break characters in canonical input processing */ if (lflag & ICANON) { if (CCEQ (cc[VEOL], c) || CCEQ (cc[VEOL2], c) || CCEQ (cc[VEOF], c) || c == '\n') /* Make input available */ while (qsize (rawq)) enqueue (&inputq, dequeue (rawq)); } alldone: /* Restart output */ if ((iflag & IXANY) || (CCEQ (cc[VSTART], c))) termflags &= ~USER_OUTPUT_SUSP; (*bottom->start_output) (); return flush; }
/*ARGSUSED*/ static int ptyioctl(struct dev_ioctl_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp = dev->si_tty; struct pt_ioctl *pti = dev->si_drv1; u_char *cc = tp->t_cc; int stop, error; lwkt_gettoken(&tty_token); if (dev_dflags(dev) & D_MASTER) { switch (ap->a_cmd) { case TIOCGPGRP: /* * We avoid calling ttioctl on the controller since, * in that case, tp must be the controlling terminal. */ *(int *)ap->a_data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; lwkt_reltoken(&tty_token); return (0); case TIOCPKT: if (*(int *)ap->a_data) { if (pti->pt_flags & PF_UCNTL) { lwkt_reltoken(&tty_token); return (EINVAL); } pti->pt_flags |= PF_PKT; } else { pti->pt_flags &= ~PF_PKT; } lwkt_reltoken(&tty_token); return (0); case TIOCUCNTL: if (*(int *)ap->a_data) { if (pti->pt_flags & PF_PKT) { lwkt_reltoken(&tty_token); return (EINVAL); } pti->pt_flags |= PF_UCNTL; } else { pti->pt_flags &= ~PF_UCNTL; } lwkt_reltoken(&tty_token); return (0); case TIOCREMOTE: if (*(int *)ap->a_data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); lwkt_reltoken(&tty_token); return (0); #ifdef UNIX98_PTYS case TIOCISPTMASTER: if ((pti->pt_flags & PF_UNIX98) && (pti->devc == dev)) { lwkt_reltoken(&tty_token); return (0); } else { lwkt_reltoken(&tty_token); return (EINVAL); } } #endif /* * The rest of the ioctls shouldn't be called until * the slave is open. */ if ((tp->t_state & TS_ISOPEN) == 0) { lwkt_reltoken(&tty_token); return (EAGAIN); } switch (ap->a_cmd) { #ifdef COMPAT_43 case TIOCSETP: case TIOCSETN: #endif case TIOCSETD: case TIOCSETA: case TIOCSETAW: case TIOCSETAF: /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in * the outq. */ ndflush(&tp->t_outq, tp->t_outq.c_cc); break; case TIOCSIG: if (*(unsigned int *)ap->a_data >= NSIG || *(unsigned int *)ap->a_data == 0) { lwkt_reltoken(&tty_token); return(EINVAL); } if ((tp->t_lflag&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); pgsignal(tp->t_pgrp, *(unsigned int *)ap->a_data, 1); if ((*(unsigned int *)ap->a_data == SIGINFO) && ((tp->t_lflag&NOKERNINFO) == 0)) ttyinfo(tp); lwkt_reltoken(&tty_token); return(0); } } if (ap->a_cmd == TIOCEXT) { /* * When the EXTPROC bit is being toggled, we need * to send an TIOCPKT_IOCTL if the packet driver * is turned on. */ if (*(int *)ap->a_data) { if (pti->pt_flags & PF_PKT) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag |= EXTPROC; } else { if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag &= ~EXTPROC; } lwkt_reltoken(&tty_token); return(0); } error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred); if (error == ENOIOCTL) error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag); if (error == ENOIOCTL) { if (pti->pt_flags & PF_UCNTL && (ap->a_cmd & ~0xff) == UIOCCMD(0)) { if (ap->a_cmd & 0xff) { pti->pt_ucntl = (u_char)ap->a_cmd; ptcwakeup(tp, FREAD); } lwkt_reltoken(&tty_token); return (0); } error = ENOTTY; } /* * If external processing and packet mode send ioctl packet. */ if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { switch(ap->a_cmd) { case TIOCSETA: case TIOCSETAW: case TIOCSETAF: #ifdef COMPAT_43 case TIOCSETP: case TIOCSETN: #endif #if defined(COMPAT_43) || defined(COMPAT_SUNOS) case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: #endif pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } lwkt_reltoken(&tty_token); return (error); }
/** Read a line from the input file in canonical mode. Perform echoing and input processing as directed by the termios flags. @param[in] filp A pointer to a file descriptor structure. @return The number of characters in the input buffer, or -1 if there was an error. **/ ssize_t IIO_CanonRead ( struct __filedes *filp ) { cIIO *This; cFIFO *InBuf; struct termios *Termio; struct __filedes *fpOut; ssize_t NumRead; wint_t InChar; tcflag_t IFlag; tcflag_t LFlag; BOOLEAN EchoIsOK; BOOLEAN Activate; BOOLEAN FirstRead; int OutMode; UINTN MaxColumn; UINTN MaxRow; NumRead = MAX_INPUT; // Workaround "potentially uninitialized" warning EchoIsOK = FALSE; FirstRead = TRUE; This = filp->devdata; Termio = &This->Termio; InBuf = This->InBuf; // Get a copy of the flags we are going to use IFlag = Termio->c_iflag; LFlag = Termio->c_lflag; /* Determine what the current screen size is. Also validates the output device. */ OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow); if(OutMode >= 0) { /* Set the maximum screen dimensions. */ This->MaxColumn = MaxColumn; This->MaxRow = MaxRow; /* Record where the cursor is at the beginning of this Input operation. The currently set stdout device is used to determine this. If there is no stdout, or stdout is not an interactive device, nothing is recorded. */ if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) { This->CurrentXY.Column = This->InitialXY.Column; This->CurrentXY.Row = This->InitialXY.Row; EchoIsOK = TRUE; // Can only echo to stdout } } // For now, we only echo to stdout. fpOut = &gMD->fdarray[STDOUT_FILENO]; // Input and process characters until BufferSize is exhausted. do { ssize_t CharRead; CharRead = IIO_GetInChar(filp, FirstRead, &InChar); if (CharRead <= 0) { /* * Error or EOF. */ NumRead = CharRead; break; } FirstRead = FALSE; Activate = TRUE; if(InChar == CHAR_CARRIAGE_RETURN) { if((IFlag & IGNCR) != 0) { continue; // Restart the do loop, discarding the CR } else if((IFlag & ICRNL) != 0) { InChar = L'\n'; } } else if(InChar == CHAR_LINEFEED) { if((IFlag & INLCR) != 0) { InChar = L'\r'; } } else if(CCEQ(Termio->c_cc[VQUIT], InChar) || CCEQ(Termio->c_cc[VINTR], InChar)) { /* * This is currently broken/not-implemented, * but it is assumed that in ICANON mode, * Ctrl-C/Ctrl-\ are expected to do *something*. * * On LFLag & ISIG != 0, this should raise the * signal before returning EINTR. */ if((LFlag & ISIG) != 0) { errno = EINTR; } else { /* * Whatever it takes to make I/O fail. */ errno = EIO; } return -1; } else if(CCEQ(Termio->c_cc[VEOF], InChar)) { /* * Seen EOT. */ InChar = IIO_ECHO_DISCARD; } else if(CCEQ(Termio->c_cc[VEOL], InChar)) { EchoIsOK = FALSE; // Buffer, but don't echo this character } else if(CCEQ(Termio->c_cc[VERASE], InChar)) { InChar = IIO_ECHO_ERASE; Activate = FALSE; } else if(CCEQ(Termio->c_cc[VKILL], InChar)) { InChar = IIO_ECHO_KILL; Activate = FALSE; } else { if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) { Activate = FALSE; } } /** The Echo function is responsible for: * Adding the character to the input buffer, if appropriate. * Removing characters from the input buffer for ERASE and KILL processing. * Visually removing characters from the screen if ECHOE is set. * Ensuring one can not backspace beyond the beginning of the input text. * Sending final echo strings to output. **/ (void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK); NumRead = InBuf->Count(InBuf, AsElements); } while((NumRead < MAX_INPUT) && (Activate == FALSE)); return (ssize_t)NumRead; }
/* * Process an input character, with input processing * return -1, if queue full. */ int ttinput(int c, TTY tp) { USHORT lflag = tp->t_lflag; char far *cc = tp->t_cc; CQ rq = &tp->inq; int nocan = ISCLR(lflag,ICANON); int ret = 0; /* only 8 or 7 bits */ c &= (tp->t_iflag & ISTRIP ? 0x7f : 0xff); /* filter out CR LF sequences, store as LF only */ if (c==0x0d) { if (ISSET(tp->t_iflag, IGNCR)) // Ignore CR on input { BSET(tp->state,ST_CRSEEN); return 0; } else if (ISSET(tp->t_iflag, ICRNL)) // Translate CR -> NR on input c = 0x0a; } else if (c != 0x0a && ISSET(tp->state,ST_CRSEEN)) { /* out of band CR, ok */ BCLR(tp->state,ST_CRSEEN); if (putc(0x0d,rq) < 0) return -1; if (nocan) ret = ttecho(0x0d, tp); } else if ( c == 0x0a && ISSET(tp->t_iflag, INLCR)) { BCLR(tp->state, ST_CRSEEN); c = 0x0d; } else if (ISCLR(lflag,EXTPROC)) { BCLR(tp->state,ST_CRSEEN); /* internal processing */ if (ISSET(lflag,ISIG)) { if (CCEQ(cc[VINTR],c) /*|| CCEQ(cc[VQUIT],c)*/) { if (ISCLR(lflag,NOFLSH)) ttflush(tp,3); ttecho(c,tp); pgsignal(tp->pgrp, SIGINT); goto endproc; } } } else /* else was an LF or no CRSEEN */ BCLR(tp->state,ST_CRSEEN); if (ret >= 0) { /* regular char or CR/LF: put in queue */ if (putc(c,rq) >= 0) { if (nocan) ret = ttecho(c,tp); } } endproc: /* reaches here if something has been processed */ ttstart(tp); return ret; }