@@ -17,7 +17,8 @@ static bool tty_debug_user_process(void) {
1717 if (current == NULL || current -> process == NULL || current -> process -> name == NULL ) {
1818 return false;
1919 }
20- return strstr (current -> process -> name , "Xorg" ) != NULL || strstr (current -> process -> name , "xinit" ) != NULL ;
20+ return strstr (current -> process -> name , "Xorg" ) != NULL
21+ || strstr (current -> process -> name , "xinit" ) != NULL ;
2122}
2223
2324static const char * tty_ioctl_name (const size_t req ) {
@@ -232,6 +233,7 @@ static errno_t tty_ioctl(tty_t *session, const size_t req, void *arg) {
232233 case TCSETSW : {
233234 // 对 termios 设置支持,可选实现
234235 const struct termios * termios_sw = arg ;
236+ session -> termios .c_iflag = termios_sw -> c_iflag ;
235237 session -> termios .c_lflag = termios_sw -> c_lflag ;
236238 session -> termios .c_oflag = termios_sw -> c_oflag ;
237239 session -> termios .c_cflag = termios_sw -> c_cflag ;
@@ -336,46 +338,105 @@ static errno_t tty_ioctl(tty_t *session, const size_t req, void *arg) {
336338 return EOK ;
337339}
338340
341+ static bool tty_is_erase_char (tty_t * session , const char c ) {
342+ return c == '\b' || c == (char )session -> termios .c_cc [VERASE ];
343+ }
344+
345+ static void tty_echo_char (tty_t * session , const char c ) {
346+ if (!(session -> termios .c_lflag & ECHO )) {
347+ return ;
348+ }
349+ session -> ops .write (session , & c , 0 , 1 );
350+ }
351+
339352static size_t stdin_read (tty_t * session , char * buffer , size_t offset , const size_t number ) {
340353 const tcb_t tcb = get_current_task () == NULL ? NULL : get_current_task ();
341354 if (tcb != NULL ) {
342355 tcb -> status = T_IO_WAIT ;
343356 }
357+ if (number == 0 ) {
358+ if (tcb != NULL ) {
359+ tcb -> status = T_RUNNING ;
360+ }
361+ return 0 ;
362+ }
363+
344364 size_t i = 0 ;
345- for (; i < number ; i ++ ) {
346- char c = (char )kernel_getch ();
347- if (c == 0x7f ) {
348- c = '\b' ;
365+ const bool canonical = (session -> termios .c_lflag & ICANON ) != 0 ;
366+
367+ if (!canonical ) {
368+ size_t vmin = session -> termios .c_cc [VMIN ];
369+ if (vmin == 0 && session -> queue -> size == 0 ) {
370+ if (tcb != NULL ) {
371+ tcb -> status = T_RUNNING ;
372+ }
373+ return 0 ;
349374 }
350- if (c == 0x9 ) {
351- c = '\t' ;
375+ if (vmin == 0 ) {
376+ vmin = 1 ;
352377 }
353- if (c == '\b' ) {
354- if (session -> termios .c_lflag & ECHO ) {
355- session -> ops .write (session , "\b \b" , 0 , 3 );
356- }
357- if (session -> termios .c_lflag & ICANON ) {
358- if (i > 0 ) {
359- buffer [i -- ] = '\0' ;
360- i -- ;
361- }
378+
379+ while (i < number ) {
380+ char c = (char )kernel_getch ();
381+
382+ if ((session -> termios .c_iflag & IGNCR ) && c == '\r' ) {
362383 continue ;
363384 }
364- buffer [i ] = session -> termios .c_cc [VERASE ];
385+ if ((session -> termios .c_iflag & ICRNL ) && c == '\r' ) {
386+ c = '\n' ;
387+ } else if ((session -> termios .c_iflag & INLCR ) && c == '\n' ) {
388+ c = '\r' ;
389+ }
390+
391+ buffer [i ] = c ;
392+ tty_echo_char (session , c );
393+
394+ if (i + 1 >= vmin ) {
395+ i ++ ;
396+ break ;
397+ }
398+ i ++ ;
399+ }
400+
401+ if (tcb != NULL ) {
402+ tcb -> status = T_RUNNING ;
403+ }
404+ return i ;
405+ }
406+
407+ while (i < number ) {
408+ char c = (char )kernel_getch ();
409+
410+ if ((session -> termios .c_iflag & IGNCR ) && c == '\r' ) {
365411 continue ;
366412 }
367- if (session -> termios .c_lflag & ECHO ) {
368- printk ("%c" , c );
413+ if ((session -> termios .c_iflag & ICRNL ) && c == '\r' ) {
414+ c = '\n' ;
415+ } else if ((session -> termios .c_iflag & INLCR ) && c == '\n' ) {
416+ c = '\r' ;
369417 }
418+
419+ if (tty_is_erase_char (session , c )) {
420+ if (i > 0 ) {
421+ i -- ;
422+ buffer [i ] = '\0' ;
423+ if (session -> termios .c_lflag & ECHO ) {
424+ session -> ops .write (session , "\b \b" , 0 , 3 );
425+ }
426+ }
427+ continue ;
428+ }
429+
370430 if (c == '\n' || c == '\r' ) {
371431 buffer [i ] = 0x0a ;
432+ tty_echo_char (session , '\n' );
372433 i ++ ;
373- if (session -> termios .c_lflag & ECHO && c == '\r' ) {
374- session -> ops .write (session , "\n" , 0 , 1 );
375- }
376434 break ;
377435 }
436+
378437 buffer [i ] = c ;
438+ tty_echo_char (session , c );
439+ i ++ ;
379440 }
380441 if (tcb != NULL ) {
381442 tcb -> status = T_RUNNING ;
0 commit comments