xref: /illumos-gate/usr/src/cmd/stmfsvc/stmfsvc.c (revision bdf0047c9427cca40961a023475891c898579c37)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <strings.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <libintl.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <getopt.h>
37 #include <cmdparse.h>
38 #include <libstmf.h>
39 #include <signal.h>
40 #include <pthread.h>
41 #include <locale.h>
42 
43 static int svcStart(int, char **, cmdOptions_t *, void *);
44 static int svcStop(int, char **, cmdOptions_t *, void *);
45 static int online();
46 
47 /*
48  *  MAJOR - This should only change when there is an incompatible change made
49  *  to the interfaces or the output.
50  *
51  *  MINOR - This should change whenever there is a new command or new feature
52  *  with no incompatible change.
53  */
54 #define	VERSION_STRING_MAJOR	    "1"
55 #define	VERSION_STRING_MINOR	    "0"
56 #define	VERSION_STRING_MAX_LEN	    10
57 
58 /* 10 ms sleep in nanoseconds */
59 #define	TEN_MS_NANOSLEEP  10000000
60 
61 /* tables set up based on cmdparse instructions */
62 
63 /* add new options here */
64 optionTbl_t longOptions[] = {
65 	{NULL, 0, 0, 0}
66 };
67 
68 /*
69  * Add new subcommands here
70  */
71 subCommandProps_t subcommands[] = {
72 	{"start", svcStart, NULL, NULL, NULL, OPERAND_NONE, NULL},
73 	{"stop", svcStop, NULL, NULL, NULL, OPERAND_NONE, NULL},
74 	{NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
75 };
76 
77 /* globals */
78 char *cmdName;
79 
80 /*
81  * svcStop
82  *
83  * Offlines the stmf service
84  *
85  */
86 /*ARGSUSED*/
87 static int
88 svcStop(int operandLen, char *operands[], cmdOptions_t *options,
89     void *args)
90 {
91 	int stmfRet;
92 	int ret = 0;
93 	stmfState state;
94 	boolean_t serviceOffline = B_FALSE;
95 	struct timespec rqtp;
96 
97 	bzero(&rqtp, sizeof (rqtp));
98 
99 	rqtp.tv_nsec = TEN_MS_NANOSLEEP;
100 
101 	if ((stmfRet = stmfOffline()) != STMF_STATUS_SUCCESS) {
102 		switch (stmfRet) {
103 			case STMF_ERROR_PERM:
104 				(void) fprintf(stderr, "%s: %s\n", cmdName,
105 				    gettext("permission denied"));
106 				break;
107 			case STMF_ERROR_SERVICE_NOT_FOUND:
108 				(void) fprintf(stderr, "%s: %s\n", cmdName,
109 				    gettext("STMF service not found"));
110 				break;
111 			case STMF_ERROR_SERVICE_OFFLINE:
112 				(void) fprintf(stderr, "%s: %s\n", cmdName,
113 				    gettext("STMF service already offline"));
114 				break;
115 			default:
116 				(void) fprintf(stderr, "%s: %s\n", cmdName,
117 				    gettext("unable to offline service"));
118 				break;
119 		}
120 		return (1);
121 	}
122 
123 	/* wait for service offline */
124 	while (!serviceOffline) {
125 		stmfRet = stmfGetState(&state);
126 		if (stmfRet != STMF_STATUS_SUCCESS) {
127 			ret = 1;
128 			break;
129 		}
130 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
131 			serviceOffline = B_TRUE;
132 		} else {
133 			(void) nanosleep(&rqtp, NULL);
134 		}
135 	}
136 
137 	return (ret);
138 }
139 
140 /*
141  * loadConfig
142  *
143  * Loads the stmf config from the SMF repository
144  *
145  */
146 /*ARGSUSED*/
147 static int
148 svcStart(int operandLen, char *operands[], cmdOptions_t *options,
149     void *args)
150 {
151 	int stmfRet;
152 	int ret = 0;
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(1M)"));
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(1M)"));
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