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