Lines 32-54
Link Here
|
32 |
#include <sys/cdefs.h> |
32 |
#include <sys/cdefs.h> |
33 |
__FBSDID("$FreeBSD: src/usr.bin/ipcrm/ipcrm.c,v 1.11 2002/09/04 23:29:02 dwmalone Exp $"); |
33 |
__FBSDID("$FreeBSD: src/usr.bin/ipcrm/ipcrm.c,v 1.11 2002/09/04 23:29:02 dwmalone Exp $"); |
34 |
|
34 |
|
|
|
35 |
#include <sys/types.h> |
36 |
#include <sys/sysctl.h> |
37 |
#include <sys/cdefs.h> |
38 |
#define _KERNEL |
39 |
#include <sys/ipc.h> |
40 |
#include <sys/msg.h> |
41 |
#include <sys/sem.h> |
42 |
#include <sys/shm.h> |
43 |
#undef _KERNEL |
35 |
#include <ctype.h> |
44 |
#include <ctype.h> |
36 |
#include <err.h> |
45 |
#include <err.h> |
37 |
#include <signal.h> |
46 |
#include <signal.h> |
38 |
#include <stdio.h> |
47 |
#include <stdio.h> |
39 |
#include <stdlib.h> |
48 |
#include <stdlib.h> |
40 |
#include <unistd.h> |
49 |
#include <unistd.h> |
41 |
#include <sys/types.h> |
50 |
#include <assert.h> |
42 |
#include <sys/ipc.h> |
51 |
#include <limits.h> |
43 |
#include <sys/msg.h> |
52 |
#include <fcntl.h> |
44 |
#include <sys/sem.h> |
53 |
#include <nlist.h> |
45 |
#include <sys/shm.h> |
54 |
#include <kvm.h> |
46 |
|
55 |
|
47 |
#define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem")) |
56 |
#define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem")) |
48 |
#define IPC_TO_STRING(x) (x == 'Q' ? "message queue" : \ |
57 |
#define IPC_TO_STRING(x) (x == 'Q' ? "message queue" : \ |
49 |
(x == 'M' ? "shared memory segment" : "semaphore")) |
58 |
(x == 'M' ? "shared memory segment" : "semaphore")) |
50 |
|
59 |
|
51 |
int signaled; |
60 |
/* Copied from ipcs/ipcs.c */ |
|
|
61 |
/* SysCtlGatherStruct structure. */ |
62 |
struct scgs_vector { |
63 |
const char *sysctl; |
64 |
off_t offset; |
65 |
size_t size; |
66 |
}; |
67 |
|
68 |
static struct semid_kernel *sema; |
69 |
static struct seminfo seminfo; |
70 |
static struct msginfo msginfo; |
71 |
static struct msqid_kernel *msqids; |
72 |
static struct shminfo shminfo; |
73 |
static struct shmid_kernel *shmsegs; |
74 |
|
75 |
void kget(int idx, void *addr, size_t size); |
76 |
void sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vec); |
77 |
|
78 |
static struct nlist symbols[] = { |
79 |
{"sema"}, |
80 |
#define X_SEMA 0 |
81 |
{"seminfo"}, |
82 |
#define X_SEMINFO 1 |
83 |
{"msginfo"}, |
84 |
#define X_MSGINFO 2 |
85 |
{"msqids"}, |
86 |
#define X_MSQIDS 3 |
87 |
{"shminfo"}, |
88 |
#define X_SHMINFO 4 |
89 |
{"shmsegs"}, |
90 |
#define X_SHMSEGS 5 |
91 |
{NULL} |
92 |
}; |
93 |
|
94 |
#define SHMINFO_XVEC \ |
95 |
X(shmmax, sizeof(int)) \ |
96 |
X(shmmin, sizeof(int)) \ |
97 |
X(shmmni, sizeof(int)) \ |
98 |
X(shmseg, sizeof(int)) \ |
99 |
X(shmall, sizeof(int)) |
100 |
|
101 |
#define SEMINFO_XVEC \ |
102 |
X(semmap, sizeof(int)) \ |
103 |
X(semmni, sizeof(int)) \ |
104 |
X(semmns, sizeof(int)) \ |
105 |
X(semmnu, sizeof(int)) \ |
106 |
X(semmsl, sizeof(int)) \ |
107 |
X(semopm, sizeof(int)) \ |
108 |
X(semume, sizeof(int)) \ |
109 |
X(semusz, sizeof(int)) \ |
110 |
X(semvmx, sizeof(int)) \ |
111 |
X(semaem, sizeof(int)) |
112 |
|
113 |
#define MSGINFO_XVEC \ |
114 |
X(msgmax, sizeof(int)) \ |
115 |
X(msgmni, sizeof(int)) \ |
116 |
X(msgmnb, sizeof(int)) \ |
117 |
X(msgtql, sizeof(int)) \ |
118 |
X(msgssz, sizeof(int)) \ |
119 |
X(msgseg, sizeof(int)) |
120 |
|
121 |
#define X(a, b) { "kern.ipc." #a, __offsetof(TYPEC, a), (b) }, |
122 |
#define TYPEC struct shminfo |
123 |
struct scgs_vector shminfo_scgsv[] = { SHMINFO_XVEC { NULL } }; |
124 |
#undef TYPEC |
125 |
#define TYPEC struct seminfo |
126 |
struct scgs_vector seminfo_scgsv[] = { SEMINFO_XVEC { NULL } }; |
127 |
#undef TYPEC |
128 |
#define TYPEC struct msginfo |
129 |
struct scgs_vector msginfo_scgsv[] = { MSGINFO_XVEC { NULL } }; |
130 |
#undef TYPEC |
131 |
#undef X |
132 |
|
133 |
static int errflg; |
134 |
static int signaled; |
135 |
static int use_sysctl = 1; |
52 |
|
136 |
|
53 |
void usage(void); |
137 |
void usage(void); |
54 |
int msgrm(key_t, int); |
138 |
int msgrm(key_t, int); |
Lines 56-62
Link Here
|
56 |
int semrm(key_t, int); |
140 |
int semrm(key_t, int); |
57 |
void not_configured(int); |
141 |
void not_configured(int); |
58 |
|
142 |
|
59 |
void usage(void) |
143 |
void |
|
|
144 |
usage(void) |
60 |
{ |
145 |
{ |
61 |
fprintf(stderr, "%s\n%s\n", |
146 |
fprintf(stderr, "%s\n%s\n", |
62 |
"usage: ipcrm [-q msqid] [-m shmid] [-s semid]", |
147 |
"usage: ipcrm [-q msqid] [-m shmid] [-s semid]", |
Lines 64-172
Link Here
|
64 |
exit(1); |
149 |
exit(1); |
65 |
} |
150 |
} |
66 |
|
151 |
|
67 |
int msgrm(key_t key, int id) |
152 |
int |
|
|
153 |
msgrm(key_t key, int id) |
154 |
{ |
155 |
if (key) { |
156 |
id = msgget(key, 0); |
157 |
if (id == -1) |
158 |
return -1; |
159 |
} |
160 |
if (id == -1) { |
161 |
struct msqid_kernel *kxmsqids; |
162 |
size_t kxmsqids_len; |
163 |
int num; |
164 |
|
165 |
kget(X_MSGINFO, &msginfo, sizeof(msginfo)); |
166 |
kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni; |
167 |
kxmsqids = malloc(kxmsqids_len); |
168 |
kget(X_MSQIDS, kxmsqids, kxmsqids_len); |
169 |
num = msginfo.msgmni; |
170 |
while (num-- && !signaled) |
171 |
if (kxmsqids[num].u.msg_qbytes != 0) { |
172 |
id = IXSEQ_TO_IPCID(num, kxmsqids[num].u.msg_perm); |
173 |
if (msgctl(id, IPC_RMID, NULL) < 0) { |
174 |
warn("msqid(%d): ", id); |
175 |
errflg++; |
176 |
} |
177 |
} |
178 |
return signaled ? -1 : 0; /* errors maybe handled above */ |
179 |
} |
180 |
return msgctl(id, IPC_RMID, NULL); |
181 |
} |
182 |
|
183 |
int |
184 |
shmrm(key_t key, int id) |
185 |
{ |
186 |
if (key) { |
187 |
id = shmget(key, 0, 0); |
188 |
if (id == -1) |
189 |
return -1; |
190 |
} |
191 |
if (id == -1) { |
192 |
struct shmid_kernel *kxshmids; |
193 |
size_t kxshmids_len; |
194 |
int num; |
195 |
|
196 |
kget(X_SHMINFO, &shminfo, sizeof(shminfo)); |
197 |
kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni; |
198 |
kxshmids = malloc(kxshmids_len); |
199 |
kget(X_SHMSEGS, kxshmids, kxshmids_len); |
200 |
num = shminfo.shmmni; |
201 |
while (num-- && !signaled) |
202 |
if (kxshmids[num].u.shm_perm.mode & 0x0800) { |
203 |
id = IXSEQ_TO_IPCID(num, kxshmids[num].u.shm_perm); |
204 |
if (shmctl(id, IPC_RMID, NULL) < 0) { |
205 |
warn("shmid(%d): ", id); |
206 |
errflg++; |
207 |
} |
208 |
} |
209 |
return signaled ? -1 : 0; /* errors maybe handled above */ |
210 |
} |
211 |
return shmctl(id, IPC_RMID, NULL); |
212 |
} |
213 |
|
214 |
int |
215 |
semrm(key_t key, int id) |
68 |
{ |
216 |
{ |
69 |
if (key) { |
217 |
union semun arg; |
70 |
id = msgget(key, 0); |
218 |
|
71 |
if (id == -1) |
219 |
if (key) { |
72 |
return -1; |
220 |
id = semget(key, 0, 0); |
73 |
} |
221 |
if (id == -1) |
74 |
return msgctl(id, IPC_RMID, NULL); |
222 |
return -1; |
75 |
} |
223 |
} |
76 |
|
224 |
if (id == -1) { |
77 |
int shmrm(key_t key, int id) |
225 |
struct semid_kernel *kxsema; |
78 |
{ |
226 |
size_t kxsema_len; |
79 |
if (key) { |
227 |
int num; |
80 |
id = shmget(key, 0, 0); |
228 |
|
81 |
if (id == -1) |
229 |
kget(X_SEMINFO, &seminfo, sizeof(seminfo)); |
82 |
return -1; |
230 |
kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni; |
83 |
} |
231 |
kxsema = malloc(kxsema_len); |
84 |
return shmctl(id, IPC_RMID, NULL); |
232 |
kget(X_SEMA, kxsema, kxsema_len); |
85 |
} |
233 |
num = seminfo.semmni; |
86 |
|
234 |
while (num-- && !signaled) |
87 |
int semrm(key_t key, int id) |
235 |
if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) { |
88 |
{ |
236 |
id = IXSEQ_TO_IPCID(num, kxsema[num].u.sem_perm); |
89 |
union semun arg; |
237 |
if (semctl(id, IPC_RMID, NULL) < 0) { |
90 |
|
238 |
warn("semid(%d): ", id); |
91 |
if (key) { |
239 |
errflg++; |
92 |
id = semget(key, 0, 0); |
240 |
} |
93 |
if (id == -1) |
241 |
} |
94 |
return -1; |
242 |
return signaled ? -1 : 0; /* errors maybe handled above */ |
95 |
} |
243 |
} |
96 |
return semctl(id, 0, IPC_RMID, arg); |
244 |
return semctl(id, 0, IPC_RMID, arg); |
97 |
} |
245 |
} |
98 |
|
246 |
|
99 |
void not_configured(int signo __unused) |
247 |
void |
100 |
{ |
248 |
not_configured(int signo __unused) |
101 |
signaled++; |
249 |
{ |
102 |
} |
250 |
signaled++; |
103 |
|
251 |
} |
104 |
int main(int argc, char *argv[]) |
252 |
|
105 |
{ |
253 |
int |
106 |
int c, result, errflg, target_id; |
254 |
main(int argc, char *argv[]) |
107 |
key_t target_key; |
255 |
{ |
108 |
|
256 |
int c, result, target_id; |
109 |
errflg = 0; |
257 |
key_t target_key; |
110 |
signal(SIGSYS, not_configured); |
258 |
|
111 |
while ((c = getopt(argc, argv, ":q:m:s:Q:M:S:")) != -1) { |
259 |
errflg = 0; |
112 |
|
260 |
signal(SIGSYS, not_configured); |
113 |
signaled = 0; |
261 |
while ((c = getopt(argc, argv, ":q:m:s:Q:M:S:y")) != -1) { |
114 |
switch (c) { |
262 |
|
115 |
case 'q': |
263 |
signaled = 0; |
116 |
case 'm': |
264 |
switch (c) { |
117 |
case 's': |
265 |
case 'q': |
118 |
target_id = atoi(optarg); |
266 |
case 'm': |
119 |
if (c == 'q') |
267 |
case 's': |
120 |
result = msgrm(0, target_id); |
268 |
target_id = atoi(optarg); |
121 |
else if (c == 'm') |
269 |
if (c == 'q') |
122 |
result = shmrm(0, target_id); |
270 |
result = msgrm(0, target_id); |
123 |
else |
271 |
else if (c == 'm') |
124 |
result = semrm(0, target_id); |
272 |
result = shmrm(0, target_id); |
125 |
if (result < 0) { |
273 |
else |
126 |
errflg++; |
274 |
result = semrm(0, target_id); |
127 |
if (!signaled) |
275 |
if (result < 0) { |
128 |
warn("%sid(%d): ", IPC_TO_STR(toupper(c)), target_id); |
276 |
errflg++; |
129 |
else |
277 |
if (!signaled) |
130 |
warnx("%ss are not configured in the running kernel", |
278 |
warn("%sid(%d): ", IPC_TO_STR(toupper(c)), target_id); |
131 |
IPC_TO_STRING(toupper(c))); |
279 |
else |
132 |
} |
280 |
warnx("%ss are not configured in the running kernel", |
133 |
break; |
281 |
IPC_TO_STRING(toupper(c))); |
134 |
case 'Q': |
282 |
} |
135 |
case 'M': |
283 |
break; |
136 |
case 'S': |
284 |
case 'Q': |
137 |
target_key = atol(optarg); |
285 |
case 'M': |
138 |
if (target_key == IPC_PRIVATE) { |
286 |
case 'S': |
139 |
warnx("can't remove private %ss", IPC_TO_STRING(c)); |
287 |
target_key = atol(optarg); |
140 |
continue; |
288 |
if (target_key == IPC_PRIVATE) { |
141 |
} |
289 |
warnx("can't remove private %ss", IPC_TO_STRING(c)); |
142 |
if (c == 'Q') |
290 |
continue; |
143 |
result = msgrm(target_key, 0); |
291 |
} |
144 |
else if (c == 'M') |
292 |
if (c == 'Q') |
145 |
result = shmrm(target_key, 0); |
293 |
result = msgrm(target_key, 0); |
146 |
else |
294 |
else if (c == 'M') |
147 |
result = semrm(target_key, 0); |
295 |
result = shmrm(target_key, 0); |
148 |
if (result < 0) { |
296 |
else |
149 |
errflg++; |
297 |
result = semrm(target_key, 0); |
150 |
if (!signaled) |
298 |
if (result < 0) { |
151 |
warn("%ss(%ld): ", IPC_TO_STR(c), target_key); |
299 |
errflg++; |
152 |
else |
300 |
if (!signaled) |
153 |
warnx("%ss are not configured in the running kernel", |
301 |
warn("%ss(%ld): ", IPC_TO_STR(c), target_key); |
154 |
IPC_TO_STRING(c)); |
302 |
else |
155 |
} |
303 |
warnx("%ss are not configured in the running kernel", |
156 |
break; |
304 |
IPC_TO_STRING(c)); |
157 |
case ':': |
305 |
} |
158 |
fprintf(stderr, "option -%c requires an argument\n", optopt); |
306 |
break; |
159 |
usage(); |
307 |
case 'y': |
160 |
case '?': |
308 |
use_sysctl = 0; |
161 |
fprintf(stderr, "unrecognized option: -%c\n", optopt); |
309 |
break; |
162 |
usage(); |
310 |
case ':': |
163 |
} |
311 |
fprintf(stderr, "option -%c requires an argument\n", optopt); |
164 |
} |
312 |
usage(); |
165 |
|
313 |
case '?': |
166 |
if (optind != argc) { |
314 |
fprintf(stderr, "unrecognized option: -%c\n", optopt); |
167 |
fprintf(stderr, "unknown argument: %s\n", argv[optind]); |
315 |
usage(); |
168 |
usage(); |
316 |
} |
169 |
} |
317 |
} |
170 |
exit(errflg); |
318 |
|
|
|
319 |
if (optind != argc) { |
320 |
fprintf(stderr, "unknown argument: %s\n", argv[optind]); |
321 |
usage(); |
322 |
} |
323 |
exit(errflg); |
324 |
} |
325 |
|
326 |
/* The remainder is from ipcs/ipcs.c */ |
327 |
void |
328 |
sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vecarr) |
329 |
{ |
330 |
struct scgs_vector *xp; |
331 |
size_t tsiz; |
332 |
int rv; |
333 |
|
334 |
for (xp = vecarr; xp->sysctl != NULL; xp++) { |
335 |
assert(xp->offset <= size); |
336 |
tsiz = xp->size; |
337 |
rv = sysctlbyname(xp->sysctl, (char *)addr + xp->offset, |
338 |
&tsiz, NULL, 0); |
339 |
if (rv == -1) |
340 |
err(1, "sysctlbyname: %s", xp->sysctl); |
341 |
if (tsiz != xp->size) |
342 |
errx(1, "%s size mismatch (expected %d, got %d)", |
343 |
xp->sysctl, xp->size, tsiz); |
344 |
} |
345 |
} |
346 |
|
347 |
void |
348 |
kget(int idx, void *addr, size_t size) |
349 |
{ |
350 |
char *symn; /* symbol name */ |
351 |
size_t tsiz; |
352 |
int rv; |
353 |
unsigned long kaddr; |
354 |
const char *sym2sysctl[] = { /* symbol to sysctl name table */ |
355 |
"kern.ipc.sema", |
356 |
"kern.ipc.seminfo", |
357 |
"kern.ipc.msginfo", |
358 |
"kern.ipc.msqids", |
359 |
"kern.ipc.shminfo", |
360 |
"kern.ipc.shmsegs" }; |
361 |
|
362 |
assert((unsigned)idx <= sizeof(sym2sysctl) / sizeof(*sym2sysctl)); |
363 |
if (!use_sysctl) { |
364 |
kvm_t *kd; |
365 |
char kvmoferr[_POSIX2_LINE_MAX]; /* Error buf for kvm_openfiles. */ |
366 |
char *core = NULL, *namelist = NULL; |
367 |
|
368 |
kd = kvm_openfiles(namelist, core, NULL, O_RDONLY, kvmoferr); |
369 |
if (kd == NULL) |
370 |
errx(1, "kvm_openfiles: %s", kvmoferr); |
371 |
switch (kvm_nlist(kd, symbols)) { |
372 |
case 0: |
373 |
break; |
374 |
case -1: |
375 |
errx(1, "unable to read kernel symbol table"); |
376 |
default: |
377 |
#ifdef notdef /* they'll be told more civilly later */ |
378 |
warnx("nlist failed"); |
379 |
for (i = 0; symbols[i].n_name != NULL; i++) |
380 |
if (symbols[i].n_value == 0) |
381 |
warnx("symbol %s not found", |
382 |
symbols[i].n_name); |
383 |
#endif |
384 |
break; |
385 |
} |
386 |
symn = symbols[idx].n_name; |
387 |
if (*symn == '_') |
388 |
symn++; |
389 |
if (symbols[idx].n_type == 0 || symbols[idx].n_value == 0) |
390 |
errx(1, "symbol %s undefined", symn); |
391 |
/* |
392 |
* For some symbols, the value we retrieve is |
393 |
* actually a pointer; since we want the actual value, |
394 |
* we have to manually dereference it. |
395 |
*/ |
396 |
switch (idx) { |
397 |
case X_MSQIDS: |
398 |
tsiz = sizeof(msqids); |
399 |
rv = kvm_read(kd, symbols[idx].n_value, |
400 |
&msqids, tsiz); |
401 |
kaddr = (u_long)msqids; |
402 |
break; |
403 |
case X_SHMSEGS: |
404 |
tsiz = sizeof(shmsegs); |
405 |
rv = kvm_read(kd, symbols[idx].n_value, |
406 |
&shmsegs, tsiz); |
407 |
kaddr = (u_long)shmsegs; |
408 |
break; |
409 |
case X_SEMA: |
410 |
tsiz = sizeof(sema); |
411 |
rv = kvm_read(kd, symbols[idx].n_value, |
412 |
&sema, tsiz); |
413 |
kaddr = (u_long)sema; |
414 |
break; |
415 |
default: |
416 |
rv = tsiz = 0; |
417 |
kaddr = symbols[idx].n_value; |
418 |
break; |
419 |
} |
420 |
if ((unsigned)rv != tsiz) |
421 |
errx(1, "%s: %s", symn, kvm_geterr(kd)); |
422 |
if ((unsigned)kvm_read(kd, kaddr, addr, size) != size) |
423 |
errx(1, "%s: %s", symn, kvm_geterr(kd)); |
424 |
kvm_close(kd); |
425 |
} else { |
426 |
switch (idx) { |
427 |
case X_SHMINFO: |
428 |
sysctlgatherstruct(addr, size, shminfo_scgsv); |
429 |
break; |
430 |
case X_SEMINFO: |
431 |
sysctlgatherstruct(addr, size, seminfo_scgsv); |
432 |
break; |
433 |
case X_MSGINFO: |
434 |
sysctlgatherstruct(addr, size, msginfo_scgsv); |
435 |
break; |
436 |
default: |
437 |
tsiz = size; |
438 |
rv = sysctlbyname(sym2sysctl[idx], addr, &tsiz, |
439 |
NULL, 0); |
440 |
if (rv == -1) |
441 |
err(1, "sysctlbyname: %s", sym2sysctl[idx]); |
442 |
if (tsiz != size) |
443 |
errx(1, "%s size mismatch " |
444 |
"(expected %d, got %d)", |
445 |
sym2sysctl[idx], size, tsiz); |
446 |
break; |
447 |
} |
448 |
} |
171 |
} |
449 |
} |
172 |
|
450 |
|