xref: /illumos-gate/usr/src/cmd/stmfsvc/stmfsvc.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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 2008 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 config"));
170 				break;
171 		}
172 		return (1);
173 	}
174 	ret = online();
175 	return (ret);
176 
177 }
178 
179 /*
180  * online
181  *
182  * Onlines the stmf service
183  *
184  */
185 /*ARGSUSED*/
186 static int
187 online()
188 {
189 	int stmfRet;
190 	int ret = 0;
191 	stmfState state;
192 	boolean_t serviceOnline = B_FALSE;
193 	struct timespec rqtp;
194 
195 	bzero(&rqtp, sizeof (rqtp));
196 
197 	rqtp.tv_nsec = TEN_MS_NANOSLEEP;
198 
199 	if ((stmfRet = stmfOnline()) != STMF_STATUS_SUCCESS) {
200 		switch (stmfRet) {
201 			case STMF_ERROR_PERM:
202 				(void) fprintf(stderr, "%s: %s\n", cmdName,
203 				    gettext("permission denied"));
204 				break;
205 			case STMF_ERROR_SERVICE_NOT_FOUND:
206 				(void) fprintf(stderr, "%s: %s\n", cmdName,
207 				    gettext("STMF service not found"));
208 				break;
209 			case STMF_ERROR_SERVICE_ONLINE:
210 				(void) fprintf(stderr, "%s: %s\n", cmdName,
211 				    gettext("STMF service already online"));
212 				break;
213 			default:
214 				(void) fprintf(stderr, "%s: %s\n", cmdName,
215 				    gettext("unable to online service"));
216 				break;
217 		}
218 		return (1);
219 	}
220 
221 	/* wait for service online */
222 	while (!serviceOnline) {
223 		stmfRet = stmfGetState(&state);
224 		if (stmfRet != STMF_STATUS_SUCCESS) {
225 			ret = 1;
226 			break;
227 		}
228 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
229 			serviceOnline = B_TRUE;
230 		} else {
231 			(void) nanosleep(&rqtp, NULL);
232 		}
233 	}
234 
235 	return (ret);
236 }
237 
238 
239 /*
240  * input:
241  *  execFullName - exec name of program (argv[0])
242  *
243  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
244  *  (changed name to lowerCamelCase to keep consistent with this file)
245  *
246  * Returns:
247  *  command name portion of execFullName
248  */
249 static char *
250 getExecBasename(char *execFullname)
251 {
252 	char *lastSlash, *execBasename;
253 
254 	/* guard against '/' at end of command invocation */
255 	for (;;) {
256 		lastSlash = strrchr(execFullname, '/');
257 		if (lastSlash == NULL) {
258 			execBasename = execFullname;
259 			break;
260 		} else {
261 			execBasename = lastSlash + 1;
262 			if (*execBasename == '\0') {
263 				*lastSlash = '\0';
264 				continue;
265 			}
266 			break;
267 		}
268 	}
269 	return (execBasename);
270 }
271 
272 int
273 main(int argc, char *argv[])
274 {
275 	synTables_t synTables;
276 	char versionString[VERSION_STRING_MAX_LEN];
277 	int ret;
278 	int funcRet;
279 	void *subcommandArgs = NULL;
280 
281 	(void) setlocale(LC_ALL, "");
282 	/* set global command name */
283 	cmdName = getExecBasename(argv[0]);
284 
285 	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
286 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
287 	synTables.versionString = versionString;
288 	synTables.longOptionTbl = &longOptions[0];
289 	synTables.subCommandPropsTbl = &subcommands[0];
290 
291 	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
292 	if (ret != 0) {
293 		return (ret);
294 	}
295 
296 	return (funcRet);
297 } /* end main */
298