1cddcb259SBaptiste Daroussin /*-
28ad16e55SEdward Tomasz Napierala * Copyright (c) 2019 Klara Inc.
3cddcb259SBaptiste Daroussin * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
48729f5ecSAllan Jude * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
58729f5ecSAllan Jude * Copyright (c) 2000 by Matthew Jacob
6cddcb259SBaptiste Daroussin * All rights reserved.
7cddcb259SBaptiste Daroussin *
88ad16e55SEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala
98ad16e55SEdward Tomasz Napierala * under sponsorship from Klara Inc.
108ad16e55SEdward Tomasz Napierala *
11cddcb259SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
12cddcb259SBaptiste Daroussin * modification, are permitted provided that the following conditions
13cddcb259SBaptiste Daroussin * are met:
14cddcb259SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright
15cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer
16cddcb259SBaptiste Daroussin * in this position and unchanged.
17cddcb259SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright
18cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
19cddcb259SBaptiste Daroussin * documentation and/or other materials provided with the distribution.
20cddcb259SBaptiste Daroussin *
21cddcb259SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
22cddcb259SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23cddcb259SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24cddcb259SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
25cddcb259SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26cddcb259SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27cddcb259SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28cddcb259SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29cddcb259SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30cddcb259SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31cddcb259SBaptiste Daroussin */
32cddcb259SBaptiste Daroussin
33cddcb259SBaptiste Daroussin #include <sys/cdefs.h>
3420a957e3SBaptiste Daroussin #include <sys/endian.h>
35cddcb259SBaptiste Daroussin #include <sys/param.h>
368ad16e55SEdward Tomasz Napierala #include <sys/disk.h>
37cddcb259SBaptiste Daroussin #include <sys/ioctl.h>
38d7654478SBaptiste Daroussin #include <sys/types.h>
39cddcb259SBaptiste Daroussin
40cddcb259SBaptiste Daroussin #include <errno.h>
41cddcb259SBaptiste Daroussin #include <fcntl.h>
428729f5ecSAllan Jude #include <getopt.h>
43cddcb259SBaptiste Daroussin #include <glob.h>
44cddcb259SBaptiste Daroussin #include <stdbool.h>
45cddcb259SBaptiste Daroussin #include <stddef.h>
46cddcb259SBaptiste Daroussin #include <stdint.h>
47cddcb259SBaptiste Daroussin #include <stdio.h>
48cddcb259SBaptiste Daroussin #include <stdlib.h>
49cddcb259SBaptiste Daroussin #include <string.h>
50cddcb259SBaptiste Daroussin #include <unistd.h>
51d25c1ff6SBaptiste Daroussin #include <libxo/xo.h>
52cddcb259SBaptiste Daroussin
53cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h>
54cddcb259SBaptiste Daroussin
558729f5ecSAllan Jude #include "eltsub.h"
568729f5ecSAllan Jude
57d25c1ff6SBaptiste Daroussin #define SESUTIL_XO_VERSION "1"
58d25c1ff6SBaptiste Daroussin
598ad16e55SEdward Tomasz Napierala #define TEMPERATURE_OFFSET 20
608ad16e55SEdward Tomasz Napierala
618ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED 0
628ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED_2 1
638ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV 2
648ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV_2 3
658ad16e55SEdward Tomasz Napierala
668729f5ecSAllan Jude static int encstatus(int argc, char **argv);
678729f5ecSAllan Jude static int fault(int argc, char **argv);
68cddcb259SBaptiste Daroussin static int locate(int argc, char **argv);
698729f5ecSAllan Jude static int objmap(int argc, char **argv);
708729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault);
718ad16e55SEdward Tomasz Napierala static int show(int argc, char **argv);
728ad16e55SEdward Tomasz Napierala static void sesutil_print(int *style, const char *fmt, ...) __printflike(2,3);
73cddcb259SBaptiste Daroussin
74cddcb259SBaptiste Daroussin static struct command {
75cddcb259SBaptiste Daroussin const char *name;
768729f5ecSAllan Jude const char *param;
77cddcb259SBaptiste Daroussin const char *desc;
78cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv);
79cddcb259SBaptiste Daroussin } cmds[] = {
808729f5ecSAllan Jude { "fault",
818729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)",
828729f5ecSAllan Jude "Change the state of the fault LED associated with a disk",
838729f5ecSAllan Jude fault },
848729f5ecSAllan Jude { "locate",
858729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)",
868729f5ecSAllan Jude "Change the state of the locate LED associated with a disk",
878729f5ecSAllan Jude locate },
888729f5ecSAllan Jude { "map", "",
898729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } ,
908ad16e55SEdward Tomasz Napierala { "show", "",
918ad16e55SEdward Tomasz Napierala "Print a human-friendly summary of the enclosure", show } ,
928729f5ecSAllan Jude { "status", "", "Print the status of the enclosure",
938729f5ecSAllan Jude encstatus },
94cddcb259SBaptiste Daroussin };
95cddcb259SBaptiste Daroussin
96cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds);
978729f5ecSAllan Jude static const char *uflag;
98cddcb259SBaptiste Daroussin
99cddcb259SBaptiste Daroussin static void
usage(const char * subcmd)100*3d1b233eSYan-Hao Wang usage(const char *subcmd)
1018729f5ecSAllan Jude {
1028729f5ecSAllan Jude int i;
1038729f5ecSAllan Jude
1048729f5ecSAllan Jude if (subcmd == NULL) {
105*3d1b233eSYan-Hao Wang xo_error("usage: %s [-u /dev/ses<N>] <command> [options]\n",
1068729f5ecSAllan Jude getprogname());
107*3d1b233eSYan-Hao Wang xo_error("Commands supported:\n");
1088729f5ecSAllan Jude }
1098729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) {
1108729f5ecSAllan Jude if (subcmd != NULL) {
1118729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) {
112*3d1b233eSYan-Hao Wang xo_error("usage: %s %s [-u /dev/ses<N>] "
1138729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd,
1148729f5ecSAllan Jude cmds[i].param, cmds[i].desc);
1158729f5ecSAllan Jude break;
1168729f5ecSAllan Jude }
1178729f5ecSAllan Jude continue;
1188729f5ecSAllan Jude }
119*3d1b233eSYan-Hao Wang xo_error(" %-12s%s\n\t\t%s\n\n", cmds[i].name,
1208729f5ecSAllan Jude cmds[i].param, cmds[i].desc);
1218729f5ecSAllan Jude }
1228729f5ecSAllan Jude
1238729f5ecSAllan Jude exit(EXIT_FAILURE);
1248729f5ecSAllan Jude }
1258729f5ecSAllan Jude
1268729f5ecSAllan Jude static void
do_led(int fd,unsigned int idx,elm_type_t type,bool onoff,bool setfault)127fe74eaabSAlexander Motin do_led(int fd, unsigned int idx, elm_type_t type, bool onoff, bool setfault)
128cddcb259SBaptiste Daroussin {
129fe74eaabSAlexander Motin int state = onoff ? 1 : 0;
130cddcb259SBaptiste Daroussin encioc_elm_status_t o;
131fe74eaabSAlexander Motin struct ses_ctrl_dev_slot *slot;
132cddcb259SBaptiste Daroussin
133cddcb259SBaptiste Daroussin o.elm_idx = idx;
134cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) {
135cddcb259SBaptiste Daroussin close(fd);
136d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
137cddcb259SBaptiste Daroussin }
1382e19fae4SAlexander Motin ses_status_to_ctrl(type, &o.cstat[0]);
139fe74eaabSAlexander Motin switch (type) {
140fe74eaabSAlexander Motin case ELMTYP_DEVICE:
141fe74eaabSAlexander Motin case ELMTYP_ARRAY_DEV:
1422e19fae4SAlexander Motin slot = (struct ses_ctrl_dev_slot *) &o.cstat[0];
143fe74eaabSAlexander Motin ses_ctrl_common_set_select(&slot->common, 1);
144fe74eaabSAlexander Motin if (setfault)
145fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_fault(slot, state);
146efab8bfdSAlexander Motin else
147fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_ident(slot, state);
148fe74eaabSAlexander Motin break;
149fe74eaabSAlexander Motin default:
150fe74eaabSAlexander Motin return;
1518729f5ecSAllan Jude }
152cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
153cddcb259SBaptiste Daroussin close(fd);
154d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT");
155cddcb259SBaptiste Daroussin }
156cddcb259SBaptiste Daroussin }
157cddcb259SBaptiste Daroussin
158cddcb259SBaptiste Daroussin static bool
disk_match(const char * devnames,const char * disk,size_t len)159cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len)
160cddcb259SBaptiste Daroussin {
1611bc54324SBaptiste Daroussin const char *dname;
162cddcb259SBaptiste Daroussin
1631bc54324SBaptiste Daroussin dname = devnames;
1641bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) {
1658729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') {
166cddcb259SBaptiste Daroussin return (true);
1678729f5ecSAllan Jude }
1681bc54324SBaptiste Daroussin dname++;
169cddcb259SBaptiste Daroussin }
1708729f5ecSAllan Jude
171cddcb259SBaptiste Daroussin return (false);
172cddcb259SBaptiste Daroussin }
173cddcb259SBaptiste Daroussin
174cddcb259SBaptiste Daroussin static int
sesled(int argc,char ** argv,bool setfault)1756af5d161SAllan Jude sesled(int argc, char **argv, bool setfault)
176cddcb259SBaptiste Daroussin {
177cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn;
178cddcb259SBaptiste Daroussin encioc_element_t *objp;
179cddcb259SBaptiste Daroussin glob_t g;
1808729f5ecSAllan Jude char *disk, *endptr;
1818729f5ecSAllan Jude size_t len, i, ndisks;
1828729f5ecSAllan Jude int fd;
1838729f5ecSAllan Jude unsigned int nobj, j, sesid;
1848729f5ecSAllan Jude bool all, isses, onoff;
185cddcb259SBaptiste Daroussin
1868729f5ecSAllan Jude isses = false;
1878729f5ecSAllan Jude all = false;
1888729f5ecSAllan Jude onoff = false;
1898729f5ecSAllan Jude
1908729f5ecSAllan Jude if (argc != 3) {
191*3d1b233eSYan-Hao Wang usage(setfault ? "fault" : "locate");
192cddcb259SBaptiste Daroussin }
193cddcb259SBaptiste Daroussin
1948729f5ecSAllan Jude disk = argv[1];
195cddcb259SBaptiste Daroussin
1968729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10);
1978729f5ecSAllan Jude if (*endptr == '\0') {
1988729f5ecSAllan Jude endptr = strrchr(uflag, '*');
19996e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') {
200d25c1ff6SBaptiste Daroussin xo_warnx("Must specifying a SES device (-u) to use a SES "
2018729f5ecSAllan Jude "id# to identify a disk");
202*3d1b233eSYan-Hao Wang usage(setfault ? "fault" : "locate");
2038729f5ecSAllan Jude }
2048729f5ecSAllan Jude isses = true;
2058729f5ecSAllan Jude }
2068729f5ecSAllan Jude
2078729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) {
2084569e7cfSBaptiste Daroussin onoff = true;
2098729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) {
2104569e7cfSBaptiste Daroussin onoff = false;
211cddcb259SBaptiste Daroussin } else {
212*3d1b233eSYan-Hao Wang usage(setfault ? "fault" : "locate");
213cddcb259SBaptiste Daroussin }
214cddcb259SBaptiste Daroussin
215cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) {
216cddcb259SBaptiste Daroussin all = true;
217cddcb259SBaptiste Daroussin }
218cddcb259SBaptiste Daroussin len = strlen(disk);
219cddcb259SBaptiste Daroussin
220cddcb259SBaptiste Daroussin /* Get the list of ses devices */
2218729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) ==
2228729f5ecSAllan Jude GLOB_NOMATCH) {
2238729f5ecSAllan Jude globfree(&g);
224d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found");
2258729f5ecSAllan Jude }
2268729f5ecSAllan Jude
2278729f5ecSAllan Jude ndisks = 0;
2288729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) {
2298729f5ecSAllan Jude /* ensure we only got numbers after ses */
2308729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
2318729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) {
2328729f5ecSAllan Jude continue;
2338729f5ecSAllan Jude }
2348729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
2358729f5ecSAllan Jude /*
2368729f5ecSAllan Jude * Don't treat non-access errors as critical if we are
2378729f5ecSAllan Jude * accessing all devices
2388729f5ecSAllan Jude */
2398729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) {
240d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device");
2418729f5ecSAllan Jude }
242d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
2438729f5ecSAllan Jude continue;
2448729f5ecSAllan Jude }
2458729f5ecSAllan Jude
2468729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
2478729f5ecSAllan Jude close(fd);
248d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
2498729f5ecSAllan Jude }
2508729f5ecSAllan Jude
2518729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t));
2528729f5ecSAllan Jude if (objp == NULL) {
2538729f5ecSAllan Jude close(fd);
254d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()");
2558729f5ecSAllan Jude }
2568729f5ecSAllan Jude
2578729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) {
258a221b104SAlan Somers free(objp);
2598729f5ecSAllan Jude close(fd);
260d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
2618729f5ecSAllan Jude }
2628729f5ecSAllan Jude
2638729f5ecSAllan Jude if (isses) {
264691a834cSAlan Somers if (sesid >= nobj) {
265a221b104SAlan Somers free(objp);
2668729f5ecSAllan Jude close(fd);
267d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE,
2688729f5ecSAllan Jude "Requested SES ID does not exist");
2698729f5ecSAllan Jude }
270fe74eaabSAlexander Motin do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault);
2718729f5ecSAllan Jude ndisks++;
272a221b104SAlan Somers free(objp);
2738729f5ecSAllan Jude close(fd);
2748729f5ecSAllan Jude break;
2758729f5ecSAllan Jude }
2768729f5ecSAllan Jude for (j = 0; j < nobj; j++) {
2779f96f106SAlan Somers const int devnames_size = 128;
2789f96f106SAlan Somers char devnames[devnames_size];
2799f96f106SAlan Somers
28024ffc649SAllan Jude if (all) {
28157dc6f5eSAlan Somers encioc_elm_status_t es;
28257dc6f5eSAlan Somers memset(&es, 0, sizeof(es));
28357dc6f5eSAlan Somers es.elm_idx = objp[j].elm_idx;
28457dc6f5eSAlan Somers if (ioctl(fd, ENCIOC_GETELMSTAT, &es) < 0) {
28557dc6f5eSAlan Somers close(fd);
28657dc6f5eSAlan Somers xo_err(EXIT_FAILURE,
28757dc6f5eSAlan Somers "ENCIOC_GETELMSTAT");
28857dc6f5eSAlan Somers }
28957dc6f5eSAlan Somers if ((es.cstat[0] & 0xf) == SES_OBJSTAT_NOACCESS)
29057dc6f5eSAlan Somers continue;
291fe74eaabSAlexander Motin do_led(fd, objp[j].elm_idx, objp[j].elm_type,
292fe74eaabSAlexander Motin onoff, setfault);
29324ffc649SAllan Jude continue;
29424ffc649SAllan Jude }
2958729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn));
2969f96f106SAlan Somers memset(devnames, 0, devnames_size);
2978729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx;
2989f96f106SAlan Somers objdn.elm_names_size = devnames_size;
2999f96f106SAlan Somers objdn.elm_devnames = devnames;
3008729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
3018729f5ecSAllan Jude (caddr_t) &objdn) <0) {
3028729f5ecSAllan Jude continue;
3038729f5ecSAllan Jude }
3048729f5ecSAllan Jude if (objdn.elm_names_len > 0) {
3058729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) {
306fe74eaabSAlexander Motin do_led(fd, objdn.elm_idx, objp[j].elm_type,
3076af5d161SAllan Jude onoff, setfault);
3088729f5ecSAllan Jude ndisks++;
3098729f5ecSAllan Jude break;
3108729f5ecSAllan Jude }
3118729f5ecSAllan Jude }
3128729f5ecSAllan Jude }
313f734685eSBaptiste Daroussin free(objp);
3148729f5ecSAllan Jude close(fd);
3158729f5ecSAllan Jude }
3168729f5ecSAllan Jude globfree(&g);
3178729f5ecSAllan Jude if (ndisks == 0 && all == false) {
3187d893fceSJeremy Faulkner xo_errx(EXIT_FAILURE, "Could not find the SES id of device '%s'",
3198729f5ecSAllan Jude disk);
3208729f5ecSAllan Jude }
3218729f5ecSAllan Jude
3228729f5ecSAllan Jude return (EXIT_SUCCESS);
3238729f5ecSAllan Jude }
3248729f5ecSAllan Jude
3258729f5ecSAllan Jude static int
locate(int argc,char ** argv)3268729f5ecSAllan Jude locate(int argc, char **argv)
3278729f5ecSAllan Jude {
3288729f5ecSAllan Jude
3298729f5ecSAllan Jude return (sesled(argc, argv, false));
3308729f5ecSAllan Jude }
3318729f5ecSAllan Jude
3328729f5ecSAllan Jude static int
fault(int argc,char ** argv)3338729f5ecSAllan Jude fault(int argc, char **argv)
3348729f5ecSAllan Jude {
3358729f5ecSAllan Jude
3368729f5ecSAllan Jude return (sesled(argc, argv, true));
3378729f5ecSAllan Jude }
3388729f5ecSAllan Jude
33920a957e3SBaptiste Daroussin static void
sesutil_print(int * style,const char * fmt,...)3408ad16e55SEdward Tomasz Napierala sesutil_print(int *style, const char *fmt, ...)
34120a957e3SBaptiste Daroussin {
34220a957e3SBaptiste Daroussin va_list args;
34320a957e3SBaptiste Daroussin
3448ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED) {
345d25c1ff6SBaptiste Daroussin xo_open_container("extra_status");
346d25c1ff6SBaptiste Daroussin xo_emit("\t\tExtra status:\n");
3478ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_DASHED_2;
3488ad16e55SEdward Tomasz Napierala } else if (*style == PRINT_STYLE_CSV) {
3498ad16e55SEdward Tomasz Napierala xo_open_container("extra_status");
3508ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_CSV_2;
35120a957e3SBaptiste Daroussin }
3528ad16e55SEdward Tomasz Napierala
3538ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2)
3548ad16e55SEdward Tomasz Napierala xo_emit("\t\t- ");
3558ad16e55SEdward Tomasz Napierala else if (*style == PRINT_STYLE_CSV_2)
3568ad16e55SEdward Tomasz Napierala xo_emit(", ");
35720a957e3SBaptiste Daroussin va_start(args, fmt);
358d25c1ff6SBaptiste Daroussin xo_emit_hv(NULL, fmt, args);
35920a957e3SBaptiste Daroussin va_end(args);
3608ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2)
3618ad16e55SEdward Tomasz Napierala xo_emit("\n");
36220a957e3SBaptiste Daroussin }
36320a957e3SBaptiste Daroussin
36420a957e3SBaptiste Daroussin static void
print_extra_status(int eletype,u_char * cstat,int style)3658ad16e55SEdward Tomasz Napierala print_extra_status(int eletype, u_char *cstat, int style)
36620a957e3SBaptiste Daroussin {
36720a957e3SBaptiste Daroussin
36820a957e3SBaptiste Daroussin if (cstat[0] & 0x40) {
3698ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:predicted_failure/true} Predicted Failure");
37020a957e3SBaptiste Daroussin }
37120a957e3SBaptiste Daroussin if (cstat[0] & 0x20) {
3728ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:disabled/true} Disabled");
37320a957e3SBaptiste Daroussin }
37420a957e3SBaptiste Daroussin if (cstat[0] & 0x10) {
3758ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:swapped/true} Swapped");
37620a957e3SBaptiste Daroussin }
37720a957e3SBaptiste Daroussin switch (eletype) {
37820a957e3SBaptiste Daroussin case ELMTYP_DEVICE:
37920a957e3SBaptiste Daroussin case ELMTYP_ARRAY_DEV:
38020a957e3SBaptiste Daroussin if (cstat[2] & 0x02) {
3818ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/locate}");
38220a957e3SBaptiste Daroussin }
38320a957e3SBaptiste Daroussin if (cstat[2] & 0x20) {
3848ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/fault}");
38520a957e3SBaptiste Daroussin }
38620a957e3SBaptiste Daroussin break;
38720a957e3SBaptiste Daroussin case ELMTYP_FAN:
3888ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Speed: {:speed/%d}{Uw:rpm}",
38920a957e3SBaptiste Daroussin (((0x7 & cstat[1]) << 8) + cstat[2]) * 10);
39020a957e3SBaptiste Daroussin break;
39120a957e3SBaptiste Daroussin case ELMTYP_THERM:
39220a957e3SBaptiste Daroussin if (cstat[2]) {
3938ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: {:temperature/%d}{Uw:C}",
39420a957e3SBaptiste Daroussin cstat[2] - TEMPERATURE_OFFSET);
39520a957e3SBaptiste Daroussin } else {
3968ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: -{q:temperature/reserved}");
39720a957e3SBaptiste Daroussin }
39820a957e3SBaptiste Daroussin break;
39920a957e3SBaptiste Daroussin case ELMTYP_VOM:
4008ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Voltage: {:voltage/%.2f}{Uw:V}",
40120a957e3SBaptiste Daroussin be16dec(cstat + 2) / 100.0);
40220a957e3SBaptiste Daroussin break;
40320a957e3SBaptiste Daroussin }
4048ad16e55SEdward Tomasz Napierala if (style) {
405d25c1ff6SBaptiste Daroussin xo_close_container("extra_status");
406d25c1ff6SBaptiste Daroussin }
40720a957e3SBaptiste Daroussin }
40820a957e3SBaptiste Daroussin
4098729f5ecSAllan Jude static int
objmap(int argc,char ** argv __unused)4108729f5ecSAllan Jude objmap(int argc, char **argv __unused)
4118729f5ecSAllan Jude {
41260f46640SBaptiste Daroussin encioc_string_t stri;
4138729f5ecSAllan Jude encioc_elm_devnames_t e_devname;
4148729f5ecSAllan Jude encioc_elm_status_t e_status;
4158729f5ecSAllan Jude encioc_elm_desc_t e_desc;
4168729f5ecSAllan Jude encioc_element_t *e_ptr;
4178729f5ecSAllan Jude glob_t g;
4188729f5ecSAllan Jude int fd;
4198729f5ecSAllan Jude unsigned int j, nobj;
4208729f5ecSAllan Jude size_t i;
42160f46640SBaptiste Daroussin char str[32];
4228729f5ecSAllan Jude
4238729f5ecSAllan Jude if (argc != 1) {
424*3d1b233eSYan-Hao Wang usage("map");
4258729f5ecSAllan Jude }
4268729f5ecSAllan Jude
4274bd4e4b4SAlan Somers memset(&e_desc, 0, sizeof(e_desc));
4284bd4e4b4SAlan Somers /* SES4r02 allows element descriptors of up to 65536 characters */
4294bd4e4b4SAlan Somers e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
4304bd4e4b4SAlan Somers if (e_desc.elm_desc_str == NULL)
4314bd4e4b4SAlan Somers xo_err(EXIT_FAILURE, "calloc()");
4324bd4e4b4SAlan Somers
4334bd4e4b4SAlan Somers e_devname.elm_devnames = calloc(128, sizeof(char));
4344bd4e4b4SAlan Somers if (e_devname.elm_devnames == NULL)
4354bd4e4b4SAlan Somers xo_err(EXIT_FAILURE, "calloc()");
4364bd4e4b4SAlan Somers e_devname.elm_names_size = 128;
4374bd4e4b4SAlan Somers
4388729f5ecSAllan Jude /* Get the list of ses devices */
4398729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
440cddcb259SBaptiste Daroussin globfree(&g);
441d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found");
442cddcb259SBaptiste Daroussin }
443d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION);
444d25c1ff6SBaptiste Daroussin xo_open_container("sesutil");
445d25c1ff6SBaptiste Daroussin xo_open_list("enclosures");
446cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) {
447cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */
448cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
4498729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) {
450cddcb259SBaptiste Daroussin continue;
4518729f5ecSAllan Jude }
452cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
4538729f5ecSAllan Jude /*
4548729f5ecSAllan Jude * Don't treat non-access errors as critical if we are
4558729f5ecSAllan Jude * accessing all devices
4568729f5ecSAllan Jude */
4578729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) {
458d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device");
4598729f5ecSAllan Jude }
460d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
4618729f5ecSAllan Jude continue;
462cddcb259SBaptiste Daroussin }
463cddcb259SBaptiste Daroussin
4648729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
4658729f5ecSAllan Jude close(fd);
466d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
4678729f5ecSAllan Jude }
468cddcb259SBaptiste Daroussin
4698729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t));
4708729f5ecSAllan Jude if (e_ptr == NULL) {
4718729f5ecSAllan Jude close(fd);
472d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()");
4738729f5ecSAllan Jude }
474cddcb259SBaptiste Daroussin
4758729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) {
4768729f5ecSAllan Jude close(fd);
477d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
4788729f5ecSAllan Jude }
479cddcb259SBaptiste Daroussin
480d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures");
481d25c1ff6SBaptiste Daroussin xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5);
48260f46640SBaptiste Daroussin stri.bufsiz = sizeof(str);
48360f46640SBaptiste Daroussin stri.buf = &str[0];
48460f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0)
485d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf);
48660f46640SBaptiste Daroussin stri.bufsiz = sizeof(str);
48760f46640SBaptiste Daroussin stri.buf = &str[0];
48860f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0)
489d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf);
49060f46640SBaptiste Daroussin
491d25c1ff6SBaptiste Daroussin xo_open_list("elements");
492cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) {
4938729f5ecSAllan Jude /* Get the status of the element */
4948729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status));
4958729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx;
4968729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT,
4978729f5ecSAllan Jude (caddr_t) &e_status) < 0) {
4988729f5ecSAllan Jude close(fd);
499d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
5008729f5ecSAllan Jude }
5018729f5ecSAllan Jude /* Get the description of the element */
5028729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx;
5038729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX;
5048729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC,
5058729f5ecSAllan Jude (caddr_t) &e_desc) < 0) {
5068729f5ecSAllan Jude close(fd);
507d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC");
5088729f5ecSAllan Jude }
5094bd4e4b4SAlan Somers e_desc.elm_desc_str[e_desc.elm_desc_len] = '\0';
5108729f5ecSAllan Jude /* Get the device name(s) of the element */
5118729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx;
512cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
5138729f5ecSAllan Jude (caddr_t) &e_devname) <0) {
51418acbeb3SAlan Somers /* Continue even if we can't look up devnames */
5158729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0';
516cddcb259SBaptiste Daroussin }
517d25c1ff6SBaptiste Daroussin xo_open_instance("elements");
518d25c1ff6SBaptiste Daroussin xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx,
5198729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type));
520d25c1ff6SBaptiste Daroussin xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n",
521d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0],
522d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2],
523d7654478SBaptiste Daroussin e_status.cstat[3]);
5248729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) {
525d25c1ff6SBaptiste Daroussin xo_emit("\t\tDescription: {:description/%s}\n",
5268729f5ecSAllan Jude e_desc.elm_desc_str);
527cddcb259SBaptiste Daroussin }
5288729f5ecSAllan Jude if (e_devname.elm_names_len > 0) {
529d25c1ff6SBaptiste Daroussin xo_emit("\t\tDevice Names: {:device_names/%s}\n",
5308729f5ecSAllan Jude e_devname.elm_devnames);
531cddcb259SBaptiste Daroussin }
5328ad16e55SEdward Tomasz Napierala print_extra_status(e_ptr[j].elm_type, e_status.cstat, PRINT_STYLE_DASHED);
533d25c1ff6SBaptiste Daroussin xo_close_instance("elements");
534cddcb259SBaptiste Daroussin }
535d25c1ff6SBaptiste Daroussin xo_close_list("elements");
536f734685eSBaptiste Daroussin free(e_ptr);
537cddcb259SBaptiste Daroussin close(fd);
538cddcb259SBaptiste Daroussin }
539cddcb259SBaptiste Daroussin globfree(&g);
5404bd4e4b4SAlan Somers free(e_devname.elm_devnames);
5414bd4e4b4SAlan Somers free(e_desc.elm_desc_str);
542d25c1ff6SBaptiste Daroussin xo_close_list("enclosures");
543d25c1ff6SBaptiste Daroussin xo_close_container("sesutil");
544*3d1b233eSYan-Hao Wang if (xo_finish() < 0)
545*3d1b233eSYan-Hao Wang xo_err(EXIT_FAILURE, "stdout");
546cddcb259SBaptiste Daroussin
547cddcb259SBaptiste Daroussin return (EXIT_SUCCESS);
548cddcb259SBaptiste Daroussin }
549cddcb259SBaptiste Daroussin
5508ad16e55SEdward Tomasz Napierala /*
5518ad16e55SEdward Tomasz Napierala * Get rid of the 'passN' devices, unless there's nothing else to show.
5528ad16e55SEdward Tomasz Napierala */
5538ad16e55SEdward Tomasz Napierala static void
skip_pass_devices(char * devnames,size_t devnameslen)5548ad16e55SEdward Tomasz Napierala skip_pass_devices(char *devnames, size_t devnameslen)
5558ad16e55SEdward Tomasz Napierala {
5568ad16e55SEdward Tomasz Napierala char *dev, devs[128], passes[128], *tmp;
5578ad16e55SEdward Tomasz Napierala
5588ad16e55SEdward Tomasz Napierala devs[0] = passes[0] = '\0';
5598ad16e55SEdward Tomasz Napierala tmp = devnames;
5608ad16e55SEdward Tomasz Napierala
5618ad16e55SEdward Tomasz Napierala while ((dev = strsep(&tmp, ",")) != NULL) {
5628ad16e55SEdward Tomasz Napierala if (strncmp(dev, "pass", 4) == 0) {
5638ad16e55SEdward Tomasz Napierala if (passes[0] != '\0')
5648ad16e55SEdward Tomasz Napierala strlcat(passes, ",", sizeof(passes));
5658ad16e55SEdward Tomasz Napierala strlcat(passes, dev, sizeof(passes));
5668ad16e55SEdward Tomasz Napierala } else {
5678ad16e55SEdward Tomasz Napierala if (devs[0] != '\0')
5688ad16e55SEdward Tomasz Napierala strlcat(devs, ",", sizeof(devs));
5698ad16e55SEdward Tomasz Napierala strlcat(devs, dev, sizeof(devs));
5708ad16e55SEdward Tomasz Napierala }
5718ad16e55SEdward Tomasz Napierala }
5728ad16e55SEdward Tomasz Napierala strlcpy(devnames, devs, devnameslen);
5738ad16e55SEdward Tomasz Napierala if (devnames[0] == '\0')
5748ad16e55SEdward Tomasz Napierala strlcpy(devnames, passes, devnameslen);
5758ad16e55SEdward Tomasz Napierala }
5768ad16e55SEdward Tomasz Napierala
5778ad16e55SEdward Tomasz Napierala static void
fetch_device_details(char * devnames,char ** model,char ** serial,off_t * size)5788ad16e55SEdward Tomasz Napierala fetch_device_details(char *devnames, char **model, char **serial, off_t *size)
5798ad16e55SEdward Tomasz Napierala {
5808ad16e55SEdward Tomasz Napierala char ident[DISK_IDENT_SIZE];
5818ad16e55SEdward Tomasz Napierala struct diocgattr_arg arg;
582f05cc0f1SAlan Somers char *tmp;
5838ad16e55SEdward Tomasz Napierala off_t mediasize;
584f05cc0f1SAlan Somers int comma;
5858ad16e55SEdward Tomasz Napierala int fd;
5868ad16e55SEdward Tomasz Napierala
587f05cc0f1SAlan Somers comma = (int)strcspn(devnames, ",");
588f05cc0f1SAlan Somers asprintf(&tmp, "/dev/%.*s", comma, devnames);
5898ad16e55SEdward Tomasz Napierala if (tmp == NULL)
590*3d1b233eSYan-Hao Wang xo_err(EXIT_FAILURE, "asprintf");
5918ad16e55SEdward Tomasz Napierala fd = open(tmp, O_RDONLY);
592f05cc0f1SAlan Somers free(tmp);
5938ad16e55SEdward Tomasz Napierala if (fd < 0) {
5948ad16e55SEdward Tomasz Napierala /*
5958ad16e55SEdward Tomasz Napierala * This can happen with a disk so broken it cannot
5968ad16e55SEdward Tomasz Napierala * be probed by GEOM.
5978ad16e55SEdward Tomasz Napierala */
5988ad16e55SEdward Tomasz Napierala *model = strdup("?");
5998ad16e55SEdward Tomasz Napierala *serial = strdup("?");
6008ad16e55SEdward Tomasz Napierala *size = -1;
601f05cc0f1SAlan Somers close(fd);
6028ad16e55SEdward Tomasz Napierala return;
6038ad16e55SEdward Tomasz Napierala }
6048ad16e55SEdward Tomasz Napierala
6058ad16e55SEdward Tomasz Napierala strlcpy(arg.name, "GEOM::descr", sizeof(arg.name));
6068ad16e55SEdward Tomasz Napierala arg.len = sizeof(arg.value.str);
6078ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGATTR, &arg) == 0)
6088ad16e55SEdward Tomasz Napierala *model = strdup(arg.value.str);
6098ad16e55SEdward Tomasz Napierala else
6108ad16e55SEdward Tomasz Napierala *model = NULL;
6118ad16e55SEdward Tomasz Napierala
6128ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGIDENT, ident) == 0)
6138ad16e55SEdward Tomasz Napierala *serial = strdup(ident);
6148ad16e55SEdward Tomasz Napierala else
6158ad16e55SEdward Tomasz Napierala *serial = NULL;
6168ad16e55SEdward Tomasz Napierala
6178ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0)
6188ad16e55SEdward Tomasz Napierala *size = mediasize;
6198ad16e55SEdward Tomasz Napierala else
6208ad16e55SEdward Tomasz Napierala *size = -1;
621f05cc0f1SAlan Somers close(fd);
6228ad16e55SEdward Tomasz Napierala }
6238ad16e55SEdward Tomasz Napierala
6248ad16e55SEdward Tomasz Napierala static void
show_device(int fd,int elm_idx,encioc_elm_status_t e_status,encioc_elm_desc_t e_desc)6258ad16e55SEdward Tomasz Napierala show_device(int fd, int elm_idx, encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6268ad16e55SEdward Tomasz Napierala {
6278ad16e55SEdward Tomasz Napierala encioc_elm_devnames_t e_devname;
62809f29b03SAlan Somers char *model = NULL, *serial = NULL;
6298ad16e55SEdward Tomasz Napierala off_t size;
6308ad16e55SEdward Tomasz Napierala
6318ad16e55SEdward Tomasz Napierala /* Get the device name(s) of the element */
6328ad16e55SEdward Tomasz Napierala memset(&e_devname, 0, sizeof(e_devname));
6338ad16e55SEdward Tomasz Napierala e_devname.elm_idx = elm_idx;
6348ad16e55SEdward Tomasz Napierala e_devname.elm_names_size = 128;
6358ad16e55SEdward Tomasz Napierala e_devname.elm_devnames = calloc(128, sizeof(char));
6368ad16e55SEdward Tomasz Napierala if (e_devname.elm_devnames == NULL) {
6378ad16e55SEdward Tomasz Napierala close(fd);
6388ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()");
6398ad16e55SEdward Tomasz Napierala }
6408ad16e55SEdward Tomasz Napierala
6418ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
6428ad16e55SEdward Tomasz Napierala (caddr_t) &e_devname) < 0) {
6438ad16e55SEdward Tomasz Napierala /* We don't care if this fails */
6448ad16e55SEdward Tomasz Napierala e_devname.elm_devnames[0] = '\0';
6458ad16e55SEdward Tomasz Napierala size = -1;
6468ad16e55SEdward Tomasz Napierala } else {
6478ad16e55SEdward Tomasz Napierala skip_pass_devices(e_devname.elm_devnames, 128);
6488ad16e55SEdward Tomasz Napierala fetch_device_details(e_devname.elm_devnames, &model, &serial, &size);
6498ad16e55SEdward Tomasz Napierala }
6508ad16e55SEdward Tomasz Napierala xo_open_instance("elements");
6518ad16e55SEdward Tomasz Napierala xo_emit("{e:type/device_slot}");
65279f38143SPoul-Henning Kamp xo_emit("{d:description/%-15s} ", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "-");
65379f38143SPoul-Henning Kamp xo_emit("{e:description/%-15s}", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "");
6548ad16e55SEdward Tomasz Napierala xo_emit("{d:device_names/%-7s} ", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "-");
6558ad16e55SEdward Tomasz Napierala xo_emit("{e:device_names/%s}", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "");
6568ad16e55SEdward Tomasz Napierala xo_emit("{d:model/%-25s} ", model ? model : "-");
6578ad16e55SEdward Tomasz Napierala xo_emit("{e:model/%s}", model ? model : "");
6588ad16e55SEdward Tomasz Napierala xo_emit("{d:serial/%-20s} ", serial != NULL ? serial : "-");
6598ad16e55SEdward Tomasz Napierala xo_emit("{e:serial/%s}", serial != NULL ? serial : "");
660a1571967SEdward Tomasz Napierala if ((e_status.cstat[0] & 0xf) == SES_OBJSTAT_OK && size >= 0) {
6618ad16e55SEdward Tomasz Napierala xo_emit("{h,hn-1000:size/%ld}{e:status/%s}",
6628ad16e55SEdward Tomasz Napierala size, scode2ascii(e_status.cstat[0]));
6638ad16e55SEdward Tomasz Napierala } else {
6648ad16e55SEdward Tomasz Napierala xo_emit("{:status/%s}", scode2ascii(e_status.cstat[0]));
6658ad16e55SEdward Tomasz Napierala }
6668ad16e55SEdward Tomasz Napierala print_extra_status(ELMTYP_ARRAY_DEV, e_status.cstat, PRINT_STYLE_CSV);
6678ad16e55SEdward Tomasz Napierala xo_emit("\n");
6688ad16e55SEdward Tomasz Napierala xo_close_instance("elements");
66909f29b03SAlan Somers free(serial);
67009f29b03SAlan Somers free(model);
6718ad16e55SEdward Tomasz Napierala free(e_devname.elm_devnames);
6728ad16e55SEdward Tomasz Napierala }
6738ad16e55SEdward Tomasz Napierala
6748ad16e55SEdward Tomasz Napierala static void
show_therm(encioc_elm_status_t e_status,encioc_elm_desc_t e_desc)6758ad16e55SEdward Tomasz Napierala show_therm(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6768ad16e55SEdward Tomasz Napierala {
6778ad16e55SEdward Tomasz Napierala
6788ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) {
6798ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */
6808ad16e55SEdward Tomasz Napierala return;
6818ad16e55SEdward Tomasz Napierala }
6828ad16e55SEdward Tomasz Napierala
6838ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) {
6848ad16e55SEdward Tomasz Napierala /* No temperature to show. */
6858ad16e55SEdward Tomasz Napierala return;
6868ad16e55SEdward Tomasz Napierala }
6878ad16e55SEdward Tomasz Napierala
6888ad16e55SEdward Tomasz Napierala xo_open_instance("elements");
6898ad16e55SEdward Tomasz Napierala xo_emit("{e:type/temperature_sensor}");
6908ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:temperature/%d}{Uw:C}",
6918ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, e_status.cstat[2] - TEMPERATURE_OFFSET);
6928ad16e55SEdward Tomasz Napierala xo_close_instance("elements");
6938ad16e55SEdward Tomasz Napierala }
6948ad16e55SEdward Tomasz Napierala
6958ad16e55SEdward Tomasz Napierala static void
show_vom(encioc_elm_status_t e_status,encioc_elm_desc_t e_desc)6968ad16e55SEdward Tomasz Napierala show_vom(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6978ad16e55SEdward Tomasz Napierala {
6988ad16e55SEdward Tomasz Napierala
6998ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) {
7008ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */
7018ad16e55SEdward Tomasz Napierala return;
7028ad16e55SEdward Tomasz Napierala }
7038ad16e55SEdward Tomasz Napierala
7048ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) {
7058ad16e55SEdward Tomasz Napierala /* No voltage to show. */
7068ad16e55SEdward Tomasz Napierala return;
7078ad16e55SEdward Tomasz Napierala }
7088ad16e55SEdward Tomasz Napierala
7098ad16e55SEdward Tomasz Napierala xo_open_instance("elements");
7108ad16e55SEdward Tomasz Napierala xo_emit("{e:type/voltage_sensor}");
7118ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:voltage/%.2f}{Uw:V}",
7128ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, be16dec(e_status.cstat + 2) / 100.0);
7138ad16e55SEdward Tomasz Napierala xo_close_instance("elements");
7148ad16e55SEdward Tomasz Napierala }
7158ad16e55SEdward Tomasz Napierala
7168ad16e55SEdward Tomasz Napierala static int
show(int argc,char ** argv __unused)7178ad16e55SEdward Tomasz Napierala show(int argc, char **argv __unused)
7188ad16e55SEdward Tomasz Napierala {
7198ad16e55SEdward Tomasz Napierala encioc_string_t stri;
7208ad16e55SEdward Tomasz Napierala encioc_elm_status_t e_status;
7218ad16e55SEdward Tomasz Napierala encioc_elm_desc_t e_desc;
7228ad16e55SEdward Tomasz Napierala encioc_element_t *e_ptr;
7238ad16e55SEdward Tomasz Napierala glob_t g;
7248ad16e55SEdward Tomasz Napierala elm_type_t prev_type;
7258ad16e55SEdward Tomasz Napierala int fd;
7268ad16e55SEdward Tomasz Napierala unsigned int j, nobj;
7278ad16e55SEdward Tomasz Napierala size_t i;
7288ad16e55SEdward Tomasz Napierala bool first_ses;
7298ad16e55SEdward Tomasz Napierala char str[32];
7308ad16e55SEdward Tomasz Napierala
7318ad16e55SEdward Tomasz Napierala if (argc != 1) {
732*3d1b233eSYan-Hao Wang usage("map");
7338ad16e55SEdward Tomasz Napierala }
7348ad16e55SEdward Tomasz Napierala
7358ad16e55SEdward Tomasz Napierala first_ses = true;
7368ad16e55SEdward Tomasz Napierala
7374bd4e4b4SAlan Somers e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
7384bd4e4b4SAlan Somers if (e_desc.elm_desc_str == NULL)
7394bd4e4b4SAlan Somers xo_err(EXIT_FAILURE, "calloc()");
7404bd4e4b4SAlan Somers
7418ad16e55SEdward Tomasz Napierala /* Get the list of ses devices */
7428ad16e55SEdward Tomasz Napierala if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
7438ad16e55SEdward Tomasz Napierala globfree(&g);
7448ad16e55SEdward Tomasz Napierala xo_errx(EXIT_FAILURE, "No SES devices found");
7458ad16e55SEdward Tomasz Napierala }
7468ad16e55SEdward Tomasz Napierala xo_set_version(SESUTIL_XO_VERSION);
7478ad16e55SEdward Tomasz Napierala xo_open_container("sesutil");
7488ad16e55SEdward Tomasz Napierala xo_open_list("enclosures");
7498ad16e55SEdward Tomasz Napierala for (i = 0; i < g.gl_pathc; i++) {
7508ad16e55SEdward Tomasz Napierala /* ensure we only got numbers after ses */
7518ad16e55SEdward Tomasz Napierala if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
7528ad16e55SEdward Tomasz Napierala strlen(g.gl_pathv[i] + 8)) {
7538ad16e55SEdward Tomasz Napierala continue;
7548ad16e55SEdward Tomasz Napierala }
7558ad16e55SEdward Tomasz Napierala if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
7568ad16e55SEdward Tomasz Napierala /*
7578ad16e55SEdward Tomasz Napierala * Don't treat non-access errors as critical if we are
7588ad16e55SEdward Tomasz Napierala * accessing all devices
7598ad16e55SEdward Tomasz Napierala */
7608ad16e55SEdward Tomasz Napierala if (errno == EACCES && g.gl_pathc > 1) {
7618ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "unable to access SES device");
7628ad16e55SEdward Tomasz Napierala }
7638ad16e55SEdward Tomasz Napierala xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
7648ad16e55SEdward Tomasz Napierala continue;
7658ad16e55SEdward Tomasz Napierala }
7668ad16e55SEdward Tomasz Napierala
7678ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
7688ad16e55SEdward Tomasz Napierala close(fd);
7698ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
7708ad16e55SEdward Tomasz Napierala }
7718ad16e55SEdward Tomasz Napierala
7728ad16e55SEdward Tomasz Napierala e_ptr = calloc(nobj, sizeof(encioc_element_t));
7738ad16e55SEdward Tomasz Napierala if (e_ptr == NULL) {
7748ad16e55SEdward Tomasz Napierala close(fd);
7758ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()");
7768ad16e55SEdward Tomasz Napierala }
7778ad16e55SEdward Tomasz Napierala
7788ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) {
7798ad16e55SEdward Tomasz Napierala close(fd);
7808ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
7818ad16e55SEdward Tomasz Napierala }
7828ad16e55SEdward Tomasz Napierala
7838ad16e55SEdward Tomasz Napierala xo_open_instance("enclosures");
7848ad16e55SEdward Tomasz Napierala
7858ad16e55SEdward Tomasz Napierala if (first_ses)
7868ad16e55SEdward Tomasz Napierala first_ses = false;
7878ad16e55SEdward Tomasz Napierala else
7888ad16e55SEdward Tomasz Napierala xo_emit("\n");
7898ad16e55SEdward Tomasz Napierala
7908ad16e55SEdward Tomasz Napierala xo_emit("{t:enc/%s}: ", g.gl_pathv[i] + 5);
7918ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str);
7928ad16e55SEdward Tomasz Napierala stri.buf = &str[0];
7938ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0)
7948ad16e55SEdward Tomasz Napierala xo_emit("<{t:name/%s}>; ", stri.buf);
7958ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str);
7968ad16e55SEdward Tomasz Napierala stri.buf = &str[0];
7978ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0)
7988ad16e55SEdward Tomasz Napierala xo_emit("ID: {t:id/%s}", stri.buf);
7998ad16e55SEdward Tomasz Napierala xo_emit("\n");
8008ad16e55SEdward Tomasz Napierala
8018ad16e55SEdward Tomasz Napierala xo_open_list("elements");
8028ad16e55SEdward Tomasz Napierala prev_type = -1;
8038ad16e55SEdward Tomasz Napierala for (j = 0; j < nobj; j++) {
8048ad16e55SEdward Tomasz Napierala /* Get the status of the element */
8058ad16e55SEdward Tomasz Napierala memset(&e_status, 0, sizeof(e_status));
8068ad16e55SEdward Tomasz Napierala e_status.elm_idx = e_ptr[j].elm_idx;
8078ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMSTAT,
8088ad16e55SEdward Tomasz Napierala (caddr_t) &e_status) < 0) {
8098ad16e55SEdward Tomasz Napierala close(fd);
8108ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
8118ad16e55SEdward Tomasz Napierala }
8128ad16e55SEdward Tomasz Napierala
8138ad16e55SEdward Tomasz Napierala /*
8148ad16e55SEdward Tomasz Napierala * Skip "Unsupported" elements; those usually precede
8158ad16e55SEdward Tomasz Napierala * the actual device entries and are not particularly
8168ad16e55SEdward Tomasz Napierala * interesting.
8178ad16e55SEdward Tomasz Napierala */
8188ad16e55SEdward Tomasz Napierala if (e_status.cstat[0] == SES_OBJSTAT_UNSUPPORTED)
8198ad16e55SEdward Tomasz Napierala continue;
8208ad16e55SEdward Tomasz Napierala
8218ad16e55SEdward Tomasz Napierala /* Get the description of the element */
8228ad16e55SEdward Tomasz Napierala e_desc.elm_idx = e_ptr[j].elm_idx;
8238ad16e55SEdward Tomasz Napierala e_desc.elm_desc_len = UINT16_MAX;
8248ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDESC,
8258ad16e55SEdward Tomasz Napierala (caddr_t) &e_desc) < 0) {
8268ad16e55SEdward Tomasz Napierala close(fd);
8278ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC");
8288ad16e55SEdward Tomasz Napierala }
8294bd4e4b4SAlan Somers e_desc.elm_desc_str[e_desc.elm_desc_len] = '\0';
8308ad16e55SEdward Tomasz Napierala
8318ad16e55SEdward Tomasz Napierala switch (e_ptr[j].elm_type) {
8328ad16e55SEdward Tomasz Napierala case ELMTYP_DEVICE:
8338ad16e55SEdward Tomasz Napierala case ELMTYP_ARRAY_DEV:
8348ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type)
8358ad16e55SEdward Tomasz Napierala xo_emit("Desc Dev Model Ident Size/Status\n");
8368ad16e55SEdward Tomasz Napierala
8378ad16e55SEdward Tomasz Napierala show_device(fd, e_ptr[j].elm_idx, e_status, e_desc);
8388ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type;
8398ad16e55SEdward Tomasz Napierala break;
8408ad16e55SEdward Tomasz Napierala case ELMTYP_THERM:
8418ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type)
8423d10bf72SEdward Tomasz Napierala xo_emit("\nTemperatures: ");
8438ad16e55SEdward Tomasz Napierala else
8448ad16e55SEdward Tomasz Napierala xo_emit(", ");
8458ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type;
8468ad16e55SEdward Tomasz Napierala show_therm(e_status, e_desc);
8478ad16e55SEdward Tomasz Napierala break;
8488ad16e55SEdward Tomasz Napierala case ELMTYP_VOM:
8498ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type)
8503d10bf72SEdward Tomasz Napierala xo_emit("\nVoltages: ");
8518ad16e55SEdward Tomasz Napierala else
8528ad16e55SEdward Tomasz Napierala xo_emit(", ");
8538ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type;
8548ad16e55SEdward Tomasz Napierala show_vom(e_status, e_desc);
8558ad16e55SEdward Tomasz Napierala break;
8568ad16e55SEdward Tomasz Napierala default:
8578ad16e55SEdward Tomasz Napierala /*
8588ad16e55SEdward Tomasz Napierala * Ignore stuff not interesting to the user.
8598ad16e55SEdward Tomasz Napierala */
8608ad16e55SEdward Tomasz Napierala break;
8618ad16e55SEdward Tomasz Napierala }
8628ad16e55SEdward Tomasz Napierala }
8638ad16e55SEdward Tomasz Napierala if (prev_type != (elm_type_t)-1 &&
8648ad16e55SEdward Tomasz Napierala prev_type != ELMTYP_DEVICE && prev_type != ELMTYP_ARRAY_DEV)
8658ad16e55SEdward Tomasz Napierala xo_emit("\n");
8668ad16e55SEdward Tomasz Napierala xo_close_list("elements");
8678ad16e55SEdward Tomasz Napierala free(e_ptr);
8688ad16e55SEdward Tomasz Napierala close(fd);
8698ad16e55SEdward Tomasz Napierala }
8708ad16e55SEdward Tomasz Napierala globfree(&g);
8714bd4e4b4SAlan Somers free(e_desc.elm_desc_str);
8728ad16e55SEdward Tomasz Napierala xo_close_list("enclosures");
8738ad16e55SEdward Tomasz Napierala xo_close_container("sesutil");
874*3d1b233eSYan-Hao Wang if (xo_finish() < 0)
875*3d1b233eSYan-Hao Wang xo_err(EXIT_FAILURE, "stdout");
8768ad16e55SEdward Tomasz Napierala
8778ad16e55SEdward Tomasz Napierala return (EXIT_SUCCESS);
8788ad16e55SEdward Tomasz Napierala }
8798ad16e55SEdward Tomasz Napierala
8808729f5ecSAllan Jude static int
encstatus(int argc,char ** argv __unused)8818729f5ecSAllan Jude encstatus(int argc, char **argv __unused)
882cddcb259SBaptiste Daroussin {
8838729f5ecSAllan Jude glob_t g;
8848729f5ecSAllan Jude int fd, status;
8858729f5ecSAllan Jude size_t i, e;
8868729f5ecSAllan Jude u_char estat;
887cddcb259SBaptiste Daroussin
8888729f5ecSAllan Jude status = 0;
8898729f5ecSAllan Jude if (argc != 1) {
890*3d1b233eSYan-Hao Wang usage("status");
8918729f5ecSAllan Jude }
8928729f5ecSAllan Jude
8938729f5ecSAllan Jude /* Get the list of ses devices */
8948729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
8958729f5ecSAllan Jude globfree(&g);
896d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found");
8978729f5ecSAllan Jude }
898d25c1ff6SBaptiste Daroussin
899d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION);
900d25c1ff6SBaptiste Daroussin xo_open_container("sesutil");
901d25c1ff6SBaptiste Daroussin xo_open_list("enclosures");
9028729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) {
9038729f5ecSAllan Jude /* ensure we only got numbers after ses */
9048729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
9058729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) {
9068729f5ecSAllan Jude continue;
9078729f5ecSAllan Jude }
9088729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
9098729f5ecSAllan Jude /*
9108729f5ecSAllan Jude * Don't treat non-access errors as critical if we are
9118729f5ecSAllan Jude * accessing all devices
9128729f5ecSAllan Jude */
9138729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) {
914d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device");
9158729f5ecSAllan Jude }
916d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
9178729f5ecSAllan Jude continue;
9188729f5ecSAllan Jude }
9198729f5ecSAllan Jude
9208729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) {
921d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT");
9228729f5ecSAllan Jude close(fd);
9238729f5ecSAllan Jude }
9248729f5ecSAllan Jude
925d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures");
926d25c1ff6SBaptiste Daroussin xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5);
9278729f5ecSAllan Jude e = 0;
9288729f5ecSAllan Jude if (estat == 0) {
9298729f5ecSAllan Jude if (status == 0) {
9308729f5ecSAllan Jude status = 1;
9318729f5ecSAllan Jude }
932d25c1ff6SBaptiste Daroussin xo_emit("{q:status/OK}");
9338729f5ecSAllan Jude } else {
9348729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) {
935d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/INFO}");
9368729f5ecSAllan Jude e++;
9378729f5ecSAllan Jude }
9388729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) {
9398729f5ecSAllan Jude if (e)
940d25c1ff6SBaptiste Daroussin xo_emit(",");
941d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/NONCRITICAL}");
9428729f5ecSAllan Jude e++;
9438729f5ecSAllan Jude }
9448729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) {
9458729f5ecSAllan Jude if (e)
946d25c1ff6SBaptiste Daroussin xo_emit(",");
947d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/CRITICAL}");
9488729f5ecSAllan Jude e++;
9498729f5ecSAllan Jude status = -1;
9508729f5ecSAllan Jude }
9518729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) {
9528729f5ecSAllan Jude if (e)
953d25c1ff6SBaptiste Daroussin xo_emit(",");
954d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/UNRECOV}");
9558729f5ecSAllan Jude e++;
9568729f5ecSAllan Jude status = -1;
9578729f5ecSAllan Jude }
9588729f5ecSAllan Jude }
959d25c1ff6SBaptiste Daroussin xo_close_instance("enclosures");
960d25c1ff6SBaptiste Daroussin xo_emit("\n");
9618729f5ecSAllan Jude close(fd);
9628729f5ecSAllan Jude }
9638729f5ecSAllan Jude globfree(&g);
9648729f5ecSAllan Jude
965d25c1ff6SBaptiste Daroussin xo_close_list("enclosures");
966d25c1ff6SBaptiste Daroussin xo_close_container("sesutil");
967*3d1b233eSYan-Hao Wang if (xo_finish() < 0)
968*3d1b233eSYan-Hao Wang xo_err(EXIT_FAILURE, "stdout");
969d25c1ff6SBaptiste Daroussin
9708729f5ecSAllan Jude if (status == 1) {
9718729f5ecSAllan Jude return (EXIT_SUCCESS);
9728729f5ecSAllan Jude } else {
9738729f5ecSAllan Jude return (EXIT_FAILURE);
9748729f5ecSAllan Jude }
975cddcb259SBaptiste Daroussin }
976cddcb259SBaptiste Daroussin
977cddcb259SBaptiste Daroussin int
main(int argc,char ** argv)978cddcb259SBaptiste Daroussin main(int argc, char **argv)
979cddcb259SBaptiste Daroussin {
9808729f5ecSAllan Jude int i, ch;
981cddcb259SBaptiste Daroussin struct command *cmd = NULL;
982cddcb259SBaptiste Daroussin
983d25c1ff6SBaptiste Daroussin argc = xo_parse_args(argc, argv);
984d25c1ff6SBaptiste Daroussin if (argc < 0)
985*3d1b233eSYan-Hao Wang exit(EXIT_FAILURE);
986d25c1ff6SBaptiste Daroussin
9878729f5ecSAllan Jude uflag = "/dev/ses[0-9]*";
9888729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) {
9898729f5ecSAllan Jude switch (ch) {
9908729f5ecSAllan Jude case 'u':
9918729f5ecSAllan Jude uflag = optarg;
9928729f5ecSAllan Jude break;
9938729f5ecSAllan Jude case '?':
9948729f5ecSAllan Jude default:
995*3d1b233eSYan-Hao Wang usage(NULL);
9968729f5ecSAllan Jude }
9978729f5ecSAllan Jude }
9988729f5ecSAllan Jude argc -= optind;
9998729f5ecSAllan Jude argv += optind;
10008729f5ecSAllan Jude
10018729f5ecSAllan Jude if (argc < 1) {
1002*3d1b233eSYan-Hao Wang xo_warnx("Missing command");
1003*3d1b233eSYan-Hao Wang usage(NULL);
1004cddcb259SBaptiste Daroussin }
1005cddcb259SBaptiste Daroussin
1006cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) {
10078729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) {
1008cddcb259SBaptiste Daroussin cmd = &cmds[i];
1009cddcb259SBaptiste Daroussin break;
1010cddcb259SBaptiste Daroussin }
1011cddcb259SBaptiste Daroussin }
1012cddcb259SBaptiste Daroussin
1013cddcb259SBaptiste Daroussin if (cmd == NULL) {
1014*3d1b233eSYan-Hao Wang xo_warnx("unknown command %s", argv[0]);
1015*3d1b233eSYan-Hao Wang usage(NULL);
1016cddcb259SBaptiste Daroussin }
1017cddcb259SBaptiste Daroussin
1018cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv));
1019cddcb259SBaptiste Daroussin }
1020