ipcrm.c revision 174891
1/*
2 * Copyright (c) 1994 Adam Glass
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Adam Glass.
16 * 4. The name of the Author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL Adam Glass BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/usr.bin/ipcrm/ipcrm.c 174891 2007-12-25 00:52:24Z edwin $");
35
36#include <sys/param.h>
37#define _KERNEL
38#include <sys/sem.h>
39#include <sys/shm.h>
40#include <sys/msg.h>
41#undef _KERNEL
42
43#include <ctype.h>
44#include <err.h>
45#include <grp.h>
46#include <kvm.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <unistd.h>
50
51#include "ipc.h"
52
53int	signaled;
54int	errflg;
55int	rmverbose = 0;
56
57void	usage(void);
58
59int	msgrm(key_t, int);
60int	shmrm(key_t, int);
61int	semrm(key_t, int);
62void	not_configured(int);
63
64void
65usage(void)
66{
67
68	fprintf(stderr,
69	    "usage: ipcrm [-W] [-v[v]]\n"
70	    "             [-q msqid] [-m shmid] [-s semid]\n"
71	    "             [-Q msgkey] [-M shmkey] [-S semkey] ...\n");
72	exit(1);
73}
74
75int
76msgrm(key_t key, int id)
77{
78
79	if (key == -1 || id == -1) {
80		struct msqid_kernel *kxmsqids;
81		size_t kxmsqids_len;
82		int num;
83
84		kget(X_MSGINFO, &msginfo, sizeof(msginfo));
85		kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni;
86		kxmsqids = malloc(kxmsqids_len);
87		kget(X_MSQIDS, kxmsqids, kxmsqids_len);
88		num = msginfo.msgmni;
89		while (num-- && !signaled)
90			if (kxmsqids[num].u.msg_qbytes != 0) {
91				id = IXSEQ_TO_IPCID(num,
92					kxmsqids[num].u.msg_perm);
93				if (msgctl(id, IPC_RMID, NULL) < 0) {
94					if (rmverbose > 1)
95						warn("msqid(%d): ", id);
96					errflg++;
97				} else
98					if (rmverbose)
99						printf(
100						    "Removed %s %d\n",
101						    IPC_TO_STRING('Q'),
102						    id);
103			}
104		return signaled ? -1 : 0;       /* errors maybe handled above */
105	}
106
107	if (key) {
108		id = msgget(key, 0);
109		if (id == -1)
110			return -1;
111	}
112
113	return msgctl(id, IPC_RMID, NULL);
114}
115
116int
117shmrm(key_t key, int id)
118{
119
120	if (key == -1 || id == -1) {
121		struct shmid_kernel *kxshmids;
122		size_t kxshmids_len;
123		int num;
124
125		kget(X_SHMINFO, &shminfo, sizeof(shminfo));
126		kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni;
127		kxshmids = malloc(kxshmids_len);
128		kget(X_SHMSEGS, kxshmids, kxshmids_len);
129		num = shminfo.shmmni;
130		while (num-- && !signaled)
131			if (kxshmids[num].u.shm_perm.mode & 0x0800) {
132				id = IXSEQ_TO_IPCID(num,
133					kxshmids[num].u.shm_perm);
134				if (shmctl(id, IPC_RMID, NULL) < 0) {
135					if (rmverbose > 1)
136						warn("shmid(%d): ", id);
137					errflg++;
138				} else
139					if (rmverbose)
140						printf(
141						    "Removed %s %d\n",
142						    IPC_TO_STRING('M'),
143						    id);
144			}
145		return signaled ? -1 : 0;       /* errors maybe handled above */
146	}
147
148	if (key) {
149		id = shmget(key, 0, 0);
150		if (id == -1)
151			return -1;
152	}
153
154	return shmctl(id, IPC_RMID, NULL);
155}
156
157int
158semrm(key_t key, int id)
159{
160	union semun arg;
161
162	if (key == -1 || id == -1) {
163		struct semid_kernel *kxsema;
164		size_t kxsema_len;
165		int num;
166
167		kget(X_SEMINFO, &seminfo, sizeof(seminfo));
168		kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni;
169		kxsema = malloc(kxsema_len);
170		kget(X_SEMA, kxsema, kxsema_len);
171		num = seminfo.semmni;
172		while (num-- && !signaled)
173			if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) {
174				id = IXSEQ_TO_IPCID(num,
175					kxsema[num].u.sem_perm);
176				if (semctl(id, IPC_RMID, NULL) < 0) {
177					if (rmverbose > 1)
178						warn("semid(%d): ", id);
179					errflg++;
180				} else
181					if (rmverbose)
182						printf(
183						    "Removed %s %d\n",
184						    IPC_TO_STRING('S'),
185						    id);
186			}
187		return signaled ? -1 : 0;       /* errors maybe handled above */
188	}
189
190	if (key) {
191		id = semget(key, 0, 0);
192		if (id == -1)
193			return -1;
194	}
195
196	return semctl(id, 0, IPC_RMID, arg);
197}
198
199void
200not_configured(int signo __unused)
201{
202
203	signaled++;
204}
205
206int
207main(int argc, char *argv[])
208{
209	int c, result, target_id;
210	key_t target_key;
211
212	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
213
214		signaled = 0;
215		switch (c) {
216		case 'v':
217			rmverbose++;
218			break;
219		case 'y':
220			use_sysctl = 0;
221			break;
222		}
223	}
224
225	optind = 1;
226	errflg = 0;
227	signal(SIGSYS, not_configured);
228	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
229
230		signaled = 0;
231		switch (c) {
232		case 'q':
233		case 'm':
234		case 's':
235			target_id = atoi(optarg);
236			if (c == 'q')
237				result = msgrm(0, target_id);
238			else if (c == 'm')
239				result = shmrm(0, target_id);
240			else
241				result = semrm(0, target_id);
242			if (result < 0) {
243				errflg++;
244				if (!signaled)
245					warn("%sid(%d): ",
246					    IPC_TO_STR(toupper(c)), target_id);
247				else
248					warnx(
249					    "%ss are not configured "
250					    "in the running kernel",
251					    IPC_TO_STRING(toupper(c)));
252			}
253			break;
254		case 'Q':
255		case 'M':
256		case 'S':
257			target_key = atol(optarg);
258			if (target_key == IPC_PRIVATE) {
259				warnx("can't remove private %ss",
260				    IPC_TO_STRING(c));
261				continue;
262			}
263			if (c == 'Q')
264				result = msgrm(target_key, 0);
265			else if (c == 'M')
266				result = shmrm(target_key, 0);
267			else
268				result = semrm(target_key, 0);
269			if (result < 0) {
270				errflg++;
271				if (!signaled)
272					warn("%ss(%ld): ",
273					    IPC_TO_STR(c), target_key);
274				else
275					warnx("%ss are not configured "
276					    "in the running kernel",
277					    IPC_TO_STRING(c));
278			}
279			break;
280		case 'v':
281		case 'y':
282			/* Handled in other getopt() loop */
283			break;
284		case 'W':
285			msgrm(-1, 0);
286			shmrm(-1, 0);
287			semrm(-1, 0);
288			break;
289		case ':':
290			fprintf(stderr,
291			    "option -%c requires an argument\n", optopt);
292			usage();
293		case '?':
294			fprintf(stderr, "unrecognized option: -%c\n", optopt);
295			usage();
296		}
297	}
298
299	if (optind != argc) {
300		fprintf(stderr, "unknown argument: %s\n", argv[optind]);
301		usage();
302	}
303	exit(errflg);
304}
305