ipcrm.c revision 286093
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 286093 2015-07-30 19:44:46Z rodrigc $");
35
36#include <sys/param.h>
37#define _WANT_MSG_PROTOTYPES
38#define _WANT_SEM_PROTOTYPES
39#define _WANT_SHM_PROTOTYPES
40#define _KERNEL
41#include <sys/sem.h>
42#include <sys/shm.h>
43#include <sys/msg.h>
44#undef _KERNEL
45
46#include <ctype.h>
47#include <err.h>
48#include <grp.h>
49#include <kvm.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <unistd.h>
53
54#include "ipc.h"
55
56static int	signaled;
57static int	errflg;
58static int	rmverbose = 0;
59
60static void
61usage(void)
62{
63
64	fprintf(stderr,
65	    "usage: ipcrm [-W] [-v[v]]\n"
66	    "             [-q msqid] [-m shmid] [-s semid]\n"
67	    "             [-Q msgkey] [-M shmkey] [-S semkey] ...\n");
68	exit(1);
69}
70
71static int
72msgrm(key_t key, int id)
73{
74
75	if (key == -1 || id == -1) {
76		struct msqid_kernel *kxmsqids;
77		size_t kxmsqids_len;
78		int num;
79
80		kget(X_MSGINFO, &msginfo, sizeof(msginfo));
81		kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni;
82		kxmsqids = malloc(kxmsqids_len);
83		kget(X_MSQIDS, kxmsqids, kxmsqids_len);
84		num = msginfo.msgmni;
85		while (num-- && !signaled)
86			if (kxmsqids[num].u.msg_qbytes != 0) {
87				id = IXSEQ_TO_IPCID(num,
88					kxmsqids[num].u.msg_perm);
89				if (msgctl(id, IPC_RMID, NULL) < 0) {
90					if (rmverbose > 1)
91						warn("msqid(%d): ", id);
92					errflg++;
93				} else
94					if (rmverbose)
95						printf(
96						    "Removed %s %d\n",
97						    IPC_TO_STRING('Q'),
98						    id);
99			}
100		return signaled ? -1 : 0;       /* errors maybe handled above */
101	}
102
103	if (key) {
104		id = msgget(key, 0);
105		if (id == -1)
106			return -1;
107	}
108
109	return msgctl(id, IPC_RMID, NULL);
110}
111
112static int
113shmrm(key_t key, int id)
114{
115
116	if (key == -1 || id == -1) {
117		struct shmid_kernel *kxshmids;
118		size_t kxshmids_len;
119		int num;
120
121		kget(X_SHMINFO, &shminfo, sizeof(shminfo));
122		kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni;
123		kxshmids = malloc(kxshmids_len);
124		kget(X_SHMSEGS, kxshmids, kxshmids_len);
125		num = shminfo.shmmni;
126		while (num-- && !signaled)
127			if (kxshmids[num].u.shm_perm.mode & 0x0800) {
128				id = IXSEQ_TO_IPCID(num,
129					kxshmids[num].u.shm_perm);
130				if (shmctl(id, IPC_RMID, NULL) < 0) {
131					if (rmverbose > 1)
132						warn("shmid(%d): ", id);
133					errflg++;
134				} else
135					if (rmverbose)
136						printf(
137						    "Removed %s %d\n",
138						    IPC_TO_STRING('M'),
139						    id);
140			}
141		return signaled ? -1 : 0;       /* errors maybe handled above */
142	}
143
144	if (key) {
145		id = shmget(key, 0, 0);
146		if (id == -1)
147			return -1;
148	}
149
150	return shmctl(id, IPC_RMID, NULL);
151}
152
153static int
154semrm(key_t key, int id)
155{
156	union semun arg;
157
158	if (key == -1 || id == -1) {
159		struct semid_kernel *kxsema;
160		size_t kxsema_len;
161		int num;
162
163		kget(X_SEMINFO, &seminfo, sizeof(seminfo));
164		kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni;
165		kxsema = malloc(kxsema_len);
166		kget(X_SEMA, kxsema, kxsema_len);
167		num = seminfo.semmni;
168		while (num-- && !signaled)
169			if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) {
170				id = IXSEQ_TO_IPCID(num,
171					kxsema[num].u.sem_perm);
172				if (semctl(id, 0, IPC_RMID, NULL) < 0) {
173					if (rmverbose > 1)
174						warn("semid(%d): ", id);
175					errflg++;
176				} else
177					if (rmverbose)
178						printf(
179						    "Removed %s %d\n",
180						    IPC_TO_STRING('S'),
181						    id);
182			}
183		return signaled ? -1 : 0;       /* errors maybe handled above */
184	}
185
186	if (key) {
187		id = semget(key, 0, 0);
188		if (id == -1)
189			return -1;
190	}
191
192	return semctl(id, 0, IPC_RMID, arg);
193}
194
195static void
196not_configured(int signo __unused)
197{
198
199	signaled++;
200}
201
202int
203main(int argc, char *argv[])
204{
205	int c, result, target_id;
206	key_t target_key;
207
208	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
209
210		signaled = 0;
211		switch (c) {
212		case 'v':
213			rmverbose++;
214			break;
215		case 'y':
216			use_sysctl = 0;
217			break;
218		}
219	}
220
221	optind = 1;
222	errflg = 0;
223	signal(SIGSYS, not_configured);
224	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
225
226		signaled = 0;
227		switch (c) {
228		case 'q':
229		case 'm':
230		case 's':
231			target_id = atoi(optarg);
232			if (c == 'q')
233				result = msgrm(0, target_id);
234			else if (c == 'm')
235				result = shmrm(0, target_id);
236			else
237				result = semrm(0, target_id);
238			if (result < 0) {
239				errflg++;
240				if (!signaled)
241					warn("%sid(%d): ",
242					    IPC_TO_STR(toupper(c)), target_id);
243				else
244					warnx(
245					    "%ss are not configured "
246					    "in the running kernel",
247					    IPC_TO_STRING(toupper(c)));
248			}
249			break;
250		case 'Q':
251		case 'M':
252		case 'S':
253			target_key = atol(optarg);
254			if (target_key == IPC_PRIVATE) {
255				warnx("can't remove private %ss",
256				    IPC_TO_STRING(c));
257				continue;
258			}
259			if (c == 'Q')
260				result = msgrm(target_key, 0);
261			else if (c == 'M')
262				result = shmrm(target_key, 0);
263			else
264				result = semrm(target_key, 0);
265			if (result < 0) {
266				errflg++;
267				if (!signaled)
268					warn("%ss(%ld): ",
269					    IPC_TO_STR(c), target_key);
270				else
271					warnx("%ss are not configured "
272					    "in the running kernel",
273					    IPC_TO_STRING(c));
274			}
275			break;
276		case 'v':
277		case 'y':
278			/* Handled in other getopt() loop */
279			break;
280		case 'W':
281			msgrm(-1, 0);
282			shmrm(-1, 0);
283			semrm(-1, 0);
284			break;
285		case ':':
286			fprintf(stderr,
287			    "option -%c requires an argument\n", optopt);
288			usage();
289		case '?':
290			fprintf(stderr, "unrecognized option: -%c\n", optopt);
291			usage();
292		}
293	}
294
295	if (optind != argc) {
296		fprintf(stderr, "unknown argument: %s\n", argv[optind]);
297		usage();
298	}
299	exit(errflg);
300}
301