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