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