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