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