diff options
author | LAN-TW <lantw44@gmail.com> | 2013-10-29 14:06:33 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-10-29 14:06:33 +0800 |
commit | 20fc705be54802af5d0fe344e9bfba6d66db8d4f (patch) | |
tree | 5d1fd4bb703de18d62fdc388406fb5b1aeb5b45e | |
parent | 0c74adcd15ac2988a6c3246ece07fe823386bdbb (diff) | |
download | cn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.tar.gz cn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.tar.zst cn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.zip |
HW1: 加入關於 RasShell 的基本架構,但目前仍無法運作
-rw-r--r-- | hw1/shell.c | 131 | ||||
-rw-r--r-- | hw1/xwrap.c | 15 | ||||
-rw-r--r-- | hw1/xwrap.h | 1 |
3 files changed, 143 insertions, 4 deletions
diff --git a/hw1/shell.c b/hw1/shell.c index c21669b..bf8c50e 100644 --- a/hw1/shell.c +++ b/hw1/shell.c @@ -9,26 +9,112 @@ #include <errno.h> #include <inttypes.h> #include <locale.h> +#include <pwd.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <string.h> +#include <sys/types.h> #include <time.h> #include <unistd.h> +#define RAS_SHELL_BUILTIN(x) ((RasShellBuiltin*)(x)) +#define RAS_SHELL_SAVED(x) ((RasShellSaved*)(x)) +#define RAS_SHELL_CMD_COMP(x) ((RasShellCmdComp*)(x)) +#define RAS_SHELL_CMD(x) ((RasShellCmd*)(x)) +#define RAS_SHELL(x) ((RasShell*)(x)) +#define STRV(x) ((char**)(x)) +#define STR(x) ((char*)(x)) + +typedef int (*RasShellFunc) (char* argv[]); +typedef char* (*RasShellReadline) (void* data); + +typedef struct { + char* cmd; + RasShellFunc func; +} RasShellBuiltin; + +typedef struct { + uint64_t count; + char* reason; + char file[]; +} RasShellSaved; + +typedef struct { + Array* arg; + char* redir_stdin; + char* redir_stdout; + char* redir_stderr; +} RasShellCmdComp; + +typedef struct { + List* argrp; /* A List of RasShellCmdComp */ + int save_output : 1; +} RasShellCmd; + typedef struct { char* name; /* This is argv[0]. Do not modify or free it. */ uint64_t count; - List* saved_list; + List* saved_list; /* A list of RasShellSaved */ char* saved_tmpdir; + int last_rval; int attr_login : 1; /* login shell */ int attr_rshell : 1; /* restricted shell */ + char* user_name; + char user_ps; + int req_exit : 1; /* request for exit */ + int req_exit_status; /* requested exit status */ } RasShell; -int ras_shell_init (RasShell* shell, int argc, char* argv[]) { +static char* ras_shell_cmd_read (void* data) { + Array* cmdstr = array_readline (); + char* cmd; + + if (cmdstr == NULL) { + return NULL; + } + + cmd = array_drop_struct (cmdstr); + return cmd; +} + +static int ras_shell_cmd_parse ( + RasShellCmd* cmd, const char* cmdstr, RasShellReadline read_cb, void* data) { + + +} + +static int ras_shell_cmd_run (RasShellCmd* cmd, RasShell* shell) { +} + +static void ras_shell_cmd_destroy (RasShellCmd* cmd) { + if (cmd == NULL) { + return; + } + + ListNode* iter; + for (iter = list_node_front (cmd->argrp); iter != NULL; iter = list_next (iter)) { + if (list_data (iter) == NULL) { + continue; + } + RasShellCmdComp* comp = RAS_SHELL_CMD_COMP (list_data (iter)); + free (comp->redir_stdin); + free (comp->redir_stdout); + free (comp->redir_stderr); + for (int i = 0; i < array_getlen (comp->arg); i++) { + free (STRV (array_data (comp->arg))[i]); + } + array_free (comp->arg); + } +} + +static int ras_shell_init (RasShell* shell, int argc, char* argv[]) { + shell->last_rval = 0; shell->attr_login = argv[0][0] == '-'; shell->attr_rshell = false; + shell->req_exit = false; + shell->req_exit_status = 0; for (int i = 1; i < argc; i++) { if (argv[i][0] != '-') { @@ -73,10 +159,14 @@ int ras_shell_init (RasShell* shell, int argc, char* argv[]) { shell->saved_list = list_create (); shell->saved_tmpdir = tmpdir; + struct passwd* pwname = getpwuid (getuid ()); + shell->user_name = pwname == NULL ? NULL : xstrdup (pwname->pw_name); + shell->user_ps = geteuid () ? '$' : '#'; + return 0; } -void ras_shell_destroy (RasShell* shell) { +static void ras_shell_destroy (RasShell* shell) { list_free (shell->saved_list); free (shell->saved_tmpdir); } @@ -109,7 +199,40 @@ int ras_shell_main (int argc, char* argv[]) { puts ("Note: This is a restricted shell. Some command may be disabled."); } + for (; !shell.req_exit; shell.count++) { + char* user = shell.user_name == NULL ? "I have no name!" : shell.user_name; + char* cwd = xgetcwd (); + + printf ("%" PRIu64 ":%s[%s]%c ", shell.count, user, cwd, shell.user_ps); + fflush (stdout); + free (cwd); + + Array* cmdstr = NULL; + RasShellCmd cmd; + + cmdstr = array_readline (); + if (cmdstr == NULL) { + shell.req_exit = true; + shell.req_exit_status = 0; + continue; + } + + if (ras_shell_cmd_parse ( + &cmd, array_data (cmdstr), ras_shell_cmd_read, NULL) < 0) { + fprintf (stderr, "%s: cannot parse command `%s\'\n", + shell.name, STR (array_data (cmdstr))); + array_free (cmdstr); + continue; + } + + shell.last_rval = ras_shell_cmd_run (&cmd, &shell); + + array_free (cmdstr); + ras_shell_cmd_destroy (&cmd); + } + + int exit_status = shell.req_exit_status; ras_shell_destroy (&shell); - return 0; + return exit_status; } diff --git a/hw1/xwrap.c b/hw1/xwrap.c index 4999ec7..4659751 100644 --- a/hw1/xwrap.c +++ b/hw1/xwrap.c @@ -93,3 +93,18 @@ char* xsprintf (const char* format, ...) { return newstr; } + +char* xgetcwd (void) { + char *cwd, *result; + size_t size = pathconf (".", _PC_PATH_MAX); + + size = size > 0 ? size : 256; + cwd = xmalloc (sizeof (char) * size); + + while ((result = getcwd (cwd, size)) == NULL) { + size *= 2; + cwd = xrealloc (cwd, size); + } + + return cwd; +} diff --git a/hw1/xwrap.h b/hw1/xwrap.h index 5a0e0f6..d96871d 100644 --- a/hw1/xwrap.h +++ b/hw1/xwrap.h @@ -10,6 +10,7 @@ void* xrealloc (void* ptr, size_t size); char* xstrcat (const char* str, ...); char* xstrdup (const char* str); char* xsprintf (const char* format, ...); +char* xgetcwd (void); static inline int xmax (int a, int b) { return a > b ? a : b; |