summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-10-24 01:35:50 +0800
committerLAN-TW <lantw44@gmail.com>2013-10-24 01:35:50 +0800
commitb6bf030497fb7814c5549b02540198c76ab9c98b (patch)
tree61e8b963f70fe9d891da5cb0742bdacd678e1bda
parent246435b6ac1acd202eb6a3eff10cfc5a43a0781b (diff)
downloadcn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.tar.gz
cn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.tar.zst
cn2013-b6bf030497fb7814c5549b02540198c76ab9c98b.zip
HW1: 初始化 RasShell 和簡單的命令列解析
-rw-r--r--hw1/configure.ac7
-rw-r--r--hw1/connection.c10
-rw-r--r--hw1/connection.h1
-rw-r--r--hw1/session.c21
-rw-r--r--hw1/shell.c106
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;
}