devs.c revision 40060
139230Sgibbs/*
239230Sgibbs * Copyright (c) 1998 Kenneth D. Merry.
339230Sgibbs * All rights reserved.
439230Sgibbs *
539230Sgibbs * Redistribution and use in source and binary forms, with or without
639230Sgibbs * modification, are permitted provided that the following conditions
739230Sgibbs * are met:
839230Sgibbs * 1. Redistributions of source code must retain the above copyright
939230Sgibbs *    notice, this list of conditions and the following disclaimer.
1039230Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
1139230Sgibbs *    notice, this list of conditions and the following disclaimer in the
1239230Sgibbs *    documentation and/or other materials provided with the distribution.
1339230Sgibbs * 3. The name of the author may not be used to endorse or promote products
1439230Sgibbs *    derived from this software without specific prior written permission.
1539230Sgibbs *
1639230Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1739230Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1839230Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1939230Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2039230Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2139230Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2239230Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2339230Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2439230Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2539230Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2639230Sgibbs * SUCH DAMAGE.
2739230Sgibbs *
2840060Sobrien *	$Id: devs.c,v 1.2 1998/09/20 00:11:23 ken Exp $
2939230Sgibbs */
3039230Sgibbs/*
3139230Sgibbs * Some code and ideas taken from the old disks.c.
3239230Sgibbs * static char sccsid[] = "@(#)disks.c	8.1 (Berkeley) 6/6/93";
3339230Sgibbs */
3439230Sgibbs/*-
3539230Sgibbs * Copyright (c) 1980, 1992, 1993
3639230Sgibbs *	The Regents of the University of California.  All rights reserved.
3739230Sgibbs *
3839230Sgibbs * Redistribution and use in source and binary forms, with or without
3939230Sgibbs * modification, are permitted provided that the following conditions
4039230Sgibbs * are met:
4139230Sgibbs * 1. Redistributions of source code must retain the above copyright
4239230Sgibbs *    notice, this list of conditions and the following disclaimer.
4339230Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
4439230Sgibbs *    notice, this list of conditions and the following disclaimer in the
4539230Sgibbs *    documentation and/or other materials provided with the distribution.
4639230Sgibbs * 3. All advertising materials mentioning features or use of this software
4739230Sgibbs *    must display the following acknowledgement:
4839230Sgibbs *	This product includes software developed by the University of
4939230Sgibbs *	California, Berkeley and its contributors.
5039230Sgibbs * 4. Neither the name of the University nor the names of its contributors
5139230Sgibbs *    may be used to endorse or promote products derived from this software
5239230Sgibbs *    without specific prior written permission.
5339230Sgibbs *
5439230Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5539230Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5639230Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5739230Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5839230Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5939230Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6039230Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6139230Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6239230Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6339230Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6439230Sgibbs * SUCH DAMAGE.
6539230Sgibbs */
6639230Sgibbs
6739230Sgibbs#include <sys/types.h>
6839230Sgibbs#include <sys/devicestat.h>
6939230Sgibbs#include <sys/dkstat.h>
7039230Sgibbs
7139230Sgibbs#include <string.h>
7239230Sgibbs#include <devstat.h>
7340060Sobrien#include <stdlib.h>
7440060Sobrien#include <ctype.h>
7540060Sobrien#include <err.h>
7639230Sgibbs#include "systat.h"
7739230Sgibbs#include "extern.h"
7840060Sobrien#include "devs.h"
7939230Sgibbs
8039230Sgibbstypedef enum {
8139230Sgibbs	DS_MATCHTYPE_NONE,
8239230Sgibbs	DS_MATCHTYPE_SPEC,
8339230Sgibbs	DS_MATCHTYPE_PATTERN
8439230Sgibbs} last_match_type;
8539230Sgibbs
8639230Sgibbslast_match_type last_type;
8739230Sgibbsstruct device_selection *dev_select;
8839498Skenlong generation;
8939498Skenint num_devices, num_selected;
9039498Skenint num_selections;
9139498Skenlong select_generation;
9239230Sgibbsstruct devstat_match *matches = NULL;
9339230Sgibbsint num_matches = 0;
9439230Sgibbschar **specified_devices;
9539230Sgibbsint num_devices_specified = 0;
9639230Sgibbs
9739230Sgibbsstatic int dsmatchselect(char *args, devstat_select_mode select_mode,
9839230Sgibbs			 int maxshowdevs, struct statinfo *s1);
9939230Sgibbsstatic int dsselect(char *args, devstat_select_mode select_mode,
10039230Sgibbs		    int maxshowdevs, struct statinfo *s1);
10139230Sgibbs
10239230Sgibbsint
10339230Sgibbsdsinit(int maxshowdevs, struct statinfo *s1, struct statinfo *s2,
10439230Sgibbs       struct statinfo *s3)
10539230Sgibbs{
10639230Sgibbs
10739230Sgibbs	/*
10839230Sgibbs	 * Make sure that the userland devstat version matches the kernel
10939230Sgibbs	 * devstat version.  If not, exit and print a message informing
11039230Sgibbs	 * the user of his mistake.
11139230Sgibbs	 */
11239230Sgibbs	if (checkversion() < 0)
11339230Sgibbs		errx(1, "%s", devstat_errbuf);
11439230Sgibbs
11539230Sgibbs	generation = 0;
11639230Sgibbs	num_devices = 0;
11739230Sgibbs	num_selected = 0;
11839230Sgibbs	num_selections = 0;
11939230Sgibbs	select_generation = 0;
12039230Sgibbs	last_type = DS_MATCHTYPE_NONE;
12139230Sgibbs
12239230Sgibbs	if (getdevs(s1) == -1)
12339230Sgibbs		errx(1, "%s", devstat_errbuf);
12439230Sgibbs
12539230Sgibbs	num_devices = s1->dinfo->numdevs;
12639230Sgibbs	generation = s1->dinfo->generation;
12739230Sgibbs
12839230Sgibbs	dev_select = NULL;
12939230Sgibbs
13039230Sgibbs	/*
13139230Sgibbs	 * At this point, selectdevs will almost surely indicate that the
13239230Sgibbs	 * device list has changed, so we don't look for return values of 0
13339230Sgibbs	 * or 1.  If we get back -1, though, there is an error.
13439230Sgibbs	 */
13539230Sgibbs	if (selectdevs(&dev_select, &num_selected, &num_selections,
13639230Sgibbs		       &select_generation, generation, s1->dinfo->devices,
13739230Sgibbs		       num_devices, NULL, 0, NULL, 0, DS_SELECT_ADD,
13839230Sgibbs		       maxshowdevs, 0) == -1)
13939230Sgibbs		errx(1, "%s", devstat_errbuf);
14039230Sgibbs
14139230Sgibbs	return(1);
14239230Sgibbs}
14339230Sgibbs
14439230Sgibbsint
14539230Sgibbsdscmd(char *cmd, char *args, int maxshowdevs, struct statinfo *s1)
14639230Sgibbs{
14739230Sgibbs	int retval;
14839230Sgibbs
14939230Sgibbs	if (prefix(cmd, "display") || prefix(cmd, "add"))
15039230Sgibbs		return(dsselect(args, DS_SELECT_ADDONLY, maxshowdevs, s1));
15139230Sgibbs	if (prefix(cmd, "ignore") || prefix(cmd, "delete"))
15239230Sgibbs		return(dsselect(args, DS_SELECT_REMOVE, maxshowdevs, s1));
15339230Sgibbs	if (prefix(cmd, "show") || prefix(cmd, "only"))
15439230Sgibbs		return(dsselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
15539230Sgibbs	if (prefix(cmd, "type") || prefix(cmd, "match"))
15639230Sgibbs		return(dsmatchselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
15739230Sgibbs	if (prefix(cmd, "refresh")) {
15839230Sgibbs		retval = selectdevs(&dev_select, &num_selected, &num_selections,
15939230Sgibbs				    &select_generation, generation,
16039230Sgibbs				    s1->dinfo->devices, num_devices,
16139230Sgibbs				    (last_type == DS_MATCHTYPE_PATTERN) ?
16239230Sgibbs					matches : NULL,
16339230Sgibbs				    (last_type == DS_MATCHTYPE_PATTERN) ?
16439230Sgibbs					num_matches : 0,
16539230Sgibbs				    (last_type == DS_MATCHTYPE_SPEC) ?
16639230Sgibbs					specified_devices : NULL,
16739230Sgibbs				    (last_type == DS_MATCHTYPE_SPEC) ?
16839230Sgibbs					num_devices_specified : 0,
16939230Sgibbs				    (last_type == DS_MATCHTYPE_NONE) ?
17039230Sgibbs					DS_SELECT_ADD : DS_SELECT_ADDONLY,
17139230Sgibbs				    maxshowdevs, 0);
17239230Sgibbs		if (retval == -1) {
17339230Sgibbs			warnx("%s", devstat_errbuf);
17439230Sgibbs			return(0);
17539230Sgibbs		} else if (retval == 1)
17639230Sgibbs			return(2);
17739230Sgibbs	}
17839230Sgibbs	if (prefix(cmd, "drives")) {
17939230Sgibbs		register int i;
18039230Sgibbs		move(CMDLINE, 0);
18139230Sgibbs		clrtoeol();
18239230Sgibbs		for (i = 0; i < num_devices; i++) {
18339230Sgibbs			printw("%s%d ", s1->dinfo->devices[i].device_name,
18439230Sgibbs			       s1->dinfo->devices[i].unit_number);
18539230Sgibbs		}
18639230Sgibbs		return(1);
18739230Sgibbs	}
18839230Sgibbs	return(0);
18939230Sgibbs}
19039230Sgibbs
19139230Sgibbsstatic int
19239230Sgibbsdsmatchselect(char *args, devstat_select_mode select_mode, int maxshowdevs,
19339230Sgibbs	      struct statinfo *s1)
19439230Sgibbs{
19539230Sgibbs	char **tempstr;
19639230Sgibbs	char *tstr[100];
19739230Sgibbs	int num_args = 0;
19839230Sgibbs	register int i;
19939230Sgibbs	int retval = 0;
20039230Sgibbs
20139230Sgibbs	/*
20239230Sgibbs	 * Break the (pipe delimited) input string out into separate
20339230Sgibbs	 * strings.
20439230Sgibbs	 */
20539230Sgibbs	for (tempstr = tstr, num_args  = 0;
20639230Sgibbs	     (*tempstr = strsep(&args, "|")) != NULL && (num_args < 100);
20739230Sgibbs	     num_args++)
20839230Sgibbs		if (**tempstr != '\0')
20939230Sgibbs			if (++tempstr >= &tstr[100])
21039230Sgibbs				break;
21139230Sgibbs
21239230Sgibbs	if (num_args > 99) {
21339230Sgibbs		warnx("dsmatchselect: too many match arguments");
21439230Sgibbs		return(0);
21539230Sgibbs	}
21639230Sgibbs
21739230Sgibbs	/*
21839230Sgibbs	 * If we've gone through the matching code before, clean out
21939230Sgibbs	 * previously used memory.
22039230Sgibbs	 */
22139230Sgibbs	if (num_matches > 0) {
22239230Sgibbs		free(matches);
22339230Sgibbs		matches = NULL;
22439230Sgibbs		num_matches = 0;
22539230Sgibbs	}
22639230Sgibbs
22739230Sgibbs	for (i = 0; i < num_args; i++) {
22839230Sgibbs		if (buildmatch(tstr[i], &matches, &num_matches) != 0) {
22939230Sgibbs			warnx("%s", devstat_errbuf);
23039230Sgibbs			return(0);
23139230Sgibbs		}
23239230Sgibbs	}
23339230Sgibbs	if (num_args > 0) {
23439230Sgibbs
23539230Sgibbs		last_type = DS_MATCHTYPE_PATTERN;
23639230Sgibbs
23739230Sgibbs		retval = selectdevs(&dev_select, &num_selected, &num_selections,
23839230Sgibbs				    &select_generation, generation,
23939230Sgibbs				    s1->dinfo->devices, num_devices, matches,
24039230Sgibbs				    num_matches, NULL, 0, select_mode,
24139230Sgibbs				    maxshowdevs, 0);
24239230Sgibbs		if (retval == -1)
24339230Sgibbs			err(1, "device selection error");
24439230Sgibbs		else if (retval == 1)
24539230Sgibbs			return(2);
24639230Sgibbs	}
24739230Sgibbs	return(1);
24839230Sgibbs}
24939230Sgibbs
25039230Sgibbsstatic int
25139230Sgibbsdsselect(char *args, devstat_select_mode select_mode, int maxshowdevs,
25239230Sgibbs	 struct statinfo *s1)
25339230Sgibbs{
25439230Sgibbs	register char *cp;
25539230Sgibbs	register int i;
25639230Sgibbs	int retval = 0;
25739230Sgibbs	char *index();
25839230Sgibbs
25939230Sgibbs	/*
26039230Sgibbs	 * If we've gone through this code before, free previously
26139230Sgibbs	 * allocated resources.
26239230Sgibbs	 */
26339230Sgibbs	if (num_devices_specified > 0) {
26439230Sgibbs		for (i = 0; i < num_devices_specified; i++)
26539230Sgibbs			free(specified_devices[i]);
26639230Sgibbs		free(specified_devices);
26739230Sgibbs		specified_devices = NULL;
26839230Sgibbs		num_devices_specified = 0;
26939230Sgibbs	}
27039230Sgibbs
27139230Sgibbs	/* do an initial malloc */
27239230Sgibbs	specified_devices = (char **)malloc(sizeof(char *));
27339230Sgibbs
27439230Sgibbs	cp = index(args, '\n');
27539230Sgibbs	if (cp)
27639230Sgibbs		*cp = '\0';
27739230Sgibbs	for (;;) {
27839230Sgibbs		for (cp = args; *cp && isspace(*cp); cp++)
27939230Sgibbs			;
28039230Sgibbs		args = cp;
28139230Sgibbs		for (; *cp && !isspace(*cp); cp++)
28239230Sgibbs			;
28339230Sgibbs		if (*cp)
28439230Sgibbs			*cp++ = '\0';
28539230Sgibbs		if (cp - args == 0)
28639230Sgibbs			break;
28739230Sgibbs		for (i = 0; i < num_devices; i++) {
28839230Sgibbs			char tmpstr[80];
28939230Sgibbs
29039230Sgibbs			sprintf(tmpstr, "%s%d", dev_select[i].device_name,
29139230Sgibbs				dev_select[i].unit_number);
29239230Sgibbs			if (strcmp(args, tmpstr) == 0) {
29339230Sgibbs
29439230Sgibbs				num_devices_specified++;
29539230Sgibbs
29639230Sgibbs				specified_devices =(char **)realloc(
29739230Sgibbs						specified_devices,
29839230Sgibbs						sizeof(char *) *
29939230Sgibbs						num_devices_specified);
30039230Sgibbs				specified_devices[num_devices_specified -1]=
30139230Sgibbs					strdup(args);
30239230Sgibbs
30339230Sgibbs				break;
30439230Sgibbs			}
30539230Sgibbs		}
30639230Sgibbs		if (i >= num_devices)
30739230Sgibbs			error("%s: unknown drive", args);
30839230Sgibbs		args = cp;
30939230Sgibbs	}
31039230Sgibbs
31139230Sgibbs	if (num_devices_specified > 0) {
31239230Sgibbs		last_type = DS_MATCHTYPE_SPEC;
31339230Sgibbs
31439230Sgibbs		retval = selectdevs(&dev_select, &num_selected, &num_selections,
31539230Sgibbs				    &select_generation, generation,
31639230Sgibbs				    s1->dinfo->devices, num_devices, NULL, 0,
31739230Sgibbs				    specified_devices, num_devices_specified,
31839230Sgibbs				    select_mode, maxshowdevs, 0);
31939230Sgibbs		if (retval == -1)
32039230Sgibbs			err(1, "%s", devstat_errbuf);
32139230Sgibbs		else if (retval == 1)
32239230Sgibbs			return(2);
32339230Sgibbs	}
32439230Sgibbs	return(1);
32539230Sgibbs}
326