From 8215f5f278bb5827db06788c203cc1430d459583 Mon Sep 17 00:00:00 2001 From: MartinusR Date: Fri, 12 May 2017 22:05:57 +0200 Subject: [PATCH] History, pipe, redirections (?) --- TODO | 14 +- programs/lib/error.c | 2 +- programs/lib/error.h | 2 +- programs/lib/keycode.c | 4 + programs/lib/keycode.h | 12 +- programs/lib/lib.c | 8 +- programs/lib/parsing.c | 2 +- programs/lib/stream.c | 3 +- programs/src/cacatoes/main.c | 1 - programs/src/cat/main.c | 16 +-- programs/src/cp/main.c | 6 +- programs/src/kill/main.c | 4 +- programs/src/ls/main.c | 5 +- programs/src/mkdir/main.c | 4 +- programs/src/mv/main.c | 6 +- programs/src/p/main.c | 6 +- programs/src/ps/main.c | 1 + programs/src/rm/main.c | 4 +- programs/src/rmdir/main.c | 4 +- programs/src/shell/main.c | 256 ++++++++++++++++++++++++++++++++--- programs/src/spread/main.c | 13 +- programs/src/touch/main.c | 4 +- sources/channel.c | 42 +++++- sources/channel.h | 4 +- sources/error.c | 2 +- sources/error.h | 2 +- sources/kernel.c | 14 +- sources/timer.c | 1 + 28 files changed, 363 insertions(+), 79 deletions(-) diff --git a/TODO b/TODO index 4fc7840..7cda186 100644 --- a/TODO +++ b/TODO @@ -6,6 +6,7 @@ File system : - Duplication of function finddir - Directories Improvement : open them as streams ? - Add some malloc and free instead of 'buffer', but this will make unsafe a lot of currently safe functions ! + - BUg of mv a b; rm b -> crash ? (twice)!!! Global organisation : - Folders ? @@ -29,4 +30,15 @@ Malloc : - Test - Kernel one ? - +Shell: + - Colors for directories in ls + alignement + - tree + - Implement fwrite (writes stdin into a file) + - Test redirection > + - Code cat properly to not display error message ? (special end character ?) + - Code commands to accept input from stdin ! (not all) + - Multiple arguments ? + - Options ? + - Cacatoes -> fg color ? (+print dans un fichier, le stocker, et ne faire que le charger) + - Cursor not disappearing when scroll + - Scroll with arrows diff --git a/programs/lib/error.c b/programs/lib/error.c index 0f557f5..f86f160 100644 --- a/programs/lib/error.c +++ b/programs/lib/error.c @@ -48,7 +48,7 @@ void init_error_msg() { error_msg[43] = "Message too long"; error_msg[44] = "Too many processes"; error_msg[45] = "Too many streams"; - error_msg[46] = "Protocol not supported"; + error_msg[46] = "Alone on this channel"; error_msg[47] = "Socket type not supported"; error_msg[48] = "Operation not supported on socket"; error_msg[49] = "Protocol family not supported"; diff --git a/programs/lib/error.h b/programs/lib/error.h index 2123671..9acbf08 100644 --- a/programs/lib/error.h +++ b/programs/lib/error.h @@ -51,7 +51,7 @@ typedef enum { EMSGSIZE, //Message too long EMPROC, //Too many processes EMSTREAM, //Too many streams - EPROTONOSUPPORT, //Protocol not supported + EALONE, //Alone on this channel ESOCKTNOSUPPORT, //Socket type not supported EOPNOTSUPP, //Operation not supported on socket EPFNOSUPPORT, //Protocol family not supported diff --git a/programs/lib/keycode.c b/programs/lib/keycode.c index 1c4bf9e..214cd5a 100644 --- a/programs/lib/keycode.c +++ b/programs/lib/keycode.c @@ -55,6 +55,10 @@ void initCharTable() { chars[KEY_COLON] = ':'; chars[KEY_EXCLAMATION] = '!'; chars[KEY_COMP] = '<'; + chars[KEY_UP] = 0x11; + chars[KEY_DOWN] = 0x12; + chars[KEY_LEFT] = 0x13; + chars[KEY_RIGHT] = 0x14; char *shift = chars + 128; shift[KEY_A] = 'A'; diff --git a/programs/lib/keycode.h b/programs/lib/keycode.h index 6687d3b..5780b1f 100644 --- a/programs/lib/keycode.h +++ b/programs/lib/keycode.h @@ -61,19 +61,23 @@ #define KEY_ALT_GR 56 #define KEY_SPACE 57 #define KEY_NUM_1 79 -#define KEY_NUM_2 80 +#define KEY_DOWN 80 #define KEY_NUM_3 81 -#define KEY_NUM_4 75 +#define KEY_LEFT 75 #define KEY_NUM_5 76 -#define KEY_NUM_6 77 +#define KEY_RIGHT 77 #define KEY_NUM_7 71 -#define KEY_NUM_8 72 +#define KEY_UP 72 #define KEY_NUM_9 73 #define KEY_NUM_0 82 // TODO ARROWS have same code ?! (ci dessus) #define KEY_COMP 86 #define TERMINATION_KEY 0 +#define CHAR_UP 0x11 +#define CHAR_DOWN 0x12 +#define CHAR_LEFT 0x13 +#define CHAR_RIGHT 0x14 char getKeyChar(u8 key, u8 shift, u8 alt); void initCharTable(); diff --git a/programs/lib/lib.c b/programs/lib/lib.c index 3cf1370..66832f9 100644 --- a/programs/lib/lib.c +++ b/programs/lib/lib.c @@ -15,9 +15,10 @@ void clear_screen(u8 color) { set_char_at(' ', color, color, x , y); } -u32 last_rand = 1351968; +u32 last_rand; u32 rand() { + last_rand = (last_rand * 16807) % (((u32) 1 << 31) -1); return last_rand; } @@ -27,6 +28,11 @@ void lib_init() { create_channel_stream(1); initCharTable(); init_error_msg(); + rtc_time_t t; + gettimeofday(&t); + last_rand = ((u32) 16807 * 16807 * 16807 * ((u32) t.century - (u32) t.year + (u32) t.month) + + 16807 * 16807 * ((u32)t.day - (u32)t.hours) + + 16807 * ((u32)t.minutes + (u32)t.seconds) + 49 * (u32)t.mseconds) % (((u32) 1 << 31) - 1); } void *memcpy(void *dst, void *src, u32 n) { diff --git a/programs/lib/parsing.c b/programs/lib/parsing.c index 5788f36..a4fc6ec 100644 --- a/programs/lib/parsing.c +++ b/programs/lib/parsing.c @@ -80,6 +80,6 @@ int string_to_int(char *src) { } void too_many_args(char *fun) { - fprintf(STDERR, "%s: Too many arguments", fun); + fprintf(STDERR, "%s: Too many arguments\n", fun); exit(EXIT_FAILURE); } \ No newline at end of file diff --git a/programs/lib/stream.c b/programs/lib/stream.c index 3f86ddb..a3ac1f5 100644 --- a/programs/lib/stream.c +++ b/programs/lib/stream.c @@ -95,10 +95,11 @@ int flush(sid_t sid) { if (is_channel) { int ready = wait_channel(stream->chanid, 1); while (ready == -1) { + if (errno == EALONE) + return -1; sleep(10); ready = wait_channel(stream->chanid, 1); } - wait_channel(stream->chanid, 1); written = send(stream->chanid, index, remaining); } else { diff --git a/programs/src/cacatoes/main.c b/programs/src/cacatoes/main.c index 02d7783..ce843cd 100644 --- a/programs/src/cacatoes/main.c +++ b/programs/src/cacatoes/main.c @@ -71,7 +71,6 @@ int main(char *args) { break; } flush(STDOUT); - sleep(500); exit(EXIT_SUCCESS); return 0; } \ No newline at end of file diff --git a/programs/src/cat/main.c b/programs/src/cat/main.c index b417521..b9b555a 100644 --- a/programs/src/cat/main.c +++ b/programs/src/cat/main.c @@ -15,12 +15,12 @@ int main(char *args) { while (run) { nb = wait_channel(STDIN, 0); if (nb < 0) { - fprintf(STDERR, "cat: Cannot read input: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot read input: %s\n", strerror(errno)); exit(EXIT_FAILURE); } nb = receive(STDIN, buffer, 512); if (nb < 0) { - fprintf(STDERR, "cat: Cannot read input: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot read input: %s\n", strerror(errno)); exit(EXIT_FAILURE); } for (int j = 0; j < nb; j++) { @@ -32,12 +32,12 @@ int main(char *args) { while (nb > 0) { written = wait_channel(STDOUT, 1); if (written < 0) { - fprintf(STDERR, "cat: Cannot write to output: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot write to output: %s\n", strerror(errno)); exit(EXIT_FAILURE); } written = send(STDOUT, buffer, nb); if (written < 0) { - fprintf(STDERR, "cat: Cannot write to output: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot write to output: %s\n", strerror(errno)); exit(EXIT_FAILURE); } nb -= written; @@ -47,7 +47,7 @@ int main(char *args) { if (nb_args == 1) { fd_t fd = fopen(path, O_RDONLY); if (fd < 0) { - fprintf(STDERR, "cat: Couldn't open %s: %s", path, strerror(errno)); + fprintf(STDERR, "cat: Couldn't open %s: %s\n", path, strerror(errno)); exit(EXIT_FAILURE); } char buffer[512]; @@ -60,20 +60,20 @@ int main(char *args) { exit(EXIT_SUCCESS); } if (nb == -1) { - fprintf(STDERR, "cat: Failed to read file %s: %s", path, strerror(errno)); + fprintf(STDERR, "cat: Failed to read file %s: %s\n", path, strerror(errno)); close(fd); exit(EXIT_FAILURE); } while (nb > 0) { written = wait_channel(STDOUT, 1); if (written < 0) { - fprintf(STDERR, "cat: Cannot write to output: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot write to output: %s\n", strerror(errno)); close(fd); exit(EXIT_FAILURE); } written = send(STDOUT, buffer, nb); if (written < 0) { - fprintf(STDERR, "cat: Cannot write to output: %s", strerror(errno)); + fprintf(STDERR, "cat: Cannot write to output: %s\n", strerror(errno)); close(fd); exit(EXIT_FAILURE); } diff --git a/programs/src/cp/main.c b/programs/src/cp/main.c index 5c4a4fc..53ab383 100644 --- a/programs/src/cp/main.c +++ b/programs/src/cp/main.c @@ -8,11 +8,11 @@ int main(char *args) { too_many_args("cp"); if (nb == 0) { - fprintf(STDERR, "cp: Missing operands"); + fprintf(STDERR, "cp: Missing operands\n"); exit(EXIT_FAILURE); } if (nb == 1) { - fprintf(STDERR, "cp: Missing destination operand"); + fprintf(STDERR, "cp: Missing destination operand\n"); exit(EXIT_FAILURE); } char *src = paths[0]; @@ -20,7 +20,7 @@ int main(char *args) { int res = fcopy(src, dest); if (res != 0) { - fprintf(STDERR, "cp: Cannot copy %s to %s: %s", src, dest, strerror(errno)); + fprintf(STDERR, "cp: Cannot copy %s to %s: %s\n", src, dest, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); diff --git a/programs/src/kill/main.c b/programs/src/kill/main.c index a374e91..3d3677a 100644 --- a/programs/src/kill/main.c +++ b/programs/src/kill/main.c @@ -35,14 +35,14 @@ int main(char *args) { return 0; } if (nb_args == 0) { - fprintf(STDERR, "kill: Missing poor target process"); + fprintf(STDERR, "kill: Missing poor target process\n"); exit(EXIT_FAILURE); } if (nb_args == 1) { errno = EINVAL; pid = string_to_int(pid_string); if (pid == -1 || kill_rec(pid) == -1) { - fprintf(STDERR, "kill: Cannot kill process %s: %s", pid_string, strerror(errno)); + fprintf(STDERR, "kill: Cannot kill process %s: %s\n", pid_string, strerror(errno)); exit(EXIT_FAILURE); } } diff --git a/programs/src/ls/main.c b/programs/src/ls/main.c index 42c3010..913188b 100644 --- a/programs/src/ls/main.c +++ b/programs/src/ls/main.c @@ -7,7 +7,7 @@ int main(char *args) { } fd_t fd = opendir(args); if (fd < 0) { - fprintf(STDERR, "ls: Cannot open directory / %s: %s", args, strerror(errno)); + fprintf(STDERR, "ls: Cannot open directory / %s: %s\n", args, strerror(errno)); exit(EXIT_FAILURE); } int res = readdir(fd, &dirent); @@ -18,9 +18,10 @@ int main(char *args) { int err = errno; closedir(fd); if (err != ENOENT) { - fprintf(STDERR, "\nls: An error occured while reading %s: %s", args, strerror(errno)); + fprintf(STDERR, "\nls: An error occured while reading %s: %s\n", args, strerror(errno)); exit(EXIT_FAILURE); } + printf("\n"); flush(STDOUT); exit(EXIT_SUCCESS); return 0; diff --git a/programs/src/mkdir/main.c b/programs/src/mkdir/main.c index bdbc16e..d7ef288 100644 --- a/programs/src/mkdir/main.c +++ b/programs/src/mkdir/main.c @@ -2,12 +2,12 @@ int main(char *args) { if (!*args) { - fprintf(STDERR, "mkdir: Missing operand"); + fprintf(STDERR, "mkdir: Missing operand\n"); exit(EXIT_FAILURE); } int res = mkdir(args, 0); if (res != 0) { - fprintf(STDERR, "mkdir: Cannot create directory '%s': %s", args, strerror(errno)); + fprintf(STDERR, "mkdir: Cannot create directory '%s': %s\n", args, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); diff --git a/programs/src/mv/main.c b/programs/src/mv/main.c index c42ee14..06f45ea 100644 --- a/programs/src/mv/main.c +++ b/programs/src/mv/main.c @@ -26,11 +26,11 @@ int main(char *args) { too_many_args("mv"); if (nb == 0) { - fprintf(STDERR, "mv: Missing operands"); + fprintf(STDERR, "mv: Missing operands\n"); exit(EXIT_FAILURE); } if (nb == 1) { - fprintf(STDERR, "mv: Missing destination operand"); + fprintf(STDERR, "mv: Missing destination operand\n"); exit(EXIT_FAILURE); } char *src = paths[0]; @@ -38,7 +38,7 @@ int main(char *args) { int res = aux_mv(src, dest); if (res != 0) { - fprintf(STDERR, "mv: Cannot rename %s into %s: %s", src, dest, strerror(errno)); + fprintf(STDERR, "mv: Cannot rename %s into %s: %s\n", src, dest, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); diff --git a/programs/src/p/main.c b/programs/src/p/main.c index bbfb9b2..8967c7a 100644 --- a/programs/src/p/main.c +++ b/programs/src/p/main.c @@ -3,12 +3,12 @@ u8 recv_buff[513]; int main() { - clear_screen(COLOR_BLUE); + clear_screen(BLUE); u8 c = '%'; if(send(1, &c, 1) < 0) { int err = errno; - set_char_at('0'+err/10, COLOR_GREEN, COLOR_BLUE, 0, 0); - set_char_at('0'+err%10, COLOR_GREEN, COLOR_BLUE, 1, 0); + set_char_at('0'+err/10, GREEN, BLUE, 0, 0); + set_char_at('0'+err%10, GREEN, BLUE, 1, 0); for(;;); } for(u8 i = 0;; i++) { diff --git a/programs/src/ps/main.c b/programs/src/ps/main.c index fab49a9..e0c0353 100644 --- a/programs/src/ps/main.c +++ b/programs/src/ps/main.c @@ -53,6 +53,7 @@ int main(char *args) { pid++; res = pinfo(pid, &p); } + printf("\n"); exit(EXIT_SUCCESS); return 0; } diff --git a/programs/src/rm/main.c b/programs/src/rm/main.c index 2ed455b..7ed6122 100644 --- a/programs/src/rm/main.c +++ b/programs/src/rm/main.c @@ -2,12 +2,12 @@ int main(char *args) { if (!*args) { - fprintf(STDERR, "rm: Missing operand"); + fprintf(STDERR, "rm: Missing operand\n"); exit(EXIT_FAILURE); } int res = remove(args); if (res != 0) { - fprintf(STDERR, "rm: Cannot delete '%s': %s", args, strerror(errno)); + fprintf(STDERR, "rm: Cannot delete '%s': %s\n", args, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); diff --git a/programs/src/rmdir/main.c b/programs/src/rmdir/main.c index 504a92f..5fb422e 100644 --- a/programs/src/rmdir/main.c +++ b/programs/src/rmdir/main.c @@ -2,12 +2,12 @@ int main(char *args) { if (!*args) { - fprintf(STDERR, "rmdir: Missing operand"); + fprintf(STDERR, "rmdir: Missing operand\n"); exit(EXIT_FAILURE); } int res = rmdir(args); if (res != 0) { - fprintf(STDERR, "rmdir: Cannot remove directory '%s': %s", args, strerror(errno)); + fprintf(STDERR, "rmdir: Cannot remove directory '%s': %s\n", args, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); diff --git a/programs/src/shell/main.c b/programs/src/shell/main.c index 7ade70a..c27b88f 100644 --- a/programs/src/shell/main.c +++ b/programs/src/shell/main.c @@ -2,7 +2,9 @@ #include "parsing.h" #define CMD_SIZE 0x200 +#define HISTORY_LENGTH 512 #define NB_SHELL_CMD 27 + char *shell_commands[NB_SHELL_CMD] = { "ls", "mkdir", @@ -23,13 +25,20 @@ char *shell_commands[NB_SHELL_CMD] = { #define SHELL_CMD_PATH "/" #define SHELL_CMD_EXT ".bin" +#define SHELL_PATH "/shell.bin" u8 recv_buff[512]; char cmd[CMD_SIZE]; char cwd[MAX_PATH_NAME]; +char *history[HISTORY_LENGTH] = {0}; +int last_cmd = 0; +int cur_cmd = 0; +int first_cmd = 0; + int pos; int run; +int ephemeral = 0; void new_cmd() { printf("%fgwhateveryouwant@CacatOez:%pfg%fg%s%pfg>", GREEN, BLUE, cwd); @@ -39,7 +48,11 @@ void new_cmd() { int exec_builtin(char *fun, char *args) { if(strEqual(fun, "help")) { - printf("Available commands: help, exit, int, test\n"); + printf("Available commands:\n"); + for (int i = 0; i < NB_SHELL_CMD; i++) { + if (shell_commands[i]) + printf("%fg%s\n%pfg", BLUE, shell_commands[i]); + } } else if(strEqual(fun, "exit")) { char *exit_string; @@ -57,16 +70,16 @@ int exec_builtin(char *fun, char *args) { } else if (strEqual(fun, "pwd")) { if (*args) { - fprintf(STDERR, "pwd: Too many arguments"); + fprintf(STDERR, "pwd: Too many arguments\n"); } else { int res = getcwd(cwd); if (res == -1) { - fprintf(STDERR, "pwd: Couldn't print current working directory: %s", + fprintf(STDERR, "pwd: Couldn't print current working directory: %s\n", strerror(errno)); } else { - printf("%s", cwd); + printf("%s\n", cwd); } } } @@ -74,14 +87,14 @@ int exec_builtin(char *fun, char *args) { char *path; int nb_args = get_args(args, &path, 1); if (nb_args == -1) { - fprintf(STDERR, "cd: Too many arguments"); + fprintf(STDERR, "cd: Too many arguments\n"); } else { if (nb_args == 0) path = ROOT_NAME_STR; int res = chdir(path); if (res == -1) - fprintf(STDERR, "cd: Couldn't change directory to %s: %s", path, + fprintf(STDERR, "cd: Couldn't change directory to %s: %s\n", path, strerror(errno)); else { getcwd(cwd); @@ -98,18 +111,18 @@ int exec_builtin(char *fun, char *args) { return 0; } -int exec_file(char *file, char *args) { - printf("Exec file <%s>\n", file); - if(exec(file, args, STDIN, STDOUT) < 0) // TODO Args ? +int exec_file(char *file, char *args, int bg) { + //printf("Exec file <%s> with args <%s> and bg <%d>\n", file, args, bg); + if(exec(file, args, STDIN, STDOUT) < 0) printf("Error: %s\n", strerror(errno)); - else { + else if (!bg) { int status; wait(&status); } return 0; } -int exec_shell_cmd(char *fun, char *args) { +int exec_shell_cmd(char *fun, char *args, int bg) { int i; for (i = 0; i < NB_SHELL_CMD; i++) { if (shell_commands[i] && strEqual(shell_commands[i], fun)) @@ -124,16 +137,17 @@ int exec_shell_cmd(char *fun, char *args) { strCopy(fun, &file[offset]); offset += strlen(fun); strCopy(SHELL_CMD_EXT, &file[offset]); - exec_file(file, args); + exec_file(file, args, bg); return 0; } -void exec_cmd() { +int exec_simple_cmd(char *s, int bg) { errno = ECLEAN; char *first; - char *args = parse_arg(cmd, &first); + char *args = parse_arg(s, &first); args = args ? args : ""; - + //printf("Executing simple cmd <%s> with args <%s>\n", first, args); + //flush(STDOUT); if (first != NULL) { if (exec_builtin(first, args) != 0) { if(strEqual(first, "test")) { @@ -143,14 +157,165 @@ void exec_cmd() { asm volatile ("int $13"); } else if(first[0] == '/' || first[0] == '.') { // Execute a file. - exec_file(first, args); + return exec_file(first, args, bg); } else { - if (exec_shell_cmd(first, args) == -1) - printf("Unknown command (%s)", cmd); + if (exec_shell_cmd(first, args, bg) == -1) { + fprintf(STDERR, "Unknown command (%s)\n", s); + return -1; + } + } + } + } + return 0; +} + +char *strip(char *s) { + // Removes ending spaces and returns pointer to the end. + char *cur = s; + while (*cur) + cur++; + cur--; + while (cur >= s && *cur == ' ') + *cur-- = 0; + if (cur >= s) + return cur; + return s; +} + +int exec_pipe(char *cmd1, char *cmd2, int no_wait) { + //printf("Executing some pipe\n"); + //flush(STDOUT); + strip(cmd1); + strip(cmd2); + if (!*cmd1 || !*cmd2) { + fprintf(STDERR, "pipe: Syntax error\n"); + return -1; + } + int chan = new_channel(); + if (chan == -1) { + fprintf(STDERR, "pipe: Unable to create a channel: %s\n", strerror(errno)); + return -1; + } + int res1 = exec(SHELL_PATH, cmd1, STDIN, chan); + if (res1 == -1) { + fprintf(STDERR, "pipe: Unable to exec: %s\n", strerror(errno)); + } + sleep(50); + int res2 = exec(SHELL_PATH, cmd2, chan, STDOUT); + if (res2 == -1) { + fprintf(STDERR, "pipe: Unable to exec: %s\n", strerror(errno)); + } + free_channel(chan); + if (ephemeral) { + free_channel(STDIN); + free_channel(STDOUT); + } + if (!no_wait && res1 >= 0) { + wait(NULL); + } + if (!no_wait && res2 >= 0) { + wait(NULL); + } + return 0; +} + +int exec_redir(char *s, int bg) { + //printf("searching some redirection\n"); + //flush(STDOUT); + char *cur = s; + while (*cur) { + if (*cur == '>') { + *cur = 0; + cur++; + //printf("Found a redirection to %s\n", cur); + // Executes '| fwrite' instead + char *cmd2 = malloc(MAX_PATH_NAME); + if (cmd2 == NULL) { + fprintf(STDERR, "redirection >: Out of memory\n"); + return -1; + } + strCopy(SHELL_CMD_PATH, cmd2); + int offset = strlen(SHELL_CMD_PATH); + strCopy("fwrite", &cmd2[offset]); + offset += strlen("fwrite"); + strCopy(SHELL_CMD_EXT, &cmd2[offset]); + offset += strlen(SHELL_CMD_EXT); + cmd2[offset] = ' '; + offset++; + strCopy(cur, &cmd2[offset]); + int res = exec_pipe(s, cmd2, 1); + free(cmd2); + return res;; + } + cur++; + } + // No redirections + return exec_simple_cmd(s, bg); +} + +int exec_cmd(char *s) { + //printf("Parsing some cmd\n"); + //flush(STDOUT); + // Search for pipes + char *cur = s; + while(*cur) { + if (*cur == '|') { + *cur = 0; + cur++; + return exec_pipe(s, cur, 0); + } + cur++; + } + //printf("No pipes, searching for &\n"); + //flush(STDOUT); + // It is a simple command. + // Checks for an ampersand + char *last_ch = strip(s); + + if (*last_ch == '&') { + if (ephemeral) { + // We have to execute this command and die. + *last_ch = 0; + //printf("We have to exec this cmd and die\n"); + //flush(STDOUT); + return exec_redir(s, 1); + } + else { + //printf("Found a &: forking a ephemeral shell\n"); + //flush(STDOUT); + int res = exec(SHELL_PATH, s, -1, STDOUT); + if (res == -1) { + fprintf(STDERR, "bg-task: Unable to exec: %s\n", strerror(errno)); + return -1; } + wait(NULL); + return 0; } } + //printf("No &\n"); + return exec_redir(s, 0); +} + +void save_cmd() { + int prev_cmd = (last_cmd + HISTORY_LENGTH - 1) % HISTORY_LENGTH; + if (last_cmd == first_cmd || !strEqual(history[prev_cmd], cmd)) { + size_t len = strlen(cmd); + history[last_cmd] = malloc(len + 1); + if (history[last_cmd]) { + strCopy(cmd, history[last_cmd]); + last_cmd = (last_cmd + 1) % HISTORY_LENGTH; + } + if (history[last_cmd]) { + free(history[last_cmd]); + history[last_cmd] = NULL; + first_cmd = (first_cmd + 1) % HISTORY_LENGTH; + } + } + cur_cmd = last_cmd; +} + +void clear_cmd() { while(pos > 0) cmd[--pos] = 0; new_cmd(); @@ -160,22 +325,71 @@ void key_typed(u8 c) { if(c == '\n' || pos == CMD_SIZE-1) { stream_putchar(c, STDOUT); flush(STDOUT); - exec_cmd(); + char *end = strip(cmd); + if (*end) { + save_cmd(); + exec_cmd(cmd); + } + clear_cmd(); } else if(c == 0x8) { if(pos > 0) { cmd[--pos] = 0; stream_putchar(c, STDOUT); } - } else { + } else if (c == CHAR_UP) { + if (cur_cmd == first_cmd) + return; + + cur_cmd = (cur_cmd + HISTORY_LENGTH - 1) % HISTORY_LENGTH; + while (pos > 0) { + cmd[--pos] = 0; + stream_putchar(0x8, STDOUT); + } + if (history[cur_cmd]) { + char *s = history[cur_cmd]; + while (*s) { + c = *s++; + cmd[pos++] = c; + stream_putchar(c, STDOUT); + } + } + } else if (c == CHAR_DOWN) { + if (cur_cmd == last_cmd) { + return; + } + while (pos > 0) { + cmd[--pos] = 0; + stream_putchar(0x8, STDOUT); + } + + cur_cmd = (cur_cmd + 1) % HISTORY_LENGTH; + if (history[cur_cmd]) { + char *s = history[cur_cmd]; + while (*s) { + c = *s++; + cmd[pos++] = c; + stream_putchar(c, STDOUT); + } + } + }else if (c == CHAR_LEFT || c == CHAR_RIGHT) { + // Nothing to do yet. + } + else { cmd[pos++] = c; stream_putchar(c, STDOUT); } } -int main() { +int main(char *init_cmd) { + ephemeral = *init_cmd; run = 1; + flush(STDOUT); memset(cwd, 0, MAX_PATH_NAME); getcwd(cwd); + if (ephemeral) { + //printf("EPHEMERAL\n"); + exit(exec_cmd(init_cmd)); + } new_cmd(); while(run) { int ct; diff --git a/programs/src/spread/main.c b/programs/src/spread/main.c index 8ee4fe9..8320969 100644 --- a/programs/src/spread/main.c +++ b/programs/src/spread/main.c @@ -42,10 +42,10 @@ void incr_new_at(char v, u8 x, u8 y) { void init() { initCharTable(); - player_color[0] = COLOR_RED; - player_color[1] = COLOR_BLUE; - neutral_color = COLOR_BLACK; - clear_screen(COLOR_WHITE); + player_color[0] = RED; + player_color[1] = BLUE; + neutral_color = BLACK; + clear_screen(WHITE); for(int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { map[i] = 0; } @@ -134,7 +134,7 @@ int main() { score += get_at(x, y); } } - u8 bg = COLOR_WHITE; + u8 bg = WHITE; u8 fg; if(score == 0) fg = neutral_color; else fg = player_color[(sgn(score)+1)/2]; @@ -143,5 +143,6 @@ int main() { set_char_at('#', fg, bg, x, y); } } - for(;;) asm("hlt"); + sleep(1000); + exit(EXIT_SUCCESS); } diff --git a/programs/src/touch/main.c b/programs/src/touch/main.c index c411c82..dcbb64f 100644 --- a/programs/src/touch/main.c +++ b/programs/src/touch/main.c @@ -8,14 +8,14 @@ int main(char *args) { too_many_args("touch"); if (nb == 0) { - fprintf(STDERR, "touch: Missing operand"); + fprintf(STDERR, "touch: Missing operand\n"); exit(EXIT_FAILURE); } fd_t res = fopen(file, O_CREAT); if (res == -1) { - fprintf(STDERR, "touch: Couldn't touch file %s: %s", file, strerror(errno)); + fprintf(STDERR, "touch: Couldn't touch file %s: %s\n", file, strerror(errno)); exit(EXIT_FAILURE); } close(res); diff --git a/sources/channel.c b/sources/channel.c index 05b108e..bdd47e5 100644 --- a/sources/channel.c +++ b/sources/channel.c @@ -33,6 +33,7 @@ int new_channel(channel_state_t *channels) { channels_table[i].size = CHANNEL_SIZE; channels_table[i].sender = -1; channels_table[i].receiver = -1; + channels_table[i].nb_users = 1; channels[chan_index].chanid = i; channels[chan_index].read = 1; channels[chan_index].write = 1; @@ -43,18 +44,37 @@ int new_channel(channel_state_t *channels) { return -1; } -int free_channel(int chanid, channel_state_t *channels) { - // Frees the corresponding channel +int free_channel(state *s, int chanid, channel_state_t *channels) { + // Frees the corresponding channel for one user. if (check_channel(chanid, channels) == -1) return -1; int kchanid = channels[chanid].chanid; - if (channels_table[kchanid].len != 0 || channels_table[kchanid].receiver >= 0) { - errno = EINPROGRESS; - return -1; + channels_table[kchanid].receiver -= 1; + + if (channels_table[kchanid].nb_users == 1) { + // Release with an error the receiver and sender. + pid_t waiter = channels_table[kchanid].receiver; + if (waiter >= 0) { + // Release receiver + s->processes[waiter].saved_context.regs.eax = -1; + s->processes[waiter].saved_context.regs.ebx = EALONE; + s->processes[waiter].state = RUNNABLE; + channels_table[kchanid].receiver = -1; + } + waiter = channels_table[kchanid].sender; + if (waiter >= 0) { + // Release sender + s->processes[waiter].saved_context.regs.eax = -1; + s->processes[waiter].saved_context.regs.ebx = EALONE; + s->processes[waiter].state = RUNNABLE; + channels_table[kchanid].receiver = -1; + } + } + + if (channels_table[kchanid].nb_users <= 0) { + channels_table[kchanid].data = NULL; } - // TODO free(channels_table[chanid].data); - channels_table[chanid].data = NULL; channels[chanid].chanid = -1; return 0; } @@ -200,6 +220,10 @@ ssize_t wait_channel(state *s) { // Looks for some place. size_t empty = channels_table[kchanid].size - channels_table[kchanid].len; if (empty == 0) { + if (channels_table[chanid].nb_users <= 1) { + errno = EALONE; + return -1; + } // Blocks the waiter. channels_table[kchanid].sender = waiter; s->processes[waiter].state = BLOCKEDWRITING; @@ -211,6 +235,10 @@ ssize_t wait_channel(state *s) { // Looks for some data. size_t len = channels_table[kchanid].len; if (len == 0) { + if (channels_table[chanid].nb_users <= 1) { + errno = EALONE; + return -1; + } // Blocks the waiter. channels_table[kchanid].receiver = waiter; s->processes[waiter].state = BLOCKEDREADING; diff --git a/sources/channel.h b/sources/channel.h index e1d485b..34b5a0a 100644 --- a/sources/channel.h +++ b/sources/channel.h @@ -16,13 +16,15 @@ typedef struct { size_t write; pid_t sender; pid_t receiver; + int nb_users; } channel_t; int new_channel(channel_state_t *channels); ssize_t send(state *s); ssize_t receive(state *s); -int free_channel(int chanid, channel_state_t *channels); +int free_channel(state *s, int chanid, channel_state_t *channels); ssize_t wait_channel(state *s); +channel_t channels_table[NB_MAX_CHANNELS]; #endif /* CHANNEL_H */ diff --git a/sources/error.c b/sources/error.c index f0a548a..1abee90 100644 --- a/sources/error.c +++ b/sources/error.c @@ -51,7 +51,7 @@ void init_error_msg() { error_msg[43] = "Message too long"; error_msg[44] = "Too many processes"; error_msg[45] = "Too many streams"; - error_msg[46] = "Protocol not supported"; + error_msg[46] = "Alone on this channel"; error_msg[47] = "Socket type not supported"; error_msg[48] = "Operation not supported on socket"; error_msg[49] = "Protocol family not supported"; diff --git a/sources/error.h b/sources/error.h index 5dd44e2..7e0e763 100644 --- a/sources/error.h +++ b/sources/error.h @@ -55,7 +55,7 @@ typedef enum { EMSGSIZE, //Message too long EMPROC, //Too many processes EMSTREAM, //Too many streams - EPROTONOSUPPORT, //Protocol not supported + EALONE, //Alone on this channel ESOCKTNOSUPPORT, //Socket type not supported EOPNOTSUPP, //Operation not supported on socket EPFNOSUPPORT, //Protocol family not supported diff --git a/sources/kernel.c b/sources/kernel.c index 1769296..a436cee 100644 --- a/sources/kernel.c +++ b/sources/kernel.c @@ -150,9 +150,14 @@ int start_process(int parent, char* file, char *args, int chin, int chout) { p->channels[0].chanid = chin; p->channels[0].write = 0; p->channels[0].read = 1; + if (chin != -1) + channels_table[chin].nb_users += 1; p->channels[1].chanid = chout; p->channels[1].write = 1; p->channels[1].read = 0; + if (chout != -1) + channels_table[chout].nb_users += 1; + p->cwd = opendir(CUR_DIR_NAME); if (strlen(file) >= 255) file[255] = 0; @@ -191,10 +196,15 @@ void kill_process(pid_t pid) { regs->ecx = s->ctx->regs.ebx; } - //On enlève le processus de sa file + //Removes the process from its runqueue. s->runqueues[MAX_PRIORITY] = filter(s->runqueues[MAX_PRIORITY], pid); //TODO priority? + //Closes the channels of the process. + for (int i = 0; i < NUM_CHANNELS_PROC; i++) { + free_channel(s, i, s->processes[pid].channels); + } close(s->processes[pid].cwd); + // TODO Files property -> close opened files ? } int _exit(state *s) { @@ -238,7 +248,7 @@ int _new_channel(state *s) { } int _free_channel(state *s) { - int res = free_channel(s->ctx->regs.ebx, s->processes[s->curr_pid].channels); + int res = free_channel(s, s->ctx->regs.ebx, s->processes[s->curr_pid].channels); s->ctx->regs.eax = res; s->ctx->regs.ebx = errno; return 0; // No reorder diff --git a/sources/timer.c b/sources/timer.c index 7e78d8c..c5dc346 100644 --- a/sources/timer.c +++ b/sources/timer.c @@ -110,6 +110,7 @@ void update_time() { while (t->minutes >= 60) { t->minutes -= 60; t->hours ++; + reset_time(); } if (t->hours >= 24) { reset_time();