diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-19 09:23:48 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-19 09:23:48 +0200 |
commit | 7b466345af0d3a7dc5622617ce443a90c64e34a4 (patch) | |
tree | f276b6bf391ccfe8ec3a2cb62a7f70964249621f /src/user | |
parent | ac10c1a29c44b0cb29960cd0f792c7361bc430ce (diff) | |
download | TCE-7b466345af0d3a7dc5622617ce443a90c64e34a4.tar.gz TCE-7b466345af0d3a7dc5622617ce443a90c64e34a4.zip |
Added ANSI support, minimal readline-like library.
Diffstat (limited to 'src/user')
-rw-r--r-- | src/user/init/main.c | 8 | ||||
-rw-r--r-- | src/user/lib/Makefile | 2 | ||||
-rw-r--r-- | src/user/lib/include/readline.h | 16 | ||||
-rw-r--r-- | src/user/lib/include/stdio.h | 4 | ||||
-rw-r--r-- | src/user/lib/include/tce/syscall.h | 4 | ||||
-rw-r--r-- | src/user/lib/std/readline.c | 139 | ||||
-rw-r--r-- | src/user/lib/std/stdio.c | 124 | ||||
-rw-r--r-- | src/user/lib/tce/syscall.c | 8 | ||||
-rw-r--r-- | src/user/test/main.c | 56 | ||||
-rw-r--r-- | src/user/yosh/main.c | 200 |
10 files changed, 361 insertions, 200 deletions
diff --git a/src/user/init/main.c b/src/user/init/main.c index 54dd4b6..7300efe 100644 --- a/src/user/init/main.c +++ b/src/user/init/main.c @@ -5,19 +5,19 @@ int main(char** args) { int i; - term = open("/.ui/klog", 0); - if (term <= 0) return -1; + FILE home_term = open("/.ui/home", 0); + if (home_term < 0) return -1; print("(init) Trivial/Computing Environment says hello. Press super to go home.\n"); for (i = 0; args[i] != 0; i++) { if (i == 0) continue; printf("(init) Spawning %s...\n", args[i]); - int pid = run(args[i], 0); + int pid = run(args[i], 0, home_term); if (pid < 0) { print("(init) Error. Sorry.\n"); } else { - waitpid(pid); + waitpid(pid, 1); } } print("(init) Goodbye.\n"); diff --git a/src/user/lib/Makefile b/src/user/lib/Makefile index 9111ff5..c2630c4 100644 --- a/src/user/lib/Makefile +++ b/src/user/lib/Makefile @@ -1,6 +1,6 @@ Out = _user.o Obj = tce/syscall.o std/_dlmalloc.o \ - std/stdio.o std/stdlib.o std/string.o std/sched.o \ + std/stdio.o std/stdlib.o std/string.o std/sched.o std/readline.o \ start.o include $(SrcPath)/common.make diff --git a/src/user/lib/include/readline.h b/src/user/lib/include/readline.h new file mode 100644 index 0000000..53193d7 --- /dev/null +++ b/src/user/lib/include/readline.h @@ -0,0 +1,16 @@ +#ifndef DEF_READLINE_H +#define DEF_READLINE_H + +#include <stdio.h> + +char* freadln(FILE f); // minimal line-reading function. user must free the returned value. + +typedef struct _rdln_hist { + int max; + int n; + char **str; +} readline_history; +char* readline(FILE f, readline_history *h); + +#endif + diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h index 6c3a974..099746e 100644 --- a/src/user/lib/include/stdio.h +++ b/src/user/lib/include/stdio.h @@ -2,6 +2,7 @@ #define DEF_STDIO_H #include <stdarg.h> +#include <tce/syscall.h> extern FILE term; @@ -14,8 +15,7 @@ void fprint_int(FILE f, int number); void fprint_hex(FILE f, unsigned number); void fprintf(FILE f, char *s, ...); -void vsfprintf(FILE f, char *s, va_list arg); +void vfprintf(FILE f, char *s, va_list arg); -char* freadln(FILE f); #endif diff --git a/src/user/lib/include/tce/syscall.h b/src/user/lib/include/tce/syscall.h index 1811422..c182f40 100644 --- a/src/user/lib/include/tce/syscall.h +++ b/src/user/lib/include/tce/syscall.h @@ -19,8 +19,8 @@ int proc_priv(); void* sbrk(size_t size); void brk(void* ptr); -int run(char* file, char** args); -int waitpid(int pid); +int run(char* file, char** args, FILE zero_fd); +int waitpid(int pid, int block); FILE open(char* filename, int mode); FILE open_relative(FILE root, char* filename, int mode); diff --git a/src/user/lib/std/readline.c b/src/user/lib/std/readline.c new file mode 100644 index 0000000..a3beefa --- /dev/null +++ b/src/user/lib/std/readline.c @@ -0,0 +1,139 @@ +#include <readline.h> +#include <stdlib.h> + +char* freadln(FILE f) { + fprint(f, "\x1b[e"); // enable keyboard echo + int i; + + char *p = (char*)malloc(256); + char *b = p; + + while (1) { + int l = read(f, 0, 255, b); + if (l < 0) { + free(b); + return 0; + } + + for (i = 0; i < l; i++) { + if (b[i] == '\n') { + b[i+1] = 0; + return p; + } else if (b[i] == 27) { // ignore escape sequences + b[i] = 0; + l = i; + } + } + + int d = b - p + l; + + char* newp = (char*)malloc(d + 256); + memcpy(newp, p, d); + free(p); + p = newp; + b = p + d; + } +} + + +// ** READLINE + +char *readline(FILE f, readline_history *h) { + int i; + fprint(f, "\x1b[h"); // disable keyboard echo + + if (h->str == 0) { + h->str = (char**)malloc(h->max * sizeof(char*)); + for (i = 0; i < h->max; i++) h->str[i] = 0; + h->n = 0; + } + + int lid; + if (h->n < h->max) { + lid = h->n++; + } else { + free(h->str[0]); + int i; + for (i = 0; i < h->max - 1; i++) { + h->str[i] = h->str[i+1]; + } + lid = h->max - 1; + h->str[lid] = 0; + } + + if (h->str[lid] == 0) h->str[lid] = (char*)malloc(256); + + char *str = h->str[lid]; + str[0] = 0; + char *cur = str; // position in string + int len = 0; // string length + + while (1) { + int finished = 0; + + int te = cur - str; + + char buf[16]; + int l = read(f, 0, 16, buf); + if (l < 0) return 0; + + if (buf[0] == 27) { + if (buf[1] == '[') { + if (buf[2] == 'A') { // up + if (lid > 0) { + lid--; + str = h->str[lid]; + len = strlen(str); + cur = str + len; + } + } else if (buf[2] == 'B') { // down + if (lid < h->n - 1) { + lid++; + str = h->str[lid]; + len = strlen(str); + cur = str + len; + } + } else if (buf[2] == 'C') { // forward (right) + if (cur < str + len) cur++; + } else if (buf[2] == 'D') { // back (left) + if (cur > str) cur--; + } + } else { + // ALT sequence - ignore + } + } else if (buf[0] == '\n') { + finished = 1; + cur = str + len; + } else if (buf[0] == '\b') { + if (cur > str) { + cur--; + len--; + char* c; + for (c = cur; *c != 0; c++) c[0] = c[1]; + } + } else if (buf[0] == '\t') { + // ignore tabs -- todo: tab completion???? haha + } else if (buf[0] >= ' ') { + if (l < 255) { + char* c; + for (c = cur + len; c >= cur; c--) c[1] = c[0]; + cur[0] = buf[0]; + cur++; + len++; + } + } + + // ASSUMPTION : everything will fit on one line... + if (te > 0) fprintf(f, "\x1b[%iD", te); + fprintf(f, "\x1b[K%s", str); + te = len - (cur - str); + if (te > 0) fprintf(f, "\x1b[%iD", te); + + + if (finished) { + fprintf(f, "\n"); + if (h->str[h->n-1][0] == 0) h->n--; + return str; + } + } +} diff --git a/src/user/lib/std/stdio.c b/src/user/lib/std/stdio.c index 1628a78..b1778d6 100644 --- a/src/user/lib/std/stdio.c +++ b/src/user/lib/std/stdio.c @@ -7,7 +7,7 @@ void print(char *s) { fprint(term, s); } void printf(char *format, ...) { va_list ap; va_start(ap, format); - vsfprintf(term, format, ap); + vfprintf(term, format, ap); va_end(ap); } char* readln() { return freadln(term); } @@ -15,25 +15,22 @@ char* readln() { return freadln(term); } void fprintf(FILE f, char* format, ...) { va_list ap; va_start(ap, format); - vsfprintf(f, format, ap); + vfprintf(f, format, ap); va_end(ap); } +// INTERNAL, FOR FORMATTING -void fprint(FILE f, char *s) { - write(f, 0, strlen(s), s); -} - -void fprint_int(FILE f, int number) { +static char* format_int(char* buf, int number) { if (number == 0) { - fprint(f, "0"); - return; + *(buf++) = '0'; + return buf; } - int negative = 0; if (number < 0) { - negative = 1; + *(buf++) = '-'; number = 0 - number; } + int order = 0, temp = number, i; char numbers[] = "0123456789"; while (temp > 0) { @@ -41,86 +38,81 @@ void fprint_int(FILE f, int number) { temp /= 10; } - char s[32], *r; - if (negative) { - s[0] = '-'; - r = s + 1; - } else { - r = s; - } - for (i = order; i > 0; i--) { - r[i - 1] = numbers[number % 10]; + buf[i - 1] = numbers[number % 10]; number /= 10; } - r[order] = 0; - fprint(f, s); + return buf + order; } -void fprint_hex(FILE f, unsigned v) { - char s[11] = {'0', 'x', 0}; +static char* format_hex(char *buf, unsigned v) { + *(buf++) = '0'; + *(buf++) = 'x'; int i; - char hexdigits[] = "0123456789ABCDEF"; - for (i = 0; i < 8; i++) { - s[i + 2] = (hexdigits[v >> 28]); + *(buf++) = hexdigits[v >> 28]; v = v << 4; } - s[11] = 0; + return buf; +} + + +// FUNCTIONS + +void fprint(FILE f, char *s) { + write(f, 0, strlen(s), s); +} + +void fprint_int(FILE f, int number) { + char s[32]; + char *v = format_int(s, number); + *v = 0; + fprint(f, s); +} + +void fprint_hex(FILE f, unsigned v) { + char s[11]; + char *e = format_hex(s, v); + *e = 0; fprint(f, s); } -void vsfprintf(FILE f, char *format, va_list ap) { - char* start = format; +void vfprintf(FILE f, char *format, va_list ap) { + char bb[256]; + int bufl = 256; + + char *buf = bb; + char *end = buf; while (*format) { if (*format == '%') { - if (start != format) write(f, 0, format - start, start); + // ASSUMPTION : (TODO) WE HAVE ENOUGH SPACE - NOT THE CASE!!! format++; if (*format == 'd' || *format == 'i') { - fprint_int(f, va_arg(ap, int)); + end = format_int(end, va_arg(ap, int)); } else if (*format == 'p') { - fprint_hex(f, va_arg(ap, uint32_t)); + end = format_hex(end, va_arg(ap, uint32_t)); } else if (*format == 's') { - fprint(f, va_arg(ap, char*)); + char *s = va_arg(ap, char*); + strcpy(end, s); + end += strlen(s); } format++; - start = format; } else { - format++; + *(end++) = *(format++); } - } - if (start != format) write(f, 0, format - start, start); -} - -char* freadln(FILE f) { - int i; - - char *p = (char*)malloc(256); - char *b = p; - - while (1) { - int l = read(f, 0, 255, b); - if (l < 0) { - free(b); - return 0; + if (end - buf > bufl - 2) { + bufl *= 2; + char *nbuf = (char*)malloc(bufl); + memcpy(nbuf, buf, end - buf); + end = nbuf + (end - buf); + if (buf != bb) free(buf); + buf = nbuf; } - - for (i = 0; i < l; i++) { - if (b[i] == '\n') { - b[i+1] = 0; - return p; - } - } - - int d = b - p + l; - - char* newp = (char*)malloc(d + 256); - memcpy(newp, p, d); - free(p); - p = newp; - b = p + d; } + *end = 0; + fprint(f, buf); + if (buf != bb) free(buf); } diff --git a/src/user/lib/tce/syscall.c b/src/user/lib/tce/syscall.c index bc8bfd8..4304840 100644 --- a/src/user/lib/tce/syscall.c +++ b/src/user/lib/tce/syscall.c @@ -75,12 +75,12 @@ void brk(void* ptr) { // ********** proc -int run(char* filename, char** args) { - return call(SC_RUN, (unsigned)filename, (unsigned)args, 0, 0, 0); +int run(char* filename, char** args, FILE zero_fd) { + return call(SC_RUN, (unsigned)filename, (unsigned)args, (unsigned)zero_fd, 0, 0); } -int waitpid(int p) { - return call(SC_WAITPID, p, 0, 0, 0, 0); +int waitpid(int p, int block) { + return call(SC_WAITPID, p, block, 0, 0, 0); } // ********** file diff --git a/src/user/test/main.c b/src/user/test/main.c index 3457ac3..7ca4802 100644 --- a/src/user/test/main.c +++ b/src/user/test/main.c @@ -34,57 +34,6 @@ void thread_cascade(void* d) { threads--; } -void list_dir(FILE f, int lv) { - char buf[256]; - int i = 0, k; - int r; - file_info info; - - while ((r = read(f, i, 256, buf)) > 0) { - if (strcmp(buf, ".") == 0 || strcmp(buf, "..") == 0) { - i++; - continue; - } - for (k = 0; k < lv; k++) print(" "); - print(buf); - stat_relative(f, buf, &info); - if (info.type & FT_DIR) print("/"); - print(" \t"); - - if (info.type & FT_FILE) print("file "); - if (info.type & FT_DIR) print("dir "); - if (info.type & FT_SYMLINK) print("symlink "); - if (info.type & FT_DEV) print("dev "); - if (info.type & FT_TERMINAL) print("term "); - - if (info.type & FT_DIR) { - print(" \t"); - FILE ff = open_relative(f, buf, 0); - if (ff <= 0) { - printf("error: %i\n", ff); - } else { - printf("fd: %i\n", ff); - list_dir(ff, lv+1); - close(ff); - } - } else { - print("\n"); - } - i++; - } -} - -void list_root() { - FILE f = open("/", 0); - if (f <= 0) { - printf(" -> Could not open '/', error #%i\n", f); - } else { - printf("Now enumerating '/' (fd %i) :\n", f); - list_dir(f, 1); - close(f); - } -} - int main(char** args) { char**a; if (args != 0) { @@ -103,10 +52,7 @@ int main(char** args) { thread_sleep(100); if (threads == 0) break; } - printk("\n"); - - term = open("/.ui/klog", 0); - list_root(); + printk("\n -> Test process exiting. Press the super key to go to the home terminal.\n"); return 0; } diff --git a/src/user/yosh/main.c b/src/user/yosh/main.c index 7586ab0..d334d1e 100644 --- a/src/user/yosh/main.c +++ b/src/user/yosh/main.c @@ -2,17 +2,18 @@ #include <tce/vfs.h> #include <stdlib.h> #include <stdio.h> +#include <readline.h> FILE cwd_f; char *cwd; void about() { - print("Trivial/Computing Environment v0.1.0 - yosh 2.\n"); + print("Trivial/Computing Environment v0.1.0 - yosh 3.\n"); } void help(char *args[]) { if (args[1] == 0) { - print("Available commands: about, help, exit, ls, cd, switch.\n"); + print("Available commands: about, help, exit, ls, cd, goto.\n"); } else if (strcmp(args[1], "about") == 0) { print("Usage:\tabout\nShows some info about yosh. Very usefull.\n"); } else if (strcmp(args[1], "help") == 0) { @@ -25,8 +26,8 @@ void help(char *args[]) { print("Usage:\tcd <location>\nGoes to the location specified.\n"); } else if (strcmp(args[1], "ls") == 0) { print("Usage:\tls\n\tls <location>...\nShows the content of the current/specified directory.\n"); - } else if (strcmp(args[1], "switch") == 0) { - print("Usage:\tswitch <vt name>\nSwitchs focus to specified virtual terminal.\n"); + } else if (strcmp(args[1], "goto") == 0) { + print("Usage:\tgoto <vt name>\nSwitchs focus to specified virtual terminal.\n"); print("Type `ls /.ui` to see available terminals.\n"); } else { printf("No such command: %s\n", args[1]); @@ -82,7 +83,7 @@ void simplify_path(char* p) { } } -char* path_cat (char* a, char* b) { +char* path_cat (char* a, char* b, int trailing_slash) { char* ret; if (b[0] == '/') { int lb = strlen(b); @@ -111,6 +112,10 @@ char* path_cat (char* a, char* b) { ret[la + lb] = 0; } simplify_path(ret); + if (!trailing_slash) { + int l = strlen(ret); + if (ret[l-1] == '/') ret[l-1] = 0; + } return ret; } @@ -120,7 +125,7 @@ void cd(char **args) { } if (strcmp(args[1], ".") == 0) return; - char* newcwd = path_cat(cwd, args[1]); + char* newcwd = path_cat(cwd, args[1], 1); file_info info; int i = stat(newcwd, &info); @@ -135,7 +140,7 @@ void cd(char **args) { free(newcwd); } else { FILE nf = open(newcwd, 0); - if (nf <= 0) { + if (nf < 0) { printf("Error opening: %i\n", nf); free(newcwd); } else { @@ -186,16 +191,18 @@ void ls(char **args) { int i; for (i = 1; args[i] != 0; i++) { printf("Contents of %s :\n", args[i]); - char* d = path_cat(cwd, args[i]); + char* d = path_cat(cwd, args[i], 1); file_info info; int e = stat(d, &info); if (e == E_NOT_FOUND) { print(" No such file or directory\n"); } else if (e < 0) { printf(" Error stating: %i\n", e); + } else if ((info.type & FT_DIR) == 0) { + printf(" Not a directory.\n"); } else { FILE ff = open(d, 0); - if (ff <= 0) { + if (ff < 0) { printf(" Error opening: %i\n", ff); } else { ls_dir(ff); @@ -207,12 +214,35 @@ void ls(char **args) { } } -void t_switch(char** args) { +void cat(char **args) { + int i; + for (i = 1; args[i] != 0; i++) { + char *d = path_cat(cwd, args[i], 0); + file_info info; + int e = stat(d, &info); + if (e == E_NOT_FOUND) { + printf("No such file: %s\n", d); + } else if (e < 0) { + printf("Error stating %s : %i\n", d, e); + } else if ((info.type & FT_FILE) == 0) { + printf("Not a file: %s\n", d); + } else { + FILE ff = open(d, 0); + char* buff = (char*)malloc(info.size); + read(ff, 0, info.size, buff); + close(ff); + write(term, 0, info.size, buff); + free(buff); + } + } +} + +void t_goto(char** args) { if (args[1] == 0) { - print("Usage: switch <vt_name>\n"); + print("Usage: goto <vt_name>\n"); return; } - char* p = path_cat("/.ui/", args[1]); + char* p = path_cat("/.ui/", args[1], 0); int i; if ((i = link(p, "/.dev/vgatxt", LM_OUTPUT_TO)) == 0) { link("/.dev/ps2kbd", p, LM_OUTPUT_TO); @@ -222,78 +252,116 @@ void t_switch(char** args) { } int main(char **sh_args) { - term = open("/.ui/home", 0); - if (term <= 0) { - return -1; - } - about(); cwd = strdup("/"); cwd_f = open(cwd, 0); - char *path = path_cat(sh_args[0], ".."); - + char *path = path_cat(sh_args[0], "..", 1); + + int bg_pr[128], bg_pr_c = 0; + + readline_history h; h.str = 0; h.max = 4; + while (1) { - printf(" %s ", cwd); + printf("\x1b[33m %s \x1b[1m", cwd); - char *s = readln(); + char *s = readline(term, &h); + printf("\x1b[0m"); if (s == 0) return -1; - int l = strlen(s); - if (s[l-1] == '\n') { - s[l-1] = 0; l--; - - char *c_args[16] = {0}, *cmd; - c_args[0] = s; - int argc = 1; - for (cmd = s; *cmd != 0; cmd++) { - if (*cmd == ' ') { - *cmd = 0; - if (cmd[1] != ' ' && cmd[1] != 0) { - c_args[argc] = cmd + 1; - argc++; - if (argc == 15) break; - } + if (*s == 0) continue; + + char *c_args[16] = {0}, *cmd; + c_args[0] = s; + int argc = 1; + for (cmd = s; *cmd != 0; cmd++) { + if (*cmd == ' ') { + *cmd = 0; + if (cmd[1] != ' ' && cmd[1] != 0) { + c_args[argc] = cmd + 1; + argc++; + if (argc == 15) break; + } + } + } + + if (strcmp(c_args[0], "about") == 0) { + about(); + } else if (strcmp(c_args[0], "help") == 0) { + help(c_args); + } else if (strcmp(c_args[0], "exit") == 0) { + print("Exiting the shell. See you later!\n"); + break; + } else if (strcmp(c_args[0], "cd") == 0) { + cd(c_args); + } else if (strcmp(c_args[0], "ls") == 0) { + ls(c_args); + } else if (strcmp(c_args[0], "goto") == 0) { + t_goto(c_args); + } else if (strcmp(c_args[0], "cat") == 0) { + cat(c_args); + } else { + FILE vt = term; + char *t = 0; + if (strcmp(c_args[0], "on") == 0) { + if (c_args[1] == 0 || c_args[2] == 0) { + printf("Usage:\ton <vt> <command>\n"); + continue; + } + t = path_cat("/.ui/", c_args[1], 0); + vt = open(t, 0); + if (vt < 0 || vt == term) { + printf("Error: cannot open terminal %s (%i)\n", t, vt); + free(t); + continue; + } + int i = 0; + while (1) { + c_args[i] = c_args[i+2]; + if (c_args[i] == 0) break; + i++; } } - if (strcmp(c_args[0], "about") == 0) { - about(); - } else if (strcmp(c_args[0], "help") == 0) { - help(c_args); - } else if (strcmp(c_args[0], "exit") == 0) { - print("Exiting the shell. See you later!\n"); - break; - } else if (strcmp(c_args[0], "cd") == 0) { - cd(c_args); - } else if (strcmp(c_args[0], "ls") == 0) { - ls(c_args); - } else if (strcmp(c_args[0], "switch") == 0) { - t_switch(c_args); + char *c; + if (strchr(c_args[0], '/')) { + c = path_cat(cwd, c_args[0], 0); } else { - char *c; - if (strchr(c_args[0], '/')) { - c = path_cat(cwd, c_args[0]); + c = path_cat(path, c_args[0], 0); + } + int pid = run(c, c_args + 1, vt); + if (pid <= 0) { + if (pid == E_NOT_FOUND) { + printf("Error: no such file %s\n", c); } else { - c = path_cat(path, c_args[0]); + printf("Error %i\n", pid); } - int pid = run(c, c_args + 1); - if (pid <= 0) { - if (pid == E_NOT_FOUND) { - printf("Error: no such file %s\n", c); - } else { - printf("Error %i\n", pid); - } - } else { - int ret = waitpid(pid); + } else { + if (vt == term) { + int ret = waitpid(pid, 1); printf(" -> child (pid %i) exited with status %i\n", pid, ret); + } else { + printf(" -> running on terminal %s, pid:%i\n", t, pid); + bg_pr[bg_pr_c++] = pid; + free(t); } - free(c); } - } else { - print("[freadln fail, sorry.]\n"); + free(c); + } + + for (; s < cmd; s++) if (*s == 0) *s = ' '; + + int i = 0; + while (i < bg_pr_c) { + int ret = waitpid(bg_pr[i], 0); + if (ret != E_NOT_FINISHED) { + printf(" -> child (pid %i) exited with status %i\n", bg_pr[i], ret); + bg_pr_c--; + bg_pr[i] = bg_pr[bg_pr_c]; + } else { + i++; + } } - free(s); } return 0; |