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