150488Speter/* $FreeBSD$ */ 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 23208075Suqsusage(void) 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 39166509Skevlo while ((ch = getopt(ac, av, "ans:")) != -1) { 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 16781982Sbrian if ((slen = snprintf(buf, sizeof buf, "N%d", slot)) < 0) { 16881977Sbrian warnc(0, "write"); 16981977Sbrian goto err; 17081977Sbrian } 17181977Sbrian 17248730Siwasaki if ((rv = write(so, buf, slen)) < 0) { 17348730Siwasaki warn("write"); 17448730Siwasaki goto err; 17548730Siwasaki } else if (rv != slen) { 17648730Siwasaki warnc(0, "write"); 17748730Siwasaki goto err; 17848730Siwasaki } 17948730Siwasaki 18048730Siwasaki if ((rv = read(so, buf, sizeof buf)) < 0) { 18148730Siwasaki warn("read"); 18248730Siwasaki goto err; 18348730Siwasaki } 18448730Siwasaki 18548730Siwasaki s = buf; 18648730Siwasaki if ((sl = strsep(&s, "~")) == NULL) 18748730Siwasaki goto parse_err; 18848730Siwasaki if (atoi(sl) != slot) 18948730Siwasaki goto parse_err; 19048730Siwasaki if ((_manuf = strsep(&s, "~")) == NULL) 19148730Siwasaki goto parse_err; 19248730Siwasaki if ((_version = strsep(&s, "~")) == NULL) 19348730Siwasaki goto parse_err; 19448730Siwasaki if ((_device = strsep(&s, "~")) == NULL) 19548730Siwasaki goto parse_err; 19648730Siwasaki if (sscanf(s, "%1d", state) != 1) 19748730Siwasaki goto parse_err; 19848730Siwasaki if (s != NULL && strchr(s, '~') != NULL) 19948730Siwasaki goto parse_err; 20048730Siwasaki 20171277Sjedgar if ((*manuf = strdup(_manuf)) == NULL) { 20271277Sjedgar warn("strdup"); 20371277Sjedgar goto err; 20471277Sjedgar } 20571277Sjedgar if ((*version = strdup(_version)) == NULL) { 20671277Sjedgar warn("strdup"); 20771277Sjedgar goto err; 20871277Sjedgar } 20971277Sjedgar if ((*device = strdup(_device)) == NULL) { 21071277Sjedgar warn("strdup"); 21171277Sjedgar goto err; 21271277Sjedgar } 21348730Siwasaki if (*manuf == NULL || *version == NULL || *device == NULL) { 21448730Siwasaki warn("strdup"); 21548730Siwasaki goto err; 21648730Siwasaki } 21748730Siwasaki 21848730Siwasaki rc = 0; 21948730Siwasaki err: 22048730Siwasaki return rc; 22148730Siwasaki parse_err: 22248730Siwasaki warnc(0, "Invalid response: %*s", rv, buf); 22348730Siwasaki return rc; 22448730Siwasaki} 22548730Siwasaki 226208075Suqsconst char * 22748730Siwasakistrstate(int state) 22848730Siwasaki{ 22948730Siwasaki switch (state) { 23048730Siwasaki case 0: 23148730Siwasaki return "empty"; 23248730Siwasaki case 1: 23348730Siwasaki return "filled"; 23448730Siwasaki case 2: 23548730Siwasaki return "inactive"; 23648730Siwasaki default: 23748730Siwasaki return "unknown"; 23848730Siwasaki } 23948730Siwasaki} 24048730Siwasaki 24148730Siwasakiint 24248730Siwasakimain(int ac, char **av) 24348730Siwasaki{ 24448730Siwasaki char *path = NULL; 24548730Siwasaki int so = -1; 24648730Siwasaki int nslot; 24748730Siwasaki int i; 24848730Siwasaki 24948730Siwasaki if (proc_arg(ac, av) < 0) 25048730Siwasaki goto out; 25148730Siwasaki if ((so = connect_to_pccardd(&path)) < 0) 25248730Siwasaki goto out; 25348730Siwasaki if ((nslot = get_slot_number(so)) < 0) 25448730Siwasaki goto out; 25548730Siwasaki if (slot_map == 0) { 25648730Siwasaki printf("%d\n", nslot); 25748730Siwasaki } else { 25848730Siwasaki for (i = 0; i < nslot; i++) { 25948730Siwasaki if ((slot_map & (1 << i))) { 26048730Siwasaki char *manuf; 26148730Siwasaki char *version; 26248730Siwasaki char *device; 26348730Siwasaki int state; 26448730Siwasaki 26548730Siwasaki if (get_slot_info(so, i, &manuf, &version, &device, 26648730Siwasaki &state) < 0) 26748730Siwasaki goto out; 26848730Siwasaki if (manuf == NULL || version == NULL || device == NULL) 26948730Siwasaki goto out; 27048730Siwasaki printf("%d~%s~%s~%s~%s\n", 27148730Siwasaki i, manuf, version, device, strstate(state)); 27248730Siwasaki free(manuf); 27348730Siwasaki free(version); 27448730Siwasaki free(device); 27548730Siwasaki } 27648730Siwasaki } 27748730Siwasaki } 27848730Siwasaki out: 27948730Siwasaki if (path) { 28048730Siwasaki unlink(path); 28148730Siwasaki free(path); 28248730Siwasaki } 28348730Siwasaki if (so >= 0) 28448730Siwasaki close(so); 28548730Siwasaki exit(0); 28648730Siwasaki} 287