summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-10-29 14:06:33 +0800
committerLAN-TW <lantw44@gmail.com>2013-10-29 14:06:33 +0800
commit20fc705be54802af5d0fe344e9bfba6d66db8d4f (patch)
tree5d1fd4bb703de18d62fdc388406fb5b1aeb5b45e
parent0c74adcd15ac2988a6c3246ece07fe823386bdbb (diff)
downloadcn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.tar.gz
cn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.tar.zst
cn2013-20fc705be54802af5d0fe344e9bfba6d66db8d4f.zip
HW1: 加入關於 RasShell 的基本架構,但目前仍無法運作
-rw-r--r--hw1/shell.c131
-rw-r--r--hw1/xwrap.c15
-rw-r--r--hw1/xwrap.h1
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;