summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-11-08 17:31:35 +0800
committerb01902062 <b01902062@linux5.csie.ntu.edu.tw>2013-11-08 17:32:08 +0800
commit328e88167e396b8d72e88019c67b7391ad7f601a (patch)
tree9884301d4e23630c5fc7e8098f508a228ac134bd
parentd3160db062ac5ed2106b317ade5e6ccf4afcd958 (diff)
downloadcn2013-328e88167e396b8d72e88019c67b7391ad7f601a.tar.gz
cn2013-328e88167e396b8d72e88019c67b7391ad7f601a.tar.zst
cn2013-328e88167e396b8d72e88019c67b7391ad7f601a.zip
HW1: 支援寫入 TA pipe 檔案,並修正 parse command memory leak
-rw-r--r--hw1/shell-builtin.c13
-rw-r--r--hw1/shell-builtin.h1
-rw-r--r--hw1/shell.c84
-rw-r--r--hw1/shell.h6
4 files changed, 93 insertions, 11 deletions
diff --git a/hw1/shell-builtin.c b/hw1/shell-builtin.c
index 599f2c2..7d5abb0 100644
--- a/hw1/shell-builtin.c
+++ b/hw1/shell-builtin.c
@@ -7,6 +7,7 @@
#include "xwrap.h"
#include <errno.h>
+#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,6 +26,7 @@ const RasShellBuiltin ras_shell_builtins[] = {
RAS_SHELL_BUILTIN_ENTRY (set),
RAS_SHELL_BUILTIN_ENTRY (setenv),
RAS_SHELL_BUILTIN_ENTRY (shopt),
+ RAS_SHELL_BUILTIN_ENTRY (tapipe),
RAS_SHELL_BUILTIN_ENTRY (umask),
RAS_SHELL_BUILTIN_ENTRY (unset),
RAS_SHELL_BUILTIN_ENTRY (unsetenv),
@@ -215,6 +217,17 @@ int ras_shell_builtin_umask (int argc, char* argv[], RasShell* shell) {
return 0;
}
+int ras_shell_builtin_tapipe (int argc, char* argv[], RasShell* shell) {
+ ListNode* iter = list_node_front (shell->saved_list);
+ for (; iter != NULL; iter = list_next (iter)) {
+ RasShellSaved* saved = list_data (iter);
+ printf ("Command %" PRIu64 " input == "
+ "Command %" PRIu64 " output (%s)\n",
+ saved->to, saved->from, saved->cmdorg);
+ }
+ return 0;
+}
+
int ras_shell_builtin_unset (int argc, char* argv[], RasShell* shell) {
fputs ("This command has not been implemented. Try `unsetenv\'.\n", stderr);
return 1;
diff --git a/hw1/shell-builtin.h b/hw1/shell-builtin.h
index f965359..8fb1a77 100644
--- a/hw1/shell-builtin.h
+++ b/hw1/shell-builtin.h
@@ -26,6 +26,7 @@ RAS_SHELL_BUILTIN_DECL (pwd);
RAS_SHELL_BUILTIN_DECL (set);
RAS_SHELL_BUILTIN_DECL (setenv);
RAS_SHELL_BUILTIN_DECL (shopt);
+RAS_SHELL_BUILTIN_DECL (tapipe);
RAS_SHELL_BUILTIN_DECL (umask);
RAS_SHELL_BUILTIN_DECL (unset);
RAS_SHELL_BUILTIN_DECL (unsetenv);
diff --git a/hw1/shell.c b/hw1/shell.c
index f9728c4..d5791ba 100644
--- a/hw1/shell.c
+++ b/hw1/shell.c
@@ -37,12 +37,6 @@
#define STR(x) ((char*)(x))
typedef struct {
- uint64_t count;
- char* reason;
- char file[];
-} RasShellSaved;
-
-typedef struct {
Array* arg; /* NULL-terminated string array */
Array* redir_stdin; /* string */
Array* redir_stdout; /* string */
@@ -103,6 +97,7 @@ static void complete_string (Array*** ws, int* append,
*ws[*append] = array_create (sizeof (char), 0);
}
}
+ printf ("%d\n", *append);
*append = APPEND_STR;
}
@@ -207,6 +202,10 @@ static int ras_shell_cmd_parse (
}
}
+ if (append != APPEND_STR) {
+ array_free (str);
+ }
+
complete_component (ws, &append, &comp, cmd, allow_empty, false);
return 0;
@@ -239,7 +238,50 @@ static void ras_shell_cmd_print (RasShellCmd* cmd) {
}
}
-static int ras_shell_cmd_run (RasShellCmd* cmd, RasShell* shell) {
+static int ras_shell_cmd_save (
+ RasShellCmd* cmd, RasShell* shell, const char* cmdstr, int num) {
+
+ char* outfile = xsprintf ("%s/%" PRIu64, shell->saved_tmpdir, shell->count);
+ int outfd = open (outfile, O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+ if (outfd < 0 && errno == ENOENT) {
+ mkdir (shell->saved_tmpdir, S_IRWXU);
+ outfd = open (outfile, O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ }
+
+ if (outfd < 0) {
+ free (outfile);
+ return outfd;
+ }
+
+ free (outfile);
+
+ RasShellSaved saved = {
+ .from = shell->count,
+ .to = shell->count + num,
+ .cmdorg = xstrdup (cmdstr)
+ };
+ bool inserted = false;
+ ListNode* iter = list_node_front (shell->saved_list);
+
+ for (; iter != NULL; iter = list_next (iter)) {
+ if (RAS_SHELL_SAVED (list_data (iter))->to > saved.to) {
+ list_insert_prev (shell->saved_list, iter, &saved, sizeof (saved));
+ inserted = true;
+ }
+ }
+
+ if (!inserted) {
+ list_pushback (shell->saved_list, &saved, sizeof (saved));
+ }
+
+ return outfd;
+}
+
+static int ras_shell_cmd_run (
+ RasShellCmd* cmd, RasShell* shell, const char* cmdstr) {
ListNode* iter = list_node_front (cmd->argrp);
pid_t child;
@@ -291,13 +333,17 @@ static int ras_shell_cmd_run (RasShellCmd* cmd, RasShell* shell) {
}
if (array_getlen (comp->tapipe)) {
int tpnum;
- sscanf (STR (array_data (comp->tapipe)) + 1, "%d", &tpnum);
- if (tpnum < 1) {
+ if (sscanf (STR (array_data (comp->tapipe)), "%d", &tpnum) < 1) {
fprintf (stderr, "%s: invalid TA pipe number `%s\'\n",
shell->name, STR (array_data (comp->tapipe)));
break;
}
- // TODO: TA pipe handling
+ outfile = ras_shell_cmd_save (cmd, shell, cmdstr, tpnum);
+ if (outfile < 0) {
+ fprintf (stderr, "%s: cannot setup TA pipe: %s\n",
+ shell->name, strerror (errno));
+ break;
+ }
}
}
@@ -360,6 +406,18 @@ static int ras_shell_cmd_run (RasShellCmd* cmd, RasShell* shell) {
} else {
/* child */
+ struct sigaction sa = {
+ .sa_handler = SIG_DFL,
+ .sa_flags = 0
+ };
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGINT, &sa, NULL);
+ sigaction (SIGQUIT, &sa, NULL);
+ sigaction (SIGTSTP, &sa, NULL);
+ sigaction (SIGTTOU, &sa, NULL);
+ sigaction (SIGPIPE, &sa, NULL);
+ sigaction (SIGHUP, &sa, NULL);
+
pid_t pid = getpid ();
if (cmd->pgid == 0) {
cmd->pgid = pid;
@@ -555,6 +613,10 @@ static int ras_shell_init (RasShell* shell, int argc, char* argv[]) {
}
static void ras_shell_destroy (RasShell* shell) {
+ ListNode* iter = list_node_front (shell->saved_list);
+ for (; iter != NULL; iter = list_next (iter)) {
+ free (RAS_SHELL_SAVED (list_data (iter))->cmdorg);
+ }
list_free (shell->saved_list);
free (shell->saved_tmpdir);
free (shell->user_name);
@@ -641,7 +703,7 @@ int ras_shell_main (int argc, char* argv[]) {
ras_shell_cmd_print (&cmd);
}
- shell.last_rval = ras_shell_cmd_run (&cmd, &shell);
+ shell.last_rval = ras_shell_cmd_run (&cmd, &shell, array_data (cmdstr));
array_free (cmdstr);
ras_shell_cmd_destroy (&cmd);
diff --git a/hw1/shell.h b/hw1/shell.h
index 4b9e343..5e5142c 100644
--- a/hw1/shell.h
+++ b/hw1/shell.h
@@ -28,6 +28,12 @@ typedef struct {
struct termios tmode; /* shell terminal mode */
} RasShell;
+typedef struct {
+ uint64_t from;
+ uint64_t to;
+ char* cmdorg;
+} RasShellSaved;
+
typedef int (*RasShellFunc) (int argc, char* argv[], RasShell* shell);
typedef char* (*RasShellRead) (void* data);