summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-05-19 15:41:33 +0000
committerStef Walter <stef@memberwebs.com>2004-05-19 15:41:33 +0000
commite11f6612b763e48e70b88290a29e553976e88534 (patch)
treeadbe0da3032ece0170205c55b76de67bc2313c61
parent3c26bc63b98bf1c8bb8e2a55d5708b295187be50 (diff)
Support for running inside a jail
-rw-r--r--srcx/jkill.c251
1 files changed, 175 insertions, 76 deletions
diff --git a/srcx/jkill.c b/srcx/jkill.c
index 79b24bb..d3fdf53 100644
--- a/srcx/jkill.c
+++ b/srcx/jkill.c
@@ -66,31 +66,178 @@
#define DEFAULT_TIMEOUT 3
int g_timeout = DEFAULT_TIMEOUT;
-/* Supress warnings */
-int g_quiet = 0;
-int g_verbose = 0;
+int g_quiet = 0; /* Supress warnings */
+int g_verbose = 0; /* Print output from scripts */
+int g_force = 0; /* Use SIGKILL after if processes don't exit */
+int g_usescripts = 1; /* Call startup and shutdown scripts */
+int g_restart = 0; /* Restart jail after stop */
+static int kill_jail(const char* jail);
static void kill_jail_processes(kvm_t* kd, int sig);
-static int kill_jail(const char* jail, int usescripts, int restart, int force);
static int check_running_processes(kvm_t* kd);
+
+static void parse_jail_opts(int argc, char* argv[]);
+static void parse_host_opts(int argc, char* argv[]);
+
static void usage();
+static void usage_jail(const char* name);
int main(int argc, char* argv[])
{
- int ch, r, jid;
+ int r, jid;
int ret = 0;
- int restart = 0;
- int force = 0;
- int verbose = 0;
- int usescripts = 1;
pid_t child;
+ /*
+ * When running in a jail we do things slightly
+ * differently, and accept different args
+ */
+ if(running_in_jail())
+ {
+ parse_jail_opts(argc, argv);
+
+ /*
+ * Turn into a daemon, so that we don't get disconnected
+ * when we kill our parent program.
+ */
+ if(daemon(0, 1) == -1)
+ err(1, "couldn't disconnect from console");
+
+ r = kill_jail(argv[0]);
+ exit(r);
+ }
+
+ else
+ {
+ parse_host_opts(argc, argv);
+
+ argc -= optind;
+ argv += optind;
+
+ /* For each jail */
+ for(; argc > 0; argc--, argv++)
+ {
+ jid = translate_jail_name(argv[0]);
+ if(jid == -1)
+ {
+ warnx("unknown jail host name: %s", argv[0]);
+ ret = 1;
+ continue;
+ }
+
+ /*
+ * We fork and the child goes into the jail and
+ * does the dirty work. Unless in debug mode where
+ * we just do one jail.
+ */
+#ifdef _DEBUG
+ switch((child = fork()))
+ {
+ /* Error condition */
+ case -1:
+ err(1, "couldn't fork child process");
+ break;
+
+ /* The child */
+ case 0:
+#endif
+ if(jail_attach(jid) == -1)
+ err(1, "couldn't attach to jail");
+
+ r = kill_jail(argv[0]);
+ exit(r);
+#ifdef _DEBUG
+ break;
+
+ /* The parent */
+ default:
+ if(waitpid(child, &r, 0) == -1)
+ err(1, "error waiting for child process");
+
+ if(WEXITSTATUS(r) != 0)
+ ret = WEXITSTATUS(r);
+ break;
+ };
+#endif
+
+ argc--;
+ argv++;
+ }
+
+ return ret;
+ }
+}
+
+static void parse_jail_opts(int argc, char* argv[])
+{
+ char* t;
+ int ch;
+
+ t = strchr(argv[0], '/');
+ t = t ? t + 1 : argv[0];
+
+ if(strcmp(argv[0], "halt"))
+ {
+ g_verbose = 1;
+ g_force = 1;
+ g_usescripts = 1;
+ }
+
+ else if(strcmp(argv[0], "reboot"))
+ {
+ g_verbose = 1;
+ g_force = 1;
+ g_usescripts = 1;
+ g_reboot = 1;
+ }
+
+ else
+ {
+ /*
+ * When not named either of the above we fall through
+ * and process the arguments as usual.
+ */
+ parse_host_opts(argc, argv);
+ return;
+ }
+
+ while((ch = getopt(argc, argv, "dk:lnqp")) != -1)
+ {
+ switch(ch)
+ {
+ case 'd':
+ case 'k':
+ case 'l':
+ case 'n':
+ case 'q':
+ case 'p':
+ warnx("the '-%c' option is not supported from inside a jail", (char)ch);
+ break;
+
+ case '?':
+ default:
+ usage_jail(t);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if(argc > 0)
+ usage_jail(t);
+}
+
+static void parse_host_opts(int argc, char* argv[])
+{
+ int ch;
+
while((ch = getopt(argc, argv, "fhkqrt:v")) != -1)
{
switch(ch)
{
case 'f':
- force = 1;
+ g_force = 1;
break;
case 'h':
@@ -99,7 +246,7 @@ int main(int argc, char* argv[])
break;
case 'k':
- usescripts = 0;
+ g_usescripts = 0;
break;
case 'q':
@@ -108,7 +255,7 @@ int main(int argc, char* argv[])
break;
case 'r':
- restart = 1;
+ g_restart = 1;
break;
/* Timeout to use between kills */
@@ -126,72 +273,18 @@ int main(int argc, char* argv[])
case '?':
default:
usage();
+ break;
}
}
- argc -= optind;
- argv += optind;
-
- /* Make sure we have a jail id or name */
- if(argc == 0)
+ if(!g_usescripts && g_restart)
usage();
- if(!usescripts && restart)
- usage();
-
- if(running_in_jail())
- errx(1, "can't run inside jail");
-
- /* For each jail */
- for(; argc > 0; argc--, argv++)
- {
- jid = translate_jail_name(argv[0]);
- if(jid == -1)
- {
- warnx("unknown jail host name: %s", argv[0]);
- ret = 1;
- continue;
- }
-
- /*
- * We fork and the child goes into the jail and
- * does the dirty work.
- */
-#ifdef _DEBUG
- switch((child = fork()))
- {
- /* Error condition */
- case -1:
- err(1, "couldn't fork child process");
- break;
-
- /* The child */
- case 0:
-#endif
- if(jail_attach(jid) == -1)
- err(1, "couldn't attach to jail");
-
- r = kill_jail(argv[0], usescripts, restart, force);
- exit(r);
-#ifdef _DEBUG
- break;
-
- /* The parent */
- default:
- if(waitpid(child, &r, 0) == -1)
- err(1, "error waiting for child process");
-
- if(WEXITSTATUS(r) != 0)
- ret = WEXITSTATUS(r);
- break;
- };
-#endif
-
- argc--;
- argv++;
- }
+ argc -= optind;
+ argv += optind;
- return ret;
+ if(argc <= 0)
+ usage();
}
#define SHUTDOWN_SCRIPT "/etc/rc.shutdown"
@@ -200,7 +293,7 @@ static char* SHUTDOWN_ARGS[] = { _PATH_BSHELL, SHUTDOWN_SCRIPT };
#define START_SCRIPT "/etc/rc"
static char* START_ARGS[] = { _PATH_BSHELL, START_SCRIPT };
-static int kill_jail(const char* jail, int usescripts, int restart, int force)
+static int kill_jail(const char* jail)
{
kvm_t* kd = NULL;
char errbuf[_POSIX2_LINE_MAX];
@@ -239,7 +332,7 @@ static int kill_jail(const char* jail, int usescripts, int restart, int force)
case 0:
/* Check if we have an executable shutdown script */
- if(usescripts && check_jail_command(jail, SHUTDOWN_SCRIPT))
+ if(g_usescripts && check_jail_command(jail, SHUTDOWN_SCRIPT))
run_jail_command(jail, SHUTDOWN_ARGS[0], SHUTDOWN_ARGS, cmdargs);
break;
@@ -259,7 +352,7 @@ static int kill_jail(const char* jail, int usescripts, int restart, int force)
/* Okay now we force kill the processes if necessary */
case 3:
- if(force)
+ if(g_force)
{
/* If we get here, jailer looks like it's really irresponsive */
if(!g_quiet)
@@ -288,7 +381,7 @@ static int kill_jail(const char* jail, int usescripts, int restart, int force)
}
done:
- if(restart)
+ if(g_restart)
{
/* Check if we have an executable shutdown script */
if(check_jail_command(jail, START_SCRIPT))
@@ -358,3 +451,9 @@ static void usage()
fprintf(stderr, " jkill -r [-fqv] [-t timeout] jail ...\n");
exit(2);
}
+
+static void usage_jail(const char* name)
+{
+ fprintf(stderr, "usage: %s\n", name);
+ exit(2);
+}