1*b6955755SRobert Johnston /*
2*b6955755SRobert Johnston  * CDDL HEADER START
3*b6955755SRobert Johnston  *
4*b6955755SRobert Johnston  * The contents of this file are subject to the terms of the
5*b6955755SRobert Johnston  * Common Development and Distribution License (the "License").
6*b6955755SRobert Johnston  * You may not use this file except in compliance with the License.
7*b6955755SRobert Johnston  *
8*b6955755SRobert Johnston  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*b6955755SRobert Johnston  * or http://www.opensolaris.org/os/licensing.
10*b6955755SRobert Johnston  * See the License for the specific language governing permissions
11*b6955755SRobert Johnston  * and limitations under the License.
12*b6955755SRobert Johnston  *
13*b6955755SRobert Johnston  * When distributing Covered Code, include this CDDL HEADER in each
14*b6955755SRobert Johnston  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*b6955755SRobert Johnston  * If applicable, add the following below this CDDL HEADER, with the
16*b6955755SRobert Johnston  * fields enclosed by brackets "[]" replaced with your own identifying
17*b6955755SRobert Johnston  * information: Portions Copyright [yyyy] [name of copyright owner]
18*b6955755SRobert Johnston  *
19*b6955755SRobert Johnston  * CDDL HEADER END
20*b6955755SRobert Johnston  */
21*b6955755SRobert Johnston 
22*b6955755SRobert Johnston /*
23*b6955755SRobert Johnston  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*b6955755SRobert Johnston  * Use is subject to license terms.
25*b6955755SRobert Johnston  */
26*b6955755SRobert Johnston 
27*b6955755SRobert Johnston #include <sys/types.h>
28*b6955755SRobert Johnston #include <sys/wait.h>
29*b6955755SRobert Johnston 
30*b6955755SRobert Johnston #include <sys/fm/protocol.h>
31*b6955755SRobert Johnston #include <fm/fmd_msg.h>
32*b6955755SRobert Johnston 
33*b6955755SRobert Johnston #include <unistd.h>
34*b6955755SRobert Johnston #include <signal.h>
35*b6955755SRobert Johnston #include <strings.h>
36*b6955755SRobert Johnston #include <stdlib.h>
37*b6955755SRobert Johnston #include <stdio.h>
38*b6955755SRobert Johnston #include <errno.h>
39*b6955755SRobert Johnston 
40*b6955755SRobert Johnston #define	TEST_ARR_SZ	2
41*b6955755SRobert Johnston 
42*b6955755SRobert Johnston int
43*b6955755SRobert Johnston main(int argc, char *argv[])
44*b6955755SRobert Johnston {
45*b6955755SRobert Johnston 	fmd_msg_hdl_t *h;
46*b6955755SRobert Johnston 	pid_t pid;
47*b6955755SRobert Johnston 	int i, err = 0;
48*b6955755SRobert Johnston 	char *s;
49*b6955755SRobert Johnston 
50*b6955755SRobert Johnston 	nvlist_t *auth, *fmri, *list, *test_arr[TEST_ARR_SZ];
51*b6955755SRobert Johnston 	const char *code = "TEST-8000-08";
52*b6955755SRobert Johnston 	int64_t tod[] = { 0x9400000, 0 };
53*b6955755SRobert Johnston 
54*b6955755SRobert Johnston 	if (argc > 1) {
55*b6955755SRobert Johnston 		(void) fprintf(stderr, "Usage: %s\n", argv[0]);
56*b6955755SRobert Johnston 		return (2);
57*b6955755SRobert Johnston 	}
58*b6955755SRobert Johnston 
59*b6955755SRobert Johnston 	/*
60*b6955755SRobert Johnston 	 * Build up a valid list.suspect event for a fictional diagnosis
61*b6955755SRobert Johnston 	 * using a diagnosis code from our test dictionary so we can format
62*b6955755SRobert Johnston 	 * messages.
63*b6955755SRobert Johnston 	 */
64*b6955755SRobert Johnston 	if (nvlist_alloc(&auth, NV_UNIQUE_NAME, 0) != 0 ||
65*b6955755SRobert Johnston 	    nvlist_alloc(&fmri, NV_UNIQUE_NAME, 0) != 0 ||
66*b6955755SRobert Johnston 	    nvlist_alloc(&list, NV_UNIQUE_NAME, 0) != 0) {
67*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: nvlist_alloc failed\n", argv[0]);
68*b6955755SRobert Johnston 		return (1);
69*b6955755SRobert Johnston 	}
70*b6955755SRobert Johnston 
71*b6955755SRobert Johnston 	err |= nvlist_add_uint8(auth, FM_VERSION, FM_FMRI_AUTH_VERSION);
72*b6955755SRobert Johnston 	err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, "product");
73*b6955755SRobert Johnston 	err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, "chassis");
74*b6955755SRobert Johnston 	err |= nvlist_add_string(auth, FM_FMRI_AUTH_DOMAIN, "domain");
75*b6955755SRobert Johnston 	err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, "server");
76*b6955755SRobert Johnston 
77*b6955755SRobert Johnston 	if (err != 0) {
78*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: failed to build auth nvlist: %s\n",
79*b6955755SRobert Johnston 		    argv[0], strerror(err));
80*b6955755SRobert Johnston 		return (1);
81*b6955755SRobert Johnston 	}
82*b6955755SRobert Johnston 
83*b6955755SRobert Johnston 	err |= nvlist_add_uint8(fmri, FM_VERSION, FM_FMD_SCHEME_VERSION);
84*b6955755SRobert Johnston 	err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD);
85*b6955755SRobert Johnston 	err |= nvlist_add_nvlist(fmri, FM_FMRI_AUTHORITY, auth);
86*b6955755SRobert Johnston 	err |= nvlist_add_string(fmri, FM_FMRI_FMD_NAME, "fmd_msg_test");
87*b6955755SRobert Johnston 	err |= nvlist_add_string(fmri, FM_FMRI_FMD_VERSION, "1.0");
88*b6955755SRobert Johnston 
89*b6955755SRobert Johnston 	if (err != 0) {
90*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: failed to build fmri nvlist: %s\n",
91*b6955755SRobert Johnston 		    argv[0], strerror(err));
92*b6955755SRobert Johnston 		return (1);
93*b6955755SRobert Johnston 	}
94*b6955755SRobert Johnston 
95*b6955755SRobert Johnston 	err |= nvlist_add_uint8(list, FM_VERSION, FM_SUSPECT_VERSION);
96*b6955755SRobert Johnston 	err |= nvlist_add_string(list, FM_CLASS, FM_LIST_SUSPECT_CLASS);
97*b6955755SRobert Johnston 	err |= nvlist_add_string(list, FM_SUSPECT_UUID, "12345678");
98*b6955755SRobert Johnston 	err |= nvlist_add_string(list, FM_SUSPECT_DIAG_CODE, code);
99*b6955755SRobert Johnston 	err |= nvlist_add_int64_array(list, FM_SUSPECT_DIAG_TIME, tod, 2);
100*b6955755SRobert Johnston 	err |= nvlist_add_nvlist(list, FM_SUSPECT_DE, fmri);
101*b6955755SRobert Johnston 	err |= nvlist_add_uint32(list, FM_SUSPECT_FAULT_SZ, 0);
102*b6955755SRobert Johnston 
103*b6955755SRobert Johnston 	/*
104*b6955755SRobert Johnston 	 * Add a contrived nvlist array to our list.suspect so that we can
105*b6955755SRobert Johnston 	 * exercise the expansion syntax for dereferencing nvlist array members
106*b6955755SRobert Johnston 	 */
107*b6955755SRobert Johnston 	for (i = 0; i < TEST_ARR_SZ; i++) {
108*b6955755SRobert Johnston 		if (nvlist_alloc(&test_arr[i], NV_UNIQUE_NAME, 0) != 0) {
109*b6955755SRobert Johnston 			(void) fprintf(stderr, "%s: failed to alloc nvlist "
110*b6955755SRobert Johnston 			    "array: %s\n", argv[0], strerror(err));
111*b6955755SRobert Johnston 			return (1);
112*b6955755SRobert Johnston 		}
113*b6955755SRobert Johnston 		err |= nvlist_add_uint8(test_arr[i], "index", i);
114*b6955755SRobert Johnston 	}
115*b6955755SRobert Johnston 	err |= nvlist_add_nvlist_array(list, "test_arr", test_arr, TEST_ARR_SZ);
116*b6955755SRobert Johnston 
117*b6955755SRobert Johnston 	if (err != 0) {
118*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: failed to build list nvlist: %s\n",
119*b6955755SRobert Johnston 		    argv[0], strerror(err));
120*b6955755SRobert Johnston 		return (1);
121*b6955755SRobert Johnston 	}
122*b6955755SRobert Johnston 
123*b6955755SRobert Johnston 	/*
124*b6955755SRobert Johnston 	 * Now initialize the libfmd_msg library for testing, using the message
125*b6955755SRobert Johnston 	 * catalogs found in the proto area of the current workspace.
126*b6955755SRobert Johnston 	 */
127*b6955755SRobert Johnston 	if ((h = fmd_msg_init(getenv("ROOT"), FMD_MSG_VERSION)) == NULL) {
128*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: fmd_msg_init failed: %s\n",
129*b6955755SRobert Johnston 		    argv[0], strerror(errno));
130*b6955755SRobert Johnston 		return (1);
131*b6955755SRobert Johnston 	}
132*b6955755SRobert Johnston 
133*b6955755SRobert Johnston 	/*
134*b6955755SRobert Johnston 	 * Test 0: Verify that both fmd_msg_getitem_id and fmd_msg_gettext_id
135*b6955755SRobert Johnston 	 * return NULL and EINVAL for an illegal message code, and NULL
136*b6955755SRobert Johnston 	 * and ENOENT for a valid but not defined message code.
137*b6955755SRobert Johnston 	 */
138*b6955755SRobert Johnston 	s = fmd_msg_getitem_id(h, NULL, "I_AM_NOT_VALID", 0);
139*b6955755SRobert Johnston 	if (s != NULL || errno != EINVAL) {
140*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: test0 FAIL: illegal code returned "
141*b6955755SRobert Johnston 		    "s = %p, errno = %d\n", argv[0], (void *)s, errno);
142*b6955755SRobert Johnston 		return (1);
143*b6955755SRobert Johnston 	}
144*b6955755SRobert Johnston 
145*b6955755SRobert Johnston 	s = fmd_msg_gettext_id(h, NULL, "I_AM_NOT_VALID");
146*b6955755SRobert Johnston 	if (s != NULL || errno != EINVAL) {
147*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: test0 FAIL: illegal code returned "
148*b6955755SRobert Johnston 		    "s = %p, errno = %d\n", argv[0], (void *)s, errno);
149*b6955755SRobert Johnston 		return (1);
150*b6955755SRobert Johnston 	}
151*b6955755SRobert Johnston 
152*b6955755SRobert Johnston 	s = fmd_msg_getitem_id(h, NULL, "I_AM_NOT_HERE-0000-0000", 0);
153*b6955755SRobert Johnston 	if (s != NULL || errno != ENOENT) {
154*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: test0 FAIL: missing code returned "
155*b6955755SRobert Johnston 		    "s = %p, errno = %d\n", argv[0], (void *)s, errno);
156*b6955755SRobert Johnston 		return (1);
157*b6955755SRobert Johnston 	}
158*b6955755SRobert Johnston 
159*b6955755SRobert Johnston 	s = fmd_msg_gettext_id(h, NULL, "I_AM_NOT_HERE-0000-0000");
160*b6955755SRobert Johnston 	if (s != NULL || errno != ENOENT) {
161*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: test0 FAIL: missing code returned "
162*b6955755SRobert Johnston 		    "s = %p, errno = %d\n", argv[0], (void *)s, errno);
163*b6955755SRobert Johnston 		return (1);
164*b6955755SRobert Johnston 	}
165*b6955755SRobert Johnston 
166*b6955755SRobert Johnston 	/*
167*b6955755SRobert Johnston 	 * Test 1: Use fmd_msg_getitem_id to retrieve the item strings for
168*b6955755SRobert Johnston 	 * a known message code without having any actual event handle.
169*b6955755SRobert Johnston 	 */
170*b6955755SRobert Johnston 	for (i = 0; i < FMD_MSG_ITEM_MAX; i++) {
171*b6955755SRobert Johnston 		if ((s = fmd_msg_getitem_id(h, NULL, code, i)) == NULL) {
172*b6955755SRobert Johnston 			(void) fprintf(stderr, "%s: fmd_msg_getitem_id failed "
173*b6955755SRobert Johnston 			    "for %s, item %d: %s\n",
174*b6955755SRobert Johnston 			    argv[0], code, i, strerror(errno));
175*b6955755SRobert Johnston 		}
176*b6955755SRobert Johnston 
177*b6955755SRobert Johnston 		(void) printf("code %s item %d = <<%s>>\n", code, i, s);
178*b6955755SRobert Johnston 		free(s);
179*b6955755SRobert Johnston 	}
180*b6955755SRobert Johnston 
181*b6955755SRobert Johnston 	/*
182*b6955755SRobert Johnston 	 * Test 2: Use fmd_msg_gettext_id to retrieve the complete message for
183*b6955755SRobert Johnston 	 * a known message code without having any actual event handle.
184*b6955755SRobert Johnston 	 */
185*b6955755SRobert Johnston 	if ((s = fmd_msg_gettext_id(h, NULL, code)) == NULL) {
186*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: fmd_msg_gettext_id failed for %s: "
187*b6955755SRobert Johnston 		    "%s\n", argv[0], code, strerror(errno));
188*b6955755SRobert Johnston 		return (1);
189*b6955755SRobert Johnston 	}
190*b6955755SRobert Johnston 
191*b6955755SRobert Johnston 	(void) printf("%s\n", s);
192*b6955755SRobert Johnston 	free(s);
193*b6955755SRobert Johnston 
194*b6955755SRobert Johnston 	/*
195*b6955755SRobert Johnston 	 * Test 3: Use fmd_msg_getitem_nv to retrieve the item strings for
196*b6955755SRobert Johnston 	 * our list.suspect event handle.
197*b6955755SRobert Johnston 	 */
198*b6955755SRobert Johnston 	for (i = 0; i < FMD_MSG_ITEM_MAX; i++) {
199*b6955755SRobert Johnston 		if ((s = fmd_msg_getitem_nv(h, NULL, list, i)) == NULL) {
200*b6955755SRobert Johnston 			(void) fprintf(stderr, "%s: fmd_msg_getitem_nv failed "
201*b6955755SRobert Johnston 			    "for %s, item %d: %s\n",
202*b6955755SRobert Johnston 			    argv[0], code, i, strerror(errno));
203*b6955755SRobert Johnston 		}
204*b6955755SRobert Johnston 
205*b6955755SRobert Johnston 		(void) printf("code %s item %d = <<%s>>\n", code, i, s);
206*b6955755SRobert Johnston 		free(s);
207*b6955755SRobert Johnston 	}
208*b6955755SRobert Johnston 
209*b6955755SRobert Johnston 	/*
210*b6955755SRobert Johnston 	 * Test 4: Use fmd_msg_getitem_nv to retrieve the complete message for
211*b6955755SRobert Johnston 	 * a known message code using our list.suspect event handle.
212*b6955755SRobert Johnston 	 */
213*b6955755SRobert Johnston 	if ((s = fmd_msg_gettext_nv(h, NULL, list)) == NULL) {
214*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: fmd_msg_gettext_nv failed for %s: "
215*b6955755SRobert Johnston 		    "%s\n", argv[0], code, strerror(errno));
216*b6955755SRobert Johnston 		return (1);
217*b6955755SRobert Johnston 	}
218*b6955755SRobert Johnston 
219*b6955755SRobert Johnston 	(void) printf("%s\n", s);
220*b6955755SRobert Johnston 	free(s);
221*b6955755SRobert Johnston 
222*b6955755SRobert Johnston 	/*
223*b6955755SRobert Johnston 	 * Test 5: Use fmd_msg_getitem_nv to retrieve the complete message for
224*b6955755SRobert Johnston 	 * a known message code using our list.suspect event handle, but this
225*b6955755SRobert Johnston 	 * time set the URL to our own customized URL.  Our contrived message
226*b6955755SRobert Johnston 	 * has been designed to exercise the key aspects of the variable
227*b6955755SRobert Johnston 	 * expansion syntax.
228*b6955755SRobert Johnston 	 */
229*b6955755SRobert Johnston 	if (fmd_msg_url_set(h, "http://foo.bar.com/") != 0) {
230*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: fmd_msg_url_set failed: %s\n",
231*b6955755SRobert Johnston 		    argv[0], strerror(errno));
232*b6955755SRobert Johnston 	}
233*b6955755SRobert Johnston 
234*b6955755SRobert Johnston 	if ((s = fmd_msg_gettext_nv(h, NULL, list)) == NULL) {
235*b6955755SRobert Johnston 		(void) fprintf(stderr, "%s: fmd_msg_gettext_nv failed for %s: "
236*b6955755SRobert Johnston 		    "%s\n", argv[0], code, strerror(errno));
237*b6955755SRobert Johnston 		return (1);
238*b6955755SRobert Johnston 	}
239*b6955755SRobert Johnston 
240*b6955755SRobert Johnston 	(void) printf("%s\n", s);
241*b6955755SRobert Johnston 	free(s);
242*b6955755SRobert Johnston 
243*b6955755SRobert Johnston 	for (i = 0; i < TEST_ARR_SZ; i++)
244*b6955755SRobert Johnston 		nvlist_free(test_arr[i]);
245*b6955755SRobert Johnston 	nvlist_free(fmri);
246*b6955755SRobert Johnston 	nvlist_free(auth);
247*b6955755SRobert Johnston 	nvlist_free(list);
248*b6955755SRobert Johnston 
249*b6955755SRobert Johnston 	fmd_msg_fini(h);	/* free library state before dumping core */
250*b6955755SRobert Johnston 	pid = fork();		/* fork into background to not bother make(1) */
251*b6955755SRobert Johnston 
252*b6955755SRobert Johnston 	switch (pid) {
253*b6955755SRobert Johnston 	case -1:
254*b6955755SRobert Johnston 		(void) fprintf(stderr, "FAIL (failed to fork)\n");
255*b6955755SRobert Johnston 		return (1);
256*b6955755SRobert Johnston 	case 0:
257*b6955755SRobert Johnston 		abort();
258*b6955755SRobert Johnston 		return (1);
259*b6955755SRobert Johnston 	}
260*b6955755SRobert Johnston 
261*b6955755SRobert Johnston 	if (waitpid(pid, &err, 0) == -1) {
262*b6955755SRobert Johnston 		(void) fprintf(stderr, "FAIL (failed to wait for %d: %s)\n",
263*b6955755SRobert Johnston 		    (int)pid, strerror(errno));
264*b6955755SRobert Johnston 		return (1);
265*b6955755SRobert Johnston 	}
266*b6955755SRobert Johnston 
267*b6955755SRobert Johnston 	if (WIFSIGNALED(err) == 0 || WTERMSIG(err) != SIGABRT) {
268*b6955755SRobert Johnston 		(void) fprintf(stderr, "FAIL (child did not SIGABRT)\n");
269*b6955755SRobert Johnston 		return (1);
270*b6955755SRobert Johnston 	}
271*b6955755SRobert Johnston 
272*b6955755SRobert Johnston 	if (!WCOREDUMP(err)) {
273*b6955755SRobert Johnston 		(void) fprintf(stderr, "FAIL (no core generated)\n");
274*b6955755SRobert Johnston 		return (1);
275*b6955755SRobert Johnston 	}
276*b6955755SRobert Johnston 
277*b6955755SRobert Johnston 	(void) fprintf(stderr, "done\n");
278*b6955755SRobert Johnston 	return (0);
279*b6955755SRobert Johnston }
280