Change login/sh for ICANON
This commit is contained in:
parent
407d61196f
commit
3e31f8508b
@ -1,4 +1,5 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
@ -14,42 +15,46 @@ struct spwd {
|
||||
static int attempt = 0;
|
||||
static char line_buf[64];
|
||||
|
||||
static ssize_t getline(char *buf, size_t lim, char pwchr) {
|
||||
size_t c = 0;
|
||||
char chr;
|
||||
static ssize_t getline(char *buf, size_t lim, int echo) {
|
||||
ssize_t len;
|
||||
struct termios old_tc;
|
||||
struct termios tc;
|
||||
|
||||
while (1) {
|
||||
if (c == lim) {
|
||||
if (!echo) {
|
||||
// Disable echo
|
||||
if (tcgetattr(STDIN_FILENO, &old_tc)) {
|
||||
perror("tcgetattr()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read(STDIN_FILENO, &chr, 1) != 1) {
|
||||
memcpy(&tc, &old_tc, sizeof(struct termios));
|
||||
// This won't show typed characters, but newlines will still be visible
|
||||
tc.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tc)) {
|
||||
perror("tcsetattr()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (chr) {
|
||||
case '\n':
|
||||
putchar('\n');
|
||||
buf[c] = 0;
|
||||
return c;
|
||||
case '\b':
|
||||
if (c) {
|
||||
buf[--c] = 0;
|
||||
puts2("\033[D \033[D");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (chr >= ' ' && chr < 255) {
|
||||
if (pwchr) {
|
||||
putchar(pwchr);
|
||||
} else {
|
||||
putchar(chr);
|
||||
}
|
||||
buf[c++] = chr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = read(STDIN_FILENO, buf, lim);
|
||||
|
||||
if (!echo) {
|
||||
// Restore terminal to sane state
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &old_tc)) {
|
||||
perror("tcsetattr()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Remove trailing newline
|
||||
if (buf[len - 1] == '\n') {
|
||||
buf[len - 1] = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t buf_size) {
|
||||
@ -169,7 +174,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
printf("login: ");
|
||||
if (getline(line_buf, sizeof(line_buf), 0) < 0) {
|
||||
if (getline(line_buf, sizeof(line_buf), 1) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -181,7 +186,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (sp.sp_pwdp[0] != 0) {
|
||||
printf("password: ");
|
||||
if (getline(line_buf, sizeof(line_buf), '*') < 0) {
|
||||
if (getline(line_buf, sizeof(line_buf), 0) < 0) {
|
||||
++attempt;
|
||||
continue;
|
||||
}
|
||||
|
@ -143,7 +143,6 @@ static struct sh_builtin __builtins[] = {
|
||||
DECL_BUILTIN(exit),
|
||||
DECL_BUILTIN(into),
|
||||
DECL_BUILTIN(setid),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
|
280
sh/readline.c
280
sh/readline.c
@ -1,145 +1,157 @@
|
||||
#include <sys/select.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define KEY_UP (256)
|
||||
#define KEY_DOWN (257)
|
||||
#define KEY_RIGHT (258)
|
||||
#define KEY_LEFT (259)
|
||||
|
||||
// With support for escape sequences
|
||||
static int getch_del(void) {
|
||||
struct timeval tv = {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = 500000
|
||||
};
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
int res;
|
||||
|
||||
if ((res = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv)) < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||
res = 0;
|
||||
if (read(STDIN_FILENO, &res, 1) != 1) {
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int escape_read(void) {
|
||||
// Maybe [
|
||||
int c = getch_del();
|
||||
|
||||
if (c < 0) {
|
||||
return '\033';
|
||||
}
|
||||
|
||||
if (c != '[') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = getch_del();
|
||||
|
||||
switch (c) {
|
||||
case 'A':
|
||||
return KEY_UP;
|
||||
case 'B':
|
||||
return KEY_DOWN;
|
||||
case 'C':
|
||||
return KEY_RIGHT;
|
||||
case 'D':
|
||||
return KEY_LEFT;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int getch(void) {
|
||||
char c;
|
||||
|
||||
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c == '\033') {
|
||||
int r = escape_read();
|
||||
|
||||
if (r > 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
//#define KEY_UP (256)
|
||||
//#define KEY_DOWN (257)
|
||||
//#define KEY_RIGHT (258)
|
||||
//#define KEY_LEFT (259)
|
||||
//
|
||||
//// With support for escape sequences
|
||||
//static int getch_del(void) {
|
||||
// struct timeval tv = {
|
||||
// .tv_sec = 0,
|
||||
// .tv_usec = 500000
|
||||
// };
|
||||
// fd_set fds;
|
||||
// FD_ZERO(&fds);
|
||||
// FD_SET(STDIN_FILENO, &fds);
|
||||
// int res;
|
||||
//
|
||||
// if ((res = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv)) < 0) {
|
||||
// return res;
|
||||
// }
|
||||
//
|
||||
// if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||
// res = 0;
|
||||
// if (read(STDIN_FILENO, &res, 1) != 1) {
|
||||
// return -1;
|
||||
// }
|
||||
// return res;
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//static int escape_read(void) {
|
||||
// // Maybe [
|
||||
// int c = getch_del();
|
||||
//
|
||||
// if (c < 0) {
|
||||
// return '\033';
|
||||
// }
|
||||
//
|
||||
// if (c != '[') {
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// c = getch_del();
|
||||
//
|
||||
// switch (c) {
|
||||
// case 'A':
|
||||
// return KEY_UP;
|
||||
// case 'B':
|
||||
// return KEY_DOWN;
|
||||
// case 'C':
|
||||
// return KEY_RIGHT;
|
||||
// case 'D':
|
||||
// return KEY_LEFT;
|
||||
// default:
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//static int getch(void) {
|
||||
// char c;
|
||||
//
|
||||
// if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// if (c == '\033') {
|
||||
// int r = escape_read();
|
||||
//
|
||||
// if (r > 0) {
|
||||
// return r;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return c;
|
||||
//}
|
||||
|
||||
int readline(char *buf, size_t lim) {
|
||||
int len = 0;
|
||||
int cur = 0;
|
||||
int chr;
|
||||
// TODO: rewrite this for new kernel line discipline to disable ECHO/ICANON
|
||||
ssize_t len = read(STDIN_FILENO, buf, lim);
|
||||
|
||||
while (1) {
|
||||
if ((chr = getch()) <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len == lim) {
|
||||
printf("Input line is too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (chr) {
|
||||
case KEY_LEFT:
|
||||
if (cur) {
|
||||
puts2("\033[D");
|
||||
--cur;
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
if (cur < len) {
|
||||
puts2("\033[C");
|
||||
++cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (chr == '\n') {
|
||||
putchar(chr);
|
||||
buf[len] = 0;
|
||||
break;
|
||||
} else if (chr == '\b') {
|
||||
if (cur) {
|
||||
--cur;
|
||||
for (int i = cur; i < len - 1; ++i) {
|
||||
buf[i] = buf[i + 1];
|
||||
}
|
||||
puts2("\033[D\033[s");
|
||||
--len;
|
||||
for (int i = cur; i < len; ++i) {
|
||||
putchar(buf[i]);
|
||||
}
|
||||
puts2(" \033[u");
|
||||
}
|
||||
} else if (chr >= ' ' && chr < 255) {
|
||||
putchar(chr);
|
||||
puts2("\033[s");
|
||||
for (int i = cur; i < len; ++i) {
|
||||
putchar(buf[i]);
|
||||
}
|
||||
puts2("\033[u");
|
||||
for (int i = len; i > cur; --i) {
|
||||
buf[i] = buf[i - 1];
|
||||
}
|
||||
buf[cur++] = chr;
|
||||
++len;
|
||||
}
|
||||
// Just strip newline
|
||||
if (len <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf[len - 1] == '\n') {
|
||||
buf[len - 1] = 0;
|
||||
}
|
||||
|
||||
//int len = 0;
|
||||
//int cur = 0;
|
||||
//int chr;
|
||||
|
||||
//while (1) {
|
||||
// if ((chr = getch()) <= 0) {
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// if (len == lim) {
|
||||
// printf("Input line is too long\n");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// switch (chr) {
|
||||
// case KEY_LEFT:
|
||||
// if (cur) {
|
||||
// puts2("\033[D");
|
||||
// --cur;
|
||||
// }
|
||||
// break;
|
||||
// case KEY_RIGHT:
|
||||
// if (cur < len) {
|
||||
// puts2("\033[C");
|
||||
// ++cur;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (chr == '\n') {
|
||||
// putchar(chr);
|
||||
// buf[len] = 0;
|
||||
// break;
|
||||
// } else if (chr == '\b') {
|
||||
// if (cur) {
|
||||
// --cur;
|
||||
// for (int i = cur; i < len - 1; ++i) {
|
||||
// buf[i] = buf[i + 1];
|
||||
// }
|
||||
// puts2("\033[D\033[s");
|
||||
// --len;
|
||||
// for (int i = cur; i < len; ++i) {
|
||||
// putchar(buf[i]);
|
||||
// }
|
||||
// puts2(" \033[u");
|
||||
// }
|
||||
// } else if (chr >= ' ' && chr < 255) {
|
||||
// putchar(chr);
|
||||
// puts2("\033[s");
|
||||
// for (int i = cur; i < len; ++i) {
|
||||
// putchar(buf[i]);
|
||||
// }
|
||||
// puts2("\033[u");
|
||||
// for (int i = len; i > cur; --i) {
|
||||
// buf[i] = buf[i - 1];
|
||||
// }
|
||||
// buf[cur++] = chr;
|
||||
// ++len;
|
||||
// }
|
||||
//}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
10
sh/sh.c
10
sh/sh.c
@ -74,6 +74,16 @@ static void display_prompt(void) {
|
||||
}
|
||||
|
||||
static void signal_handle(int signum) {
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
printf("\n");
|
||||
update_prompt();
|
||||
display_prompt();
|
||||
break;
|
||||
default:
|
||||
printf("\nUnhandled signal: %d\n", signum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user