4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * zoneadm is a command interpreter for zone administration. It is all in
28 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
29 * main() calls parse_and_run() which calls cmd_match(), then invokes the
30 * appropriate command's handler function. The rest of the program is the
31 * handler functions and their helper functions.
32 *
33 * Some of the helper functions are used largely to simplify I18N: reducing
34 * the need for translation notes. This is particularly true of many of
35 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
36 * than zerror(gettext("foo failed")) with a translation note indicating
37 * that "foo" need not be translated.
38 */
39
40 #include <stdio.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <signal.h>
113 char *name;
114 int af;
115 };
116
117 /* 0755 is the default directory mode. */
118 #define DEFAULT_DIR_MODE \
119 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
120
121 struct cmd {
122 uint_t cmd_num; /* command number */
123 char *cmd_name; /* command name */
124 char *short_usage; /* short form help */
125 int (*handler)(int argc, char *argv[]); /* function to call */
126
127 };
128
129 #define SHELP_HELP "help"
130 #define SHELP_BOOT "boot [-- boot_arguments]"
131 #define SHELP_HALT "halt"
132 #define SHELP_READY "ready"
133 #define SHELP_REBOOT "reboot [-- boot_arguments]"
134 #define SHELP_LIST "list [-cipv]"
135 #define SHELP_VERIFY "verify"
136 #define SHELP_INSTALL "install [brand-specific args]"
137 #define SHELP_UNINSTALL "uninstall [-F] [brand-specific args]"
138 #define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] "\
139 "[brand-specific args] zonename"
140 #define SHELP_MOVE "move zonepath"
141 #define SHELP_DETACH "detach [-n] [brand-specific args]"
142 #define SHELP_ATTACH "attach [-F] [-n <path>] [brand-specific args]"
143 #define SHELP_MARK "mark incomplete"
144
145 #define EXEC_PREFIX "exec "
146 #define EXEC_LEN (strlen(EXEC_PREFIX))
147 #define RMCOMMAND "/usr/bin/rm -rf"
148
149 static int cleanup_zonepath(char *, boolean_t);
150
151
152 static int help_func(int argc, char *argv[]);
153 static int ready_func(int argc, char *argv[]);
154 static int boot_func(int argc, char *argv[]);
155 static int halt_func(int argc, char *argv[]);
156 static int reboot_func(int argc, char *argv[]);
157 static int list_func(int argc, char *argv[]);
158 static int verify_func(int argc, char *argv[]);
159 static int install_func(int argc, char *argv[]);
160 static int uninstall_func(int argc, char *argv[]);
161 static int mount_func(int argc, char *argv[]);
162 static int unmount_func(int argc, char *argv[]);
163 static int clone_func(int argc, char *argv[]);
164 static int move_func(int argc, char *argv[]);
165 static int detach_func(int argc, char *argv[]);
166 static int attach_func(int argc, char *argv[]);
167 static int mark_func(int argc, char *argv[]);
168 static int apply_func(int argc, char *argv[]);
169 static int sysboot_func(int argc, char *argv[]);
170 static int sanity_check(char *zone, int cmd_num, boolean_t running,
171 boolean_t unsafe_when_running, boolean_t force);
172 static int cmd_match(char *cmd);
173 static int verify_details(int, char *argv[]);
174 static int verify_brand(zone_dochandle_t, int, char *argv[]);
175 static int invoke_brand_handler(int, char *argv[]);
176
177 static struct cmd cmdtab[] = {
178 { CMD_HELP, "help", SHELP_HELP, help_func },
179 { CMD_BOOT, "boot", SHELP_BOOT, boot_func },
180 { CMD_HALT, "halt", SHELP_HALT, halt_func },
181 { CMD_READY, "ready", SHELP_READY, ready_func },
182 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func },
183 { CMD_LIST, "list", SHELP_LIST, list_func },
184 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func },
185 { CMD_INSTALL, "install", SHELP_INSTALL, install_func },
186 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL,
187 uninstall_func },
188 /* mount and unmount are private commands for admin/install */
189 { CMD_MOUNT, "mount", NULL, mount_func },
190 { CMD_UNMOUNT, "unmount", NULL, unmount_func },
191 { CMD_CLONE, "clone", SHELP_CLONE, clone_func },
192 { CMD_MOVE, "move", SHELP_MOVE, move_func },
193 { CMD_DETACH, "detach", SHELP_DETACH, detach_func },
194 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func },
195 { CMD_MARK, "mark", SHELP_MARK, mark_func },
196 { CMD_APPLY, "apply", NULL, apply_func },
197 { CMD_SYSBOOT, "sysboot", NULL, sysboot_func }
198 };
199
200 /* global variables */
201
215 return (cmdtab[cmd_num].cmd_name);
216 }
217
218 /* This is a separate function because of gettext() wrapping. */
219 static char *
220 long_help(int cmd_num)
221 {
222 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
223 switch (cmd_num) {
224 case CMD_HELP:
225 return (gettext("Print usage message."));
226 case CMD_BOOT:
227 return (gettext("Activates (boots) specified zone. See "
228 "zoneadm(1m) for valid boot\n\targuments."));
229 case CMD_HALT:
230 return (gettext("Halts specified zone, bypassing shutdown "
231 "scripts and removing runtime\n\tresources of the zone."));
232 case CMD_READY:
233 return (gettext("Prepares a zone for running applications but "
234 "does not start any user\n\tprocesses in the zone."));
235 case CMD_REBOOT:
236 return (gettext("Restarts the zone (equivalent to a halt / "
237 "boot sequence).\n\tFails if the zone is not active. "
238 "See zoneadm(1m) for valid boot\n\targuments."));
239 case CMD_LIST:
240 return (gettext("Lists the current zones, or a "
241 "specific zone if indicated. By default,\n\tall "
242 "running zones are listed, though this can be "
243 "expanded to all\n\tinstalled zones with the -i "
244 "option or all configured zones with the\n\t-c "
245 "option. When used with the general -z <zone> and/or -u "
246 "<uuid-match>\n\toptions, lists only the specified "
247 "matching zone, but lists it\n\tregardless of its state, "
248 "and the -i and -c options are disallowed. The\n\t-v "
249 "option can be used to display verbose information: zone "
250 "name, id,\n\tcurrent state, root directory and options. "
251 "The -p option can be used\n\tto request machine-parsable "
252 "output. The -v and -p options are mutually\n\texclusive."
253 " If neither -v nor -p is used, just the zone name is "
254 "listed."));
1517 * user will likely need to do some manual cleanup.
1518 */
1519 return (ZONE_SUBPROC_FATAL);
1520 }
1521
1522 static int
1523 auth_check(char *user, char *zone, int cmd_num)
1524 {
1525 char authname[MAXAUTHS];
1526
1527 switch (cmd_num) {
1528 case CMD_LIST:
1529 case CMD_HELP:
1530 return (Z_OK);
1531 case SOURCE_ZONE:
1532 (void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS);
1533 break;
1534 case CMD_BOOT:
1535 case CMD_HALT:
1536 case CMD_READY:
1537 case CMD_REBOOT:
1538 case CMD_SYSBOOT:
1539 case CMD_VERIFY:
1540 case CMD_INSTALL:
1541 case CMD_UNINSTALL:
1542 case CMD_MOUNT:
1543 case CMD_UNMOUNT:
1544 case CMD_CLONE:
1545 case CMD_MOVE:
1546 case CMD_DETACH:
1547 case CMD_ATTACH:
1548 case CMD_MARK:
1549 case CMD_APPLY:
1550 default:
1551 (void) strlcpy(authname, ZONE_MANAGE_AUTH, MAXAUTHS);
1552 break;
1553 }
1554 (void) strlcat(authname, KV_OBJECT, MAXAUTHS);
1555 (void) strlcat(authname, zone, MAXAUTHS);
1556 if (chkauthattr(authname, user) == 0) {
1579 * zone, the name service knows about it.
1580 * 4b. For some operations which expect a zone not to be running, that it is
1581 * not already running (or ready).
1582 */
1583 static int
1584 sanity_check(char *zone, int cmd_num, boolean_t running,
1585 boolean_t unsafe_when_running, boolean_t force)
1586 {
1587 zone_entry_t *zent;
1588 priv_set_t *privset;
1589 zone_state_t state, min_state;
1590 char kernzone[ZONENAME_MAX];
1591 FILE *fp;
1592
1593 if (getzoneid() != GLOBAL_ZONEID) {
1594 switch (cmd_num) {
1595 case CMD_HALT:
1596 zerror(gettext("use %s to %s this zone."), "halt(1M)",
1597 cmd_to_str(cmd_num));
1598 break;
1599 case CMD_REBOOT:
1600 zerror(gettext("use %s to %s this zone."),
1601 "reboot(1M)", cmd_to_str(cmd_num));
1602 break;
1603 default:
1604 zerror(gettext("must be in the global zone to %s a "
1605 "zone."), cmd_to_str(cmd_num));
1606 break;
1607 }
1608 return (Z_ERR);
1609 }
1610
1611 if ((privset = priv_allocset()) == NULL) {
1612 zerror(gettext("%s failed"), "priv_allocset");
1613 return (Z_ERR);
1614 }
1615
1616 if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1617 zerror(gettext("%s failed"), "getppriv");
1618 priv_freeset(privset);
1808 /*
1809 * zoneadmd should be the one to decide whether or not to proceed,
1810 * so even though it seems that the fourth parameter below should
1811 * perhaps be B_TRUE, it really shouldn't be.
1812 */
1813 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
1814 != Z_OK)
1815 return (Z_ERR);
1816
1817 /*
1818 * Invoke brand-specific handler.
1819 */
1820 if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
1821 return (Z_ERR);
1822
1823 zarg.cmd = Z_HALT;
1824 return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale,
1825 B_TRUE) == 0) ? Z_OK : Z_ERR);
1826 }
1827
1828 static int
1829 reboot_func(int argc, char *argv[])
1830 {
1831 zone_cmd_arg_t zarg;
1832 int arg;
1833
1834 if (zonecfg_in_alt_root()) {
1835 zerror(gettext("cannot reboot zone in alternate root"));
1836 return (Z_ERR);
1837 }
1838
1839 optind = 0;
1840 if ((arg = getopt(argc, argv, "?")) != EOF) {
1841 switch (arg) {
1842 case '?':
1843 sub_usage(SHELP_REBOOT, CMD_REBOOT);
1844 return (optopt == '?' ? Z_OK : Z_USAGE);
1845 default:
1846 sub_usage(SHELP_REBOOT, CMD_REBOOT);
1847 return (Z_USAGE);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * zoneadm is a command interpreter for zone administration. It is all in
29 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
30 * main() calls parse_and_run() which calls cmd_match(), then invokes the
31 * appropriate command's handler function. The rest of the program is the
32 * handler functions and their helper functions.
33 *
34 * Some of the helper functions are used largely to simplify I18N: reducing
35 * the need for translation notes. This is particularly true of many of
36 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
37 * than zerror(gettext("foo failed")) with a translation note indicating
38 * that "foo" need not be translated.
39 */
40
41 #include <stdio.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <signal.h>
114 char *name;
115 int af;
116 };
117
118 /* 0755 is the default directory mode. */
119 #define DEFAULT_DIR_MODE \
120 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
121
122 struct cmd {
123 uint_t cmd_num; /* command number */
124 char *cmd_name; /* command name */
125 char *short_usage; /* short form help */
126 int (*handler)(int argc, char *argv[]); /* function to call */
127
128 };
129
130 #define SHELP_HELP "help"
131 #define SHELP_BOOT "boot [-- boot_arguments]"
132 #define SHELP_HALT "halt"
133 #define SHELP_READY "ready"
134 #define SHELP_SHUTDOWN "shutdown [-r [-- boot_arguments]]"
135 #define SHELP_REBOOT "reboot [-- boot_arguments]"
136 #define SHELP_LIST "list [-cipv]"
137 #define SHELP_VERIFY "verify"
138 #define SHELP_INSTALL "install [brand-specific args]"
139 #define SHELP_UNINSTALL "uninstall [-F] [brand-specific args]"
140 #define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] "\
141 "[brand-specific args] zonename"
142 #define SHELP_MOVE "move zonepath"
143 #define SHELP_DETACH "detach [-n] [brand-specific args]"
144 #define SHELP_ATTACH "attach [-F] [-n <path>] [brand-specific args]"
145 #define SHELP_MARK "mark incomplete"
146
147 #define EXEC_PREFIX "exec "
148 #define EXEC_LEN (strlen(EXEC_PREFIX))
149 #define RMCOMMAND "/usr/bin/rm -rf"
150
151 static int cleanup_zonepath(char *, boolean_t);
152
153
154 static int help_func(int argc, char *argv[]);
155 static int ready_func(int argc, char *argv[]);
156 static int boot_func(int argc, char *argv[]);
157 static int shutdown_func(int argc, char *argv[]);
158 static int halt_func(int argc, char *argv[]);
159 static int reboot_func(int argc, char *argv[]);
160 static int list_func(int argc, char *argv[]);
161 static int verify_func(int argc, char *argv[]);
162 static int install_func(int argc, char *argv[]);
163 static int uninstall_func(int argc, char *argv[]);
164 static int mount_func(int argc, char *argv[]);
165 static int unmount_func(int argc, char *argv[]);
166 static int clone_func(int argc, char *argv[]);
167 static int move_func(int argc, char *argv[]);
168 static int detach_func(int argc, char *argv[]);
169 static int attach_func(int argc, char *argv[]);
170 static int mark_func(int argc, char *argv[]);
171 static int apply_func(int argc, char *argv[]);
172 static int sysboot_func(int argc, char *argv[]);
173 static int sanity_check(char *zone, int cmd_num, boolean_t running,
174 boolean_t unsafe_when_running, boolean_t force);
175 static int cmd_match(char *cmd);
176 static int verify_details(int, char *argv[]);
177 static int verify_brand(zone_dochandle_t, int, char *argv[]);
178 static int invoke_brand_handler(int, char *argv[]);
179
180 static struct cmd cmdtab[] = {
181 { CMD_HELP, "help", SHELP_HELP, help_func },
182 { CMD_BOOT, "boot", SHELP_BOOT, boot_func },
183 { CMD_HALT, "halt", SHELP_HALT, halt_func },
184 { CMD_READY, "ready", SHELP_READY, ready_func },
185 { CMD_SHUTDOWN, "shutdown", SHELP_SHUTDOWN, shutdown_func },
186 { CMD_REBOOT, "reboot", SHELP_REBOOT, reboot_func },
187 { CMD_LIST, "list", SHELP_LIST, list_func },
188 { CMD_VERIFY, "verify", SHELP_VERIFY, verify_func },
189 { CMD_INSTALL, "install", SHELP_INSTALL, install_func },
190 { CMD_UNINSTALL, "uninstall", SHELP_UNINSTALL,
191 uninstall_func },
192 /* mount and unmount are private commands for admin/install */
193 { CMD_MOUNT, "mount", NULL, mount_func },
194 { CMD_UNMOUNT, "unmount", NULL, unmount_func },
195 { CMD_CLONE, "clone", SHELP_CLONE, clone_func },
196 { CMD_MOVE, "move", SHELP_MOVE, move_func },
197 { CMD_DETACH, "detach", SHELP_DETACH, detach_func },
198 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func },
199 { CMD_MARK, "mark", SHELP_MARK, mark_func },
200 { CMD_APPLY, "apply", NULL, apply_func },
201 { CMD_SYSBOOT, "sysboot", NULL, sysboot_func }
202 };
203
204 /* global variables */
205
219 return (cmdtab[cmd_num].cmd_name);
220 }
221
222 /* This is a separate function because of gettext() wrapping. */
223 static char *
224 long_help(int cmd_num)
225 {
226 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
227 switch (cmd_num) {
228 case CMD_HELP:
229 return (gettext("Print usage message."));
230 case CMD_BOOT:
231 return (gettext("Activates (boots) specified zone. See "
232 "zoneadm(1m) for valid boot\n\targuments."));
233 case CMD_HALT:
234 return (gettext("Halts specified zone, bypassing shutdown "
235 "scripts and removing runtime\n\tresources of the zone."));
236 case CMD_READY:
237 return (gettext("Prepares a zone for running applications but "
238 "does not start any user\n\tprocesses in the zone."));
239 case CMD_SHUTDOWN:
240 return (gettext("Gracefully shutdown the zone or reboot if "
241 "the '-r' option is specified.\n\t"
242 "See zoneadm(1m) for valid boot arguments."));
243 case CMD_REBOOT:
244 return (gettext("Restarts the zone (equivalent to a halt / "
245 "boot sequence).\n\tFails if the zone is not active. "
246 "See zoneadm(1m) for valid boot\n\targuments."));
247 case CMD_LIST:
248 return (gettext("Lists the current zones, or a "
249 "specific zone if indicated. By default,\n\tall "
250 "running zones are listed, though this can be "
251 "expanded to all\n\tinstalled zones with the -i "
252 "option or all configured zones with the\n\t-c "
253 "option. When used with the general -z <zone> and/or -u "
254 "<uuid-match>\n\toptions, lists only the specified "
255 "matching zone, but lists it\n\tregardless of its state, "
256 "and the -i and -c options are disallowed. The\n\t-v "
257 "option can be used to display verbose information: zone "
258 "name, id,\n\tcurrent state, root directory and options. "
259 "The -p option can be used\n\tto request machine-parsable "
260 "output. The -v and -p options are mutually\n\texclusive."
261 " If neither -v nor -p is used, just the zone name is "
262 "listed."));
1525 * user will likely need to do some manual cleanup.
1526 */
1527 return (ZONE_SUBPROC_FATAL);
1528 }
1529
1530 static int
1531 auth_check(char *user, char *zone, int cmd_num)
1532 {
1533 char authname[MAXAUTHS];
1534
1535 switch (cmd_num) {
1536 case CMD_LIST:
1537 case CMD_HELP:
1538 return (Z_OK);
1539 case SOURCE_ZONE:
1540 (void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS);
1541 break;
1542 case CMD_BOOT:
1543 case CMD_HALT:
1544 case CMD_READY:
1545 case CMD_SHUTDOWN:
1546 case CMD_REBOOT:
1547 case CMD_SYSBOOT:
1548 case CMD_VERIFY:
1549 case CMD_INSTALL:
1550 case CMD_UNINSTALL:
1551 case CMD_MOUNT:
1552 case CMD_UNMOUNT:
1553 case CMD_CLONE:
1554 case CMD_MOVE:
1555 case CMD_DETACH:
1556 case CMD_ATTACH:
1557 case CMD_MARK:
1558 case CMD_APPLY:
1559 default:
1560 (void) strlcpy(authname, ZONE_MANAGE_AUTH, MAXAUTHS);
1561 break;
1562 }
1563 (void) strlcat(authname, KV_OBJECT, MAXAUTHS);
1564 (void) strlcat(authname, zone, MAXAUTHS);
1565 if (chkauthattr(authname, user) == 0) {
1588 * zone, the name service knows about it.
1589 * 4b. For some operations which expect a zone not to be running, that it is
1590 * not already running (or ready).
1591 */
1592 static int
1593 sanity_check(char *zone, int cmd_num, boolean_t running,
1594 boolean_t unsafe_when_running, boolean_t force)
1595 {
1596 zone_entry_t *zent;
1597 priv_set_t *privset;
1598 zone_state_t state, min_state;
1599 char kernzone[ZONENAME_MAX];
1600 FILE *fp;
1601
1602 if (getzoneid() != GLOBAL_ZONEID) {
1603 switch (cmd_num) {
1604 case CMD_HALT:
1605 zerror(gettext("use %s to %s this zone."), "halt(1M)",
1606 cmd_to_str(cmd_num));
1607 break;
1608 case CMD_SHUTDOWN:
1609 zerror(gettext("use %s to %s this zone."),
1610 "shutdown(1M)", cmd_to_str(cmd_num));
1611 break;
1612 case CMD_REBOOT:
1613 zerror(gettext("use %s to %s this zone."),
1614 "reboot(1M)", cmd_to_str(cmd_num));
1615 break;
1616 default:
1617 zerror(gettext("must be in the global zone to %s a "
1618 "zone."), cmd_to_str(cmd_num));
1619 break;
1620 }
1621 return (Z_ERR);
1622 }
1623
1624 if ((privset = priv_allocset()) == NULL) {
1625 zerror(gettext("%s failed"), "priv_allocset");
1626 return (Z_ERR);
1627 }
1628
1629 if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1630 zerror(gettext("%s failed"), "getppriv");
1631 priv_freeset(privset);
1821 /*
1822 * zoneadmd should be the one to decide whether or not to proceed,
1823 * so even though it seems that the fourth parameter below should
1824 * perhaps be B_TRUE, it really shouldn't be.
1825 */
1826 if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
1827 != Z_OK)
1828 return (Z_ERR);
1829
1830 /*
1831 * Invoke brand-specific handler.
1832 */
1833 if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
1834 return (Z_ERR);
1835
1836 zarg.cmd = Z_HALT;
1837 return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale,
1838 B_TRUE) == 0) ? Z_OK : Z_ERR);
1839 }
1840
1841 static int
1842 shutdown_func(int argc, char *argv[])
1843 {
1844 zone_cmd_arg_t zarg;
1845 int arg;
1846 boolean_t reboot = B_FALSE;
1847
1848 zarg.cmd = Z_SHUTDOWN;
1849
1850 if (zonecfg_in_alt_root()) {
1851 zerror(gettext("cannot shut down zone in alternate root"));
1852 return (Z_ERR);
1853 }
1854
1855 optind = 0;
1856 while ((arg = getopt(argc, argv, "?r")) != EOF) {
1857 switch (arg) {
1858 case '?':
1859 sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN);
1860 return (optopt == '?' ? Z_OK : Z_USAGE);
1861 case 'r':
1862 reboot = B_TRUE;
1863 break;
1864 default:
1865 sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN);
1866 return (Z_USAGE);
1867 }
1868 }
1869
1870 zarg.bootbuf[0] = '\0';
1871 for (; optind < argc; optind++) {
1872 if (strlcat(zarg.bootbuf, argv[optind],
1873 sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1874 zerror(gettext("Boot argument list too long"));
1875 return (Z_ERR);
1876 }
1877 if (optind < argc - 1)
1878 if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1879 sizeof (zarg.bootbuf)) {
1880 zerror(gettext("Boot argument list too long"));
1881 return (Z_ERR);
1882 }
1883 }
1884
1885 /*
1886 * zoneadmd should be the one to decide whether or not to proceed,
1887 * so even though it seems that the third parameter below should
1888 * perhaps be B_TRUE, it really shouldn't be.
1889 */
1890 if (sanity_check(target_zone, CMD_SHUTDOWN, B_TRUE, B_FALSE, B_FALSE)
1891 != Z_OK)
1892 return (Z_ERR);
1893
1894 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != Z_OK)
1895 return (Z_ERR);
1896
1897 if (reboot) {
1898 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE,
1899 B_FALSE) != Z_OK)
1900 return (Z_ERR);
1901
1902 zarg.cmd = Z_BOOT;
1903 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale,
1904 B_TRUE) != Z_OK)
1905 return (Z_ERR);
1906 }
1907 return (Z_OK);
1908 }
1909
1910 static int
1911 reboot_func(int argc, char *argv[])
1912 {
1913 zone_cmd_arg_t zarg;
1914 int arg;
1915
1916 if (zonecfg_in_alt_root()) {
1917 zerror(gettext("cannot reboot zone in alternate root"));
1918 return (Z_ERR);
1919 }
1920
1921 optind = 0;
1922 if ((arg = getopt(argc, argv, "?")) != EOF) {
1923 switch (arg) {
1924 case '?':
1925 sub_usage(SHELP_REBOOT, CMD_REBOOT);
1926 return (optopt == '?' ? Z_OK : Z_USAGE);
1927 default:
1928 sub_usage(SHELP_REBOOT, CMD_REBOOT);
1929 return (Z_USAGE);
|