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