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