Change login/sh for ICANON

This commit is contained in:
Mark 2020-01-21 17:35:39 +02:00
parent 407d61196f
commit 3e31f8508b
4 changed files with 193 additions and 167 deletions

View File

@ -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;
}

View File

@ -143,7 +143,6 @@ static struct sh_builtin __builtins[] = {
DECL_BUILTIN(exit),
DECL_BUILTIN(into),
DECL_BUILTIN(setid),
{NULL}
};

View File

@ -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
View File

@ -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) {