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