uadmin.c revision 9160:1517e6edbc6f
1/*
2 * CDDL HEADER START
3 *
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 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28/*
29 * Wrapper function to implement reboot w/ arguments on x86
30 * platforms. Extract reboot arguments and place them in
31 * in a transient entry in /[stub]boot/grub/menu.lst
32 * All other commands are passed through.
33 */
34
35#include "lint.h"
36#include <fcntl.h>
37#include <ctype.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <sys/uadmin.h>
43#include <unistd.h>
44#include <strings.h>
45#include <pthread.h>
46#include <zone.h>
47
48static int
49legal_arg(char *bargs)
50{
51	int i;
52
53	for (i = 0; i < BOOTARGS_MAX; i++, bargs++) {
54		if (*bargs == 0 && i > 0)
55			return (i);
56		if (!isprint(*bargs))
57			break;
58	}
59	return (-1);
60}
61
62static char quote[] = "\'";
63
64int
65uadmin(int cmd, int fcn, uintptr_t mdep)
66{
67	extern int __uadmin(int cmd, int fcn, uintptr_t mdep);
68	char *bargs, cmdbuf[256];
69	struct stat sbuf;
70	char *altroot;
71
72	bargs = (char *)mdep;
73
74	if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID &&
75	    (cmd == A_SHUTDOWN || cmd == A_REBOOT)) {
76		int off = 0;
77
78		switch (fcn) {
79		case AD_IBOOT:
80		case AD_SBOOT:
81		case AD_SIBOOT:
82			/*
83			 * These functions fabricate appropriate bootargs.
84			 * If bootargs are passed in, map these functions
85			 * to AD_BOOT.
86			 */
87			if (bargs == 0) {
88				switch (fcn) {
89				case AD_IBOOT:
90					bargs = "-a";
91					break;
92				case AD_SBOOT:
93					bargs = "-s";
94					break;
95				case AD_SIBOOT:
96					bargs = "-sa";
97					break;
98				}
99			}
100			/*FALLTHROUGH*/
101		case AD_BOOT:
102		case AD_FASTREBOOT:
103			if (bargs == 0)
104				break;	/* no args */
105			if (legal_arg(bargs) < 0)
106				break;	/* bad args */
107
108			/* avoid cancellation in system() */
109			(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
110			    NULL);
111
112			/* check for /stubboot */
113			if (stat("/stubboot/boot/grub/menu.lst", &sbuf) == 0) {
114				altroot = "-R /stubboot ";
115			} else {
116				altroot = "";
117			}
118
119			if (fcn == AD_FASTREBOOT) {
120				char *newarg, *head;
121				char bargs_scratch[BOOTARGS_MAX];
122
123				bzero(bargs_scratch, BOOTARGS_MAX);
124
125				bcopy(bargs, bargs_scratch, strlen(bargs));
126				head = bargs_scratch;
127				newarg = strtok(bargs_scratch, " ");
128
129				if (newarg == NULL || newarg[0] == '-')
130					break;
131
132				/* First argument is rootdir */
133				if (strncmp(&newarg[strlen(newarg)-4],
134				    "unix", 4) != 0) {
135					newarg = strtok(NULL, " ");
136					off = newarg - head;
137				}
138
139				/*
140				 * If we are using alternate root via
141				 * mountpoint or a different BE, don't
142				 * bother to update the temp menu entry.
143				 */
144				if (off > 0)
145					break;
146			}
147
148			/* are we rebooting to a GRUB menu entry? */
149			if (isdigit(bargs[0])) {
150				int entry = strtol(bargs, NULL, 10);
151				(void) snprintf(cmdbuf, sizeof (cmdbuf),
152				    "/sbin/bootadm set-menu %sdefault=%d",
153				    altroot, entry);
154			} else {
155				(void) snprintf(cmdbuf, sizeof (cmdbuf),
156				    "/sbin/bootadm -m update_temp %s"
157				    "-o %s%s%s", altroot, quote,
158				    &bargs[off], quote);
159			}
160			(void) system(cmdbuf);
161		}
162	}
163
164	return (__uadmin(cmd, fcn, mdep));
165}
166