10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55255Sstephh * Common Development and Distribution License (the "License"). 65255Sstephh * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 229120SStephen.Hanson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 265255Sstephh #include <sys/types.h> 275255Sstephh #include <fmadm.h> 285255Sstephh #include <errno.h> 295255Sstephh #include <limits.h> 300Sstevel@tonic-gate #include <strings.h> 315255Sstephh #include <stdio.h> 325255Sstephh #include <unistd.h> 335255Sstephh #include <sys/wait.h> 345255Sstephh #include <sys/stat.h> 355255Sstephh #include <fcntl.h> 365255Sstephh #include <fm/fmd_log.h> 375255Sstephh #include <sys/fm/protocol.h> 385255Sstephh #include <fm/libtopo.h> 395255Sstephh #include <fm/fmd_adm.h> 409501SRobert.Johnston@Sun.COM #include <fm/fmd_msg.h> 415255Sstephh #include <dlfcn.h> 425255Sstephh #include <sys/systeminfo.h> 435255Sstephh #include <sys/utsname.h> 445255Sstephh #include <libintl.h> 455255Sstephh #include <locale.h> 465255Sstephh #include <sys/smbios.h> 475255Sstephh #include <libdevinfo.h> 485255Sstephh #include <stdlib.h> 495255Sstephh 505255Sstephh #define offsetof(s, m) ((size_t)(&(((s*)0)->m))) 515255Sstephh 525255Sstephh /* 535255Sstephh * Fault records are added to catalog by calling add_fault_record_to_catalog() 545255Sstephh * records are stored in order of importance to the system. 555255Sstephh * If -g flag is set or not_suppressed is not set and the class fru, fault, 565255Sstephh * type are the same then details are merged into an existing record, with uuid 575255Sstephh * records are stored in time order. 585255Sstephh * For each record information is extracted from nvlist and merged into linked 595255Sstephh * list each is checked for identical records for which percentage certainty are 605255Sstephh * added together. 615255Sstephh * print_catalog() is called to print out catalog and release external resources 625255Sstephh * 635255Sstephh * /---------------\ 645255Sstephh * status_rec_list -> | | -| 655255Sstephh * \---------------/ 665255Sstephh * \/ 675255Sstephh * /---------------\ /-------\ /-------\ 685255Sstephh * status_fru_list | status_record | -> | uurec | -> | uurec | -| 695255Sstephh * \/ | | |- | | <- | | 705255Sstephh * /-------------\ | | \-------/ \-------/ 715255Sstephh * | | -> | | \/ \/ 725255Sstephh * \-------------/ | | /-------\ /-------\ 735255Sstephh * \/ | | -> | asru | -> | asru | 745255Sstephh * --- | | | | <- | | 755255Sstephh * | | \-------/ \-------/ 765255Sstephh * status_asru_list | class | 775255Sstephh * \/ | resource | /-------\ /-------\ 785255Sstephh * /-------------\ | fru | -> | list | -> | list | 795255Sstephh * | | -> | serial | | | <- | | 805255Sstephh * \-------------/ | | \-------/ \-------/ 815255Sstephh * \/ \---------------/ 825255Sstephh * --- \/ /\ 835255Sstephh * /---------------\ 845255Sstephh * | status_record | 855255Sstephh * \---------------/ 865255Sstephh * 875255Sstephh * Fmadm faulty takes a number of options which affect the format of the 885255Sstephh * output displayed. By default, the display reports the FRU and ASRU along 895255Sstephh * with other information on per-case basis as in the example below. 905255Sstephh * 915255Sstephh * --------------- ------------------------------------ -------------- ------- 925255Sstephh * TIME EVENT-ID MSG-ID SEVERITY 935255Sstephh * --------------- ------------------------------------ -------------- ------- 945255Sstephh * Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c AMD-8000-2F Major 955255Sstephh * 965255Sstephh * Fault class : fault.memory.dimm_sb 975255Sstephh * Affects : mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 987275Sstephh * faulted but still in service 995255Sstephh * FRU : "CPU 0 DIMM 0" (hc://.../memory-controller=0/dimm=0) 1005255Sstephh * faulty 1015255Sstephh * 1025255Sstephh * Description : The number of errors associated with this memory module has 1035255Sstephh * exceeded acceptable levels. Refer to 1045255Sstephh * http://sun.com/msg/AMD-8000-2F for more information. 1055255Sstephh * 1065255Sstephh * Response : Pages of memory associated with this memory module are being 1075255Sstephh * removed from service as errors are reported. 1085255Sstephh * 1095255Sstephh * Impact : Total system memory capacity will be reduced as pages are 1105255Sstephh * retired. 1115255Sstephh * 1125255Sstephh * Action : Schedule a repair procedure to replace the affected memory 1135255Sstephh * module. Use fmdump -v -u <EVENT_ID> to identify the module. 1145255Sstephh * 1155255Sstephh * The -v flag is similar, but adds some additonal information such as the 1165255Sstephh * resource. The -s flag is also similar but just gives the top line summary. 1175255Sstephh * All these options (ie without the -f or -r flags) use the print_catalog() 1185255Sstephh * function to do the display. 1195255Sstephh * 1205255Sstephh * The -f flag changes the output so that it appears sorted on a per-fru basis. 1215255Sstephh * The output is somewhat cut down compared to the default output. If -f is 1225255Sstephh * used, then print_fru() is used to print the output. 1235255Sstephh * 1245255Sstephh * ----------------------------------------------------------------------------- 1255255Sstephh * "SLOT 2" (hc://.../hostbridge=3/pciexrc=3/pciexbus=4/pciexdev=0) faulty 1265255Sstephh * 5ca4aeb3-36...f6be-c2e8166dc484 2 suspects in this FRU total certainty 100% 1275255Sstephh * 1285255Sstephh * Description : A problem was detected for a PCI device. 1295255Sstephh * Refer to http://sun.com/msg/PCI-8000-7J for more information. 1305255Sstephh * 1315255Sstephh * Response : One or more device instances may be disabled 1325255Sstephh * 1335255Sstephh * Impact : Possible loss of services provided by the device instances 1345255Sstephh * associated with this fault 1355255Sstephh * 1365255Sstephh * Action : Schedule a repair procedure to replace the affected device. 1375255Sstephh * Use fmdump -v -u <EVENT_ID> to identify the device or contact 1385255Sstephh * Sun for support. 1395255Sstephh * 1405255Sstephh * The -r flag changes the output so that it appears sorted on a per-asru basis. 1415255Sstephh * The output is very much cut down compared to the default output, just giving 1425255Sstephh * the asru fmri and state. Here print_asru() is used to print the output. 1435255Sstephh * 1445255Sstephh * mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 degraded 1455255Sstephh * 1465255Sstephh * For all fmadm faulty options, the sequence of events is 1475255Sstephh * 1485255Sstephh * 1) Walk through all the cases in the system using fmd_adm_case_iter() and 1495255Sstephh * for each case call dfault_rec(). This will call add_fault_record_to_catalog() 1505255Sstephh * This will extract the data from the nvlist and call catalog_new_record() to 1515255Sstephh * save the data away in various linked lists in the catalogue. 1525255Sstephh * 1535255Sstephh * 2) Once this is done, the data can be supplemented by using 1545255Sstephh * fmd_adm_rsrc_iter(). However this is now only necessary for the -i option. 1555255Sstephh * 1565255Sstephh * 3) Finally print_catalog(), print_fru() or print_asru() are called as 1575255Sstephh * appropriate to display the information from the catalogue sorted in the 1585255Sstephh * requested way. 1595255Sstephh * 1605255Sstephh */ 1615255Sstephh 1625255Sstephh typedef struct name_list { 1635255Sstephh struct name_list *next; 1645255Sstephh struct name_list *prev; 1655255Sstephh char *name; 1665255Sstephh uint8_t pct; 1675255Sstephh uint8_t max_pct; 1685255Sstephh ushort_t count; 1695255Sstephh int status; 1706002Sstephh char *label; 1715255Sstephh } name_list_t; 1725255Sstephh 1735255Sstephh typedef struct ari_list { 1745255Sstephh char *ari_uuid; 1755255Sstephh struct ari_list *next; 1765255Sstephh } ari_list_t; 1775255Sstephh 1785255Sstephh typedef struct uurec { 1795255Sstephh struct uurec *next; 1805255Sstephh struct uurec *prev; 1815255Sstephh char *uuid; 1825255Sstephh ari_list_t *ari_uuid_list; 1835255Sstephh name_list_t *asru; 1845255Sstephh uint64_t sec; 18510234SRobert.Johnston@Sun.COM nvlist_t *event; 1865255Sstephh } uurec_t; 1875255Sstephh 1885255Sstephh typedef struct uurec_select { 1895255Sstephh struct uurec_select *next; 1905255Sstephh char *uuid; 1915255Sstephh } uurec_select_t; 1925255Sstephh 1935255Sstephh typedef struct host_id { 1945255Sstephh char *chassis; 1955255Sstephh char *server; 1965255Sstephh char *platform; 1979120SStephen.Hanson@Sun.COM char *domain; 19810462SSean.Ye@Sun.COM char *product_sn; 1995255Sstephh } hostid_t; 2005255Sstephh 2015255Sstephh typedef struct host_id_list { 2025255Sstephh hostid_t hostid; 2035255Sstephh struct host_id_list *next; 2045255Sstephh } host_id_list_t; 2055255Sstephh 2065255Sstephh typedef struct status_record { 2075255Sstephh hostid_t *host; 2085255Sstephh int nrecs; 2095255Sstephh uurec_t *uurec; 2105255Sstephh char *severity; /* in C locale */ 2115255Sstephh char *msgid; 2125255Sstephh name_list_t *class; 2135255Sstephh name_list_t *resource; 2145255Sstephh name_list_t *asru; 2155255Sstephh name_list_t *fru; 2165255Sstephh name_list_t *serial; 2175255Sstephh uint8_t not_suppressed; 218*10928SStephen.Hanson@Sun.COM uint8_t injected; 2195255Sstephh } status_record_t; 2205255Sstephh 2215255Sstephh typedef struct sr_list { 2225255Sstephh struct sr_list *next; 2235255Sstephh struct sr_list *prev; 2245255Sstephh struct status_record *status_record; 2255255Sstephh } sr_list_t; 2265255Sstephh 2275255Sstephh typedef struct resource_list { 2285255Sstephh struct resource_list *next; 2295255Sstephh struct resource_list *prev; 2305255Sstephh sr_list_t *status_rec_list; 2315255Sstephh char *resource; 2325255Sstephh uint8_t not_suppressed; 233*10928SStephen.Hanson@Sun.COM uint8_t injected; 2345255Sstephh uint8_t max_pct; 2355255Sstephh } resource_list_t; 2365255Sstephh 2375255Sstephh typedef struct tgetlabel_data { 2385255Sstephh char *label; 2395255Sstephh char *fru; 2405255Sstephh } tgetlabel_data_t; 2410Sstevel@tonic-gate 2425255Sstephh sr_list_t *status_rec_list; 2435255Sstephh resource_list_t *status_fru_list; 2445255Sstephh resource_list_t *status_asru_list; 2455255Sstephh 2465255Sstephh static int max_display; 2475255Sstephh static int max_fault = 0; 2485255Sstephh static topo_hdl_t *topo_handle; 2495255Sstephh static char *topo_handle_uuid; 2505255Sstephh static host_id_list_t *host_list; 2515255Sstephh static int n_server; 2525255Sstephh static int opt_g; 2539501SRobert.Johnston@Sun.COM static fmd_msg_hdl_t *fmadm_msghdl = NULL; /* handle for libfmd_msg calls */ 2545255Sstephh 2555255Sstephh static char * 2565255Sstephh format_date(char *buf, size_t len, uint64_t sec) 2575255Sstephh { 2585255Sstephh if (sec > LONG_MAX) { 2595255Sstephh (void) fprintf(stderr, 2605255Sstephh "record time is too large for 32-bit utility\n"); 2615255Sstephh (void) snprintf(buf, len, "0x%llx", sec); 2625255Sstephh } else { 2635255Sstephh time_t tod = (time_t)sec; 264*10928SStephen.Hanson@Sun.COM time_t now = time(NULL); 265*10928SStephen.Hanson@Sun.COM if (tod > now+60 || 266*10928SStephen.Hanson@Sun.COM tod < now - 6L*30L*24L*60L*60L) { /* 6 months ago */ 267*10928SStephen.Hanson@Sun.COM (void) strftime(buf, len, "%b %d %Y ", 268*10928SStephen.Hanson@Sun.COM localtime(&tod)); 269*10928SStephen.Hanson@Sun.COM } else { 270*10928SStephen.Hanson@Sun.COM (void) strftime(buf, len, "%b %d %T", localtime(&tod)); 271*10928SStephen.Hanson@Sun.COM } 2725255Sstephh } 2735255Sstephh 2745255Sstephh return (buf); 2755255Sstephh } 2765255Sstephh 2775255Sstephh static hostid_t * 27810462SSean.Ye@Sun.COM find_hostid_in_list(char *platform, char *chassis, char *server, char *domain, 27910462SSean.Ye@Sun.COM char *product_sn) 2805255Sstephh { 2815255Sstephh hostid_t *rt = NULL; 2825255Sstephh host_id_list_t *hostp; 2835255Sstephh 2845255Sstephh if (platform == NULL) 2855255Sstephh platform = "-"; 2865255Sstephh if (server == NULL) 2875255Sstephh server = "-"; 2885255Sstephh hostp = host_list; 2895255Sstephh while (hostp) { 2905255Sstephh if (hostp->hostid.platform && 2915255Sstephh strcmp(hostp->hostid.platform, platform) == 0 && 2925255Sstephh hostp->hostid.server && 2935255Sstephh strcmp(hostp->hostid.server, server) == 0 && 2945255Sstephh (chassis == NULL || hostp->hostid.chassis == NULL || 2959120SStephen.Hanson@Sun.COM strcmp(chassis, hostp->hostid.chassis) == 0) && 29610462SSean.Ye@Sun.COM (product_sn == NULL || hostp->hostid.product_sn == NULL || 29710462SSean.Ye@Sun.COM strcmp(product_sn, hostp->hostid.product_sn) == 0) && 2989120SStephen.Hanson@Sun.COM (domain == NULL || hostp->hostid.domain == NULL || 2999120SStephen.Hanson@Sun.COM strcmp(domain, hostp->hostid.domain) == 0)) { 3005255Sstephh rt = &hostp->hostid; 3015255Sstephh break; 3025255Sstephh } 3035255Sstephh hostp = hostp->next; 3045255Sstephh } 3055255Sstephh if (rt == NULL) { 3065255Sstephh hostp = malloc(sizeof (host_id_list_t)); 3075255Sstephh hostp->hostid.platform = strdup(platform); 30810462SSean.Ye@Sun.COM hostp->hostid.product_sn = 30910462SSean.Ye@Sun.COM product_sn ? strdup(product_sn) : NULL; 3105255Sstephh hostp->hostid.server = strdup(server); 3115255Sstephh hostp->hostid.chassis = chassis ? strdup(chassis) : NULL; 3129120SStephen.Hanson@Sun.COM hostp->hostid.domain = domain ? strdup(domain) : NULL; 3135255Sstephh hostp->next = host_list; 3145255Sstephh host_list = hostp; 3155255Sstephh rt = &hostp->hostid; 3165255Sstephh n_server++; 3175255Sstephh } 3185255Sstephh return (rt); 3195255Sstephh } 3205255Sstephh 3215255Sstephh static hostid_t * 3225255Sstephh find_hostid(nvlist_t *nvl) 3235255Sstephh { 3249120SStephen.Hanson@Sun.COM char *platform = NULL, *chassis = NULL, *server = NULL, *domain = NULL; 32510462SSean.Ye@Sun.COM char *product_sn = NULL; 3265255Sstephh nvlist_t *auth, *fmri; 3275255Sstephh hostid_t *rt = NULL; 3285255Sstephh 3295255Sstephh if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &fmri) == 0 && 3305255Sstephh nvlist_lookup_nvlist(fmri, FM_FMRI_AUTHORITY, &auth) == 0) { 3315255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, 3325255Sstephh &platform); 33310462SSean.Ye@Sun.COM (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, 33410462SSean.Ye@Sun.COM &product_sn); 3355255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server); 3365255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, 3375255Sstephh &chassis); 3389120SStephen.Hanson@Sun.COM (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_DOMAIN, &domain); 33910462SSean.Ye@Sun.COM rt = find_hostid_in_list(platform, chassis, server, 34010462SSean.Ye@Sun.COM domain, product_sn); 3415255Sstephh } 3425255Sstephh return (rt); 3435255Sstephh } 3445255Sstephh 3455255Sstephh /* 3465255Sstephh * compare two fru strings which are made up of substrings seperated by '/' 3475255Sstephh * return true if every substring is the same in the two strings, or if a 3485255Sstephh * substring is null in one. 3495255Sstephh */ 3505255Sstephh 3515255Sstephh static int 3525255Sstephh frucmp(char *f1, char *f2) 3535255Sstephh { 3545255Sstephh char c1, c2; 3555255Sstephh int i = 0; 3565255Sstephh 3575255Sstephh for (;;) { 3585255Sstephh c1 = *f1; 3595255Sstephh c2 = *f2; 3605255Sstephh if (c1 == c2) { 3615255Sstephh i = (c1 == '/') ? 0 : i + 1; 3625255Sstephh } else if (i == 0) { 3635255Sstephh if (c1 == '/') { 3645255Sstephh do { 3655255Sstephh f2++; 3665255Sstephh } while ((c2 = *f2) != 0 && c2 != '/'); 3675255Sstephh if (c2 == NULL) 3685255Sstephh break; 3695255Sstephh } else if (c2 == '/') { 3705255Sstephh do { 3715255Sstephh f1++; 3725255Sstephh } while ((c1 = *f1) != 0 && c1 != '/'); 3735255Sstephh if (c1 == NULL) 3745255Sstephh break; 3755255Sstephh } else 3765255Sstephh break; 3775255Sstephh } else 3785255Sstephh break; 3795255Sstephh if (c1 == NULL) 3805255Sstephh return (0); 3815255Sstephh f1++; 3825255Sstephh f2++; 3835255Sstephh } 3845255Sstephh return (1); 3855255Sstephh } 3865255Sstephh 3875255Sstephh static int 3885255Sstephh tgetlabel(topo_hdl_t *thp, tnode_t *node, void *arg) 3890Sstevel@tonic-gate { 3905255Sstephh int err; 3915255Sstephh char *fru_name, *lname; 3925255Sstephh nvlist_t *fru = NULL; 3935255Sstephh int rt = TOPO_WALK_NEXT; 3945255Sstephh tgetlabel_data_t *tdp = (tgetlabel_data_t *)arg; 3955255Sstephh 3965255Sstephh if (topo_node_fru(node, &fru, NULL, &err) == 0) { 3975255Sstephh if (topo_fmri_nvl2str(thp, fru, &fru_name, &err) == 0) { 3985255Sstephh if (frucmp(tdp->fru, fru_name) == 0 && 3995255Sstephh topo_node_label(node, &lname, &err) == 0) { 4005255Sstephh tdp->label = strdup(lname); 4015255Sstephh topo_hdl_strfree(thp, lname); 4025255Sstephh rt = TOPO_WALK_TERMINATE; 4035255Sstephh } 4045255Sstephh topo_hdl_strfree(thp, fru_name); 4055255Sstephh } 4065255Sstephh nvlist_free(fru); 4075255Sstephh } 4085255Sstephh return (rt); 4095255Sstephh } 4105255Sstephh 4115255Sstephh static void 4125255Sstephh label_get_topo(void) 4135255Sstephh { 4145255Sstephh int err; 4155255Sstephh 4165255Sstephh topo_handle = topo_open(TOPO_VERSION, 0, &err); 4175255Sstephh if (topo_handle) { 4185255Sstephh topo_handle_uuid = topo_snap_hold(topo_handle, NULL, &err); 4195255Sstephh } 4205255Sstephh } 4215255Sstephh 4225255Sstephh static void 4235255Sstephh label_release_topo(void) 4245255Sstephh { 4255255Sstephh if (topo_handle_uuid) 4265255Sstephh topo_hdl_strfree(topo_handle, topo_handle_uuid); 4275255Sstephh if (topo_handle) { 4285255Sstephh topo_snap_release(topo_handle); 4295255Sstephh topo_close(topo_handle); 4305255Sstephh } 4315255Sstephh } 4325255Sstephh 4335255Sstephh static char * 4345255Sstephh get_fmri_label(char *fru) 4355255Sstephh { 4365255Sstephh topo_walk_t *twp; 4375255Sstephh tgetlabel_data_t td; 4385255Sstephh int err; 4395255Sstephh 4405255Sstephh td.label = NULL; 4415255Sstephh td.fru = fru; 4425255Sstephh if (topo_handle == NULL) 4435255Sstephh label_get_topo(); 4445255Sstephh if (topo_handle_uuid) { 4455255Sstephh twp = topo_walk_init(topo_handle, FM_FMRI_SCHEME_HC, 4465255Sstephh tgetlabel, &td, &err); 4475255Sstephh if (twp) { 4485255Sstephh topo_walk_step(twp, TOPO_WALK_CHILD); 4495255Sstephh topo_walk_fini(twp); 4505255Sstephh } 4515255Sstephh } 4525255Sstephh return (td.label); 4535255Sstephh } 4545255Sstephh 4555255Sstephh static char * 4565255Sstephh get_nvl2str_topo(nvlist_t *nvl) 4575255Sstephh { 4585255Sstephh char *name = NULL; 4595255Sstephh char *tname; 4605255Sstephh int err; 4615255Sstephh char *scheme = NULL; 4625255Sstephh char *mod_name = NULL; 4635255Sstephh char buf[128]; 4645255Sstephh 4655255Sstephh if (topo_handle == NULL) 4665255Sstephh label_get_topo(); 4675255Sstephh if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) { 4685255Sstephh name = strdup(tname); 4695255Sstephh topo_hdl_strfree(topo_handle, tname); 4705255Sstephh } else { 4715255Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme); 4725255Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &mod_name); 4735255Sstephh if (scheme && strcmp(scheme, FM_FMRI_SCHEME_FMD) == 0 && 4745255Sstephh mod_name) { 4755255Sstephh (void) snprintf(buf, sizeof (buf), "%s:///module/%s", 4765255Sstephh scheme, mod_name); 4775255Sstephh name = strdup(buf); 4785255Sstephh } 4795255Sstephh } 4805255Sstephh return (name); 4815255Sstephh } 4825255Sstephh 4835255Sstephh static int 4845255Sstephh set_priority(char *s) 4855255Sstephh { 4865255Sstephh int rt = 0; 4875255Sstephh 4885255Sstephh if (s) { 4895255Sstephh if (strcmp(s, "Minor") == 0) 4905255Sstephh rt = 1; 4915255Sstephh else if (strcmp(s, "Major") == 0) 4925255Sstephh rt = 10; 4935255Sstephh else if (strcmp(s, "Critical") == 0) 4945255Sstephh rt = 100; 4955255Sstephh } 4965255Sstephh return (rt); 4975255Sstephh } 4985255Sstephh 4995255Sstephh static int 5005255Sstephh cmp_priority(char *s1, char *s2, uint64_t t1, uint64_t t2, uint8_t p1, 5015255Sstephh uint8_t p2) 5025255Sstephh { 5035255Sstephh int r1, r2; 5045255Sstephh int rt; 5055255Sstephh 5065255Sstephh r1 = set_priority(s1); 5075255Sstephh r2 = set_priority(s2); 5085255Sstephh rt = r1 - r2; 5095255Sstephh if (rt == 0) { 5105255Sstephh if (t1 > t2) 5115255Sstephh rt = 1; 5125255Sstephh else if (t1 < t2) 5135255Sstephh rt = -1; 5145255Sstephh else 5155255Sstephh rt = p1 - p2; 5165255Sstephh } 5175255Sstephh return (rt); 5185255Sstephh } 5195255Sstephh 5205255Sstephh /* 5215255Sstephh * merge two lists into one, by comparing enties in new and moving into list if 5225255Sstephh * name is not there or free off memory for names which are already there 5235255Sstephh * add_pct indicates if pct is the sum or highest pct 5245255Sstephh */ 5255255Sstephh static name_list_t * 5265255Sstephh merge_name_list(name_list_t **list, name_list_t *new, int add_pct) 5275255Sstephh { 5285255Sstephh name_list_t *lp, *np, *sp, *rt = NULL; 5295255Sstephh int max_pct; 5305255Sstephh 5315255Sstephh rt = *list; 5325255Sstephh np = new; 5335255Sstephh while (np) { 5345255Sstephh lp = *list; 5355255Sstephh while (lp) { 5365255Sstephh if (strcmp(lp->name, np->name) == 0) 5375255Sstephh break; 5385255Sstephh lp = lp->next; 5395255Sstephh if (lp == *list) 5405255Sstephh lp = NULL; 5415255Sstephh } 5425255Sstephh if (np->next == new) 5435255Sstephh sp = NULL; 5445255Sstephh else 5455255Sstephh sp = np->next; 5465255Sstephh if (lp) { 5475255Sstephh lp->status |= (np->status & FM_SUSPECT_FAULTY); 5485255Sstephh if (add_pct) { 5495255Sstephh lp->pct += np->pct; 5505255Sstephh lp->count += np->count; 5515255Sstephh } else if (np->pct > lp->pct) { 5525255Sstephh lp->pct = np->pct; 5535255Sstephh } 5545255Sstephh max_pct = np->max_pct; 5556002Sstephh if (np->label) 5566002Sstephh free(np->label); 5575255Sstephh free(np->name); 5585255Sstephh free(np); 5595255Sstephh np = NULL; 5605255Sstephh if (max_pct > lp->max_pct) { 5615255Sstephh lp->max_pct = max_pct; 5625255Sstephh if (lp->max_pct > lp->prev->max_pct && 5635255Sstephh lp != *list) { 5645255Sstephh lp->prev->next = lp->next; 5655255Sstephh lp->next->prev = lp->prev; 5665255Sstephh np = lp; 5675255Sstephh } 5685255Sstephh } 5695255Sstephh } 5705255Sstephh if (np) { 5715255Sstephh lp = *list; 5725255Sstephh if (lp) { 5735255Sstephh if (np->max_pct > lp->max_pct) { 5745255Sstephh np->next = lp; 5755255Sstephh np->prev = lp->prev; 5765255Sstephh lp->prev->next = np; 5775255Sstephh lp->prev = np; 5785255Sstephh *list = np; 5795255Sstephh rt = np; 5805255Sstephh } else { 5815255Sstephh lp = lp->next; 5825255Sstephh while (lp != *list && 5835255Sstephh np->max_pct < lp->max_pct) { 5845255Sstephh lp = lp->next; 5855255Sstephh } 5865255Sstephh np->next = lp; 5875255Sstephh np->prev = lp->prev; 5885255Sstephh lp->prev->next = np; 5895255Sstephh lp->prev = np; 5905255Sstephh } 5915255Sstephh } else { 5925255Sstephh *list = np; 5935255Sstephh np->next = np; 5945255Sstephh np->prev = np; 5955255Sstephh rt = np; 5965255Sstephh } 5975255Sstephh } 5985255Sstephh np = sp; 5995255Sstephh } 6005255Sstephh return (rt); 6015255Sstephh } 6025255Sstephh 6035255Sstephh static name_list_t * 6045255Sstephh alloc_name_list(char *name, uint8_t pct) 6055255Sstephh { 6065255Sstephh name_list_t *nlp; 6075255Sstephh 6085255Sstephh nlp = malloc(sizeof (*nlp)); 6095255Sstephh nlp->name = strdup(name); 6105255Sstephh nlp->pct = pct; 6115255Sstephh nlp->max_pct = pct; 6125255Sstephh nlp->count = 1; 6135255Sstephh nlp->next = nlp; 6145255Sstephh nlp->prev = nlp; 6155255Sstephh nlp->status = 0; 6166002Sstephh nlp->label = NULL; 6175255Sstephh return (nlp); 6185255Sstephh } 6195255Sstephh 6205255Sstephh static status_record_t * 6215255Sstephh new_record_init(uurec_t *uurec_p, char *msgid, name_list_t *class, 6225255Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource, 6239501SRobert.Johnston@Sun.COM name_list_t *serial, boolean_t not_suppressed, 624*10928SStephen.Hanson@Sun.COM hostid_t *hostid, boolean_t injected) 6255255Sstephh { 6265255Sstephh status_record_t *status_rec_p; 6275255Sstephh 6285255Sstephh status_rec_p = (status_record_t *)malloc(sizeof (status_record_t)); 6295255Sstephh status_rec_p->nrecs = 1; 6305255Sstephh status_rec_p->host = hostid; 6315255Sstephh status_rec_p->uurec = uurec_p; 6325255Sstephh uurec_p->next = NULL; 6335255Sstephh uurec_p->prev = NULL; 6345255Sstephh uurec_p->asru = asru; 6359501SRobert.Johnston@Sun.COM if ((status_rec_p->severity = fmd_msg_getitem_id(fmadm_msghdl, NULL, 6369501SRobert.Johnston@Sun.COM msgid, FMD_MSG_ITEM_SEVERITY)) == NULL) 6379501SRobert.Johnston@Sun.COM status_rec_p->severity = strdup("unknown"); 6385255Sstephh status_rec_p->class = class; 6395255Sstephh status_rec_p->fru = fru; 6405255Sstephh status_rec_p->asru = asru; 6415255Sstephh status_rec_p->resource = resource; 6425255Sstephh status_rec_p->serial = serial; 6435255Sstephh status_rec_p->msgid = strdup(msgid); 6445255Sstephh status_rec_p->not_suppressed = not_suppressed; 645*10928SStephen.Hanson@Sun.COM status_rec_p->injected = injected; 6465255Sstephh return (status_rec_p); 6475255Sstephh } 6485255Sstephh 6495255Sstephh /* 6505255Sstephh * add record to given list maintaining order higher priority first. 6515255Sstephh */ 6525255Sstephh static void 6535255Sstephh add_rec_list(status_record_t *status_rec_p, sr_list_t **list_pp) 6545255Sstephh { 6555255Sstephh sr_list_t *tp, *np, *sp; 6565255Sstephh int order; 6575255Sstephh uint64_t sec; 6585255Sstephh 6595255Sstephh np = malloc(sizeof (sr_list_t)); 6605255Sstephh np->status_record = status_rec_p; 6615255Sstephh sec = status_rec_p->uurec->sec; 6625255Sstephh if ((sp = *list_pp) == NULL) { 6635255Sstephh *list_pp = np; 6645255Sstephh np->next = np; 6655255Sstephh np->prev = np; 6665255Sstephh } else { 6675255Sstephh /* insert new record in front of lower priority */ 6685255Sstephh tp = sp; 6695255Sstephh order = cmp_priority(status_rec_p->severity, 6705255Sstephh sp->status_record->severity, sec, 6715255Sstephh tp->status_record->uurec->sec, 0, 0); 6725255Sstephh if (order > 0) { 6735255Sstephh *list_pp = np; 6745255Sstephh } else { 6755255Sstephh tp = sp->next; 6765255Sstephh while (tp != sp && 6775255Sstephh cmp_priority(status_rec_p->severity, 6785255Sstephh tp->status_record->severity, sec, 6795255Sstephh tp->status_record->uurec->sec, 0, 0)) { 6805255Sstephh tp = tp->next; 6815255Sstephh } 6825255Sstephh } 6835255Sstephh np->next = tp; 6845255Sstephh np->prev = tp->prev; 6855255Sstephh tp->prev->next = np; 6865255Sstephh tp->prev = np; 6875255Sstephh } 6885255Sstephh } 6895255Sstephh 6905255Sstephh static void 6915255Sstephh add_resource(status_record_t *status_rec_p, resource_list_t **rp, 6925255Sstephh resource_list_t *np) 6935255Sstephh { 6945255Sstephh int order; 6955255Sstephh uint64_t sec; 6965255Sstephh resource_list_t *sp, *tp; 6975255Sstephh status_record_t *srp; 6985255Sstephh char *severity = status_rec_p->severity; 6995255Sstephh 7005255Sstephh add_rec_list(status_rec_p, &np->status_rec_list); 7015255Sstephh if ((sp = *rp) == NULL) { 7025255Sstephh np->next = np; 7035255Sstephh np->prev = np; 7045255Sstephh *rp = np; 7055255Sstephh } else { 7065255Sstephh /* 7075255Sstephh * insert new record in front of lower priority 7085255Sstephh */ 7095255Sstephh tp = sp->next; 7105255Sstephh srp = sp->status_rec_list->status_record; 7115255Sstephh sec = status_rec_p->uurec->sec; 7125255Sstephh order = cmp_priority(severity, srp->severity, sec, 7135255Sstephh srp->uurec->sec, np->max_pct, sp->max_pct); 7145255Sstephh if (order > 0) { 7155255Sstephh *rp = np; 7165255Sstephh } else { 7175255Sstephh srp = tp->status_rec_list->status_record; 7185255Sstephh while (tp != sp && 7195255Sstephh cmp_priority(severity, srp->severity, sec, 7205255Sstephh srp->uurec->sec, np->max_pct, sp->max_pct) < 0) { 7215255Sstephh tp = tp->next; 7225255Sstephh srp = tp->status_rec_list->status_record; 7235255Sstephh } 7245255Sstephh } 7255255Sstephh np->next = tp; 7265255Sstephh np->prev = tp->prev; 7275255Sstephh tp->prev->next = np; 7285255Sstephh tp->prev = np; 7295255Sstephh } 7305255Sstephh } 7315255Sstephh 7325255Sstephh static void 7335255Sstephh add_resource_list(status_record_t *status_rec_p, name_list_t *fp, 7345255Sstephh resource_list_t **rpp) 7355255Sstephh { 7365255Sstephh int order; 7375255Sstephh resource_list_t *np, *end; 7385255Sstephh status_record_t *srp; 7395255Sstephh 7405255Sstephh np = *rpp; 7415255Sstephh end = np; 7425255Sstephh while (np) { 7435255Sstephh if (strcmp(fp->name, np->resource) == 0) { 7445255Sstephh np->not_suppressed |= status_rec_p->not_suppressed; 745*10928SStephen.Hanson@Sun.COM np->injected |= status_rec_p->injected; 7465255Sstephh srp = np->status_rec_list->status_record; 7475255Sstephh order = cmp_priority(status_rec_p->severity, 7485255Sstephh srp->severity, status_rec_p->uurec->sec, 7495255Sstephh srp->uurec->sec, fp->max_pct, np->max_pct); 7505255Sstephh if (order > 0 && np != end) { 7515255Sstephh /* 7525255Sstephh * remove from list and add again using 7535255Sstephh * new priority 7545255Sstephh */ 7555255Sstephh np->prev->next = np->next; 7565255Sstephh np->next->prev = np->prev; 7575255Sstephh add_resource(status_rec_p, 7585255Sstephh rpp, np); 7595255Sstephh } else { 7605255Sstephh add_rec_list(status_rec_p, 7615255Sstephh &np->status_rec_list); 7625255Sstephh } 7635255Sstephh break; 7645255Sstephh } 7655255Sstephh np = np->next; 7665255Sstephh if (np == end) { 7675255Sstephh np = NULL; 7685255Sstephh break; 7695255Sstephh } 7705255Sstephh } 7715255Sstephh if (np == NULL) { 7725255Sstephh np = malloc(sizeof (resource_list_t)); 7735255Sstephh np->resource = fp->name; 7745255Sstephh np->not_suppressed = status_rec_p->not_suppressed; 775*10928SStephen.Hanson@Sun.COM np->injected = status_rec_p->injected; 7765255Sstephh np->status_rec_list = NULL; 7775255Sstephh np->max_pct = fp->max_pct; 7785255Sstephh add_resource(status_rec_p, rpp, np); 7790Sstevel@tonic-gate } 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 7825255Sstephh static void 7835255Sstephh add_list(status_record_t *status_rec_p, name_list_t *listp, 7845255Sstephh resource_list_t **glistp) 7855255Sstephh { 7865255Sstephh name_list_t *fp, *end; 7875255Sstephh 7885255Sstephh fp = listp; 7895255Sstephh end = fp; 7905255Sstephh while (fp) { 7915255Sstephh add_resource_list(status_rec_p, fp, glistp); 7925255Sstephh fp = fp->next; 7935255Sstephh if (fp == end) 7945255Sstephh break; 7955255Sstephh } 7965255Sstephh } 7975255Sstephh 7985255Sstephh /* 7995255Sstephh * add record to rec, fru and asru lists. 8005255Sstephh */ 8015255Sstephh static void 8025255Sstephh catalog_new_record(uurec_t *uurec_p, char *msgid, name_list_t *class, 8035255Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource, 8049501SRobert.Johnston@Sun.COM name_list_t *serial, boolean_t not_suppressed, 805*10928SStephen.Hanson@Sun.COM hostid_t *hostid, boolean_t injected) 8065255Sstephh { 8075255Sstephh status_record_t *status_rec_p; 8085255Sstephh 8095255Sstephh status_rec_p = new_record_init(uurec_p, msgid, class, fru, asru, 810*10928SStephen.Hanson@Sun.COM resource, serial, not_suppressed, hostid, injected); 8115255Sstephh add_rec_list(status_rec_p, &status_rec_list); 8125255Sstephh if (status_rec_p->fru) 8135255Sstephh add_list(status_rec_p, status_rec_p->fru, &status_fru_list); 8145255Sstephh if (status_rec_p->asru) 8155255Sstephh add_list(status_rec_p, status_rec_p->asru, &status_asru_list); 8165255Sstephh } 8175255Sstephh 8185255Sstephh static void 8195255Sstephh get_serial_no(nvlist_t *nvl, name_list_t **serial_p, uint8_t pct) 8205255Sstephh { 8215255Sstephh char *name; 8225255Sstephh char *serial = NULL; 8235255Sstephh char **lserial = NULL; 8245255Sstephh uint64_t serint; 8255255Sstephh name_list_t *nlp; 8265255Sstephh int j; 8275255Sstephh uint_t nelem; 8285255Sstephh char buf[64]; 8290Sstevel@tonic-gate 8305255Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) == 0) { 8315255Sstephh if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 8325255Sstephh if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, 8335255Sstephh &serint) == 0) { 8345255Sstephh (void) snprintf(buf, sizeof (buf), "%llX", 8355255Sstephh serint); 8365255Sstephh nlp = alloc_name_list(buf, pct); 8375255Sstephh (void) merge_name_list(serial_p, nlp, 1); 8385255Sstephh } 8395255Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 8405255Sstephh if (nvlist_lookup_string_array(nvl, 8415255Sstephh FM_FMRI_MEM_SERIAL_ID, &lserial, &nelem) == 0) { 8425255Sstephh nlp = alloc_name_list(lserial[0], pct); 8435255Sstephh for (j = 1; j < nelem; j++) { 8445255Sstephh name_list_t *n1lp; 8455255Sstephh n1lp = alloc_name_list(lserial[j], pct); 8465255Sstephh (void) merge_name_list(&nlp, n1lp, 1); 8475255Sstephh } 8485255Sstephh (void) merge_name_list(serial_p, nlp, 1); 8495255Sstephh } 8505255Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_HC) == 0) { 8515255Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, 8525255Sstephh &serial) == 0) { 8535255Sstephh nlp = alloc_name_list(serial, pct); 8545255Sstephh (void) merge_name_list(serial_p, nlp, 1); 8555255Sstephh } 8565255Sstephh } 8575255Sstephh } 8585255Sstephh } 8595255Sstephh 8605255Sstephh static void 8615255Sstephh extract_record_info(nvlist_t *nvl, name_list_t **class_p, 8625255Sstephh name_list_t **fru_p, name_list_t **serial_p, 8635255Sstephh name_list_t **resource_p, name_list_t **asru_p, uint8_t status) 8640Sstevel@tonic-gate { 8655255Sstephh nvlist_t *lfru, *lasru, *rsrc; 8665255Sstephh name_list_t *nlp; 8675255Sstephh char *name; 8685255Sstephh uint8_t lpct = 0; 8695255Sstephh char *lclass = NULL; 8706002Sstephh char *label; 8715255Sstephh 8725255Sstephh (void) nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &lpct); 8735255Sstephh if (nvlist_lookup_string(nvl, FM_CLASS, &lclass) == 0) { 8745255Sstephh nlp = alloc_name_list(lclass, lpct); 8755255Sstephh (void) merge_name_list(class_p, nlp, 1); 8765255Sstephh } 8775255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &lfru) == 0) { 8785255Sstephh name = get_nvl2str_topo(lfru); 8795255Sstephh if (name != NULL) { 8805255Sstephh nlp = alloc_name_list(name, lpct); 8817275Sstephh nlp->status = status & ~(FM_SUSPECT_UNUSABLE | 8827275Sstephh FM_SUSPECT_DEGRADED); 8835255Sstephh free(name); 8846002Sstephh if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION, 8856002Sstephh &label) == 0) 8866002Sstephh nlp->label = strdup(label); 8875255Sstephh (void) merge_name_list(fru_p, nlp, 1); 8885255Sstephh } 8895255Sstephh get_serial_no(lfru, serial_p, lpct); 89010656SStephen.Hanson@Sun.COM } else if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) != 0) { 89110656SStephen.Hanson@Sun.COM /* 89210656SStephen.Hanson@Sun.COM * No FRU or resource. But we want to display the repair status 89310656SStephen.Hanson@Sun.COM * somehow, so create a dummy FRU field. 89410656SStephen.Hanson@Sun.COM */ 89510656SStephen.Hanson@Sun.COM nlp = alloc_name_list(dgettext("FMD", "None"), lpct); 89610656SStephen.Hanson@Sun.COM nlp->status = status & ~(FM_SUSPECT_UNUSABLE | 89710656SStephen.Hanson@Sun.COM FM_SUSPECT_DEGRADED); 89810656SStephen.Hanson@Sun.COM (void) merge_name_list(fru_p, nlp, 1); 8995255Sstephh } 9005255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &lasru) == 0) { 9015255Sstephh name = get_nvl2str_topo(lasru); 9025255Sstephh if (name != NULL) { 9035255Sstephh nlp = alloc_name_list(name, lpct); 9047275Sstephh nlp->status = status & ~(FM_SUSPECT_NOT_PRESENT | 9057275Sstephh FM_SUSPECT_REPAIRED | FM_SUSPECT_REPLACED | 9067275Sstephh FM_SUSPECT_ACQUITTED); 9075255Sstephh free(name); 9085255Sstephh (void) merge_name_list(asru_p, nlp, 1); 9095255Sstephh } 9105255Sstephh get_serial_no(lasru, serial_p, lpct); 9115255Sstephh } 9125255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) { 9135255Sstephh name = get_nvl2str_topo(rsrc); 9145255Sstephh if (name != NULL) { 9155255Sstephh nlp = alloc_name_list(name, lpct); 9166228Sstephh nlp->status = status; 9175255Sstephh free(name); 9188245SStephen.Hanson@Sun.COM if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION, 9198245SStephen.Hanson@Sun.COM &label) == 0) 9208245SStephen.Hanson@Sun.COM nlp->label = strdup(label); 9215255Sstephh (void) merge_name_list(resource_p, nlp, 1); 9225255Sstephh } 9235255Sstephh } 9245255Sstephh } 9255255Sstephh 9265255Sstephh static void 9279501SRobert.Johnston@Sun.COM add_fault_record_to_catalog(nvlist_t *nvl, uint64_t sec, char *uuid) 9285255Sstephh { 9295255Sstephh char *msgid = "-"; 9305255Sstephh uint_t i, size = 0; 9315255Sstephh name_list_t *class = NULL, *resource = NULL; 9325255Sstephh name_list_t *asru = NULL, *fru = NULL, *serial = NULL; 9335255Sstephh nvlist_t **nva; 9345255Sstephh uint8_t *ba; 9355255Sstephh uurec_t *uurec_p; 9365255Sstephh hostid_t *host; 9375255Sstephh boolean_t not_suppressed = 1; 9385255Sstephh boolean_t any_present = 0; 939*10928SStephen.Hanson@Sun.COM boolean_t injected = 0; 9405255Sstephh 9415255Sstephh (void) nvlist_lookup_string(nvl, FM_SUSPECT_DIAG_CODE, &msgid); 9425255Sstephh (void) nvlist_lookup_uint32(nvl, FM_SUSPECT_FAULT_SZ, &size); 9435255Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE, 9445255Sstephh ¬_suppressed); 945*10928SStephen.Hanson@Sun.COM (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_INJECTED, &injected); 9465255Sstephh 9475255Sstephh if (size != 0) { 9485255Sstephh (void) nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 9495255Sstephh &nva, &size); 9505255Sstephh (void) nvlist_lookup_uint8_array(nvl, FM_SUSPECT_FAULT_STATUS, 9515255Sstephh &ba, &size); 9525255Sstephh for (i = 0; i < size; i++) { 9535255Sstephh extract_record_info(nva[i], &class, &fru, &serial, 9545255Sstephh &resource, &asru, ba[i]); 9555255Sstephh if (!(ba[i] & FM_SUSPECT_NOT_PRESENT) && 9565255Sstephh (ba[i] & FM_SUSPECT_FAULTY)) 9575255Sstephh any_present = 1; 9585255Sstephh } 9595255Sstephh /* 9605255Sstephh * also suppress if no resources present 9615255Sstephh */ 9625255Sstephh if (any_present == 0) 9635255Sstephh not_suppressed = 0; 9640Sstevel@tonic-gate } 9650Sstevel@tonic-gate 9665255Sstephh uurec_p = (uurec_t *)malloc(sizeof (uurec_t)); 9675255Sstephh uurec_p->uuid = strdup(uuid); 9685255Sstephh uurec_p->sec = sec; 9695255Sstephh uurec_p->ari_uuid_list = NULL; 97010234SRobert.Johnston@Sun.COM uurec_p->event = NULL; 97110234SRobert.Johnston@Sun.COM (void) nvlist_dup(nvl, &uurec_p->event, 0); 9725255Sstephh host = find_hostid(nvl); 97310656SStephen.Hanson@Sun.COM catalog_new_record(uurec_p, msgid, class, fru, asru, 974*10928SStephen.Hanson@Sun.COM resource, serial, not_suppressed, host, injected); 9755255Sstephh } 9765255Sstephh 9775255Sstephh static void 9785255Sstephh update_asru_state_in_catalog(const char *uuid, const char *ari_uuid) 9795255Sstephh { 9805255Sstephh sr_list_t *srp; 9815255Sstephh uurec_t *uurp; 9825255Sstephh ari_list_t *ari_list; 9835255Sstephh 9845255Sstephh srp = status_rec_list; 9855255Sstephh if (srp) { 9865255Sstephh for (;;) { 9875255Sstephh uurp = srp->status_record->uurec; 9885255Sstephh while (uurp) { 9895255Sstephh if (strcmp(uuid, uurp->uuid) == 0) { 9905255Sstephh ari_list = (ari_list_t *) 9915255Sstephh malloc(sizeof (ari_list_t)); 9925255Sstephh ari_list->ari_uuid = strdup(ari_uuid); 9935255Sstephh ari_list->next = uurp->ari_uuid_list; 9945255Sstephh uurp->ari_uuid_list = ari_list; 9955255Sstephh return; 9965255Sstephh } 9975255Sstephh uurp = uurp->next; 9985255Sstephh } 9995255Sstephh if (srp->next == status_rec_list) 10005255Sstephh break; 10015255Sstephh srp = srp->next; 10025255Sstephh } 10035255Sstephh } 10045255Sstephh } 10055255Sstephh 10065255Sstephh static void 10075255Sstephh print_line(char *label, char *buf) 10085255Sstephh { 10095255Sstephh char *cp, *ep, *wp; 10105255Sstephh char c; 10115255Sstephh int i; 10125255Sstephh int lsz; 10135255Sstephh char *padding; 10145255Sstephh 10155255Sstephh lsz = strlen(label); 10165255Sstephh padding = malloc(lsz + 1); 10175255Sstephh for (i = 0; i < lsz; i++) 10185255Sstephh padding[i] = ' '; 10195255Sstephh padding[i] = 0; 10205255Sstephh cp = buf; 10215255Sstephh ep = buf; 10225255Sstephh c = *ep; 10235255Sstephh (void) printf("\n"); 10245255Sstephh while (c) { 10255255Sstephh i = lsz; 10265255Sstephh wp = NULL; 10275255Sstephh while ((c = *ep) != NULL && (wp == NULL || i < 80)) { 10285255Sstephh if (c == ' ') 10295255Sstephh wp = ep; 10305255Sstephh else if (c == '\n') { 10315255Sstephh i = 0; 10325255Sstephh *ep = 0; 10335255Sstephh do { 10345255Sstephh ep++; 10355255Sstephh } while ((c = *ep) != NULL && c == ' '); 10365255Sstephh break; 10375255Sstephh } 10385255Sstephh ep++; 10395255Sstephh i++; 10405255Sstephh } 10415255Sstephh if (i >= 80 && wp) { 10425255Sstephh *wp = 0; 10435255Sstephh ep = wp + 1; 10445255Sstephh c = *ep; 10455255Sstephh } 10465255Sstephh (void) printf("%s%s\n", label, cp); 10475255Sstephh cp = ep; 10485255Sstephh label = padding; 10495255Sstephh } 10505255Sstephh free(padding); 10515255Sstephh } 10525255Sstephh 10535255Sstephh static void 105410234SRobert.Johnston@Sun.COM print_dict_info_line(nvlist_t *e, fmd_msg_item_t what, const char *linehdr) 10555255Sstephh { 105610234SRobert.Johnston@Sun.COM char *cp = fmd_msg_getitem_nv(fmadm_msghdl, NULL, e, what); 10575255Sstephh 10585255Sstephh if (cp) { 10599501SRobert.Johnston@Sun.COM print_line(dgettext("FMD", linehdr), cp); 10609501SRobert.Johnston@Sun.COM free(cp); 10615255Sstephh } 10629501SRobert.Johnston@Sun.COM } 10639501SRobert.Johnston@Sun.COM 10649501SRobert.Johnston@Sun.COM static void 106510234SRobert.Johnston@Sun.COM print_dict_info(nvlist_t *nvl) 10669501SRobert.Johnston@Sun.COM { 106710234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_DESC, "Description : "); 106810234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_RESPONSE, "Response : "); 106910234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_IMPACT, "Impact : "); 107010234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_ACTION, "Action : "); 10715255Sstephh } 10725255Sstephh 10735255Sstephh static void 10745255Sstephh print_name(name_list_t *list, char *(func)(char *), char *padding, int *np, 10755255Sstephh int pct, int full) 10765255Sstephh { 10778245SStephen.Hanson@Sun.COM char *name, *fru_label = NULL; 10785255Sstephh 10795255Sstephh name = list->name; 10808245SStephen.Hanson@Sun.COM if (list->label) { 10818245SStephen.Hanson@Sun.COM (void) printf("%s \"%s\" (%s)", padding, list->label, name); 10825255Sstephh *np += 1; 10838245SStephen.Hanson@Sun.COM } else if (func && (fru_label = func(list->name)) != NULL) { 10848245SStephen.Hanson@Sun.COM (void) printf("%s \"%s\" (%s)", padding, fru_label, name); 10858245SStephen.Hanson@Sun.COM *np += 1; 10868245SStephen.Hanson@Sun.COM free(fru_label); 10875255Sstephh } else { 10885255Sstephh (void) printf("%s %s", padding, name); 10895255Sstephh *np += 1; 10905255Sstephh } 10915255Sstephh if (list->pct && pct > 0 && pct < 100) { 10925255Sstephh if (list->count > 1) { 10935255Sstephh if (full) { 10945255Sstephh (void) printf(" %d @ %s %d%%\n", list->count, 10955255Sstephh dgettext("FMD", "max"), 10965255Sstephh list->max_pct); 10975255Sstephh } else { 10985255Sstephh (void) printf(" %s %d%%\n", 10995255Sstephh dgettext("FMD", "max"), 11005255Sstephh list->max_pct); 11015255Sstephh } 11025255Sstephh } else { 11035255Sstephh (void) printf(" %d%%\n", list->pct); 11045255Sstephh } 11055255Sstephh } else { 11065255Sstephh (void) printf("\n"); 11075255Sstephh } 11085255Sstephh } 11095255Sstephh 11105255Sstephh static void 11115255Sstephh print_asru_status(int status, char *label) 11125255Sstephh { 11135255Sstephh char *msg = NULL; 11145255Sstephh 11155255Sstephh switch (status) { 11165255Sstephh case 0: 11175255Sstephh msg = dgettext("FMD", "ok and in service"); 11185255Sstephh break; 11197275Sstephh case FM_SUSPECT_DEGRADED: 11207275Sstephh msg = dgettext("FMD", "service degraded, " 11217275Sstephh "but associated components no longer faulty"); 11227275Sstephh break; 11237275Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED: 11247275Sstephh msg = dgettext("FMD", "faulted but still " 11257275Sstephh "providing degraded service"); 11267275Sstephh break; 11275255Sstephh case FM_SUSPECT_FAULTY: 11287275Sstephh msg = dgettext("FMD", "faulted but still in service"); 11295255Sstephh break; 11305255Sstephh case FM_SUSPECT_UNUSABLE: 11317275Sstephh msg = dgettext("FMD", "out of service, " 11327275Sstephh "but associated components no longer faulty"); 11335255Sstephh break; 11345255Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE: 11355255Sstephh msg = dgettext("FMD", "faulted and taken out of service"); 11365255Sstephh break; 11375255Sstephh default: 11385255Sstephh break; 11395255Sstephh } 11405255Sstephh if (msg) { 11415255Sstephh (void) printf("%s %s\n", label, msg); 11425255Sstephh } 11435255Sstephh } 11445255Sstephh 11455255Sstephh static void 11466228Sstephh print_fru_status(int status, char *label) 11476228Sstephh { 11486228Sstephh char *msg = NULL; 11496228Sstephh 11506228Sstephh if (status & FM_SUSPECT_NOT_PRESENT) 11516228Sstephh msg = dgettext("FMD", "not present"); 11526228Sstephh else if (status & FM_SUSPECT_FAULTY) 11536228Sstephh msg = dgettext("FMD", "faulty"); 11547275Sstephh else if (status & FM_SUSPECT_REPLACED) 11557275Sstephh msg = dgettext("FMD", "replaced"); 11567275Sstephh else if (status & FM_SUSPECT_REPAIRED) 11577275Sstephh msg = dgettext("FMD", "repair attempted"); 11587275Sstephh else if (status & FM_SUSPECT_ACQUITTED) 11597275Sstephh msg = dgettext("FMD", "acquitted"); 11606228Sstephh else 11617275Sstephh msg = dgettext("FMD", "removed"); 11626228Sstephh (void) printf("%s %s\n", label, msg); 11636228Sstephh } 11646228Sstephh 11656228Sstephh static void 11669120SStephen.Hanson@Sun.COM print_rsrc_status(int status, char *label) 11679120SStephen.Hanson@Sun.COM { 11689120SStephen.Hanson@Sun.COM char *msg = ""; 11699120SStephen.Hanson@Sun.COM 11709120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_NOT_PRESENT) 11719120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "not present"); 11729120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_FAULTY) { 11739120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_DEGRADED) 11749120SStephen.Hanson@Sun.COM msg = dgettext("FMD", 11759120SStephen.Hanson@Sun.COM "faulted but still providing degraded service"); 11769120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_UNUSABLE) 11779120SStephen.Hanson@Sun.COM msg = dgettext("FMD", 11789120SStephen.Hanson@Sun.COM "faulted and taken out of service"); 11799120SStephen.Hanson@Sun.COM else 11809120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "faulted but still in service"); 11819120SStephen.Hanson@Sun.COM } else if (status & FM_SUSPECT_REPLACED) 11829120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "replaced"); 11839120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_REPAIRED) 11849120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "repair attempted"); 11859120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_ACQUITTED) 11869120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "acquitted"); 11879120SStephen.Hanson@Sun.COM else 11889120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "removed"); 11899120SStephen.Hanson@Sun.COM (void) printf("%s %s\n", label, msg); 11909120SStephen.Hanson@Sun.COM } 11919120SStephen.Hanson@Sun.COM 11929120SStephen.Hanson@Sun.COM static void 11935255Sstephh print_name_list(name_list_t *list, char *label, char *(func)(char *), 11945255Sstephh int limit, int pct, void (func1)(int, char *), int full) 11955255Sstephh { 11968245SStephen.Hanson@Sun.COM char *name, *fru_label = NULL; 11975255Sstephh char *padding; 11985255Sstephh int i, j, l, n; 11995255Sstephh name_list_t *end = list; 12005255Sstephh 12015255Sstephh l = strlen(label); 12025255Sstephh padding = malloc(l + 1); 12035255Sstephh for (i = 0; i < l; i++) 12045255Sstephh padding[i] = ' '; 12055255Sstephh padding[l] = 0; 12065255Sstephh (void) printf("%s", label); 12075255Sstephh name = list->name; 12088245SStephen.Hanson@Sun.COM if (list->label) 12096002Sstephh (void) printf(" \"%s\" (%s)", list->label, name); 12108245SStephen.Hanson@Sun.COM else if (func && (fru_label = func(list->name)) != NULL) { 12118245SStephen.Hanson@Sun.COM (void) printf(" \"%s\" (%s)", fru_label, name); 12128245SStephen.Hanson@Sun.COM free(fru_label); 12138245SStephen.Hanson@Sun.COM } else 12148245SStephen.Hanson@Sun.COM (void) printf(" %s", name); 12155255Sstephh if (list->pct && pct > 0 && pct < 100) { 12165255Sstephh if (list->count > 1) { 12175255Sstephh if (full) { 12185255Sstephh (void) printf(" %d @ %s %d%%\n", list->count, 12195255Sstephh dgettext("FMD", "max"), list->max_pct); 12205255Sstephh } else { 12215255Sstephh (void) printf(" %s %d%%\n", 12225255Sstephh dgettext("FMD", "max"), list->max_pct); 12235255Sstephh } 12245255Sstephh } else { 12255255Sstephh (void) printf(" %d%%\n", list->pct); 12265255Sstephh } 12275255Sstephh } else { 12285255Sstephh (void) printf("\n"); 12295255Sstephh } 12305255Sstephh if (func1) 12315255Sstephh func1(list->status, padding); 12325255Sstephh n = 1; 12335255Sstephh j = 0; 12345255Sstephh while ((list = list->next) != end) { 12355255Sstephh if (limit == 0 || n < limit) { 12365255Sstephh print_name(list, func, padding, &n, pct, full); 12375255Sstephh if (func1) 12385255Sstephh func1(list->status, padding); 12395255Sstephh } else 12405255Sstephh j++; 12415255Sstephh } 12425255Sstephh if (j == 1) { 12435255Sstephh print_name(list->prev, func, padding, &n, pct, full); 12445255Sstephh } else if (j > 1) { 12455255Sstephh (void) printf("%s... %d %s\n", padding, j, 12465255Sstephh dgettext("FMD", "more entries suppressed," 12475255Sstephh " use -v option for full list")); 12485255Sstephh } 12495255Sstephh free(padding); 12505255Sstephh } 12515255Sstephh 12525255Sstephh static int 12535255Sstephh asru_same_status(name_list_t *list) 12545255Sstephh { 12555255Sstephh name_list_t *end = list; 12565255Sstephh int status = list->status; 12575255Sstephh 12585255Sstephh while ((list = list->next) != end) { 12595255Sstephh if (status == -1) { 12605255Sstephh status = list->status; 12615255Sstephh continue; 12625255Sstephh } 12635255Sstephh if (list->status != -1 && status != list->status) { 12645255Sstephh status = -1; 12655255Sstephh break; 12665255Sstephh } 12675255Sstephh } 12685255Sstephh return (status); 12695255Sstephh } 12705255Sstephh 12715255Sstephh static int 12725255Sstephh serial_in_fru(name_list_t *fru, name_list_t *serial) 12735255Sstephh { 12745255Sstephh name_list_t *sp = serial; 12755255Sstephh name_list_t *fp; 12765255Sstephh int nserial = 0; 12775255Sstephh int found = 0; 12785255Sstephh char buf[128]; 12795255Sstephh 12805255Sstephh while (sp) { 12815255Sstephh fp = fru; 12825255Sstephh nserial++; 12835255Sstephh (void) snprintf(buf, sizeof (buf), "serial=%s", sp->name); 12845255Sstephh buf[sizeof (buf) - 1] = 0; 12855255Sstephh while (fp) { 12865255Sstephh if (strstr(fp->name, buf) != NULL) { 12875255Sstephh found++; 12885255Sstephh break; 12895255Sstephh } 12905255Sstephh fp = fp->next; 12915255Sstephh if (fp == fru) 12925255Sstephh break; 12935255Sstephh } 12945255Sstephh sp = sp->next; 12955255Sstephh if (sp == serial) 12965255Sstephh break; 12975255Sstephh } 12985255Sstephh return (found == nserial ? 1 : 0); 12995255Sstephh } 13005255Sstephh 13015255Sstephh static void 13025255Sstephh print_sup_record(status_record_t *srp, int opt_i, int full) 13035255Sstephh { 13045255Sstephh char buf[32]; 13055255Sstephh uurec_t *uurp = srp->uurec; 13065255Sstephh int n, j, k, max; 13075255Sstephh int status; 13085255Sstephh ari_list_t *ari_list; 13095255Sstephh 13105255Sstephh n = 0; 13115255Sstephh max = max_fault; 13125255Sstephh if (max < 0) { 13135255Sstephh max = 0; 13145255Sstephh } 13155255Sstephh j = max / 2; 13165255Sstephh max -= j; 13175255Sstephh k = srp->nrecs - max; 13185255Sstephh while ((uurp = uurp->next) != NULL) { 13195255Sstephh if (full || n < j || n >= k || max_fault == 0 || 13205255Sstephh srp->nrecs == max_fault+1) { 13215255Sstephh if (opt_i) { 13225255Sstephh ari_list = uurp->ari_uuid_list; 13235255Sstephh while (ari_list) { 13245255Sstephh (void) printf("%-15s %s\n", 13255255Sstephh format_date(buf, sizeof (buf), 13265255Sstephh uurp->sec), ari_list->ari_uuid); 13275255Sstephh ari_list = ari_list->next; 13285255Sstephh } 13295255Sstephh } else { 13305255Sstephh (void) printf("%-15s %s\n", 13315255Sstephh format_date(buf, sizeof (buf), uurp->sec), 13325255Sstephh uurp->uuid); 13335255Sstephh } 13345255Sstephh } else if (n == j) 13355255Sstephh (void) printf("... %d %s\n", srp->nrecs - max_fault, 13365255Sstephh dgettext("FMD", "more entries suppressed")); 13375255Sstephh n++; 13385255Sstephh } 13395255Sstephh (void) printf("\n"); 13409120SStephen.Hanson@Sun.COM (void) printf("%s %s", dgettext("FMD", "Host :"), 13419120SStephen.Hanson@Sun.COM srp->host->server); 13429120SStephen.Hanson@Sun.COM if (srp->host->domain) 13439120SStephen.Hanson@Sun.COM (void) printf("\t%s %s", dgettext("FMD", "Domain :"), 13449120SStephen.Hanson@Sun.COM srp->host->domain); 13459120SStephen.Hanson@Sun.COM (void) printf("\n%s %s", dgettext("FMD", "Platform :"), 13469120SStephen.Hanson@Sun.COM srp->host->platform); 134710462SSean.Ye@Sun.COM (void) printf("\t%s %s", dgettext("FMD", "Chassis_id :"), 13489120SStephen.Hanson@Sun.COM srp->host->chassis ? srp->host->chassis : ""); 134910462SSean.Ye@Sun.COM (void) printf("\n%s %s\n\n", dgettext("FMD", "Product_sn :"), 135010462SSean.Ye@Sun.COM srp->host->product_sn? srp->host->product_sn : ""); 13515255Sstephh if (srp->class) 13525255Sstephh print_name_list(srp->class, 13535255Sstephh dgettext("FMD", "Fault class :"), NULL, 0, srp->class->pct, 13545255Sstephh NULL, full); 13555255Sstephh if (srp->asru) { 13565255Sstephh status = asru_same_status(srp->asru); 13575255Sstephh if (status != -1) { 13585255Sstephh print_name_list(srp->asru, 13595255Sstephh dgettext("FMD", "Affects :"), NULL, 13605255Sstephh full ? 0 : max_display, 0, NULL, full); 13615255Sstephh print_asru_status(status, " "); 13625255Sstephh } else 13635255Sstephh print_name_list(srp->asru, 13645255Sstephh dgettext("FMD", "Affects :"), NULL, 13655255Sstephh full ? 0 : max_display, 0, print_asru_status, full); 13665255Sstephh } 13679120SStephen.Hanson@Sun.COM if (full || srp->fru == NULL || srp->asru == NULL) { 13685255Sstephh if (srp->resource) { 136910656SStephen.Hanson@Sun.COM status = asru_same_status(srp->resource); 137010656SStephen.Hanson@Sun.COM if (status != -1) { 137110656SStephen.Hanson@Sun.COM print_name_list(srp->resource, 137210656SStephen.Hanson@Sun.COM dgettext("FMD", "Problem in :"), NULL, 137310656SStephen.Hanson@Sun.COM full ? 0 : max_display, 0, NULL, full); 137410656SStephen.Hanson@Sun.COM print_rsrc_status(status, " "); 137510656SStephen.Hanson@Sun.COM } else 137610656SStephen.Hanson@Sun.COM print_name_list(srp->resource, 137710656SStephen.Hanson@Sun.COM dgettext("FMD", "Problem in :"), 137810656SStephen.Hanson@Sun.COM NULL, full ? 0 : max_display, 0, 137910656SStephen.Hanson@Sun.COM print_rsrc_status, full); 13805255Sstephh } 13815255Sstephh } 13825255Sstephh if (srp->fru) { 13836228Sstephh status = asru_same_status(srp->fru); 13846228Sstephh if (status != -1) { 13856228Sstephh print_name_list(srp->fru, dgettext("FMD", 13866228Sstephh "FRU :"), get_fmri_label, 0, 13876228Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct, 13886228Sstephh NULL, full); 13896228Sstephh print_fru_status(status, " "); 13906228Sstephh } else 13916228Sstephh print_name_list(srp->fru, dgettext("FMD", 13926228Sstephh "FRU :"), get_fmri_label, 0, 13936228Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct, 13946228Sstephh print_fru_status, full); 13955255Sstephh } 13965255Sstephh if (srp->serial && !serial_in_fru(srp->fru, srp->serial) && 13975255Sstephh !serial_in_fru(srp->asru, srp->serial)) { 13985255Sstephh print_name_list(srp->serial, dgettext("FMD", "Serial ID. :"), 13995255Sstephh NULL, 0, 0, NULL, full); 14005255Sstephh } 140110234SRobert.Johnston@Sun.COM print_dict_info(srp->uurec->event); 14025255Sstephh (void) printf("\n"); 14035255Sstephh } 14045255Sstephh 14055255Sstephh static void 14065255Sstephh print_status_record(status_record_t *srp, int summary, int opt_i, int full) 14075255Sstephh { 14085255Sstephh char buf[32]; 14095255Sstephh uurec_t *uurp = srp->uurec; 14105255Sstephh static int header = 0; 14115255Sstephh char *head; 14125255Sstephh ari_list_t *ari_list; 14135255Sstephh 14145255Sstephh if (!summary || !header) { 14155255Sstephh if (opt_i) { 14165255Sstephh head = "--------------- " 14175255Sstephh "------------------------------------ " 14185255Sstephh "-------------- ---------\n" 14195255Sstephh "TIME CACHE-ID" 14205255Sstephh " MSG-ID" 14215255Sstephh " SEVERITY\n--------------- " 14225255Sstephh "------------------------------------ " 14235255Sstephh " -------------- ---------"; 14245255Sstephh } else { 14255255Sstephh head = "--------------- " 14265255Sstephh "------------------------------------ " 14275255Sstephh "-------------- ---------\n" 14285255Sstephh "TIME EVENT-ID" 14295255Sstephh " MSG-ID" 14305255Sstephh " SEVERITY\n--------------- " 14315255Sstephh "------------------------------------ " 14325255Sstephh " -------------- ---------"; 14335255Sstephh } 14345255Sstephh (void) printf("%s\n", dgettext("FMD", head)); 14355255Sstephh header = 1; 14365255Sstephh } 14375255Sstephh if (opt_i) { 14385255Sstephh ari_list = uurp->ari_uuid_list; 14395255Sstephh while (ari_list) { 1440*10928SStephen.Hanson@Sun.COM (void) printf("%-15s %-37s %-14s %-9s %s\n", 14415255Sstephh format_date(buf, sizeof (buf), uurp->sec), 1442*10928SStephen.Hanson@Sun.COM ari_list->ari_uuid, srp->msgid, srp->severity, 1443*10928SStephen.Hanson@Sun.COM srp->injected ? dgettext("FMD", "injected") : ""); 14445255Sstephh ari_list = ari_list->next; 14455255Sstephh } 14465255Sstephh } else { 1447*10928SStephen.Hanson@Sun.COM (void) printf("%-15s %-37s %-14s %-9s %s\n", 14485255Sstephh format_date(buf, sizeof (buf), uurp->sec), 1449*10928SStephen.Hanson@Sun.COM uurp->uuid, srp->msgid, srp->severity, 1450*10928SStephen.Hanson@Sun.COM srp->injected ? dgettext("FMD", "injected") : ""); 14515255Sstephh } 14525255Sstephh 14535255Sstephh if (!summary) 14545255Sstephh print_sup_record(srp, opt_i, full); 14555255Sstephh } 14565255Sstephh 14575255Sstephh static void 14585255Sstephh print_catalog(int summary, int opt_a, int full, int opt_i, int page_feed) 14595255Sstephh { 14605255Sstephh status_record_t *srp; 14615255Sstephh sr_list_t *slp; 14625255Sstephh 14635255Sstephh slp = status_rec_list; 14645255Sstephh if (slp) { 14655255Sstephh for (;;) { 14665255Sstephh srp = slp->status_record; 14675255Sstephh if (opt_a || srp->not_suppressed) { 14685255Sstephh if (page_feed) 14695255Sstephh (void) printf("\f\n"); 14705255Sstephh print_status_record(srp, summary, opt_i, full); 14715255Sstephh } 14725255Sstephh if (slp->next == status_rec_list) 14735255Sstephh break; 14745255Sstephh slp = slp->next; 14755255Sstephh } 14765255Sstephh } 14775255Sstephh } 14785255Sstephh 14795255Sstephh static name_list_t * 14805255Sstephh find_fru(status_record_t *srp, char *resource) 14815255Sstephh { 14825255Sstephh name_list_t *rt = NULL; 14835255Sstephh name_list_t *fru = srp->fru; 14845255Sstephh 14855255Sstephh while (fru) { 14865255Sstephh if (strcmp(resource, fru->name) == 0) { 14875255Sstephh rt = fru; 14885255Sstephh break; 14895255Sstephh } 14905255Sstephh fru = fru->next; 14915255Sstephh if (fru == srp->fru) 14925255Sstephh break; 14935255Sstephh } 14945255Sstephh return (rt); 14955255Sstephh } 14965255Sstephh 14975255Sstephh static void 14985255Sstephh print_fru_line(name_list_t *fru, char *uuid) 14995255Sstephh { 15005255Sstephh if (fru->pct == 100) { 15015255Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count, 15025255Sstephh dgettext("FMD", "suspects in this FRU total certainty"), 15035255Sstephh 100); 15045255Sstephh } else { 15055255Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count, 15065255Sstephh dgettext("FMD", "suspects in this FRU max certainty"), 15075255Sstephh fru->max_pct); 15085255Sstephh } 15095255Sstephh } 15105255Sstephh 15115255Sstephh static void 15125255Sstephh print_fru(int summary, int opt_a, int opt_i, int page_feed) 15135255Sstephh { 15145255Sstephh resource_list_t *tp = status_fru_list; 15155255Sstephh status_record_t *srp; 15165255Sstephh sr_list_t *slp, *end; 15175255Sstephh char *msgid, *fru_label; 15185255Sstephh uurec_t *uurp; 15195255Sstephh name_list_t *fru; 15206228Sstephh int status; 15215255Sstephh ari_list_t *ari_list; 15225255Sstephh 15235255Sstephh while (tp) { 15245255Sstephh if (opt_a || tp->not_suppressed) { 15255255Sstephh if (page_feed) 15265255Sstephh (void) printf("\f\n"); 15275255Sstephh if (!summary) 15285255Sstephh (void) printf("-----------------------------" 15295255Sstephh "---------------------------------------" 15305255Sstephh "----------\n"); 15316002Sstephh slp = tp->status_rec_list; 15326002Sstephh end = slp; 15336002Sstephh do { 15346002Sstephh srp = slp->status_record; 15356002Sstephh fru = find_fru(srp, tp->resource); 15366002Sstephh if (fru) { 15376002Sstephh if (fru->label) 15386228Sstephh (void) printf("\"%s\" (%s) ", 15396002Sstephh fru->label, fru->name); 15406228Sstephh else if ((fru_label = get_fmri_label( 15416228Sstephh fru->name)) != NULL) { 15426228Sstephh (void) printf("\"%s\" (%s) ", 15436002Sstephh fru_label, fru->name); 15446002Sstephh free(fru_label); 15456002Sstephh } else 15466228Sstephh (void) printf("%s ", 15476002Sstephh fru->name); 15486002Sstephh break; 15496002Sstephh } 15506002Sstephh slp = slp->next; 15516002Sstephh } while (slp != end); 15526002Sstephh 15535255Sstephh slp = tp->status_rec_list; 15545255Sstephh end = slp; 15556228Sstephh status = 0; 15566228Sstephh do { 15576228Sstephh srp = slp->status_record; 15586228Sstephh fru = srp->fru; 15596228Sstephh while (fru) { 15606228Sstephh if (strcmp(tp->resource, 15616228Sstephh fru->name) == 0) 15626228Sstephh status |= fru->status; 15636228Sstephh fru = fru->next; 15646228Sstephh if (fru == srp->fru) 15656228Sstephh break; 15666228Sstephh } 15676228Sstephh slp = slp->next; 15686228Sstephh } while (slp != end); 15696228Sstephh if (status & FM_SUSPECT_NOT_PRESENT) 1570*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "not present")); 15716228Sstephh else if (status & FM_SUSPECT_FAULTY) 1572*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "faulty")); 15737275Sstephh else if (status & FM_SUSPECT_REPLACED) 1574*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "replaced")); 15757275Sstephh else if (status & FM_SUSPECT_REPAIRED) 15767275Sstephh (void) printf(dgettext("FMD", 1577*10928SStephen.Hanson@Sun.COM "repair attempted")); 15787275Sstephh else if (status & FM_SUSPECT_ACQUITTED) 1579*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "acquitted")); 15806228Sstephh else 1581*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "removed")); 1582*10928SStephen.Hanson@Sun.COM 1583*10928SStephen.Hanson@Sun.COM if (tp->injected) 1584*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", " injected\n")); 1585*10928SStephen.Hanson@Sun.COM else 1586*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "\n")); 15876228Sstephh 15886228Sstephh slp = tp->status_rec_list; 15896228Sstephh end = slp; 15905255Sstephh do { 15915255Sstephh srp = slp->status_record; 15925255Sstephh uurp = srp->uurec; 15935255Sstephh fru = find_fru(srp, tp->resource); 15945255Sstephh if (fru) { 15955255Sstephh if (opt_i) { 15965255Sstephh ari_list = uurp->ari_uuid_list; 15975255Sstephh while (ari_list) { 15985255Sstephh print_fru_line(fru, 15995255Sstephh ari_list->ari_uuid); 16005255Sstephh ari_list = 16015255Sstephh ari_list->next; 16025255Sstephh } 16035255Sstephh } else { 16045255Sstephh print_fru_line(fru, uurp->uuid); 16055255Sstephh } 16065255Sstephh } 16075255Sstephh slp = slp->next; 16085255Sstephh } while (slp != end); 16095255Sstephh if (!summary) { 16105255Sstephh slp = tp->status_rec_list; 16115255Sstephh end = slp; 16125255Sstephh srp = slp->status_record; 16135255Sstephh if (srp->serial && 16145255Sstephh !serial_in_fru(srp->fru, srp->serial)) { 16155255Sstephh print_name_list(srp->serial, 16165255Sstephh dgettext("FMD", "Serial ID. :"), 16175255Sstephh NULL, 0, 0, NULL, 1); 16185255Sstephh } 16195255Sstephh msgid = NULL; 16205255Sstephh do { 16215255Sstephh if (msgid == NULL || 16225255Sstephh strcmp(msgid, srp->msgid) != 0) { 16235255Sstephh msgid = srp->msgid; 162410234SRobert.Johnston@Sun.COM print_dict_info(uurp->event); 16255255Sstephh } 16265255Sstephh slp = slp->next; 16275255Sstephh } while (slp != end); 16285255Sstephh } 16295255Sstephh } 16305255Sstephh tp = tp->next; 16315255Sstephh if (tp == status_fru_list) 16325255Sstephh break; 16335255Sstephh } 16345255Sstephh } 16355255Sstephh 16365255Sstephh static void 16375255Sstephh print_asru(int opt_a) 16385255Sstephh { 16395255Sstephh resource_list_t *tp = status_asru_list; 16405255Sstephh status_record_t *srp; 16415255Sstephh sr_list_t *slp, *end; 16425255Sstephh char *msg; 16435255Sstephh int status; 16445255Sstephh name_list_t *asru; 16455255Sstephh 16465255Sstephh while (tp) { 16475255Sstephh if (opt_a || tp->not_suppressed) { 16485255Sstephh status = 0; 16495255Sstephh slp = tp->status_rec_list; 16505255Sstephh end = slp; 16515255Sstephh do { 16525255Sstephh srp = slp->status_record; 16535255Sstephh asru = srp->asru; 16545255Sstephh while (asru) { 16555255Sstephh if (strcmp(tp->resource, 16565255Sstephh asru->name) == 0) 16575255Sstephh status |= asru->status; 16585255Sstephh asru = asru->next; 16595255Sstephh if (asru == srp->asru) 16605255Sstephh break; 16615255Sstephh } 16625255Sstephh slp = slp->next; 16635255Sstephh } while (slp != end); 16645255Sstephh switch (status) { 16655255Sstephh case 0: 16665255Sstephh msg = dgettext("FMD", "ok"); 16675255Sstephh break; 16687275Sstephh case FM_SUSPECT_DEGRADED: 16697275Sstephh msg = dgettext("FMD", "degraded"); 16707275Sstephh break; 16717275Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED: 16727275Sstephh msg = dgettext("FMD", "degraded"); 16737275Sstephh break; 16745255Sstephh case FM_SUSPECT_FAULTY: 16755255Sstephh msg = dgettext("FMD", "degraded"); 16765255Sstephh break; 16775255Sstephh case FM_SUSPECT_UNUSABLE: 16785255Sstephh msg = dgettext("FMD", "unknown"); 16795255Sstephh break; 16805255Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE: 16815255Sstephh msg = dgettext("FMD", "faulted"); 16825255Sstephh break; 16835255Sstephh default: 16845255Sstephh msg = ""; 16855255Sstephh break; 16865255Sstephh } 1687*10928SStephen.Hanson@Sun.COM (void) printf("%-69s %s", tp->resource, msg); 1688*10928SStephen.Hanson@Sun.COM if (tp->injected) 1689*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", " injected\n")); 1690*10928SStephen.Hanson@Sun.COM else 1691*10928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "\n")); 16925255Sstephh } 16935255Sstephh tp = tp->next; 16945255Sstephh if (tp == status_asru_list) 16955255Sstephh break; 16965255Sstephh } 16975255Sstephh } 16985255Sstephh 16995255Sstephh static int 17005255Sstephh uuid_in_list(char *uuid, uurec_select_t *uurecp) 17015255Sstephh { 17025255Sstephh while (uurecp) { 17035255Sstephh if (strcmp(uuid, uurecp->uuid) == 0) 17045255Sstephh return (1); 17055255Sstephh uurecp = uurecp->next; 17065255Sstephh } 17070Sstevel@tonic-gate return (0); 17080Sstevel@tonic-gate } 17090Sstevel@tonic-gate 17105255Sstephh static int 17115255Sstephh dfault_rec(const fmd_adm_caseinfo_t *acp, void *arg) 17125255Sstephh { 17135255Sstephh int64_t *diag_time; 17145255Sstephh uint_t nelem; 17155255Sstephh int rt = 0; 17165255Sstephh char *uuid = "-"; 17175255Sstephh uurec_select_t *uurecp = (uurec_select_t *)arg; 17185255Sstephh 17195255Sstephh if (nvlist_lookup_int64_array(acp->aci_event, FM_SUSPECT_DIAG_TIME, 17205255Sstephh &diag_time, &nelem) == 0 && nelem >= 2) { 17215255Sstephh (void) nvlist_lookup_string(acp->aci_event, FM_SUSPECT_UUID, 17225255Sstephh &uuid); 17235255Sstephh if (uurecp == NULL || uuid_in_list(uuid, uurecp)) 17245255Sstephh add_fault_record_to_catalog(acp->aci_event, *diag_time, 17259501SRobert.Johnston@Sun.COM uuid); 17265255Sstephh } else { 17275255Sstephh rt = -1; 17285255Sstephh } 17295255Sstephh return (rt); 17305255Sstephh } 17315255Sstephh 17320Sstevel@tonic-gate /*ARGSUSED*/ 17330Sstevel@tonic-gate static int 17345255Sstephh dstatus_rec(const fmd_adm_rsrcinfo_t *ari, void *unused) 17350Sstevel@tonic-gate { 17365255Sstephh update_asru_state_in_catalog(ari->ari_case, ari->ari_uuid); 17370Sstevel@tonic-gate return (0); 17380Sstevel@tonic-gate } 17390Sstevel@tonic-gate 17405255Sstephh static int 17415255Sstephh get_cases_from_fmd(fmd_adm_t *adm, uurec_select_t *uurecp, int opt_i) 17425255Sstephh { 17435255Sstephh int rt = FMADM_EXIT_SUCCESS; 17445255Sstephh 17455255Sstephh /* 174610234SRobert.Johnston@Sun.COM * These calls may fail with Protocol error if message payload is 174710234SRobert.Johnston@Sun.COM * too big 17485255Sstephh */ 17495255Sstephh if (fmd_adm_case_iter(adm, NULL, dfault_rec, uurecp) != 0) 17505255Sstephh die("failed to get case list from fmd"); 17515255Sstephh if (opt_i && fmd_adm_rsrc_iter(adm, 1, dstatus_rec, NULL) != 0) 17525255Sstephh die("failed to get case status from fmd"); 17535255Sstephh return (rt); 17545255Sstephh } 17555255Sstephh 17565255Sstephh /* 17575255Sstephh * fmadm faulty command 17585255Sstephh * 17595255Sstephh * -a show hidden fault records 17605255Sstephh * -f show faulty fru's 17615255Sstephh * -g force grouping of similar faults on the same fru 17625255Sstephh * -n number of fault records to display 17635255Sstephh * -p pipe output through pager 17645255Sstephh * -r show faulty asru's 17655255Sstephh * -s print summary of first fault 17665255Sstephh * -u print listed uuid's only 17675255Sstephh * -v full output 17685255Sstephh */ 17695255Sstephh 17700Sstevel@tonic-gate int 17710Sstevel@tonic-gate cmd_faulty(fmd_adm_t *adm, int argc, char *argv[]) 17720Sstevel@tonic-gate { 17735255Sstephh int opt_a = 0, opt_v = 0, opt_p = 0, opt_s = 0, opt_r = 0, opt_f = 0; 17745255Sstephh int opt_i = 0; 17755255Sstephh char *pager; 17765255Sstephh FILE *fp; 17775255Sstephh int rt, c, stat; 17785255Sstephh uurec_select_t *tp; 17795255Sstephh uurec_select_t *uurecp = NULL; 17800Sstevel@tonic-gate 17815255Sstephh while ((c = getopt(argc, argv, "afgin:prsu:v")) != EOF) { 17820Sstevel@tonic-gate switch (c) { 17830Sstevel@tonic-gate case 'a': 17840Sstevel@tonic-gate opt_a++; 17850Sstevel@tonic-gate break; 17865255Sstephh case 'f': 17875255Sstephh opt_f++; 17885255Sstephh break; 17895255Sstephh case 'g': 17905255Sstephh opt_g++; 17915255Sstephh break; 17920Sstevel@tonic-gate case 'i': 17935255Sstephh opt_i++; 17945255Sstephh break; 17955255Sstephh case 'n': 17965255Sstephh max_fault = atoi(optarg); 17975255Sstephh break; 17985255Sstephh case 'p': 17995255Sstephh opt_p++; 18005255Sstephh break; 18015255Sstephh case 'r': 18025255Sstephh opt_r++; 18035255Sstephh break; 18045255Sstephh case 's': 18055255Sstephh opt_s++; 18065255Sstephh break; 18075255Sstephh case 'u': 18085255Sstephh tp = (uurec_select_t *)malloc(sizeof (uurec_select_t)); 18095255Sstephh tp->uuid = optarg; 18105255Sstephh tp->next = uurecp; 18115255Sstephh uurecp = tp; 18125255Sstephh opt_a = 1; 18135255Sstephh break; 18145255Sstephh case 'v': 18155255Sstephh opt_v++; 18160Sstevel@tonic-gate break; 18170Sstevel@tonic-gate default: 18180Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18190Sstevel@tonic-gate } 18200Sstevel@tonic-gate } 18210Sstevel@tonic-gate if (optind < argc) 18220Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18230Sstevel@tonic-gate 18249501SRobert.Johnston@Sun.COM if ((fmadm_msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) == NULL) 18259501SRobert.Johnston@Sun.COM return (FMADM_EXIT_ERROR); 18265255Sstephh rt = get_cases_from_fmd(adm, uurecp, opt_i); 18275255Sstephh if (opt_p) { 18285255Sstephh if ((pager = getenv("PAGER")) == NULL) 18295255Sstephh pager = "/usr/bin/more"; 18305255Sstephh fp = popen(pager, "w"); 18315255Sstephh if (fp == NULL) { 18325255Sstephh rt = FMADM_EXIT_ERROR; 18335255Sstephh opt_p = 0; 18345255Sstephh } else { 18355255Sstephh dup2(fileno(fp), 1); 18365255Sstephh setbuf(stdout, NULL); 18375255Sstephh (void) fclose(fp); 18385255Sstephh } 18395255Sstephh } 18405255Sstephh max_display = max_fault; 18415255Sstephh if (opt_f) 18425255Sstephh print_fru(opt_s, opt_a, opt_i, opt_p && !opt_s); 18435255Sstephh if (opt_r) 18445255Sstephh print_asru(opt_a); 18455255Sstephh if (opt_f == 0 && opt_r == 0) 18465255Sstephh print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s); 18479501SRobert.Johnston@Sun.COM fmd_msg_fini(fmadm_msghdl); 18485255Sstephh label_release_topo(); 18495255Sstephh if (opt_p) { 18505255Sstephh (void) fclose(stdout); 18515255Sstephh (void) wait(&stat); 18525255Sstephh } 18535255Sstephh return (rt); 18540Sstevel@tonic-gate } 18550Sstevel@tonic-gate 18560Sstevel@tonic-gate int 18570Sstevel@tonic-gate cmd_flush(fmd_adm_t *adm, int argc, char *argv[]) 18580Sstevel@tonic-gate { 18590Sstevel@tonic-gate int i, status = FMADM_EXIT_SUCCESS; 18600Sstevel@tonic-gate 18610Sstevel@tonic-gate if (argc < 2 || (i = getopt(argc, argv, "")) != EOF) 18620Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18630Sstevel@tonic-gate 18640Sstevel@tonic-gate for (i = 1; i < argc; i++) { 18650Sstevel@tonic-gate if (fmd_adm_rsrc_flush(adm, argv[i]) != 0) { 18660Sstevel@tonic-gate warn("failed to flush %s", argv[i]); 18670Sstevel@tonic-gate status = FMADM_EXIT_ERROR; 18680Sstevel@tonic-gate } else 18690Sstevel@tonic-gate note("flushed resource history for %s\n", argv[i]); 18700Sstevel@tonic-gate } 18710Sstevel@tonic-gate 18720Sstevel@tonic-gate return (status); 18730Sstevel@tonic-gate } 18740Sstevel@tonic-gate 18750Sstevel@tonic-gate int 18760Sstevel@tonic-gate cmd_repair(fmd_adm_t *adm, int argc, char *argv[]) 18770Sstevel@tonic-gate { 18780Sstevel@tonic-gate int err; 18790Sstevel@tonic-gate 18800Sstevel@tonic-gate if (getopt(argc, argv, "") != EOF) 18810Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18820Sstevel@tonic-gate 18830Sstevel@tonic-gate if (argc - optind != 1) 18840Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18850Sstevel@tonic-gate 18860Sstevel@tonic-gate /* 18877275Sstephh * argument could be a uuid, an fmri (asru, fru or resource) 18886228Sstephh * or a label. Try uuid first, If that fails try the others. 18890Sstevel@tonic-gate */ 18906228Sstephh err = fmd_adm_case_repair(adm, argv[optind]); 18916228Sstephh if (err != 0) 18927275Sstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]); 18930Sstevel@tonic-gate 18940Sstevel@tonic-gate if (err != 0) 18950Sstevel@tonic-gate die("failed to record repair to %s", argv[optind]); 18960Sstevel@tonic-gate 18970Sstevel@tonic-gate note("recorded repair to %s\n", argv[optind]); 18980Sstevel@tonic-gate return (FMADM_EXIT_SUCCESS); 18990Sstevel@tonic-gate } 19007275Sstephh 19017275Sstephh int 19027275Sstephh cmd_repaired(fmd_adm_t *adm, int argc, char *argv[]) 19037275Sstephh { 19047275Sstephh int err; 19057275Sstephh 19067275Sstephh if (getopt(argc, argv, "") != EOF) 19077275Sstephh return (FMADM_EXIT_USAGE); 19087275Sstephh 19097275Sstephh if (argc - optind != 1) 19107275Sstephh return (FMADM_EXIT_USAGE); 19117275Sstephh 19127275Sstephh /* 19137275Sstephh * argument could be an fmri (asru, fru or resource) or a label. 19147275Sstephh */ 19157275Sstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]); 19167275Sstephh if (err != 0) 19177275Sstephh die("failed to record repair to %s", argv[optind]); 19187275Sstephh 19197275Sstephh note("recorded repair to of %s\n", argv[optind]); 19207275Sstephh return (FMADM_EXIT_SUCCESS); 19217275Sstephh } 19227275Sstephh 19237275Sstephh int 19247275Sstephh cmd_replaced(fmd_adm_t *adm, int argc, char *argv[]) 19257275Sstephh { 19267275Sstephh int err; 19277275Sstephh 19287275Sstephh if (getopt(argc, argv, "") != EOF) 19297275Sstephh return (FMADM_EXIT_USAGE); 19307275Sstephh 19317275Sstephh if (argc - optind != 1) 19327275Sstephh return (FMADM_EXIT_USAGE); 19337275Sstephh 19347275Sstephh /* 19357275Sstephh * argument could be an fmri (asru, fru or resource) or a label. 19367275Sstephh */ 19377275Sstephh err = fmd_adm_rsrc_replaced(adm, argv[optind]); 19387275Sstephh if (err != 0) 19397275Sstephh die("failed to record replacement of %s", argv[optind]); 19407275Sstephh 19417275Sstephh note("recorded replacement of %s\n", argv[optind]); 19427275Sstephh return (FMADM_EXIT_SUCCESS); 19437275Sstephh } 19447275Sstephh 19457275Sstephh int 19467275Sstephh cmd_acquit(fmd_adm_t *adm, int argc, char *argv[]) 19477275Sstephh { 19487275Sstephh int err; 19497275Sstephh 19507275Sstephh if (getopt(argc, argv, "") != EOF) 19517275Sstephh return (FMADM_EXIT_USAGE); 19527275Sstephh 19537275Sstephh if (argc - optind != 1 && argc - optind != 2) 19547275Sstephh return (FMADM_EXIT_USAGE); 19557275Sstephh 19567275Sstephh /* 19577275Sstephh * argument could be a uuid, an fmri (asru, fru or resource) 19587275Sstephh * or a label. Or it could be a uuid and an fmri or label. 19597275Sstephh */ 19607275Sstephh if (argc - optind == 2) { 19617275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], argv[optind + 1]); 19627275Sstephh if (err != 0) 19637275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind + 1], 19647275Sstephh argv[optind]); 19657275Sstephh } else { 19667275Sstephh err = fmd_adm_case_acquit(adm, argv[optind]); 19677275Sstephh if (err != 0) 19687275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], ""); 19697275Sstephh } 19707275Sstephh 19717275Sstephh if (err != 0) 19727275Sstephh die("failed to record acquital of %s", argv[optind]); 19737275Sstephh 19747275Sstephh note("recorded acquital of %s\n", argv[optind]); 19757275Sstephh return (FMADM_EXIT_SUCCESS); 19767275Sstephh } 1977