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