import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / i386 / sys / uadmin.c
blobdd132d3aa14f3ab246164fc6f0a42b3e83c4a42f
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * Wrapper function to implement reboot w/ arguments on x86
30 * platforms. Extract reboot arguments and place them in
31 * in a transient entry. All other commands are passed through.
33 #include "lint.h"
34 #include "mtlib.h"
35 #include <fcntl.h>
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/uadmin.h>
42 #include <unistd.h>
43 #include <strings.h>
44 #include <pthread.h>
45 #include <zone.h>
46 #include <libscf.h>
47 #include <thread.h>
48 #include <dlfcn.h>
49 #include <atomic.h>
52 * Pull in the following three interfaces from libscf without introducing
53 * a dependency on it, which since libscf depends on libc would be circular:
55 * scf_simple_prop_get
56 * scf_simple_prop_next_boolean
57 * scf_simple_prop_free
59 typedef scf_simple_prop_t *(*scf_simple_prop_get_t)(scf_handle_t *,
60 const char *, const char *, const char *);
61 static scf_simple_prop_get_t real_scf_simple_prop_get = NULL;
62 typedef uint8_t *(*scf_simple_prop_next_boolean_t)(scf_simple_prop_t *);
63 static scf_simple_prop_next_boolean_t real_scf_simple_prop_next_boolean = NULL;
64 typedef void (*scf_simple_prop_free_t)(scf_simple_prop_t *);
65 static scf_simple_prop_free_t real_scf_simple_prop_free = NULL;
66 static mutex_t scf_lock = DEFAULTMUTEX;
68 static void
69 load_scf(void)
71 void *scf_handle = dlopen("libscf.so.1", RTLD_LAZY);
72 scf_simple_prop_get_t scf_simple_prop_get = (scf_handle == NULL)? NULL :
73 (scf_simple_prop_get_t)dlsym(scf_handle, "scf_simple_prop_get");
74 scf_simple_prop_next_boolean_t scf_simple_prop_next_boolean =
75 (scf_handle == NULL)? NULL :
76 (scf_simple_prop_next_boolean_t)dlsym(scf_handle,
77 "scf_simple_prop_next_boolean");
78 scf_simple_prop_free_t scf_simple_prop_free =
79 (scf_handle == NULL)? NULL :
80 (scf_simple_prop_free_t)dlsym(scf_handle, "scf_simple_prop_free");
82 lmutex_lock(&scf_lock);
83 if (real_scf_simple_prop_get == NULL ||
84 real_scf_simple_prop_next_boolean == NULL ||
85 real_scf_simple_prop_free == NULL) {
86 if (scf_simple_prop_get == NULL)
87 real_scf_simple_prop_get = (scf_simple_prop_get_t)(-1);
88 else {
89 real_scf_simple_prop_get = scf_simple_prop_get;
90 scf_handle = NULL; /* don't dlclose it */
92 if (scf_simple_prop_next_boolean == NULL)
93 real_scf_simple_prop_next_boolean =
94 (scf_simple_prop_next_boolean_t)(-1);
95 else {
96 real_scf_simple_prop_next_boolean =
97 scf_simple_prop_next_boolean;
98 scf_handle = NULL; /* don't dlclose it */
100 if (scf_simple_prop_free == NULL)
101 real_scf_simple_prop_free =
102 (scf_simple_prop_free_t)(-1);
103 else {
104 real_scf_simple_prop_free = scf_simple_prop_free;
105 scf_handle = NULL; /* don't dlclose it */
107 membar_producer();
109 lmutex_unlock(&scf_lock);
111 if (scf_handle)
112 (void) dlclose(scf_handle);
115 static void
116 check_archive_update(void)
118 scf_simple_prop_t *prop = NULL;
119 boolean_t update_flag = B_FALSE;
120 char *fmri = "svc:/system/boot-config:default";
121 uint8_t *ret_val = NULL;
123 if (real_scf_simple_prop_get == NULL ||
124 real_scf_simple_prop_next_boolean == NULL ||
125 real_scf_simple_prop_free == NULL) {
126 load_scf();
128 if (real_scf_simple_prop_get == (scf_simple_prop_get_t)(-1) ||
129 real_scf_simple_prop_next_boolean ==
130 (scf_simple_prop_next_boolean_t)(-1) ||
131 real_scf_simple_prop_free == (scf_simple_prop_free_t)(-1)) {
132 return;
135 prop = real_scf_simple_prop_get(NULL, fmri, "config",
136 "uadmin_boot_archive_sync");
137 if (prop) {
138 if ((ret_val = real_scf_simple_prop_next_boolean(prop)) !=
139 NULL)
140 update_flag = (*ret_val == 0) ? B_FALSE :
141 B_TRUE;
142 real_scf_simple_prop_free(prop);
145 if (update_flag == B_TRUE)
146 (void) system("/sbin/bootadm update-archive");
149 static int
150 legal_arg(char *bargs)
152 int i;
154 for (i = 0; i < BOOTARGS_MAX; i++, bargs++) {
155 if (*bargs == 0 && i > 0)
156 return (i);
157 if (!isprint(*bargs))
158 break;
160 return (-1);
163 static char quote[] = "\'";
166 uadmin(int cmd, int fcn, uintptr_t mdep)
168 extern int __uadmin(int cmd, int fcn, uintptr_t mdep);
169 char *bargs, cmdbuf[256];
170 struct stat sbuf;
171 char *altroot;
173 bargs = (char *)mdep;
175 if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID &&
176 (cmd == A_SHUTDOWN || cmd == A_REBOOT)) {
177 int off = 0;
179 switch (fcn) {
180 case AD_IBOOT:
181 case AD_SBOOT:
182 case AD_SIBOOT:
184 * These functions fabricate appropriate bootargs.
185 * If bootargs are passed in, map these functions
186 * to AD_BOOT.
188 if (bargs == 0) {
189 switch (fcn) {
190 case AD_IBOOT:
191 bargs = "-a";
192 break;
193 case AD_SBOOT:
194 bargs = "-s";
195 break;
196 case AD_SIBOOT:
197 bargs = "-sa";
198 break;
201 /*FALLTHROUGH*/
202 case AD_BOOT:
203 case AD_FASTREBOOT:
204 if (bargs == 0)
205 break; /* no args */
206 if (legal_arg(bargs) < 0)
207 break; /* bad args */
209 /* avoid cancellation in system() */
210 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
211 NULL);
213 altroot = "";
215 if (fcn == AD_FASTREBOOT) {
216 char *newarg, *head;
217 char bargs_scratch[BOOTARGS_MAX];
219 bzero(bargs_scratch, BOOTARGS_MAX);
221 bcopy(bargs, bargs_scratch, strlen(bargs));
222 head = bargs_scratch;
223 newarg = strtok(bargs_scratch, " ");
225 if (newarg == NULL || newarg[0] == '-')
226 break;
228 /* First argument is rootdir */
229 if (strncmp(&newarg[strlen(newarg)-4],
230 "unix", 4) != 0) {
231 newarg = strtok(NULL, " ");
232 off = newarg - head;
236 * If we are using alternate root via
237 * mountpoint or a different BE, don't
238 * bother to update the temp menu entry.
240 if (off > 0)
241 break;
244 /* are we rebooting to a boot menu entry? */
245 if (isdigit(bargs[0])) {
246 int entry = strtol(bargs, NULL, 10);
247 (void) snprintf(cmdbuf, sizeof (cmdbuf),
248 "/sbin/bootadm set-menu %sdefault=%d",
249 altroot, entry);
250 } else {
251 (void) snprintf(cmdbuf, sizeof (cmdbuf),
252 "/sbin/bootadm -m update_temp %s"
253 "-o %s%s%s", altroot, quote,
254 &bargs[off], quote);
256 (void) system(cmdbuf);
258 check_archive_update();
260 return (__uadmin(cmd, fcn, mdep));