pccardq.c revision 50488
150488Speter/* $FreeBSD: head/usr.sbin/apmd/contrib/pccardq.c 50488 1999-08-28 05:11:36Z peter $ */ 248730Siwasaki 348730Siwasaki#include <err.h> 448730Siwasaki#include <errno.h> 548730Siwasaki#include <limits.h> 648730Siwasaki#include <stdarg.h> 748730Siwasaki#include <stddef.h> 848730Siwasaki#include <stdio.h> 948730Siwasaki#include <stdlib.h> 1048730Siwasaki#include <string.h> 1148730Siwasaki#include <time.h> 1248730Siwasaki#include <unistd.h> 1348730Siwasaki#include <sys/types.h> 1448730Siwasaki#include <sys/socket.h> 1548730Siwasaki#include <sys/un.h> 1648730Siwasaki 1748730Siwasakiconst char *const pccardd_file = "/var/tmp/.pccardd"; 1848730Siwasakiconst char *prog = "pccardq"; 1948730Siwasakiconst char *tmp_dir = "/tmp"; 2048730Siwasakiunsigned slot_map = ~0; 2148730Siwasaki 2248730Siwasakivoid 2348730Siwasakiusage() 2448730Siwasaki{ 2548730Siwasaki fprintf(stderr, "usage: %s [-a] [-n] [-s slot]\n", prog); 2648730Siwasaki} 2748730Siwasaki 2848730Siwasakiint 2948730Siwasakiproc_arg(int ac, char **av) 3048730Siwasaki{ 3148730Siwasaki int rc = -1; 3248730Siwasaki int ch; 3348730Siwasaki 3448730Siwasaki char *p = strrchr(av[0], '/'); 3548730Siwasaki prog = p ? p + 1 : av[0]; 3648730Siwasaki 3748730Siwasaki tmp_dir = getenv("TMPDIR") ? getenv("TMPDIR") : tmp_dir; 3848730Siwasaki 3948730Siwasaki while ((ch = getopt(ac, av, "ans:")) != EOF) { 4048730Siwasaki switch (ch) { 4148730Siwasaki case 'a': 4248730Siwasaki slot_map = ~0; 4348730Siwasaki break; 4448730Siwasaki case 'n': 4548730Siwasaki slot_map = 0; 4648730Siwasaki break; 4748730Siwasaki case 's': 4848730Siwasaki { 4948730Siwasaki int n = atoi(optarg); 5048730Siwasaki if (n < 0 || n >= CHAR_BIT * sizeof slot_map) { 5148730Siwasaki warnc(0, "Invalid slot number."); 5248730Siwasaki usage(); 5348730Siwasaki goto out; 5448730Siwasaki } 5548730Siwasaki if (slot_map == ~0) 5648730Siwasaki slot_map = 0; 5748730Siwasaki slot_map |= 1 << n; 5848730Siwasaki } 5948730Siwasaki break; 6048730Siwasaki default: 6148730Siwasaki usage(); 6248730Siwasaki goto out; 6348730Siwasaki } 6448730Siwasaki } 6548730Siwasaki 6648730Siwasaki rc = 0; 6748730Siwasaki out: 6848730Siwasaki return rc; 6948730Siwasaki} 7048730Siwasaki 7148730Siwasakiint 7248730Siwasakiconnect_to_pccardd(char **path) 7348730Siwasaki{ 7448730Siwasaki int so = -1; 7548730Siwasaki int pccardd_len; 7648730Siwasaki struct sockaddr_un pccardq; 7748730Siwasaki struct sockaddr_un pccardd; 7848730Siwasaki 7948730Siwasaki if ((so = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { 8048730Siwasaki warn("socket"); 8148730Siwasaki goto err; 8248730Siwasaki } 8348730Siwasaki 8448730Siwasaki snprintf(pccardq.sun_path, sizeof pccardq.sun_path, 8548730Siwasaki "%s/%s%ld%ld", tmp_dir, prog, (long) getpid(), (long) time(0)); 8648730Siwasaki pccardq.sun_family = AF_UNIX; 8748730Siwasaki pccardq.sun_len = offsetof(struct sockaddr_un, sun_path) + strlen(pccardq.sun_path); 8848730Siwasaki if (bind(so, (struct sockaddr *) &pccardq, pccardq.sun_len) < 0) { 8948730Siwasaki warn("bind: %s", pccardq.sun_path); 9048730Siwasaki goto err; 9148730Siwasaki } 9248730Siwasaki if ((*path = strdup(pccardq.sun_path)) == NULL) { 9348730Siwasaki warn("strdup"); 9448730Siwasaki goto err; 9548730Siwasaki } 9648730Siwasaki 9748730Siwasaki pccardd_len = strlen(pccardd_file) + 1; 9848730Siwasaki if (pccardd_len > sizeof pccardd.sun_path) { 9948730Siwasaki warnc(0, "%s: too long", pccardd_file); 10048730Siwasaki goto err; 10148730Siwasaki } 10248730Siwasaki pccardd.sun_len = offsetof(struct sockaddr_un, sun_path) + pccardd_len; 10348730Siwasaki pccardd.sun_family = AF_UNIX; 10448730Siwasaki strcpy(pccardd.sun_path, pccardd_file); 10548730Siwasaki if (connect(so, (struct sockaddr *) &pccardd, pccardd.sun_len) < 0) { 10648730Siwasaki warn("connect: %s", pccardd_file); 10748730Siwasaki goto err; 10848730Siwasaki } 10948730Siwasaki return so; 11048730Siwasaki err: 11148730Siwasaki if (so >= 0) 11248730Siwasaki close(so); 11348730Siwasaki return -1; 11448730Siwasaki} 11548730Siwasaki 11648730Siwasakiint 11748730Siwasakiget_slot_number(int so) 11848730Siwasaki{ 11948730Siwasaki char buf[8]; 12048730Siwasaki int rv; 12148730Siwasaki int nslot; 12248730Siwasaki 12348730Siwasaki if ((rv = write(so, "S", 1)) < 1) { 12448730Siwasaki warn("write"); 12548730Siwasaki goto err; 12648730Siwasaki } else if (rv != 1) { 12748730Siwasaki warnc(0, "write: fail."); 12848730Siwasaki goto err; 12948730Siwasaki } 13048730Siwasaki 13148730Siwasaki if ((rv = read(so, buf, sizeof buf)) < 0) { 13248730Siwasaki warn("read"); 13348730Siwasaki goto err; 13448730Siwasaki } 13548730Siwasaki buf[sizeof buf - 1] = 0; 13648730Siwasaki if (sscanf(buf, "%d", &nslot) != 1) { 13748730Siwasaki warnc(0, "Invalid response."); 13848730Siwasaki goto err; 13948730Siwasaki } 14048730Siwasaki return nslot; 14148730Siwasaki err: 14248730Siwasaki return -1; 14348730Siwasaki} 14448730Siwasaki 14548730Siwasakienum { 14648730Siwasaki SLOT_EMPTY = 0, 14748730Siwasaki SLOT_FILLED = 1, 14848730Siwasaki SLOT_INACTIVE = 2, 14948730Siwasaki SLOT_UNDEFINED = 9 15048730Siwasaki}; 15148730Siwasaki 15248730Siwasakiint 15348730Siwasakiget_slot_info(int so, int slot, char **manuf, char **version, char 15448730Siwasaki **device, int *state) 15548730Siwasaki{ 15648730Siwasaki int rc = -1; 15748730Siwasaki int rv; 15848730Siwasaki static char buf[1024]; 15948730Siwasaki int slen; 16048730Siwasaki char *s; 16148730Siwasaki char *sl; 16248730Siwasaki 16348730Siwasaki char *_manuf; 16448730Siwasaki char *_version; 16548730Siwasaki char *_device; 16648730Siwasaki 16748730Siwasaki slen = snprintf(buf, sizeof buf, "N%d", slot); 16848730Siwasaki if ((rv = write(so, buf, slen)) < 0) { 16948730Siwasaki warn("write"); 17048730Siwasaki goto err; 17148730Siwasaki } else if (rv != slen) { 17248730Siwasaki warnc(0, "write"); 17348730Siwasaki goto err; 17448730Siwasaki } 17548730Siwasaki 17648730Siwasaki if ((rv = read(so, buf, sizeof buf)) < 0) { 17748730Siwasaki warn("read"); 17848730Siwasaki goto err; 17948730Siwasaki } 18048730Siwasaki 18148730Siwasaki s = buf; 18248730Siwasaki if ((sl = strsep(&s, "~")) == NULL) 18348730Siwasaki goto parse_err; 18448730Siwasaki if (atoi(sl) != slot) 18548730Siwasaki goto parse_err; 18648730Siwasaki if ((_manuf = strsep(&s, "~")) == NULL) 18748730Siwasaki goto parse_err; 18848730Siwasaki if ((_version = strsep(&s, "~")) == NULL) 18948730Siwasaki goto parse_err; 19048730Siwasaki if ((_device = strsep(&s, "~")) == NULL) 19148730Siwasaki goto parse_err; 19248730Siwasaki if (sscanf(s, "%1d", state) != 1) 19348730Siwasaki goto parse_err; 19448730Siwasaki if (s != NULL && strchr(s, '~') != NULL) 19548730Siwasaki goto parse_err; 19648730Siwasaki 19748730Siwasaki *manuf = strdup(_manuf); 19848730Siwasaki *version = strdup(_version); 19948730Siwasaki *device = strdup(_device); 20048730Siwasaki if (*manuf == NULL || *version == NULL || *device == NULL) { 20148730Siwasaki warn("strdup"); 20248730Siwasaki goto err; 20348730Siwasaki } 20448730Siwasaki 20548730Siwasaki rc = 0; 20648730Siwasaki err: 20748730Siwasaki return rc; 20848730Siwasaki parse_err: 20948730Siwasaki warnc(0, "Invalid response: %*s", rv, buf); 21048730Siwasaki return rc; 21148730Siwasaki} 21248730Siwasaki 21348730Siwasakiconst char * 21448730Siwasakistrstate(int state) 21548730Siwasaki{ 21648730Siwasaki switch (state) { 21748730Siwasaki case 0: 21848730Siwasaki return "empty"; 21948730Siwasaki case 1: 22048730Siwasaki return "filled"; 22148730Siwasaki case 2: 22248730Siwasaki return "inactive"; 22348730Siwasaki default: 22448730Siwasaki return "unknown"; 22548730Siwasaki } 22648730Siwasaki} 22748730Siwasaki 22848730Siwasakiint 22948730Siwasakimain(int ac, char **av) 23048730Siwasaki{ 23148730Siwasaki char *path = NULL; 23248730Siwasaki int so = -1; 23348730Siwasaki int nslot; 23448730Siwasaki int i; 23548730Siwasaki 23648730Siwasaki if (proc_arg(ac, av) < 0) 23748730Siwasaki goto out; 23848730Siwasaki if ((so = connect_to_pccardd(&path)) < 0) 23948730Siwasaki goto out; 24048730Siwasaki if ((nslot = get_slot_number(so)) < 0) 24148730Siwasaki goto out; 24248730Siwasaki if (slot_map == 0) { 24348730Siwasaki printf("%d\n", nslot); 24448730Siwasaki } else { 24548730Siwasaki for (i = 0; i < nslot; i++) { 24648730Siwasaki if ((slot_map & (1 << i))) { 24748730Siwasaki char *manuf; 24848730Siwasaki char *version; 24948730Siwasaki char *device; 25048730Siwasaki int state; 25148730Siwasaki 25248730Siwasaki if (get_slot_info(so, i, &manuf, &version, &device, 25348730Siwasaki &state) < 0) 25448730Siwasaki goto out; 25548730Siwasaki if (manuf == NULL || version == NULL || device == NULL) 25648730Siwasaki goto out; 25748730Siwasaki printf("%d~%s~%s~%s~%s\n", 25848730Siwasaki i, manuf, version, device, strstate(state)); 25948730Siwasaki free(manuf); 26048730Siwasaki free(version); 26148730Siwasaki free(device); 26248730Siwasaki } 26348730Siwasaki } 26448730Siwasaki } 26548730Siwasaki out: 26648730Siwasaki if (path) { 26748730Siwasaki unlink(path); 26848730Siwasaki free(path); 26948730Siwasaki } 27048730Siwasaki if (so >= 0) 27148730Siwasaki close(so); 27248730Siwasaki exit(0); 27348730Siwasaki} 274