freebsd-dev/usr.sbin/lsdev/lsdev.c

220 lines
4.0 KiB
C

#include "lsdev.h"
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <ctype.h>
#include <string.h>
const char *const devtypes[] = DEVTYPENAMES;
int vflag = 0;
const char *whoami;
static void usage(void);
static void badtype(const char *);
static void badname(const char *);
static void print_pretty(struct devconf *);
static void hprint_pretty(void);
int
main(int argc, char **argv)
{
struct devconf *dc = 0;
size_t size, osize;
int ndevs, i;
int mib[8];
int c;
int showonlytype = -1;
int showonlydev = 0;
char showonlydevclass[MAXDEVNAME];
int showonlydevunit = -1;
void (*prtfcn)(struct devconf *) = print_pretty;
void (*hprtfcn)(void) = hprint_pretty;
whoami = argv[0];
while((c = getopt(argc, argv, "t:vc")) != EOF) {
switch(c) {
case 't':
showonlytype = findtype(optarg);
if(showonlytype < 0)
badtype(optarg);
break;
case 'v':
vflag++;
break;
case 'c':
prtfcn = print_config;
hprtfcn = hprint_config;
break;
default:
usage();
break;
}
}
if(argc - optind > 1) {
usage();
}
if(argv[optind]) {
char *s = &argv[optind][strlen(argv[optind])];
if(s - argv[optind] > MAXDEVNAME)
badname(argv[optind]);
s--; /* step over null */
while(s > argv[optind] && isdigit(*s))
s--;
s++;
if(*s) {
showonlydevunit = atoi(s);
*s = '\0';
} else {
showonlydevunit = -1;
}
strcpy(showonlydevclass, argv[optind]);
showonlydev = 1;
}
mib[0] = CTL_HW;
mib[1] = HW_DEVCONF;
mib[2] = DEVCONF_NUMBER;
size = sizeof ndevs;
if(sysctl(mib, 3, &ndevs, &size, 0, 0) < 0) {
err(1, "sysctl(hw.devconf.number)");
}
osize = 0;
hprtfcn();
for(i = 1; i <= ndevs; i++) {
mib[2] = i;
if(sysctl(mib, 3, 0, &size, 0, 0) < 0) {
/*
* Probably a deleted device; just go on to the next
* one.
*/
continue;
}
if(size > osize) {
dc = realloc(dc, size);
if(!dc) {
err(2, "realloc(%lu)", (unsigned long)size);
}
}
if(sysctl(mib, 3, dc, &size, 0, 0) < 0) {
err(1, "sysctl(hw.devconf.%d)", i);
}
if(!showonlydev && showonlytype < 0) {
prtfcn(dc);
} else if(showonlydev) {
if(!strcmp(showonlydevclass, dc->dc_name)
&& (showonlydevunit < 0 ||
showonlydevunit == dc->dc_unit))
prtfcn(dc);
} else if(showonlytype == dc->dc_devtype) {
prtfcn(dc);
}
osize = size;
}
return 0;
}
static void
usage(void)
{
fprintf(stderr,
"usage:\n"
"\t%s [-t type] [-v] [name]\n",
whoami);
exit(-1);
}
int
findtype(const char *name)
{
int i;
for(i = 0; devtypes[i]; i++) {
if(!strcmp(name, devtypes[i]))
return i;
}
return -1;
}
static void
badtype(const char *name)
{
int i;
fprintf(stderr,
"%s: invalid device type `%s'\n", whoami, name);
fprintf(stderr,
"%s: valid types are: ", whoami);
for(i = 0; devtypes[i]; i++) {
fprintf(stderr, "%s`%s'", i ? ", " : "", devtypes[i]);
}
fputs(".\n", stderr);
exit(-1);
}
static void
badname(const char *name)
{
errx(3, "invalid device name `%s'", name);
}
static void
hprint_pretty(void)
{
printf("%-10.10s ", "Device");
if(vflag) {
printf("%-2.2s %-10.10s ", "St", "Parent");
} else {
printf("%-15.15s ", "State");
}
printf("%s\n", "Description");
printf("%-10.10s ", "----------");
if(vflag) {
printf("%-2.2s %-10.10s ", "--", "----------");
} else {
printf("%-15.15s ", "---------------");
}
printf("%s\n", "--------------------------------------------------");
}
static const char *const states[] = { "??", "NC", "I", "B" };
static const char *const longstates[] = {
"Unknown", "Unconfigured", "Idle", "Busy"
};
static void
print_pretty(struct devconf *dc)
{
char buf[MAXDEVNAME * 2];
snprintf(buf, sizeof buf, "%s%d", dc->dc_name, dc->dc_unit);
if(vflag) {
printf("%-10.10s %2.2s ", buf, states[dc->dc_state]);
if(dc->dc_punit >= 0) {
snprintf(buf, sizeof buf, "%s%d", dc->dc_pname,
dc->dc_punit);
} else {
buf[0] = '-';
buf[1] = '\0';
}
printf("%-10.10s ", buf);
} else {
printf("%-10.10s %-15.15s ", buf, longstates[dc->dc_state]);
}
printf("%s\n", dc->dc_descr);
}