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 <strings.h> 27 #include <limits.h> 28 #include <stdlib.h> 29 #include <stdarg.h> 30 #include <stdio.h> 31 #include <errno.h> 32 33 #include <fmadm.h> 34 35 static const char *g_pname; 36 static fmd_adm_t *g_adm; 37 static int g_quiet; 38 39 /*PRINTFLIKE1*/ 40 void 41 note(const char *format, ...) 42 { 43 va_list ap; 44 45 if (g_quiet) 46 return; /* suppress notices if -q specified */ 47 48 (void) fprintf(stdout, "%s: ", g_pname); 49 va_start(ap, format); 50 (void) vfprintf(stdout, format, ap); 51 va_end(ap); 52 } 53 54 static void 55 vwarn(const char *format, va_list ap) 56 { 57 int err = errno; 58 59 (void) fprintf(stderr, "%s: ", g_pname); 60 61 if (format != NULL) 62 (void) vfprintf(stderr, format, ap); 63 64 errno = err; /* restore errno for fmd_adm_errmsg() */ 65 66 if (format == NULL) 67 (void) fprintf(stderr, "%s\n", fmd_adm_errmsg(g_adm)); 68 else if (strchr(format, '\n') == NULL) 69 (void) fprintf(stderr, ": %s\n", fmd_adm_errmsg(g_adm)); 70 } 71 72 /*PRINTFLIKE1*/ 73 void 74 warn(const char *format, ...) 75 { 76 va_list ap; 77 78 va_start(ap, format); 79 vwarn(format, ap); 80 va_end(ap); 81 } 82 83 /*PRINTFLIKE1*/ 84 void 85 die(const char *format, ...) 86 { 87 va_list ap; 88 89 va_start(ap, format); 90 vwarn(format, ap); 91 va_end(ap); 92 93 fmd_adm_close(g_adm); 94 exit(FMADM_EXIT_ERROR); 95 } 96 97 static const struct cmd { 98 int (*cmd_func)(fmd_adm_t *, int, char *[]); 99 const char *cmd_name; 100 const char *cmd_usage; 101 const char *cmd_desc; 102 } cmds[] = { 103 { cmd_config, "config", NULL, "display fault manager configuration" }, 104 { cmd_faulty, "faulty", "[-afgiprsv] [-u <uuid>] [-n <max_fault>]", 105 "display list of faulty resources" }, 106 { cmd_flush, "flush", "<fmri> ...", "flush cached state for resource" }, 107 { cmd_gc, "gc", "<module>", NULL }, 108 { cmd_load, "load", "<path>", "load specified fault manager module" }, 109 { cmd_repair, "repair", "<fmri>|label|<uuid>", NULL }, 110 { cmd_repaired, "repaired", "<fmri>|label>", 111 "notify fault manager that resource has been repaired" }, 112 { cmd_acquit, "acquit", "<fmri> [<uuid>] | label [<uuid>] | <uuid>", 113 "acquit resource or acquit case" }, 114 { cmd_replaced, "replaced", "<fmri>|label", 115 "notify fault manager that resource has been replaced" }, 116 { cmd_reset, "reset", "[-s serd] <module>", "reset module or sub-component" }, 117 { cmd_rotate, "rotate", "<logname>", "rotate log file" }, 118 { cmd_unload, "unload", "<module>", "unload specified fault manager module" }, 119 { NULL, NULL, NULL } 120 }; 121 122 static int 123 usage(FILE *fp) 124 { 125 const struct cmd *cp; 126 char buf[256]; 127 128 (void) fprintf(fp, 129 "Usage: %s [-P prog] [-q] [cmd [args ... ]]\n\n", g_pname); 130 131 for (cp = cmds; cp->cmd_name != NULL; cp++) { 132 if (cp->cmd_desc == NULL) 133 continue; 134 135 if (cp->cmd_usage != NULL) { 136 (void) snprintf(buf, sizeof (buf), "%s %s %s", 137 g_pname, cp->cmd_name, cp->cmd_usage); 138 } else { 139 (void) snprintf(buf, sizeof (buf), "%s %s", 140 g_pname, cp->cmd_name); 141 } 142 (void) fprintf(fp, "\t%-30s - %s\n", buf, cp->cmd_desc); 143 } 144 145 return (FMADM_EXIT_USAGE); 146 } 147 148 static uint32_t 149 getu32(const char *name, const char *s) 150 { 151 u_longlong_t val; 152 char *p; 153 154 errno = 0; 155 val = strtoull(s, &p, 0); 156 157 if (errno != 0 || p == s || *p != '\0' || val > UINT32_MAX) { 158 (void) fprintf(stderr, "%s: invalid %s argument -- %s\n", 159 g_pname, name, s); 160 exit(FMADM_EXIT_USAGE); 161 } 162 163 return ((uint32_t)val); 164 } 165 166 int 167 main(int argc, char *argv[]) 168 { 169 const struct cmd *cp; 170 uint32_t program; 171 const char *p; 172 int c, err; 173 174 if ((p = strrchr(argv[0], '/')) == NULL) 175 g_pname = argv[0]; 176 else 177 g_pname = p + 1; 178 179 if ((p = getenv("FMD_PROGRAM")) != NULL) 180 program = getu32("$FMD_PROGRAM", p); 181 else 182 program = FMD_ADM_PROGRAM; 183 184 while ((c = getopt(argc, argv, "P:q")) != EOF) { 185 switch (c) { 186 case 'P': 187 program = getu32("program", optarg); 188 break; 189 case 'q': 190 g_quiet++; 191 break; 192 default: 193 return (usage(stderr)); 194 } 195 } 196 197 if (optind >= argc) 198 return (usage(stdout)); 199 200 for (cp = cmds; cp->cmd_name != NULL; cp++) { 201 if (strcmp(cp->cmd_name, argv[optind]) == 0) 202 break; 203 } 204 205 if (cp->cmd_name == NULL) { 206 (void) fprintf(stderr, "%s: illegal subcommand -- %s\n", 207 g_pname, argv[optind]); 208 return (usage(stderr)); 209 } 210 211 if ((g_adm = fmd_adm_open(NULL, program, FMD_ADM_VERSION)) == NULL) 212 die(NULL); /* fmd_adm_errmsg() has enough info */ 213 214 argc -= optind; 215 argv += optind; 216 217 optind = 1; /* reset optind so subcommands can getopt() */ 218 219 err = cp->cmd_func(g_adm, argc, argv); 220 fmd_adm_close(g_adm); 221 return (err == FMADM_EXIT_USAGE ? usage(stderr) : err); 222 } 223