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 /*
22*12618SStephen.Hanson@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
255255Sstephh #include <sys/types.h>
265255Sstephh #include <fmadm.h>
275255Sstephh #include <errno.h>
285255Sstephh #include <limits.h>
290Sstevel@tonic-gate #include <strings.h>
305255Sstephh #include <stdio.h>
315255Sstephh #include <unistd.h>
325255Sstephh #include <sys/wait.h>
335255Sstephh #include <sys/stat.h>
345255Sstephh #include <fcntl.h>
355255Sstephh #include <fm/fmd_log.h>
365255Sstephh #include <sys/fm/protocol.h>
375255Sstephh #include <fm/libtopo.h>
385255Sstephh #include <fm/fmd_adm.h>
399501SRobert.Johnston@Sun.COM #include <fm/fmd_msg.h>
405255Sstephh #include <dlfcn.h>
415255Sstephh #include <sys/systeminfo.h>
425255Sstephh #include <sys/utsname.h>
435255Sstephh #include <libintl.h>
445255Sstephh #include <locale.h>
455255Sstephh #include <sys/smbios.h>
465255Sstephh #include <libdevinfo.h>
475255Sstephh #include <stdlib.h>
485255Sstephh
495255Sstephh #define offsetof(s, m) ((size_t)(&(((s*)0)->m)))
505255Sstephh
515255Sstephh /*
525255Sstephh * Fault records are added to catalog by calling add_fault_record_to_catalog()
535255Sstephh * records are stored in order of importance to the system.
545255Sstephh * If -g flag is set or not_suppressed is not set and the class fru, fault,
555255Sstephh * type are the same then details are merged into an existing record, with uuid
565255Sstephh * records are stored in time order.
575255Sstephh * For each record information is extracted from nvlist and merged into linked
585255Sstephh * list each is checked for identical records for which percentage certainty are
595255Sstephh * added together.
605255Sstephh * print_catalog() is called to print out catalog and release external resources
615255Sstephh *
625255Sstephh * /---------------\
635255Sstephh * status_rec_list -> | | -|
645255Sstephh * \---------------/
655255Sstephh * \/
665255Sstephh * /---------------\ /-------\ /-------\
675255Sstephh * status_fru_list | status_record | -> | uurec | -> | uurec | -|
685255Sstephh * \/ | | |- | | <- | |
695255Sstephh * /-------------\ | | \-------/ \-------/
705255Sstephh * | | -> | | \/ \/
715255Sstephh * \-------------/ | | /-------\ /-------\
725255Sstephh * \/ | | -> | asru | -> | asru |
735255Sstephh * --- | | | | <- | |
745255Sstephh * | | \-------/ \-------/
755255Sstephh * status_asru_list | class |
765255Sstephh * \/ | resource | /-------\ /-------\
775255Sstephh * /-------------\ | fru | -> | list | -> | list |
785255Sstephh * | | -> | serial | | | <- | |
795255Sstephh * \-------------/ | | \-------/ \-------/
805255Sstephh * \/ \---------------/
815255Sstephh * --- \/ /\
825255Sstephh * /---------------\
835255Sstephh * | status_record |
845255Sstephh * \---------------/
855255Sstephh *
865255Sstephh * Fmadm faulty takes a number of options which affect the format of the
875255Sstephh * output displayed. By default, the display reports the FRU and ASRU along
885255Sstephh * with other information on per-case basis as in the example below.
895255Sstephh *
905255Sstephh * --------------- ------------------------------------ -------------- -------
915255Sstephh * TIME EVENT-ID MSG-ID SEVERITY
925255Sstephh * --------------- ------------------------------------ -------------- -------
935255Sstephh * Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c AMD-8000-2F Major
945255Sstephh *
955255Sstephh * Fault class : fault.memory.dimm_sb
965255Sstephh * Affects : mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0
977275Sstephh * faulted but still in service
985255Sstephh * FRU : "CPU 0 DIMM 0" (hc://.../memory-controller=0/dimm=0)
995255Sstephh * faulty
1005255Sstephh *
1015255Sstephh * Description : The number of errors associated with this memory module has
1025255Sstephh * exceeded acceptable levels. Refer to
1035255Sstephh * http://sun.com/msg/AMD-8000-2F for more information.
1045255Sstephh *
1055255Sstephh * Response : Pages of memory associated with this memory module are being
1065255Sstephh * removed from service as errors are reported.
1075255Sstephh *
1085255Sstephh * Impact : Total system memory capacity will be reduced as pages are
1095255Sstephh * retired.
1105255Sstephh *
1115255Sstephh * Action : Schedule a repair procedure to replace the affected memory
1125255Sstephh * module. Use fmdump -v -u <EVENT_ID> to identify the module.
1135255Sstephh *
1145255Sstephh * The -v flag is similar, but adds some additonal information such as the
1155255Sstephh * resource. The -s flag is also similar but just gives the top line summary.
1165255Sstephh * All these options (ie without the -f or -r flags) use the print_catalog()
1175255Sstephh * function to do the display.
1185255Sstephh *
1195255Sstephh * The -f flag changes the output so that it appears sorted on a per-fru basis.
1205255Sstephh * The output is somewhat cut down compared to the default output. If -f is
1215255Sstephh * used, then print_fru() is used to print the output.
1225255Sstephh *
1235255Sstephh * -----------------------------------------------------------------------------
1245255Sstephh * "SLOT 2" (hc://.../hostbridge=3/pciexrc=3/pciexbus=4/pciexdev=0) faulty
1255255Sstephh * 5ca4aeb3-36...f6be-c2e8166dc484 2 suspects in this FRU total certainty 100%
1265255Sstephh *
1275255Sstephh * Description : A problem was detected for a PCI device.
1285255Sstephh * Refer to http://sun.com/msg/PCI-8000-7J for more information.
1295255Sstephh *
1305255Sstephh * Response : One or more device instances may be disabled
1315255Sstephh *
1325255Sstephh * Impact : Possible loss of services provided by the device instances
1335255Sstephh * associated with this fault
1345255Sstephh *
1355255Sstephh * Action : Schedule a repair procedure to replace the affected device.
1365255Sstephh * Use fmdump -v -u <EVENT_ID> to identify the device or contact
1375255Sstephh * Sun for support.
1385255Sstephh *
1395255Sstephh * The -r flag changes the output so that it appears sorted on a per-asru basis.
1405255Sstephh * The output is very much cut down compared to the default output, just giving
1415255Sstephh * the asru fmri and state. Here print_asru() is used to print the output.
1425255Sstephh *
1435255Sstephh * mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 degraded
1445255Sstephh *
1455255Sstephh * For all fmadm faulty options, the sequence of events is
1465255Sstephh *
1475255Sstephh * 1) Walk through all the cases in the system using fmd_adm_case_iter() and
1485255Sstephh * for each case call dfault_rec(). This will call add_fault_record_to_catalog()
1495255Sstephh * This will extract the data from the nvlist and call catalog_new_record() to
1505255Sstephh * save the data away in various linked lists in the catalogue.
1515255Sstephh *
1525255Sstephh * 2) Once this is done, the data can be supplemented by using
1535255Sstephh * fmd_adm_rsrc_iter(). However this is now only necessary for the -i option.
1545255Sstephh *
1555255Sstephh * 3) Finally print_catalog(), print_fru() or print_asru() are called as
1565255Sstephh * appropriate to display the information from the catalogue sorted in the
1575255Sstephh * requested way.
1585255Sstephh *
1595255Sstephh */
1605255Sstephh
1615255Sstephh typedef struct name_list {
1625255Sstephh struct name_list *next;
1635255Sstephh struct name_list *prev;
1645255Sstephh char *name;
1655255Sstephh uint8_t pct;
1665255Sstephh uint8_t max_pct;
1675255Sstephh ushort_t count;
1685255Sstephh int status;
1696002Sstephh char *label;
1705255Sstephh } name_list_t;
1715255Sstephh
1725255Sstephh typedef struct ari_list {
1735255Sstephh char *ari_uuid;
1745255Sstephh struct ari_list *next;
1755255Sstephh } ari_list_t;
1765255Sstephh
1775255Sstephh typedef struct uurec {
1785255Sstephh struct uurec *next;
1795255Sstephh struct uurec *prev;
1805255Sstephh char *uuid;
1815255Sstephh ari_list_t *ari_uuid_list;
1825255Sstephh name_list_t *asru;
1835255Sstephh uint64_t sec;
18410234SRobert.Johnston@Sun.COM nvlist_t *event;
1855255Sstephh } uurec_t;
1865255Sstephh
1875255Sstephh typedef struct uurec_select {
1885255Sstephh struct uurec_select *next;
1895255Sstephh char *uuid;
1905255Sstephh } uurec_select_t;
1915255Sstephh
1925255Sstephh typedef struct host_id {
1935255Sstephh char *chassis;
1945255Sstephh char *server;
1955255Sstephh char *platform;
1969120SStephen.Hanson@Sun.COM char *domain;
19710462SSean.Ye@Sun.COM char *product_sn;
1985255Sstephh } hostid_t;
1995255Sstephh
2005255Sstephh typedef struct host_id_list {
2015255Sstephh hostid_t hostid;
2025255Sstephh struct host_id_list *next;
2035255Sstephh } host_id_list_t;
2045255Sstephh
2055255Sstephh typedef struct status_record {
2065255Sstephh hostid_t *host;
2075255Sstephh int nrecs;
2085255Sstephh uurec_t *uurec;
2095255Sstephh char *severity; /* in C locale */
2105255Sstephh char *msgid;
2115255Sstephh name_list_t *class;
2125255Sstephh name_list_t *resource;
2135255Sstephh name_list_t *asru;
2145255Sstephh name_list_t *fru;
2155255Sstephh name_list_t *serial;
2165255Sstephh uint8_t not_suppressed;
21710928SStephen.Hanson@Sun.COM uint8_t injected;
2185255Sstephh } status_record_t;
2195255Sstephh
2205255Sstephh typedef struct sr_list {
2215255Sstephh struct sr_list *next;
2225255Sstephh struct sr_list *prev;
2235255Sstephh struct status_record *status_record;
2245255Sstephh } sr_list_t;
2255255Sstephh
2265255Sstephh typedef struct resource_list {
2275255Sstephh struct resource_list *next;
2285255Sstephh struct resource_list *prev;
2295255Sstephh sr_list_t *status_rec_list;
2305255Sstephh char *resource;
2315255Sstephh uint8_t not_suppressed;
23210928SStephen.Hanson@Sun.COM uint8_t injected;
2335255Sstephh uint8_t max_pct;
2345255Sstephh } resource_list_t;
2355255Sstephh
2365255Sstephh sr_list_t *status_rec_list;
2375255Sstephh resource_list_t *status_fru_list;
2385255Sstephh resource_list_t *status_asru_list;
2395255Sstephh
2405255Sstephh static int max_display;
2415255Sstephh static int max_fault = 0;
2425255Sstephh static topo_hdl_t *topo_handle;
2435255Sstephh static host_id_list_t *host_list;
2445255Sstephh static int n_server;
2455255Sstephh static int opt_g;
2469501SRobert.Johnston@Sun.COM static fmd_msg_hdl_t *fmadm_msghdl = NULL; /* handle for libfmd_msg calls */
2475255Sstephh
2485255Sstephh static char *
format_date(char * buf,size_t len,uint64_t sec)2495255Sstephh format_date(char *buf, size_t len, uint64_t sec)
2505255Sstephh {
2515255Sstephh if (sec > LONG_MAX) {
2525255Sstephh (void) fprintf(stderr,
2535255Sstephh "record time is too large for 32-bit utility\n");
2545255Sstephh (void) snprintf(buf, len, "0x%llx", sec);
2555255Sstephh } else {
2565255Sstephh time_t tod = (time_t)sec;
25710928SStephen.Hanson@Sun.COM time_t now = time(NULL);
25810928SStephen.Hanson@Sun.COM if (tod > now+60 ||
25910928SStephen.Hanson@Sun.COM tod < now - 6L*30L*24L*60L*60L) { /* 6 months ago */
26010928SStephen.Hanson@Sun.COM (void) strftime(buf, len, "%b %d %Y ",
26110928SStephen.Hanson@Sun.COM localtime(&tod));
26210928SStephen.Hanson@Sun.COM } else {
26310928SStephen.Hanson@Sun.COM (void) strftime(buf, len, "%b %d %T", localtime(&tod));
26410928SStephen.Hanson@Sun.COM }
2655255Sstephh }
2665255Sstephh
2675255Sstephh return (buf);
2685255Sstephh }
2695255Sstephh
2705255Sstephh static hostid_t *
find_hostid_in_list(char * platform,char * chassis,char * server,char * domain,char * product_sn)27110462SSean.Ye@Sun.COM find_hostid_in_list(char *platform, char *chassis, char *server, char *domain,
27210462SSean.Ye@Sun.COM char *product_sn)
2735255Sstephh {
2745255Sstephh hostid_t *rt = NULL;
2755255Sstephh host_id_list_t *hostp;
2765255Sstephh
2775255Sstephh if (platform == NULL)
2785255Sstephh platform = "-";
2795255Sstephh if (server == NULL)
2805255Sstephh server = "-";
2815255Sstephh hostp = host_list;
2825255Sstephh while (hostp) {
2835255Sstephh if (hostp->hostid.platform &&
2845255Sstephh strcmp(hostp->hostid.platform, platform) == 0 &&
2855255Sstephh hostp->hostid.server &&
2865255Sstephh strcmp(hostp->hostid.server, server) == 0 &&
2875255Sstephh (chassis == NULL || hostp->hostid.chassis == NULL ||
2889120SStephen.Hanson@Sun.COM strcmp(chassis, hostp->hostid.chassis) == 0) &&
28910462SSean.Ye@Sun.COM (product_sn == NULL || hostp->hostid.product_sn == NULL ||
29010462SSean.Ye@Sun.COM strcmp(product_sn, hostp->hostid.product_sn) == 0) &&
2919120SStephen.Hanson@Sun.COM (domain == NULL || hostp->hostid.domain == NULL ||
2929120SStephen.Hanson@Sun.COM strcmp(domain, hostp->hostid.domain) == 0)) {
2935255Sstephh rt = &hostp->hostid;
2945255Sstephh break;
2955255Sstephh }
2965255Sstephh hostp = hostp->next;
2975255Sstephh }
2985255Sstephh if (rt == NULL) {
2995255Sstephh hostp = malloc(sizeof (host_id_list_t));
3005255Sstephh hostp->hostid.platform = strdup(platform);
30110462SSean.Ye@Sun.COM hostp->hostid.product_sn =
30210462SSean.Ye@Sun.COM product_sn ? strdup(product_sn) : NULL;
3035255Sstephh hostp->hostid.server = strdup(server);
3045255Sstephh hostp->hostid.chassis = chassis ? strdup(chassis) : NULL;
3059120SStephen.Hanson@Sun.COM hostp->hostid.domain = domain ? strdup(domain) : NULL;
3065255Sstephh hostp->next = host_list;
3075255Sstephh host_list = hostp;
3085255Sstephh rt = &hostp->hostid;
3095255Sstephh n_server++;
3105255Sstephh }
3115255Sstephh return (rt);
3125255Sstephh }
3135255Sstephh
3145255Sstephh static hostid_t *
find_hostid(nvlist_t * nvl)3155255Sstephh find_hostid(nvlist_t *nvl)
3165255Sstephh {
3179120SStephen.Hanson@Sun.COM char *platform = NULL, *chassis = NULL, *server = NULL, *domain = NULL;
31810462SSean.Ye@Sun.COM char *product_sn = NULL;
3195255Sstephh nvlist_t *auth, *fmri;
3205255Sstephh hostid_t *rt = NULL;
3215255Sstephh
3225255Sstephh if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &fmri) == 0 &&
3235255Sstephh nvlist_lookup_nvlist(fmri, FM_FMRI_AUTHORITY, &auth) == 0) {
3245255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
3255255Sstephh &platform);
32610462SSean.Ye@Sun.COM (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
32710462SSean.Ye@Sun.COM &product_sn);
3285255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server);
3295255Sstephh (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS,
3305255Sstephh &chassis);
3319120SStephen.Hanson@Sun.COM (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_DOMAIN, &domain);
33210462SSean.Ye@Sun.COM rt = find_hostid_in_list(platform, chassis, server,
33310462SSean.Ye@Sun.COM domain, product_sn);
3345255Sstephh }
3355255Sstephh return (rt);
3365255Sstephh }
3375255Sstephh
3385255Sstephh static char *
get_nvl2str_topo(nvlist_t * nvl)3395255Sstephh get_nvl2str_topo(nvlist_t *nvl)
3405255Sstephh {
3415255Sstephh char *name = NULL;
3425255Sstephh char *tname;
3435255Sstephh int err;
3445255Sstephh char *scheme = NULL;
3455255Sstephh char *mod_name = NULL;
3465255Sstephh char buf[128];
3475255Sstephh
3485255Sstephh if (topo_handle == NULL)
349*12618SStephen.Hanson@Sun.COM topo_handle = topo_open(TOPO_VERSION, 0, &err);
3505255Sstephh if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) {
3515255Sstephh name = strdup(tname);
3525255Sstephh topo_hdl_strfree(topo_handle, tname);
3535255Sstephh } else {
3545255Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme);
3555255Sstephh (void) nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &mod_name);
3565255Sstephh if (scheme && strcmp(scheme, FM_FMRI_SCHEME_FMD) == 0 &&
3575255Sstephh mod_name) {
3585255Sstephh (void) snprintf(buf, sizeof (buf), "%s:///module/%s",
3595255Sstephh scheme, mod_name);
3605255Sstephh name = strdup(buf);
3615255Sstephh }
3625255Sstephh }
3635255Sstephh return (name);
3645255Sstephh }
3655255Sstephh
3665255Sstephh static int
set_priority(char * s)3675255Sstephh set_priority(char *s)
3685255Sstephh {
3695255Sstephh int rt = 0;
3705255Sstephh
3715255Sstephh if (s) {
3725255Sstephh if (strcmp(s, "Minor") == 0)
3735255Sstephh rt = 1;
3745255Sstephh else if (strcmp(s, "Major") == 0)
3755255Sstephh rt = 10;
3765255Sstephh else if (strcmp(s, "Critical") == 0)
3775255Sstephh rt = 100;
3785255Sstephh }
3795255Sstephh return (rt);
3805255Sstephh }
3815255Sstephh
3825255Sstephh static int
cmp_priority(char * s1,char * s2,uint64_t t1,uint64_t t2,uint8_t p1,uint8_t p2)3835255Sstephh cmp_priority(char *s1, char *s2, uint64_t t1, uint64_t t2, uint8_t p1,
3845255Sstephh uint8_t p2)
3855255Sstephh {
3865255Sstephh int r1, r2;
3875255Sstephh int rt;
3885255Sstephh
3895255Sstephh r1 = set_priority(s1);
3905255Sstephh r2 = set_priority(s2);
3915255Sstephh rt = r1 - r2;
3925255Sstephh if (rt == 0) {
3935255Sstephh if (t1 > t2)
3945255Sstephh rt = 1;
3955255Sstephh else if (t1 < t2)
3965255Sstephh rt = -1;
3975255Sstephh else
3985255Sstephh rt = p1 - p2;
3995255Sstephh }
4005255Sstephh return (rt);
4015255Sstephh }
4025255Sstephh
4035255Sstephh /*
4045255Sstephh * merge two lists into one, by comparing enties in new and moving into list if
4055255Sstephh * name is not there or free off memory for names which are already there
4065255Sstephh * add_pct indicates if pct is the sum or highest pct
4075255Sstephh */
4085255Sstephh static name_list_t *
merge_name_list(name_list_t ** list,name_list_t * new,int add_pct)4095255Sstephh merge_name_list(name_list_t **list, name_list_t *new, int add_pct)
4105255Sstephh {
4115255Sstephh name_list_t *lp, *np, *sp, *rt = NULL;
4125255Sstephh int max_pct;
4135255Sstephh
4145255Sstephh rt = *list;
4155255Sstephh np = new;
4165255Sstephh while (np) {
4175255Sstephh lp = *list;
4185255Sstephh while (lp) {
4195255Sstephh if (strcmp(lp->name, np->name) == 0)
4205255Sstephh break;
4215255Sstephh lp = lp->next;
4225255Sstephh if (lp == *list)
4235255Sstephh lp = NULL;
4245255Sstephh }
4255255Sstephh if (np->next == new)
4265255Sstephh sp = NULL;
4275255Sstephh else
4285255Sstephh sp = np->next;
4295255Sstephh if (lp) {
4305255Sstephh lp->status |= (np->status & FM_SUSPECT_FAULTY);
4315255Sstephh if (add_pct) {
4325255Sstephh lp->pct += np->pct;
4335255Sstephh lp->count += np->count;
4345255Sstephh } else if (np->pct > lp->pct) {
4355255Sstephh lp->pct = np->pct;
4365255Sstephh }
4375255Sstephh max_pct = np->max_pct;
4386002Sstephh if (np->label)
4396002Sstephh free(np->label);
4405255Sstephh free(np->name);
4415255Sstephh free(np);
4425255Sstephh np = NULL;
4435255Sstephh if (max_pct > lp->max_pct) {
4445255Sstephh lp->max_pct = max_pct;
4455255Sstephh if (lp->max_pct > lp->prev->max_pct &&
4465255Sstephh lp != *list) {
4475255Sstephh lp->prev->next = lp->next;
4485255Sstephh lp->next->prev = lp->prev;
4495255Sstephh np = lp;
4505255Sstephh }
4515255Sstephh }
4525255Sstephh }
4535255Sstephh if (np) {
4545255Sstephh lp = *list;
4555255Sstephh if (lp) {
4565255Sstephh if (np->max_pct > lp->max_pct) {
4575255Sstephh np->next = lp;
4585255Sstephh np->prev = lp->prev;
4595255Sstephh lp->prev->next = np;
4605255Sstephh lp->prev = np;
4615255Sstephh *list = np;
4625255Sstephh rt = np;
4635255Sstephh } else {
4645255Sstephh lp = lp->next;
4655255Sstephh while (lp != *list &&
4665255Sstephh np->max_pct < lp->max_pct) {
4675255Sstephh lp = lp->next;
4685255Sstephh }
4695255Sstephh np->next = lp;
4705255Sstephh np->prev = lp->prev;
4715255Sstephh lp->prev->next = np;
4725255Sstephh lp->prev = np;
4735255Sstephh }
4745255Sstephh } else {
4755255Sstephh *list = np;
4765255Sstephh np->next = np;
4775255Sstephh np->prev = np;
4785255Sstephh rt = np;
4795255Sstephh }
4805255Sstephh }
4815255Sstephh np = sp;
4825255Sstephh }
4835255Sstephh return (rt);
4845255Sstephh }
4855255Sstephh
4865255Sstephh static name_list_t *
alloc_name_list(char * name,uint8_t pct)4875255Sstephh alloc_name_list(char *name, uint8_t pct)
4885255Sstephh {
4895255Sstephh name_list_t *nlp;
4905255Sstephh
4915255Sstephh nlp = malloc(sizeof (*nlp));
4925255Sstephh nlp->name = strdup(name);
4935255Sstephh nlp->pct = pct;
4945255Sstephh nlp->max_pct = pct;
4955255Sstephh nlp->count = 1;
4965255Sstephh nlp->next = nlp;
4975255Sstephh nlp->prev = nlp;
4985255Sstephh nlp->status = 0;
4996002Sstephh nlp->label = NULL;
5005255Sstephh return (nlp);
5015255Sstephh }
5025255Sstephh
5035255Sstephh static status_record_t *
new_record_init(uurec_t * uurec_p,char * msgid,name_list_t * class,name_list_t * fru,name_list_t * asru,name_list_t * resource,name_list_t * serial,boolean_t not_suppressed,hostid_t * hostid,boolean_t injected)5045255Sstephh new_record_init(uurec_t *uurec_p, char *msgid, name_list_t *class,
5055255Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource,
5069501SRobert.Johnston@Sun.COM name_list_t *serial, boolean_t not_suppressed,
50710928SStephen.Hanson@Sun.COM hostid_t *hostid, boolean_t injected)
5085255Sstephh {
5095255Sstephh status_record_t *status_rec_p;
5105255Sstephh
5115255Sstephh status_rec_p = (status_record_t *)malloc(sizeof (status_record_t));
5125255Sstephh status_rec_p->nrecs = 1;
5135255Sstephh status_rec_p->host = hostid;
5145255Sstephh status_rec_p->uurec = uurec_p;
5155255Sstephh uurec_p->next = NULL;
5165255Sstephh uurec_p->prev = NULL;
5175255Sstephh uurec_p->asru = asru;
5189501SRobert.Johnston@Sun.COM if ((status_rec_p->severity = fmd_msg_getitem_id(fmadm_msghdl, NULL,
5199501SRobert.Johnston@Sun.COM msgid, FMD_MSG_ITEM_SEVERITY)) == NULL)
5209501SRobert.Johnston@Sun.COM status_rec_p->severity = strdup("unknown");
5215255Sstephh status_rec_p->class = class;
5225255Sstephh status_rec_p->fru = fru;
5235255Sstephh status_rec_p->asru = asru;
5245255Sstephh status_rec_p->resource = resource;
5255255Sstephh status_rec_p->serial = serial;
5265255Sstephh status_rec_p->msgid = strdup(msgid);
5275255Sstephh status_rec_p->not_suppressed = not_suppressed;
52810928SStephen.Hanson@Sun.COM status_rec_p->injected = injected;
5295255Sstephh return (status_rec_p);
5305255Sstephh }
5315255Sstephh
5325255Sstephh /*
5335255Sstephh * add record to given list maintaining order higher priority first.
5345255Sstephh */
5355255Sstephh static void
add_rec_list(status_record_t * status_rec_p,sr_list_t ** list_pp)5365255Sstephh add_rec_list(status_record_t *status_rec_p, sr_list_t **list_pp)
5375255Sstephh {
5385255Sstephh sr_list_t *tp, *np, *sp;
5395255Sstephh int order;
5405255Sstephh uint64_t sec;
5415255Sstephh
5425255Sstephh np = malloc(sizeof (sr_list_t));
5435255Sstephh np->status_record = status_rec_p;
5445255Sstephh sec = status_rec_p->uurec->sec;
5455255Sstephh if ((sp = *list_pp) == NULL) {
5465255Sstephh *list_pp = np;
5475255Sstephh np->next = np;
5485255Sstephh np->prev = np;
5495255Sstephh } else {
5505255Sstephh /* insert new record in front of lower priority */
5515255Sstephh tp = sp;
5525255Sstephh order = cmp_priority(status_rec_p->severity,
5535255Sstephh sp->status_record->severity, sec,
5545255Sstephh tp->status_record->uurec->sec, 0, 0);
5555255Sstephh if (order > 0) {
5565255Sstephh *list_pp = np;
5575255Sstephh } else {
5585255Sstephh tp = sp->next;
5595255Sstephh while (tp != sp &&
5605255Sstephh cmp_priority(status_rec_p->severity,
5615255Sstephh tp->status_record->severity, sec,
5625255Sstephh tp->status_record->uurec->sec, 0, 0)) {
5635255Sstephh tp = tp->next;
5645255Sstephh }
5655255Sstephh }
5665255Sstephh np->next = tp;
5675255Sstephh np->prev = tp->prev;
5685255Sstephh tp->prev->next = np;
5695255Sstephh tp->prev = np;
5705255Sstephh }
5715255Sstephh }
5725255Sstephh
5735255Sstephh static void
add_resource(status_record_t * status_rec_p,resource_list_t ** rp,resource_list_t * np)5745255Sstephh add_resource(status_record_t *status_rec_p, resource_list_t **rp,
5755255Sstephh resource_list_t *np)
5765255Sstephh {
5775255Sstephh int order;
5785255Sstephh uint64_t sec;
5795255Sstephh resource_list_t *sp, *tp;
5805255Sstephh status_record_t *srp;
5815255Sstephh char *severity = status_rec_p->severity;
5825255Sstephh
5835255Sstephh add_rec_list(status_rec_p, &np->status_rec_list);
5845255Sstephh if ((sp = *rp) == NULL) {
5855255Sstephh np->next = np;
5865255Sstephh np->prev = np;
5875255Sstephh *rp = np;
5885255Sstephh } else {
5895255Sstephh /*
5905255Sstephh * insert new record in front of lower priority
5915255Sstephh */
5925255Sstephh tp = sp->next;
5935255Sstephh srp = sp->status_rec_list->status_record;
5945255Sstephh sec = status_rec_p->uurec->sec;
5955255Sstephh order = cmp_priority(severity, srp->severity, sec,
5965255Sstephh srp->uurec->sec, np->max_pct, sp->max_pct);
5975255Sstephh if (order > 0) {
5985255Sstephh *rp = np;
5995255Sstephh } else {
6005255Sstephh srp = tp->status_rec_list->status_record;
6015255Sstephh while (tp != sp &&
6025255Sstephh cmp_priority(severity, srp->severity, sec,
6035255Sstephh srp->uurec->sec, np->max_pct, sp->max_pct) < 0) {
6045255Sstephh tp = tp->next;
6055255Sstephh srp = tp->status_rec_list->status_record;
6065255Sstephh }
6075255Sstephh }
6085255Sstephh np->next = tp;
6095255Sstephh np->prev = tp->prev;
6105255Sstephh tp->prev->next = np;
6115255Sstephh tp->prev = np;
6125255Sstephh }
6135255Sstephh }
6145255Sstephh
6155255Sstephh static void
add_resource_list(status_record_t * status_rec_p,name_list_t * fp,resource_list_t ** rpp)6165255Sstephh add_resource_list(status_record_t *status_rec_p, name_list_t *fp,
6175255Sstephh resource_list_t **rpp)
6185255Sstephh {
6195255Sstephh int order;
6205255Sstephh resource_list_t *np, *end;
6215255Sstephh status_record_t *srp;
6225255Sstephh
6235255Sstephh np = *rpp;
6245255Sstephh end = np;
6255255Sstephh while (np) {
6265255Sstephh if (strcmp(fp->name, np->resource) == 0) {
6275255Sstephh np->not_suppressed |= status_rec_p->not_suppressed;
62810928SStephen.Hanson@Sun.COM np->injected |= status_rec_p->injected;
6295255Sstephh srp = np->status_rec_list->status_record;
6305255Sstephh order = cmp_priority(status_rec_p->severity,
6315255Sstephh srp->severity, status_rec_p->uurec->sec,
6325255Sstephh srp->uurec->sec, fp->max_pct, np->max_pct);
6335255Sstephh if (order > 0 && np != end) {
6345255Sstephh /*
6355255Sstephh * remove from list and add again using
6365255Sstephh * new priority
6375255Sstephh */
6385255Sstephh np->prev->next = np->next;
6395255Sstephh np->next->prev = np->prev;
6405255Sstephh add_resource(status_rec_p,
6415255Sstephh rpp, np);
6425255Sstephh } else {
6435255Sstephh add_rec_list(status_rec_p,
6445255Sstephh &np->status_rec_list);
6455255Sstephh }
6465255Sstephh break;
6475255Sstephh }
6485255Sstephh np = np->next;
6495255Sstephh if (np == end) {
6505255Sstephh np = NULL;
6515255Sstephh break;
6525255Sstephh }
6535255Sstephh }
6545255Sstephh if (np == NULL) {
6555255Sstephh np = malloc(sizeof (resource_list_t));
6565255Sstephh np->resource = fp->name;
6575255Sstephh np->not_suppressed = status_rec_p->not_suppressed;
65810928SStephen.Hanson@Sun.COM np->injected = status_rec_p->injected;
6595255Sstephh np->status_rec_list = NULL;
6605255Sstephh np->max_pct = fp->max_pct;
6615255Sstephh add_resource(status_rec_p, rpp, np);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate
6655255Sstephh static void
add_list(status_record_t * status_rec_p,name_list_t * listp,resource_list_t ** glistp)6665255Sstephh add_list(status_record_t *status_rec_p, name_list_t *listp,
6675255Sstephh resource_list_t **glistp)
6685255Sstephh {
6695255Sstephh name_list_t *fp, *end;
6705255Sstephh
6715255Sstephh fp = listp;
6725255Sstephh end = fp;
6735255Sstephh while (fp) {
6745255Sstephh add_resource_list(status_rec_p, fp, glistp);
6755255Sstephh fp = fp->next;
6765255Sstephh if (fp == end)
6775255Sstephh break;
6785255Sstephh }
6795255Sstephh }
6805255Sstephh
6815255Sstephh /*
6825255Sstephh * add record to rec, fru and asru lists.
6835255Sstephh */
6845255Sstephh static void
catalog_new_record(uurec_t * uurec_p,char * msgid,name_list_t * class,name_list_t * fru,name_list_t * asru,name_list_t * resource,name_list_t * serial,boolean_t not_suppressed,hostid_t * hostid,boolean_t injected,boolean_t dummy_fru)6855255Sstephh catalog_new_record(uurec_t *uurec_p, char *msgid, name_list_t *class,
6865255Sstephh name_list_t *fru, name_list_t *asru, name_list_t *resource,
6879501SRobert.Johnston@Sun.COM name_list_t *serial, boolean_t not_suppressed,
68811416SStephen.Hanson@Sun.COM hostid_t *hostid, boolean_t injected, boolean_t dummy_fru)
6895255Sstephh {
6905255Sstephh status_record_t *status_rec_p;
6915255Sstephh
6925255Sstephh status_rec_p = new_record_init(uurec_p, msgid, class, fru, asru,
69310928SStephen.Hanson@Sun.COM resource, serial, not_suppressed, hostid, injected);
6945255Sstephh add_rec_list(status_rec_p, &status_rec_list);
69511416SStephen.Hanson@Sun.COM if (status_rec_p->fru && !dummy_fru)
6965255Sstephh add_list(status_rec_p, status_rec_p->fru, &status_fru_list);
6975255Sstephh if (status_rec_p->asru)
6985255Sstephh add_list(status_rec_p, status_rec_p->asru, &status_asru_list);
6995255Sstephh }
7005255Sstephh
7015255Sstephh static void
get_serial_no(nvlist_t * nvl,name_list_t ** serial_p,uint8_t pct)7025255Sstephh get_serial_no(nvlist_t *nvl, name_list_t **serial_p, uint8_t pct)
7035255Sstephh {
7045255Sstephh char *name;
7055255Sstephh char *serial = NULL;
7065255Sstephh char **lserial = NULL;
7075255Sstephh uint64_t serint;
7085255Sstephh name_list_t *nlp;
7095255Sstephh int j;
7105255Sstephh uint_t nelem;
7115255Sstephh char buf[64];
7120Sstevel@tonic-gate
7135255Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) == 0) {
7145255Sstephh if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
7155255Sstephh if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID,
7165255Sstephh &serint) == 0) {
7175255Sstephh (void) snprintf(buf, sizeof (buf), "%llX",
7185255Sstephh serint);
7195255Sstephh nlp = alloc_name_list(buf, pct);
7205255Sstephh (void) merge_name_list(serial_p, nlp, 1);
7215255Sstephh }
7225255Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
7235255Sstephh if (nvlist_lookup_string_array(nvl,
7245255Sstephh FM_FMRI_MEM_SERIAL_ID, &lserial, &nelem) == 0) {
7255255Sstephh nlp = alloc_name_list(lserial[0], pct);
7265255Sstephh for (j = 1; j < nelem; j++) {
7275255Sstephh name_list_t *n1lp;
7285255Sstephh n1lp = alloc_name_list(lserial[j], pct);
7295255Sstephh (void) merge_name_list(&nlp, n1lp, 1);
7305255Sstephh }
7315255Sstephh (void) merge_name_list(serial_p, nlp, 1);
7325255Sstephh }
7335255Sstephh } else if (strcmp(name, FM_FMRI_SCHEME_HC) == 0) {
7345255Sstephh if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID,
7355255Sstephh &serial) == 0) {
7365255Sstephh nlp = alloc_name_list(serial, pct);
7375255Sstephh (void) merge_name_list(serial_p, nlp, 1);
7385255Sstephh }
7395255Sstephh }
7405255Sstephh }
7415255Sstephh }
7425255Sstephh
7435255Sstephh static void
extract_record_info(nvlist_t * nvl,name_list_t ** class_p,name_list_t ** fru_p,name_list_t ** serial_p,name_list_t ** resource_p,name_list_t ** asru_p,boolean_t * dummy_fru,uint8_t status)7445255Sstephh extract_record_info(nvlist_t *nvl, name_list_t **class_p,
74511416SStephen.Hanson@Sun.COM name_list_t **fru_p, name_list_t **serial_p, name_list_t **resource_p,
74611416SStephen.Hanson@Sun.COM name_list_t **asru_p, boolean_t *dummy_fru, uint8_t status)
7470Sstevel@tonic-gate {
7485255Sstephh nvlist_t *lfru, *lasru, *rsrc;
7495255Sstephh name_list_t *nlp;
7505255Sstephh char *name;
7515255Sstephh uint8_t lpct = 0;
7525255Sstephh char *lclass = NULL;
7536002Sstephh char *label;
7545255Sstephh
7555255Sstephh (void) nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &lpct);
7565255Sstephh if (nvlist_lookup_string(nvl, FM_CLASS, &lclass) == 0) {
7575255Sstephh nlp = alloc_name_list(lclass, lpct);
7585255Sstephh (void) merge_name_list(class_p, nlp, 1);
7595255Sstephh }
7605255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &lfru) == 0) {
7615255Sstephh name = get_nvl2str_topo(lfru);
7625255Sstephh if (name != NULL) {
7635255Sstephh nlp = alloc_name_list(name, lpct);
7647275Sstephh nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
7657275Sstephh FM_SUSPECT_DEGRADED);
7665255Sstephh free(name);
7676002Sstephh if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
7686002Sstephh &label) == 0)
7696002Sstephh nlp->label = strdup(label);
7705255Sstephh (void) merge_name_list(fru_p, nlp, 1);
7715255Sstephh }
7725255Sstephh get_serial_no(lfru, serial_p, lpct);
77310656SStephen.Hanson@Sun.COM } else if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) != 0) {
77410656SStephen.Hanson@Sun.COM /*
77510656SStephen.Hanson@Sun.COM * No FRU or resource. But we want to display the repair status
77610656SStephen.Hanson@Sun.COM * somehow, so create a dummy FRU field.
77710656SStephen.Hanson@Sun.COM */
77811416SStephen.Hanson@Sun.COM *dummy_fru = 1;
77910656SStephen.Hanson@Sun.COM nlp = alloc_name_list(dgettext("FMD", "None"), lpct);
78010656SStephen.Hanson@Sun.COM nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
78110656SStephen.Hanson@Sun.COM FM_SUSPECT_DEGRADED);
78210656SStephen.Hanson@Sun.COM (void) merge_name_list(fru_p, nlp, 1);
7835255Sstephh }
7845255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &lasru) == 0) {
7855255Sstephh name = get_nvl2str_topo(lasru);
7865255Sstephh if (name != NULL) {
7875255Sstephh nlp = alloc_name_list(name, lpct);
7887275Sstephh nlp->status = status & ~(FM_SUSPECT_NOT_PRESENT |
7897275Sstephh FM_SUSPECT_REPAIRED | FM_SUSPECT_REPLACED |
7907275Sstephh FM_SUSPECT_ACQUITTED);
7915255Sstephh free(name);
7925255Sstephh (void) merge_name_list(asru_p, nlp, 1);
7935255Sstephh }
7945255Sstephh get_serial_no(lasru, serial_p, lpct);
7955255Sstephh }
7965255Sstephh if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
7975255Sstephh name = get_nvl2str_topo(rsrc);
7985255Sstephh if (name != NULL) {
7995255Sstephh nlp = alloc_name_list(name, lpct);
8006228Sstephh nlp->status = status;
8015255Sstephh free(name);
8028245SStephen.Hanson@Sun.COM if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
8038245SStephen.Hanson@Sun.COM &label) == 0)
8048245SStephen.Hanson@Sun.COM nlp->label = strdup(label);
8055255Sstephh (void) merge_name_list(resource_p, nlp, 1);
8065255Sstephh }
8075255Sstephh }
8085255Sstephh }
8095255Sstephh
8105255Sstephh static void
add_fault_record_to_catalog(nvlist_t * nvl,uint64_t sec,char * uuid)8119501SRobert.Johnston@Sun.COM add_fault_record_to_catalog(nvlist_t *nvl, uint64_t sec, char *uuid)
8125255Sstephh {
8135255Sstephh char *msgid = "-";
8145255Sstephh uint_t i, size = 0;
8155255Sstephh name_list_t *class = NULL, *resource = NULL;
8165255Sstephh name_list_t *asru = NULL, *fru = NULL, *serial = NULL;
8175255Sstephh nvlist_t **nva;
8185255Sstephh uint8_t *ba;
8195255Sstephh uurec_t *uurec_p;
8205255Sstephh hostid_t *host;
8215255Sstephh boolean_t not_suppressed = 1;
8225255Sstephh boolean_t any_present = 0;
82310928SStephen.Hanson@Sun.COM boolean_t injected = 0;
82411416SStephen.Hanson@Sun.COM boolean_t dummy_fru = 0;
8255255Sstephh
8265255Sstephh (void) nvlist_lookup_string(nvl, FM_SUSPECT_DIAG_CODE, &msgid);
8275255Sstephh (void) nvlist_lookup_uint32(nvl, FM_SUSPECT_FAULT_SZ, &size);
8285255Sstephh (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE,
8295255Sstephh ¬_suppressed);
83010928SStephen.Hanson@Sun.COM (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_INJECTED, &injected);
8315255Sstephh
8325255Sstephh if (size != 0) {
8335255Sstephh (void) nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST,
8345255Sstephh &nva, &size);
8355255Sstephh (void) nvlist_lookup_uint8_array(nvl, FM_SUSPECT_FAULT_STATUS,
8365255Sstephh &ba, &size);
8375255Sstephh for (i = 0; i < size; i++) {
8385255Sstephh extract_record_info(nva[i], &class, &fru, &serial,
83911416SStephen.Hanson@Sun.COM &resource, &asru, &dummy_fru, ba[i]);
8405255Sstephh if (!(ba[i] & FM_SUSPECT_NOT_PRESENT) &&
8415255Sstephh (ba[i] & FM_SUSPECT_FAULTY))
8425255Sstephh any_present = 1;
8435255Sstephh }
8445255Sstephh /*
8455255Sstephh * also suppress if no resources present
8465255Sstephh */
8475255Sstephh if (any_present == 0)
8485255Sstephh not_suppressed = 0;
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate
8515255Sstephh uurec_p = (uurec_t *)malloc(sizeof (uurec_t));
8525255Sstephh uurec_p->uuid = strdup(uuid);
8535255Sstephh uurec_p->sec = sec;
8545255Sstephh uurec_p->ari_uuid_list = NULL;
85510234SRobert.Johnston@Sun.COM uurec_p->event = NULL;
85610234SRobert.Johnston@Sun.COM (void) nvlist_dup(nvl, &uurec_p->event, 0);
8575255Sstephh host = find_hostid(nvl);
85810656SStephen.Hanson@Sun.COM catalog_new_record(uurec_p, msgid, class, fru, asru,
85911416SStephen.Hanson@Sun.COM resource, serial, not_suppressed, host, injected, dummy_fru);
8605255Sstephh }
8615255Sstephh
8625255Sstephh static void
update_asru_state_in_catalog(const char * uuid,const char * ari_uuid)8635255Sstephh update_asru_state_in_catalog(const char *uuid, const char *ari_uuid)
8645255Sstephh {
8655255Sstephh sr_list_t *srp;
8665255Sstephh uurec_t *uurp;
8675255Sstephh ari_list_t *ari_list;
8685255Sstephh
8695255Sstephh srp = status_rec_list;
8705255Sstephh if (srp) {
8715255Sstephh for (;;) {
8725255Sstephh uurp = srp->status_record->uurec;
8735255Sstephh while (uurp) {
8745255Sstephh if (strcmp(uuid, uurp->uuid) == 0) {
8755255Sstephh ari_list = (ari_list_t *)
8765255Sstephh malloc(sizeof (ari_list_t));
8775255Sstephh ari_list->ari_uuid = strdup(ari_uuid);
8785255Sstephh ari_list->next = uurp->ari_uuid_list;
8795255Sstephh uurp->ari_uuid_list = ari_list;
8805255Sstephh return;
8815255Sstephh }
8825255Sstephh uurp = uurp->next;
8835255Sstephh }
8845255Sstephh if (srp->next == status_rec_list)
8855255Sstephh break;
8865255Sstephh srp = srp->next;
8875255Sstephh }
8885255Sstephh }
8895255Sstephh }
8905255Sstephh
8915255Sstephh static void
print_line(char * label,char * buf)8925255Sstephh print_line(char *label, char *buf)
8935255Sstephh {
8945255Sstephh char *cp, *ep, *wp;
8955255Sstephh char c;
8965255Sstephh int i;
8975255Sstephh int lsz;
8985255Sstephh char *padding;
8995255Sstephh
9005255Sstephh lsz = strlen(label);
9015255Sstephh padding = malloc(lsz + 1);
9025255Sstephh for (i = 0; i < lsz; i++)
9035255Sstephh padding[i] = ' ';
9045255Sstephh padding[i] = 0;
9055255Sstephh cp = buf;
9065255Sstephh ep = buf;
9075255Sstephh c = *ep;
9085255Sstephh (void) printf("\n");
9095255Sstephh while (c) {
9105255Sstephh i = lsz;
9115255Sstephh wp = NULL;
9125255Sstephh while ((c = *ep) != NULL && (wp == NULL || i < 80)) {
9135255Sstephh if (c == ' ')
9145255Sstephh wp = ep;
9155255Sstephh else if (c == '\n') {
9165255Sstephh i = 0;
9175255Sstephh *ep = 0;
9185255Sstephh do {
9195255Sstephh ep++;
9205255Sstephh } while ((c = *ep) != NULL && c == ' ');
9215255Sstephh break;
9225255Sstephh }
9235255Sstephh ep++;
9245255Sstephh i++;
9255255Sstephh }
9265255Sstephh if (i >= 80 && wp) {
9275255Sstephh *wp = 0;
9285255Sstephh ep = wp + 1;
9295255Sstephh c = *ep;
9305255Sstephh }
9315255Sstephh (void) printf("%s%s\n", label, cp);
9325255Sstephh cp = ep;
9335255Sstephh label = padding;
9345255Sstephh }
9355255Sstephh free(padding);
9365255Sstephh }
9375255Sstephh
9385255Sstephh static void
print_dict_info_line(nvlist_t * e,fmd_msg_item_t what,const char * linehdr)93910234SRobert.Johnston@Sun.COM print_dict_info_line(nvlist_t *e, fmd_msg_item_t what, const char *linehdr)
9405255Sstephh {
94110234SRobert.Johnston@Sun.COM char *cp = fmd_msg_getitem_nv(fmadm_msghdl, NULL, e, what);
9425255Sstephh
9435255Sstephh if (cp) {
9449501SRobert.Johnston@Sun.COM print_line(dgettext("FMD", linehdr), cp);
9459501SRobert.Johnston@Sun.COM free(cp);
9465255Sstephh }
9479501SRobert.Johnston@Sun.COM }
9489501SRobert.Johnston@Sun.COM
9499501SRobert.Johnston@Sun.COM static void
print_dict_info(nvlist_t * nvl)95010234SRobert.Johnston@Sun.COM print_dict_info(nvlist_t *nvl)
9519501SRobert.Johnston@Sun.COM {
95210234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_DESC, "Description : ");
95310234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_RESPONSE, "Response : ");
95410234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_IMPACT, "Impact : ");
95510234SRobert.Johnston@Sun.COM print_dict_info_line(nvl, FMD_MSG_ITEM_ACTION, "Action : ");
9565255Sstephh }
9575255Sstephh
9585255Sstephh static void
print_name(name_list_t * list,char * padding,int * np,int pct,int full)959*12618SStephen.Hanson@Sun.COM print_name(name_list_t *list, char *padding, int *np, int pct, int full)
9605255Sstephh {
961*12618SStephen.Hanson@Sun.COM char *name;
9625255Sstephh
9635255Sstephh name = list->name;
9648245SStephen.Hanson@Sun.COM if (list->label) {
9658245SStephen.Hanson@Sun.COM (void) printf("%s \"%s\" (%s)", padding, list->label, name);
9665255Sstephh *np += 1;
9675255Sstephh } else {
9685255Sstephh (void) printf("%s %s", padding, name);
9695255Sstephh *np += 1;
9705255Sstephh }
9715255Sstephh if (list->pct && pct > 0 && pct < 100) {
9725255Sstephh if (list->count > 1) {
9735255Sstephh if (full) {
9745255Sstephh (void) printf(" %d @ %s %d%%\n", list->count,
9755255Sstephh dgettext("FMD", "max"),
9765255Sstephh list->max_pct);
9775255Sstephh } else {
9785255Sstephh (void) printf(" %s %d%%\n",
9795255Sstephh dgettext("FMD", "max"),
9805255Sstephh list->max_pct);
9815255Sstephh }
9825255Sstephh } else {
9835255Sstephh (void) printf(" %d%%\n", list->pct);
9845255Sstephh }
9855255Sstephh } else {
9865255Sstephh (void) printf("\n");
9875255Sstephh }
9885255Sstephh }
9895255Sstephh
9905255Sstephh static void
print_asru_status(int status,char * label)9915255Sstephh print_asru_status(int status, char *label)
9925255Sstephh {
9935255Sstephh char *msg = NULL;
9945255Sstephh
9955255Sstephh switch (status) {
9965255Sstephh case 0:
9975255Sstephh msg = dgettext("FMD", "ok and in service");
9985255Sstephh break;
9997275Sstephh case FM_SUSPECT_DEGRADED:
10007275Sstephh msg = dgettext("FMD", "service degraded, "
10017275Sstephh "but associated components no longer faulty");
10027275Sstephh break;
10037275Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
10047275Sstephh msg = dgettext("FMD", "faulted but still "
10057275Sstephh "providing degraded service");
10067275Sstephh break;
10075255Sstephh case FM_SUSPECT_FAULTY:
10087275Sstephh msg = dgettext("FMD", "faulted but still in service");
10095255Sstephh break;
10105255Sstephh case FM_SUSPECT_UNUSABLE:
10117275Sstephh msg = dgettext("FMD", "out of service, "
10127275Sstephh "but associated components no longer faulty");
10135255Sstephh break;
10145255Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
10155255Sstephh msg = dgettext("FMD", "faulted and taken out of service");
10165255Sstephh break;
10175255Sstephh default:
10185255Sstephh break;
10195255Sstephh }
10205255Sstephh if (msg) {
10215255Sstephh (void) printf("%s %s\n", label, msg);
10225255Sstephh }
10235255Sstephh }
10245255Sstephh
10255255Sstephh static void
print_fru_status(int status,char * label)10266228Sstephh print_fru_status(int status, char *label)
10276228Sstephh {
10286228Sstephh char *msg = NULL;
10296228Sstephh
10306228Sstephh if (status & FM_SUSPECT_NOT_PRESENT)
10316228Sstephh msg = dgettext("FMD", "not present");
10326228Sstephh else if (status & FM_SUSPECT_FAULTY)
10336228Sstephh msg = dgettext("FMD", "faulty");
10347275Sstephh else if (status & FM_SUSPECT_REPLACED)
10357275Sstephh msg = dgettext("FMD", "replaced");
10367275Sstephh else if (status & FM_SUSPECT_REPAIRED)
10377275Sstephh msg = dgettext("FMD", "repair attempted");
10387275Sstephh else if (status & FM_SUSPECT_ACQUITTED)
10397275Sstephh msg = dgettext("FMD", "acquitted");
10406228Sstephh else
10417275Sstephh msg = dgettext("FMD", "removed");
10426228Sstephh (void) printf("%s %s\n", label, msg);
10436228Sstephh }
10446228Sstephh
10456228Sstephh static void
print_rsrc_status(int status,char * label)10469120SStephen.Hanson@Sun.COM print_rsrc_status(int status, char *label)
10479120SStephen.Hanson@Sun.COM {
10489120SStephen.Hanson@Sun.COM char *msg = "";
10499120SStephen.Hanson@Sun.COM
10509120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_NOT_PRESENT)
10519120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "not present");
10529120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_FAULTY) {
10539120SStephen.Hanson@Sun.COM if (status & FM_SUSPECT_DEGRADED)
10549120SStephen.Hanson@Sun.COM msg = dgettext("FMD",
10559120SStephen.Hanson@Sun.COM "faulted but still providing degraded service");
10569120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_UNUSABLE)
10579120SStephen.Hanson@Sun.COM msg = dgettext("FMD",
10589120SStephen.Hanson@Sun.COM "faulted and taken out of service");
10599120SStephen.Hanson@Sun.COM else
10609120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "faulted but still in service");
10619120SStephen.Hanson@Sun.COM } else if (status & FM_SUSPECT_REPLACED)
10629120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "replaced");
10639120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_REPAIRED)
10649120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "repair attempted");
10659120SStephen.Hanson@Sun.COM else if (status & FM_SUSPECT_ACQUITTED)
10669120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "acquitted");
10679120SStephen.Hanson@Sun.COM else
10689120SStephen.Hanson@Sun.COM msg = dgettext("FMD", "removed");
10699120SStephen.Hanson@Sun.COM (void) printf("%s %s\n", label, msg);
10709120SStephen.Hanson@Sun.COM }
10719120SStephen.Hanson@Sun.COM
10729120SStephen.Hanson@Sun.COM static void
print_name_list(name_list_t * list,char * label,int limit,int pct,void (func1)(int,char *),int full)1073*12618SStephen.Hanson@Sun.COM print_name_list(name_list_t *list, char *label,
10745255Sstephh int limit, int pct, void (func1)(int, char *), int full)
10755255Sstephh {
1076*12618SStephen.Hanson@Sun.COM char *name;
10775255Sstephh char *padding;
10785255Sstephh int i, j, l, n;
10795255Sstephh name_list_t *end = list;
10805255Sstephh
10815255Sstephh l = strlen(label);
10825255Sstephh padding = malloc(l + 1);
10835255Sstephh for (i = 0; i < l; i++)
10845255Sstephh padding[i] = ' ';
10855255Sstephh padding[l] = 0;
10865255Sstephh (void) printf("%s", label);
10875255Sstephh name = list->name;
10888245SStephen.Hanson@Sun.COM if (list->label)
10896002Sstephh (void) printf(" \"%s\" (%s)", list->label, name);
1090*12618SStephen.Hanson@Sun.COM else
10918245SStephen.Hanson@Sun.COM (void) printf(" %s", name);
10925255Sstephh if (list->pct && pct > 0 && pct < 100) {
10935255Sstephh if (list->count > 1) {
10945255Sstephh if (full) {
10955255Sstephh (void) printf(" %d @ %s %d%%\n", list->count,
10965255Sstephh dgettext("FMD", "max"), list->max_pct);
10975255Sstephh } else {
10985255Sstephh (void) printf(" %s %d%%\n",
10995255Sstephh dgettext("FMD", "max"), list->max_pct);
11005255Sstephh }
11015255Sstephh } else {
11025255Sstephh (void) printf(" %d%%\n", list->pct);
11035255Sstephh }
11045255Sstephh } else {
11055255Sstephh (void) printf("\n");
11065255Sstephh }
11075255Sstephh if (func1)
11085255Sstephh func1(list->status, padding);
11095255Sstephh n = 1;
11105255Sstephh j = 0;
11115255Sstephh while ((list = list->next) != end) {
11125255Sstephh if (limit == 0 || n < limit) {
1113*12618SStephen.Hanson@Sun.COM print_name(list, padding, &n, pct, full);
11145255Sstephh if (func1)
11155255Sstephh func1(list->status, padding);
11165255Sstephh } else
11175255Sstephh j++;
11185255Sstephh }
11195255Sstephh if (j == 1) {
1120*12618SStephen.Hanson@Sun.COM print_name(list->prev, padding, &n, pct, full);
11215255Sstephh } else if (j > 1) {
11225255Sstephh (void) printf("%s... %d %s\n", padding, j,
11235255Sstephh dgettext("FMD", "more entries suppressed,"
11245255Sstephh " use -v option for full list"));
11255255Sstephh }
11265255Sstephh free(padding);
11275255Sstephh }
11285255Sstephh
11295255Sstephh static int
asru_same_status(name_list_t * list)11305255Sstephh asru_same_status(name_list_t *list)
11315255Sstephh {
11325255Sstephh name_list_t *end = list;
11335255Sstephh int status = list->status;
11345255Sstephh
11355255Sstephh while ((list = list->next) != end) {
11365255Sstephh if (status == -1) {
11375255Sstephh status = list->status;
11385255Sstephh continue;
11395255Sstephh }
11405255Sstephh if (list->status != -1 && status != list->status) {
11415255Sstephh status = -1;
11425255Sstephh break;
11435255Sstephh }
11445255Sstephh }
11455255Sstephh return (status);
11465255Sstephh }
11475255Sstephh
11485255Sstephh static int
serial_in_fru(name_list_t * fru,name_list_t * serial)11495255Sstephh serial_in_fru(name_list_t *fru, name_list_t *serial)
11505255Sstephh {
11515255Sstephh name_list_t *sp = serial;
11525255Sstephh name_list_t *fp;
11535255Sstephh int nserial = 0;
11545255Sstephh int found = 0;
11555255Sstephh char buf[128];
11565255Sstephh
11575255Sstephh while (sp) {
11585255Sstephh fp = fru;
11595255Sstephh nserial++;
11605255Sstephh (void) snprintf(buf, sizeof (buf), "serial=%s", sp->name);
11615255Sstephh buf[sizeof (buf) - 1] = 0;
11625255Sstephh while (fp) {
11635255Sstephh if (strstr(fp->name, buf) != NULL) {
11645255Sstephh found++;
11655255Sstephh break;
11665255Sstephh }
11675255Sstephh fp = fp->next;
11685255Sstephh if (fp == fru)
11695255Sstephh break;
11705255Sstephh }
11715255Sstephh sp = sp->next;
11725255Sstephh if (sp == serial)
11735255Sstephh break;
11745255Sstephh }
11755255Sstephh return (found == nserial ? 1 : 0);
11765255Sstephh }
11775255Sstephh
11785255Sstephh static void
print_sup_record(status_record_t * srp,int opt_i,int full)11795255Sstephh print_sup_record(status_record_t *srp, int opt_i, int full)
11805255Sstephh {
11815255Sstephh char buf[32];
11825255Sstephh uurec_t *uurp = srp->uurec;
11835255Sstephh int n, j, k, max;
11845255Sstephh int status;
11855255Sstephh ari_list_t *ari_list;
11865255Sstephh
11875255Sstephh n = 0;
11885255Sstephh max = max_fault;
11895255Sstephh if (max < 0) {
11905255Sstephh max = 0;
11915255Sstephh }
11925255Sstephh j = max / 2;
11935255Sstephh max -= j;
11945255Sstephh k = srp->nrecs - max;
11955255Sstephh while ((uurp = uurp->next) != NULL) {
11965255Sstephh if (full || n < j || n >= k || max_fault == 0 ||
11975255Sstephh srp->nrecs == max_fault+1) {
11985255Sstephh if (opt_i) {
11995255Sstephh ari_list = uurp->ari_uuid_list;
12005255Sstephh while (ari_list) {
12015255Sstephh (void) printf("%-15s %s\n",
12025255Sstephh format_date(buf, sizeof (buf),
12035255Sstephh uurp->sec), ari_list->ari_uuid);
12045255Sstephh ari_list = ari_list->next;
12055255Sstephh }
12065255Sstephh } else {
12075255Sstephh (void) printf("%-15s %s\n",
12085255Sstephh format_date(buf, sizeof (buf), uurp->sec),
12095255Sstephh uurp->uuid);
12105255Sstephh }
12115255Sstephh } else if (n == j)
12125255Sstephh (void) printf("... %d %s\n", srp->nrecs - max_fault,
12135255Sstephh dgettext("FMD", "more entries suppressed"));
12145255Sstephh n++;
12155255Sstephh }
12165255Sstephh (void) printf("\n");
12179120SStephen.Hanson@Sun.COM (void) printf("%s %s", dgettext("FMD", "Host :"),
12189120SStephen.Hanson@Sun.COM srp->host->server);
12199120SStephen.Hanson@Sun.COM if (srp->host->domain)
12209120SStephen.Hanson@Sun.COM (void) printf("\t%s %s", dgettext("FMD", "Domain :"),
12219120SStephen.Hanson@Sun.COM srp->host->domain);
12229120SStephen.Hanson@Sun.COM (void) printf("\n%s %s", dgettext("FMD", "Platform :"),
12239120SStephen.Hanson@Sun.COM srp->host->platform);
122410462SSean.Ye@Sun.COM (void) printf("\t%s %s", dgettext("FMD", "Chassis_id :"),
12259120SStephen.Hanson@Sun.COM srp->host->chassis ? srp->host->chassis : "");
122610462SSean.Ye@Sun.COM (void) printf("\n%s %s\n\n", dgettext("FMD", "Product_sn :"),
122710462SSean.Ye@Sun.COM srp->host->product_sn? srp->host->product_sn : "");
12285255Sstephh if (srp->class)
12295255Sstephh print_name_list(srp->class,
1230*12618SStephen.Hanson@Sun.COM dgettext("FMD", "Fault class :"), 0, srp->class->pct,
12315255Sstephh NULL, full);
12325255Sstephh if (srp->asru) {
12335255Sstephh status = asru_same_status(srp->asru);
12345255Sstephh if (status != -1) {
12355255Sstephh print_name_list(srp->asru,
1236*12618SStephen.Hanson@Sun.COM dgettext("FMD", "Affects :"),
12375255Sstephh full ? 0 : max_display, 0, NULL, full);
12385255Sstephh print_asru_status(status, " ");
12395255Sstephh } else
12405255Sstephh print_name_list(srp->asru,
1241*12618SStephen.Hanson@Sun.COM dgettext("FMD", "Affects :"),
12425255Sstephh full ? 0 : max_display, 0, print_asru_status, full);
12435255Sstephh }
12449120SStephen.Hanson@Sun.COM if (full || srp->fru == NULL || srp->asru == NULL) {
12455255Sstephh if (srp->resource) {
124610656SStephen.Hanson@Sun.COM status = asru_same_status(srp->resource);
124710656SStephen.Hanson@Sun.COM if (status != -1) {
124810656SStephen.Hanson@Sun.COM print_name_list(srp->resource,
1249*12618SStephen.Hanson@Sun.COM dgettext("FMD", "Problem in :"),
125010656SStephen.Hanson@Sun.COM full ? 0 : max_display, 0, NULL, full);
125110656SStephen.Hanson@Sun.COM print_rsrc_status(status, " ");
125210656SStephen.Hanson@Sun.COM } else
125310656SStephen.Hanson@Sun.COM print_name_list(srp->resource,
125410656SStephen.Hanson@Sun.COM dgettext("FMD", "Problem in :"),
1255*12618SStephen.Hanson@Sun.COM full ? 0 : max_display, 0,
125610656SStephen.Hanson@Sun.COM print_rsrc_status, full);
12575255Sstephh }
12585255Sstephh }
12595255Sstephh if (srp->fru) {
12606228Sstephh status = asru_same_status(srp->fru);
12616228Sstephh if (status != -1) {
12626228Sstephh print_name_list(srp->fru, dgettext("FMD",
1263*12618SStephen.Hanson@Sun.COM "FRU :"), 0,
12646228Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
12656228Sstephh NULL, full);
12666228Sstephh print_fru_status(status, " ");
12676228Sstephh } else
12686228Sstephh print_name_list(srp->fru, dgettext("FMD",
1269*12618SStephen.Hanson@Sun.COM "FRU :"), 0,
12706228Sstephh srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
12716228Sstephh print_fru_status, full);
12725255Sstephh }
12735255Sstephh if (srp->serial && !serial_in_fru(srp->fru, srp->serial) &&
12745255Sstephh !serial_in_fru(srp->asru, srp->serial)) {
12755255Sstephh print_name_list(srp->serial, dgettext("FMD", "Serial ID. :"),
1276*12618SStephen.Hanson@Sun.COM 0, 0, NULL, full);
12775255Sstephh }
127810234SRobert.Johnston@Sun.COM print_dict_info(srp->uurec->event);
12795255Sstephh (void) printf("\n");
12805255Sstephh }
12815255Sstephh
12825255Sstephh static void
print_status_record(status_record_t * srp,int summary,int opt_i,int full)12835255Sstephh print_status_record(status_record_t *srp, int summary, int opt_i, int full)
12845255Sstephh {
12855255Sstephh char buf[32];
12865255Sstephh uurec_t *uurp = srp->uurec;
12875255Sstephh static int header = 0;
12885255Sstephh char *head;
12895255Sstephh ari_list_t *ari_list;
12905255Sstephh
12915255Sstephh if (!summary || !header) {
12925255Sstephh if (opt_i) {
12935255Sstephh head = "--------------- "
12945255Sstephh "------------------------------------ "
12955255Sstephh "-------------- ---------\n"
12965255Sstephh "TIME CACHE-ID"
12975255Sstephh " MSG-ID"
12985255Sstephh " SEVERITY\n--------------- "
12995255Sstephh "------------------------------------ "
13005255Sstephh " -------------- ---------";
13015255Sstephh } else {
13025255Sstephh head = "--------------- "
13035255Sstephh "------------------------------------ "
13045255Sstephh "-------------- ---------\n"
13055255Sstephh "TIME EVENT-ID"
13065255Sstephh " MSG-ID"
13075255Sstephh " SEVERITY\n--------------- "
13085255Sstephh "------------------------------------ "
13095255Sstephh " -------------- ---------";
13105255Sstephh }
13115255Sstephh (void) printf("%s\n", dgettext("FMD", head));
13125255Sstephh header = 1;
13135255Sstephh }
13145255Sstephh if (opt_i) {
13155255Sstephh ari_list = uurp->ari_uuid_list;
13165255Sstephh while (ari_list) {
131710928SStephen.Hanson@Sun.COM (void) printf("%-15s %-37s %-14s %-9s %s\n",
13185255Sstephh format_date(buf, sizeof (buf), uurp->sec),
131910928SStephen.Hanson@Sun.COM ari_list->ari_uuid, srp->msgid, srp->severity,
132010928SStephen.Hanson@Sun.COM srp->injected ? dgettext("FMD", "injected") : "");
13215255Sstephh ari_list = ari_list->next;
13225255Sstephh }
13235255Sstephh } else {
132410928SStephen.Hanson@Sun.COM (void) printf("%-15s %-37s %-14s %-9s %s\n",
13255255Sstephh format_date(buf, sizeof (buf), uurp->sec),
132610928SStephen.Hanson@Sun.COM uurp->uuid, srp->msgid, srp->severity,
132710928SStephen.Hanson@Sun.COM srp->injected ? dgettext("FMD", "injected") : "");
13285255Sstephh }
13295255Sstephh
13305255Sstephh if (!summary)
13315255Sstephh print_sup_record(srp, opt_i, full);
13325255Sstephh }
13335255Sstephh
13345255Sstephh static void
print_catalog(int summary,int opt_a,int full,int opt_i,int page_feed)13355255Sstephh print_catalog(int summary, int opt_a, int full, int opt_i, int page_feed)
13365255Sstephh {
13375255Sstephh status_record_t *srp;
13385255Sstephh sr_list_t *slp;
13395255Sstephh
13405255Sstephh slp = status_rec_list;
13415255Sstephh if (slp) {
13425255Sstephh for (;;) {
13435255Sstephh srp = slp->status_record;
13445255Sstephh if (opt_a || srp->not_suppressed) {
13455255Sstephh if (page_feed)
13465255Sstephh (void) printf("\f\n");
13475255Sstephh print_status_record(srp, summary, opt_i, full);
13485255Sstephh }
13495255Sstephh if (slp->next == status_rec_list)
13505255Sstephh break;
13515255Sstephh slp = slp->next;
13525255Sstephh }
13535255Sstephh }
13545255Sstephh }
13555255Sstephh
13565255Sstephh static name_list_t *
find_fru(status_record_t * srp,char * resource)13575255Sstephh find_fru(status_record_t *srp, char *resource)
13585255Sstephh {
13595255Sstephh name_list_t *rt = NULL;
13605255Sstephh name_list_t *fru = srp->fru;
13615255Sstephh
13625255Sstephh while (fru) {
13635255Sstephh if (strcmp(resource, fru->name) == 0) {
13645255Sstephh rt = fru;
13655255Sstephh break;
13665255Sstephh }
13675255Sstephh fru = fru->next;
13685255Sstephh if (fru == srp->fru)
13695255Sstephh break;
13705255Sstephh }
13715255Sstephh return (rt);
13725255Sstephh }
13735255Sstephh
13745255Sstephh static void
print_fru_line(name_list_t * fru,char * uuid)13755255Sstephh print_fru_line(name_list_t *fru, char *uuid)
13765255Sstephh {
13775255Sstephh if (fru->pct == 100) {
13785255Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count,
13795255Sstephh dgettext("FMD", "suspects in this FRU total certainty"),
13805255Sstephh 100);
13815255Sstephh } else {
13825255Sstephh (void) printf("%s %d %s %d%%\n", uuid, fru->count,
13835255Sstephh dgettext("FMD", "suspects in this FRU max certainty"),
13845255Sstephh fru->max_pct);
13855255Sstephh }
13865255Sstephh }
13875255Sstephh
13885255Sstephh static void
print_fru(int summary,int opt_a,int opt_i,int page_feed)13895255Sstephh print_fru(int summary, int opt_a, int opt_i, int page_feed)
13905255Sstephh {
13915255Sstephh resource_list_t *tp = status_fru_list;
13925255Sstephh status_record_t *srp;
13935255Sstephh sr_list_t *slp, *end;
13945255Sstephh uurec_t *uurp;
13955255Sstephh name_list_t *fru;
13966228Sstephh int status;
13975255Sstephh ari_list_t *ari_list;
13985255Sstephh
13995255Sstephh while (tp) {
14005255Sstephh if (opt_a || tp->not_suppressed) {
14015255Sstephh if (page_feed)
14025255Sstephh (void) printf("\f\n");
14035255Sstephh if (!summary)
14045255Sstephh (void) printf("-----------------------------"
14055255Sstephh "---------------------------------------"
14065255Sstephh "----------\n");
14076002Sstephh slp = tp->status_rec_list;
14086002Sstephh end = slp;
14096002Sstephh do {
14106002Sstephh srp = slp->status_record;
141111416SStephen.Hanson@Sun.COM if (!srp->not_suppressed) {
141211416SStephen.Hanson@Sun.COM slp = slp->next;
141311416SStephen.Hanson@Sun.COM continue;
141411416SStephen.Hanson@Sun.COM }
14156002Sstephh fru = find_fru(srp, tp->resource);
14166002Sstephh if (fru) {
14176002Sstephh if (fru->label)
14186228Sstephh (void) printf("\"%s\" (%s) ",
14196002Sstephh fru->label, fru->name);
1420*12618SStephen.Hanson@Sun.COM else
14216228Sstephh (void) printf("%s ",
14226002Sstephh fru->name);
14236002Sstephh break;
14246002Sstephh }
14256002Sstephh slp = slp->next;
14266002Sstephh } while (slp != end);
14276002Sstephh
14285255Sstephh slp = tp->status_rec_list;
14295255Sstephh end = slp;
14306228Sstephh status = 0;
14316228Sstephh do {
14326228Sstephh srp = slp->status_record;
143311416SStephen.Hanson@Sun.COM if (!srp->not_suppressed) {
143411416SStephen.Hanson@Sun.COM slp = slp->next;
143511416SStephen.Hanson@Sun.COM continue;
143611416SStephen.Hanson@Sun.COM }
14376228Sstephh fru = srp->fru;
14386228Sstephh while (fru) {
14396228Sstephh if (strcmp(tp->resource,
14406228Sstephh fru->name) == 0)
14416228Sstephh status |= fru->status;
14426228Sstephh fru = fru->next;
14436228Sstephh if (fru == srp->fru)
14446228Sstephh break;
14456228Sstephh }
14466228Sstephh slp = slp->next;
14476228Sstephh } while (slp != end);
14486228Sstephh if (status & FM_SUSPECT_NOT_PRESENT)
144910928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "not present"));
14506228Sstephh else if (status & FM_SUSPECT_FAULTY)
145110928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "faulty"));
14527275Sstephh else if (status & FM_SUSPECT_REPLACED)
145310928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "replaced"));
14547275Sstephh else if (status & FM_SUSPECT_REPAIRED)
14557275Sstephh (void) printf(dgettext("FMD",
145610928SStephen.Hanson@Sun.COM "repair attempted"));
14577275Sstephh else if (status & FM_SUSPECT_ACQUITTED)
145810928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "acquitted"));
14596228Sstephh else
146010928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "removed"));
146110928SStephen.Hanson@Sun.COM
146210928SStephen.Hanson@Sun.COM if (tp->injected)
146310928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", " injected\n"));
146410928SStephen.Hanson@Sun.COM else
146510928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "\n"));
14666228Sstephh
14676228Sstephh slp = tp->status_rec_list;
14686228Sstephh end = slp;
14695255Sstephh do {
14705255Sstephh srp = slp->status_record;
147111416SStephen.Hanson@Sun.COM if (!srp->not_suppressed) {
147211416SStephen.Hanson@Sun.COM slp = slp->next;
147311416SStephen.Hanson@Sun.COM continue;
147411416SStephen.Hanson@Sun.COM }
14755255Sstephh uurp = srp->uurec;
14765255Sstephh fru = find_fru(srp, tp->resource);
14775255Sstephh if (fru) {
14785255Sstephh if (opt_i) {
14795255Sstephh ari_list = uurp->ari_uuid_list;
14805255Sstephh while (ari_list) {
14815255Sstephh print_fru_line(fru,
14825255Sstephh ari_list->ari_uuid);
14835255Sstephh ari_list =
14845255Sstephh ari_list->next;
14855255Sstephh }
14865255Sstephh } else {
14875255Sstephh print_fru_line(fru, uurp->uuid);
14885255Sstephh }
14895255Sstephh }
14905255Sstephh slp = slp->next;
14915255Sstephh } while (slp != end);
14925255Sstephh if (!summary) {
14935255Sstephh slp = tp->status_rec_list;
14945255Sstephh end = slp;
14955255Sstephh do {
149611416SStephen.Hanson@Sun.COM srp = slp->status_record;
149711416SStephen.Hanson@Sun.COM if (!srp->not_suppressed) {
149811416SStephen.Hanson@Sun.COM slp = slp->next;
149911416SStephen.Hanson@Sun.COM continue;
150011416SStephen.Hanson@Sun.COM }
150111416SStephen.Hanson@Sun.COM if (srp->serial &&
150211416SStephen.Hanson@Sun.COM !serial_in_fru(srp->fru,
150311416SStephen.Hanson@Sun.COM srp->serial)) {
150411416SStephen.Hanson@Sun.COM print_name_list(srp->serial,
150511416SStephen.Hanson@Sun.COM dgettext("FMD",
150611416SStephen.Hanson@Sun.COM "Serial ID. :"),
1507*12618SStephen.Hanson@Sun.COM 0, 0, NULL, 1);
150811416SStephen.Hanson@Sun.COM break;
15095255Sstephh }
15105255Sstephh slp = slp->next;
15115255Sstephh } while (slp != end);
15125255Sstephh }
15135255Sstephh }
15145255Sstephh tp = tp->next;
15155255Sstephh if (tp == status_fru_list)
15165255Sstephh break;
15175255Sstephh }
15185255Sstephh }
15195255Sstephh
15205255Sstephh static void
print_asru(int opt_a)15215255Sstephh print_asru(int opt_a)
15225255Sstephh {
15235255Sstephh resource_list_t *tp = status_asru_list;
15245255Sstephh status_record_t *srp;
15255255Sstephh sr_list_t *slp, *end;
15265255Sstephh char *msg;
15275255Sstephh int status;
15285255Sstephh name_list_t *asru;
15295255Sstephh
15305255Sstephh while (tp) {
15315255Sstephh if (opt_a || tp->not_suppressed) {
15325255Sstephh status = 0;
15335255Sstephh slp = tp->status_rec_list;
15345255Sstephh end = slp;
15355255Sstephh do {
15365255Sstephh srp = slp->status_record;
153711416SStephen.Hanson@Sun.COM if (!srp->not_suppressed) {
153811416SStephen.Hanson@Sun.COM slp = slp->next;
153911416SStephen.Hanson@Sun.COM continue;
154011416SStephen.Hanson@Sun.COM }
15415255Sstephh asru = srp->asru;
15425255Sstephh while (asru) {
15435255Sstephh if (strcmp(tp->resource,
15445255Sstephh asru->name) == 0)
15455255Sstephh status |= asru->status;
15465255Sstephh asru = asru->next;
15475255Sstephh if (asru == srp->asru)
15485255Sstephh break;
15495255Sstephh }
15505255Sstephh slp = slp->next;
15515255Sstephh } while (slp != end);
15525255Sstephh switch (status) {
15535255Sstephh case 0:
15545255Sstephh msg = dgettext("FMD", "ok");
15555255Sstephh break;
15567275Sstephh case FM_SUSPECT_DEGRADED:
15577275Sstephh msg = dgettext("FMD", "degraded");
15587275Sstephh break;
15597275Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
15607275Sstephh msg = dgettext("FMD", "degraded");
15617275Sstephh break;
15625255Sstephh case FM_SUSPECT_FAULTY:
15635255Sstephh msg = dgettext("FMD", "degraded");
15645255Sstephh break;
15655255Sstephh case FM_SUSPECT_UNUSABLE:
15665255Sstephh msg = dgettext("FMD", "unknown");
15675255Sstephh break;
15685255Sstephh case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
15695255Sstephh msg = dgettext("FMD", "faulted");
15705255Sstephh break;
15715255Sstephh default:
15725255Sstephh msg = "";
15735255Sstephh break;
15745255Sstephh }
157510928SStephen.Hanson@Sun.COM (void) printf("%-69s %s", tp->resource, msg);
157610928SStephen.Hanson@Sun.COM if (tp->injected)
157710928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", " injected\n"));
157810928SStephen.Hanson@Sun.COM else
157910928SStephen.Hanson@Sun.COM (void) printf(dgettext("FMD", "\n"));
15805255Sstephh }
15815255Sstephh tp = tp->next;
15825255Sstephh if (tp == status_asru_list)
15835255Sstephh break;
15845255Sstephh }
15855255Sstephh }
15865255Sstephh
15875255Sstephh static int
uuid_in_list(char * uuid,uurec_select_t * uurecp)15885255Sstephh uuid_in_list(char *uuid, uurec_select_t *uurecp)
15895255Sstephh {
15905255Sstephh while (uurecp) {
15915255Sstephh if (strcmp(uuid, uurecp->uuid) == 0)
15925255Sstephh return (1);
15935255Sstephh uurecp = uurecp->next;
15945255Sstephh }
15950Sstevel@tonic-gate return (0);
15960Sstevel@tonic-gate }
15970Sstevel@tonic-gate
15985255Sstephh static int
dfault_rec(const fmd_adm_caseinfo_t * acp,void * arg)15995255Sstephh dfault_rec(const fmd_adm_caseinfo_t *acp, void *arg)
16005255Sstephh {
16015255Sstephh int64_t *diag_time;
16025255Sstephh uint_t nelem;
16035255Sstephh int rt = 0;
16045255Sstephh char *uuid = "-";
16055255Sstephh uurec_select_t *uurecp = (uurec_select_t *)arg;
16065255Sstephh
16075255Sstephh if (nvlist_lookup_int64_array(acp->aci_event, FM_SUSPECT_DIAG_TIME,
16085255Sstephh &diag_time, &nelem) == 0 && nelem >= 2) {
16095255Sstephh (void) nvlist_lookup_string(acp->aci_event, FM_SUSPECT_UUID,
16105255Sstephh &uuid);
16115255Sstephh if (uurecp == NULL || uuid_in_list(uuid, uurecp))
16125255Sstephh add_fault_record_to_catalog(acp->aci_event, *diag_time,
16139501SRobert.Johnston@Sun.COM uuid);
16145255Sstephh } else {
16155255Sstephh rt = -1;
16165255Sstephh }
16175255Sstephh return (rt);
16185255Sstephh }
16195255Sstephh
16200Sstevel@tonic-gate /*ARGSUSED*/
16210Sstevel@tonic-gate static int
dstatus_rec(const fmd_adm_rsrcinfo_t * ari,void * unused)16225255Sstephh dstatus_rec(const fmd_adm_rsrcinfo_t *ari, void *unused)
16230Sstevel@tonic-gate {
16245255Sstephh update_asru_state_in_catalog(ari->ari_case, ari->ari_uuid);
16250Sstevel@tonic-gate return (0);
16260Sstevel@tonic-gate }
16270Sstevel@tonic-gate
16285255Sstephh static int
get_cases_from_fmd(fmd_adm_t * adm,uurec_select_t * uurecp,int opt_i)16295255Sstephh get_cases_from_fmd(fmd_adm_t *adm, uurec_select_t *uurecp, int opt_i)
16305255Sstephh {
16315255Sstephh int rt = FMADM_EXIT_SUCCESS;
16325255Sstephh
16335255Sstephh /*
163410234SRobert.Johnston@Sun.COM * These calls may fail with Protocol error if message payload is
163510234SRobert.Johnston@Sun.COM * too big
16365255Sstephh */
16375255Sstephh if (fmd_adm_case_iter(adm, NULL, dfault_rec, uurecp) != 0)
16385255Sstephh die("failed to get case list from fmd");
16395255Sstephh if (opt_i && fmd_adm_rsrc_iter(adm, 1, dstatus_rec, NULL) != 0)
16405255Sstephh die("failed to get case status from fmd");
16415255Sstephh return (rt);
16425255Sstephh }
16435255Sstephh
16445255Sstephh /*
16455255Sstephh * fmadm faulty command
16465255Sstephh *
16475255Sstephh * -a show hidden fault records
16485255Sstephh * -f show faulty fru's
16495255Sstephh * -g force grouping of similar faults on the same fru
16505255Sstephh * -n number of fault records to display
16515255Sstephh * -p pipe output through pager
16525255Sstephh * -r show faulty asru's
16535255Sstephh * -s print summary of first fault
16545255Sstephh * -u print listed uuid's only
16555255Sstephh * -v full output
16565255Sstephh */
16575255Sstephh
16580Sstevel@tonic-gate int
cmd_faulty(fmd_adm_t * adm,int argc,char * argv[])16590Sstevel@tonic-gate cmd_faulty(fmd_adm_t *adm, int argc, char *argv[])
16600Sstevel@tonic-gate {
16615255Sstephh int opt_a = 0, opt_v = 0, opt_p = 0, opt_s = 0, opt_r = 0, opt_f = 0;
16625255Sstephh int opt_i = 0;
16635255Sstephh char *pager;
16645255Sstephh FILE *fp;
16655255Sstephh int rt, c, stat;
16665255Sstephh uurec_select_t *tp;
16675255Sstephh uurec_select_t *uurecp = NULL;
16680Sstevel@tonic-gate
16695255Sstephh while ((c = getopt(argc, argv, "afgin:prsu:v")) != EOF) {
16700Sstevel@tonic-gate switch (c) {
16710Sstevel@tonic-gate case 'a':
16720Sstevel@tonic-gate opt_a++;
16730Sstevel@tonic-gate break;
16745255Sstephh case 'f':
16755255Sstephh opt_f++;
16765255Sstephh break;
16775255Sstephh case 'g':
16785255Sstephh opt_g++;
16795255Sstephh break;
16800Sstevel@tonic-gate case 'i':
16815255Sstephh opt_i++;
16825255Sstephh break;
16835255Sstephh case 'n':
16845255Sstephh max_fault = atoi(optarg);
16855255Sstephh break;
16865255Sstephh case 'p':
16875255Sstephh opt_p++;
16885255Sstephh break;
16895255Sstephh case 'r':
16905255Sstephh opt_r++;
16915255Sstephh break;
16925255Sstephh case 's':
16935255Sstephh opt_s++;
16945255Sstephh break;
16955255Sstephh case 'u':
16965255Sstephh tp = (uurec_select_t *)malloc(sizeof (uurec_select_t));
16975255Sstephh tp->uuid = optarg;
16985255Sstephh tp->next = uurecp;
16995255Sstephh uurecp = tp;
17005255Sstephh opt_a = 1;
17015255Sstephh break;
17025255Sstephh case 'v':
17035255Sstephh opt_v++;
17040Sstevel@tonic-gate break;
17050Sstevel@tonic-gate default:
17060Sstevel@tonic-gate return (FMADM_EXIT_USAGE);
17070Sstevel@tonic-gate }
17080Sstevel@tonic-gate }
17090Sstevel@tonic-gate if (optind < argc)
17100Sstevel@tonic-gate return (FMADM_EXIT_USAGE);
17110Sstevel@tonic-gate
17129501SRobert.Johnston@Sun.COM if ((fmadm_msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) == NULL)
17139501SRobert.Johnston@Sun.COM return (FMADM_EXIT_ERROR);
17145255Sstephh rt = get_cases_from_fmd(adm, uurecp, opt_i);
17155255Sstephh if (opt_p) {
17165255Sstephh if ((pager = getenv("PAGER")) == NULL)
17175255Sstephh pager = "/usr/bin/more";
17185255Sstephh fp = popen(pager, "w");
17195255Sstephh if (fp == NULL) {
17205255Sstephh rt = FMADM_EXIT_ERROR;
17215255Sstephh opt_p = 0;
17225255Sstephh } else {
172311050SRobert.Johnston@Sun.COM (void) dup2(fileno(fp), 1);
17245255Sstephh setbuf(stdout, NULL);
17255255Sstephh (void) fclose(fp);
17265255Sstephh }
17275255Sstephh }
17285255Sstephh max_display = max_fault;
17295255Sstephh if (opt_f)
17305255Sstephh print_fru(opt_s, opt_a, opt_i, opt_p && !opt_s);
17315255Sstephh if (opt_r)
17325255Sstephh print_asru(opt_a);
17335255Sstephh if (opt_f == 0 && opt_r == 0)
17345255Sstephh print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s);
17359501SRobert.Johnston@Sun.COM fmd_msg_fini(fmadm_msghdl);
1736*12618SStephen.Hanson@Sun.COM if (topo_handle)
1737*12618SStephen.Hanson@Sun.COM topo_close(topo_handle);
17385255Sstephh if (opt_p) {
17395255Sstephh (void) fclose(stdout);
17405255Sstephh (void) wait(&stat);
17415255Sstephh }
17425255Sstephh return (rt);
17430Sstevel@tonic-gate }
17440Sstevel@tonic-gate
17450Sstevel@tonic-gate int
cmd_flush(fmd_adm_t * adm,int argc,char * argv[])17460Sstevel@tonic-gate cmd_flush(fmd_adm_t *adm, int argc, char *argv[])
17470Sstevel@tonic-gate {
17480Sstevel@tonic-gate int i, status = FMADM_EXIT_SUCCESS;
17490Sstevel@tonic-gate
17500Sstevel@tonic-gate if (argc < 2 || (i = getopt(argc, argv, "")) != EOF)
17510Sstevel@tonic-gate return (FMADM_EXIT_USAGE);
17520Sstevel@tonic-gate
17530Sstevel@tonic-gate for (i = 1; i < argc; i++) {
17540Sstevel@tonic-gate if (fmd_adm_rsrc_flush(adm, argv[i]) != 0) {
17550Sstevel@tonic-gate warn("failed to flush %s", argv[i]);
17560Sstevel@tonic-gate status = FMADM_EXIT_ERROR;
17570Sstevel@tonic-gate } else
17580Sstevel@tonic-gate note("flushed resource history for %s\n", argv[i]);
17590Sstevel@tonic-gate }
17600Sstevel@tonic-gate
17610Sstevel@tonic-gate return (status);
17620Sstevel@tonic-gate }
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate int
cmd_repair(fmd_adm_t * adm,int argc,char * argv[])17650Sstevel@tonic-gate cmd_repair(fmd_adm_t *adm, int argc, char *argv[])
17660Sstevel@tonic-gate {
17670Sstevel@tonic-gate int err;
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate if (getopt(argc, argv, "") != EOF)
17700Sstevel@tonic-gate return (FMADM_EXIT_USAGE);
17710Sstevel@tonic-gate
17720Sstevel@tonic-gate if (argc - optind != 1)
17730Sstevel@tonic-gate return (FMADM_EXIT_USAGE);
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate /*
17767275Sstephh * argument could be a uuid, an fmri (asru, fru or resource)
17776228Sstephh * or a label. Try uuid first, If that fails try the others.
17780Sstevel@tonic-gate */
17796228Sstephh err = fmd_adm_case_repair(adm, argv[optind]);
17806228Sstephh if (err != 0)
17817275Sstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]);
17820Sstevel@tonic-gate
17830Sstevel@tonic-gate if (err != 0)
17840Sstevel@tonic-gate die("failed to record repair to %s", argv[optind]);
17850Sstevel@tonic-gate
17860Sstevel@tonic-gate note("recorded repair to %s\n", argv[optind]);
17870Sstevel@tonic-gate return (FMADM_EXIT_SUCCESS);
17880Sstevel@tonic-gate }
17897275Sstephh
17907275Sstephh int
cmd_repaired(fmd_adm_t * adm,int argc,char * argv[])17917275Sstephh cmd_repaired(fmd_adm_t *adm, int argc, char *argv[])
17927275Sstephh {
17937275Sstephh int err;
17947275Sstephh
17957275Sstephh if (getopt(argc, argv, "") != EOF)
17967275Sstephh return (FMADM_EXIT_USAGE);
17977275Sstephh
17987275Sstephh if (argc - optind != 1)
17997275Sstephh return (FMADM_EXIT_USAGE);
18007275Sstephh
18017275Sstephh /*
18027275Sstephh * argument could be an fmri (asru, fru or resource) or a label.
18037275Sstephh */
18047275Sstephh err = fmd_adm_rsrc_repaired(adm, argv[optind]);
18057275Sstephh if (err != 0)
18067275Sstephh die("failed to record repair to %s", argv[optind]);
18077275Sstephh
18087275Sstephh note("recorded repair to of %s\n", argv[optind]);
18097275Sstephh return (FMADM_EXIT_SUCCESS);
18107275Sstephh }
18117275Sstephh
18127275Sstephh int
cmd_replaced(fmd_adm_t * adm,int argc,char * argv[])18137275Sstephh cmd_replaced(fmd_adm_t *adm, int argc, char *argv[])
18147275Sstephh {
18157275Sstephh int err;
18167275Sstephh
18177275Sstephh if (getopt(argc, argv, "") != EOF)
18187275Sstephh return (FMADM_EXIT_USAGE);
18197275Sstephh
18207275Sstephh if (argc - optind != 1)
18217275Sstephh return (FMADM_EXIT_USAGE);
18227275Sstephh
18237275Sstephh /*
18247275Sstephh * argument could be an fmri (asru, fru or resource) or a label.
18257275Sstephh */
18267275Sstephh err = fmd_adm_rsrc_replaced(adm, argv[optind]);
18277275Sstephh if (err != 0)
18287275Sstephh die("failed to record replacement of %s", argv[optind]);
18297275Sstephh
18307275Sstephh note("recorded replacement of %s\n", argv[optind]);
18317275Sstephh return (FMADM_EXIT_SUCCESS);
18327275Sstephh }
18337275Sstephh
18347275Sstephh int
cmd_acquit(fmd_adm_t * adm,int argc,char * argv[])18357275Sstephh cmd_acquit(fmd_adm_t *adm, int argc, char *argv[])
18367275Sstephh {
18377275Sstephh int err;
18387275Sstephh
18397275Sstephh if (getopt(argc, argv, "") != EOF)
18407275Sstephh return (FMADM_EXIT_USAGE);
18417275Sstephh
18427275Sstephh if (argc - optind != 1 && argc - optind != 2)
18437275Sstephh return (FMADM_EXIT_USAGE);
18447275Sstephh
18457275Sstephh /*
18467275Sstephh * argument could be a uuid, an fmri (asru, fru or resource)
18477275Sstephh * or a label. Or it could be a uuid and an fmri or label.
18487275Sstephh */
18497275Sstephh if (argc - optind == 2) {
18507275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], argv[optind + 1]);
18517275Sstephh if (err != 0)
18527275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind + 1],
18537275Sstephh argv[optind]);
18547275Sstephh } else {
18557275Sstephh err = fmd_adm_case_acquit(adm, argv[optind]);
18567275Sstephh if (err != 0)
18577275Sstephh err = fmd_adm_rsrc_acquit(adm, argv[optind], "");
18587275Sstephh }
18597275Sstephh
18607275Sstephh if (err != 0)
18617275Sstephh die("failed to record acquital of %s", argv[optind]);
18627275Sstephh
18637275Sstephh note("recorded acquital of %s\n", argv[optind]);
18647275Sstephh return (FMADM_EXIT_SUCCESS);
18657275Sstephh }
1866