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