style: compare return value of getopt() against -1 rather than EOF
[games.git] / usr.sbin / apmd / contrib / pccardq.c
CommitLineData
984263bc 1/* $FreeBSD: src/usr.sbin/apmd/contrib/pccardq.c,v 1.2 1999/08/28 05:11:25 peter Exp $ */
9b0ec895 2/* $DragonFly: src/usr.sbin/apmd/contrib/pccardq.c,v 1.4 2008/07/10 18:29:52 swildner Exp $ */
984263bc
MD
3
4#include <err.h>
5#include <errno.h>
6#include <limits.h>
7#include <stdarg.h>
8#include <stddef.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <time.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <sys/socket.h>
16#include <sys/un.h>
17
18const char *const pccardd_file = "/var/tmp/.pccardd";
19const char *prog = "pccardq";
20const char *tmp_dir = "/tmp";
21unsigned slot_map = ~0;
22
23void
a4c90f86 24usage(void)
984263bc
MD
25{
26 fprintf(stderr, "usage: %s [-a] [-n] [-s slot]\n", prog);
27}
28
29int
30proc_arg(int ac, char **av)
31{
32 int rc = -1;
33 int ch;
34
35 char *p = strrchr(av[0], '/');
36 prog = p ? p + 1 : av[0];
37
38 tmp_dir = getenv("TMPDIR") ? getenv("TMPDIR") : tmp_dir;
39
9b0ec895 40 while ((ch = getopt(ac, av, "ans:")) != -1) {
984263bc
MD
41 switch (ch) {
42 case 'a':
43 slot_map = ~0;
44 break;
45 case 'n':
46 slot_map = 0;
47 break;
48 case 's':
49 {
50 int n = atoi(optarg);
51 if (n < 0 || n >= CHAR_BIT * sizeof slot_map) {
52 warnc(0, "Invalid slot number.");
53 usage();
54 goto out;
55 }
56 if (slot_map == ~0)
57 slot_map = 0;
58 slot_map |= 1 << n;
59 }
60 break;
61 default:
62 usage();
63 goto out;
64 }
65 }
66
67 rc = 0;
68 out:
69 return rc;
70}
71
72int
73connect_to_pccardd(char **path)
74{
75 int so = -1;
76 int pccardd_len;
77 struct sockaddr_un pccardq;
78 struct sockaddr_un pccardd;
79
80 if ((so = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
81 warn("socket");
82 goto err;
83 }
84
85 snprintf(pccardq.sun_path, sizeof pccardq.sun_path,
86 "%s/%s%ld%ld", tmp_dir, prog, (long) getpid(), (long) time(0));
87 pccardq.sun_family = AF_UNIX;
88 pccardq.sun_len = offsetof(struct sockaddr_un, sun_path) + strlen(pccardq.sun_path);
89 if (bind(so, (struct sockaddr *) &pccardq, pccardq.sun_len) < 0) {
90 warn("bind: %s", pccardq.sun_path);
91 goto err;
92 }
93 if ((*path = strdup(pccardq.sun_path)) == NULL) {
94 warn("strdup");
95 goto err;
96 }
97
98 pccardd_len = strlen(pccardd_file) + 1;
99 if (pccardd_len > sizeof pccardd.sun_path) {
100 warnc(0, "%s: too long", pccardd_file);
101 goto err;
102 }
103 pccardd.sun_len = offsetof(struct sockaddr_un, sun_path) + pccardd_len;
104 pccardd.sun_family = AF_UNIX;
105 strcpy(pccardd.sun_path, pccardd_file);
106 if (connect(so, (struct sockaddr *) &pccardd, pccardd.sun_len) < 0) {
107 warn("connect: %s", pccardd_file);
108 goto err;
109 }
110 return so;
111 err:
112 if (so >= 0)
113 close(so);
114 return -1;
115}
116
117int
118get_slot_number(int so)
119{
120 char buf[8];
121 int rv;
122 int nslot;
123
124 if ((rv = write(so, "S", 1)) < 1) {
125 warn("write");
126 goto err;
127 } else if (rv != 1) {
128 warnc(0, "write: fail.");
129 goto err;
130 }
131
132 if ((rv = read(so, buf, sizeof buf)) < 0) {
133 warn("read");
134 goto err;
135 }
136 buf[sizeof buf - 1] = 0;
137 if (sscanf(buf, "%d", &nslot) != 1) {
138 warnc(0, "Invalid response.");
139 goto err;
140 }
141 return nslot;
142 err:
143 return -1;
144}
145
146enum {
147 SLOT_EMPTY = 0,
148 SLOT_FILLED = 1,
149 SLOT_INACTIVE = 2,
150 SLOT_UNDEFINED = 9
151};
152
153int
154get_slot_info(int so, int slot, char **manuf, char **version, char
155 **device, int *state)
156{
157 int rc = -1;
158 int rv;
159 static char buf[1024];
160 int slen;
161 char *s;
162 char *sl;
163
164 char *_manuf;
165 char *_version;
166 char *_device;
167
168 slen = snprintf(buf, sizeof buf, "N%d", slot);
169 if ((rv = write(so, buf, slen)) < 0) {
170 warn("write");
171 goto err;
172 } else if (rv != slen) {
173 warnc(0, "write");
174 goto err;
175 }
176
177 if ((rv = read(so, buf, sizeof buf)) < 0) {
178 warn("read");
179 goto err;
180 }
181
182 s = buf;
183 if ((sl = strsep(&s, "~")) == NULL)
184 goto parse_err;
185 if (atoi(sl) != slot)
186 goto parse_err;
187 if ((_manuf = strsep(&s, "~")) == NULL)
188 goto parse_err;
189 if ((_version = strsep(&s, "~")) == NULL)
190 goto parse_err;
191 if ((_device = strsep(&s, "~")) == NULL)
192 goto parse_err;
193 if (sscanf(s, "%1d", state) != 1)
194 goto parse_err;
195 if (s != NULL && strchr(s, '~') != NULL)
196 goto parse_err;
197
198 *manuf = strdup(_manuf);
199 *version = strdup(_version);
200 *device = strdup(_device);
201 if (*manuf == NULL || *version == NULL || *device == NULL) {
202 warn("strdup");
203 goto err;
204 }
205
206 rc = 0;
207 err:
208 return rc;
209 parse_err:
210 warnc(0, "Invalid response: %*s", rv, buf);
211 return rc;
212}
213
a4c90f86 214const char *
984263bc
MD
215strstate(int state)
216{
217 switch (state) {
218 case 0:
219 return "empty";
220 case 1:
221 return "filled";
222 case 2:
223 return "inactive";
224 default:
225 return "unknown";
226 }
227}
228
229int
230main(int ac, char **av)
231{
232 char *path = NULL;
233 int so = -1;
234 int nslot;
235 int i;
236
237 if (proc_arg(ac, av) < 0)
238 goto out;
239 if ((so = connect_to_pccardd(&path)) < 0)
240 goto out;
241 if ((nslot = get_slot_number(so)) < 0)
242 goto out;
243 if (slot_map == 0) {
244 printf("%d\n", nslot);
245 } else {
246 for (i = 0; i < nslot; i++) {
247 if ((slot_map & (1 << i))) {
248 char *manuf;
249 char *version;
250 char *device;
251 int state;
252
253 if (get_slot_info(so, i, &manuf, &version, &device,
254 &state) < 0)
255 goto out;
256 if (manuf == NULL || version == NULL || device == NULL)
257 goto out;
258 printf("%d~%s~%s~%s~%s\n",
259 i, manuf, version, device, strstate(state));
260 free(manuf);
261 free(version);
262 free(device);
263 }
264 }
265 }
266 out:
267 if (path) {
268 unlink(path);
269 free(path);
270 }
271 if (so >= 0)
272 close(so);
273 exit(0);
274}