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$"); 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 53 int signaled; 54 int errflg; 55 int rmverbose = 0; 56 57 void usage(void); 58 59 int msgrm(key_t, int); 60 int shmrm(key_t, int); 61 int semrm(key_t, int); 62 void not_configured(int); 63 64 void 65 usage(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 75 int 76 msgrm(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 116 int 117 shmrm(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 157 int 158 semrm(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 199 void 200 not_configured(int signo __unused) 201 { 202 203 signaled++; 204 } 205 206 int 207 main(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