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 */ 2839230Sgibbs/*- 2939230Sgibbs * Copyright (c) 1980, 1992, 1993 3039230Sgibbs * The Regents of the University of California. All rights reserved. 3139230Sgibbs * 3239230Sgibbs * Redistribution and use in source and binary forms, with or without 3339230Sgibbs * modification, are permitted provided that the following conditions 3439230Sgibbs * are met: 3539230Sgibbs * 1. Redistributions of source code must retain the above copyright 3639230Sgibbs * notice, this list of conditions and the following disclaimer. 3739230Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 3839230Sgibbs * notice, this list of conditions and the following disclaimer in the 3939230Sgibbs * documentation and/or other materials provided with the distribution. 4039230Sgibbs * 4. Neither the name of the University nor the names of its contributors 4139230Sgibbs * may be used to endorse or promote products derived from this software 4239230Sgibbs * without specific prior written permission. 4339230Sgibbs * 4439230Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4539230Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4639230Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4739230Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 4839230Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4939230Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5039230Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5139230Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5239230Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5339230Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5439230Sgibbs * SUCH DAMAGE. 5539230Sgibbs */ 5639230Sgibbs 5787715Smarkm#include <sys/cdefs.h> 5887715Smarkm 5987715Smarkm__FBSDID("$FreeBSD$"); 6087715Smarkm 6187715Smarkm#ifdef lint 6287715Smarkmstatic const char sccsid[] = "@(#)disks.c 8.1 (Berkeley) 6/6/93"; 6387715Smarkm#endif 6487715Smarkm 6539230Sgibbs#include <sys/types.h> 6639230Sgibbs#include <sys/devicestat.h> 67111007Sphk#include <sys/resource.h> 6839230Sgibbs 6987715Smarkm#include <ctype.h> 7039230Sgibbs#include <devstat.h> 7187715Smarkm#include <err.h> 7240060Sobrien#include <stdlib.h> 7387715Smarkm#include <string.h> 7487715Smarkm 7539230Sgibbs#include "systat.h" 7639230Sgibbs#include "extern.h" 7740060Sobrien#include "devs.h" 7839230Sgibbs 7939230Sgibbstypedef enum { 8039230Sgibbs DS_MATCHTYPE_NONE, 8139230Sgibbs DS_MATCHTYPE_SPEC, 8239230Sgibbs DS_MATCHTYPE_PATTERN 8339230Sgibbs} last_match_type; 8439230Sgibbs 8539230Sgibbslast_match_type last_type; 8639230Sgibbsstruct device_selection *dev_select; 8739498Skenlong generation; 8839498Skenint num_devices, num_selected; 8939498Skenint num_selections; 9039498Skenlong select_generation; 9139230Sgibbsstruct devstat_match *matches = NULL; 9239230Sgibbsint num_matches = 0; 9339230Sgibbschar **specified_devices; 9439230Sgibbsint num_devices_specified = 0; 9539230Sgibbs 9687715Smarkmstatic int dsmatchselect(const char *args, devstat_select_mode select_mode, 9739230Sgibbs int maxshowdevs, struct statinfo *s1); 9887715Smarkmstatic int dsselect(const char *args, devstat_select_mode select_mode, 9939230Sgibbs int maxshowdevs, struct statinfo *s1); 10039230Sgibbs 10139230Sgibbsint 10287715Smarkmdsinit(int maxshowdevs, struct statinfo *s1, struct statinfo *s2 __unused, 10387715Smarkm struct statinfo *s3 __unused) 10439230Sgibbs{ 10539230Sgibbs 10639230Sgibbs /* 10739230Sgibbs * Make sure that the userland devstat version matches the kernel 108226396Sed * devstat version. If not, exit and print a message informing 10939230Sgibbs * the user of his mistake. 11039230Sgibbs */ 11183131Sken if (devstat_checkversion(NULL) < 0) 11239230Sgibbs errx(1, "%s", devstat_errbuf); 11339230Sgibbs 11439230Sgibbs generation = 0; 11539230Sgibbs num_devices = 0; 11639230Sgibbs num_selected = 0; 11739230Sgibbs num_selections = 0; 11839230Sgibbs select_generation = 0; 11939230Sgibbs last_type = DS_MATCHTYPE_NONE; 12039230Sgibbs 12183131Sken if (devstat_getdevs(NULL, s1) == -1) 12239230Sgibbs errx(1, "%s", devstat_errbuf); 12339230Sgibbs 12439230Sgibbs num_devices = s1->dinfo->numdevs; 12539230Sgibbs generation = s1->dinfo->generation; 12639230Sgibbs 12739230Sgibbs dev_select = NULL; 12839230Sgibbs 12939230Sgibbs /* 13039230Sgibbs * At this point, selectdevs will almost surely indicate that the 13139230Sgibbs * device list has changed, so we don't look for return values of 0 13239230Sgibbs * or 1. If we get back -1, though, there is an error. 13339230Sgibbs */ 13483131Sken if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, 13583131Sken &select_generation, generation, s1->dinfo->devices, num_devices, 13683131Sken NULL, 0, NULL, 0, DS_SELECT_ADD, maxshowdevs, 0) == -1) 137121291Sphk errx(1, "%d %s", __LINE__, devstat_errbuf); 13839230Sgibbs 13939230Sgibbs return(1); 14039230Sgibbs} 14139230Sgibbs 14239230Sgibbsint 14387715Smarkmdscmd(const char *cmd, const char *args, int maxshowdevs, struct statinfo *s1) 14439230Sgibbs{ 14539230Sgibbs int retval; 14639230Sgibbs 14739230Sgibbs if (prefix(cmd, "display") || prefix(cmd, "add")) 14839230Sgibbs return(dsselect(args, DS_SELECT_ADDONLY, maxshowdevs, s1)); 14939230Sgibbs if (prefix(cmd, "ignore") || prefix(cmd, "delete")) 15039230Sgibbs return(dsselect(args, DS_SELECT_REMOVE, maxshowdevs, s1)); 15139230Sgibbs if (prefix(cmd, "show") || prefix(cmd, "only")) 15239230Sgibbs return(dsselect(args, DS_SELECT_ONLY, maxshowdevs, s1)); 15339230Sgibbs if (prefix(cmd, "type") || prefix(cmd, "match")) 15439230Sgibbs return(dsmatchselect(args, DS_SELECT_ONLY, maxshowdevs, s1)); 15539230Sgibbs if (prefix(cmd, "refresh")) { 15683131Sken retval = devstat_selectdevs(&dev_select, &num_selected, 15783131Sken &num_selections, &select_generation, generation, 158226396Sed s1->dinfo->devices, num_devices, 15983131Sken (last_type ==DS_MATCHTYPE_PATTERN) ? matches : NULL, 16083131Sken (last_type ==DS_MATCHTYPE_PATTERN) ? num_matches : 0, 161226396Sed (last_type == DS_MATCHTYPE_SPEC) ?specified_devices : NULL, 16283131Sken (last_type == DS_MATCHTYPE_SPEC) ?num_devices_specified : 0, 16383131Sken (last_type == DS_MATCHTYPE_NONE) ? DS_SELECT_ADD : 16483131Sken DS_SELECT_ADDONLY, maxshowdevs, 0); 16539230Sgibbs if (retval == -1) { 16639230Sgibbs warnx("%s", devstat_errbuf); 16739230Sgibbs return(0); 16839230Sgibbs } else if (retval == 1) 16939230Sgibbs return(2); 17039230Sgibbs } 17139230Sgibbs if (prefix(cmd, "drives")) { 172175387Sdelphij int i; 17339230Sgibbs move(CMDLINE, 0); 17439230Sgibbs clrtoeol(); 17539230Sgibbs for (i = 0; i < num_devices; i++) { 17639230Sgibbs printw("%s%d ", s1->dinfo->devices[i].device_name, 17739230Sgibbs s1->dinfo->devices[i].unit_number); 17839230Sgibbs } 17939230Sgibbs return(1); 18039230Sgibbs } 18139230Sgibbs return(0); 18239230Sgibbs} 18339230Sgibbs 18439230Sgibbsstatic int 18587715Smarkmdsmatchselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, 18639230Sgibbs struct statinfo *s1) 18739230Sgibbs{ 18887715Smarkm char **tempstr, *tmpstr, *tmpstr1; 18939230Sgibbs char *tstr[100]; 19039230Sgibbs int num_args = 0; 19187715Smarkm int i; 19239230Sgibbs int retval = 0; 19339230Sgibbs 19439230Sgibbs /* 19539230Sgibbs * Break the (pipe delimited) input string out into separate 19639230Sgibbs * strings. 19739230Sgibbs */ 19887715Smarkm tmpstr = tmpstr1 = strdup(args); 19939230Sgibbs for (tempstr = tstr, num_args = 0; 20087715Smarkm (*tempstr = strsep(&tmpstr1, "|")) != NULL && (num_args < 100); 20139230Sgibbs num_args++) 20239230Sgibbs if (**tempstr != '\0') 20339230Sgibbs if (++tempstr >= &tstr[100]) 20439230Sgibbs break; 20587715Smarkm free(tmpstr); 20639230Sgibbs 20739230Sgibbs if (num_args > 99) { 20839230Sgibbs warnx("dsmatchselect: too many match arguments"); 20939230Sgibbs return(0); 21039230Sgibbs } 21139230Sgibbs 21239230Sgibbs /* 21339230Sgibbs * If we've gone through the matching code before, clean out 21439230Sgibbs * previously used memory. 21539230Sgibbs */ 21639230Sgibbs if (num_matches > 0) { 21739230Sgibbs free(matches); 21839230Sgibbs matches = NULL; 21939230Sgibbs num_matches = 0; 22039230Sgibbs } 22139230Sgibbs 22239230Sgibbs for (i = 0; i < num_args; i++) { 223226396Sed if (devstat_buildmatch(tstr[i], &matches, &num_matches) != 0) { 22439230Sgibbs warnx("%s", devstat_errbuf); 22539230Sgibbs return(0); 22639230Sgibbs } 22739230Sgibbs } 22839230Sgibbs if (num_args > 0) { 22939230Sgibbs 23039230Sgibbs last_type = DS_MATCHTYPE_PATTERN; 23139230Sgibbs 23283131Sken retval = devstat_selectdevs(&dev_select, &num_selected, 23383131Sken &num_selections, &select_generation, generation, 23483131Sken s1->dinfo->devices, num_devices, matches, num_matches, 23583131Sken NULL, 0, select_mode, maxshowdevs, 0); 23639230Sgibbs if (retval == -1) 23739230Sgibbs err(1, "device selection error"); 23839230Sgibbs else if (retval == 1) 23939230Sgibbs return(2); 24039230Sgibbs } 24139230Sgibbs return(1); 24239230Sgibbs} 24339230Sgibbs 24439230Sgibbsstatic int 24587715Smarkmdsselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, 24639230Sgibbs struct statinfo *s1) 24739230Sgibbs{ 24887715Smarkm char *cp, *tmpstr, *tmpstr1, *buffer; 24987715Smarkm int i; 25039230Sgibbs int retval = 0; 25139230Sgibbs 25239230Sgibbs /* 25339230Sgibbs * If we've gone through this code before, free previously 25439230Sgibbs * allocated resources. 25539230Sgibbs */ 25639230Sgibbs if (num_devices_specified > 0) { 25739230Sgibbs for (i = 0; i < num_devices_specified; i++) 25839230Sgibbs free(specified_devices[i]); 25939230Sgibbs free(specified_devices); 26039230Sgibbs specified_devices = NULL; 26139230Sgibbs num_devices_specified = 0; 26239230Sgibbs } 26339230Sgibbs 26439230Sgibbs /* do an initial malloc */ 26539230Sgibbs specified_devices = (char **)malloc(sizeof(char *)); 26639230Sgibbs 26787715Smarkm tmpstr = tmpstr1 = strdup(args); 268229403Sed cp = strchr(tmpstr1, '\n'); 26939230Sgibbs if (cp) 27039230Sgibbs *cp = '\0'; 27139230Sgibbs for (;;) { 27287715Smarkm for (cp = tmpstr1; *cp && isspace(*cp); cp++) 27339230Sgibbs ; 27487715Smarkm tmpstr1 = cp; 27539230Sgibbs for (; *cp && !isspace(*cp); cp++) 27639230Sgibbs ; 27739230Sgibbs if (*cp) 27839230Sgibbs *cp++ = '\0'; 27939230Sgibbs if (cp - args == 0) 28039230Sgibbs break; 28139230Sgibbs for (i = 0; i < num_devices; i++) { 28287715Smarkm asprintf(&buffer, "%s%d", dev_select[i].device_name, 28339230Sgibbs dev_select[i].unit_number); 28487715Smarkm if (strcmp(buffer, tmpstr1) == 0) { 285226396Sed 28639230Sgibbs num_devices_specified++; 28739230Sgibbs 28839230Sgibbs specified_devices =(char **)realloc( 28939230Sgibbs specified_devices, 29039230Sgibbs sizeof(char *) * 29139230Sgibbs num_devices_specified); 29239230Sgibbs specified_devices[num_devices_specified -1]= 29387715Smarkm strdup(tmpstr1); 29487715Smarkm free(buffer); 29539230Sgibbs 29639230Sgibbs break; 29739230Sgibbs } 29887715Smarkm else 29987715Smarkm free(buffer); 30039230Sgibbs } 30139230Sgibbs if (i >= num_devices) 30239230Sgibbs error("%s: unknown drive", args); 30339230Sgibbs args = cp; 30439230Sgibbs } 30587715Smarkm free(tmpstr); 30639230Sgibbs 30739230Sgibbs if (num_devices_specified > 0) { 30839230Sgibbs last_type = DS_MATCHTYPE_SPEC; 30939230Sgibbs 31083131Sken retval = devstat_selectdevs(&dev_select, &num_selected, 31183131Sken &num_selections, &select_generation, generation, 31283131Sken s1->dinfo->devices, num_devices, NULL, 0, 31383131Sken specified_devices, num_devices_specified, 31483131Sken select_mode, maxshowdevs, 0); 31539230Sgibbs if (retval == -1) 31639230Sgibbs err(1, "%s", devstat_errbuf); 31739230Sgibbs else if (retval == 1) 31839230Sgibbs return(2); 31939230Sgibbs } 32039230Sgibbs return(1); 32139230Sgibbs} 322