summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2003-12-02 17:20:39 +0000
committerStef Walter <stef@memberwebs.com>2003-12-02 17:20:39 +0000
commit58c696e88cfeb6d97d836b9f328d683b0e187d65 (patch)
tree1b1a15cdc8cb13fa2ba8d25f0bd4a165524e79db /src
parentf38c902303a704db26f8632e6e582af5d65f0a50 (diff)
Initial Import
Diffstat (limited to 'src')
-rw-r--r--src/Makefile357
-rw-r--r--src/Makefile.am8
-rw-r--r--src/getjail.c69
-rw-r--r--src/getjail.h35
-rw-r--r--src/jails.826
-rw-r--r--src/jails.c157
-rw-r--r--src/killjail.868
-rw-r--r--src/killjail.c387
8 files changed, 1107 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..7b914d5
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,357 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/jailutils
+pkglibdir = $(libdir)/jailutils
+pkgincludedir = $(includedir)/jailutils
+top_builddir = ..
+
+ACLOCAL = ${SHELL} /usr/work/src/jailutils/missing --run aclocal
+AUTOCONF = ${SHELL} /usr/work/src/jailutils/missing --run autoconf
+AUTOMAKE = ${SHELL} /usr/work/src/jailutils/missing --run automake
+AUTOHEADER = ${SHELL} /usr/work/src/jailutils/missing --run autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+AMTAR = ${SHELL} /usr/work/src/jailutils/missing --run tar
+AWK = nawk
+CC = gcc
+DEPDIR = .deps
+EXEEXT =
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+OBJEXT = o
+PACKAGE = jailutils
+VERSION = 0.5.4
+am__include = include
+am__quote =
+install_sh = /usr/work/src/jailutils/install-sh
+
+sbin_PROGRAMS = killjail jails
+killjail_SOURCES = killjail.c getjail.c getjail.h
+killjail_LDADD = -lkvm
+jails_SOURCES = jails.c getjail.c getjail.h
+jails_LDADD = -lkvm
+man_MANS = killjail.8 jails.8
+EXTRA_DIST = $(man_MANS)
+subdir = src
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+sbin_PROGRAMS = killjail$(EXEEXT) jails$(EXEEXT)
+PROGRAMS = $(sbin_PROGRAMS)
+
+am_jails_OBJECTS = jails.$(OBJEXT) getjail.$(OBJEXT)
+jails_OBJECTS = $(am_jails_OBJECTS)
+jails_DEPENDENCIES =
+jails_LDFLAGS =
+am_killjail_OBJECTS = killjail.$(OBJEXT) getjail.$(OBJEXT)
+killjail_OBJECTS = $(am_killjail_OBJECTS)
+killjail_DEPENDENCIES =
+killjail_LDFLAGS =
+
+DEFS = -DHAVE_CONFIG_H
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS =
+LDFLAGS =
+LIBS = -lkvm
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+DEP_FILES = $(DEPDIR)/getjail.Po $(DEPDIR)/jails.Po \
+ $(DEPDIR)/killjail.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = -g -O2
+DIST_SOURCES = $(jails_SOURCES) $(killjail_SOURCES)
+
+NROFF = nroff
+MANS = $(man_MANS)
+DIST_COMMON = Makefile.am Makefile.in
+SOURCES = $(jails_SOURCES) $(killjail_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(sbindir)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/$$f"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/$$f; \
+ else :; fi; \
+ done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \
+ rm -f $(DESTDIR)$(sbindir)/$$f; \
+ done
+
+clean-sbinPROGRAMS:
+ -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+jails$(EXEEXT): $(jails_OBJECTS) $(jails_DEPENDENCIES)
+ @rm -f jails$(EXEEXT)
+ $(LINK) $(jails_LDFLAGS) $(jails_OBJECTS) $(jails_LDADD) $(LIBS)
+killjail$(EXEEXT): $(killjail_OBJECTS) $(killjail_DEPENDENCIES)
+ @rm -f killjail$(EXEEXT)
+ $(LINK) $(killjail_LDFLAGS) $(killjail_OBJECTS) $(killjail_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include $(DEPDIR)/getjail.Po
+include $(DEPDIR)/jails.Po
+include $(DEPDIR)/killjail.Po
+
+distclean-depend:
+ -rm -rf $(DEPDIR)
+
+.c.o:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CCDEPMODE) $(depcomp) \
+ $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CCDEPMODE) $(depcomp) \
+ $(COMPILE) -c `cygpath -w $<`
+CCDEPMODE = depmode=gcc
+uninstall-info-am:
+
+man8dir = $(mandir)/man8
+install-man8: $(man8_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(man8dir)
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
+ done
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man8dir)/$$inst; \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || etags $(ETAGS_ARGS) $$tags $$unique $(LISP)
+
+GTAGS:
+ here=`CDPATH=: && cd $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ $(mkinstalldirs) "$(distdir)/$$dir"; \
+ fi; \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-exec-am: install-sbinPROGRAMS
+
+install-info: install-info-am
+
+install-man: install-man8
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+uninstall-am: uninstall-info-am uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+ clean-sbinPROGRAMS distclean distclean-compile distclean-depend \
+ distclean-generic distclean-tags distdir dvi dvi-am info \
+ info-am install install-am install-data install-data-am \
+ install-exec install-exec-am install-info install-info-am \
+ install-man install-man8 install-sbinPROGRAMS install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic tags uninstall uninstall-am \
+ uninstall-info-am uninstall-man uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..8dc8d62
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,8 @@
+sbin_PROGRAMS = killjail jails
+killjail_SOURCES = killjail.c getjail.c getjail.h
+killjail_LDADD = -lkvm
+jails_SOURCES = jails.c getjail.c getjail.h
+jails_LDADD = -lkvm
+man_MANS = killjail.8 jails.8
+EXTRA_DIST = $(man_MANS)
+
diff --git a/src/getjail.c b/src/getjail.c
new file mode 100644
index 0000000..9106557
--- /dev/null
+++ b/src/getjail.c
@@ -0,0 +1,69 @@
+/*
+// AUTHOR
+// N. Nielsen
+//
+// LICENSE
+// This software is in the public domain.
+//
+// The software is provided "as is", without warranty of any kind,
+// express or implied, including but not limited to the warranties
+// of merchantability, fitness for a particular purpose, and
+// noninfringement. In no event shall the author(s) be liable for any
+// claim, damages, or other liability, whether in an action of
+// contract, tort, or otherwise, arising from, out of, or in connection
+// with the software or the use or other dealings in the software.
+//
+// SUPPORT
+// Send bug reports to: <nielsen@memberwebs.com>
+//
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include "getjail.h"
+
+#define PROC_STATUS_PATH "/proc/%d/status"
+
+int getpidjail(pid_t pid, char* buff)
+{
+ int fd;
+ size_t bytes;
+ off_t off;
+
+ /* Format the file name */
+ if(snprintf(buff, JAIL_BUFF_SIZE, PROC_STATUS_PATH, pid))
+ {
+ /* Open the file */
+ if((fd = open(buff, O_RDONLY)) >= 0)
+ {
+ /* Seek to the last bit */
+ off = lseek(fd, SEEK_END, 0);
+
+ if(off != -1)
+ {
+ off -= JAIL_BUFF_SIZE;
+ if(off < 0) off = 0;
+ lseek(fd, SEEK_SET, off);
+
+ if((bytes = read(fd, buff, JAIL_BUFF_SIZE - 1)) > 0)
+ {
+ /* Okay now jailname should be the last token */
+ while(isspace(buff[bytes - 1]))
+ bytes--;
+
+ buff[bytes] = 0;
+
+ while(!isspace(buff[bytes - 1]))
+ bytes--;
+
+ memmove(buff, buff + bytes, JAIL_BUFF_SIZE - bytes);
+ return 0;
+
+ }
+ }
+ }
+ }
+
+ return -1;
+}
diff --git a/src/getjail.h b/src/getjail.h
new file mode 100644
index 0000000..5e58542
--- /dev/null
+++ b/src/getjail.h
@@ -0,0 +1,35 @@
+/*
+// AUTHOR
+// N. Nielsen
+//
+// LICENSE
+// This software is in the public domain.
+//
+// The software is provided "as is", without warranty of any kind,
+// express or implied, including but not limited to the warranties
+// of merchantability, fitness for a particular purpose, and
+// noninfringement. In no event shall the author(s) be liable for any
+// claim, damages, or other liability, whether in an action of
+// contract, tort, or otherwise, arising from, out of, or in connection
+// with the software or the use or other dealings in the software.
+//
+// SUPPORT
+// Send bug reports to: <nielsen@memberwebs.com>
+//
+*/
+
+#ifndef _GETJAIL_H_
+#define _GETJAIL_H_
+
+
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#define JAIL_BUFF_SIZE MAXHOSTNAMELEN + 2
+
+int getpidjail(pid_t pid, char* buff);
+
+
+
+#endif /* _GETJAIL_H_ */
diff --git a/src/jails.8 b/src/jails.8
new file mode 100644
index 0000000..11de04f
--- /dev/null
+++ b/src/jails.8
@@ -0,0 +1,26 @@
+.\" Process this file with
+.\" groff -man -Tascii jails.8
+.\"
+.TH JAILS 8 "May 2002" FreeBSD "User Manual"
+.SH NAME
+.B jails
+\- list all jails running on a system
+.SH SYNOPSIS
+.B jails
+
+.SH DESCRIPTION
+The
+.B jails
+command will print a list of all the various jails running
+on your system. The hostnames of those jails are printed.
+The list is not ordered.
+
+.SH BUGS
+I'm sure they're out there.
+
+.SH AUTHOR
+Nate Nielsen <nielsen@memberwebs.com>
+
+.SH "SEE ALSO"
+.BR jail (8),
+.BR jailer (8)
diff --git a/src/jails.c b/src/jails.c
new file mode 100644
index 0000000..9c99743
--- /dev/null
+++ b/src/jails.c
@@ -0,0 +1,157 @@
+/*
+// AUTHOR
+// N. Nielsen
+//
+// LICENSE
+// This software is in the public domain.
+//
+// The software is provided "as is", without warranty of any kind,
+// express or implied, including but not limited to the warranties
+// of merchantability, fitness for a particular purpose, and
+// noninfringement. In no event shall the author(s) be liable for any
+// claim, damages, or other liability, whether in an action of
+// contract, tort, or otherwise, arising from, out of, or in connection
+// with the software or the use or other dealings in the software.
+//
+// SUPPORT
+// Send bug reports to: <nielsen@memberwebs.com>
+//
+// CHANGES
+// 0.5.1 kvm_openfiles call uses /dev/null so non root users can use
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <paths.h>
+#include <stdio.h>
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include "getjail.h"
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+static int listJails();
+static void usage();
+
+int main(int argc, char* argv[])
+{
+ /* Nice main :) */
+ return listJails() >= 0 ? 0 : 1;
+}
+
+
+int listJails()
+{
+ kvm_t *kd;
+ struct kinfo_proc* kp;
+ char errbuf[_POSIX2_LINE_MAX];
+ char jailName[JAIL_BUFF_SIZE];
+ int nentries, i;
+
+
+ char* jails = NULL; /* jail list buffer */
+ size_t nextJail = 0; /* current write positon */
+ size_t endJails = 0; /* size of buffer */
+ int numJails = 0; /* return value */
+
+
+ /* Open kernel interface */
+ kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL,
+ O_RDONLY, errbuf);
+ if(kd == 0)
+ errx(1, "%s", errbuf);
+
+ /* Get a process listing */
+ if((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == 0)
+ errx(1, "%s", kvm_geterr(kd));
+
+
+ /* Okay now loop through and look for the jails */
+ for(i = 0; i < nentries; i++)
+ {
+ pid_t pid;
+
+#if __FreeBSD_version > 500000
+
+ /* Check the flags first */
+ if(!(kp[i].ki_flag & P_JAILED))
+ continue;
+
+ pid = kp[i].ki_pid;
+
+#else
+
+ /* Check the flags first */
+ if(!(kp[i].kp_proc.p_flag & P_JAILED))
+ continue;
+
+ pid = kp[i].kp_proc.p_pid;
+
+#endif
+
+ /* Get this processes jail name */
+ if(getpidjail(pid, jailName) < 0)
+ continue;
+
+ if(jails)
+ {
+ char* j;
+
+ /* See if that jail name was already taken */
+ for(j = jails; *j != NULL; j += strlen(j) + 1)
+ {
+ if(!strcmp(jailName, j))
+ break;
+ }
+
+ /* Can't do this in loop above */
+ if(*j)
+ continue;
+ }
+
+
+ /* Okay we got a jail name */
+
+
+ /* Allocate if necessary enough space for it */
+ if(nextJail + strlen(jailName) + 2 > endJails)
+ {
+ endJails += (JAIL_BUFF_SIZE * 0x2);
+ jails = (char*)realloc(jails, endJails);
+ if(!jails)
+ errx(1, "out of memory");
+ }
+
+
+ /* Put the jail name in the buffer */
+ strcpy(jails + nextJail, jailName);
+ nextJail += strlen(jailName) + 1;
+ jails[nextJail] = 0;
+ numJails++;
+
+ /* And print it */
+ fprintf(stdout, "%s\n", jailName);
+ }
+
+ kvm_close(kd);
+
+ return numJails;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: jails\n");
+ exit(2);
+}
+
diff --git a/src/killjail.8 b/src/killjail.8
new file mode 100644
index 0000000..b0f73b0
--- /dev/null
+++ b/src/killjail.8
@@ -0,0 +1,68 @@
+.\" Process this file with
+.\" groff -man -Tascii killjail.8
+.\"
+.TH KILLJAIL 8 "May 2002" FreeBSD "User Manual"
+.SH NAME
+.B killjail
+\- stop or restart a jail
+.SH SYNOPSIS
+.B killjail
+[
+.B -h
+|
+.B -r
+] [
+.B -t
+.I timeout
+] [
+.B -fq
+]
+.I jailname ...
+.SH DESCRIPTION
+.B killjail
+can either send signals to a
+.BR jailer (8)
+process to manage the shutdown or restart of a jail or it can kill all
+the processes in a jail on it's own.
+
+When no options are given the jail is shutdown as follows:
+.IP 1. 3
+A stop request (SIGTERM) is sent to the
+.BR jailer (8)
+process for the jail if there is one. This initiates an orderly shutdown.
+.IP 2. 3
+Any remaining processes are killed with a SIGTERM.
+.IP 3. 3
+If the
+.B -f
+option is specified, send a SIGKILL to any remaining processes.
+
+.SH OPTIONS
+.IP -f
+Force jail to shutdown sending a SIGKILL as a last resort.
+.IP -h
+Sends a halt request to a jail (SIGQUIT). The jail must have a
+.BR jailer (8)
+process running inside it. The
+.BR jailer (8)
+process remains running within the jail, but all other jailed
+processes are shutdown in and orderly fashion.
+.IP -q
+Supress warnings.
+.IP -r
+Sends a restart request to a jail (SIGHUP). The jail must have a
+.BR jailer (8)
+process running inside it.
+.IP "-t timeout"
+The timeout in seconds to wait between steps 1, 2 and 3 above. Defaults to 3.
+
+.SH BUGS
+I'm sure they're out there. Let me know.
+
+.SH AUTHOR
+Nate Nielsen <nielsen@memberwebs.com>
+
+.SH "SEE ALSO"
+.BR jail (8),
+.BR jailer (8),
+.BR kill (1)
diff --git a/src/killjail.c b/src/killjail.c
new file mode 100644
index 0000000..2b4eb7d
--- /dev/null
+++ b/src/killjail.c
@@ -0,0 +1,387 @@
+/*
+// AUTHOR
+// N. Nielsen
+//
+// LICENSE
+// This software is in the public domain.
+//
+// The software is provided "as is", without warranty of any kind,
+// express or implied, including but not limited to the warranties
+// of merchantability, fitness for a particular purpose, and
+// noninfringement. In no event shall the author(s) be liable for any
+// claim, damages, or other liability, whether in an action of
+// contract, tort, or otherwise, arising from, out of, or in connection
+// with the software or the use or other dealings in the software.
+//
+// SUPPORT
+// Send bug reports to: <nielsen@memberwebs.com>
+//
+// CHANGES
+// 0.5.1 kvm_openfiles uses /dev/null
+//
+// 0.5.3
+// Added quiet option
+// Added force option
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <kvm.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include "getjail.h"
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+/* The big long stop process */
+static int stopJail(char* jailName, int force);
+
+/* Signals the jailer for various requests */
+static int signalJail(char* jailName, int signal);
+
+static void killProcesses(pid_t* pids, int signal);
+static int getJailProcesses(const char* jailName, pid_t* pidJailer, pid_t** pids);
+
+static void usage();
+
+
+/* The timeout to wait between kills */
+#define DEFAULT_TIMEOUT 10
+int g_timeout = DEFAULT_TIMEOUT;
+
+/* To find the jailer process look for this command */
+#define JAILER_COMMAND "jailer"
+
+/* Supress warnings */
+int g_quiet = 0;
+
+int main(int argc, char* argv[])
+{
+ /* If this gets set then only signal jailer, no kill */
+ int signal = 0;
+ int ch = 0;
+ int force = 0;
+ int ret = 0;
+
+ while((ch = getopt(argc, argv, "fhqrt:")) != -1)
+ {
+ switch(ch)
+ {
+ /* Force jail to shutdown */
+ case 'f':
+ force = 1;
+ break;
+
+ case 'q':
+ g_quiet = 1;
+ break;
+
+ /* Send halt request to jailer */
+ case 'h':
+ signal = SIGQUIT;
+ break;
+
+ /* Send restart request to jailer */
+ case 'r':
+ signal = SIGHUP;
+ break;
+
+ /* Timeout to use between kills */
+ case 't':
+ g_timeout = atoi(optarg);
+ if(g_timeout <= 0)
+ errx(1, "invalid timeout argument: %s", optarg);
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Make sure we have a jailName */
+ if(argc == 0)
+ usage();
+
+ /* For each jail */
+ while(argc > 0)
+ {
+ /* If a signal option was set above then signal,
+ otherwise kill */
+ if(signal == 0)
+ {
+ if(stopJail(*argv, force) != 0)
+ ret = 1;
+ }
+ else
+ {
+ if(force)
+ errx(1, "-f option incompatible with -r or -h");
+
+ if(signalJail(*argv, signal) != 0)
+ ret = 1;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ return ret;
+}
+
+
+int signalJail(char* jailName, int signal)
+{
+ pid_t jailerPid = 0;
+
+ /* Only ask for jailer pid */
+ getJailProcesses(jailName, &jailerPid, NULL);
+
+ if(jailerPid == 0)
+ {
+ warnx("%s: jailer not running in jail", jailName);
+ return 1;
+ }
+
+ if(kill(jailerPid, signal) < 0)
+ err(1, "%s: couldn't signal jailer", jailName);
+
+ return 0;
+}
+
+
+int stopJail(char* jailName, int force)
+{
+ pid_t jailerPid = 0;
+ pid_t* jailProcesses = NULL;
+ int pass = 0;
+ int timeout = 0;
+ int ret = 0;
+
+ /*
+ * Multiple passes are used to do different things.
+ * Each time the jails processes are listed.
+ */
+ while(ret == 0 &&
+ getJailProcesses(jailName, &jailerPid, &jailProcesses))
+ {
+
+ if(timeout > 0)
+ {
+ sleep(1);
+ timeout--;
+ }
+
+ else
+ {
+
+ switch(pass)
+ {
+
+ /* First pass is killing the jailer */
+ case 0:
+
+ if(jailerPid == 0)
+ {
+ /* No jailer */
+ if(!g_quiet)
+ warnx("%s: jailer not running in jail", jailName);
+ }
+
+ else
+ {
+ if(kill(jailerPid, SIGTERM) < 0 && errno != ESRCH)
+ err(1, "%s: couldn't signal jailer:", jailName);
+
+ else
+ timeout = g_timeout;
+ }
+
+ break;
+
+
+ /* Okay now quit all processes in jail */
+ case 1:
+
+ /* If we get here, jailer looks like it's irresponsive */
+ if(jailerPid != 0 && !g_quiet)
+ warnx("%s: jailer (pid %d) won't quit. terminating jail...", jailName, jailerPid);
+
+
+ killProcesses(jailProcesses, SIGTERM);
+ timeout = g_timeout;
+ break;
+
+
+ /* Okay now we force kill the processes if necessary */
+ case 2:
+
+ if(force)
+ {
+ /* If we get here, jailer looks like it's really irresponsive */
+ if(!g_quiet)
+ warnx("%s: jail won't stop. forcing jail termination...", jailName);
+
+ killProcesses(jailProcesses, SIGKILL);
+ timeout = g_timeout;
+ }
+
+ break;
+
+
+ /* And if that didn't do it, well then give up */
+ case 3:
+
+ if(!g_quiet)
+ warnx("%s: couldn't stop jail, processes wouldn't die", jailName);
+
+ ret = 1;
+ break;
+
+ }
+
+ pass++;
+ }
+
+ if(jailProcesses)
+ free(jailProcesses);
+
+ }
+
+ if(pass == 0)
+ {
+ if(!g_quiet)
+ warnx("%s: jail not running", jailName);
+
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void killProcesses(pid_t* pids, int signal)
+{
+ /* Note that we assume pids is null terminated
+ this is what getJailProcesses returns */
+
+ while(*pids)
+ {
+ if(kill(*pids, signal) < 0)
+ {
+ /* We ignore missing process errors */
+ if(errno != ESRCH)
+ err(1, "couldn't kill process: %d", *pids);
+ }
+
+ pids++;
+ }
+}
+
+int getJailProcesses(const char* jailName, pid_t* pidJailer, pid_t** pids)
+{
+ kvm_t *kd;
+ struct kinfo_proc* kp;
+ char errbuf[_POSIX2_LINE_MAX];
+ char pidJail[JAIL_BUFF_SIZE];
+ int nentries, i, j;
+
+ /* Open the kernel interface */
+ kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL,
+ O_RDONLY, errbuf);
+ if(kd == 0)
+ errx(1, "%s", errbuf);
+
+ /* Get a process listing */
+ if((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == 0)
+ errx(1, "%s", kvm_geterr(kd));
+
+ /* Allocate memory */
+ if(pids)
+ {
+ if((*pids = (pid_t*)malloc((nentries + 1) * sizeof(pid_t))) == NULL)
+ err(1, "out of memory");
+ }
+
+ /* Okay now loop and look at each process' jail */
+ for(i = 0, j = 0; i < nentries; i++)
+ {
+ pid_t pid;
+
+#if __FreeBSD_version > 500000
+
+ /* Check the flags first */
+ if(!(kp[i].ki_flag & P_JAILED))
+ continue;
+
+ pid = kp[i].ki_pid;
+
+#else
+
+ /* Check the flags first */
+ if(!(kp[i].kp_proc.p_flag & P_JAILED))
+ continue;
+
+ pid = kp[i].kp_proc.p_pid;
+
+#endif
+
+ /* Now actually get the jail name */
+ if(getpidjail(pid, pidJail) < 0)
+ continue;
+
+ if(strcmp(pidJail, jailName))
+ continue;
+
+ /* Copy the PID over */
+ if(pids)
+ (*pids)[j++] = pid;
+
+ /* If it's the jailer then copy that */
+ if(pidJailer)
+ {
+#if __FreeBSD_version > 500000
+ if(strstr(kp[i].ki_comm, JAILER_COMMAND))
+#else
+ if(strstr(kp[i].kp_proc.p_comm, JAILER_COMMAND))
+#endif
+ *pidJailer = pid;
+ }
+
+ }
+
+ /* Null terminate pids array */
+ if(pids)
+ (*pids)[j] = 0;
+
+ kvm_close(kd);
+
+ return j == 0 ? 0 : 1;
+}
+
+
+
+static void usage()
+{
+ fprintf(stderr, "usage: killjail [ -h | -r ] [ -t timeout ] [ -qf ] jailname ...\n");
+ exit(2);
+}
+