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