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