diff options
author | LAN-TW <lantw44@gmail.com> | 2013-10-22 14:08:32 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-10-22 14:08:32 +0800 |
commit | 5b0ecafc3d5f8312755ae59057e6de413516098f (patch) | |
tree | ab28cc9d83d885b549106aaf4ad909cec1cf06d3 | |
parent | d2fc67d8dc6095918830d509cd300b7a9d1ed170 (diff) | |
download | cn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.tar.gz cn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.tar.zst cn2013-5b0ecafc3d5f8312755ae59057e6de413516098f.zip |
HW1: 加入 RasSession 基本架構、修正 xsprintf 的 segfault 問題
-rw-r--r-- | hw1/Makefile.am | 2 | ||||
-rw-r--r-- | hw1/connection.c | 18 | ||||
-rw-r--r-- | hw1/connection.h | 2 | ||||
-rw-r--r-- | hw1/server-main.c | 42 | ||||
-rw-r--r-- | hw1/server.c | 2 | ||||
-rw-r--r-- | hw1/server.h | 4 | ||||
-rw-r--r-- | hw1/session.c | 45 | ||||
-rw-r--r-- | hw1/session.h | 29 | ||||
-rw-r--r-- | hw1/xwrap.c | 6 |
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; |