#include <sys/types.h>
#include <sys/devicestat.h>
#include <string.h>
#include <devstat.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <err.h>
#include "systat.h"
#include "extern.h"
#include "devs.h"
typedef enum {
DS_MATCHTYPE_NONE,
DS_MATCHTYPE_SPEC,
DS_MATCHTYPE_PATTERN
} last_match_type;
last_match_type last_type;
struct device_selection *dev_select;
long generation;
int num_devices, num_selected;
int num_selections;
long select_generation;
struct devstat_match *matches = NULL;
int num_matches = 0;
char **specified_devices;
int num_devices_specified = 0;
static void dsinit_ignores(int maxshowdevs, struct statinfo *s1);
static int dsmatchselect(char *args, devstat_select_mode select_mode,
int maxshowdevs, struct statinfo *s1);
static int dsselect(char *args, devstat_select_mode select_mode,
int maxshowdevs, struct statinfo *s1);
int
dsinit(int maxshowdevs, struct statinfo *s1, struct statinfo *s2 __unused,
struct statinfo *s3 __unused)
{
if (checkversion() < 0)
errx(1, "%s", devstat_errbuf);
generation = 0;
num_devices = 0;
num_selected = 0;
num_selections = 0;
select_generation = 0;
last_type = DS_MATCHTYPE_NONE;
if (getdevs(s1) == -1)
errx(1, "%s", devstat_errbuf);
num_devices = s1->dinfo->numdevs;
generation = s1->dinfo->generation;
dev_select = NULL;
if (selectdevs(&dev_select, &num_selected, &num_selections,
&select_generation, generation, s1->dinfo->devices,
num_devices, NULL, 0, NULL, 0, DS_SELECT_ADD,
maxshowdevs, 0) == -1) {
errx(1, "%s", devstat_errbuf);
}
dsinit_ignores(maxshowdevs, s1);
return(1);
}
static
void
dsinit_ignores(int maxshowdevs, struct statinfo *s1)
{
char tmp[64];
snprintf(tmp, sizeof(tmp), "md*");
dscmd("ignore", tmp, maxshowdevs, s1);
snprintf(tmp, sizeof(tmp), "pass*");
dscmd("ignore", tmp, maxshowdevs, s1);
snprintf(tmp, sizeof(tmp), "sg*");
dscmd("ignore", tmp, maxshowdevs, s1);
}
int
dscmd(const char *cmd, char *args, int maxshowdevs, struct statinfo *s1)
{
int retval;
if (prefix(cmd, "display") || prefix(cmd, "add"))
return(dsselect(args, DS_SELECT_ADDONLY, maxshowdevs, s1));
if (prefix(cmd, "ignore") || prefix(cmd, "delete"))
return(dsselect(args, DS_SELECT_REMOVE, maxshowdevs, s1));
if (prefix(cmd, "show") || prefix(cmd, "only"))
return(dsselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
if (prefix(cmd, "type") || prefix(cmd, "match"))
return(dsmatchselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
if (prefix(cmd, "refresh")) {
retval = selectdevs(&dev_select, &num_selected, &num_selections,
&select_generation, generation,
s1->dinfo->devices, num_devices,
(last_type == DS_MATCHTYPE_PATTERN) ?
matches : NULL,
(last_type == DS_MATCHTYPE_PATTERN) ?
num_matches : 0,
(last_type == DS_MATCHTYPE_SPEC) ?
specified_devices : NULL,
(last_type == DS_MATCHTYPE_SPEC) ?
num_devices_specified : 0,
(last_type == DS_MATCHTYPE_NONE) ?
DS_SELECT_ADD : DS_SELECT_ADDONLY,
maxshowdevs, 0);
dsinit_ignores(maxshowdevs, s1);
if (retval == -1) {
warnx("%s", devstat_errbuf);
return(0);
} else if (retval == 1) {
return(2);
}
}
if (prefix(cmd, "drives")) {
int i;
move(CMDLINE, 0);
clrtoeol();
for (i = 0; i < num_devices; i++) {
printw("%s%d ", s1->dinfo->devices[i].device_name,
s1->dinfo->devices[i].unit_number);
}
return(1);
}
return(0);
}
static int
dsmatchselect(char *args, devstat_select_mode select_mode, int maxshowdevs,
struct statinfo *s1)
{
char **tempstr;
char *tstr[100];
int num_args = 0;
int i;
int retval = 0;
for (tempstr = tstr, num_args = 0;
(*tempstr = strsep(&args, "|")) != NULL && (num_args < 100);
num_args++)
if (**tempstr != '\0')
if (++tempstr >= &tstr[100])
break;
if (num_args > 99) {
warnx("dsmatchselect: too many match arguments");
return(0);
}
if (num_matches > 0) {
free(matches);
matches = NULL;
num_matches = 0;
}
for (i = 0; i < num_args; i++) {
if (buildmatch(tstr[i], &matches, &num_matches) != 0) {
warnx("%s", devstat_errbuf);
return(0);
}
}
if (num_args > 0) {
last_type = DS_MATCHTYPE_PATTERN;
retval = selectdevs(&dev_select, &num_selected, &num_selections,
&select_generation, generation,
s1->dinfo->devices, num_devices, matches,
num_matches, NULL, 0, select_mode,
maxshowdevs, 0);
if (retval == -1)
err(1, "device selection error");
else if (retval == 1)
return(2);
}
return(1);
}
static int
dsselect(char *args, devstat_select_mode select_mode, int maxshowdevs,
struct statinfo *s1)
{
char *cp;
int i;
int retval = 0;
int iswild;
if (num_devices_specified > 0) {
for (i = 0; i < num_devices_specified; i++)
free(specified_devices[i]);
free(specified_devices);
specified_devices = NULL;
num_devices_specified = 0;
}
specified_devices = (char **)malloc(sizeof(char *));
cp = strchr(args, '\n');
if (cp)
*cp = '\0';
for (;;) {
for (cp = args; *cp && isspace(*cp); cp++)
;
args = cp;
for (; *cp && !isspace(*cp); cp++)
;
if (*cp)
*cp++ = '\0';
if (cp - args == 0)
break;
if (cp[-1] == '*') {
cp[-1] = 0;
iswild = 1;
} else {
iswild = 0;
}
for (i = 0; i < num_devices; i++) {
char tmpstr[80];
sprintf(tmpstr, "%s%d", dev_select[i].device_name,
dev_select[i].unit_number);
if (strcmp(args, tmpstr) == 0 ||
(iswild &&
strcmp(args, dev_select[i].device_name) == 0)) {
num_devices_specified++;
specified_devices =(char **)realloc(
specified_devices,
sizeof(char *) *
num_devices_specified);
specified_devices[num_devices_specified - 1] =
strdup(tmpstr);
}
}
#if 0
if (i >= num_devices)
error("%s: unknown drive", args);
#endif
args = cp;
}
if (num_devices_specified > 0) {
last_type = DS_MATCHTYPE_SPEC;
retval = selectdevs(&dev_select, &num_selected, &num_selections,
&select_generation, generation,
s1->dinfo->devices, num_devices, NULL, 0,
specified_devices, num_devices_specified,
select_mode, maxshowdevs, 0);
if (retval == -1)
err(1, "%s", devstat_errbuf);
else if (retval == 1)
return(2);
}
return(1);
}