17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 544743693Sstephh * Common Development and Distribution License (the "License"). 644743693Sstephh * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22cbf75e67SStephen Hanson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 2644743693Sstephh #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <fmadm.h> 2844743693Sstephh #include <errno.h> 2944743693Sstephh #include <limits.h> 3044743693Sstephh #include <strings.h> 3144743693Sstephh #include <stdio.h> 3244743693Sstephh #include <unistd.h> 3344743693Sstephh #include <sys/wait.h> 3444743693Sstephh #include <sys/stat.h> 3544743693Sstephh #include <fcntl.h> 3644743693Sstephh #include <fm/fmd_log.h> 3744743693Sstephh #include <sys/fm/protocol.h> 3844743693Sstephh #include <fm/libtopo.h> 3944743693Sstephh #include <fm/fmd_adm.h> 40*b6955755SRobert Johnston #include <fm/fmd_msg.h> 4144743693Sstephh #include <dlfcn.h> 4244743693Sstephh #include <sys/systeminfo.h> 4344743693Sstephh #include <sys/utsname.h> 4444743693Sstephh #include <libintl.h> 4544743693Sstephh #include <locale.h> 4644743693Sstephh #include <sys/smbios.h> 4744743693Sstephh #include <libdevinfo.h> 4844743693Sstephh #include <stdlib.h> 4944743693Sstephh 5044743693Sstephh #define offsetof(s, m) ((size_t)(&(((s*)0)->m))) 5144743693Sstephh 5244743693Sstephh /* 5344743693Sstephh * Fault records are added to catalog by calling add_fault_record_to_catalog() 5444743693Sstephh * records are stored in order of importance to the system. 5544743693Sstephh * If -g flag is set or not_suppressed is not set and the class fru, fault, 5644743693Sstephh * type are the same then details are merged into an existing record, with uuid 5744743693Sstephh * records are stored in time order. 5844743693Sstephh * For each record information is extracted from nvlist and merged into linked 5944743693Sstephh * list each is checked for identical records for which percentage certainty are 6044743693Sstephh * added together. 6144743693Sstephh * print_catalog() is called to print out catalog and release external resources 6244743693Sstephh * 6344743693Sstephh * /---------------\ 6444743693Sstephh * status_rec_list -> | | -| 6544743693Sstephh * \---------------/ 6644743693Sstephh * \/ 6744743693Sstephh * /---------------\ /-------\ /-------\ 6844743693Sstephh * status_fru_list | status_record | -> | uurec | -> | uurec | -| 6944743693Sstephh * \/ | | |- | | <- | | 7044743693Sstephh * /-------------\ | | \-------/ \-------/ 7144743693Sstephh * | | -> | | \/ \/ 7244743693Sstephh * \-------------/ | | /-------\ /-------\ 7344743693Sstephh * \/ | | -> | asru | -> | asru | 7444743693Sstephh * --- | | | | <- | | 7544743693Sstephh * | | \-------/ \-------/ 7644743693Sstephh * status_asru_list | class | 7744743693Sstephh * \/ | resource | /-------\ /-------\ 7844743693Sstephh * /-------------\ | fru | -> | list | -> | list | 7944743693Sstephh * | | -> | serial | | | <- | | 8044743693Sstephh * \-------------/ | | \-------/ \-------/ 8144743693Sstephh * \/ \---------------/ 8244743693Sstephh * --- \/ /\ 8344743693Sstephh * /---------------\ 8444743693Sstephh * | status_record | 8544743693Sstephh * \---------------/ 8644743693Sstephh * 8744743693Sstephh * Fmadm faulty takes a number of options which affect the format of the 8844743693Sstephh * output displayed. By default, the display reports the FRU and ASRU along 8944743693Sstephh * with other information on per-case basis as in the example below. 9044743693Sstephh * 9144743693Sstephh * --------------- ------------------------------------ -------------- ------- 9244743693Sstephh * TIME EVENT-ID MSG-ID SEVERITY 9344743693Sstephh * --------------- ------------------------------------ -------------- ------- 9444743693Sstephh * Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c AMD-8000-2F Major 9544743693Sstephh * 9644743693Sstephh * Fault class : fault.memory.dimm_sb 9744743693Sstephh * Affects : mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 9825c6ff4bSstephh * faulted but still in service 9944743693Sstephh * FRU : "CPU 0 DIMM 0" (hc://.../memory-controller=0/dimm=0) 10044743693Sstephh * faulty 10144743693Sstephh * 10244743693Sstephh * Description : The number of errors associated with this memory module has 10344743693Sstephh * exceeded acceptable levels. Refer to 10444743693Sstephh * http://sun.com/msg/AMD-8000-2F for more information. 10544743693Sstephh * 10644743693Sstephh * Response : Pages of memory associated with this memory module are being 10744743693Sstephh * removed from service as errors are reported. 10844743693Sstephh * 10944743693Sstephh * Impact : Total system memory capacity will be reduced as pages are 11044743693Sstephh * retired. 11144743693Sstephh * 11244743693Sstephh * Action : Schedule a repair procedure to replace the affected memory 11344743693Sstephh * module. Use fmdump -v -u <EVENT_ID> to identify the module. 11444743693Sstephh * 11544743693Sstephh * The -v flag is similar, but adds some additonal information such as the 11644743693Sstephh * resource. The -s flag is also similar but just gives the top line summary. 11744743693Sstephh * All these options (ie without the -f or -r flags) use the print_catalog() 11844743693Sstephh * function to do the display. 11944743693Sstephh * 12044743693Sstephh * The -f flag changes the output so that it appears sorted on a per-fru basis. 12144743693Sstephh * The output is somewhat cut down compared to the default output. If -f is 12244743693Sstephh * used, then print_fru() is used to print the output. 12344743693Sstephh * 12444743693Sstephh * ----------------------------------------------------------------------------- 12544743693Sstephh * "SLOT 2" (hc://.../hostbridge=3/pciexrc=3/pciexbus=4/pciexdev=0) faulty 12644743693Sstephh * 5ca4aeb3-36...f6be-c2e8166dc484 2 suspects in this FRU total certainty 100% 12744743693Sstephh * 12844743693Sstephh * Description : A problem was detected for a PCI device. 12944743693Sstephh * Refer to http://sun.com/msg/PCI-8000-7J for more information. 13044743693Sstephh * 13144743693Sstephh * Response : One or more device instances may be disabled 13244743693Sstephh * 13344743693Sstephh * Impact : Possible loss of services provided by the device instances 13444743693Sstephh * associated with this fault 13544743693Sstephh * 13644743693Sstephh * Action : Schedule a repair procedure to replace the affected device. 13744743693Sstephh * Use fmdump -v -u <EVENT_ID> to identify the device or contact 13844743693Sstephh * Sun for support. 13944743693Sstephh * 14044743693Sstephh * The -r flag changes the output so that it appears sorted on a per-asru basis. 14144743693Sstephh * The output is very much cut down compared to the default output, just giving 14244743693Sstephh * the asru fmri and state. Here print_asru() is used to print the output. 14344743693Sstephh * 14444743693Sstephh * mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 degraded 14544743693Sstephh * 14644743693Sstephh * For all fmadm faulty options, the sequence of events is 14744743693Sstephh * 14844743693Sstephh * 1) Walk through all the cases in the system using fmd_adm_case_iter() and 14944743693Sstephh * for each case call dfault_rec(). This will call add_fault_record_to_catalog() 15044743693Sstephh * This will extract the data from the nvlist and call catalog_new_record() to 15144743693Sstephh * save the data away in various linked lists in the catalogue. 15244743693Sstephh * 15344743693Sstephh * 2) Once this is done, the data can be supplemented by using 15444743693Sstephh * fmd_adm_rsrc_iter(). However this is now only necessary for the -i option. 15544743693Sstephh * 15644743693Sstephh * 3) Finally print_catalog(), print_fru() or print_asru() are called as 15744743693Sstephh * appropriate to display the information from the catalogue sorted in the 15844743693Sstephh * requested way. 15944743693Sstephh * 16044743693Sstephh */ 16144743693Sstephh 16244743693Sstephh typedef struct name_list { 16344743693Sstephh struct name_list *next; 16444743693Sstephh struct name_list *prev; 16544743693Sstephh char *name; 16644743693Sstephh uint8_t pct; 16744743693Sstephh uint8_t max_pct; 16844743693Sstephh ushort_t count; 16944743693Sstephh int status; 170d4c0a8c5Sstephh char *label; 17144743693Sstephh } name_list_t; 17244743693Sstephh 17344743693Sstephh typedef struct ari_list { 17444743693Sstephh char *ari_uuid; 17544743693Sstephh struct ari_list *next; 17644743693Sstephh } ari_list_t; 17744743693Sstephh 17844743693Sstephh typedef struct uurec { 17944743693Sstephh struct uurec *next; 18044743693Sstephh struct uurec *prev; 18144743693Sstephh char *uuid; 18244743693Sstephh ari_list_t *ari_uuid_list; 18344743693Sstephh name_list_t *asru; 18444743693Sstephh uint64_t sec; 18544743693Sstephh } uurec_t; 18644743693Sstephh 18744743693Sstephh typedef struct uurec_select { 18844743693Sstephh struct uurec_select *next; 18944743693Sstephh char *uuid; 19044743693Sstephh } uurec_select_t; 19144743693Sstephh 19244743693Sstephh typedef struct host_id { 19344743693Sstephh char *chassis; 19444743693Sstephh char *server; 19544743693Sstephh char *platform; 196cbf75e67SStephen Hanson char *domain; 19744743693Sstephh } hostid_t; 19844743693Sstephh 19944743693Sstephh typedef struct host_id_list { 20044743693Sstephh hostid_t hostid; 20144743693Sstephh struct host_id_list *next; 20244743693Sstephh } host_id_list_t; 20344743693Sstephh 20444743693Sstephh typedef struct status_record { 20544743693Sstephh hostid_t *host; 20644743693Sstephh int nrecs; 20744743693Sstephh uurec_t *uurec; 20844743693Sstephh char *severity; /* in C locale */ 20944743693Sstephh char *msgid; 21044743693Sstephh name_list_t *class; 21144743693Sstephh name_list_t *resource; 21244743693Sstephh name_list_t *asru; 21344743693Sstephh name_list_t *fru; 21444743693Sstephh name_list_t *serial; 21544743693Sstephh uint8_t not_suppressed; 21644743693Sstephh } status_record_t; 21744743693Sstephh 21844743693Sstephh typedef struct sr_list { 21944743693Sstephh struct sr_list *next; 22044743693Sstephh struct sr_list *prev; 22144743693Sstephh struct status_record *status_record; 22244743693Sstephh } sr_list_t; 22344743693Sstephh 22444743693Sstephh typedef struct resource_list { 22544743693Sstephh struct resource_list *next; 22644743693Sstephh struct resource_list *prev; 22744743693Sstephh sr_list_t *status_rec_list; 22844743693Sstephh char *resource; 22944743693Sstephh uint8_t not_suppressed; 23044743693Sstephh uint8_t max_pct; 23144743693Sstephh } resource_list_t; 23244743693Sstephh 23344743693Sstephh typedef struct tgetlabel_data { 23444743693Sstephh char *label; 23544743693Sstephh char *fru; 23644743693Sstephh } tgetlabel_data_t; 23744743693Sstephh 23844743693Sstephh sr_list_t *status_rec_list; 23944743693Sstephh resource_list_t *status_fru_list; 24044743693Sstephh resource_list_t *status_asru_list; 24144743693Sstephh 24244743693Sstephh static int max_display; 24344743693Sstephh static int max_fault = 0; 24444743693Sstephh static topo_hdl_t *topo_handle; 24544743693Sstephh static char *topo_handle_uuid; 24644743693Sstephh static host_id_list_t *host_list; 24744743693Sstephh static int n_server; 24844743693Sstephh static int opt_g; 249*b6955755SRobert Johnston static fmd_msg_hdl_t *fmadm_msghdl = NULL; /* handle for libfmd_msg calls */ 25044743693Sstephh 25144743693Sstephh static char * 25244743693Sstephh format_date(char *buf, size_t len, uint64_t sec) 25344743693Sstephh { 25444743693Sstephh if (sec > LONG_MAX) { 25544743693Sstephh (void) fprintf(stderr, 25644743693Sstephh "record time is too large for 32-bit utility\n"); 25744743693Sstephh (void) snprintf(buf, len, "0x%llx", sec); 25844743693Sstephh } else { 25944743693Sstephh time_t tod = (time_t)sec; 26044743693Sstephh (void) strftime(buf, len, "%b %d %T", localtime(&tod)); 26144743693Sstephh } 26244743693Sstephh 26344743693Sstephh return (buf); 26444743693Sstephh } 26544743693Sstephh 26644743693Sstephh static hostid_t * 267cbf75e67SStephen Hanson find_hostid_in_list(char *platform, char *chassis, char *server, char *domain) 26844743693Sstephh { 26944743693Sstephh hostid_t *rt = NULL; 27044743693Sstephh host_id_list_t *hostp; 27144743693Sstephh 27244743693Sstephh if (platform == NULL) 27344743693Sstephh platform = "-"; 27444743693Sstephh if (server == NULL) 27544743693Sstephh server = "-"; 27644743693Sstephh hostp = host_list; 27744743693Sstephh while (hostp) { 27844743693Sstephh if (hostp->hostid.platform && 27944743693Sstephh strcmp(hostp->hostid.platform, platform) == 0 && 28044743693Sstephh hostp->hostid.server && 28144743693Sstephh strcmp(hostp->hostid.server, server) == 0 && 28244743693Sstephh (chassis == NULL || hostp->hostid.chassis == NULL || 283cbf75e67SStephen Hanson strcmp(chassis, hostp->hostid.chassis) == 0) && 284cbf75e67SStephen Hanson (domain == NULL || hostp->hostid.domain == NULL || 285cbf75e67SStephen Hanson strcmp(domain, hostp->hostid.domain) == 0)) { 28644743693Sstephh rt = &hostp->hostid; 28744743693Sstephh break; 28844743693Sstephh } 28944743693Sstephh hostp = hostp->next; 29044743693Sstephh } 29144743693Sstephh if (rt == NULL) { 29244743693Sstephh hostp = malloc(sizeof (host_id_list_t)); 29344743693Sstephh hostp->hostid.platform = strdup(platform); 29444743693Sstephh hostp->hostid.server = strdup(server); 29544743693Sstephh hostp->hostid.chassis = chassis ? strdup(chassis) : NULL; 296cbf75e67SStephen Hanson hostp->hostid.domain = domain ? strdup(domain) : NULL; 29744743693Sstephh hostp->next = host_list; 29844743693Sstephh host_list = hostp; 29944743693Sstephh rt = &hostp->hostid; 30044743693Sstephh n_server++; 30144743693Sstephh } 30244743693Sstephh return (rt); 30344743693Sstephh } 30444743693Sstephh 30544743693Sstephh static hostid_t * 30644743693Sstephh find_hostid(nvlist_t *nvl) 30744743693Sstephh { 308cbf75e67SStephen Hanson char *platform = NULL, *chassis = NULL, *server = NULL, *domain = NULL; 30944743693Sstephh nvlist_t *auth, *fmri; 31044743693Sstephh hostid_t *rt = NULL; 31144743693Sstephh 31244743693Sstephh if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &fmri) == 0 && 31344743693Sstephh nvlist_lookup_nvlist(fmri, FM_FMRI_AUTHORITY, &auth) == 0) { 31444743693Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, 31544743693Sstephh &platform); 31644743693Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server); 31744743693Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, 31844743693Sstephh &chassis); 319cbf75e67SStephen Hanson (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_DOMAIN, &domain); 320cbf75e67SStephen Hanson rt = find_hostid_in_list(platform, chassis, server, domain); 32144743693Sstephh } 32244743693Sstephh return (rt); 32344743693Sstephh } 32444743693Sstephh 32544743693Sstephh /* 32644743693Sstephh * compare two fru strings which are made up of substrings seperated by '/' 32744743693Sstephh * return true if every substring is the same in the two strings, or if a 32844743693Sstephh * substring is null in one. 32944743693Sstephh */ 33044743693Sstephh 33144743693Sstephh static int 33244743693Sstephh frucmp(char *f1, char *f2) 33344743693Sstephh { 33444743693Sstephh char c1, c2; 33544743693Sstephh int i = 0; 33644743693Sstephh 33744743693Sstephh for (;;) { 33844743693Sstephh c1 = *f1; 33944743693Sstephh c2 = *f2; 34044743693Sstephh if (c1 == c2) { 34144743693Sstephh i = (c1 == '/') ? 0 : i + 1; 34244743693Sstephh } else if (i == 0) { 34344743693Sstephh if (c1 == '/') { 34444743693Sstephh do { 34544743693Sstephh f2++; 34644743693Sstephh } while ((c2 = *f2) != 0 && c2 != '/'); 34744743693Sstephh if (c2 == NULL) 34844743693Sstephh break; 34944743693Sstephh } else if (c2 == '/') { 35044743693Sstephh do { 35144743693Sstephh f1++; 35244743693Sstephh } while ((c1 = *f1) != 0 && c1 != '/'); 35344743693Sstephh if (c1 == NULL) 35444743693Sstephh break; 35544743693Sstephh } else 35644743693Sstephh break; 35744743693Sstephh } else 35844743693Sstephh break; 35944743693Sstephh if (c1 == NULL) 36044743693Sstephh return (0); 36144743693Sstephh f1++; 36244743693Sstephh f2++; 36344743693Sstephh } 36444743693Sstephh return (1); 36544743693Sstephh } 36644743693Sstephh 36744743693Sstephh static int 36844743693Sstephh tgetlabel(topo_hdl_t *thp, tnode_t *node, void *arg) 36944743693Sstephh { 37044743693Sstephh int err; 37144743693Sstephh char *fru_name, *lname; 37244743693Sstephh nvlist_t *fru = NULL; 37344743693Sstephh int rt = TOPO_WALK_NEXT; 37444743693Sstephh tgetlabel_data_t *tdp = (tgetlabel_data_t *)arg; 37544743693Sstephh 37644743693Sstephh if (topo_node_fru(node, &fru, NULL, &err) == 0) { 37744743693Sstephh if (topo_fmri_nvl2str(thp, fru, &fru_name, &err) == 0) { 37844743693Sstephh if (frucmp(tdp->fru, fru_name) == 0 && 37944743693Sstephh topo_node_label(node, &lname, &err) == 0) { 38044743693Sstephh tdp->label = strdup(lname); 38144743693Sstephh topo_hdl_strfree(thp, lname); 38244743693Sstephh rt = TOPO_WALK_TERMINATE; 38344743693Sstephh } 38444743693Sstephh topo_hdl_strfree(thp, fru_name); 38544743693Sstephh } 38644743693Sstephh nvlist_free(fru); 38744743693Sstephh } 38844743693Sstephh return (rt); 38944743693Sstephh } 39044743693Sstephh 39144743693Sstephh static void 39244743693Sstephh label_get_topo(void) 39344743693Sstephh { 39444743693Sstephh int err; 39544743693Sstephh 39644743693Sstephh topo_handle = topo_open(TOPO_VERSION, 0, &err); 39744743693Sstephh if (topo_handle) { 39844743693Sstephh topo_handle_uuid = topo_snap_hold(topo_handle, NULL, &err); 39944743693Sstephh } 40044743693Sstephh } 40144743693Sstephh 40244743693Sstephh static void 40344743693Sstephh label_release_topo(void) 40444743693Sstephh { 40544743693Sstephh if (topo_handle_uuid) 40644743693Sstephh topo_hdl_strfree(topo_handle, topo_handle_uuid); 40744743693Sstephh if (topo_handle) { 40844743693Sstephh topo_snap_release(topo_handle); 40944743693Sstephh topo_close(topo_handle); 41044743693Sstephh } 41144743693Sstephh } 41244743693Sstephh 41344743693Sstephh static char * 41444743693Sstephh get_fmri_label(char *fru) 41544743693Sstephh { 41644743693Sstephh topo_walk_t *twp; 41744743693Sstephh tgetlabel_data_t td; 41844743693Sstephh int err; 41944743693Sstephh 42044743693Sstephh td.label = NULL; 42144743693Sstephh td.fru = fru; 42244743693Sstephh if (topo_handle == NULL) 42344743693Sstephh label_get_topo(); 42444743693Sstephh if (topo_handle_uuid) { 42544743693Sstephh twp = topo_walk_init(topo_handle, FM_FMRI_SCHEME_HC, 42644743693Sstephh tgetlabel, &td, &err); 42744743693Sstephh if (twp) { 42844743693Sstephh topo_walk_step(twp, TOPO_WALK_CHILD); 42944743693Sstephh topo_walk_fini(twp); 43044743693Sstephh } 43144743693Sstephh } 43244743693Sstephh return (td.label); 43344743693Sstephh } 43444743693Sstephh 43544743693Sstephh static char * 43644743693Sstephh get_nvl2str_topo(nvlist_t *nvl) 43744743693Sstephh { 43844743693Sstephh char *name = NULL; 43944743693Sstephh char *tname; 44044743693Sstephh int err; 44144743693Sstephh char *scheme = NULL; 44244743693Sstephh char *mod_name = NULL; 44344743693Sstephh char buf[128]; 44444743693Sstephh 44544743693Sstephh if (topo_handle == NULL) 44644743693Sstephh label_get_topo(); 44744743693Sstephh if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) { 44844743693Sstephh name = strdup(tname); 44944743693Sstephh topo_hdl_strfree(topo_handle, tname); 45044743693Sstephh } else { 45144743693Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme); 45244743693Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &mod_name); 45344743693Sstephh if (scheme && strcmp(scheme, FM_FMRI_SCHEME_FMD) == 0 && 45444743693Sstephh mod_name) { 45544743693Sstephh (void) snprintf(buf, sizeof (buf), "%s:///module/%s", 45644743693Sstephh scheme, mod_name); 45744743693Sstephh name = strdup(buf); 45844743693Sstephh } 45944743693Sstephh } 46044743693Sstephh return (name); 46144743693Sstephh } 46244743693Sstephh 46344743693Sstephh static int 46444743693Sstephh set_priority(char *s) 46544743693Sstephh { 46644743693Sstephh int rt = 0; 46744743693Sstephh 46844743693Sstephh if (s) { 46944743693Sstephh if (strcmp(s, "Minor") == 0) 47044743693Sstephh rt = 1; 47144743693Sstephh else if (strcmp(s, "Major") == 0) 47244743693Sstephh rt = 10; 47344743693Sstephh else if (strcmp(s, "Critical") == 0) 47444743693Sstephh rt = 100; 47544743693Sstephh } 47644743693Sstephh return (rt); 47744743693Sstephh } 47844743693Sstephh 47944743693Sstephh static int 48044743693Sstephh cmp_priority(char *s1, char *s2, uint64_t t1, uint64_t t2, uint8_t p1, 48144743693Sstephh uint8_t p2) 48244743693Sstephh { 48344743693Sstephh int r1, r2; 48444743693Sstephh int rt; 48544743693Sstephh 48644743693Sstephh r1 = set_priority(s1); 48744743693Sstephh r2 = set_priority(s2); 48844743693Sstephh rt = r1 - r2; 48944743693Sstephh if (rt == 0) { 49044743693Sstephh if (t1 > t2) 49144743693Sstephh rt = 1; 49244743693Sstephh else if (t1 < t2) 49344743693Sstephh rt = -1; 49444743693Sstephh else 49544743693Sstephh rt = p1 - p2; 49644743693Sstephh } 49744743693Sstephh return (rt); 49844743693Sstephh } 49944743693Sstephh 50044743693Sstephh /* 50144743693Sstephh * merge two lists into one, by comparing enties in new and moving into list if 50244743693Sstephh * name is not there or free off memory for names which are already there 50344743693Sstephh * add_pct indicates if pct is the sum or highest pct 50444743693Sstephh */ 50544743693Sstephh static name_list_t * 50644743693Sstephh merge_name_list(name_list_t **list, name_list_t *new, int add_pct) 50744743693Sstephh { 50844743693Sstephh name_list_t *lp, *np, *sp, *rt = NULL; 50944743693Sstephh int max_pct; 51044743693Sstephh 51144743693Sstephh rt = *list; 51244743693Sstephh np = new; 51344743693Sstephh while (np) { 51444743693Sstephh lp = *list; 51544743693Sstephh while (lp) { 51644743693Sstephh if (strcmp(lp->name, np->name) == 0) 51744743693Sstephh break; 51844743693Sstephh lp = lp->next; 51944743693Sstephh if (lp == *list) 52044743693Sstephh lp = NULL; 52144743693Sstephh } 52244743693Sstephh if (np->next == new) 52344743693Sstephh sp = NULL; 52444743693Sstephh else 52544743693Sstephh sp = np->next; 52644743693Sstephh if (lp) { 52744743693Sstephh lp->status |= (np->status & FM_SUSPECT_FAULTY); 52844743693Sstephh if (add_pct) { 52944743693Sstephh lp->pct += np->pct; 53044743693Sstephh lp->count += np->count; 53144743693Sstephh } else if (np->pct > lp->pct) { 53244743693Sstephh lp->pct = np->pct; 53344743693Sstephh } 53444743693Sstephh max_pct = np->max_pct; 535d4c0a8c5Sstephh if (np->label) 536d4c0a8c5Sstephh free(np->label); 53744743693Sstephh free(np->name); 53844743693Sstephh free(np); 53944743693Sstephh np = NULL; 54044743693Sstephh if (max_pct > lp->max_pct) { 54144743693Sstephh lp->max_pct = max_pct; 54244743693Sstephh if (lp->max_pct > lp->prev->max_pct && 54344743693Sstephh lp != *list) { 54444743693Sstephh lp->prev->next = lp->next; 54544743693Sstephh lp->next->prev = lp->prev; 54644743693Sstephh np = lp; 54744743693Sstephh } 54844743693Sstephh } 54944743693Sstephh } 55044743693Sstephh if (np) { 55144743693Sstephh lp = *list; 55244743693Sstephh if (lp) { 55344743693Sstephh if (np->max_pct > lp->max_pct) { 55444743693Sstephh np->next = lp; 55544743693Sstephh np->prev = lp->prev; 55644743693Sstephh lp->prev->next = np; 55744743693Sstephh lp->prev = np; 55844743693Sstephh *list = np; 55944743693Sstephh rt = np; 56044743693Sstephh } else { 56144743693Sstephh lp = lp->next; 56244743693Sstephh while (lp != *list && 56344743693Sstephh np->max_pct < lp->max_pct) { 56444743693Sstephh lp = lp->next; 56544743693Sstephh } 56644743693Sstephh np->next = lp; 56744743693Sstephh np->prev = lp->prev; 56844743693Sstephh lp->prev->next = np; 56944743693Sstephh lp->prev = np; 57044743693Sstephh } 57144743693Sstephh } else { 57244743693Sstephh *list = np; 57344743693Sstephh np->next = np; 57444743693Sstephh np->prev = np; 57544743693Sstephh rt = np; 57644743693Sstephh } 57744743693Sstephh } 57844743693Sstephh np = sp; 57944743693Sstephh } 58044743693Sstephh return (rt); 58144743693Sstephh } 58244743693Sstephh 58344743693Sstephh /* 58444743693Sstephh * compare entries in two lists return true if the two lists have identical 58544743693Sstephh * content. The two lists may not have entries in the same order, so we compare 58644743693Sstephh * the size of the list as well as trying to find every entry from one list in 58744743693Sstephh * the other. 58844743693Sstephh */ 58944743693Sstephh static int 59044743693Sstephh cmp_name_list(name_list_t *lxp1, name_list_t *lxp2) 59144743693Sstephh { 59244743693Sstephh name_list_t *lp1, *lp2; 59344743693Sstephh int l1 = 0, l2 = 0, common = 0; 59444743693Sstephh 59544743693Sstephh lp2 = lxp2; 59644743693Sstephh while (lp2) { 59744743693Sstephh l2++; 59844743693Sstephh lp2 = lp2->next; 59944743693Sstephh if (lp2 == lxp2) 60044743693Sstephh break; 60144743693Sstephh } 60244743693Sstephh lp1 = lxp1; 60344743693Sstephh while (lp1) { 60444743693Sstephh l1++; 60544743693Sstephh lp2 = lxp2; 60644743693Sstephh while (lp2) { 60744743693Sstephh if (strcmp(lp2->name, lp1->name) == 0) { 60844743693Sstephh common++; 60944743693Sstephh break; 61044743693Sstephh } 61144743693Sstephh lp2 = lp2->next; 61244743693Sstephh if (lp2 == lxp2) 61344743693Sstephh break; 61444743693Sstephh } 61544743693Sstephh lp1 = lp1->next; 61644743693Sstephh if (lp1 == lxp1) 61744743693Sstephh break; 61844743693Sstephh } 61944743693Sstephh if (l1 == l2 && l2 == common) 62044743693Sstephh return (0); 62144743693Sstephh else 62244743693Sstephh return (1); 62344743693Sstephh } 62444743693Sstephh 62544743693Sstephh static name_list_t * 62644743693Sstephh alloc_name_list(char *name, uint8_t pct) 62744743693Sstephh { 62844743693Sstephh name_list_t *nlp; 62944743693Sstephh 63044743693Sstephh nlp = malloc(sizeof (*nlp)); 63144743693Sstephh nlp->name = strdup(name); 63244743693Sstephh nlp->pct = pct; 63344743693Sstephh nlp->max_pct = pct; 63444743693Sstephh nlp->count = 1; 63544743693Sstephh nlp->next = nlp; 63644743693Sstephh nlp->prev = nlp; 63744743693Sstephh nlp->status = 0; 638d4c0a8c5Sstephh nlp->label = NULL; 63944743693Sstephh return (nlp); 64044743693Sstephh } 64144743693Sstephh 64244743693Sstephh static void 64344743693Sstephh free_name_list(name_list_t *list) 64444743693Sstephh { 64544743693Sstephh name_list_t *next = list; 64644743693Sstephh name_list_t *lp; 64744743693Sstephh 64844743693Sstephh if (list) { 64944743693Sstephh do { 65044743693Sstephh lp = next; 65144743693Sstephh next = lp->next; 652d4c0a8c5Sstephh if (lp->label) 653d4c0a8c5Sstephh free(lp->label); 65444743693Sstephh free(lp->name); 65544743693Sstephh free(lp); 65644743693Sstephh } while (next != list); 65744743693Sstephh } 65844743693Sstephh } 65944743693Sstephh 66044743693Sstephh static status_record_t * 66144743693Sstephh new_record_init(uurec_t *uurec_p, char *msgid, name_list_t *class, 66244743693Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource, 663*b6955755SRobert Johnston name_list_t *serial, boolean_t not_suppressed, 66444743693Sstephh hostid_t *hostid) 66544743693Sstephh { 66644743693Sstephh status_record_t *status_rec_p; 66744743693Sstephh 66844743693Sstephh status_rec_p = (status_record_t *)malloc(sizeof (status_record_t)); 66944743693Sstephh status_rec_p->nrecs = 1; 67044743693Sstephh status_rec_p->host = hostid; 67144743693Sstephh status_rec_p->uurec = uurec_p; 67244743693Sstephh uurec_p->next = NULL; 67344743693Sstephh uurec_p->prev = NULL; 67444743693Sstephh uurec_p->asru = asru; 675*b6955755SRobert Johnston if ((status_rec_p->severity = fmd_msg_getitem_id(fmadm_msghdl, NULL, 676*b6955755SRobert Johnston msgid, FMD_MSG_ITEM_SEVERITY)) == NULL) 677*b6955755SRobert Johnston status_rec_p->severity = strdup("unknown"); 67844743693Sstephh status_rec_p->class = class; 67944743693Sstephh status_rec_p->fru = fru; 68044743693Sstephh status_rec_p->asru = asru; 68144743693Sstephh status_rec_p->resource = resource; 68244743693Sstephh status_rec_p->serial = serial; 68344743693Sstephh status_rec_p->msgid = strdup(msgid); 68444743693Sstephh status_rec_p->not_suppressed = not_suppressed; 68544743693Sstephh return (status_rec_p); 68644743693Sstephh } 68744743693Sstephh 68844743693Sstephh /* 68944743693Sstephh * add record to given list maintaining order higher priority first. 69044743693Sstephh */ 69144743693Sstephh static void 69244743693Sstephh add_rec_list(status_record_t *status_rec_p, sr_list_t **list_pp) 69344743693Sstephh { 69444743693Sstephh sr_list_t *tp, *np, *sp; 69544743693Sstephh int order; 69644743693Sstephh uint64_t sec; 6977c478bd9Sstevel@tonic-gate 69844743693Sstephh np = malloc(sizeof (sr_list_t)); 69944743693Sstephh np->status_record = status_rec_p; 70044743693Sstephh sec = status_rec_p->uurec->sec; 70144743693Sstephh if ((sp = *list_pp) == NULL) { 70244743693Sstephh *list_pp = np; 70344743693Sstephh np->next = np; 70444743693Sstephh np->prev = np; 70544743693Sstephh } else { 70644743693Sstephh /* insert new record in front of lower priority */ 70744743693Sstephh tp = sp; 70844743693Sstephh order = cmp_priority(status_rec_p->severity, 70944743693Sstephh sp->status_record->severity, sec, 71044743693Sstephh tp->status_record->uurec->sec, 0, 0); 71144743693Sstephh if (order > 0) { 71244743693Sstephh *list_pp = np; 71344743693Sstephh } else { 71444743693Sstephh tp = sp->next; 71544743693Sstephh while (tp != sp && 71644743693Sstephh cmp_priority(status_rec_p->severity, 71744743693Sstephh tp->status_record->severity, sec, 71844743693Sstephh tp->status_record->uurec->sec, 0, 0)) { 71944743693Sstephh tp = tp->next; 72044743693Sstephh } 72144743693Sstephh } 72244743693Sstephh np->next = tp; 72344743693Sstephh np->prev = tp->prev; 72444743693Sstephh tp->prev->next = np; 72544743693Sstephh tp->prev = np; 72644743693Sstephh } 72744743693Sstephh } 72844743693Sstephh 72944743693Sstephh static void 73044743693Sstephh add_resource(status_record_t *status_rec_p, resource_list_t **rp, 73144743693Sstephh resource_list_t *np) 73244743693Sstephh { 73344743693Sstephh int order; 73444743693Sstephh uint64_t sec; 73544743693Sstephh resource_list_t *sp, *tp; 73644743693Sstephh status_record_t *srp; 73744743693Sstephh char *severity = status_rec_p->severity; 73844743693Sstephh 73944743693Sstephh add_rec_list(status_rec_p, &np->status_rec_list); 74044743693Sstephh if ((sp = *rp) == NULL) { 74144743693Sstephh np->next = np; 74244743693Sstephh np->prev = np; 74344743693Sstephh *rp = np; 74444743693Sstephh } else { 74544743693Sstephh /* 74644743693Sstephh * insert new record in front of lower priority 74744743693Sstephh */ 74844743693Sstephh tp = sp->next; 74944743693Sstephh srp = sp->status_rec_list->status_record; 75044743693Sstephh sec = status_rec_p->uurec->sec; 75144743693Sstephh order = cmp_priority(severity, srp->severity, sec, 75244743693Sstephh srp->uurec->sec, np->max_pct, sp->max_pct); 75344743693Sstephh if (order > 0) { 75444743693Sstephh *rp = np; 75544743693Sstephh } else { 75644743693Sstephh srp = tp->status_rec_list->status_record; 75744743693Sstephh while (tp != sp && 75844743693Sstephh cmp_priority(severity, srp->severity, sec, 75944743693Sstephh srp->uurec->sec, np->max_pct, sp->max_pct) < 0) { 76044743693Sstephh tp = tp->next; 76144743693Sstephh srp = tp->status_rec_list->status_record; 76244743693Sstephh } 76344743693Sstephh } 76444743693Sstephh np->next = tp; 76544743693Sstephh np->prev = tp->prev; 76644743693Sstephh tp->prev->next = np; 76744743693Sstephh tp->prev = np; 76844743693Sstephh } 76944743693Sstephh } 77044743693Sstephh 77144743693Sstephh static void 77244743693Sstephh add_resource_list(status_record_t *status_rec_p, name_list_t *fp, 77344743693Sstephh resource_list_t **rpp) 77444743693Sstephh { 77544743693Sstephh int order; 77644743693Sstephh resource_list_t *np, *end; 77744743693Sstephh status_record_t *srp; 77844743693Sstephh 77944743693Sstephh np = *rpp; 78044743693Sstephh end = np; 78144743693Sstephh while (np) { 78244743693Sstephh if (strcmp(fp->name, np->resource) == 0) { 78344743693Sstephh np->not_suppressed |= status_rec_p->not_suppressed; 78444743693Sstephh srp = np->status_rec_list->status_record; 78544743693Sstephh order = cmp_priority(status_rec_p->severity, 78644743693Sstephh srp->severity, status_rec_p->uurec->sec, 78744743693Sstephh srp->uurec->sec, fp->max_pct, np->max_pct); 78844743693Sstephh if (order > 0 && np != end) { 78944743693Sstephh /* 79044743693Sstephh * remove from list and add again using 79144743693Sstephh * new priority 79244743693Sstephh */ 79344743693Sstephh np->prev->next = np->next; 79444743693Sstephh np->next->prev = np->prev; 79544743693Sstephh add_resource(status_rec_p, 79644743693Sstephh rpp, np); 79744743693Sstephh } else { 79844743693Sstephh add_rec_list(status_rec_p, 79944743693Sstephh &np->status_rec_list); 80044743693Sstephh } 80144743693Sstephh break; 80244743693Sstephh } 80344743693Sstephh np = np->next; 80444743693Sstephh if (np == end) { 80544743693Sstephh np = NULL; 80644743693Sstephh break; 80744743693Sstephh } 80844743693Sstephh } 80944743693Sstephh if (np == NULL) { 81044743693Sstephh np = malloc(sizeof (resource_list_t)); 81144743693Sstephh np->resource = fp->name; 81244743693Sstephh np->not_suppressed = status_rec_p->not_suppressed; 81344743693Sstephh np->status_rec_list = NULL; 81444743693Sstephh np->max_pct = fp->max_pct; 81544743693Sstephh add_resource(status_rec_p, rpp, np); 81644743693Sstephh } 81744743693Sstephh } 81844743693Sstephh 81944743693Sstephh static void 82044743693Sstephh add_list(status_record_t *status_rec_p, name_list_t *listp, 82144743693Sstephh resource_list_t **glistp) 8227c478bd9Sstevel@tonic-gate { 82344743693Sstephh name_list_t *fp, *end; 82444743693Sstephh 82544743693Sstephh fp = listp; 82644743693Sstephh end = fp; 82744743693Sstephh while (fp) { 82844743693Sstephh add_resource_list(status_rec_p, fp, glistp); 82944743693Sstephh fp = fp->next; 83044743693Sstephh if (fp == end) 83144743693Sstephh break; 83244743693Sstephh } 83344743693Sstephh } 83444743693Sstephh 83544743693Sstephh /* 83644743693Sstephh * add record to rec, fru and asru lists. 83744743693Sstephh */ 83844743693Sstephh static void 83944743693Sstephh catalog_new_record(uurec_t *uurec_p, char *msgid, name_list_t *class, 84044743693Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource, 841*b6955755SRobert Johnston name_list_t *serial, boolean_t not_suppressed, 84244743693Sstephh hostid_t *hostid) 84344743693Sstephh { 84444743693Sstephh status_record_t *status_rec_p; 84544743693Sstephh 84644743693Sstephh status_rec_p = new_record_init(uurec_p, msgid, class, fru, asru, 847*b6955755SRobert Johnston resource, serial, not_suppressed, hostid); 84844743693Sstephh add_rec_list(status_rec_p, &status_rec_list); 84944743693Sstephh if (status_rec_p->fru) 85044743693Sstephh add_list(status_rec_p, status_rec_p->fru, &status_fru_list); 85144743693Sstephh if (status_rec_p->asru) 85244743693Sstephh add_list(status_rec_p, status_rec_p->asru, &status_asru_list); 85344743693Sstephh } 85444743693Sstephh 85544743693Sstephh /* 85644743693Sstephh * add uuid and diagnoses time to an existing record for similar fault on the 85744743693Sstephh * same fru 85844743693Sstephh */ 85944743693Sstephh static void 86044743693Sstephh catalog_merge_record(status_record_t *status_rec_p, uurec_t *uurec_p, 86144743693Sstephh name_list_t *asru, name_list_t *resource, name_list_t *serial, 862*b6955755SRobert Johnston boolean_t not_suppressed) 86344743693Sstephh { 86444743693Sstephh uurec_t *uurec1_p; 86544743693Sstephh 86644743693Sstephh status_rec_p->nrecs++; 86744743693Sstephh /* add uurec in time order */ 86844743693Sstephh if (status_rec_p->uurec->sec > uurec_p->sec) { 86944743693Sstephh uurec_p->next = status_rec_p->uurec; 87044743693Sstephh uurec_p->prev = NULL; 87144743693Sstephh status_rec_p->uurec = uurec_p; 87244743693Sstephh } else { 87344743693Sstephh uurec1_p = status_rec_p->uurec; 87444743693Sstephh while (uurec1_p->next && uurec1_p->next->sec <= uurec_p->sec) 87544743693Sstephh uurec1_p = uurec1_p->next; 87644743693Sstephh if (uurec1_p->next) 87744743693Sstephh uurec1_p->next->prev = uurec_p; 87844743693Sstephh uurec_p->next = uurec1_p->next; 87944743693Sstephh uurec_p->prev = uurec1_p; 88044743693Sstephh uurec1_p->next = uurec_p; 88144743693Sstephh } 88244743693Sstephh status_rec_p->not_suppressed |= not_suppressed; 88344743693Sstephh uurec_p->asru = merge_name_list(&status_rec_p->asru, asru, 0); 88444743693Sstephh (void) merge_name_list(&status_rec_p->resource, resource, 0); 88544743693Sstephh (void) merge_name_list(&status_rec_p->serial, serial, 0); 88644743693Sstephh } 88744743693Sstephh 88844743693Sstephh static status_record_t * 88944743693Sstephh record_in_catalog(name_list_t *class, name_list_t *fru, 89044743693Sstephh char *msgid, hostid_t *host) 89144743693Sstephh { 89244743693Sstephh sr_list_t *status_rec_p; 89344743693Sstephh status_record_t *srp = NULL; 89444743693Sstephh 89544743693Sstephh status_rec_p = status_rec_list; 89644743693Sstephh while (status_rec_p) { 89744743693Sstephh srp = status_rec_p->status_record; 89844743693Sstephh if (host == srp->host && 89944743693Sstephh cmp_name_list(class, srp->class) == 0 && 90044743693Sstephh cmp_name_list(fru, srp->fru) == 0 && 90144743693Sstephh strcmp(msgid, srp->msgid) == 0) 90244743693Sstephh break; 90344743693Sstephh if (status_rec_p->next == status_rec_list) { 90444743693Sstephh srp = NULL; 90544743693Sstephh break; 90644743693Sstephh } else { 90744743693Sstephh status_rec_p = status_rec_p->next; 90844743693Sstephh } 90944743693Sstephh } 91044743693Sstephh return (srp); 91144743693Sstephh } 91244743693Sstephh 91344743693Sstephh static void 91444743693Sstephh get_serial_no(nvlist_t *nvl, name_list_t **serial_p, uint8_t pct) 91544743693Sstephh { 91644743693Sstephh char *name; 91744743693Sstephh char *serial = NULL; 91844743693Sstephh char **lserial = NULL; 91944743693Sstephh uint64_t serint; 92044743693Sstephh name_list_t *nlp; 92144743693Sstephh int j; 92244743693Sstephh uint_t nelem; 92344743693Sstephh char buf[64]; 92444743693Sstephh 92544743693Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) == 0) { 92644743693Sstephh if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) { 92744743693Sstephh if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, 92844743693Sstephh &serint) == 0) { 92944743693Sstephh (void) snprintf(buf, sizeof (buf), "%llX", 93044743693Sstephh serint); 93144743693Sstephh nlp = alloc_name_list(buf, pct); 93244743693Sstephh (void) merge_name_list(serial_p, nlp, 1); 93344743693Sstephh } 93444743693Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) { 93544743693Sstephh if (nvlist_lookup_string_array(nvl, 93644743693Sstephh FM_FMRI_MEM_SERIAL_ID, &lserial, &nelem) == 0) { 93744743693Sstephh nlp = alloc_name_list(lserial[0], pct); 93844743693Sstephh for (j = 1; j < nelem; j++) { 93944743693Sstephh name_list_t *n1lp; 94044743693Sstephh n1lp = alloc_name_list(lserial[j], pct); 94144743693Sstephh (void) merge_name_list(&nlp, n1lp, 1); 94244743693Sstephh } 94344743693Sstephh (void) merge_name_list(serial_p, nlp, 1); 94444743693Sstephh } 94544743693Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_HC) == 0) { 94644743693Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, 94744743693Sstephh &serial) == 0) { 94844743693Sstephh nlp = alloc_name_list(serial, pct); 94944743693Sstephh (void) merge_name_list(serial_p, nlp, 1); 95044743693Sstephh } 95144743693Sstephh } 95244743693Sstephh } 95344743693Sstephh } 95444743693Sstephh 95544743693Sstephh static void 95644743693Sstephh extract_record_info(nvlist_t *nvl, name_list_t **class_p, 95744743693Sstephh name_list_t **fru_p, name_list_t **serial_p, 95844743693Sstephh name_list_t **resource_p, name_list_t **asru_p, uint8_t status) 95944743693Sstephh { 96044743693Sstephh nvlist_t *lfru, *lasru, *rsrc; 96144743693Sstephh name_list_t *nlp; 96244743693Sstephh char *name; 96344743693Sstephh uint8_t lpct = 0; 96444743693Sstephh char *lclass = NULL; 965d4c0a8c5Sstephh char *label; 96644743693Sstephh 96744743693Sstephh (void) nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &lpct); 96844743693Sstephh if (nvlist_lookup_string(nvl, FM_CLASS, &lclass) == 0) { 96944743693Sstephh nlp = alloc_name_list(lclass, lpct); 97044743693Sstephh (void) merge_name_list(class_p, nlp, 1); 97144743693Sstephh } 97244743693Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &lfru) == 0) { 97344743693Sstephh name = get_nvl2str_topo(lfru); 97444743693Sstephh if (name != NULL) { 97544743693Sstephh nlp = alloc_name_list(name, lpct); 97625c6ff4bSstephh nlp->status = status & ~(FM_SUSPECT_UNUSABLE | 97725c6ff4bSstephh FM_SUSPECT_DEGRADED); 97844743693Sstephh free(name); 979d4c0a8c5Sstephh if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION, 980d4c0a8c5Sstephh &label) == 0) 981d4c0a8c5Sstephh nlp->label = strdup(label); 98244743693Sstephh (void) merge_name_list(fru_p, nlp, 1); 98344743693Sstephh } 98444743693Sstephh get_serial_no(lfru, serial_p, lpct); 98544743693Sstephh } 98644743693Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &lasru) == 0) { 98744743693Sstephh name = get_nvl2str_topo(lasru); 98844743693Sstephh if (name != NULL) { 98944743693Sstephh nlp = alloc_name_list(name, lpct); 99025c6ff4bSstephh nlp->status = status & ~(FM_SUSPECT_NOT_PRESENT | 99125c6ff4bSstephh FM_SUSPECT_REPAIRED | FM_SUSPECT_REPLACED | 99225c6ff4bSstephh FM_SUSPECT_ACQUITTED); 99344743693Sstephh free(name); 99444743693Sstephh (void) merge_name_list(asru_p, nlp, 1); 99544743693Sstephh } 99644743693Sstephh get_serial_no(lasru, serial_p, lpct); 99744743693Sstephh } 99844743693Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) { 99944743693Sstephh name = get_nvl2str_topo(rsrc); 100044743693Sstephh if (name != NULL) { 100144743693Sstephh nlp = alloc_name_list(name, lpct); 1002567cc2e6Sstephh nlp->status = status; 100344743693Sstephh free(name); 10048e7248e5SStephen Hanson if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION, 10058e7248e5SStephen Hanson &label) == 0) 10068e7248e5SStephen Hanson nlp->label = strdup(label); 100744743693Sstephh (void) merge_name_list(resource_p, nlp, 1); 100844743693Sstephh } 100944743693Sstephh } 101044743693Sstephh } 101144743693Sstephh 101244743693Sstephh static void 1013*b6955755SRobert Johnston add_fault_record_to_catalog(nvlist_t *nvl, uint64_t sec, char *uuid) 101444743693Sstephh { 101544743693Sstephh char *msgid = "-"; 101644743693Sstephh uint_t i, size = 0; 101744743693Sstephh name_list_t *class = NULL, *resource = NULL; 101844743693Sstephh name_list_t *asru = NULL, *fru = NULL, *serial = NULL; 101944743693Sstephh nvlist_t **nva; 102044743693Sstephh uint8_t *ba; 102144743693Sstephh status_record_t *status_rec_p; 102244743693Sstephh uurec_t *uurec_p; 102344743693Sstephh hostid_t *host; 102444743693Sstephh boolean_t not_suppressed = 1; 102544743693Sstephh boolean_t any_present = 0; 102644743693Sstephh 102744743693Sstephh (void) nvlist_lookup_string(nvl, FM_SUSPECT_DIAG_CODE, &msgid); 102844743693Sstephh (void) nvlist_lookup_uint32(nvl, FM_SUSPECT_FAULT_SZ, &size); 102944743693Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE, 103044743693Sstephh ¬_suppressed); 103144743693Sstephh 103244743693Sstephh if (size != 0) { 103344743693Sstephh (void) nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 103444743693Sstephh &nva, &size); 103544743693Sstephh (void) nvlist_lookup_uint8_array(nvl, FM_SUSPECT_FAULT_STATUS, 103644743693Sstephh &ba, &size); 103744743693Sstephh for (i = 0; i < size; i++) { 103844743693Sstephh extract_record_info(nva[i], &class, &fru, &serial, 103944743693Sstephh &resource, &asru, ba[i]); 104044743693Sstephh if (!(ba[i] & FM_SUSPECT_NOT_PRESENT) && 104144743693Sstephh (ba[i] & FM_SUSPECT_FAULTY)) 104244743693Sstephh any_present = 1; 104344743693Sstephh } 104444743693Sstephh /* 104544743693Sstephh * also suppress if no resources present 104644743693Sstephh */ 104744743693Sstephh if (any_present == 0) 104844743693Sstephh not_suppressed = 0; 104944743693Sstephh } 105044743693Sstephh 105144743693Sstephh uurec_p = (uurec_t *)malloc(sizeof (uurec_t)); 105244743693Sstephh uurec_p->uuid = strdup(uuid); 105344743693Sstephh uurec_p->sec = sec; 105444743693Sstephh uurec_p->ari_uuid_list = NULL; 105544743693Sstephh host = find_hostid(nvl); 105644743693Sstephh if (not_suppressed && !opt_g) 105744743693Sstephh status_rec_p = NULL; 105844743693Sstephh else 105944743693Sstephh status_rec_p = record_in_catalog(class, fru, msgid, host); 106044743693Sstephh if (status_rec_p) { 106144743693Sstephh catalog_merge_record(status_rec_p, uurec_p, asru, resource, 1062*b6955755SRobert Johnston serial, not_suppressed); 106344743693Sstephh free_name_list(class); 106444743693Sstephh free_name_list(fru); 106544743693Sstephh } else { 106644743693Sstephh catalog_new_record(uurec_p, msgid, class, fru, asru, 1067*b6955755SRobert Johnston resource, serial, not_suppressed, host); 106844743693Sstephh } 106944743693Sstephh } 107044743693Sstephh 107144743693Sstephh static void 107244743693Sstephh update_asru_state_in_catalog(const char *uuid, const char *ari_uuid) 107344743693Sstephh { 107444743693Sstephh sr_list_t *srp; 107544743693Sstephh uurec_t *uurp; 107644743693Sstephh ari_list_t *ari_list; 107744743693Sstephh 107844743693Sstephh srp = status_rec_list; 107944743693Sstephh if (srp) { 108044743693Sstephh for (;;) { 108144743693Sstephh uurp = srp->status_record->uurec; 108244743693Sstephh while (uurp) { 108344743693Sstephh if (strcmp(uuid, uurp->uuid) == 0) { 108444743693Sstephh ari_list = (ari_list_t *) 108544743693Sstephh malloc(sizeof (ari_list_t)); 108644743693Sstephh ari_list->ari_uuid = strdup(ari_uuid); 108744743693Sstephh ari_list->next = uurp->ari_uuid_list; 108844743693Sstephh uurp->ari_uuid_list = ari_list; 108944743693Sstephh return; 109044743693Sstephh } 109144743693Sstephh uurp = uurp->next; 109244743693Sstephh } 109344743693Sstephh if (srp->next == status_rec_list) 109444743693Sstephh break; 109544743693Sstephh srp = srp->next; 109644743693Sstephh } 109744743693Sstephh } 109844743693Sstephh } 109944743693Sstephh 110044743693Sstephh static void 110144743693Sstephh print_line(char *label, char *buf) 110244743693Sstephh { 110344743693Sstephh char *cp, *ep, *wp; 110444743693Sstephh char c; 110544743693Sstephh int i; 110644743693Sstephh int lsz; 110744743693Sstephh char *padding; 110844743693Sstephh 110944743693Sstephh lsz = strlen(label); 111044743693Sstephh padding = malloc(lsz + 1); 111144743693Sstephh for (i = 0; i < lsz; i++) 111244743693Sstephh padding[i] = ' '; 111344743693Sstephh padding[i] = 0; 111444743693Sstephh cp = buf; 111544743693Sstephh ep = buf; 111644743693Sstephh c = *ep; 111744743693Sstephh (void) printf("\n"); 111844743693Sstephh while (c) { 111944743693Sstephh i = lsz; 112044743693Sstephh wp = NULL; 112144743693Sstephh while ((c = *ep) != NULL && (wp == NULL || i < 80)) { 112244743693Sstephh if (c == ' ') 112344743693Sstephh wp = ep; 112444743693Sstephh else if (c == '\n') { 112544743693Sstephh i = 0; 112644743693Sstephh *ep = 0; 112744743693Sstephh do { 112844743693Sstephh ep++; 112944743693Sstephh } while ((c = *ep) != NULL && c == ' '); 113044743693Sstephh break; 113144743693Sstephh } 113244743693Sstephh ep++; 113344743693Sstephh i++; 113444743693Sstephh } 113544743693Sstephh if (i >= 80 && wp) { 113644743693Sstephh *wp = 0; 113744743693Sstephh ep = wp + 1; 113844743693Sstephh c = *ep; 113944743693Sstephh } 114044743693Sstephh (void) printf("%s%s\n", label, cp); 114144743693Sstephh cp = ep; 114244743693Sstephh label = padding; 114344743693Sstephh } 114444743693Sstephh free(padding); 114544743693Sstephh } 114644743693Sstephh 114744743693Sstephh static void 1148*b6955755SRobert Johnston print_dict_info_line(char *msgid, fmd_msg_item_t what, const char *linehdr) 114944743693Sstephh { 1150*b6955755SRobert Johnston char *cp = fmd_msg_getitem_id(fmadm_msghdl, NULL, msgid, what); 115144743693Sstephh 115244743693Sstephh if (cp) { 1153*b6955755SRobert Johnston print_line(dgettext("FMD", linehdr), cp); 1154*b6955755SRobert Johnston free(cp); 115544743693Sstephh } 115644743693Sstephh } 115744743693Sstephh 1158*b6955755SRobert Johnston static void 1159*b6955755SRobert Johnston print_dict_info(char *msgid) 1160*b6955755SRobert Johnston { 1161*b6955755SRobert Johnston print_dict_info_line(msgid, FMD_MSG_ITEM_DESC, "Description : "); 1162*b6955755SRobert Johnston print_dict_info_line(msgid, FMD_MSG_ITEM_RESPONSE, "Response : "); 1163*b6955755SRobert Johnston print_dict_info_line(msgid, FMD_MSG_ITEM_IMPACT, "Impact : "); 1164*b6955755SRobert Johnston print_dict_info_line(msgid, FMD_MSG_ITEM_ACTION, "Action : "); 1165*b6955755SRobert Johnston } 1166*b6955755SRobert Johnston 116744743693Sstephh static void 116844743693Sstephh print_name(name_list_t *list, char *(func)(char *), char *padding, int *np, 116944743693Sstephh int pct, int full) 117044743693Sstephh { 11718e7248e5SStephen Hanson char *name, *fru_label = NULL; 117244743693Sstephh 117344743693Sstephh name = list->name; 11748e7248e5SStephen Hanson if (list->label) { 11758e7248e5SStephen Hanson (void) printf("%s \"%s\" (%s)", padding, list->label, name); 11768e7248e5SStephen Hanson *np += 1; 11778e7248e5SStephen Hanson } else if (func && (fru_label = func(list->name)) != NULL) { 11788e7248e5SStephen Hanson (void) printf("%s \"%s\" (%s)", padding, fru_label, name); 117944743693Sstephh *np += 1; 11808e7248e5SStephen Hanson free(fru_label); 118144743693Sstephh } else { 118244743693Sstephh (void) printf("%s %s", padding, name); 118344743693Sstephh *np += 1; 118444743693Sstephh } 118544743693Sstephh if (list->pct && pct > 0 && pct < 100) { 118644743693Sstephh if (list->count > 1) { 118744743693Sstephh if (full) { 118844743693Sstephh (void) printf(" %d @ %s %d%%\n", list->count, 118944743693Sstephh dgettext("FMD", "max"), 119044743693Sstephh list->max_pct); 119144743693Sstephh } else { 119244743693Sstephh (void) printf(" %s %d%%\n", 119344743693Sstephh dgettext("FMD", "max"), 119444743693Sstephh list->max_pct); 119544743693Sstephh } 119644743693Sstephh } else { 119744743693Sstephh (void) printf(" %d%%\n", list->pct); 119844743693Sstephh } 119944743693Sstephh } else { 120044743693Sstephh (void) printf("\n"); 120144743693Sstephh } 120244743693Sstephh } 120344743693Sstephh 120444743693Sstephh static void 120544743693Sstephh print_asru_status(int status, char *label) 120644743693Sstephh { 120744743693Sstephh char *msg = NULL; 120844743693Sstephh 120944743693Sstephh switch (status) { 121044743693Sstephh case 0: 121144743693Sstephh msg = dgettext("FMD", "ok and in service"); 121244743693Sstephh break; 121325c6ff4bSstephh case FM_SUSPECT_DEGRADED: 121425c6ff4bSstephh msg = dgettext("FMD", "service degraded, " 121525c6ff4bSstephh "but associated components no longer faulty"); 121625c6ff4bSstephh break; 121725c6ff4bSstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED: 121825c6ff4bSstephh msg = dgettext("FMD", "faulted but still " 121925c6ff4bSstephh "providing degraded service"); 122025c6ff4bSstephh break; 122144743693Sstephh case FM_SUSPECT_FAULTY: 122225c6ff4bSstephh msg = dgettext("FMD", "faulted but still in service"); 122344743693Sstephh break; 122444743693Sstephh case FM_SUSPECT_UNUSABLE: 122525c6ff4bSstephh msg = dgettext("FMD", "out of service, " 122625c6ff4bSstephh "but associated components no longer faulty"); 122744743693Sstephh break; 122844743693Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE: 122944743693Sstephh msg = dgettext("FMD", "faulted and taken out of service"); 123044743693Sstephh break; 12317c478bd9Sstevel@tonic-gate default: 123244743693Sstephh break; 123344743693Sstephh } 123444743693Sstephh if (msg) { 123544743693Sstephh (void) printf("%s %s\n", label, msg); 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 1239567cc2e6Sstephh static void 1240567cc2e6Sstephh print_fru_status(int status, char *label) 1241567cc2e6Sstephh { 1242567cc2e6Sstephh char *msg = NULL; 1243567cc2e6Sstephh 1244567cc2e6Sstephh if (status & FM_SUSPECT_NOT_PRESENT) 1245567cc2e6Sstephh msg = dgettext("FMD", "not present"); 1246567cc2e6Sstephh else if (status & FM_SUSPECT_FAULTY) 1247567cc2e6Sstephh msg = dgettext("FMD", "faulty"); 124825c6ff4bSstephh else if (status & FM_SUSPECT_REPLACED) 124925c6ff4bSstephh msg = dgettext("FMD", "replaced"); 125025c6ff4bSstephh else if (status & FM_SUSPECT_REPAIRED) 125125c6ff4bSstephh msg = dgettext("FMD", "repair attempted"); 125225c6ff4bSstephh else if (status & FM_SUSPECT_ACQUITTED) 125325c6ff4bSstephh msg = dgettext("FMD", "acquitted"); 1254567cc2e6Sstephh else 125525c6ff4bSstephh msg = dgettext("FMD", "removed"); 1256567cc2e6Sstephh (void) printf("%s %s\n", label, msg); 1257567cc2e6Sstephh } 1258567cc2e6Sstephh 1259cbf75e67SStephen Hanson static void 1260cbf75e67SStephen Hanson print_rsrc_status(int status, char *label) 1261cbf75e67SStephen Hanson { 1262cbf75e67SStephen Hanson char *msg = ""; 1263cbf75e67SStephen Hanson 1264cbf75e67SStephen Hanson if (status & FM_SUSPECT_NOT_PRESENT) 1265cbf75e67SStephen Hanson msg = dgettext("FMD", "not present"); 1266cbf75e67SStephen Hanson else if (status & FM_SUSPECT_FAULTY) { 1267cbf75e67SStephen Hanson if (status & FM_SUSPECT_DEGRADED) 1268cbf75e67SStephen Hanson msg = dgettext("FMD", 1269cbf75e67SStephen Hanson "faulted but still providing degraded service"); 1270cbf75e67SStephen Hanson else if (status & FM_SUSPECT_UNUSABLE) 1271cbf75e67SStephen Hanson msg = dgettext("FMD", 1272cbf75e67SStephen Hanson "faulted and taken out of service"); 1273cbf75e67SStephen Hanson else 1274cbf75e67SStephen Hanson msg = dgettext("FMD", "faulted but still in service"); 1275cbf75e67SStephen Hanson } else if (status & FM_SUSPECT_REPLACED) 1276cbf75e67SStephen Hanson msg = dgettext("FMD", "replaced"); 1277cbf75e67SStephen Hanson else if (status & FM_SUSPECT_REPAIRED) 1278cbf75e67SStephen Hanson msg = dgettext("FMD", "repair attempted"); 1279cbf75e67SStephen Hanson else if (status & FM_SUSPECT_ACQUITTED) 1280cbf75e67SStephen Hanson msg = dgettext("FMD", "acquitted"); 1281cbf75e67SStephen Hanson else 1282cbf75e67SStephen Hanson msg = dgettext("FMD", "removed"); 1283cbf75e67SStephen Hanson (void) printf("%s %s\n", label, msg); 1284cbf75e67SStephen Hanson } 1285cbf75e67SStephen Hanson 128644743693Sstephh static void 128744743693Sstephh print_name_list(name_list_t *list, char *label, char *(func)(char *), 128844743693Sstephh int limit, int pct, void (func1)(int, char *), int full) 128944743693Sstephh { 12908e7248e5SStephen Hanson char *name, *fru_label = NULL; 129144743693Sstephh char *padding; 129244743693Sstephh int i, j, l, n; 129344743693Sstephh name_list_t *end = list; 12947c478bd9Sstevel@tonic-gate 129544743693Sstephh l = strlen(label); 129644743693Sstephh padding = malloc(l + 1); 129744743693Sstephh for (i = 0; i < l; i++) 129844743693Sstephh padding[i] = ' '; 129944743693Sstephh padding[l] = 0; 130044743693Sstephh (void) printf("%s", label); 130144743693Sstephh name = list->name; 13028e7248e5SStephen Hanson if (list->label) 1303d4c0a8c5Sstephh (void) printf(" \"%s\" (%s)", list->label, name); 13048e7248e5SStephen Hanson else if (func && (fru_label = func(list->name)) != NULL) { 13058e7248e5SStephen Hanson (void) printf(" \"%s\" (%s)", fru_label, name); 13068e7248e5SStephen Hanson free(fru_label); 13078e7248e5SStephen Hanson } else 13088e7248e5SStephen Hanson (void) printf(" %s", name); 130944743693Sstephh if (list->pct && pct > 0 && pct < 100) { 131044743693Sstephh if (list->count > 1) { 131144743693Sstephh if (full) { 131244743693Sstephh (void) printf(" %d @ %s %d%%\n", list->count, 131344743693Sstephh dgettext("FMD", "max"), list->max_pct); 131444743693Sstephh } else { 131544743693Sstephh (void) printf(" %s %d%%\n", 131644743693Sstephh dgettext("FMD", "max"), list->max_pct); 131744743693Sstephh } 131844743693Sstephh } else { 131944743693Sstephh (void) printf(" %d%%\n", list->pct); 132044743693Sstephh } 132144743693Sstephh } else { 132244743693Sstephh (void) printf("\n"); 132344743693Sstephh } 132444743693Sstephh if (func1) 132544743693Sstephh func1(list->status, padding); 132644743693Sstephh n = 1; 132744743693Sstephh j = 0; 132844743693Sstephh while ((list = list->next) != end) { 132944743693Sstephh if (limit == 0 || n < limit) { 133044743693Sstephh print_name(list, func, padding, &n, pct, full); 133144743693Sstephh if (func1) 133244743693Sstephh func1(list->status, padding); 133344743693Sstephh } else 133444743693Sstephh j++; 133544743693Sstephh } 133644743693Sstephh if (j == 1) { 133744743693Sstephh print_name(list->prev, func, padding, &n, pct, full); 133844743693Sstephh } else if (j > 1) { 133944743693Sstephh (void) printf("%s... %d %s\n", padding, j, 134044743693Sstephh dgettext("FMD", "more entries suppressed," 134144743693Sstephh " use -v option for full list")); 134244743693Sstephh } 134344743693Sstephh free(padding); 134444743693Sstephh } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate static int 134744743693Sstephh asru_same_status(name_list_t *list) 13487c478bd9Sstevel@tonic-gate { 134944743693Sstephh name_list_t *end = list; 135044743693Sstephh int status = list->status; 135144743693Sstephh 135244743693Sstephh while ((list = list->next) != end) { 135344743693Sstephh if (status == -1) { 135444743693Sstephh status = list->status; 135544743693Sstephh continue; 135644743693Sstephh } 135744743693Sstephh if (list->status != -1 && status != list->status) { 135844743693Sstephh status = -1; 135944743693Sstephh break; 136044743693Sstephh } 13617c478bd9Sstevel@tonic-gate } 136244743693Sstephh return (status); 136344743693Sstephh } 136444743693Sstephh 136544743693Sstephh static int 136644743693Sstephh serial_in_fru(name_list_t *fru, name_list_t *serial) 136744743693Sstephh { 136844743693Sstephh name_list_t *sp = serial; 136944743693Sstephh name_list_t *fp; 137044743693Sstephh int nserial = 0; 137144743693Sstephh int found = 0; 137244743693Sstephh char buf[128]; 13737c478bd9Sstevel@tonic-gate 137444743693Sstephh while (sp) { 137544743693Sstephh fp = fru; 137644743693Sstephh nserial++; 137744743693Sstephh (void) snprintf(buf, sizeof (buf), "serial=%s", sp->name); 137844743693Sstephh buf[sizeof (buf) - 1] = 0; 137944743693Sstephh while (fp) { 138044743693Sstephh if (strstr(fp->name, buf) != NULL) { 138144743693Sstephh found++; 138244743693Sstephh break; 138344743693Sstephh } 138444743693Sstephh fp = fp->next; 138544743693Sstephh if (fp == fru) 138644743693Sstephh break; 138744743693Sstephh } 138844743693Sstephh sp = sp->next; 138944743693Sstephh if (sp == serial) 139044743693Sstephh break; 139144743693Sstephh } 139244743693Sstephh return (found == nserial ? 1 : 0); 139344743693Sstephh } 139444743693Sstephh 139544743693Sstephh static void 139644743693Sstephh print_sup_record(status_record_t *srp, int opt_i, int full) 139744743693Sstephh { 139844743693Sstephh char buf[32]; 139944743693Sstephh uurec_t *uurp = srp->uurec; 140044743693Sstephh int n, j, k, max; 140144743693Sstephh int status; 140244743693Sstephh ari_list_t *ari_list; 140344743693Sstephh 140444743693Sstephh n = 0; 140544743693Sstephh max = max_fault; 140644743693Sstephh if (max < 0) { 140744743693Sstephh max = 0; 140844743693Sstephh } 140944743693Sstephh j = max / 2; 141044743693Sstephh max -= j; 141144743693Sstephh k = srp->nrecs - max; 141244743693Sstephh while ((uurp = uurp->next) != NULL) { 141344743693Sstephh if (full || n < j || n >= k || max_fault == 0 || 141444743693Sstephh srp->nrecs == max_fault+1) { 141544743693Sstephh if (opt_i) { 141644743693Sstephh ari_list = uurp->ari_uuid_list; 141744743693Sstephh while (ari_list) { 141844743693Sstephh (void) printf("%-15s %s\n", 141944743693Sstephh format_date(buf, sizeof (buf), 142044743693Sstephh uurp->sec), ari_list->ari_uuid); 142144743693Sstephh ari_list = ari_list->next; 142244743693Sstephh } 142344743693Sstephh } else { 142444743693Sstephh (void) printf("%-15s %s\n", 142544743693Sstephh format_date(buf, sizeof (buf), uurp->sec), 142644743693Sstephh uurp->uuid); 142744743693Sstephh } 142844743693Sstephh } else if (n == j) 142944743693Sstephh (void) printf("... %d %s\n", srp->nrecs - max_fault, 143044743693Sstephh dgettext("FMD", "more entries suppressed")); 143144743693Sstephh n++; 143244743693Sstephh } 143344743693Sstephh (void) printf("\n"); 1434cbf75e67SStephen Hanson (void) printf("%s %s", dgettext("FMD", "Host :"), 1435cbf75e67SStephen Hanson srp->host->server); 1436cbf75e67SStephen Hanson if (srp->host->domain) 1437cbf75e67SStephen Hanson (void) printf("\t%s %s", dgettext("FMD", "Domain :"), 1438cbf75e67SStephen Hanson srp->host->domain); 1439cbf75e67SStephen Hanson (void) printf("\n%s %s", dgettext("FMD", "Platform :"), 1440cbf75e67SStephen Hanson srp->host->platform); 1441cbf75e67SStephen Hanson (void) printf("\t%s %s\n\n", dgettext("FMD", "Chassis_id :"), 1442cbf75e67SStephen Hanson srp->host->chassis ? srp->host->chassis : ""); 144344743693Sstephh if (srp->class) 144444743693Sstephh print_name_list(srp->class, 144544743693Sstephh dgettext("FMD", "Fault class :"), NULL, 0, srp->class->pct, 144644743693Sstephh NULL, full); 144744743693Sstephh if (srp->asru) { 144844743693Sstephh status = asru_same_status(srp->asru); 144944743693Sstephh if (status != -1) { 145044743693Sstephh print_name_list(srp->asru, 145144743693Sstephh dgettext("FMD", "Affects :"), NULL, 145244743693Sstephh full ? 0 : max_display, 0, NULL, full); 145344743693Sstephh print_asru_status(status, " "); 145444743693Sstephh } else 145544743693Sstephh print_name_list(srp->asru, 145644743693Sstephh dgettext("FMD", "Affects :"), NULL, 145744743693Sstephh full ? 0 : max_display, 0, print_asru_status, full); 145844743693Sstephh } 1459cbf75e67SStephen Hanson if (full || srp->fru == NULL || srp->asru == NULL) { 146044743693Sstephh if (srp->resource) { 146144743693Sstephh print_name_list(srp->resource, 146244743693Sstephh dgettext("FMD", "Problem in :"), 1463cbf75e67SStephen Hanson NULL, full ? 0 : max_display, 0, print_rsrc_status, 1464567cc2e6Sstephh full); 146544743693Sstephh } 146644743693Sstephh } 146744743693Sstephh if (srp->fru) { 1468567cc2e6Sstephh status = asru_same_status(srp->fru); 1469567cc2e6Sstephh if (status != -1) { 1470567cc2e6Sstephh print_name_list(srp->fru, dgettext("FMD", 1471567cc2e6Sstephh "FRU :"), get_fmri_label, 0, 1472567cc2e6Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct, 1473567cc2e6Sstephh NULL, full); 1474567cc2e6Sstephh print_fru_status(status, " "); 1475567cc2e6Sstephh } else 1476567cc2e6Sstephh print_name_list(srp->fru, dgettext("FMD", 1477567cc2e6Sstephh "FRU :"), get_fmri_label, 0, 1478567cc2e6Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct, 1479567cc2e6Sstephh print_fru_status, full); 148044743693Sstephh } 148144743693Sstephh if (srp->serial && !serial_in_fru(srp->fru, srp->serial) && 148244743693Sstephh !serial_in_fru(srp->asru, srp->serial)) { 148344743693Sstephh print_name_list(srp->serial, dgettext("FMD", "Serial ID. :"), 148444743693Sstephh NULL, 0, 0, NULL, full); 148544743693Sstephh } 1486*b6955755SRobert Johnston print_dict_info(srp->msgid); 148744743693Sstephh (void) printf("\n"); 148844743693Sstephh } 148944743693Sstephh 149044743693Sstephh static void 149144743693Sstephh print_status_record(status_record_t *srp, int summary, int opt_i, int full) 149244743693Sstephh { 149344743693Sstephh char buf[32]; 149444743693Sstephh uurec_t *uurp = srp->uurec; 149544743693Sstephh static int header = 0; 149644743693Sstephh char *head; 149744743693Sstephh ari_list_t *ari_list; 149844743693Sstephh 149944743693Sstephh if (!summary || !header) { 150044743693Sstephh if (opt_i) { 150144743693Sstephh head = "--------------- " 150244743693Sstephh "------------------------------------ " 150344743693Sstephh "-------------- ---------\n" 150444743693Sstephh "TIME CACHE-ID" 150544743693Sstephh " MSG-ID" 150644743693Sstephh " SEVERITY\n--------------- " 150744743693Sstephh "------------------------------------ " 150844743693Sstephh " -------------- ---------"; 150944743693Sstephh } else { 151044743693Sstephh head = "--------------- " 151144743693Sstephh "------------------------------------ " 151244743693Sstephh "-------------- ---------\n" 151344743693Sstephh "TIME EVENT-ID" 151444743693Sstephh " MSG-ID" 151544743693Sstephh " SEVERITY\n--------------- " 151644743693Sstephh "------------------------------------ " 151744743693Sstephh " -------------- ---------"; 151844743693Sstephh } 151944743693Sstephh (void) printf("%s\n", dgettext("FMD", head)); 152044743693Sstephh header = 1; 152144743693Sstephh } 152244743693Sstephh if (opt_i) { 152344743693Sstephh ari_list = uurp->ari_uuid_list; 152444743693Sstephh while (ari_list) { 152544743693Sstephh (void) printf("%-15s %-37s %-14s %-9s\n", 152644743693Sstephh format_date(buf, sizeof (buf), uurp->sec), 1527*b6955755SRobert Johnston ari_list->ari_uuid, srp->msgid, srp->severity); 152844743693Sstephh ari_list = ari_list->next; 152944743693Sstephh } 153044743693Sstephh } else { 153144743693Sstephh (void) printf("%-15s %-37s %-14s %-9s\n", 153244743693Sstephh format_date(buf, sizeof (buf), uurp->sec), 1533*b6955755SRobert Johnston uurp->uuid, srp->msgid, srp->severity); 153444743693Sstephh } 153544743693Sstephh 153644743693Sstephh if (!summary) 153744743693Sstephh print_sup_record(srp, opt_i, full); 153844743693Sstephh } 153944743693Sstephh 154044743693Sstephh static void 154144743693Sstephh print_catalog(int summary, int opt_a, int full, int opt_i, int page_feed) 154244743693Sstephh { 154344743693Sstephh status_record_t *srp; 154444743693Sstephh sr_list_t *slp; 154544743693Sstephh 154644743693Sstephh slp = status_rec_list; 154744743693Sstephh if (slp) { 154844743693Sstephh for (;;) { 154944743693Sstephh srp = slp->status_record; 155044743693Sstephh if (opt_a || srp->not_suppressed) { 155144743693Sstephh if (page_feed) 155244743693Sstephh (void) printf("\f\n"); 155344743693Sstephh print_status_record(srp, summary, opt_i, full); 155444743693Sstephh } 155544743693Sstephh if (slp->next == status_rec_list) 155644743693Sstephh break; 155744743693Sstephh slp = slp->next; 155844743693Sstephh } 155944743693Sstephh } 156044743693Sstephh } 156144743693Sstephh 156244743693Sstephh static name_list_t * 156344743693Sstephh find_fru(status_record_t *srp, char *resource) 156444743693Sstephh { 156544743693Sstephh name_list_t *rt = NULL; 156644743693Sstephh name_list_t *fru = srp->fru; 156744743693Sstephh 156844743693Sstephh while (fru) { 156944743693Sstephh if (strcmp(resource, fru->name) == 0) { 157044743693Sstephh rt = fru; 157144743693Sstephh break; 157244743693Sstephh } 157344743693Sstephh fru = fru->next; 157444743693Sstephh if (fru == srp->fru) 157544743693Sstephh break; 157644743693Sstephh } 157744743693Sstephh return (rt); 157844743693Sstephh } 157944743693Sstephh 158044743693Sstephh static void 158144743693Sstephh print_fru_line(name_list_t *fru, char *uuid) 158244743693Sstephh { 158344743693Sstephh if (fru->pct == 100) { 158444743693Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count, 158544743693Sstephh dgettext("FMD", "suspects in this FRU total certainty"), 158644743693Sstephh 100); 158744743693Sstephh } else { 158844743693Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count, 158944743693Sstephh dgettext("FMD", "suspects in this FRU max certainty"), 159044743693Sstephh fru->max_pct); 159144743693Sstephh } 159244743693Sstephh } 159344743693Sstephh 159444743693Sstephh static void 159544743693Sstephh print_fru(int summary, int opt_a, int opt_i, int page_feed) 159644743693Sstephh { 159744743693Sstephh resource_list_t *tp = status_fru_list; 159844743693Sstephh status_record_t *srp; 159944743693Sstephh sr_list_t *slp, *end; 160044743693Sstephh char *msgid, *fru_label; 160144743693Sstephh uurec_t *uurp; 160244743693Sstephh name_list_t *fru; 1603567cc2e6Sstephh int status; 160444743693Sstephh ari_list_t *ari_list; 160544743693Sstephh 160644743693Sstephh while (tp) { 160744743693Sstephh if (opt_a || tp->not_suppressed) { 160844743693Sstephh if (page_feed) 160944743693Sstephh (void) printf("\f\n"); 161044743693Sstephh if (!summary) 161144743693Sstephh (void) printf("-----------------------------" 161244743693Sstephh "---------------------------------------" 161344743693Sstephh "----------\n"); 1614d4c0a8c5Sstephh slp = tp->status_rec_list; 1615d4c0a8c5Sstephh end = slp; 1616d4c0a8c5Sstephh do { 1617d4c0a8c5Sstephh srp = slp->status_record; 1618d4c0a8c5Sstephh fru = find_fru(srp, tp->resource); 1619d4c0a8c5Sstephh if (fru) { 1620d4c0a8c5Sstephh if (fru->label) 1621567cc2e6Sstephh (void) printf("\"%s\" (%s) ", 1622d4c0a8c5Sstephh fru->label, fru->name); 1623567cc2e6Sstephh else if ((fru_label = get_fmri_label( 1624567cc2e6Sstephh fru->name)) != NULL) { 1625567cc2e6Sstephh (void) printf("\"%s\" (%s) ", 1626d4c0a8c5Sstephh fru_label, fru->name); 1627d4c0a8c5Sstephh free(fru_label); 1628d4c0a8c5Sstephh } else 1629567cc2e6Sstephh (void) printf("%s ", 1630d4c0a8c5Sstephh fru->name); 1631d4c0a8c5Sstephh break; 1632d4c0a8c5Sstephh } 1633d4c0a8c5Sstephh slp = slp->next; 1634d4c0a8c5Sstephh } while (slp != end); 1635d4c0a8c5Sstephh 1636567cc2e6Sstephh slp = tp->status_rec_list; 1637567cc2e6Sstephh end = slp; 1638567cc2e6Sstephh status = 0; 1639567cc2e6Sstephh do { 1640567cc2e6Sstephh srp = slp->status_record; 1641567cc2e6Sstephh fru = srp->fru; 1642567cc2e6Sstephh while (fru) { 1643567cc2e6Sstephh if (strcmp(tp->resource, 1644567cc2e6Sstephh fru->name) == 0) 1645567cc2e6Sstephh status |= fru->status; 1646567cc2e6Sstephh fru = fru->next; 1647567cc2e6Sstephh if (fru == srp->fru) 1648567cc2e6Sstephh break; 1649567cc2e6Sstephh } 1650567cc2e6Sstephh slp = slp->next; 1651567cc2e6Sstephh } while (slp != end); 1652567cc2e6Sstephh if (status & FM_SUSPECT_NOT_PRESENT) 1653567cc2e6Sstephh (void) printf(dgettext("FMD", "not present\n")); 1654567cc2e6Sstephh else if (status & FM_SUSPECT_FAULTY) 1655567cc2e6Sstephh (void) printf(dgettext("FMD", "faulty\n")); 165625c6ff4bSstephh else if (status & FM_SUSPECT_REPLACED) 165725c6ff4bSstephh (void) printf(dgettext("FMD", "replaced\n")); 165825c6ff4bSstephh else if (status & FM_SUSPECT_REPAIRED) 165925c6ff4bSstephh (void) printf(dgettext("FMD", 166025c6ff4bSstephh "repair attempted\n")); 166125c6ff4bSstephh else if (status & FM_SUSPECT_ACQUITTED) 166225c6ff4bSstephh (void) printf(dgettext("FMD", "acquitted\n")); 1663567cc2e6Sstephh else 166425c6ff4bSstephh (void) printf(dgettext("FMD", "removed\n")); 1665567cc2e6Sstephh 166644743693Sstephh slp = tp->status_rec_list; 166744743693Sstephh end = slp; 166844743693Sstephh do { 166944743693Sstephh srp = slp->status_record; 167044743693Sstephh uurp = srp->uurec; 167144743693Sstephh fru = find_fru(srp, tp->resource); 167244743693Sstephh if (fru) { 167344743693Sstephh if (opt_i) { 167444743693Sstephh ari_list = uurp->ari_uuid_list; 167544743693Sstephh while (ari_list) { 167644743693Sstephh print_fru_line(fru, 167744743693Sstephh ari_list->ari_uuid); 167844743693Sstephh ari_list = 167944743693Sstephh ari_list->next; 168044743693Sstephh } 168144743693Sstephh } else { 168244743693Sstephh print_fru_line(fru, uurp->uuid); 168344743693Sstephh } 168444743693Sstephh } 168544743693Sstephh slp = slp->next; 168644743693Sstephh } while (slp != end); 168744743693Sstephh if (!summary) { 168844743693Sstephh slp = tp->status_rec_list; 168944743693Sstephh end = slp; 169044743693Sstephh srp = slp->status_record; 169144743693Sstephh if (srp->serial && 169244743693Sstephh !serial_in_fru(srp->fru, srp->serial)) { 169344743693Sstephh print_name_list(srp->serial, 169444743693Sstephh dgettext("FMD", "Serial ID. :"), 169544743693Sstephh NULL, 0, 0, NULL, 1); 169644743693Sstephh } 169744743693Sstephh msgid = NULL; 169844743693Sstephh do { 169944743693Sstephh if (msgid == NULL || 170044743693Sstephh strcmp(msgid, srp->msgid) != 0) { 170144743693Sstephh msgid = srp->msgid; 1702*b6955755SRobert Johnston print_dict_info(srp->msgid); 170344743693Sstephh } 170444743693Sstephh slp = slp->next; 170544743693Sstephh } while (slp != end); 170644743693Sstephh } 170744743693Sstephh } 170844743693Sstephh tp = tp->next; 170944743693Sstephh if (tp == status_fru_list) 171044743693Sstephh break; 171144743693Sstephh } 171244743693Sstephh } 171344743693Sstephh 171444743693Sstephh static void 171544743693Sstephh print_asru(int opt_a) 171644743693Sstephh { 171744743693Sstephh resource_list_t *tp = status_asru_list; 171844743693Sstephh status_record_t *srp; 171944743693Sstephh sr_list_t *slp, *end; 172044743693Sstephh char *msg; 172144743693Sstephh int status; 172244743693Sstephh name_list_t *asru; 172344743693Sstephh 172444743693Sstephh while (tp) { 172544743693Sstephh if (opt_a || tp->not_suppressed) { 172644743693Sstephh status = 0; 172744743693Sstephh slp = tp->status_rec_list; 172844743693Sstephh end = slp; 172944743693Sstephh do { 173044743693Sstephh srp = slp->status_record; 173144743693Sstephh asru = srp->asru; 173244743693Sstephh while (asru) { 173344743693Sstephh if (strcmp(tp->resource, 173444743693Sstephh asru->name) == 0) 173544743693Sstephh status |= asru->status; 173644743693Sstephh asru = asru->next; 173744743693Sstephh if (asru == srp->asru) 173844743693Sstephh break; 173944743693Sstephh } 174044743693Sstephh slp = slp->next; 174144743693Sstephh } while (slp != end); 174244743693Sstephh switch (status) { 174344743693Sstephh case 0: 174444743693Sstephh msg = dgettext("FMD", "ok"); 174544743693Sstephh break; 174625c6ff4bSstephh case FM_SUSPECT_DEGRADED: 174725c6ff4bSstephh msg = dgettext("FMD", "degraded"); 174825c6ff4bSstephh break; 174925c6ff4bSstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED: 175025c6ff4bSstephh msg = dgettext("FMD", "degraded"); 175125c6ff4bSstephh break; 175244743693Sstephh case FM_SUSPECT_FAULTY: 175344743693Sstephh msg = dgettext("FMD", "degraded"); 175444743693Sstephh break; 175544743693Sstephh case FM_SUSPECT_UNUSABLE: 175644743693Sstephh msg = dgettext("FMD", "unknown"); 175744743693Sstephh break; 175844743693Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE: 175944743693Sstephh msg = dgettext("FMD", "faulted"); 176044743693Sstephh break; 176144743693Sstephh default: 176244743693Sstephh msg = ""; 176344743693Sstephh break; 176444743693Sstephh } 176544743693Sstephh (void) printf("%-69s %s\n", tp->resource, msg); 176644743693Sstephh } 176744743693Sstephh tp = tp->next; 176844743693Sstephh if (tp == status_asru_list) 176944743693Sstephh break; 177044743693Sstephh } 177144743693Sstephh } 177244743693Sstephh 177344743693Sstephh static int 177444743693Sstephh uuid_in_list(char *uuid, uurec_select_t *uurecp) 177544743693Sstephh { 177644743693Sstephh while (uurecp) { 177744743693Sstephh if (strcmp(uuid, uurecp->uuid) == 0) 177844743693Sstephh return (1); 177944743693Sstephh uurecp = uurecp->next; 178044743693Sstephh } 17817c478bd9Sstevel@tonic-gate return (0); 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate static int 178544743693Sstephh dfault_rec(const fmd_adm_caseinfo_t *acp, void *arg) 17867c478bd9Sstevel@tonic-gate { 178744743693Sstephh int64_t *diag_time; 178844743693Sstephh uint_t nelem; 178944743693Sstephh int rt = 0; 179044743693Sstephh char *uuid = "-"; 179144743693Sstephh uurec_select_t *uurecp = (uurec_select_t *)arg; 179244743693Sstephh 179344743693Sstephh if (nvlist_lookup_int64_array(acp->aci_event, FM_SUSPECT_DIAG_TIME, 179444743693Sstephh &diag_time, &nelem) == 0 && nelem >= 2) { 179544743693Sstephh (void) nvlist_lookup_string(acp->aci_event, FM_SUSPECT_UUID, 179644743693Sstephh &uuid); 179744743693Sstephh if (uurecp == NULL || uuid_in_list(uuid, uurecp)) 179844743693Sstephh add_fault_record_to_catalog(acp->aci_event, *diag_time, 1799*b6955755SRobert Johnston uuid); 180044743693Sstephh } else { 180144743693Sstephh rt = -1; 18027c478bd9Sstevel@tonic-gate } 180344743693Sstephh return (rt); 180444743693Sstephh } 18057c478bd9Sstevel@tonic-gate 180644743693Sstephh /*ARGSUSED*/ 180744743693Sstephh static int 180844743693Sstephh dstatus_rec(const fmd_adm_rsrcinfo_t *ari, void *unused) 180944743693Sstephh { 181044743693Sstephh update_asru_state_in_catalog(ari->ari_case, ari->ari_uuid); 18117c478bd9Sstevel@tonic-gate return (0); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 181444743693Sstephh static int 181544743693Sstephh get_cases_from_fmd(fmd_adm_t *adm, uurec_select_t *uurecp, int opt_i) 181644743693Sstephh { 181744743693Sstephh int rt = FMADM_EXIT_SUCCESS; 181844743693Sstephh 181944743693Sstephh /* 182044743693Sstephh * These calls may fail with Protocol error if message payload is to big 182144743693Sstephh */ 182244743693Sstephh if (fmd_adm_case_iter(adm, NULL, dfault_rec, uurecp) != 0) 182344743693Sstephh die("failed to get case list from fmd"); 182444743693Sstephh if (opt_i && fmd_adm_rsrc_iter(adm, 1, dstatus_rec, NULL) != 0) 182544743693Sstephh die("failed to get case status from fmd"); 182644743693Sstephh return (rt); 182744743693Sstephh } 182844743693Sstephh 182944743693Sstephh /* 183044743693Sstephh * fmadm faulty command 183144743693Sstephh * 183244743693Sstephh * -a show hidden fault records 183344743693Sstephh * -f show faulty fru's 183444743693Sstephh * -g force grouping of similar faults on the same fru 183544743693Sstephh * -n number of fault records to display 183644743693Sstephh * -p pipe output through pager 183744743693Sstephh * -r show faulty asru's 183844743693Sstephh * -s print summary of first fault 183944743693Sstephh * -u print listed uuid's only 184044743693Sstephh * -v full output 184144743693Sstephh */ 184244743693Sstephh 18437c478bd9Sstevel@tonic-gate int 18447c478bd9Sstevel@tonic-gate cmd_faulty(fmd_adm_t *adm, int argc, char *argv[]) 18457c478bd9Sstevel@tonic-gate { 184644743693Sstephh int opt_a = 0, opt_v = 0, opt_p = 0, opt_s = 0, opt_r = 0, opt_f = 0; 184744743693Sstephh int opt_i = 0; 184844743693Sstephh char *pager; 184944743693Sstephh FILE *fp; 185044743693Sstephh int rt, c, stat; 185144743693Sstephh uurec_select_t *tp; 185244743693Sstephh uurec_select_t *uurecp = NULL; 18537c478bd9Sstevel@tonic-gate 185444743693Sstephh while ((c = getopt(argc, argv, "afgin:prsu:v")) != EOF) { 18557c478bd9Sstevel@tonic-gate switch (c) { 18567c478bd9Sstevel@tonic-gate case 'a': 18577c478bd9Sstevel@tonic-gate opt_a++; 18587c478bd9Sstevel@tonic-gate break; 185944743693Sstephh case 'f': 186044743693Sstephh opt_f++; 186144743693Sstephh break; 186244743693Sstephh case 'g': 186344743693Sstephh opt_g++; 186444743693Sstephh break; 18657c478bd9Sstevel@tonic-gate case 'i': 186644743693Sstephh opt_i++; 186744743693Sstephh break; 186844743693Sstephh case 'n': 186944743693Sstephh max_fault = atoi(optarg); 187044743693Sstephh break; 187144743693Sstephh case 'p': 187244743693Sstephh opt_p++; 187344743693Sstephh break; 187444743693Sstephh case 'r': 187544743693Sstephh opt_r++; 187644743693Sstephh break; 187744743693Sstephh case 's': 187844743693Sstephh opt_s++; 187944743693Sstephh break; 188044743693Sstephh case 'u': 188144743693Sstephh tp = (uurec_select_t *)malloc(sizeof (uurec_select_t)); 188244743693Sstephh tp->uuid = optarg; 188344743693Sstephh tp->next = uurecp; 188444743693Sstephh uurecp = tp; 188544743693Sstephh opt_a = 1; 188644743693Sstephh break; 188744743693Sstephh case 'v': 188844743693Sstephh opt_v++; 18897c478bd9Sstevel@tonic-gate break; 18907c478bd9Sstevel@tonic-gate default: 18917c478bd9Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate if (optind < argc) 18957c478bd9Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 18967c478bd9Sstevel@tonic-gate 1897*b6955755SRobert Johnston if ((fmadm_msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) == NULL) 1898*b6955755SRobert Johnston return (FMADM_EXIT_ERROR); 189944743693Sstephh rt = get_cases_from_fmd(adm, uurecp, opt_i); 190044743693Sstephh if (opt_p) { 190144743693Sstephh if ((pager = getenv("PAGER")) == NULL) 190244743693Sstephh pager = "/usr/bin/more"; 190344743693Sstephh fp = popen(pager, "w"); 190444743693Sstephh if (fp == NULL) { 190544743693Sstephh rt = FMADM_EXIT_ERROR; 190644743693Sstephh opt_p = 0; 190744743693Sstephh } else { 190844743693Sstephh dup2(fileno(fp), 1); 190944743693Sstephh setbuf(stdout, NULL); 191044743693Sstephh (void) fclose(fp); 191144743693Sstephh } 191244743693Sstephh } 191344743693Sstephh max_display = max_fault; 191444743693Sstephh if (opt_f) 191544743693Sstephh print_fru(opt_s, opt_a, opt_i, opt_p && !opt_s); 191644743693Sstephh if (opt_r) 191744743693Sstephh print_asru(opt_a); 191844743693Sstephh if (opt_f == 0 && opt_r == 0) 191944743693Sstephh print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s); 1920*b6955755SRobert Johnston fmd_msg_fini(fmadm_msghdl); 192144743693Sstephh label_release_topo(); 192244743693Sstephh if (opt_p) { 192344743693Sstephh (void) fclose(stdout); 192444743693Sstephh (void) wait(&stat); 192544743693Sstephh } 192644743693Sstephh return (rt); 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate int 19307c478bd9Sstevel@tonic-gate cmd_flush(fmd_adm_t *adm, int argc, char *argv[]) 19317c478bd9Sstevel@tonic-gate { 19327c478bd9Sstevel@tonic-gate int i, status = FMADM_EXIT_SUCCESS; 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate if (argc < 2 || (i = getopt(argc, argv, "")) != EOF) 19357c478bd9Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 19387c478bd9Sstevel@tonic-gate if (fmd_adm_rsrc_flush(adm, argv[i]) != 0) { 19397c478bd9Sstevel@tonic-gate warn("failed to flush %s", argv[i]); 19407c478bd9Sstevel@tonic-gate status = FMADM_EXIT_ERROR; 19417c478bd9Sstevel@tonic-gate } else 19427c478bd9Sstevel@tonic-gate note("flushed resource history for %s\n", argv[i]); 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate return (status); 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate int 19497c478bd9Sstevel@tonic-gate cmd_repair(fmd_adm_t *adm, int argc, char *argv[]) 19507c478bd9Sstevel@tonic-gate { 19517c478bd9Sstevel@tonic-gate int err; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate if (getopt(argc, argv, "") != EOF) 19547c478bd9Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate if (argc - optind != 1) 19577c478bd9Sstevel@tonic-gate return (FMADM_EXIT_USAGE); 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate /* 196025c6ff4bSstephh * argument could be a uuid, an fmri (asru, fru or resource) 1961567cc2e6Sstephh * or a label. Try uuid first, If that fails try the others. 19627c478bd9Sstevel@tonic-gate */ 1963567cc2e6Sstephh err = fmd_adm_case_repair(adm, argv[optind]); 1964567cc2e6Sstephh if (err != 0) 196525c6ff4bSstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]); 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate if (err != 0) 19687c478bd9Sstevel@tonic-gate die("failed to record repair to %s", argv[optind]); 19697c478bd9Sstevel@tonic-gate 19707c478bd9Sstevel@tonic-gate note("recorded repair to %s\n", argv[optind]); 19717c478bd9Sstevel@tonic-gate return (FMADM_EXIT_SUCCESS); 19727c478bd9Sstevel@tonic-gate } 197325c6ff4bSstephh 197425c6ff4bSstephh int 197525c6ff4bSstephh cmd_repaired(fmd_adm_t *adm, int argc, char *argv[]) 197625c6ff4bSstephh { 197725c6ff4bSstephh int err; 197825c6ff4bSstephh 197925c6ff4bSstephh if (getopt(argc, argv, "") != EOF) 198025c6ff4bSstephh return (FMADM_EXIT_USAGE); 198125c6ff4bSstephh 198225c6ff4bSstephh if (argc - optind != 1) 198325c6ff4bSstephh return (FMADM_EXIT_USAGE); 198425c6ff4bSstephh 198525c6ff4bSstephh /* 198625c6ff4bSstephh * argument could be an fmri (asru, fru or resource) or a label. 198725c6ff4bSstephh */ 198825c6ff4bSstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]); 198925c6ff4bSstephh if (err != 0) 199025c6ff4bSstephh die("failed to record repair to %s", argv[optind]); 199125c6ff4bSstephh 199225c6ff4bSstephh note("recorded repair to of %s\n", argv[optind]); 199325c6ff4bSstephh return (FMADM_EXIT_SUCCESS); 199425c6ff4bSstephh } 199525c6ff4bSstephh 199625c6ff4bSstephh int 199725c6ff4bSstephh cmd_replaced(fmd_adm_t *adm, int argc, char *argv[]) 199825c6ff4bSstephh { 199925c6ff4bSstephh int err; 200025c6ff4bSstephh 200125c6ff4bSstephh if (getopt(argc, argv, "") != EOF) 200225c6ff4bSstephh return (FMADM_EXIT_USAGE); 200325c6ff4bSstephh 200425c6ff4bSstephh if (argc - optind != 1) 200525c6ff4bSstephh return (FMADM_EXIT_USAGE); 200625c6ff4bSstephh 200725c6ff4bSstephh /* 200825c6ff4bSstephh * argument could be an fmri (asru, fru or resource) or a label. 200925c6ff4bSstephh */ 201025c6ff4bSstephh err = fmd_adm_rsrc_replaced(adm, argv[optind]); 201125c6ff4bSstephh if (err != 0) 201225c6ff4bSstephh die("failed to record replacement of %s", argv[optind]); 201325c6ff4bSstephh 201425c6ff4bSstephh note("recorded replacement of %s\n", argv[optind]); 201525c6ff4bSstephh return (FMADM_EXIT_SUCCESS); 201625c6ff4bSstephh } 201725c6ff4bSstephh 201825c6ff4bSstephh int 201925c6ff4bSstephh cmd_acquit(fmd_adm_t *adm, int argc, char *argv[]) 202025c6ff4bSstephh { 202125c6ff4bSstephh int err; 202225c6ff4bSstephh 202325c6ff4bSstephh if (getopt(argc, argv, "") != EOF) 202425c6ff4bSstephh return (FMADM_EXIT_USAGE); 202525c6ff4bSstephh 202625c6ff4bSstephh if (argc - optind != 1 && argc - optind != 2) 202725c6ff4bSstephh return (FMADM_EXIT_USAGE); 202825c6ff4bSstephh 202925c6ff4bSstephh /* 203025c6ff4bSstephh * argument could be a uuid, an fmri (asru, fru or resource) 203125c6ff4bSstephh * or a label. Or it could be a uuid and an fmri or label. 203225c6ff4bSstephh */ 203325c6ff4bSstephh if (argc - optind == 2) { 203425c6ff4bSstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], argv[optind + 1]); 203525c6ff4bSstephh if (err != 0) 203625c6ff4bSstephh err = fmd_adm_rsrc_acquit(adm, argv[optind + 1], 203725c6ff4bSstephh argv[optind]); 203825c6ff4bSstephh } else { 203925c6ff4bSstephh err = fmd_adm_case_acquit(adm, argv[optind]); 204025c6ff4bSstephh if (err != 0) 204125c6ff4bSstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], ""); 204225c6ff4bSstephh } 204325c6ff4bSstephh 204425c6ff4bSstephh if (err != 0) 204525c6ff4bSstephh die("failed to record acquital of %s", argv[optind]); 204625c6ff4bSstephh 204725c6ff4bSstephh note("recorded acquital of %s\n", argv[optind]); 204825c6ff4bSstephh return (FMADM_EXIT_SUCCESS); 204925c6ff4bSstephh } 2050