xref: /freebsd/usr.sbin/sesutil/sesutil.c (revision 09f29b03ddf857a366f338145693b5449e6ca5de)
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>
34cddcb259SBaptiste Daroussin __FBSDID("$FreeBSD$");
35cddcb259SBaptiste Daroussin 
3620a957e3SBaptiste Daroussin #include <sys/endian.h>
37cddcb259SBaptiste Daroussin #include <sys/param.h>
388ad16e55SEdward Tomasz Napierala #include <sys/disk.h>
39cddcb259SBaptiste Daroussin #include <sys/ioctl.h>
40d7654478SBaptiste Daroussin #include <sys/types.h>
41cddcb259SBaptiste Daroussin 
42cddcb259SBaptiste Daroussin #include <err.h>
43cddcb259SBaptiste Daroussin #include <errno.h>
44cddcb259SBaptiste Daroussin #include <fcntl.h>
458729f5ecSAllan Jude #include <getopt.h>
46cddcb259SBaptiste Daroussin #include <glob.h>
47cddcb259SBaptiste Daroussin #include <stdbool.h>
48cddcb259SBaptiste Daroussin #include <stddef.h>
49cddcb259SBaptiste Daroussin #include <stdint.h>
50cddcb259SBaptiste Daroussin #include <stdio.h>
51cddcb259SBaptiste Daroussin #include <stdlib.h>
52cddcb259SBaptiste Daroussin #include <string.h>
53cddcb259SBaptiste Daroussin #include <unistd.h>
54d25c1ff6SBaptiste Daroussin #include <libxo/xo.h>
55cddcb259SBaptiste Daroussin 
56cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h>
57cddcb259SBaptiste Daroussin 
588729f5ecSAllan Jude #include "eltsub.h"
598729f5ecSAllan Jude 
60d25c1ff6SBaptiste Daroussin #define SESUTIL_XO_VERSION	"1"
61d25c1ff6SBaptiste Daroussin 
628ad16e55SEdward Tomasz Napierala #define TEMPERATURE_OFFSET	20
638ad16e55SEdward Tomasz Napierala 
648ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED	0
658ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED_2	1
668ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV 	2
678ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV_2	3
688ad16e55SEdward Tomasz Napierala 
698729f5ecSAllan Jude static int encstatus(int argc, char **argv);
708729f5ecSAllan Jude static int fault(int argc, char **argv);
71cddcb259SBaptiste Daroussin static int locate(int argc, char **argv);
728729f5ecSAllan Jude static int objmap(int argc, char **argv);
738729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault);
748ad16e55SEdward Tomasz Napierala static int show(int argc, char **argv);
758ad16e55SEdward Tomasz Napierala static void sesutil_print(int *style, const char *fmt, ...) __printflike(2,3);
76cddcb259SBaptiste Daroussin 
77cddcb259SBaptiste Daroussin static struct command {
78cddcb259SBaptiste Daroussin 	const char *name;
798729f5ecSAllan Jude 	const char *param;
80cddcb259SBaptiste Daroussin 	const char *desc;
81cddcb259SBaptiste Daroussin 	int (*exec)(int argc, char **argv);
82cddcb259SBaptiste Daroussin } cmds[] = {
838729f5ecSAllan Jude 	{ "fault",
848729f5ecSAllan Jude 	    "(<disk>|<sesid>|all) (on|off)",
858729f5ecSAllan Jude 	    "Change the state of the fault LED associated with a disk",
868729f5ecSAllan Jude 	    fault },
878729f5ecSAllan Jude 	{ "locate",
888729f5ecSAllan Jude 	    "(<disk>|<sesid>|all) (on|off)",
898729f5ecSAllan Jude 	    "Change the state of the locate LED associated with a disk",
908729f5ecSAllan Jude 	    locate },
918729f5ecSAllan Jude 	{ "map", "",
928729f5ecSAllan Jude 	    "Print a map of the devices managed by the enclosure", objmap } ,
938ad16e55SEdward Tomasz Napierala 	{ "show", "",
948ad16e55SEdward Tomasz Napierala 	    "Print a human-friendly summary of the enclosure", show } ,
958729f5ecSAllan Jude 	{ "status", "", "Print the status of the enclosure",
968729f5ecSAllan Jude 	    encstatus },
97cddcb259SBaptiste Daroussin };
98cddcb259SBaptiste Daroussin 
99cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds);
1008729f5ecSAllan Jude static const char *uflag;
101cddcb259SBaptiste Daroussin 
102cddcb259SBaptiste Daroussin static void
1038729f5ecSAllan Jude usage(FILE *out, const char *subcmd)
1048729f5ecSAllan Jude {
1058729f5ecSAllan Jude 	int i;
1068729f5ecSAllan Jude 
1078729f5ecSAllan Jude 	if (subcmd == NULL) {
1088729f5ecSAllan Jude 		fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n",
1098729f5ecSAllan Jude 		    getprogname());
1108729f5ecSAllan Jude 		fprintf(out, "Commands supported:\n");
1118729f5ecSAllan Jude 	}
1128729f5ecSAllan Jude 	for (i = 0; i < nbcmds; i++) {
1138729f5ecSAllan Jude 		if (subcmd != NULL) {
1148729f5ecSAllan Jude 			if (strcmp(subcmd, cmds[i].name) == 0) {
1158729f5ecSAllan Jude 				fprintf(out, "Usage: %s %s [-u /dev/ses<N>] "
1168729f5ecSAllan Jude 				    "%s\n\t%s\n", getprogname(), subcmd,
1178729f5ecSAllan Jude 				    cmds[i].param, cmds[i].desc);
1188729f5ecSAllan Jude 				break;
1198729f5ecSAllan Jude 			}
1208729f5ecSAllan Jude 			continue;
1218729f5ecSAllan Jude 		}
1228729f5ecSAllan Jude 		fprintf(out, "    %-12s%s\n\t\t%s\n\n", cmds[i].name,
1238729f5ecSAllan Jude 		    cmds[i].param, cmds[i].desc);
1248729f5ecSAllan Jude 	}
1258729f5ecSAllan Jude 
1268729f5ecSAllan Jude 	exit(EXIT_FAILURE);
1278729f5ecSAllan Jude }
1288729f5ecSAllan Jude 
1298729f5ecSAllan Jude static void
130fe74eaabSAlexander Motin do_led(int fd, unsigned int idx, elm_type_t type, bool onoff, bool setfault)
131cddcb259SBaptiste Daroussin {
132fe74eaabSAlexander Motin 	int state = onoff ? 1 : 0;
133cddcb259SBaptiste Daroussin 	encioc_elm_status_t o;
134fe74eaabSAlexander Motin 	struct ses_ctrl_dev_slot *slot;
135cddcb259SBaptiste Daroussin 
136cddcb259SBaptiste Daroussin 	o.elm_idx = idx;
137cddcb259SBaptiste Daroussin 	if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) {
138cddcb259SBaptiste Daroussin 		close(fd);
139d25c1ff6SBaptiste Daroussin 		xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
140cddcb259SBaptiste Daroussin 	}
1412e19fae4SAlexander Motin 	ses_status_to_ctrl(type, &o.cstat[0]);
142fe74eaabSAlexander Motin 	switch (type) {
143fe74eaabSAlexander Motin 	case ELMTYP_DEVICE:
144fe74eaabSAlexander Motin 	case ELMTYP_ARRAY_DEV:
1452e19fae4SAlexander Motin 		slot = (struct ses_ctrl_dev_slot *) &o.cstat[0];
146fe74eaabSAlexander Motin 		ses_ctrl_common_set_select(&slot->common, 1);
147fe74eaabSAlexander Motin 		if (setfault)
148fe74eaabSAlexander Motin 			ses_ctrl_dev_slot_set_rqst_fault(slot, state);
149efab8bfdSAlexander Motin 		else
150fe74eaabSAlexander Motin 			ses_ctrl_dev_slot_set_rqst_ident(slot, state);
151fe74eaabSAlexander Motin 		break;
152fe74eaabSAlexander Motin 	default:
153fe74eaabSAlexander Motin 		return;
1548729f5ecSAllan Jude 	}
155cddcb259SBaptiste Daroussin 	if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
156cddcb259SBaptiste Daroussin 		close(fd);
157d25c1ff6SBaptiste Daroussin 		xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT");
158cddcb259SBaptiste Daroussin 	}
159cddcb259SBaptiste Daroussin }
160cddcb259SBaptiste Daroussin 
161cddcb259SBaptiste Daroussin static bool
162cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len)
163cddcb259SBaptiste Daroussin {
1641bc54324SBaptiste Daroussin 	const char *dname;
165cddcb259SBaptiste Daroussin 
1661bc54324SBaptiste Daroussin 	dname = devnames;
1671bc54324SBaptiste Daroussin 	while ((dname = strstr(dname, disk)) != NULL) {
1688729f5ecSAllan Jude 		if (dname[len] == '\0' || dname[len] == ',') {
169cddcb259SBaptiste Daroussin 			return (true);
1708729f5ecSAllan Jude 		}
1711bc54324SBaptiste Daroussin 		dname++;
172cddcb259SBaptiste Daroussin 	}
1738729f5ecSAllan Jude 
174cddcb259SBaptiste Daroussin 	return (false);
175cddcb259SBaptiste Daroussin }
176cddcb259SBaptiste Daroussin 
177cddcb259SBaptiste Daroussin static int
1786af5d161SAllan Jude sesled(int argc, char **argv, bool setfault)
179cddcb259SBaptiste Daroussin {
180cddcb259SBaptiste Daroussin 	encioc_elm_devnames_t objdn;
181cddcb259SBaptiste Daroussin 	encioc_element_t *objp;
182cddcb259SBaptiste Daroussin 	glob_t g;
1838729f5ecSAllan Jude 	char *disk, *endptr;
1848729f5ecSAllan Jude 	size_t len, i, ndisks;
1858729f5ecSAllan Jude 	int fd;
1868729f5ecSAllan Jude 	unsigned int nobj, j, sesid;
1878729f5ecSAllan Jude 	bool all, isses, onoff;
188cddcb259SBaptiste Daroussin 
1898729f5ecSAllan Jude 	isses = false;
1908729f5ecSAllan Jude 	all = false;
1918729f5ecSAllan Jude 	onoff = false;
1928729f5ecSAllan Jude 
1938729f5ecSAllan Jude 	if (argc != 3) {
1946af5d161SAllan Jude 		usage(stderr, (setfault ? "fault" : "locate"));
195cddcb259SBaptiste Daroussin 	}
196cddcb259SBaptiste Daroussin 
1978729f5ecSAllan Jude 	disk = argv[1];
198cddcb259SBaptiste Daroussin 
1998729f5ecSAllan Jude 	sesid = strtoul(disk, &endptr, 10);
2008729f5ecSAllan Jude 	if (*endptr == '\0') {
2018729f5ecSAllan Jude 		endptr = strrchr(uflag, '*');
20296e6c444SBaptiste Daroussin 		if (endptr != NULL && *endptr == '*') {
203d25c1ff6SBaptiste Daroussin 			xo_warnx("Must specifying a SES device (-u) to use a SES "
2048729f5ecSAllan Jude 			    "id# to identify a disk");
2056af5d161SAllan Jude 			usage(stderr, (setfault ? "fault" : "locate"));
2068729f5ecSAllan Jude 		}
2078729f5ecSAllan Jude 		isses = true;
2088729f5ecSAllan Jude 	}
2098729f5ecSAllan Jude 
2108729f5ecSAllan Jude 	if (strcmp(argv[2], "on") == 0) {
2114569e7cfSBaptiste Daroussin 		onoff = true;
2128729f5ecSAllan Jude 	} else if (strcmp(argv[2], "off") == 0) {
2134569e7cfSBaptiste Daroussin 		onoff = false;
214cddcb259SBaptiste Daroussin 	} else {
2156af5d161SAllan Jude 		usage(stderr, (setfault ? "fault" : "locate"));
216cddcb259SBaptiste Daroussin 	}
217cddcb259SBaptiste Daroussin 
218cddcb259SBaptiste Daroussin 	if (strcmp(disk, "all") == 0) {
219cddcb259SBaptiste Daroussin 		all = true;
220cddcb259SBaptiste Daroussin 	}
221cddcb259SBaptiste Daroussin 	len = strlen(disk);
222cddcb259SBaptiste Daroussin 
223cddcb259SBaptiste Daroussin 	/* Get the list of ses devices */
2248729f5ecSAllan Jude 	if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) ==
2258729f5ecSAllan Jude 	    GLOB_NOMATCH) {
2268729f5ecSAllan Jude 		globfree(&g);
227d25c1ff6SBaptiste Daroussin 		xo_errx(EXIT_FAILURE, "No SES devices found");
2288729f5ecSAllan Jude 	}
2298729f5ecSAllan Jude 
2308729f5ecSAllan Jude 	ndisks = 0;
2318729f5ecSAllan Jude 	for (i = 0; i < g.gl_pathc; i++) {
2328729f5ecSAllan Jude 		/* ensure we only got numbers after ses */
2338729f5ecSAllan Jude 		if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
2348729f5ecSAllan Jude 		    strlen(g.gl_pathv[i] + 8)) {
2358729f5ecSAllan Jude 			continue;
2368729f5ecSAllan Jude 		}
2378729f5ecSAllan Jude 		if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
2388729f5ecSAllan Jude 			/*
2398729f5ecSAllan Jude 			 * Don't treat non-access errors as critical if we are
2408729f5ecSAllan Jude 			 * accessing all devices
2418729f5ecSAllan Jude 			 */
2428729f5ecSAllan Jude 			if (errno == EACCES && g.gl_pathc > 1) {
243d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "unable to access SES device");
2448729f5ecSAllan Jude 			}
245d25c1ff6SBaptiste Daroussin 			xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
2468729f5ecSAllan Jude 			continue;
2478729f5ecSAllan Jude 		}
2488729f5ecSAllan Jude 
2498729f5ecSAllan Jude 		if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
2508729f5ecSAllan Jude 			close(fd);
251d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
2528729f5ecSAllan Jude 		}
2538729f5ecSAllan Jude 
2548729f5ecSAllan Jude 		objp = calloc(nobj, sizeof(encioc_element_t));
2558729f5ecSAllan Jude 		if (objp == NULL) {
2568729f5ecSAllan Jude 			close(fd);
257d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "calloc()");
2588729f5ecSAllan Jude 		}
2598729f5ecSAllan Jude 
2608729f5ecSAllan Jude 		if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) {
261a221b104SAlan Somers 			free(objp);
2628729f5ecSAllan Jude 			close(fd);
263d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
2648729f5ecSAllan Jude 		}
2658729f5ecSAllan Jude 
2668729f5ecSAllan Jude 		if (isses) {
267691a834cSAlan Somers 			if (sesid >= nobj) {
268a221b104SAlan Somers 				free(objp);
2698729f5ecSAllan Jude 				close(fd);
270d25c1ff6SBaptiste Daroussin 				xo_errx(EXIT_FAILURE,
2718729f5ecSAllan Jude 				     "Requested SES ID does not exist");
2728729f5ecSAllan Jude 			}
273fe74eaabSAlexander Motin 			do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault);
2748729f5ecSAllan Jude 			ndisks++;
275a221b104SAlan Somers 			free(objp);
2768729f5ecSAllan Jude 			close(fd);
2778729f5ecSAllan Jude 			break;
2788729f5ecSAllan Jude 		}
2798729f5ecSAllan Jude 		for (j = 0; j < nobj; j++) {
2809f96f106SAlan Somers 			const int devnames_size = 128;
2819f96f106SAlan Somers 			char devnames[devnames_size];
2829f96f106SAlan Somers 
28324ffc649SAllan Jude 			if (all) {
284fe74eaabSAlexander Motin 				do_led(fd, objp[j].elm_idx, objp[j].elm_type,
285fe74eaabSAlexander Motin 				    onoff, setfault);
28624ffc649SAllan Jude 				continue;
28724ffc649SAllan Jude 			}
2888729f5ecSAllan Jude 			memset(&objdn, 0, sizeof(objdn));
2899f96f106SAlan Somers 			memset(devnames, 0, devnames_size);
2908729f5ecSAllan Jude 			objdn.elm_idx = objp[j].elm_idx;
2919f96f106SAlan Somers 			objdn.elm_names_size = devnames_size;
2929f96f106SAlan Somers 			objdn.elm_devnames = devnames;
2938729f5ecSAllan Jude 			if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
2948729f5ecSAllan Jude 			    (caddr_t) &objdn) <0) {
2958729f5ecSAllan Jude 				continue;
2968729f5ecSAllan Jude 			}
2978729f5ecSAllan Jude 			if (objdn.elm_names_len > 0) {
2988729f5ecSAllan Jude 				if (disk_match(objdn.elm_devnames, disk, len)) {
299fe74eaabSAlexander Motin 					do_led(fd, objdn.elm_idx, objp[j].elm_type,
3006af5d161SAllan Jude 					    onoff, setfault);
3018729f5ecSAllan Jude 					ndisks++;
3028729f5ecSAllan Jude 					break;
3038729f5ecSAllan Jude 				}
3048729f5ecSAllan Jude 			}
3058729f5ecSAllan Jude 		}
306f734685eSBaptiste Daroussin 		free(objp);
3078729f5ecSAllan Jude 		close(fd);
3088729f5ecSAllan Jude 	}
3098729f5ecSAllan Jude 	globfree(&g);
3108729f5ecSAllan Jude 	if (ndisks == 0 && all == false) {
311d25c1ff6SBaptiste Daroussin 		xo_errx(EXIT_FAILURE, "Count not find the SES id of device '%s'",
3128729f5ecSAllan Jude 		    disk);
3138729f5ecSAllan Jude 	}
3148729f5ecSAllan Jude 
3158729f5ecSAllan Jude 	return (EXIT_SUCCESS);
3168729f5ecSAllan Jude }
3178729f5ecSAllan Jude 
3188729f5ecSAllan Jude static int
3198729f5ecSAllan Jude locate(int argc, char **argv)
3208729f5ecSAllan Jude {
3218729f5ecSAllan Jude 
3228729f5ecSAllan Jude 	return (sesled(argc, argv, false));
3238729f5ecSAllan Jude }
3248729f5ecSAllan Jude 
3258729f5ecSAllan Jude static int
3268729f5ecSAllan Jude fault(int argc, char **argv)
3278729f5ecSAllan Jude {
3288729f5ecSAllan Jude 
3298729f5ecSAllan Jude 	return (sesled(argc, argv, true));
3308729f5ecSAllan Jude }
3318729f5ecSAllan Jude 
33220a957e3SBaptiste Daroussin static void
3338ad16e55SEdward Tomasz Napierala sesutil_print(int *style, const char *fmt, ...)
33420a957e3SBaptiste Daroussin {
33520a957e3SBaptiste Daroussin 	va_list args;
33620a957e3SBaptiste Daroussin 
3378ad16e55SEdward Tomasz Napierala 	if (*style == PRINT_STYLE_DASHED) {
338d25c1ff6SBaptiste Daroussin 		xo_open_container("extra_status");
339d25c1ff6SBaptiste Daroussin 		xo_emit("\t\tExtra status:\n");
3408ad16e55SEdward Tomasz Napierala 		*style = PRINT_STYLE_DASHED_2;
3418ad16e55SEdward Tomasz Napierala 	} else if (*style == PRINT_STYLE_CSV) {
3428ad16e55SEdward Tomasz Napierala 		xo_open_container("extra_status");
3438ad16e55SEdward Tomasz Napierala 		*style = PRINT_STYLE_CSV_2;
34420a957e3SBaptiste Daroussin 	}
3458ad16e55SEdward Tomasz Napierala 
3468ad16e55SEdward Tomasz Napierala 	if (*style == PRINT_STYLE_DASHED_2)
3478ad16e55SEdward Tomasz Napierala 		xo_emit("\t\t- ");
3488ad16e55SEdward Tomasz Napierala 	else if (*style == PRINT_STYLE_CSV_2)
3498ad16e55SEdward Tomasz Napierala 		xo_emit(", ");
35020a957e3SBaptiste Daroussin 	va_start(args, fmt);
351d25c1ff6SBaptiste Daroussin 	xo_emit_hv(NULL, fmt, args);
35220a957e3SBaptiste Daroussin 	va_end(args);
3538ad16e55SEdward Tomasz Napierala 	if (*style == PRINT_STYLE_DASHED_2)
3548ad16e55SEdward Tomasz Napierala 		xo_emit("\n");
35520a957e3SBaptiste Daroussin }
35620a957e3SBaptiste Daroussin 
35720a957e3SBaptiste Daroussin static void
3588ad16e55SEdward Tomasz Napierala print_extra_status(int eletype, u_char *cstat, int style)
35920a957e3SBaptiste Daroussin {
36020a957e3SBaptiste Daroussin 
36120a957e3SBaptiste Daroussin 	if (cstat[0] & 0x40) {
3628ad16e55SEdward Tomasz Napierala 		sesutil_print(&style, "{e:predicted_failure/true} Predicted Failure");
36320a957e3SBaptiste Daroussin 	}
36420a957e3SBaptiste Daroussin 	if (cstat[0] & 0x20) {
3658ad16e55SEdward Tomasz Napierala 		sesutil_print(&style, "{e:disabled/true} Disabled");
36620a957e3SBaptiste Daroussin 	}
36720a957e3SBaptiste Daroussin 	if (cstat[0] & 0x10) {
3688ad16e55SEdward Tomasz Napierala 		sesutil_print(&style, "{e:swapped/true} Swapped");
36920a957e3SBaptiste Daroussin 	}
37020a957e3SBaptiste Daroussin 	switch (eletype) {
37120a957e3SBaptiste Daroussin 	case ELMTYP_DEVICE:
37220a957e3SBaptiste Daroussin 	case ELMTYP_ARRAY_DEV:
37320a957e3SBaptiste Daroussin 		if (cstat[2] & 0x02) {
3748ad16e55SEdward Tomasz Napierala 			sesutil_print(&style, "LED={q:led/locate}");
37520a957e3SBaptiste Daroussin 		}
37620a957e3SBaptiste Daroussin 		if (cstat[2] & 0x20) {
3778ad16e55SEdward Tomasz Napierala 			sesutil_print(&style, "LED={q:led/fault}");
37820a957e3SBaptiste Daroussin 		}
37920a957e3SBaptiste Daroussin 		break;
38020a957e3SBaptiste Daroussin 	case ELMTYP_FAN:
3818ad16e55SEdward Tomasz Napierala 		sesutil_print(&style, "Speed: {:speed/%d}{Uw:rpm}",
38220a957e3SBaptiste Daroussin 		    (((0x7 & cstat[1]) << 8) + cstat[2]) * 10);
38320a957e3SBaptiste Daroussin 		break;
38420a957e3SBaptiste Daroussin 	case ELMTYP_THERM:
38520a957e3SBaptiste Daroussin 		if (cstat[2]) {
3868ad16e55SEdward Tomasz Napierala 			sesutil_print(&style, "Temperature: {:temperature/%d}{Uw:C}",
38720a957e3SBaptiste Daroussin 			    cstat[2] - TEMPERATURE_OFFSET);
38820a957e3SBaptiste Daroussin 		} else {
3898ad16e55SEdward Tomasz Napierala 			sesutil_print(&style, "Temperature: -{q:temperature/reserved}");
39020a957e3SBaptiste Daroussin 		}
39120a957e3SBaptiste Daroussin 		break;
39220a957e3SBaptiste Daroussin 	case ELMTYP_VOM:
3938ad16e55SEdward Tomasz Napierala 		sesutil_print(&style, "Voltage: {:voltage/%.2f}{Uw:V}",
39420a957e3SBaptiste Daroussin 		    be16dec(cstat + 2) / 100.0);
39520a957e3SBaptiste Daroussin 		break;
39620a957e3SBaptiste Daroussin 	}
3978ad16e55SEdward Tomasz Napierala 	if (style) {
398d25c1ff6SBaptiste Daroussin 		xo_close_container("extra_status");
399d25c1ff6SBaptiste Daroussin 	}
40020a957e3SBaptiste Daroussin }
40120a957e3SBaptiste Daroussin 
4028729f5ecSAllan Jude static int
4038729f5ecSAllan Jude objmap(int argc, char **argv __unused)
4048729f5ecSAllan Jude {
40560f46640SBaptiste Daroussin 	encioc_string_t stri;
4068729f5ecSAllan Jude 	encioc_elm_devnames_t e_devname;
4078729f5ecSAllan Jude 	encioc_elm_status_t e_status;
4088729f5ecSAllan Jude 	encioc_elm_desc_t e_desc;
4098729f5ecSAllan Jude 	encioc_element_t *e_ptr;
4108729f5ecSAllan Jude 	glob_t g;
4118729f5ecSAllan Jude 	int fd;
4128729f5ecSAllan Jude 	unsigned int j, nobj;
4138729f5ecSAllan Jude 	size_t i;
41460f46640SBaptiste Daroussin 	char str[32];
4158729f5ecSAllan Jude 
4168729f5ecSAllan Jude 	if (argc != 1) {
4178729f5ecSAllan Jude 		usage(stderr, "map");
4188729f5ecSAllan Jude 	}
4198729f5ecSAllan Jude 
4208729f5ecSAllan Jude 	/* Get the list of ses devices */
4218729f5ecSAllan Jude 	if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
422cddcb259SBaptiste Daroussin 		globfree(&g);
423d25c1ff6SBaptiste Daroussin 		xo_errx(EXIT_FAILURE, "No SES devices found");
424cddcb259SBaptiste Daroussin 	}
425d25c1ff6SBaptiste Daroussin 	xo_set_version(SESUTIL_XO_VERSION);
426d25c1ff6SBaptiste Daroussin 	xo_open_container("sesutil");
427d25c1ff6SBaptiste Daroussin 	xo_open_list("enclosures");
428cddcb259SBaptiste Daroussin 	for (i = 0; i < g.gl_pathc; i++) {
429cddcb259SBaptiste Daroussin 		/* ensure we only got numbers after ses */
430cddcb259SBaptiste Daroussin 		if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
4318729f5ecSAllan Jude 		    strlen(g.gl_pathv[i] + 8)) {
432cddcb259SBaptiste Daroussin 			continue;
4338729f5ecSAllan Jude 		}
434cddcb259SBaptiste Daroussin 		if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
4358729f5ecSAllan Jude 			/*
4368729f5ecSAllan Jude 			 * Don't treat non-access errors as critical if we are
4378729f5ecSAllan Jude 			 * accessing all devices
4388729f5ecSAllan Jude 			 */
4398729f5ecSAllan Jude 			if (errno == EACCES && g.gl_pathc > 1) {
440d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "unable to access SES device");
4418729f5ecSAllan Jude 			}
442d25c1ff6SBaptiste Daroussin 			xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
4438729f5ecSAllan Jude 			continue;
444cddcb259SBaptiste Daroussin 		}
445cddcb259SBaptiste Daroussin 
4468729f5ecSAllan Jude 		if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
4478729f5ecSAllan Jude 			close(fd);
448d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
4498729f5ecSAllan Jude 		}
450cddcb259SBaptiste Daroussin 
4518729f5ecSAllan Jude 		e_ptr = calloc(nobj, sizeof(encioc_element_t));
4528729f5ecSAllan Jude 		if (e_ptr == NULL) {
4538729f5ecSAllan Jude 			close(fd);
454d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "calloc()");
4558729f5ecSAllan Jude 		}
456cddcb259SBaptiste Daroussin 
4578729f5ecSAllan Jude 		if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) {
4588729f5ecSAllan Jude 			close(fd);
459d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
4608729f5ecSAllan Jude 		}
461cddcb259SBaptiste Daroussin 
462d25c1ff6SBaptiste Daroussin 		xo_open_instance("enclosures");
463d25c1ff6SBaptiste Daroussin 		xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5);
46460f46640SBaptiste Daroussin 		stri.bufsiz = sizeof(str);
46560f46640SBaptiste Daroussin 		stri.buf = &str[0];
46660f46640SBaptiste Daroussin 		if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0)
467d25c1ff6SBaptiste Daroussin 			xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf);
46860f46640SBaptiste Daroussin 		stri.bufsiz = sizeof(str);
46960f46640SBaptiste Daroussin 		stri.buf = &str[0];
47060f46640SBaptiste Daroussin 		if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0)
471d25c1ff6SBaptiste Daroussin 			xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf);
47260f46640SBaptiste Daroussin 
473d25c1ff6SBaptiste Daroussin 		xo_open_list("elements");
474cddcb259SBaptiste Daroussin 		for (j = 0; j < nobj; j++) {
4758729f5ecSAllan Jude 			/* Get the status of the element */
4768729f5ecSAllan Jude 			memset(&e_status, 0, sizeof(e_status));
4778729f5ecSAllan Jude 			e_status.elm_idx = e_ptr[j].elm_idx;
4788729f5ecSAllan Jude 			if (ioctl(fd, ENCIOC_GETELMSTAT,
4798729f5ecSAllan Jude 			    (caddr_t) &e_status) < 0) {
4808729f5ecSAllan Jude 				close(fd);
481d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
4828729f5ecSAllan Jude 			}
4838729f5ecSAllan Jude 			/* Get the description of the element */
4848729f5ecSAllan Jude 			memset(&e_desc, 0, sizeof(e_desc));
4858729f5ecSAllan Jude 			e_desc.elm_idx = e_ptr[j].elm_idx;
4868729f5ecSAllan Jude 			e_desc.elm_desc_len = UINT16_MAX;
4878729f5ecSAllan Jude 			e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
4888729f5ecSAllan Jude 			if (e_desc.elm_desc_str == NULL) {
4898729f5ecSAllan Jude 				close(fd);
490d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "calloc()");
4918729f5ecSAllan Jude 			}
4928729f5ecSAllan Jude 			if (ioctl(fd, ENCIOC_GETELMDESC,
4938729f5ecSAllan Jude 			    (caddr_t) &e_desc) < 0) {
4948729f5ecSAllan Jude 				close(fd);
495d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC");
4968729f5ecSAllan Jude 			}
4978729f5ecSAllan Jude 			/* Get the device name(s) of the element */
4988729f5ecSAllan Jude 			memset(&e_devname, 0, sizeof(e_devname));
4998729f5ecSAllan Jude 			e_devname.elm_idx = e_ptr[j].elm_idx;
5008729f5ecSAllan Jude 			e_devname.elm_names_size = 128;
5018729f5ecSAllan Jude 			e_devname.elm_devnames = calloc(128, sizeof(char));
5028729f5ecSAllan Jude 			if (e_devname.elm_devnames == NULL) {
5038729f5ecSAllan Jude 				close(fd);
504d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "calloc()");
5058729f5ecSAllan Jude 			}
506cddcb259SBaptiste Daroussin 			if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
5078729f5ecSAllan Jude 			    (caddr_t) &e_devname) <0) {
50818acbeb3SAlan Somers 				/* Continue even if we can't look up devnames */
5098729f5ecSAllan Jude 				e_devname.elm_devnames[0] = '\0';
510cddcb259SBaptiste Daroussin 			}
511d25c1ff6SBaptiste Daroussin 			xo_open_instance("elements");
512d25c1ff6SBaptiste Daroussin 			xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx,
5138729f5ecSAllan Jude 			    geteltnm(e_ptr[j].elm_type));
514d25c1ff6SBaptiste Daroussin 			xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n",
515d7654478SBaptiste Daroussin 			    scode2ascii(e_status.cstat[0]), e_status.cstat[0],
516d7654478SBaptiste Daroussin 			    e_status.cstat[1], e_status.cstat[2],
517d7654478SBaptiste Daroussin 			    e_status.cstat[3]);
5188729f5ecSAllan Jude 			if (e_desc.elm_desc_len > 0) {
519d25c1ff6SBaptiste Daroussin 				xo_emit("\t\tDescription: {:description/%s}\n",
5208729f5ecSAllan Jude 				    e_desc.elm_desc_str);
521cddcb259SBaptiste Daroussin 			}
5228729f5ecSAllan Jude 			if (e_devname.elm_names_len > 0) {
523d25c1ff6SBaptiste Daroussin 				xo_emit("\t\tDevice Names: {:device_names/%s}\n",
5248729f5ecSAllan Jude 				    e_devname.elm_devnames);
525cddcb259SBaptiste Daroussin 			}
5268ad16e55SEdward Tomasz Napierala 			print_extra_status(e_ptr[j].elm_type, e_status.cstat, PRINT_STYLE_DASHED);
527d25c1ff6SBaptiste Daroussin 			xo_close_instance("elements");
528*09f29b03SAlan Somers 			free(e_desc.elm_desc_str);
5298729f5ecSAllan Jude 			free(e_devname.elm_devnames);
530cddcb259SBaptiste Daroussin 		}
531d25c1ff6SBaptiste Daroussin 		xo_close_list("elements");
532f734685eSBaptiste Daroussin 		free(e_ptr);
533cddcb259SBaptiste Daroussin 		close(fd);
534cddcb259SBaptiste Daroussin 	}
535cddcb259SBaptiste Daroussin 	globfree(&g);
536d25c1ff6SBaptiste Daroussin 	xo_close_list("enclosures");
537d25c1ff6SBaptiste Daroussin 	xo_close_container("sesutil");
538d25c1ff6SBaptiste Daroussin 	xo_finish();
539cddcb259SBaptiste Daroussin 
540cddcb259SBaptiste Daroussin 	return (EXIT_SUCCESS);
541cddcb259SBaptiste Daroussin }
542cddcb259SBaptiste Daroussin 
5438ad16e55SEdward Tomasz Napierala /*
5448ad16e55SEdward Tomasz Napierala  * Get rid of the 'passN' devices, unless there's nothing else to show.
5458ad16e55SEdward Tomasz Napierala  */
5468ad16e55SEdward Tomasz Napierala static void
5478ad16e55SEdward Tomasz Napierala skip_pass_devices(char *devnames, size_t devnameslen)
5488ad16e55SEdward Tomasz Napierala {
5498ad16e55SEdward Tomasz Napierala 	char *dev, devs[128], passes[128], *tmp;
5508ad16e55SEdward Tomasz Napierala 
5518ad16e55SEdward Tomasz Napierala 	devs[0] = passes[0] = '\0';
5528ad16e55SEdward Tomasz Napierala 	tmp = devnames;
5538ad16e55SEdward Tomasz Napierala 
5548ad16e55SEdward Tomasz Napierala 	while ((dev = strsep(&tmp, ",")) != NULL) {
5558ad16e55SEdward Tomasz Napierala 		if (strncmp(dev, "pass", 4) == 0) {
5568ad16e55SEdward Tomasz Napierala 			if (passes[0] != '\0')
5578ad16e55SEdward Tomasz Napierala 				strlcat(passes, ",", sizeof(passes));
5588ad16e55SEdward Tomasz Napierala 			strlcat(passes, dev, sizeof(passes));
5598ad16e55SEdward Tomasz Napierala 		} else {
5608ad16e55SEdward Tomasz Napierala 			if (devs[0] != '\0')
5618ad16e55SEdward Tomasz Napierala 				strlcat(devs, ",", sizeof(devs));
5628ad16e55SEdward Tomasz Napierala 			strlcat(devs, dev, sizeof(devs));
5638ad16e55SEdward Tomasz Napierala 		}
5648ad16e55SEdward Tomasz Napierala 	}
5658ad16e55SEdward Tomasz Napierala 	strlcpy(devnames, devs, devnameslen);
5668ad16e55SEdward Tomasz Napierala 	if (devnames[0] == '\0')
5678ad16e55SEdward Tomasz Napierala 		strlcpy(devnames, passes, devnameslen);
5688ad16e55SEdward Tomasz Napierala }
5698ad16e55SEdward Tomasz Napierala 
5708ad16e55SEdward Tomasz Napierala static void
5718ad16e55SEdward Tomasz Napierala fetch_device_details(char *devnames, char **model, char **serial, off_t *size)
5728ad16e55SEdward Tomasz Napierala {
5738ad16e55SEdward Tomasz Napierala 	char ident[DISK_IDENT_SIZE];
5748ad16e55SEdward Tomasz Napierala 	struct diocgattr_arg arg;
575f05cc0f1SAlan Somers 	char *tmp;
5768ad16e55SEdward Tomasz Napierala 	off_t mediasize;
577f05cc0f1SAlan Somers 	int comma;
5788ad16e55SEdward Tomasz Napierala 	int fd;
5798ad16e55SEdward Tomasz Napierala 
580f05cc0f1SAlan Somers 	comma = (int)strcspn(devnames, ",");
581f05cc0f1SAlan Somers 	asprintf(&tmp, "/dev/%.*s", comma, devnames);
5828ad16e55SEdward Tomasz Napierala 	if (tmp == NULL)
583f05cc0f1SAlan Somers 		err(1, "asprintf");
5848ad16e55SEdward Tomasz Napierala 	fd = open(tmp, O_RDONLY);
585f05cc0f1SAlan Somers 	free(tmp);
5868ad16e55SEdward Tomasz Napierala 	if (fd < 0) {
5878ad16e55SEdward Tomasz Napierala 		/*
5888ad16e55SEdward Tomasz Napierala 		 * This can happen with a disk so broken it cannot
5898ad16e55SEdward Tomasz Napierala 		 * be probed by GEOM.
5908ad16e55SEdward Tomasz Napierala 		 */
5918ad16e55SEdward Tomasz Napierala 		*model = strdup("?");
5928ad16e55SEdward Tomasz Napierala 		*serial = strdup("?");
5938ad16e55SEdward Tomasz Napierala 		*size = -1;
594f05cc0f1SAlan Somers 		close(fd);
5958ad16e55SEdward Tomasz Napierala 		return;
5968ad16e55SEdward Tomasz Napierala 	}
5978ad16e55SEdward Tomasz Napierala 
5988ad16e55SEdward Tomasz Napierala 	strlcpy(arg.name, "GEOM::descr", sizeof(arg.name));
5998ad16e55SEdward Tomasz Napierala 	arg.len = sizeof(arg.value.str);
6008ad16e55SEdward Tomasz Napierala 	if (ioctl(fd, DIOCGATTR, &arg) == 0)
6018ad16e55SEdward Tomasz Napierala 		*model = strdup(arg.value.str);
6028ad16e55SEdward Tomasz Napierala 	else
6038ad16e55SEdward Tomasz Napierala 		*model = NULL;
6048ad16e55SEdward Tomasz Napierala 
6058ad16e55SEdward Tomasz Napierala 	if (ioctl(fd, DIOCGIDENT, ident) == 0)
6068ad16e55SEdward Tomasz Napierala 		*serial = strdup(ident);
6078ad16e55SEdward Tomasz Napierala 	else
6088ad16e55SEdward Tomasz Napierala 		*serial = NULL;
6098ad16e55SEdward Tomasz Napierala 
6108ad16e55SEdward Tomasz Napierala 	if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0)
6118ad16e55SEdward Tomasz Napierala 		*size = mediasize;
6128ad16e55SEdward Tomasz Napierala 	else
6138ad16e55SEdward Tomasz Napierala 		*size = -1;
614f05cc0f1SAlan Somers 	close(fd);
6158ad16e55SEdward Tomasz Napierala }
6168ad16e55SEdward Tomasz Napierala 
6178ad16e55SEdward Tomasz Napierala static void
6188ad16e55SEdward Tomasz Napierala show_device(int fd, int elm_idx, encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6198ad16e55SEdward Tomasz Napierala {
6208ad16e55SEdward Tomasz Napierala 	encioc_elm_devnames_t e_devname;
621*09f29b03SAlan Somers 	char *model = NULL, *serial = NULL;
6228ad16e55SEdward Tomasz Napierala 	off_t size;
6238ad16e55SEdward Tomasz Napierala 
6248ad16e55SEdward Tomasz Napierala 	/* Get the device name(s) of the element */
6258ad16e55SEdward Tomasz Napierala 	memset(&e_devname, 0, sizeof(e_devname));
6268ad16e55SEdward Tomasz Napierala 	e_devname.elm_idx = elm_idx;
6278ad16e55SEdward Tomasz Napierala 	e_devname.elm_names_size = 128;
6288ad16e55SEdward Tomasz Napierala 	e_devname.elm_devnames = calloc(128, sizeof(char));
6298ad16e55SEdward Tomasz Napierala 	if (e_devname.elm_devnames == NULL) {
6308ad16e55SEdward Tomasz Napierala 		close(fd);
6318ad16e55SEdward Tomasz Napierala 		xo_err(EXIT_FAILURE, "calloc()");
6328ad16e55SEdward Tomasz Napierala 	}
6338ad16e55SEdward Tomasz Napierala 
6348ad16e55SEdward Tomasz Napierala 	if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
6358ad16e55SEdward Tomasz Napierala 	    (caddr_t) &e_devname) < 0) {
6368ad16e55SEdward Tomasz Napierala 		/* We don't care if this fails */
6378ad16e55SEdward Tomasz Napierala 		e_devname.elm_devnames[0] = '\0';
6388ad16e55SEdward Tomasz Napierala 		size = -1;
6398ad16e55SEdward Tomasz Napierala 	} else {
6408ad16e55SEdward Tomasz Napierala 		skip_pass_devices(e_devname.elm_devnames, 128);
6418ad16e55SEdward Tomasz Napierala 		fetch_device_details(e_devname.elm_devnames, &model, &serial, &size);
6428ad16e55SEdward Tomasz Napierala 	}
6438ad16e55SEdward Tomasz Napierala 	xo_open_instance("elements");
6448ad16e55SEdward Tomasz Napierala 	xo_emit("{e:type/device_slot}");
64579f38143SPoul-Henning Kamp 	xo_emit("{d:description/%-15s} ", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "-");
64679f38143SPoul-Henning Kamp 	xo_emit("{e:description/%-15s}", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "");
6478ad16e55SEdward Tomasz Napierala 	xo_emit("{d:device_names/%-7s} ", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "-");
6488ad16e55SEdward Tomasz Napierala 	xo_emit("{e:device_names/%s}", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "");
6498ad16e55SEdward Tomasz Napierala 	xo_emit("{d:model/%-25s} ", model ? model : "-");
6508ad16e55SEdward Tomasz Napierala 	xo_emit("{e:model/%s}", model ? model : "");
6518ad16e55SEdward Tomasz Napierala 	xo_emit("{d:serial/%-20s} ", serial != NULL ? serial : "-");
6528ad16e55SEdward Tomasz Napierala 	xo_emit("{e:serial/%s}", serial != NULL ? serial : "");
653a1571967SEdward Tomasz Napierala 	if ((e_status.cstat[0] & 0xf) == SES_OBJSTAT_OK && size >= 0) {
6548ad16e55SEdward Tomasz Napierala 		xo_emit("{h,hn-1000:size/%ld}{e:status/%s}",
6558ad16e55SEdward Tomasz Napierala 		    size, scode2ascii(e_status.cstat[0]));
6568ad16e55SEdward Tomasz Napierala 	} else {
6578ad16e55SEdward Tomasz Napierala 		xo_emit("{:status/%s}", scode2ascii(e_status.cstat[0]));
6588ad16e55SEdward Tomasz Napierala 	}
6598ad16e55SEdward Tomasz Napierala 	print_extra_status(ELMTYP_ARRAY_DEV, e_status.cstat, PRINT_STYLE_CSV);
6608ad16e55SEdward Tomasz Napierala 	xo_emit("\n");
6618ad16e55SEdward Tomasz Napierala 	xo_close_instance("elements");
662*09f29b03SAlan Somers 	free(serial);
663*09f29b03SAlan Somers 	free(model);
6648ad16e55SEdward Tomasz Napierala 	free(e_devname.elm_devnames);
6658ad16e55SEdward Tomasz Napierala }
6668ad16e55SEdward Tomasz Napierala 
6678ad16e55SEdward Tomasz Napierala static void
6688ad16e55SEdward Tomasz Napierala show_therm(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6698ad16e55SEdward Tomasz Napierala {
6708ad16e55SEdward Tomasz Napierala 
6718ad16e55SEdward Tomasz Napierala 	if (e_desc.elm_desc_len <= 0) {
6728ad16e55SEdward Tomasz Napierala 		/* We don't have a label to display; might as well skip it. */
6738ad16e55SEdward Tomasz Napierala 		return;
6748ad16e55SEdward Tomasz Napierala 	}
6758ad16e55SEdward Tomasz Napierala 
6768ad16e55SEdward Tomasz Napierala 	if (e_status.cstat[2] == 0) {
6778ad16e55SEdward Tomasz Napierala 		/* No temperature to show. */
6788ad16e55SEdward Tomasz Napierala 		return;
6798ad16e55SEdward Tomasz Napierala 	}
6808ad16e55SEdward Tomasz Napierala 
6818ad16e55SEdward Tomasz Napierala 	xo_open_instance("elements");
6828ad16e55SEdward Tomasz Napierala 	xo_emit("{e:type/temperature_sensor}");
6838ad16e55SEdward Tomasz Napierala 	xo_emit("{:description/%s}: {:temperature/%d}{Uw:C}",
6848ad16e55SEdward Tomasz Napierala 	    e_desc.elm_desc_str, e_status.cstat[2] - TEMPERATURE_OFFSET);
6858ad16e55SEdward Tomasz Napierala 	xo_close_instance("elements");
6868ad16e55SEdward Tomasz Napierala }
6878ad16e55SEdward Tomasz Napierala 
6888ad16e55SEdward Tomasz Napierala static void
6898ad16e55SEdward Tomasz Napierala show_vom(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc)
6908ad16e55SEdward Tomasz Napierala {
6918ad16e55SEdward Tomasz Napierala 
6928ad16e55SEdward Tomasz Napierala 	if (e_desc.elm_desc_len <= 0) {
6938ad16e55SEdward Tomasz Napierala 		/* We don't have a label to display; might as well skip it. */
6948ad16e55SEdward Tomasz Napierala 		return;
6958ad16e55SEdward Tomasz Napierala 	}
6968ad16e55SEdward Tomasz Napierala 
6978ad16e55SEdward Tomasz Napierala 	if (e_status.cstat[2] == 0) {
6988ad16e55SEdward Tomasz Napierala 		/* No voltage to show. */
6998ad16e55SEdward Tomasz Napierala 		return;
7008ad16e55SEdward Tomasz Napierala 	}
7018ad16e55SEdward Tomasz Napierala 
7028ad16e55SEdward Tomasz Napierala 	xo_open_instance("elements");
7038ad16e55SEdward Tomasz Napierala 	xo_emit("{e:type/voltage_sensor}");
7048ad16e55SEdward Tomasz Napierala 	xo_emit("{:description/%s}: {:voltage/%.2f}{Uw:V}",
7058ad16e55SEdward Tomasz Napierala 	    e_desc.elm_desc_str, be16dec(e_status.cstat + 2) / 100.0);
7068ad16e55SEdward Tomasz Napierala 	xo_close_instance("elements");
7078ad16e55SEdward Tomasz Napierala }
7088ad16e55SEdward Tomasz Napierala 
7098ad16e55SEdward Tomasz Napierala static int
7108ad16e55SEdward Tomasz Napierala show(int argc, char **argv __unused)
7118ad16e55SEdward Tomasz Napierala {
7128ad16e55SEdward Tomasz Napierala 	encioc_string_t stri;
7138ad16e55SEdward Tomasz Napierala 	encioc_elm_status_t e_status;
7148ad16e55SEdward Tomasz Napierala 	encioc_elm_desc_t e_desc;
7158ad16e55SEdward Tomasz Napierala 	encioc_element_t *e_ptr;
7168ad16e55SEdward Tomasz Napierala 	glob_t g;
7178ad16e55SEdward Tomasz Napierala 	elm_type_t prev_type;
7188ad16e55SEdward Tomasz Napierala 	int fd;
7198ad16e55SEdward Tomasz Napierala 	unsigned int j, nobj;
7208ad16e55SEdward Tomasz Napierala 	size_t i;
7218ad16e55SEdward Tomasz Napierala 	bool first_ses;
7228ad16e55SEdward Tomasz Napierala 	char str[32];
7238ad16e55SEdward Tomasz Napierala 
7248ad16e55SEdward Tomasz Napierala 	if (argc != 1) {
7258ad16e55SEdward Tomasz Napierala 		usage(stderr, "map");
7268ad16e55SEdward Tomasz Napierala 	}
7278ad16e55SEdward Tomasz Napierala 
7288ad16e55SEdward Tomasz Napierala 	first_ses = true;
7298ad16e55SEdward Tomasz Napierala 
7308ad16e55SEdward Tomasz Napierala 	/* Get the list of ses devices */
7318ad16e55SEdward Tomasz Napierala 	if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
7328ad16e55SEdward Tomasz Napierala 		globfree(&g);
7338ad16e55SEdward Tomasz Napierala 		xo_errx(EXIT_FAILURE, "No SES devices found");
7348ad16e55SEdward Tomasz Napierala 	}
7358ad16e55SEdward Tomasz Napierala 	xo_set_version(SESUTIL_XO_VERSION);
7368ad16e55SEdward Tomasz Napierala 	xo_open_container("sesutil");
7378ad16e55SEdward Tomasz Napierala 	xo_open_list("enclosures");
7388ad16e55SEdward Tomasz Napierala 	for (i = 0; i < g.gl_pathc; i++) {
7398ad16e55SEdward Tomasz Napierala 		/* ensure we only got numbers after ses */
7408ad16e55SEdward Tomasz Napierala 		if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
7418ad16e55SEdward Tomasz Napierala 		    strlen(g.gl_pathv[i] + 8)) {
7428ad16e55SEdward Tomasz Napierala 			continue;
7438ad16e55SEdward Tomasz Napierala 		}
7448ad16e55SEdward Tomasz Napierala 		if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
7458ad16e55SEdward Tomasz Napierala 			/*
7468ad16e55SEdward Tomasz Napierala 			 * Don't treat non-access errors as critical if we are
7478ad16e55SEdward Tomasz Napierala 			 * accessing all devices
7488ad16e55SEdward Tomasz Napierala 			 */
7498ad16e55SEdward Tomasz Napierala 			if (errno == EACCES && g.gl_pathc > 1) {
7508ad16e55SEdward Tomasz Napierala 				xo_err(EXIT_FAILURE, "unable to access SES device");
7518ad16e55SEdward Tomasz Napierala 			}
7528ad16e55SEdward Tomasz Napierala 			xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
7538ad16e55SEdward Tomasz Napierala 			continue;
7548ad16e55SEdward Tomasz Napierala 		}
7558ad16e55SEdward Tomasz Napierala 
7568ad16e55SEdward Tomasz Napierala 		if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
7578ad16e55SEdward Tomasz Napierala 			close(fd);
7588ad16e55SEdward Tomasz Napierala 			xo_err(EXIT_FAILURE, "ENCIOC_GETNELM");
7598ad16e55SEdward Tomasz Napierala 		}
7608ad16e55SEdward Tomasz Napierala 
7618ad16e55SEdward Tomasz Napierala 		e_ptr = calloc(nobj, sizeof(encioc_element_t));
7628ad16e55SEdward Tomasz Napierala 		if (e_ptr == NULL) {
7638ad16e55SEdward Tomasz Napierala 			close(fd);
7648ad16e55SEdward Tomasz Napierala 			xo_err(EXIT_FAILURE, "calloc()");
7658ad16e55SEdward Tomasz Napierala 		}
7668ad16e55SEdward Tomasz Napierala 
7678ad16e55SEdward Tomasz Napierala 		if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) {
7688ad16e55SEdward Tomasz Napierala 			close(fd);
7698ad16e55SEdward Tomasz Napierala 			xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
7708ad16e55SEdward Tomasz Napierala 		}
7718ad16e55SEdward Tomasz Napierala 
7728ad16e55SEdward Tomasz Napierala 		xo_open_instance("enclosures");
7738ad16e55SEdward Tomasz Napierala 
7748ad16e55SEdward Tomasz Napierala 		if (first_ses)
7758ad16e55SEdward Tomasz Napierala 			first_ses = false;
7768ad16e55SEdward Tomasz Napierala 		else
7778ad16e55SEdward Tomasz Napierala 			xo_emit("\n");
7788ad16e55SEdward Tomasz Napierala 
7798ad16e55SEdward Tomasz Napierala 		xo_emit("{t:enc/%s}: ", g.gl_pathv[i] + 5);
7808ad16e55SEdward Tomasz Napierala 		stri.bufsiz = sizeof(str);
7818ad16e55SEdward Tomasz Napierala 		stri.buf = &str[0];
7828ad16e55SEdward Tomasz Napierala 		if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0)
7838ad16e55SEdward Tomasz Napierala 			xo_emit("<{t:name/%s}>; ", stri.buf);
7848ad16e55SEdward Tomasz Napierala 		stri.bufsiz = sizeof(str);
7858ad16e55SEdward Tomasz Napierala 		stri.buf = &str[0];
7868ad16e55SEdward Tomasz Napierala 		if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0)
7878ad16e55SEdward Tomasz Napierala 			xo_emit("ID: {t:id/%s}", stri.buf);
7888ad16e55SEdward Tomasz Napierala 		xo_emit("\n");
7898ad16e55SEdward Tomasz Napierala 
7908ad16e55SEdward Tomasz Napierala 		xo_open_list("elements");
7918ad16e55SEdward Tomasz Napierala 		prev_type = -1;
7928ad16e55SEdward Tomasz Napierala 		for (j = 0; j < nobj; j++) {
7938ad16e55SEdward Tomasz Napierala 			/* Get the status of the element */
7948ad16e55SEdward Tomasz Napierala 			memset(&e_status, 0, sizeof(e_status));
7958ad16e55SEdward Tomasz Napierala 			e_status.elm_idx = e_ptr[j].elm_idx;
7968ad16e55SEdward Tomasz Napierala 			if (ioctl(fd, ENCIOC_GETELMSTAT,
7978ad16e55SEdward Tomasz Napierala 			    (caddr_t) &e_status) < 0) {
7988ad16e55SEdward Tomasz Napierala 				close(fd);
7998ad16e55SEdward Tomasz Napierala 				xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
8008ad16e55SEdward Tomasz Napierala 			}
8018ad16e55SEdward Tomasz Napierala 
8028ad16e55SEdward Tomasz Napierala 			/*
8038ad16e55SEdward Tomasz Napierala 			 * Skip "Unsupported" elements; those usually precede
8048ad16e55SEdward Tomasz Napierala 			 * the actual device entries and are not particularly
8058ad16e55SEdward Tomasz Napierala 			 * interesting.
8068ad16e55SEdward Tomasz Napierala 			 */
8078ad16e55SEdward Tomasz Napierala 			if (e_status.cstat[0] == SES_OBJSTAT_UNSUPPORTED)
8088ad16e55SEdward Tomasz Napierala 				continue;
8098ad16e55SEdward Tomasz Napierala 
8108ad16e55SEdward Tomasz Napierala 			/* Get the description of the element */
8118ad16e55SEdward Tomasz Napierala 			memset(&e_desc, 0, sizeof(e_desc));
8128ad16e55SEdward Tomasz Napierala 			e_desc.elm_idx = e_ptr[j].elm_idx;
8138ad16e55SEdward Tomasz Napierala 			e_desc.elm_desc_len = UINT16_MAX;
8148ad16e55SEdward Tomasz Napierala 			e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
8158ad16e55SEdward Tomasz Napierala 			if (e_desc.elm_desc_str == NULL) {
8168ad16e55SEdward Tomasz Napierala 				close(fd);
8178ad16e55SEdward Tomasz Napierala 				xo_err(EXIT_FAILURE, "calloc()");
8188ad16e55SEdward Tomasz Napierala 			}
8198ad16e55SEdward Tomasz Napierala 			if (ioctl(fd, ENCIOC_GETELMDESC,
8208ad16e55SEdward Tomasz Napierala 			    (caddr_t) &e_desc) < 0) {
8218ad16e55SEdward Tomasz Napierala 				close(fd);
8228ad16e55SEdward Tomasz Napierala 				xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC");
8238ad16e55SEdward Tomasz Napierala 			}
8248ad16e55SEdward Tomasz Napierala 
8258ad16e55SEdward Tomasz Napierala 			switch (e_ptr[j].elm_type) {
8268ad16e55SEdward Tomasz Napierala 			case ELMTYP_DEVICE:
8278ad16e55SEdward Tomasz Napierala 			case ELMTYP_ARRAY_DEV:
8288ad16e55SEdward Tomasz Napierala 				if (e_ptr[j].elm_type != prev_type)
8298ad16e55SEdward Tomasz Napierala 					xo_emit("Desc            Dev     Model                     Ident                Size/Status\n");
8308ad16e55SEdward Tomasz Napierala 
8318ad16e55SEdward Tomasz Napierala 				show_device(fd, e_ptr[j].elm_idx, e_status, e_desc);
8328ad16e55SEdward Tomasz Napierala 				prev_type = e_ptr[j].elm_type;
8338ad16e55SEdward Tomasz Napierala 				break;
8348ad16e55SEdward Tomasz Napierala 			case ELMTYP_THERM:
8358ad16e55SEdward Tomasz Napierala 				if (e_ptr[j].elm_type != prev_type)
8363d10bf72SEdward Tomasz Napierala 					xo_emit("\nTemperatures: ");
8378ad16e55SEdward Tomasz Napierala 				else
8388ad16e55SEdward Tomasz Napierala 					xo_emit(", ");
8398ad16e55SEdward Tomasz Napierala 				prev_type = e_ptr[j].elm_type;
8408ad16e55SEdward Tomasz Napierala 				show_therm(e_status, e_desc);
8418ad16e55SEdward Tomasz Napierala 				break;
8428ad16e55SEdward Tomasz Napierala 			case ELMTYP_VOM:
8438ad16e55SEdward Tomasz Napierala 				if (e_ptr[j].elm_type != prev_type)
8443d10bf72SEdward Tomasz Napierala 					xo_emit("\nVoltages: ");
8458ad16e55SEdward Tomasz Napierala 				else
8468ad16e55SEdward Tomasz Napierala 					xo_emit(", ");
8478ad16e55SEdward Tomasz Napierala 				prev_type = e_ptr[j].elm_type;
8488ad16e55SEdward Tomasz Napierala 				show_vom(e_status, e_desc);
8498ad16e55SEdward Tomasz Napierala 				break;
8508ad16e55SEdward Tomasz Napierala 			default:
8518ad16e55SEdward Tomasz Napierala 				/*
8528ad16e55SEdward Tomasz Napierala 				 * Ignore stuff not interesting to the user.
8538ad16e55SEdward Tomasz Napierala 				 */
8548ad16e55SEdward Tomasz Napierala 				break;
8558ad16e55SEdward Tomasz Napierala 			}
856*09f29b03SAlan Somers 			free(e_desc.elm_desc_str);
8578ad16e55SEdward Tomasz Napierala 		}
8588ad16e55SEdward Tomasz Napierala 		if (prev_type != (elm_type_t)-1 &&
8598ad16e55SEdward Tomasz Napierala 		    prev_type != ELMTYP_DEVICE && prev_type != ELMTYP_ARRAY_DEV)
8608ad16e55SEdward Tomasz Napierala 			xo_emit("\n");
8618ad16e55SEdward Tomasz Napierala 		xo_close_list("elements");
8628ad16e55SEdward Tomasz Napierala 		free(e_ptr);
8638ad16e55SEdward Tomasz Napierala 		close(fd);
8648ad16e55SEdward Tomasz Napierala 	}
8658ad16e55SEdward Tomasz Napierala 	globfree(&g);
8668ad16e55SEdward Tomasz Napierala 	xo_close_list("enclosures");
8678ad16e55SEdward Tomasz Napierala 	xo_close_container("sesutil");
8688ad16e55SEdward Tomasz Napierala 	xo_finish();
8698ad16e55SEdward Tomasz Napierala 
8708ad16e55SEdward Tomasz Napierala 	return (EXIT_SUCCESS);
8718ad16e55SEdward Tomasz Napierala }
8728ad16e55SEdward Tomasz Napierala 
8738729f5ecSAllan Jude static int
8748729f5ecSAllan Jude encstatus(int argc, char **argv __unused)
875cddcb259SBaptiste Daroussin {
8768729f5ecSAllan Jude 	glob_t g;
8778729f5ecSAllan Jude 	int fd, status;
8788729f5ecSAllan Jude 	size_t i, e;
8798729f5ecSAllan Jude 	u_char estat;
880cddcb259SBaptiste Daroussin 
8818729f5ecSAllan Jude 	status = 0;
8828729f5ecSAllan Jude 	if (argc != 1) {
8838729f5ecSAllan Jude 		usage(stderr, "status");
8848729f5ecSAllan Jude 	}
8858729f5ecSAllan Jude 
8868729f5ecSAllan Jude 	/* Get the list of ses devices */
8878729f5ecSAllan Jude 	if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
8888729f5ecSAllan Jude 		globfree(&g);
889d25c1ff6SBaptiste Daroussin 		xo_errx(EXIT_FAILURE, "No SES devices found");
8908729f5ecSAllan Jude 	}
891d25c1ff6SBaptiste Daroussin 
892d25c1ff6SBaptiste Daroussin 	xo_set_version(SESUTIL_XO_VERSION);
893d25c1ff6SBaptiste Daroussin 	xo_open_container("sesutil");
894d25c1ff6SBaptiste Daroussin 	xo_open_list("enclosures");
8958729f5ecSAllan Jude 	for (i = 0; i < g.gl_pathc; i++) {
8968729f5ecSAllan Jude 		/* ensure we only got numbers after ses */
8978729f5ecSAllan Jude 		if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
8988729f5ecSAllan Jude 		    strlen(g.gl_pathv[i] + 8)) {
8998729f5ecSAllan Jude 			continue;
9008729f5ecSAllan Jude 		}
9018729f5ecSAllan Jude 		if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
9028729f5ecSAllan Jude 			/*
9038729f5ecSAllan Jude 			 * Don't treat non-access errors as critical if we are
9048729f5ecSAllan Jude 			 * accessing all devices
9058729f5ecSAllan Jude 			 */
9068729f5ecSAllan Jude 			if (errno == EACCES && g.gl_pathc > 1) {
907d25c1ff6SBaptiste Daroussin 				xo_err(EXIT_FAILURE, "unable to access SES device");
9088729f5ecSAllan Jude 			}
909d25c1ff6SBaptiste Daroussin 			xo_warn("unable to access SES device: %s", g.gl_pathv[i]);
9108729f5ecSAllan Jude 			continue;
9118729f5ecSAllan Jude 		}
9128729f5ecSAllan Jude 
9138729f5ecSAllan Jude 		if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) {
914d25c1ff6SBaptiste Daroussin 			xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT");
9158729f5ecSAllan Jude 			close(fd);
9168729f5ecSAllan Jude 		}
9178729f5ecSAllan Jude 
918d25c1ff6SBaptiste Daroussin 		xo_open_instance("enclosures");
919d25c1ff6SBaptiste Daroussin 		xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5);
9208729f5ecSAllan Jude 		e = 0;
9218729f5ecSAllan Jude 		if (estat == 0) {
9228729f5ecSAllan Jude 			if (status == 0) {
9238729f5ecSAllan Jude 				status = 1;
9248729f5ecSAllan Jude 			}
925d25c1ff6SBaptiste Daroussin 			xo_emit("{q:status/OK}");
9268729f5ecSAllan Jude 		} else {
9278729f5ecSAllan Jude 			if (estat & SES_ENCSTAT_INFO) {
928d25c1ff6SBaptiste Daroussin 				xo_emit("{lq:status/INFO}");
9298729f5ecSAllan Jude 				e++;
9308729f5ecSAllan Jude 			}
9318729f5ecSAllan Jude 			if (estat & SES_ENCSTAT_NONCRITICAL) {
9328729f5ecSAllan Jude 				if (e)
933d25c1ff6SBaptiste Daroussin 					xo_emit(",");
934d25c1ff6SBaptiste Daroussin 				xo_emit("{lq:status/NONCRITICAL}");
9358729f5ecSAllan Jude 				e++;
9368729f5ecSAllan Jude 			}
9378729f5ecSAllan Jude 			if (estat & SES_ENCSTAT_CRITICAL) {
9388729f5ecSAllan Jude 				if (e)
939d25c1ff6SBaptiste Daroussin 					xo_emit(",");
940d25c1ff6SBaptiste Daroussin 				xo_emit("{lq:status/CRITICAL}");
9418729f5ecSAllan Jude 				e++;
9428729f5ecSAllan Jude 				status = -1;
9438729f5ecSAllan Jude 			}
9448729f5ecSAllan Jude 			if (estat & SES_ENCSTAT_UNRECOV) {
9458729f5ecSAllan Jude 				if (e)
946d25c1ff6SBaptiste Daroussin 					xo_emit(",");
947d25c1ff6SBaptiste Daroussin 				xo_emit("{lq:status/UNRECOV}");
9488729f5ecSAllan Jude 				e++;
9498729f5ecSAllan Jude 				status = -1;
9508729f5ecSAllan Jude 			}
9518729f5ecSAllan Jude 		}
952d25c1ff6SBaptiste Daroussin 		xo_close_instance("enclosures");
953d25c1ff6SBaptiste Daroussin 		xo_emit("\n");
9548729f5ecSAllan Jude 		close(fd);
9558729f5ecSAllan Jude 	}
9568729f5ecSAllan Jude 	globfree(&g);
9578729f5ecSAllan Jude 
958d25c1ff6SBaptiste Daroussin 	xo_close_list("enclosures");
959d25c1ff6SBaptiste Daroussin 	xo_close_container("sesutil");
960d25c1ff6SBaptiste Daroussin 	xo_finish();
961d25c1ff6SBaptiste Daroussin 
9628729f5ecSAllan Jude 	if (status == 1) {
9638729f5ecSAllan Jude 		return (EXIT_SUCCESS);
9648729f5ecSAllan Jude 	} else {
9658729f5ecSAllan Jude 		return (EXIT_FAILURE);
9668729f5ecSAllan Jude 	}
967cddcb259SBaptiste Daroussin }
968cddcb259SBaptiste Daroussin 
969cddcb259SBaptiste Daroussin int
970cddcb259SBaptiste Daroussin main(int argc, char **argv)
971cddcb259SBaptiste Daroussin {
9728729f5ecSAllan Jude 	int i, ch;
973cddcb259SBaptiste Daroussin 	struct command *cmd = NULL;
974cddcb259SBaptiste Daroussin 
975d25c1ff6SBaptiste Daroussin 	argc = xo_parse_args(argc, argv);
976d25c1ff6SBaptiste Daroussin 	if (argc < 0)
977d25c1ff6SBaptiste Daroussin 		exit(1);
978d25c1ff6SBaptiste Daroussin 
9798729f5ecSAllan Jude 	uflag = "/dev/ses[0-9]*";
9808729f5ecSAllan Jude 	while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) {
9818729f5ecSAllan Jude 		switch (ch) {
9828729f5ecSAllan Jude 		case 'u':
9838729f5ecSAllan Jude 			uflag = optarg;
9848729f5ecSAllan Jude 			break;
9858729f5ecSAllan Jude 		case '?':
9868729f5ecSAllan Jude 		default:
9878729f5ecSAllan Jude 			usage(stderr, NULL);
9888729f5ecSAllan Jude 		}
9898729f5ecSAllan Jude 	}
9908729f5ecSAllan Jude 	argc -= optind;
9918729f5ecSAllan Jude 	argv += optind;
9928729f5ecSAllan Jude 
9938729f5ecSAllan Jude 	if (argc < 1) {
994cddcb259SBaptiste Daroussin 		warnx("Missing command");
9958729f5ecSAllan Jude 		usage(stderr, NULL);
996cddcb259SBaptiste Daroussin 	}
997cddcb259SBaptiste Daroussin 
998cddcb259SBaptiste Daroussin 	for (i = 0; i < nbcmds; i++) {
9998729f5ecSAllan Jude 		if (strcmp(argv[0], cmds[i].name) == 0) {
1000cddcb259SBaptiste Daroussin 			cmd = &cmds[i];
1001cddcb259SBaptiste Daroussin 			break;
1002cddcb259SBaptiste Daroussin 		}
1003cddcb259SBaptiste Daroussin 	}
1004cddcb259SBaptiste Daroussin 
1005cddcb259SBaptiste Daroussin 	if (cmd == NULL) {
10068729f5ecSAllan Jude 		warnx("unknown command %s", argv[0]);
10078729f5ecSAllan Jude 		usage(stderr, NULL);
1008cddcb259SBaptiste Daroussin 	}
1009cddcb259SBaptiste Daroussin 
1010cddcb259SBaptiste Daroussin 	return (cmd->exec(argc, argv));
1011cddcb259SBaptiste Daroussin }
1012