@@ -582,6 +582,100 @@ static ssize_t process_output_block(struct tty_struct *tty,
582582 return i ;
583583}
584584
585+ static int n_tty_process_echo_ops (struct tty_struct * tty , size_t * tail ,
586+ int space )
587+ {
588+ struct n_tty_data * ldata = tty -> disc_data ;
589+ u8 op ;
590+
591+ /*
592+ * Since add_echo_byte() is called without holding output_lock, we
593+ * might see only portion of multi-byte operation.
594+ */
595+ if (MASK (ldata -> echo_commit ) == MASK (* tail + 1 ))
596+ return - ENODATA ;
597+
598+ /*
599+ * If the buffer byte is the start of a multi-byte operation, get the
600+ * next byte, which is either the op code or a control character value.
601+ */
602+ op = echo_buf (ldata , * tail + 1 );
603+
604+ switch (op ) {
605+ case ECHO_OP_ERASE_TAB : {
606+ unsigned int num_chars , num_bs ;
607+
608+ if (MASK (ldata -> echo_commit ) == MASK (* tail + 2 ))
609+ return - ENODATA ;
610+
611+ num_chars = echo_buf (ldata , * tail + 2 );
612+
613+ /*
614+ * Determine how many columns to go back in order to erase the
615+ * tab. This depends on the number of columns used by other
616+ * characters within the tab area. If this (modulo 8) count is
617+ * from the start of input rather than from a previous tab, we
618+ * offset by canon column. Otherwise, tab spacing is normal.
619+ */
620+ if (!(num_chars & 0x80 ))
621+ num_chars += ldata -> canon_column ;
622+ num_bs = 8 - (num_chars & 7 );
623+
624+ if (num_bs > space )
625+ return - ENOSPC ;
626+
627+ space -= num_bs ;
628+ while (num_bs -- ) {
629+ tty_put_char (tty , '\b' );
630+ if (ldata -> column > 0 )
631+ ldata -> column -- ;
632+ }
633+ * tail += 3 ;
634+ break ;
635+ }
636+ case ECHO_OP_SET_CANON_COL :
637+ ldata -> canon_column = ldata -> column ;
638+ * tail += 2 ;
639+ break ;
640+
641+ case ECHO_OP_MOVE_BACK_COL :
642+ if (ldata -> column > 0 )
643+ ldata -> column -- ;
644+ * tail += 2 ;
645+ break ;
646+
647+ case ECHO_OP_START :
648+ /* This is an escaped echo op start code */
649+ if (!space )
650+ return - ENOSPC ;
651+
652+ tty_put_char (tty , ECHO_OP_START );
653+ ldata -> column ++ ;
654+ space -- ;
655+ * tail += 2 ;
656+ break ;
657+
658+ default :
659+ /*
660+ * If the op is not a special byte code, it is a ctrl char
661+ * tagged to be echoed as "^X" (where X is the letter
662+ * representing the control char). Note that we must ensure
663+ * there is enough space for the whole ctrl pair.
664+ */
665+ if (space < 2 )
666+ return - ENOSPC ;
667+
668+ tty_put_char (tty , '^' );
669+ tty_put_char (tty , op ^ 0100 );
670+ ldata -> column += 2 ;
671+ space -= 2 ;
672+ * tail += 2 ;
673+ break ;
674+ }
675+
676+ return space ;
677+ }
678+
585679/**
586680 * __process_echoes - write pending echo characters
587681 * @tty: terminal device
@@ -617,104 +711,12 @@ static size_t __process_echoes(struct tty_struct *tty)
617711 while (MASK (ldata -> echo_commit ) != MASK (tail )) {
618712 c = echo_buf (ldata , tail );
619713 if (c == ECHO_OP_START ) {
620- u8 op ;
621- bool space_left = true;
622-
623- /*
624- * Since add_echo_byte() is called without holding
625- * output_lock, we might see only portion of multi-byte
626- * operation.
627- */
628- if (MASK (ldata -> echo_commit ) == MASK (tail + 1 ))
714+ int ret = n_tty_process_echo_ops (tty , & tail , space );
715+ if (ret == - ENODATA )
629716 goto not_yet_stored ;
630- /*
631- * If the buffer byte is the start of a multi-byte
632- * operation, get the next byte, which is either the
633- * op code or a control character value.
634- */
635- op = echo_buf (ldata , tail + 1 );
636-
637- switch (op ) {
638- case ECHO_OP_ERASE_TAB : {
639- unsigned int num_chars , num_bs ;
640-
641- if (MASK (ldata -> echo_commit ) == MASK (tail + 2 ))
642- goto not_yet_stored ;
643- num_chars = echo_buf (ldata , tail + 2 );
644-
645- /*
646- * Determine how many columns to go back
647- * in order to erase the tab.
648- * This depends on the number of columns
649- * used by other characters within the tab
650- * area. If this (modulo 8) count is from
651- * the start of input rather than from a
652- * previous tab, we offset by canon column.
653- * Otherwise, tab spacing is normal.
654- */
655- if (!(num_chars & 0x80 ))
656- num_chars += ldata -> canon_column ;
657- num_bs = 8 - (num_chars & 7 );
658-
659- if (num_bs > space ) {
660- space_left = false;
661- break ;
662- }
663- space -= num_bs ;
664- while (num_bs -- ) {
665- tty_put_char (tty , '\b' );
666- if (ldata -> column > 0 )
667- ldata -> column -- ;
668- }
669- tail += 3 ;
670- break ;
671- }
672- case ECHO_OP_SET_CANON_COL :
673- ldata -> canon_column = ldata -> column ;
674- tail += 2 ;
675- break ;
676-
677- case ECHO_OP_MOVE_BACK_COL :
678- if (ldata -> column > 0 )
679- ldata -> column -- ;
680- tail += 2 ;
681- break ;
682-
683- case ECHO_OP_START :
684- /* This is an escaped echo op start code */
685- if (!space ) {
686- space_left = false;
687- break ;
688- }
689- tty_put_char (tty , ECHO_OP_START );
690- ldata -> column ++ ;
691- space -- ;
692- tail += 2 ;
693- break ;
694-
695- default :
696- /*
697- * If the op is not a special byte code,
698- * it is a ctrl char tagged to be echoed
699- * as "^X" (where X is the letter
700- * representing the control char).
701- * Note that we must ensure there is
702- * enough space for the whole ctrl pair.
703- *
704- */
705- if (space < 2 ) {
706- space_left = false;
707- break ;
708- }
709- tty_put_char (tty , '^' );
710- tty_put_char (tty , op ^ 0100 );
711- ldata -> column += 2 ;
712- space -= 2 ;
713- tail += 2 ;
714- }
715-
716- if (!space_left )
717+ if (ret < 0 )
717718 break ;
719+ space = ret ;
718720 } else {
719721 if (O_OPOST (tty )) {
720722 int retval = do_output_char (c , tty , space );
0 commit comments