diff --git a/usr.sbin/jls/jls.8 b/usr.sbin/jls/jls.8 index c0eed8df9454..2107405f710d 100644 --- a/usr.sbin/jls/jls.8 +++ b/usr.sbin/jls/jls.8 @@ -1,106 +1,111 @@ .\" .\" Copyright (c) 2003 Mike Barcroft .\" 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$ .\" -.Dd May 27, 2009 +.Dd July 8, 2009 .Dt JLS 8 .Os .Sh NAME .Nm jls .Nd "list jails" .Sh SYNOPSIS .Nm .Op Fl dhnqsv .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, the default output always -contains a header. +If no parameters are given on the command line, +.Va all +is assumed. .It Fl n Print parameters in .Dq name=value format, where each parameter is preceded by its name. -This option is ignored for the default four-column output. +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 c +.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 --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c index 443eb8e8ea35..40019f119350 100644 --- a/usr.sbin/jls/jls.c +++ b/usr.sbin/jls/jls.c @@ -1,466 +1,468 @@ /*- * Copyright (c) 2003 Mike Barcroft * Copyright (c) 2008 Bjoern A. Zeeb * Copyright (c) 2009 James Gritton * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 static struct jailparam *params; static int *param_noparent; static int nparams; 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, *nname; int c, i, jflags, jid, lastjid, pflags, spc; jname = NULL; pflags = jflags = jid = 0; while ((c = getopt(argc, argv, "adj:hnqsv")) >= 0) switch (c) { case 'a': case 'd': jflags |= JAIL_DYING; break; case 'j': jid = strtoul(optarg, &ep, 10); if (!*optarg || *ep) jname = optarg; break; case 'h': - pflags = (pflags & ~PRINT_SKIP) | PRINT_HEADER; + pflags = (pflags & ~(PRINT_SKIP | PRINT_VERBOSE)) | + PRINT_HEADER; 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_NAMEVAL | PRINT_SKIP)) | + pflags = (pflags & + ~(PRINT_HEADER | PRINT_NAMEVAL | PRINT_SKIP)) | PRINT_VERBOSE; break; default: errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]"); } /* Add the parameters to print. */ if (optind == argc) { - if (pflags & PRINT_VERBOSE) { + 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); add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER); add_param("ip6.addr", NULL, (size_t)0, NULL, JP_USER | JP_OPT); } else { - pflags = (pflags & - ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) | - PRINT_DEFAULT; + pflags |= PRINT_DEFAULT; add_param("jid", NULL, (size_t)0, NULL, JP_USER); add_param("ip4.addr", 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); } } else while (optind < argc) add_param(argv[optind++], NULL, (size_t)0, NULL, JP_USER); if (pflags & PRINT_SKIP) { /* Check for parameters with boolean parents. */ for (i = 0; i < nparams; i++) { if ((params[i].jp_flags & JP_USER) && (dot = strchr(params[i].jp_name, '.'))) { *dot = 0; nname = noname(params[i].jp_name); *dot = '.'; param_noparent[i] = add_param(nname, NULL, (size_t)0, NULL, JP_OPT); free(nname); } } } /* 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) 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_noparent = malloc(paramlistsize * sizeof(*param_noparent)); if (params == NULL || param_noparent == NULL) err(1, "malloc"); } else if (nparams >= paramlistsize) { paramlistsize *= 2; params = realloc(params, paramlistsize * sizeof(*params)); param_noparent = realloc(param_noparent, paramlistsize * sizeof(*param_noparent)); if (params == NULL || param_noparent == NULL) err(1, "realloc"); } /* Look up the parameter. */ param_noparent[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, 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); count = params[6].jp_valuelen / sizeof(struct in_addr); for (ai = 0; ai < count; ai++) if (inet_ntop(AF_INET, &((struct in_addr *)params[6].jp_value)[ai], ipbuf, sizeof(ipbuf)) == NULL) err(1, "inet_ntop"); else printf("%6s %-15.15s\n", "", ipbuf); if (!strcmp(params[7].jp_name, "ip6.addr")) { count = params[7].jp_valuelen / sizeof(struct in6_addr); for (ai = 0; ai < count; ai++) if (inet_ntop(AF_INET6, &((struct in_addr *)params[7].jp_value)[ai], ipbuf, sizeof(ipbuf)) == NULL) err(1, "inet_ntop"); else printf("%6s %-15.15s\n", "", ipbuf); } } else if (pflags & PRINT_DEFAULT) printf("%6d %-15.15s %-29.29s %.74s\n", *(int *)params[0].jp_value, params[1].jp_valuelen == 0 ? "-" : inet_ntoa(*(struct in_addr *)params[1].jp_value), (char *)params[2].jp_value, (char *)params[3].jp_value); 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_noparent[i] >= 0 && *(int *)params[param_noparent[i]].jp_value))) 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]); } for (i = 0; i < nparams; i++) if (!(params[i].jp_flags & JP_RAWVALUE)) { free(params[i].jp_value); params[i].jp_value = NULL; } 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); }