Skip to content

Commit 020de44

Browse files
committed
修复 tty 对退格的处理问题.
1 parent 5f58de5 commit 020de44

File tree

2 files changed

+84
-23
lines changed

2 files changed

+84
-23
lines changed

src/driver/pty.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static size_t ptmx_write(void *file, const void *addr, size_t offset, size_t siz
223223
return -EIO;
224224
}
225225

226-
const char *input = (const char *)addr;
226+
const char *input = addr;
227227
size_t nwritten = 0;
228228

229229
for (size_t i = 0; i < size; i++) {

src/driver/tty.c

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2324
static 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+
339352
static 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

Comments
 (0)