pccardq.c revision 71277
150488Speter/* $FreeBSD: head/usr.sbin/apmd/contrib/pccardq.c 71277 2001-01-20 01:22:31Z jedgar $ */
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
19771277Sjedgar    if ((*manuf = strdup(_manuf)) == NULL) {
19871277Sjedgar	warn("strdup");
19971277Sjedgar	goto err;
20071277Sjedgar    }
20171277Sjedgar    if ((*version = strdup(_version)) == NULL) {
20271277Sjedgar	warn("strdup");
20371277Sjedgar	goto err;
20471277Sjedgar    }
20571277Sjedgar    if ((*device = strdup(_device)) == NULL) {
20671277Sjedgar	warn("strdup");
20771277Sjedgar	goto err;
20871277Sjedgar    }
20948730Siwasaki    if (*manuf == NULL || *version == NULL || *device == NULL) {
21048730Siwasaki	warn("strdup");
21148730Siwasaki	goto err;
21248730Siwasaki    }
21348730Siwasaki
21448730Siwasaki    rc = 0;
21548730Siwasaki  err:
21648730Siwasaki    return rc;
21748730Siwasaki  parse_err:
21848730Siwasaki    warnc(0, "Invalid response: %*s", rv, buf);
21948730Siwasaki    return rc;
22048730Siwasaki}
22148730Siwasaki
22248730Siwasakiconst char     *
22348730Siwasakistrstate(int state)
22448730Siwasaki{
22548730Siwasaki    switch (state) {
22648730Siwasaki    case 0:
22748730Siwasaki	return "empty";
22848730Siwasaki    case 1:
22948730Siwasaki	return "filled";
23048730Siwasaki    case 2:
23148730Siwasaki	return "inactive";
23248730Siwasaki    default:
23348730Siwasaki	return "unknown";
23448730Siwasaki    }
23548730Siwasaki}
23648730Siwasaki
23748730Siwasakiint
23848730Siwasakimain(int ac, char **av)
23948730Siwasaki{
24048730Siwasaki    char           *path = NULL;
24148730Siwasaki    int             so = -1;
24248730Siwasaki    int             nslot;
24348730Siwasaki    int             i;
24448730Siwasaki
24548730Siwasaki    if (proc_arg(ac, av) < 0)
24648730Siwasaki	goto out;
24748730Siwasaki    if ((so = connect_to_pccardd(&path)) < 0)
24848730Siwasaki	goto out;
24948730Siwasaki    if ((nslot = get_slot_number(so)) < 0)
25048730Siwasaki	goto out;
25148730Siwasaki    if (slot_map == 0) {
25248730Siwasaki	printf("%d\n", nslot);
25348730Siwasaki    } else {
25448730Siwasaki	for (i = 0; i < nslot; i++) {
25548730Siwasaki	    if ((slot_map & (1 << i))) {
25648730Siwasaki		char           *manuf;
25748730Siwasaki		char           *version;
25848730Siwasaki		char           *device;
25948730Siwasaki		int             state;
26048730Siwasaki
26148730Siwasaki		if (get_slot_info(so, i, &manuf, &version, &device,
26248730Siwasaki				  &state) < 0)
26348730Siwasaki		    goto out;
26448730Siwasaki		if (manuf == NULL || version == NULL || device == NULL)
26548730Siwasaki		    goto out;
26648730Siwasaki		printf("%d~%s~%s~%s~%s\n",
26748730Siwasaki		       i, manuf, version, device, strstate(state));
26848730Siwasaki		free(manuf);
26948730Siwasaki		free(version);
27048730Siwasaki		free(device);
27148730Siwasaki	    }
27248730Siwasaki	}
27348730Siwasaki    }
27448730Siwasaki  out:
27548730Siwasaki    if (path) {
27648730Siwasaki	unlink(path);
27748730Siwasaki	free(path);
27848730Siwasaki    }
27948730Siwasaki    if (so >= 0)
28048730Siwasaki	close(so);
28148730Siwasaki    exit(0);
28248730Siwasaki}
283