pccardq.c revision 81977
1251875Speter/* $FreeBSD: head/usr.sbin/apmd/contrib/pccardq.c 81977 2001-08-20 13:24:39Z brian $ */ 2251875Speter 3251875Speter#include <err.h> 4251875Speter#include <errno.h> 5251875Speter#include <limits.h> 6251875Speter#include <stdarg.h> 7251875Speter#include <stddef.h> 8251875Speter#include <stdio.h> 9251875Speter#include <stdlib.h> 10251875Speter#include <string.h> 11251875Speter#include <time.h> 12251875Speter#include <unistd.h> 13251875Speter#include <sys/types.h> 14251875Speter#include <sys/socket.h> 15251875Speter#include <sys/un.h> 16251875Speter 17251875Speterconst char *const pccardd_file = "/var/tmp/.pccardd"; 18251875Speterconst char *prog = "pccardq"; 19251875Speterconst char *tmp_dir = "/tmp"; 20251875Speterunsigned slot_map = ~0; 21251875Speter 22251875Spetervoid 23251875Speterusage() 24251875Speter{ 25251875Speter fprintf(stderr, "usage: %s [-a] [-n] [-s slot]\n", prog); 26251875Speter} 27251875Speter 28251875Speterint 29251875Speterproc_arg(int ac, char **av) 30251875Speter{ 31251875Speter int rc = -1; 32251875Speter int ch; 33251875Speter 34251875Speter char *p = strrchr(av[0], '/'); 35251875Speter prog = p ? p + 1 : av[0]; 36251875Speter 37251875Speter tmp_dir = getenv("TMPDIR") ? getenv("TMPDIR") : tmp_dir; 38251875Speter 39251875Speter while ((ch = getopt(ac, av, "ans:")) != EOF) { 40251875Speter switch (ch) { 41251875Speter case 'a': 42251875Speter slot_map = ~0; 43251875Speter break; 44251875Speter case 'n': 45251875Speter slot_map = 0; 46251875Speter break; 47251875Speter case 's': 48251875Speter { 49251875Speter int n = atoi(optarg); 50251875Speter if (n < 0 || n >= CHAR_BIT * sizeof slot_map) { 51251875Speter warnc(0, "Invalid slot number."); 52251875Speter usage(); 53251875Speter goto out; 54251875Speter } 55251875Speter if (slot_map == ~0) 56251875Speter slot_map = 0; 57251875Speter slot_map |= 1 << n; 58251875Speter } 59251875Speter break; 60251875Speter default: 61251875Speter usage(); 62251875Speter goto out; 63251875Speter } 64251875Speter } 65251875Speter 66251875Speter rc = 0; 67251875Speter out: 68251875Speter return rc; 69251875Speter} 70251875Speter 71251875Speterint 72251875Speterconnect_to_pccardd(char **path) 73251875Speter{ 74251875Speter int so = -1; 75251875Speter int pccardd_len; 76251875Speter struct sockaddr_un pccardq; 77251875Speter struct sockaddr_un pccardd; 78251875Speter 79251875Speter if ((so = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { 80251875Speter warn("socket"); 81251875Speter goto err; 82251875Speter } 83251875Speter 84251875Speter snprintf(pccardq.sun_path, sizeof pccardq.sun_path, 85251875Speter "%s/%s%ld%ld", tmp_dir, prog, (long) getpid(), (long) time(0)); 86251875Speter pccardq.sun_family = AF_UNIX; 87251875Speter pccardq.sun_len = offsetof(struct sockaddr_un, sun_path) + strlen(pccardq.sun_path); 88251875Speter if (bind(so, (struct sockaddr *) &pccardq, pccardq.sun_len) < 0) { 89251875Speter warn("bind: %s", pccardq.sun_path); 90251875Speter goto err; 91251875Speter } 92251875Speter if ((*path = strdup(pccardq.sun_path)) == NULL) { 93251875Speter warn("strdup"); 94251875Speter goto err; 95251875Speter } 96251875Speter 97251875Speter pccardd_len = strlen(pccardd_file) + 1; 98251875Speter if (pccardd_len > sizeof pccardd.sun_path) { 99251875Speter warnc(0, "%s: too long", pccardd_file); 100251875Speter goto err; 101251875Speter } 102251875Speter pccardd.sun_len = offsetof(struct sockaddr_un, sun_path) + pccardd_len; 103251875Speter pccardd.sun_family = AF_UNIX; 104251875Speter strcpy(pccardd.sun_path, pccardd_file); 105251875Speter if (connect(so, (struct sockaddr *) &pccardd, pccardd.sun_len) < 0) { 106251875Speter warn("connect: %s", pccardd_file); 107251875Speter goto err; 108251875Speter } 109251875Speter return so; 110251875Speter err: 111251875Speter if (so >= 0) 112251875Speter close(so); 113251875Speter return -1; 114251875Speter} 115251875Speter 116251875Speterint 117251875Speterget_slot_number(int so) 118251875Speter{ 119251875Speter char buf[8]; 120251875Speter int rv; 121251875Speter int nslot; 122251875Speter 123251875Speter if ((rv = write(so, "S", 1)) < 1) { 124251875Speter warn("write"); 125251875Speter goto err; 126251875Speter } else if (rv != 1) { 127251875Speter warnc(0, "write: fail."); 128251875Speter goto err; 129251875Speter } 130251875Speter 131251875Speter if ((rv = read(so, buf, sizeof buf)) < 0) { 132251875Speter warn("read"); 133251875Speter goto err; 134251875Speter } 135251875Speter buf[sizeof buf - 1] = 0; 136251875Speter if (sscanf(buf, "%d", &nslot) != 1) { 137251875Speter warnc(0, "Invalid response."); 138251875Speter goto err; 139251875Speter } 140251875Speter return nslot; 141251875Speter err: 142251875Speter return -1; 143251875Speter} 144251875Speter 145251875Speterenum { 146251875Speter SLOT_EMPTY = 0, 147251875Speter SLOT_FILLED = 1, 148251875Speter SLOT_INACTIVE = 2, 149251875Speter SLOT_UNDEFINED = 9 150}; 151 152int 153get_slot_info(int so, int slot, char **manuf, char **version, char 154 **device, int *state) 155{ 156 int rc = -1; 157 int rv; 158 static char buf[1024]; 159 int slen; 160 char *s; 161 char *sl; 162 163 char *_manuf; 164 char *_version; 165 char *_device; 166 167 if ((slen = snprintf(buf, sizeof buf, "N%d", slot)) == -1) { 168 warnc(0, "write"); 169 goto err; 170 } 171 172 if ((rv = write(so, buf, slen)) < 0) { 173 warn("write"); 174 goto err; 175 } else if (rv != slen) { 176 warnc(0, "write"); 177 goto err; 178 } 179 180 if ((rv = read(so, buf, sizeof buf)) < 0) { 181 warn("read"); 182 goto err; 183 } 184 185 s = buf; 186 if ((sl = strsep(&s, "~")) == NULL) 187 goto parse_err; 188 if (atoi(sl) != slot) 189 goto parse_err; 190 if ((_manuf = strsep(&s, "~")) == NULL) 191 goto parse_err; 192 if ((_version = strsep(&s, "~")) == NULL) 193 goto parse_err; 194 if ((_device = strsep(&s, "~")) == NULL) 195 goto parse_err; 196 if (sscanf(s, "%1d", state) != 1) 197 goto parse_err; 198 if (s != NULL && strchr(s, '~') != NULL) 199 goto parse_err; 200 201 if ((*manuf = strdup(_manuf)) == NULL) { 202 warn("strdup"); 203 goto err; 204 } 205 if ((*version = strdup(_version)) == NULL) { 206 warn("strdup"); 207 goto err; 208 } 209 if ((*device = strdup(_device)) == NULL) { 210 warn("strdup"); 211 goto err; 212 } 213 if (*manuf == NULL || *version == NULL || *device == NULL) { 214 warn("strdup"); 215 goto err; 216 } 217 218 rc = 0; 219 err: 220 return rc; 221 parse_err: 222 warnc(0, "Invalid response: %*s", rv, buf); 223 return rc; 224} 225 226const char * 227strstate(int state) 228{ 229 switch (state) { 230 case 0: 231 return "empty"; 232 case 1: 233 return "filled"; 234 case 2: 235 return "inactive"; 236 default: 237 return "unknown"; 238 } 239} 240 241int 242main(int ac, char **av) 243{ 244 char *path = NULL; 245 int so = -1; 246 int nslot; 247 int i; 248 249 if (proc_arg(ac, av) < 0) 250 goto out; 251 if ((so = connect_to_pccardd(&path)) < 0) 252 goto out; 253 if ((nslot = get_slot_number(so)) < 0) 254 goto out; 255 if (slot_map == 0) { 256 printf("%d\n", nslot); 257 } else { 258 for (i = 0; i < nslot; i++) { 259 if ((slot_map & (1 << i))) { 260 char *manuf; 261 char *version; 262 char *device; 263 int state; 264 265 if (get_slot_info(so, i, &manuf, &version, &device, 266 &state) < 0) 267 goto out; 268 if (manuf == NULL || version == NULL || device == NULL) 269 goto out; 270 printf("%d~%s~%s~%s~%s\n", 271 i, manuf, version, device, strstate(state)); 272 free(manuf); 273 free(version); 274 free(device); 275 } 276 } 277 } 278 out: 279 if (path) { 280 unlink(path); 281 free(path); 282 } 283 if (so >= 0) 284 close(so); 285 exit(0); 286} 287