summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-10-22 14:08:32 +0800
committerLAN-TW <lantw44@gmail.com>2013-10-22 14:08:32 +0800
commit5b0ecafc3d5f8312755ae59057e6de413516098f (patch)
treeab28cc9d83d885b549106aaf4ad909cec1cf06d3
parentd2fc67d8dc6095918830d509cd300b7a9d1ed170 (diff)
downloadcn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.tar.gz
cn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.tar.zst
cn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.zip
HW1: 加入 RasSession 基本架構、修正 xsprintf 的 segfault 問題
-rw-r--r--hw1/Makefile.am2
-rw-r--r--hw1/connection.c18
-rw-r--r--hw1/connection.h2
-rw-r--r--hw1/server-main.c42
-rw-r--r--hw1/server.c2
-rw-r--r--hw1/server.h4
-rw-r--r--hw1/session.c45
-rw-r--r--hw1/session.h29
-rw-r--r--hw1/xwrap.c6
9 files changed, 126 insertions, 24 deletions
diff --git a/hw1/Makefile.am b/hw1/Makefile.am
index 341913d..b314c9b 100644
--- a/hw1/Makefile.am
+++ b/hw1/Makefile.am
@@ -3,5 +3,5 @@ bin_PROGRAMS = ras-server
noinst_LIBRARIES = libbasic.a libras.a
libbasic_a_SOURCES = xwrap.c xwrap.h basic-list.c basic-list.h
libras_a_SOURCES = socktool.c socktool.h connection.c connection.h
-ras_server_SOURCES = server-main.c server.c server.h
+ras_server_SOURCES = server-main.c server.c server.h session.c session.h
ras_server_LDADD = $(top_builddir)/libbasic.a $(top_builddir)/libras.a
diff --git a/hw1/connection.c b/hw1/connection.c
index 4a1fd1f..77281af 100644
--- a/hw1/connection.c
+++ b/hw1/connection.c
@@ -18,7 +18,7 @@
int ras_conn_init (
RasConn* conn, RasConnPerm perm, int domain,
- const char* name, const char* log_file, int* id) {
+ const char* name, const char* log_file, int id) {
if (log_file == NULL || strcmp (log_file, "stderr") == 0) {
conn->log = stderr;
@@ -47,21 +47,24 @@ int ras_conn_init (
}
char* dir_sep_loc = strrchr (name, '/');
+ char* id_to_str;
if (dir_sep_loc != NULL) {
name = dir_sep_loc + 1;
}
conn->domain = domain;
conn->perm = perm;
- conn->id = (*id)++;
+ conn->id = id;
conn->pid = getpid ();
- conn->name = xstrcat (name, "-",
+ conn->name = xsprintf ("%s-%d (%s-%s) [%d]",
+ name, conn->id,
domain == AF_LOCAL ? "unix" :
domain == AF_INET ? "ipv4" :
- domain == AF_INET6 ? "ipv6" : "unknown", "-",
+ domain == AF_INET6 ? "ipv6" : "unknown",
perm == RAS_CONN_PERM_RESTRICTED ? "restricted" :
perm == RAS_CONN_PERM_REGULAR ? "regular" :
- perm == RAS_CONN_PERM_ADMIN ? "admin" : "unknown", NULL);
+ perm == RAS_CONN_PERM_ADMIN ? "admin" : "unknown",
+ conn->pid);
conn->fd_is_set = false;
return 0;
@@ -69,7 +72,6 @@ int ras_conn_init (
void ras_conn_destroy (RasConn* conn) {
if (conn->fd_is_set) {
- shutdown (conn->fd, SHUT_RDWR);
close (conn->fd);
}
if (conn->log_is_set) {
@@ -97,10 +99,10 @@ void ras_conn_log (RasConn* conn, const char* format, ...) {
fcntl (conn->log_fd, F_SETLKW, &lock_info);
fprintf (conn->log,
- "%04d-%02d-%02d %02d:%02d:%02d %s[%u]: ",
+ "%04d-%02d-%02d %02d:%02d:%02d %s: ",
tmd.tm_year + 1900, tmd.tm_mon + 1, tmd.tm_mday,
tmd.tm_hour, tmd.tm_min, tmd.tm_sec,
- conn->name, conn->pid);
+ conn->name);
vfprintf (conn->log, format, ap);
putc ('\n', conn->log);
diff --git a/hw1/connection.h b/hw1/connection.h
index 9a4cfe7..6ad4442 100644
--- a/hw1/connection.h
+++ b/hw1/connection.h
@@ -27,7 +27,7 @@ typedef struct {
} RasConn;
int ras_conn_init (RasConn* conn, RasConnPerm perm, int domain,
- const char* name, const char* log_file, int* id);
+ const char* name, const char* log_file, int id);
void ras_conn_destroy (RasConn* conn);
void ras_conn_log (RasConn* conn, const char* format, ...);
diff --git a/hw1/server-main.c b/hw1/server-main.c
index dbb08bd..89c2576 100644
--- a/hw1/server-main.c
+++ b/hw1/server-main.c
@@ -3,6 +3,7 @@
#endif
#include "server.h"
+#include "session.h"
#include "socktool.h"
#include "basic-list.h"
@@ -72,32 +73,32 @@ int main (int argc, char* argv[]) {
};
sigemptyset (&action.sa_mask);
sigaction (SIGPIPE, &action, NULL);
+ action.sa_handler = cleanup_child;
+ sigaction (SIGCHLD, &action, NULL);
action.sa_handler = quit_request_setter;
sigaction (SIGINT, &action, NULL);
sigaction (SIGQUIT, &action, NULL);
sigaction (SIGTERM, &action, NULL);
- action.sa_handler = cleanup_child;
- sigaction (SIGCHLD, &action, NULL);
List* svrlist = list_create ();
int sid = 0, cid = 0;
RasServer svr;
- ras_server_init (&svr, RAS_CONN_PERM_ADMIN, AF_LOCAL, NULL, &sid);
+ ras_server_init (&svr, RAS_CONN_PERM_ADMIN, AF_LOCAL, NULL, sid), sid++;
if (ras_server_listen (&svr, "/tmp/ras-server.sock", 0600) < 0) {
return 1;
} else {
list_pushback (svrlist, &svr, sizeof (RasServer));
}
- ras_server_init (&svr, RAS_CONN_PERM_RESTRICTED, AF_INET, NULL, &sid);
+ ras_server_init (&svr, RAS_CONN_PERM_RESTRICTED, AF_INET, NULL, sid), sid++;
if (ras_server_listen (&svr, NULL, atoi (argv[1])) < 0) {
return 1;
} else {
list_pushback (svrlist, &svr, sizeof (RasServer));
}
- ras_server_init (&svr, RAS_CONN_PERM_RESTRICTED, AF_INET6, NULL, &sid);
+ ras_server_init (&svr, RAS_CONN_PERM_RESTRICTED, AF_INET6, NULL, sid), sid++;
if (ras_server_listen (&svr, NULL, atoi (argv[1])) < 0) {
return 1;
} else {
@@ -127,6 +128,7 @@ int main (int argc, char* argv[]) {
continue;
}
+ RasSession session;
int session_fd;
char* peername;
pid_t cpid;
@@ -137,27 +139,49 @@ int main (int argc, char* argv[]) {
}
peername = ras_socktool_get_peername (session_fd);
- cid++;
ras_server_log (server,
"client %d from %s is accepted", cid, peername);
free (peername);
cpid = fork ();
+
if (cpid < 0) {
ras_server_log (server,
"client %d cannot continue: fork error: %s",
cid, strerror (errno));
- shutdown (session_fd, SHUT_RDWR);
close (session_fd);
ras_server_log (server,
"client %d connection closed", cid);
continue;
} else if (cpid > 0) {
- /* parent process */
+ /* parent process: just close the accepted fd */
ras_server_log (server,
"client %d is handled by process %u now", cid, cpid);
+ cid++;
+ close (session_fd);
} else {
- /* child process */
+ /* child process: we need to reset signal handlers */
+ struct sigaction session_action = {
+ .sa_handler = SIG_DFL,
+ .sa_flags = 0
+ };
+ sigemptyset (&session_action.sa_mask);
+ sigaction (SIGINT, &action, NULL);
+ sigaction (SIGQUIT, &action, NULL);
+ sigaction (SIGTERM, &action, NULL);
+ if (ras_session_init (&session, server, session_fd, cid) < 0) {
+ ras_session_destroy (&session);
+ exit (1);
+ }
+ if (ras_session_read_header (&session) < 0) {
+ ras_session_destroy (&session);
+ exit (1);
+ }
+ if (ras_session_start_shell (&session) < 0) {
+ ras_session_destroy (&session);
+ exit (1);
+ }
+ ras_session_destroy (&session);
exit (0);
}
}
diff --git a/hw1/server.c b/hw1/server.c
index 983e49e..3794847 100644
--- a/hw1/server.c
+++ b/hw1/server.c
@@ -20,7 +20,7 @@
int ras_server_init (
RasServer* server, RasConnPerm perm, int domain,
- const char* log_file, int* id) {
+ const char* log_file, int id) {
/* chain up to parent constructor */
int rval =
diff --git a/hw1/server.h b/hw1/server.h
index cdbcf6e..c070c80 100644
--- a/hw1/server.h
+++ b/hw1/server.h
@@ -14,11 +14,11 @@ typedef struct {
} RasServer;
int ras_server_init (RasServer* server, RasConnPerm perm, int domain,
- const char* log_file, int* id);
+ const char* log_file, int id);
void ras_server_destroy (RasServer* server);
int ras_server_listen (RasServer* server, const char* addr, int arg);
/* Access parent methods */
-#define ras_server_log(server, ...) ras_conn_log(RAS_CONN(server), __VA_ARGS__)
+#define ras_server_log(x, ...) ras_conn_log(RAS_CONN(x), __VA_ARGS__)
#endif /* RAS_SERVER_H */
diff --git a/hw1/session.c b/hw1/session.c
new file mode 100644
index 0000000..33b5d39
--- /dev/null
+++ b/hw1/session.c
@@ -0,0 +1,45 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "session.h"
+
+#include "server.h"
+#include "connection.h"
+
+#include <stdbool.h>
+
+int ras_session_init (RasSession* session, RasServer* server, int fd, int id) {
+ /* chain up to parent constructor */
+ int rval = ras_conn_init (
+ RAS_CONN (session),
+ RAS_CONN (server)->perm,
+ RAS_CONN (server)->domain,
+ "ras-session",
+ RAS_CONN (server)->log_file,
+ id);
+
+ if (rval < 0) {
+ return rval;
+ }
+
+ RAS_CONN (session)->fd = fd;
+ RAS_CONN (session)->fd_is_set = true;
+
+ ras_session_log (session, "session started");
+
+ return 0;
+}
+
+void ras_session_destroy (RasSession* session) {
+ ras_session_log (session, "session closed");
+
+ /* chain up to parent destructor */
+ ras_conn_destroy (RAS_CONN (session));
+}
+
+int ras_session_read_header (RasSession* session) {
+}
+
+int ras_session_start_shell (RasSession* session) {
+}
diff --git a/hw1/session.h b/hw1/session.h
new file mode 100644
index 0000000..3ceeba8
--- /dev/null
+++ b/hw1/session.h
@@ -0,0 +1,29 @@
+#ifndef RAS_SESSION_H
+#define RAS_SESSION_H
+
+#include "connection.h"
+#include "server.h"
+
+#include <sys/types.h>
+
+#define RAS_SESSION(x) ((RasSession*)(x))
+#define RAS_SESSION_BUFFER_SIZE 8192
+
+typedef struct {
+ RasConn conn;
+ pid_t shell_pid;
+ int shell_stdio;
+ char buf[RAS_SESSION_BUFFER_SIZE];
+ int buf_start;
+ int buf_len;
+} RasSession;
+
+int ras_session_init (RasSession* sesssion, RasServer* server, int fd, int cid);
+void ras_session_destroy (RasSession* session);
+int ras_session_read_header (RasSession* session);
+int ras_session_start_shell (RasSession* session);
+
+/* Access parent methods */
+#define ras_session_log(x, ...) ras_conn_log(RAS_CONN(x), __VA_ARGS__)
+
+#endif /* RAS_SESSION_H */
diff --git a/hw1/xwrap.c b/hw1/xwrap.c
index c77a744..3d56000 100644
--- a/hw1/xwrap.c
+++ b/hw1/xwrap.c
@@ -71,11 +71,13 @@ char* xsprintf (const char* format, ...) {
int len;
va_start (ap, format);
-
len = vsnprintf (NULL, 0, format, ap) + 1;
+ va_end (ap);
+
newstr = xmalloc (len);
- vsnprintf (newstr, len, format, ap);
+ va_start (ap, format);
+ vsnprintf (newstr, len, format, ap);
va_end (ap);
return newstr;