1 /* $NetBSD: ipcrm.c,v 1.16 2009/01/18 01:06:42 lukem 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 #ifdef __minix 50 #include <errno.h> 51 #endif /* __minix */ 52 53 #define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem")) 54 #define IPC_TO_STRING(x) (x == 'Q' ? "message queue" : \ 55 (x == 'M' ? "shared memory segment" : "semaphore")) 56 57 static sig_atomic_t signaled; 58 59 static void usage(void) __dead; 60 static int msgrm(key_t, int); 61 static int shmrm(key_t, int); 62 static int semrm(key_t, int); 63 static int msgrmall(void); 64 static int shmrmall(void); 65 static int semrmall(void); 66 static void not_configured(int); 67 68 static void 69 usage(void) 70 { 71 (void)fprintf(stderr, "Usage: %s [-M shmkey] [-m shmid] [-Q msgkey]\n", 72 getprogname()); 73 (void)fprintf(stderr, "\t[-q msqid] [-S semkey] [-s semid] ...\n"); 74 exit(1); 75 } 76 77 static int 78 msgrm(key_t key, int id) 79 { 80 #ifndef __minix 81 if (key) { 82 id = msgget(key, 0); 83 if (id == -1) 84 return -1; 85 } 86 return msgctl(id, IPC_RMID, NULL); 87 #else /* __minix */ 88 errno = ENOSYS; 89 return -1; 90 #endif /* __minix */ 91 } 92 93 static int 94 shmrm(key_t key, int id) 95 { 96 if (key) { 97 id = shmget(key, 0, 0); 98 if (id == -1) 99 return -1; 100 } 101 return shmctl(id, IPC_RMID, NULL); 102 } 103 104 static int 105 semrm(key_t key, int id) 106 { 107 108 if (key) { 109 id = semget(key, 0, 0); 110 if (id == -1) 111 return -1; 112 } 113 return semctl(id, 0, IPC_RMID, NULL); 114 } 115 116 static int 117 msgrmall(void) 118 { 119 int mib[4]; 120 struct msg_sysctl_info *msgsi; 121 int32_t i; 122 size_t len; 123 int result = 0; 124 125 mib[0] = CTL_KERN; 126 mib[1] = KERN_SYSVIPC; 127 mib[2] = KERN_SYSVIPC_INFO; 128 mib[3] = KERN_SYSVIPC_MSG_INFO; 129 130 if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) 131 err(1, "sysctl(KERN_SYSVIPC_MSG_INFO)"); 132 133 if ((msgsi = malloc(len)) == NULL) 134 err(1, "malloc"); 135 if (sysctl(mib, 4, msgsi, &len, NULL, 0) == -1) { 136 free(msgsi); 137 err(1, "sysctl(KERN_SYSVIPC_MSG_INFO)"); 138 } 139 140 for (i = 0; i < msgsi->msginfo.msgmni; i++) { 141 struct msgid_ds_sysctl *msgptr = &msgsi->msgids[i]; 142 if (msgptr->msg_qbytes != 0) 143 result -= msgrm((key_t)0, 144 (int)IXSEQ_TO_IPCID(i, msgptr->msg_perm)); 145 } 146 free(msgsi); 147 return result; 148 } 149 150 static int 151 shmrmall(void) 152 { 153 int mib[4]; 154 struct shm_sysctl_info *shmsi; 155 size_t i, len; 156 int result = 0; 157 158 mib[0] = CTL_KERN; 159 mib[1] = KERN_SYSVIPC; 160 mib[2] = KERN_SYSVIPC_INFO; 161 mib[3] = KERN_SYSVIPC_SHM_INFO; 162 163 if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) 164 err(1, "sysctl(KERN_SYSVIPC_SHM_INFO)"); 165 166 if ((shmsi = malloc(len)) == NULL) 167 err(1, "malloc"); 168 if (sysctl(mib, 4, shmsi, &len, NULL, 0) == -1) { 169 free(shmsi); 170 err(1, "sysctl(KERN_SYSVIPC_SHM_INFO)"); 171 } 172 173 for (i = 0; i < shmsi->shminfo.shmmni; i++) { 174 struct shmid_ds_sysctl *shmptr = &shmsi->shmids[i]; 175 if (shmptr->shm_perm.mode & 0x0800) 176 result -= shmrm((key_t)0, 177 (int)IXSEQ_TO_IPCID(i, shmptr->shm_perm)); 178 } 179 free(shmsi); 180 return result; 181 } 182 183 static int 184 semrmall(void) 185 { 186 int mib[4]; 187 struct sem_sysctl_info *semsi; 188 size_t len; 189 int32_t i; 190 int result = 0; 191 192 mib[0] = CTL_KERN; 193 mib[1] = KERN_SYSVIPC; 194 mib[2] = KERN_SYSVIPC_INFO; 195 mib[3] = KERN_SYSVIPC_SEM_INFO; 196 197 if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) 198 err(1, "sysctl(KERN_SYSVIPC_SEM_INFO)"); 199 200 if ((semsi = malloc(len)) == NULL) 201 err(1, "malloc"); 202 if (sysctl(mib, 4, semsi, &len, NULL, 0) == -1) { 203 free(semsi); 204 err(1, "sysctl(KERN_SYSVIPC_SEM_INFO)"); 205 } 206 207 for (i = 0; i < semsi->seminfo.semmni; i++) { 208 struct semid_ds_sysctl *semptr = &semsi->semids[i]; 209 if ((semptr->sem_perm.mode & SEM_ALLOC) != 0) 210 result -= semrm((key_t)0, 211 (int)IXSEQ_TO_IPCID(i, semptr->sem_perm)); 212 } 213 free(semsi); 214 return result; 215 } 216 217 static void 218 /*ARGSUSED*/ 219 not_configured(int n) 220 { 221 signaled++; 222 } 223 224 int 225 main(int argc, char *argv[]) 226 { 227 int c, result, errflg, target_id; 228 key_t target_key; 229 230 setprogname(argv[0]); 231 errflg = 0; 232 (void)signal(SIGSYS, not_configured); 233 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) { 234 signaled = 0; 235 target_id = 0; 236 target_key = 0; 237 result = 0; 238 239 if (optarg != NULL && strcmp(optarg, "all") == 0) { 240 switch (c) { 241 case 'm': 242 case 'M': 243 result = shmrmall(); 244 break; 245 case 'q': 246 case 'Q': 247 result = msgrmall(); 248 break; 249 case 's': 250 case 'S': 251 result = semrmall(); 252 break; 253 default: 254 usage(); 255 } 256 } else { 257 switch (c) { 258 case 'q': 259 case 'm': 260 case 's': 261 target_id = atoi(optarg); 262 break; 263 case 'Q': 264 case 'M': 265 case 'S': 266 target_key = atol(optarg); 267 if (target_key == IPC_PRIVATE) { 268 warnx("can't remove private %ss", 269 IPC_TO_STRING(c)); 270 continue; 271 } 272 break; 273 default: 274 usage(); 275 } 276 switch (c) { 277 case 'q': 278 result = msgrm((key_t)0, target_id); 279 break; 280 case 'm': 281 result = shmrm((key_t)0, target_id); 282 break; 283 case 's': 284 result = semrm((key_t)0, target_id); 285 break; 286 case 'Q': 287 result = msgrm(target_key, 0); 288 break; 289 case 'M': 290 result = shmrm(target_key, 0); 291 break; 292 case 'S': 293 result = semrm(target_key, 0); 294 break; 295 } 296 } 297 if (result < 0) { 298 if (!signaled) { 299 if (target_id) { 300 warn("%sid(%d): ", 301 IPC_TO_STR(toupper(c)), target_id); 302 errflg++; 303 } else if (target_key) { 304 warn("%skey(%ld): ", IPC_TO_STR(c), 305 (long)target_key); 306 errflg++; 307 } 308 } else { 309 errflg++; 310 warnx("%ss are not configured in " 311 "the running kernel", 312 IPC_TO_STRING(toupper(c))); 313 } 314 } 315 } 316 317 if (optind != argc) { 318 warnx("Unknown argument: %s", argv[optind]); 319 usage(); 320 } 321 return errflg; 322 } 323