Package: freebsd-utils
Tags: patch

Hi,

 At Tokyo Debian meeting, SUGIMOTO Norimitsu <dict...@live.jp> demonstrates
 kFreeBSD and it's interesting. And I heard about it lacks full jail support
 since jls and jexec doesn't be included. So, I made a patch for it :)

 It works, confirmed by Norimitsu as below 

$ sudo dpkg -i freebsd-utils_10.1~svn273304+jail1-1_kfreebsd-amd64.deb

[norimitu@test-kf2]$ sudo jail -J /var/run/jail/1.jid -c jid=1 \
  name=jail1 \
  path=/srv/jail/jail_kf64_1 \
  host.hostname=jail_kf64_1 \
  ip4.addr=192.168.22.61 \
  command=/bin/sh -- -c "/etc/init.d/rc S && /etc/init.d/rc 2"

## exec jls
[norimitu@test-kf2]$ sudo jls
   JID  IP Address      Hostname                      Path
     1  192.168.22.61   jail_kf64_1                   /srv/jail/jail_kf64_1


## exec jexec
[norimitu@test-kf2]$ sudo jexec 1 touch /root/foobar.txt

## check file that was created with jexec
[norimitu@test-kf2]$ sudo ls -l /srv/jail/jail_kf64_1/root
合計 0
-rw-r--r-- 1 root root 0 11月 23 15:52 foobar.txt

## seems ok :)

-- 
Regards,

 Hideki Yamane     henrich @ debian.or.jp/org
 http://wiki.debian.org/HidekiYamane
diff -urN freebsd-utils-10.1~svn273304.orig/debian/changelog freebsd-utils-10.1~svn273304/debian/changelog
--- freebsd-utils-10.1~svn273304.orig/debian/changelog	2014-10-21 19:11:16.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/changelog	2015-11-29 07:14:13.811304759 +0900
@@ -1,3 +1,9 @@
+freebsd-utils (10.1~svn273304+jail1-1) UNRELEASED; urgency=medium
+
+  * add jls/jexec support
+
+ -- Hideki Yamane <henr...@debian.org>  Sun, 22 Nov 2015 01:54:31 +0900
+
 freebsd-utils (10.1~svn273304-1) unstable; urgency=medium
 
   [ Petr Salinger ]
diff -urN freebsd-utils-10.1~svn273304.orig/debian/freebsd-utils.install freebsd-utils-10.1~svn273304/debian/freebsd-utils.install
--- freebsd-utils-10.1~svn273304.orig/debian/freebsd-utils.install	2014-08-29 07:44:16.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/freebsd-utils.install	2015-11-22 02:09:34.000000000 +0900
@@ -27,3 +27,5 @@
 
 usr/sbin/acpiconf			/usr/sbin
 usr/sbin/jail				/usr/sbin
+usr/sbin/jls				/usr/sbin
+usr/sbin/jexec				/usr/sbin
diff -urN freebsd-utils-10.1~svn273304.orig/debian/patches/makefiles.diff freebsd-utils-10.1~svn273304/debian/patches/makefiles.diff
--- freebsd-utils-10.1~svn273304.orig/debian/patches/makefiles.diff	2014-10-06 04:59:11.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/patches/makefiles.diff	2015-11-22 02:31:57.000000000 +0900
+Index: freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jexec/Makefile
+===================================================================
+--- freebsd-utils-10.1~svn273304+jail1.orig/src/usr.sbin/jexec/Makefile
++++ freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jexec/Makefile
+@@ -3,6 +3,8 @@
+ PROG=	jexec
+ MAN=	jexec.8
+ DPADD=	${LIBJAIL} ${LIBUTIL}
+-LDADD=	-ljail -lutil
++LDADD=	-ljail -lutil-freebsd
++
++LDADD+=        -lfreebsd-glue
+ 
+ .include <bsd.prog.mk>
+Index: freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jls/Makefile
+===================================================================
+--- freebsd-utils-10.1~svn273304+jail1.orig/src/usr.sbin/jls/Makefile
++++ freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jls/Makefile
+@@ -7,6 +7,8 @@ MAN=	jls.8
+ DPADD=	${LIBJAIL}
+ LDADD=	-ljail
+ 
++LDADD+=        -lfreebsd-glue
++
+ .if ${MK_INET6_SUPPORT} != "no"
+ CFLAGS+= -DINET6
+ .endif
diff -urN freebsd-utils-10.1~svn273304.orig/debian/rules freebsd-utils-10.1~svn273304/debian/rules
--- freebsd-utils-10.1~svn273304.orig/debian/rules	2014-10-20 20:14:18.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/rules	2015-11-22 02:02:32.000000000 +0900
@@ -113,6 +113,7 @@
 		sys/i386/linux/syscalls.master \
 		\
 		 usr.sbin/jail bin/chflags \
+		 usr.sbin/jls usr.sbin/jexec \
 		 sbin/devd etc/devd.conf etc/devd sys/dev/usb/usbdevs \
 		 usr.sbin/acpi/acpiconf \
 		usr.sbin/acpi/Makefile \
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/Makefile freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/Makefile
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/Makefile	2015-11-24 07:00:09.000000000 +0900
@@ -0,0 +1,10 @@
+# $FreeBSD: release/10.1.0/usr.sbin/jexec/Makefile 201390 2010-01-02 11:07:44Z ed $
+
+PROG=	jexec
+MAN=	jexec.8
+DPADD=	${LIBJAIL} ${LIBUTIL}
+LDADD=	-ljail -lutil-freebsd
+
+LDADD+=        -lfreebsd-glue
+
+.include <bsd.prog.mk>
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.8 freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.8
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.8	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.8	2015-11-22 01:46:49.000000000 +0900
@@ -0,0 +1,76 @@
+.\"
+.\" Copyright (c) 2003 Mike Barcroft <m...@freebsd.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: release/10.1.0/usr.sbin/jexec/jexec.8 192896 2009-05-27 14:30:26Z jamie $
+.\"
+.Dd May 27, 2009
+.Dt JEXEC 8
+.Os
+.Sh NAME
+.Nm jexec
+.Nd "execute a command inside an existing jail"
+.Sh SYNOPSIS
+.Nm
+.Op Fl u Ar username | Fl U Ar username
+.Ar jail command ...
+.Sh DESCRIPTION
+The
+.Nm
+utility executes
+.Ar command
+inside the
+.Ar jail
+identified by its jid or name.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl u Ar username
+The user name from host environment as whom the
+.Ar command
+should run.
+.It Fl U Ar username
+The user name from jailed environment as whom the
+.Ar command
+should run.
+.El
+.Sh SEE ALSO
+.Xr jail_attach 2 ,
+.Xr jail 8 ,
+.Xr jls 8
+.Sh HISTORY
+The
+.Nm
+utility was added in
+.Fx 5.1 .
+.Sh BUGS
+If the jail is not identified by
+.Ar jid
+there is a possible race in between the lookup of the jail
+and executing the command inside the jail.
+Giving a
+.Ar jid
+has a similar race as another process can stop the jail and
+start another one after the user looked up the
+.Ar jid .
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.c freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.c
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.c	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.c	2015-11-22 01:46:49.000000000 +0900
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <m...@freebsd.org>
+ * Copyright (c) 2008 Bjoern A. Zeeb <b...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: release/10.1.0/usr.sbin/jexec/jexec.c 194869 2009-06-24 18:18:35Z jamie $
+ */
+
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <jail.h>
+#include <limits.h>
+#include <login_cap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+static void	usage(void);
+
+#define GET_USER_INFO do {						\
+	pwd = getpwnam(username);					\
+	if (pwd == NULL) {						\
+		if (errno)						\
+			err(1, "getpwnam: %s", username);		\
+		else							\
+			errx(1, "%s: no such user", username);		\
+	}								\
+	lcap = login_getpwclass(pwd);					\
+	if (lcap == NULL)						\
+		err(1, "getpwclass: %s", username);			\
+	ngroups = ngroups_max;						\
+	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
+		err(1, "getgrouplist: %s", username);			\
+} while (0)
+
+int
+main(int argc, char *argv[])
+{
+	int jid;
+	login_cap_t *lcap = NULL;
+	struct passwd *pwd = NULL;
+	gid_t *groups = NULL;
+	int ch, ngroups, uflag, Uflag;
+	long ngroups_max;
+	char *username;
+
+	ch = uflag = Uflag = 0;
+	username = NULL;
+	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
+	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
+		err(1, "malloc");
+
+	while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
+		switch (ch) {
+		case 'n':
+			/* Specified name, now unused */
+			break;
+		case 'u':
+			username = optarg;
+			uflag = 1;
+			break;
+		case 'U':
+			username = optarg;
+			Uflag = 1;
+			break;
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc < 2)
+		usage();
+	if (uflag && Uflag)
+		usage();
+	if (uflag)
+		GET_USER_INFO;
+	jid = jail_getid(argv[0]);
+	if (jid < 0)
+		errx(1, "%s", jail_errmsg);
+	if (jail_attach(jid) == -1)
+		err(1, "jail_attach(%d)", jid);
+	if (chdir("/") == -1)
+		err(1, "chdir(): /");
+	if (username != NULL) {
+		if (Uflag)
+			GET_USER_INFO;
+		if (setgroups(ngroups, groups) != 0)
+			err(1, "setgroups");
+		if (setgid(pwd->pw_gid) != 0)
+			err(1, "setgid");
+		if (setusercontext(lcap, pwd, pwd->pw_uid,
+		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
+			err(1, "setusercontext");
+		login_close(lcap);
+	}
+	if (execvp(argv[1], argv + 1) == -1)
+		err(1, "execvp(): %s", argv[1]);
+	exit(0);
+}
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "%s\n",
+		"usage: jexec [-u username | -U username] jail command ...");
+	exit(1); 
+}
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/Makefile freebsd-utils-10.1~svn273304/src/usr.sbin/jls/Makefile
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/Makefile	2015-11-24 07:00:09.000000000 +0900
@@ -0,0 +1,19 @@
+# $FreeBSD: release/10.1.0/usr.sbin/jls/Makefile 222465 2011-05-29 21:03:40Z bz $
+
+.include <bsd.own.mk>
+
+PROG=	jls
+MAN=	jls.8
+DPADD=	${LIBJAIL}
+LDADD=	-ljail
+
+LDADD+=        -lfreebsd-glue
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
+
+.include <bsd.prog.mk>
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.8 freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.8
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.8	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.8	2015-11-22 01:46:45.000000000 +0900
@@ -0,0 +1,115 @@
+.\"
+.\" Copyright (c) 2003 Mike Barcroft <m...@freebsd.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: release/10.1.0/usr.sbin/jls/jls.8 250736 2013-05-17 08:48:16Z des $
+.\"
+.Dd July 20, 2012
+.Dt JLS 8
+.Os
+.Sh NAME
+.Nm jls
+.Nd "list jails"
+.Sh SYNOPSIS
+.Nm
+.Op Fl dhNnqsv
+.Op Fl j Ar jail
+.Op Ar parameter ...
+.Sh DESCRIPTION
+The
+.Nm
+utility lists all active jails, or the specified jail.
+Each jail is represented by one row which contains space-separated values of
+the listed
+.Ar parameters ,
+including the pseudo-parameter
+.Va all
+which will show all available jail parameters.
+A list of available parameters can be retrieved via
+.Dq Nm sysctl Fl d Va security.jail.param .
+See
+.Xr jail 8
+for a description of some core parameters.
+.Pp
+If no
+.Ar parameters
+or any of the options
+.Fl hns
+are given, the following four columns will be printed:
+jail identifier (jid), IP address (ip4.addr), hostname (host.hostname),
+and path (path).
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d
+List
+.Va dying
+as well as active jails.
+.It Fl h
+Print a header line containing the parameters listed.
+If no parameters are given on the command line,
+.Va all
+is assumed.
+.It Fl N
+In the standard display mode, print each jail's name instead of its
+numeric ID.
+If the jail does not have a name, the numeric ID is printed instead.
+.It Fl n
+Print parameters in
+.Dq name=value
+format, where each parameter is preceded by its name.
+If no parameters are given on the command line,
+.Va all
+is assumed.
+.It Fl q
+Put quotes around parameters if they contain spaces or quotes, or are
+the empty string.
+.It Fl s
+Print parameters suitable for passing to
+.Xr jail 8 ,
+skipping read-only and unused parameters.
+Implies
+.Fl nq .
+.It Fl v
+Print a multiple-line summary per jail, with the following parameters:
+jail identifier (jid), hostname (host.hostname), path (path),
+jail name (name), jail state (dying), cpuset ID (cpuset),
+IP address(es) (ip4.addr and ip6.addr).
+.It Fl j Ar jail
+The jid or name of the
+.Ar jail
+to list.
+Without this option, all active jails will be listed.
+.El
+.Sh SEE ALSO
+.Xr jail_get 2 ,
+.Xr jail 8 ,
+.Xr jexec 8
+.Sh HISTORY
+The
+.Nm
+utility was added in
+.Fx 5.1 .
+Extensible jail parameters were introduced in
+.Fx 8.0 .
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.c freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.c
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.c	1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.c	2015-11-22 01:46:45.000000000 +0900
@@ -0,0 +1,516 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <m...@freebsd.org>
+ * Copyright (c) 2008 Bjoern A. Zeeb <b...@freebsd.org>
+ * Copyright (c) 2009 James Gritton <ja...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: release/10.1.0/usr.sbin/jls/jls.c 250736 2013-05-17 08:48:16Z des $");
+
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <jail.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define	JP_USER		0x01000000
+#define	JP_OPT		0x02000000
+
+#define	PRINT_DEFAULT	0x01
+#define	PRINT_HEADER	0x02
+#define	PRINT_NAMEVAL	0x04
+#define	PRINT_QUOTED	0x08
+#define	PRINT_SKIP	0x10
+#define	PRINT_VERBOSE	0x20
+#define	PRINT_JAIL_NAME	0x40
+
+static struct jailparam *params;
+static int *param_parent;
+static int nparams;
+#ifdef INET6
+static int ip6_ok;
+#endif
+#ifdef INET
+static int ip4_ok;
+#endif
+
+static int add_param(const char *name, void *value, size_t valuelen,
+		struct jailparam *source, unsigned flags);
+static int sort_param(const void *a, const void *b);
+static char *noname(const char *name);
+static char *nononame(const char *name);
+static int print_jail(int pflags, int jflags);
+static void quoted_print(char *str);
+
+int
+main(int argc, char **argv)
+{
+	char *dot, *ep, *jname;
+	int c, i, jflags, jid, lastjid, pflags, spc;
+
+	jname = NULL;
+	pflags = jflags = jid = 0;
+	while ((c = getopt(argc, argv, "adj:hNnqsv")) >= 0)
+		switch (c) {
+		case 'a':
+		case 'd':
+			jflags |= JAIL_DYING;
+			break;
+		case 'j':
+			jid = strtoul(optarg, &ep, 10);
+			if (!jid || *ep) {
+				jid = 0;
+				jname = optarg;
+			}
+			break;
+		case 'h':
+			pflags = (pflags & ~(PRINT_SKIP | PRINT_VERBOSE)) |
+			    PRINT_HEADER;
+			break;
+		case 'N':
+			pflags |= PRINT_JAIL_NAME;
+			break;
+		case 'n':
+			pflags = (pflags & ~PRINT_VERBOSE) | PRINT_NAMEVAL;
+			break;
+		case 'q':
+			pflags |= PRINT_QUOTED;
+			break;
+		case 's':
+			pflags = (pflags & ~(PRINT_HEADER | PRINT_VERBOSE)) |
+			    PRINT_NAMEVAL | PRINT_QUOTED | PRINT_SKIP;
+			break;
+		case 'v':
+			pflags = (pflags &
+			    ~(PRINT_HEADER | PRINT_NAMEVAL | PRINT_SKIP)) |
+			    PRINT_VERBOSE;
+			break;
+		default:
+			errx(1, "usage: jls [-dhNnqv] [-j jail] [param ...]");
+		}
+
+#ifdef INET6
+	ip6_ok = feature_present("inet6");
+#endif
+#ifdef INET
+	ip4_ok = feature_present("inet");
+#endif
+
+	/* Add the parameters to print. */
+	if (optind == argc) {
+		if (pflags & (PRINT_HEADER | PRINT_NAMEVAL))
+			add_param("all", NULL, (size_t)0, NULL, JP_USER);
+		else if (pflags & PRINT_VERBOSE) {
+			add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+			add_param("host.hostname", NULL, (size_t)0, NULL,
+			    JP_USER);
+			add_param("path", NULL, (size_t)0, NULL, JP_USER);
+			add_param("name", NULL, (size_t)0, NULL, JP_USER);
+			add_param("dying", NULL, (size_t)0, NULL, JP_USER);
+			add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER);
+#ifdef INET
+			if (ip4_ok)
+				add_param("ip4.addr", NULL, (size_t)0, NULL,
+				    JP_USER);
+#endif
+#ifdef INET6
+			if (ip6_ok)
+				add_param("ip6.addr", NULL, (size_t)0, NULL,
+				    JP_USER | JP_OPT);
+#endif
+		} else {
+			pflags |= PRINT_DEFAULT;
+			if (pflags & PRINT_JAIL_NAME)
+				add_param("name", NULL, (size_t)0, NULL, JP_USER);
+			else
+				add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+#ifdef INET
+			if (ip4_ok)
+				add_param("ip4.addr", NULL, (size_t)0, NULL,
+				    JP_USER);
+#endif
+			add_param("host.hostname", NULL, (size_t)0, NULL,
+			    JP_USER);
+			add_param("path", NULL, (size_t)0, NULL, JP_USER);
+		}
+	} else
+		while (optind < argc)
+			add_param(argv[optind++], NULL, (size_t)0, NULL,
+			    JP_USER);
+
+	if (pflags & PRINT_SKIP) {
+		/* Check for parameters with jailsys parents. */
+		for (i = 0; i < nparams; i++) {
+			if ((params[i].jp_flags & JP_USER) &&
+			    (dot = strchr(params[i].jp_name, '.'))) {
+				*dot = 0;
+				param_parent[i] = add_param(params[i].jp_name,
+				    NULL, (size_t)0, NULL, JP_OPT);
+				*dot = '.';
+			}
+		}
+	}
+
+	/* Add the index key parameters. */
+	if (jid != 0)
+		add_param("jid", &jid, sizeof(jid), NULL, 0);
+	else if (jname != NULL)
+		add_param("name", jname, strlen(jname), NULL, 0);
+	else
+		add_param("lastjid", &lastjid, sizeof(lastjid), NULL, 0);
+
+	/* Print a header line if requested. */
+	if (pflags & PRINT_VERBOSE)
+		printf("   JID  Hostname                      Path\n"
+		       "        Name                          State\n"
+		       "        CPUSetID\n"
+		       "        IP Address(es)\n");
+	else if (pflags & PRINT_DEFAULT)
+		if (pflags & PRINT_JAIL_NAME)
+			printf(" JID             IP Address      "
+			    "Hostname                      Path\n");
+		else
+			printf("   JID  IP Address      "
+			    "Hostname                      Path\n");
+	else if (pflags & PRINT_HEADER) {
+		for (i = spc = 0; i < nparams; i++)
+			if (params[i].jp_flags & JP_USER) {
+				if (spc)
+					putchar(' ');
+				else
+					spc = 1;
+				fputs(params[i].jp_name, stdout);
+			}
+		putchar('\n');
+	}
+
+	/* Fetch the jail(s) and print the paramters. */
+	if (jid != 0 || jname != NULL) {
+		if (print_jail(pflags, jflags) < 0)
+			errx(1, "%s", jail_errmsg);
+	} else {
+		for (lastjid = 0;
+		     (lastjid = print_jail(pflags, jflags)) >= 0; )
+			;
+		if (errno != 0 && errno != ENOENT)
+			errx(1, "%s", jail_errmsg);
+	}
+
+	return (0);
+}
+
+static int
+add_param(const char *name, void *value, size_t valuelen,
+    struct jailparam *source, unsigned flags)
+{
+	struct jailparam *param, *tparams;
+	int i, tnparams;
+
+	static int paramlistsize;
+
+	/* The pseudo-parameter "all" scans the list of available parameters. */
+	if (!strcmp(name, "all")) {
+		tnparams = jailparam_all(&tparams);
+		if (tnparams < 0)
+			errx(1, "%s", jail_errmsg);
+		qsort(tparams, (size_t)tnparams, sizeof(struct jailparam),
+		    sort_param);
+		for (i = 0; i < tnparams; i++)
+			add_param(tparams[i].jp_name, NULL, (size_t)0,
+			    tparams + i, flags);
+		free(tparams);
+		return -1;
+	}
+
+	/* Check for repeat parameters. */
+	for (i = 0; i < nparams; i++)
+		if (!strcmp(name, params[i].jp_name)) {
+			if (value != NULL && jailparam_import_raw(params + i,
+			    value, valuelen) < 0)
+				errx(1, "%s", jail_errmsg);
+			params[i].jp_flags |= flags;
+			if (source != NULL)
+				jailparam_free(source, 1);
+			return i;
+		}
+
+	/* Make sure there is room for the new param record. */
+	if (!nparams) {
+		paramlistsize = 32;
+		params = malloc(paramlistsize * sizeof(*params));
+		param_parent = malloc(paramlistsize * sizeof(*param_parent));
+		if (params == NULL || param_parent == NULL)
+			err(1, "malloc");
+	} else if (nparams >= paramlistsize) {
+		paramlistsize *= 2;
+		params = realloc(params, paramlistsize * sizeof(*params));
+		param_parent = realloc(param_parent,
+		    paramlistsize * sizeof(*param_parent));
+		if (params == NULL || param_parent == NULL)
+			err(1, "realloc");
+	}
+
+	/* Look up the parameter. */
+	param_parent[nparams] = -1;
+	param = params + nparams++;
+	if (source != NULL) {
+		*param = *source;
+		param->jp_flags |= flags;
+		return param - params;
+	}
+	if (jailparam_init(param, name) < 0)
+		errx(1, "%s", jail_errmsg);
+	param->jp_flags = flags;
+	if ((value != NULL ? jailparam_import_raw(param, value, valuelen)
+	     : jailparam_import(param, value)) < 0) {
+		if (flags & JP_OPT) {
+			nparams--;
+			return (-1);
+		}
+		errx(1, "%s", jail_errmsg);
+	}
+	return param - params;
+}
+
+static int
+sort_param(const void *a, const void *b)
+{
+	const struct jailparam *parama, *paramb;
+	char *ap, *bp;
+
+	/* Put top-level parameters first. */
+	parama = a;
+	paramb = b;
+	ap = strchr(parama->jp_name, '.');
+	bp = strchr(paramb->jp_name, '.');
+	if (ap && !bp)
+		return (1);
+	if (bp && !ap)
+		return (-1);
+	return (strcmp(parama->jp_name, paramb->jp_name));
+}
+
+static char *
+noname(const char *name)
+{
+	char *nname, *p;
+
+	nname = malloc(strlen(name) + 3);
+	if (nname == NULL)
+		err(1, "malloc");
+	p = strrchr(name, '.');
+	if (p != NULL)
+		sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1);
+	else
+		sprintf(nname, "no%s", name);
+	return nname;
+}
+
+static char *
+nononame(const char *name)
+{
+	char *nname, *p;
+
+	p = strrchr(name, '.');
+	if (strncmp(p ? p + 1 : name, "no", 2))
+		return NULL;
+	nname = malloc(strlen(name) - 1);
+	if (nname == NULL)
+		err(1, "malloc");
+	if (p != NULL)
+		sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3);
+	else
+		strcpy(nname, name + 2);
+	return nname;
+}
+
+static int
+print_jail(int pflags, int jflags)
+{
+	char *nname;
+	char **param_values;
+	int i, ai, jid, count, n, spc;
+	char ipbuf[INET6_ADDRSTRLEN];
+
+	jid = jailparam_get(params, nparams, jflags);
+	if (jid < 0)
+		return jid;
+	if (pflags & PRINT_VERBOSE) {
+		printf("%6d  %-29.29s %.74s\n"
+		       "%6s  %-29.29s %.74s\n"
+		       "%6s  %-6d\n",
+		    *(int *)params[0].jp_value,
+		    (char *)params[1].jp_value,
+		    (char *)params[2].jp_value,
+		    "",
+		    (char *)params[3].jp_value,
+		    *(int *)params[4].jp_value ? "DYING" : "ACTIVE",
+		    "",
+		    *(int *)params[5].jp_value);
+		n = 6;
+#ifdef INET
+		if (ip4_ok && !strcmp(params[n].jp_name, "ip4.addr")) {
+			count = params[n].jp_valuelen / sizeof(struct in_addr);
+			for (ai = 0; ai < count; ai++)
+				if (inet_ntop(AF_INET,
+				    &((struct in_addr *)params[n].jp_value)[ai],
+				    ipbuf, sizeof(ipbuf)) == NULL)
+					err(1, "inet_ntop");
+				else
+					printf("%6s  %-15.15s\n", "", ipbuf);
+			n++;
+		}
+#endif
+#ifdef INET6
+		if (ip6_ok && !strcmp(params[n].jp_name, "ip6.addr")) {
+			count = params[n].jp_valuelen / sizeof(struct in6_addr);
+			for (ai = 0; ai < count; ai++)
+				if (inet_ntop(AF_INET6,
+				    &((struct in6_addr *)
+					params[n].jp_value)[ai],
+				    ipbuf, sizeof(ipbuf)) == NULL)
+					err(1, "inet_ntop");
+				else
+					printf("%6s  %s\n", "", ipbuf);
+			n++;
+		}
+#endif
+	} else if (pflags & PRINT_DEFAULT) {
+		if (pflags & PRINT_JAIL_NAME)
+			printf(" %-15s ", (char *)params[0].jp_value);
+		else
+			printf("%6d  ", *(int *)params[0].jp_value);
+		printf("%-15.15s %-29.29s %.74s\n",
+#ifdef INET
+		    (!ip4_ok || params[1].jp_valuelen == 0) ? "-"
+		    : inet_ntoa(*(struct in_addr *)params[1].jp_value),
+		    (char *)params[2-!ip4_ok].jp_value,
+		    (char *)params[3-!ip4_ok].jp_value);
+#else
+		    "-",
+		    (char *)params[1].jp_value,
+		    (char *)params[2].jp_value);
+#endif
+	} else {
+		param_values = alloca(nparams * sizeof(*param_values));
+		for (i = 0; i < nparams; i++) {
+			if (!(params[i].jp_flags & JP_USER))
+				continue;
+			param_values[i] = jailparam_export(params + i);
+			if (param_values[i] == NULL)
+				errx(1, "%s", jail_errmsg);
+		}
+		for (i = spc = 0; i < nparams; i++) {
+			if (!(params[i].jp_flags & JP_USER))
+				continue;
+			if ((pflags & PRINT_SKIP) &&
+			    ((!(params[i].jp_ctltype &
+				(CTLFLAG_WR | CTLFLAG_TUN))) ||
+			     (param_parent[i] >= 0 &&
+			      *(int *)params[param_parent[i]].jp_value !=
+			      JAIL_SYS_NEW)))
+				continue;
+			if (spc)
+				putchar(' ');
+			else
+				spc = 1;
+			if (pflags & PRINT_NAMEVAL) {
+				/*
+				 * Generally "name=value", but for booleans
+				 * either "name" or "noname".
+				 */
+				if (params[i].jp_flags &
+				    (JP_BOOL | JP_NOBOOL)) {
+					if (*(int *)params[i].jp_value)
+						printf("%s", params[i].jp_name);
+					else {
+						nname = (params[i].jp_flags &
+						    JP_NOBOOL) ?
+						    nononame(params[i].jp_name)
+						    : noname(params[i].jp_name);
+						printf("%s", nname);
+						free(nname);
+					}
+					continue;
+				}
+				printf("%s=", params[i].jp_name);
+			}
+			if (params[i].jp_valuelen == 0) {
+				if (pflags & PRINT_QUOTED)
+					printf("\"\"");
+				else if (!(pflags & PRINT_NAMEVAL))
+					putchar('-');
+			} else
+				quoted_print(param_values[i]);
+		}
+		putchar('\n');
+		for (i = 0; i < nparams; i++)
+			if (params[i].jp_flags & JP_USER)
+				free(param_values[i]);
+	}
+	return (jid);
+}
+
+static void
+quoted_print(char *str)
+{
+	int c, qc;
+	char *p = str;
+
+	/* An empty string needs quoting. */
+	if (!*p) {
+		fputs("\"\"", stdout);
+		return;
+	}
+
+	/*
+	 * The value will be surrounded by quotes if it contains spaces
+	 * or quotes.
+	 */
+	qc = strchr(p, '\'') ? '"'
+	    : strchr(p, '"') ? '\''
+	    : strchr(p, ' ') || strchr(p, '\t') ? '"'
+	    : 0;
+	if (qc)
+		putchar(qc);
+	while ((c = *p++)) {
+		if (c == '\\' || c == qc)
+			putchar('\\');
+		putchar(c);
+	}
+	if (qc)
+		putchar(qc);
+}

Reply via email to