diff options
author | LAN-TW <lantw44@gmail.com> | 2013-10-24 01:35:50 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-10-24 01:35:50 +0800 |
commit | b6bf030497fb7814c5549b02540198c76ab9c98b (patch) | |
tree | 61e8b963f70fe9d891da5cb0742bdacd678e1bda | |
parent | 246435b6ac1acd202eb6a3eff10cfc5a43a0781b (diff) | |
download | cn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.tar.gz cn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.tar.zst cn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.zip |
HW1: 初始化 RasShell 和簡單的命令列解析
-rw-r--r-- | hw1/configure.ac | 7 | ||||
-rw-r--r-- | hw1/connection.c | 10 | ||||
-rw-r--r-- | hw1/connection.h | 1 | ||||
-rw-r--r-- | hw1/session.c | 21 | ||||
-rw-r--r-- | hw1/shell.c | 106 |
5 files changed, 135 insertions, 10 deletions
diff --git a/hw1/configure.ac b/hw1/configure.ac index 40a8113..e37e45c 100644 --- a/hw1/configure.ac +++ b/hw1/configure.ac @@ -32,5 +32,12 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([setgroups initgroups getdtablesize]) +# Misc options. +AC_ARG_WITH([motd], + [AS_HELP_STRING([--with-motd=FILE], + [Set FILE as default message of the day @<:@default=/etc/motd@:>@])], + [with_motd="$withval"], [with_motd="/etc/motd"]) +AC_DEFINE_UNQUOTED([ETC_MOTD], ["$with_motd"], [Message of the day]) + AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/hw1/connection.c b/hw1/connection.c index b7bd650..4ca17b2 100644 --- a/hw1/connection.c +++ b/hw1/connection.c @@ -54,16 +54,14 @@ int ras_conn_init ( conn->domain = domain; conn->perm = perm; conn->id = id; - conn->pid = getpid (); - conn->name = xsprintf ("%s-%d (%s-%s) [%d]", + conn->name = xsprintf ("%s-%d (%s-%s)", name, conn->id, domain == AF_LOCAL ? "unix" : domain == AF_INET ? "ipv4" : domain == AF_INET6 ? "ipv6" : "unknown", perm == RAS_CONN_PERM_RESTRICTED ? "restricted" : perm == RAS_CONN_PERM_REGULAR ? "regular" : - perm == RAS_CONN_PERM_ADMIN ? "admin" : "unknown", - conn->pid); + perm == RAS_CONN_PERM_ADMIN ? "admin" : "unknown"); conn->fd_is_set = false; return 0; @@ -98,10 +96,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: ", + "%04d-%02d-%02d %02d:%02d:%02d %s [%d]: ", tmd.tm_year + 1900, tmd.tm_mon + 1, tmd.tm_mday, tmd.tm_hour, tmd.tm_min, tmd.tm_sec, - conn->name); + conn->name, getpid ()); vfprintf (conn->log, format, ap); putc ('\n', conn->log); diff --git a/hw1/connection.h b/hw1/connection.h index 6ad4442..015619b 100644 --- a/hw1/connection.h +++ b/hw1/connection.h @@ -18,7 +18,6 @@ typedef struct { int id; int fd; int fd_is_set : 1; - pid_t pid; char* name; FILE* log; char* log_file; diff --git a/hw1/session.c b/hw1/session.c index b8e122e..4c4db13 100644 --- a/hw1/session.c +++ b/hw1/session.c @@ -222,6 +222,8 @@ int ras_session_start_shell (RasSession* session) { const int noshell_len = STATIC_STRLEN (noshell_msg); const char nopty_msg[] = "Error: Cannot allocate a pseudo-tty.\n"; const int nopty_len = STATIC_STRLEN (nopty_msg); + const char nosid_msg[] = "Error: Cannot start a new session.\n"; + const int nosid_len = STATIC_STRLEN (nosid_msg); int sockpair[2]; /* parent = 0, child = 1 */ char* slave_dev = NULL; @@ -258,6 +260,7 @@ int ras_session_start_shell (RasSession* session) { close (session->shell_stdio); return -1; } + ras_session_log (session, "new pseudo-tty is %s", slave_dev); } else { if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sockpair) < 0) { write (RAS_CONN (session)->fd, noshell_msg, noshell_len); @@ -289,6 +292,8 @@ int ras_session_start_shell (RasSession* session) { FD_SET (child, &rset); FD_SET (sock, &rset); + ras_session_log (session, "child started with pid %d", session->shell_pid); + while (!child_terminated) { rresult = rset; if (select (nfds, &rresult, NULL, NULL, NULL) >= 0) { @@ -320,6 +325,11 @@ int ras_session_start_shell (RasSession* session) { /* child process */ int child_stdio; + if (setsid () < 0) { + write (RAS_CONN (session)->fd, nosid_msg, nosid_len); + ras_session_log (session, "cannot setsid: %s", strerror (errno)); + } + if (slave_dev != NULL) { child_stdio = open (slave_dev, O_RDWR); if (child_stdio < 0) { @@ -338,6 +348,8 @@ int ras_session_start_shell (RasSession* session) { child_stdio = sockpair[1]; } + ras_session_log (session, "shell environment is OK, closing log file"); + ras_socktool_reset_signals (); ras_socktool_close_except (child_stdio); @@ -346,8 +358,13 @@ int ras_session_start_shell (RasSession* session) { dup2 (child_stdio, STDERR_FILENO); close (child_stdio); - char* argv[] = { "-ras-shell", NULL }; - exit (ras_shell_main (1, argv)); + if (RAS_CONN (session)->perm == RAS_CONN_PERM_RESTRICTED) { + char* argv[] = { "-ras-shell", "-r", NULL }; + exit (ras_shell_main (2, argv)); + } else { + char* argv[] = { "-ras-shell", NULL }; + exit (ras_shell_main (1, argv)); + } } return 0; diff --git a/hw1/shell.c b/hw1/shell.c index 1060054..c21669b 100644 --- a/hw1/shell.c +++ b/hw1/shell.c @@ -2,10 +2,114 @@ # include "config.h" #endif +#include "basic-array.h" +#include "basic-list.h" +#include "xwrap.h" + +#include <errno.h> +#include <inttypes.h> +#include <locale.h> +#include <signal.h> +#include <stdbool.h> +#include <stdint.h> #include <stdio.h> +#include <string.h> +#include <time.h> #include <unistd.h> +typedef struct { + char* name; /* This is argv[0]. Do not modify or free it. */ + uint64_t count; + List* saved_list; + char* saved_tmpdir; + int attr_login : 1; /* login shell */ + int attr_rshell : 1; /* restricted shell */ +} RasShell; + +int ras_shell_init (RasShell* shell, int argc, char* argv[]) { + shell->attr_login = argv[0][0] == '-'; + shell->attr_rshell = false; + + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + fprintf (stderr, "%s: %s: unknown argument\n", argv[0], argv[i]); + return -1; + } + for (int j = 1; argv[i][j] != '\0'; j++) { + switch (argv[i][j]) { + case 'r': + shell->attr_rshell = true; + break; + case 'l': + shell->attr_login = true; + break; + case 'h': + case '?': + case '-': + printf ( + "Usage: %s [-hlr]\n" + " -h View this help message\n" + " -l Make ras-shell be a login shell\n" + " -r Make ras-shell be a restricted shell\n", + argv[0]); + return -1; + break; + default: + fprintf (stderr, "%s: -%c: unknown option\n", argv[0], argv[i][j]); + return -1; + } + } + } + + char* tmpdir = xstrcat ("/tmp/", argv[0], "-XXXXXX", NULL); + if (mkdtemp (tmpdir) < 0) { + fprintf (stderr, "%s: mkdtemp: %s\n", argv[0], strerror (errno)); + free (tmpdir); + return -1; + } + + shell->name = argv[0]; + shell->count = 1; + shell->saved_list = list_create (); + shell->saved_tmpdir = tmpdir; + + return 0; +} + +void ras_shell_destroy (RasShell* shell) { + list_free (shell->saved_list); + free (shell->saved_tmpdir); +} + int ras_shell_main (int argc, char* argv[]) { - printf ("Hello World\n"); + setlocale (LC_ALL, ""); + tzset (); + + RasShell shell; + if (ras_shell_init (&shell, argc, argv) < 0) { + return 1; + } + + if (shell.attr_login) { + FILE* motd_fp; + int c; + puts ("Welcome! This is remote access system (RAS) login shell."); + motd_fp = fopen (ETC_MOTD, "r"); + if (motd_fp == NULL) { + fprintf (stderr, "%s: fail to open " ETC_MOTD ": %s", argv[0], strerror (errno)); + } else { + while ((c = getc (motd_fp)) != EOF) { + putchar (c); + } + fclose (motd_fp); + } + } + + if (shell.attr_rshell) { + puts ("Note: This is a restricted shell. Some command may be disabled."); + } + + ras_shell_destroy (&shell); + return 0; } |