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