xref: /illumos-gate/usr/src/cmd/stmfsvc/stmfsvc.c (revision e3ae4b35c024af1196582063ecee3ab79367227d)
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  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <strings.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <libintl.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <getopt.h>
36 #include <cmdparse.h>
37 #include <libstmf.h>
38 #include <signal.h>
39 #include <pthread.h>
40 #include <locale.h>
41 
42 static int svcStart(int, char **, cmdOptions_t *, void *);
43 static int svcStop(int, char **, cmdOptions_t *, void *);
44 static int online();
45 
46 /*
47  *  MAJOR - This should only change when there is an incompatible change made
48  *  to the interfaces or the output.
49  *
50  *  MINOR - This should change whenever there is a new command or new feature
51  *  with no incompatible change.
52  */
53 #define	VERSION_STRING_MAJOR	    "1"
54 #define	VERSION_STRING_MINOR	    "0"
55 #define	VERSION_STRING_MAX_LEN	    10
56 
57 /* 10 ms sleep in nanoseconds */
58 #define	TEN_MS_NANOSLEEP  10000000
59 
60 /* tables set up based on cmdparse instructions */
61 
62 /* add new options here */
63 optionTbl_t longOptions[] = {
64 	{NULL, 0, 0, 0}
65 };
66 
67 /*
68  * Add new subcommands here
69  */
70 subCommandProps_t subcommands[] = {
71 	{"start", svcStart, NULL, NULL, NULL, OPERAND_NONE, NULL},
72 	{"stop", svcStop, NULL, NULL, NULL, OPERAND_NONE, NULL},
73 	{NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL}
74 };
75 
76 /* globals */
77 char *cmdName;
78 
79 /*
80  * svcStop
81  *
82  * Offlines the stmf service
83  *
84  */
85 /*ARGSUSED*/
86 static int
87 svcStop(int operandLen, char *operands[], cmdOptions_t *options,
88     void *args)
89 {
90 	int stmfRet;
91 	int ret = 0;
92 	stmfState state;
93 	boolean_t serviceOffline = B_FALSE;
94 	struct timespec rqtp;
95 
96 	bzero(&rqtp, sizeof (rqtp));
97 
98 	rqtp.tv_nsec = TEN_MS_NANOSLEEP;
99 
100 	if ((stmfRet = stmfOffline()) != STMF_STATUS_SUCCESS) {
101 		switch (stmfRet) {
102 			case STMF_ERROR_PERM:
103 				(void) fprintf(stderr, "%s: %s\n", cmdName,
104 				    gettext("permission denied"));
105 				break;
106 			case STMF_ERROR_SERVICE_NOT_FOUND:
107 				(void) fprintf(stderr, "%s: %s\n", cmdName,
108 				    gettext("STMF service not found"));
109 				break;
110 			case STMF_ERROR_SERVICE_OFFLINE:
111 				(void) fprintf(stderr, "%s: %s\n", cmdName,
112 				    gettext("STMF service already offline"));
113 				break;
114 			default:
115 				(void) fprintf(stderr, "%s: %s\n", cmdName,
116 				    gettext("unable to offline service"));
117 				break;
118 		}
119 		return (1);
120 	}
121 
122 	/* wait for service offline */
123 	while (!serviceOffline) {
124 		stmfRet = stmfGetState(&state);
125 		if (stmfRet != STMF_STATUS_SUCCESS) {
126 			ret = 1;
127 			break;
128 		}
129 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
130 			serviceOffline = B_TRUE;
131 		} else {
132 			(void) nanosleep(&rqtp, NULL);
133 		}
134 	}
135 
136 	return (ret);
137 }
138 
139 /*
140  * loadConfig
141  *
142  * Loads the stmf config from the SMF repository
143  *
144  */
145 /*ARGSUSED*/
146 static int
147 svcStart(int operandLen, char *operands[], cmdOptions_t *options,
148     void *args)
149 {
150 	int stmfRet;
151 	int ret = 0;
152 	(void) stmfLoadStmfProps();
153 	if ((stmfRet = stmfLoadConfig()) != STMF_STATUS_SUCCESS) {
154 		switch (stmfRet) {
155 			case STMF_ERROR_PERM:
156 				(void) fprintf(stderr, "%s: %s\n", cmdName,
157 				    gettext("permission denied"));
158 				break;
159 			case STMF_ERROR_SERVICE_NOT_FOUND:
160 				(void) fprintf(stderr, "%s: %s\n", cmdName,
161 				    gettext("STMF service not found"));
162 				break;
163 			case STMF_ERROR_SERVICE_ONLINE:
164 				(void) fprintf(stderr, "%s: %s\n", cmdName,
165 				    gettext("STMF service must be offline"));
166 				break;
167 			default:
168 				(void) fprintf(stderr, "%s: %s\n", cmdName,
169 				    gettext("Unable to load the configuration. "
170 				    "See /var/adm/messages for details"));
171 				(void) fprintf(stderr, "%s: %s\n", cmdName,
172 				    gettext("For information on reverting the "
173 				    "stmf:default instance to a previously "
174 				    "running configuration see the man page "
175 				    "for svccfg(8)"));
176 				(void) fprintf(stderr, "%s: %s\n", cmdName,
177 				    gettext("After reverting the instance "
178 				    "you must clear the service maintenance "
179 				    "state. See the man page for svcadm(8)"));
180 				break;
181 		}
182 		return (1);
183 	}
184 	ret = online();
185 	return (ret);
186 
187 }
188 
189 /*
190  * online
191  *
192  * Onlines the stmf service
193  *
194  */
195 /*ARGSUSED*/
196 static int
197 online()
198 {
199 	int stmfRet;
200 	int ret = 0;
201 	stmfState state;
202 	boolean_t serviceOnline = B_FALSE;
203 	struct timespec rqtp;
204 
205 	bzero(&rqtp, sizeof (rqtp));
206 
207 	rqtp.tv_nsec = TEN_MS_NANOSLEEP;
208 
209 	if ((stmfRet = stmfOnline()) != STMF_STATUS_SUCCESS) {
210 		switch (stmfRet) {
211 			case STMF_ERROR_PERM:
212 				(void) fprintf(stderr, "%s: %s\n", cmdName,
213 				    gettext("permission denied"));
214 				break;
215 			case STMF_ERROR_SERVICE_NOT_FOUND:
216 				(void) fprintf(stderr, "%s: %s\n", cmdName,
217 				    gettext("STMF service not found"));
218 				break;
219 			case STMF_ERROR_SERVICE_ONLINE:
220 				(void) fprintf(stderr, "%s: %s\n", cmdName,
221 				    gettext("STMF service already online"));
222 				break;
223 			default:
224 				(void) fprintf(stderr, "%s: %s\n", cmdName,
225 				    gettext("unable to online service"));
226 				break;
227 		}
228 		return (1);
229 	}
230 
231 	/* wait for service online */
232 	while (!serviceOnline) {
233 		stmfRet = stmfGetState(&state);
234 		if (stmfRet != STMF_STATUS_SUCCESS) {
235 			ret = 1;
236 			break;
237 		}
238 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
239 			serviceOnline = B_TRUE;
240 		} else {
241 			(void) nanosleep(&rqtp, NULL);
242 		}
243 	}
244 
245 	return (ret);
246 }
247 
248 
249 /*
250  * input:
251  *  execFullName - exec name of program (argv[0])
252  *
253  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
254  *  (changed name to lowerCamelCase to keep consistent with this file)
255  *
256  * Returns:
257  *  command name portion of execFullName
258  */
259 static char *
260 getExecBasename(char *execFullname)
261 {
262 	char *lastSlash, *execBasename;
263 
264 	/* guard against '/' at end of command invocation */
265 	for (;;) {
266 		lastSlash = strrchr(execFullname, '/');
267 		if (lastSlash == NULL) {
268 			execBasename = execFullname;
269 			break;
270 		} else {
271 			execBasename = lastSlash + 1;
272 			if (*execBasename == '\0') {
273 				*lastSlash = '\0';
274 				continue;
275 			}
276 			break;
277 		}
278 	}
279 	return (execBasename);
280 }
281 
282 int
283 main(int argc, char *argv[])
284 {
285 	synTables_t synTables;
286 	char versionString[VERSION_STRING_MAX_LEN];
287 	int ret;
288 	int funcRet;
289 	void *subcommandArgs = NULL;
290 
291 	(void) setlocale(LC_ALL, "");
292 	/* set global command name */
293 	cmdName = getExecBasename(argv[0]);
294 
295 	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
296 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
297 	synTables.versionString = versionString;
298 	synTables.longOptionTbl = &longOptions[0];
299 	synTables.subCommandPropsTbl = &subcommands[0];
300 
301 	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
302 	if (ret != 0) {
303 		return (ret);
304 	}
305 
306 	return (funcRet);
307 } /* end main */
308