dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / ipcrm / ipcrm.c
blob7f9f2f0cc457e1243cda14bff2ac681b3d5d4ad7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
31 * ipcrm - IPC remove
33 * Remove specified message queues,
34 * semaphore sets and shared memory ids.
37 #include <sys/types.h>
38 #include <sys/ipc.h>
39 #include <sys/msg.h>
40 #include <sys/sem.h>
41 #include <sys/shm.h>
42 #include <errno.h>
43 #include <sys/ipc_impl.h>
44 #include <zone.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <signal.h>
48 #include <locale.h>
50 #define NULL_MSG (NULL)
51 #define NULL_SEM (NULL)
52 #define NULL_SHM (NULL)
54 #define USAGE "usage: ipcrm [-z zone] [ [-q msqid] [-m shmid] " \
55 "[-s semid]\n\t [-Q msgkey] [-M shmkey] [-S semkey] ... ]\n"
57 #define IPC_KEYMATCH(perm, zoneid, key) \
58 ((perm).ipcx_key == (key) && (perm).ipcx_zoneid == (zoneid))
60 static char opts[] = "z:q:m:s:Q:M:S:"; /* allowable options for getopt */
61 extern char *optarg; /* arg pointer for getopt */
62 extern int optind; /* option index for getopt */
64 static zoneid_t zoneid;
65 static int zflg;
67 static int *idlist, nids;
69 static void
70 oops(char *thing, char *arg)
72 char *e;
74 switch (errno) {
75 case ENOENT: /* key not found */
76 case EINVAL: /* id not found */
77 e = "not found";
78 break;
80 case EPERM:
81 e = "permission denied";
82 break;
83 default:
84 e = "unknown error";
87 (void) fprintf(stderr, gettext("ipcrm: %s(%s): %s\n"), thing, arg, e);
90 /* convert string to numeric key */
91 static key_t
92 getkey(char *kp)
94 key_t k;
95 char *tp; /* will point to char that terminates strtol scan */
97 if ((k = (key_t)strtoul(kp, &tp, 0)) == IPC_PRIVATE || *tp != '\0') {
98 (void) fprintf(stderr, gettext("ipcrm: illegal key: %s\n"),
99 kp);
100 return (0);
102 return (k);
106 * Gets list of all IPC ids (of a particular type) visible in the
107 * caller's zone. Returns number of ids retrieved. On return, idlist
108 * is set to point to an array of ids at least as large as the number
109 * retrieved.
111 static uint_t
112 getids(int (*idsfunc)(int *, uint_t, uint_t *))
114 uint_t n;
116 for (;;) {
117 if (idsfunc(idlist, nids, &n) != 0)
118 goto err; /* should never happen */
119 if (n <= nids)
120 break;
121 idlist = reallocarray(idlist, (nids = n), sizeof (int));
122 if (idlist == NULL)
123 goto err;
125 return (n);
127 err:
128 perror("ipcrm");
129 exit(1);
130 /* NOTREACHED */
133 static int
134 msggetid(char *arg)
136 int id = atol(arg);
137 struct msqid_ds64 qds;
139 if (!zflg)
140 return (id);
142 if (msgctl64(id, IPC_STAT64, &qds) < 0) {
143 oops("msgctl", arg);
144 return (-1);
146 if (qds.msgx_perm.ipcx_zoneid != zoneid) {
148 * Not in right zone, pretend the call failed.
149 * Message should be the same as that returned if
150 * msggetid succeeds but the subsequent IPC_RMID fails
151 * with EINVAL.
153 errno = EINVAL;
154 oops("msgctl", arg);
155 return (-1);
157 return (id);
160 static int
161 msggetkey(char *kp)
163 key_t k;
164 int id, i;
165 uint_t n;
166 struct msqid_ds64 qds;
168 if ((k = getkey(kp)) == 0)
169 return (-1);
171 if (!zflg) {
172 /* lookup in local zone is simple */
173 if ((id = msgget(k, 0)) == -1)
174 oops("msgget", kp);
175 return (id);
178 n = getids(msgids);
180 /* search for right key and zone combination */
181 for (i = 0; i < n; i++) {
182 id = idlist[i];
183 if (msgctl64(id, IPC_STAT64, &qds) < 0)
184 continue;
185 if (IPC_KEYMATCH(qds.msgx_perm, zoneid, k))
186 return (id); /* found it, no need to look further */
188 (void) fprintf(stderr, gettext("ipcrm: unknown key: %s\n"), kp);
189 return (-1);
192 static int
193 semgetid(char *arg)
195 int id = atol(arg);
196 struct semid_ds64 sds;
197 union semun {
198 int val;
199 struct semid_ds64 *buf;
200 ushort_t *array;
201 } semarg;
203 if (!zflg)
204 return (id);
206 semarg.buf = &sds;
207 if (semctl64(id, 0, IPC_STAT64, semarg) < 0) {
208 oops("semctl", arg);
209 return (-1);
211 if (sds.semx_perm.ipcx_zoneid != zoneid) {
213 * Not in right zone, pretend the call failed.
214 * Message should be the same as that returned if
215 * semgetid succeeds but the subsequent IPC_RMID fails
216 * with EINVAL.
218 errno = EINVAL;
219 oops("semctl", arg);
220 return (-1);
222 return (id);
225 static int
226 semgetkey(char *kp)
228 key_t k;
229 int id, i;
230 uint_t n;
231 struct semid_ds64 sds;
232 union semun {
233 int val;
234 struct semid_ds64 *buf;
235 ushort_t *array;
236 } semarg;
238 if ((k = getkey(kp)) == 0)
239 return (-1);
241 if (!zflg) {
242 /* lookup in local zone is simple */
243 if ((id = semget(k, 0, 0)) == -1)
244 oops("semget", kp);
245 return (id);
248 n = getids(semids);
250 semarg.buf = &sds;
251 /* search for right key and zone combination */
252 for (i = 0; i < n; i++) {
253 int id;
254 id = idlist[i];
255 if (semctl64(id, 0, IPC_STAT64, semarg) < 0)
256 continue;
257 if (IPC_KEYMATCH(sds.semx_perm, zoneid, k))
258 return (id); /* found it, no need to look further */
261 (void) fprintf(stderr, gettext("ipcrm: unknown key: %s\n"), kp);
262 return (-1);
265 static int
266 shmgetid(char *arg)
268 int id = atol(arg);
269 struct shmid_ds64 mds;
271 if (!zflg)
272 return (id);
274 if (shmctl64(id, IPC_STAT64, &mds) < 0) {
275 oops("shmctl", arg);
276 return (-1);
278 if (mds.shmx_perm.ipcx_zoneid != zoneid) {
280 * Not in right zone, pretend the call failed.
281 * Message should be the same as that returned if
282 * shmgetid succeeds but the subsequent IPC_RMID fails
283 * with EINVAL.
285 errno = EINVAL;
286 oops("shmctl", arg);
287 return (-1);
289 return (id);
292 static int
293 shmgetkey(char *kp)
295 key_t k;
296 int id, i;
297 uint_t n;
298 struct shmid_ds64 mds;
300 if ((k = getkey(kp)) == 0)
301 return (-1);
303 if (!zflg) {
304 /* lookup in local zone is simple */
305 if ((id = shmget(k, 0, 0)) == -1)
306 oops("shmget", kp);
307 return (id);
310 n = getids(shmids);
312 /* search for right key and zone combination */
313 for (i = 0; i < n; i++) {
314 int id;
315 id = idlist[i];
316 if (shmctl64(id, IPC_STAT64, &mds) < 0)
317 continue;
318 if (IPC_KEYMATCH(mds.shmx_perm, zoneid, k))
319 return (id); /* found it, no need to look further */
321 (void) fprintf(stderr, gettext("ipcrm: unknown key: %s\n"), kp);
322 return (-1);
326 /* convert string containing zone name or id to a numeric id */
327 static zoneid_t
328 getzone(char *arg)
330 zoneid_t zoneid;
332 if (zone_get_id(arg, &zoneid) != 0) {
333 (void) fprintf(stderr, gettext("ipcrm: unknown zone: %s\n"),
334 arg);
335 exit(1);
337 return (zoneid);
341 main(int argc, char **argv)
343 int o; /* option flag */
344 int err; /* error count */
345 int ipc_id; /* id to remove */
347 (void) setlocale(LC_ALL, "");
348 (void) textdomain(TEXT_DOMAIN);
350 * If one or more of the IPC modules is not
351 * included in the kernel, the corresponding
352 * system calls will incur SIGSYS. Ignoring
353 * that signal makes the system call appear
354 * to fail with errno == EINVAL, which can be
355 * interpreted appropriately in oops().
358 (void) signal(SIGSYS, SIG_IGN);
361 * If no -z argument is specified, only objects in the current
362 * zone can be removed with keys.
364 zoneid = getzoneid();
367 * Go through the options. The first pass looks only for -z
368 * since this option can affect the processing of keys. The
369 * second pass looks for the other options and ignores -z.
371 err = 0;
372 while ((o = getopt(argc, argv, opts)) != EOF) {
373 switch (o) {
374 case 'z':
375 zflg++;
376 zoneid = getzone(optarg);
377 break;
379 case 'q': /* skip the rest of the flags */
380 case 'm':
381 case 's':
382 case 'Q':
383 case 'M':
384 case 'S':
385 break;
387 case '?': /* anything else is an error */
388 default:
389 err++;
390 break;
394 if (err || (optind < argc)) {
395 (void) fprintf(stderr, gettext(USAGE));
396 return (err);
399 if (zflg > 1) {
400 (void) fprintf(stderr,
401 gettext("multiple -z options not allowed\n"));
402 (void) fprintf(stderr, gettext(USAGE));
403 return (1);
406 optind = 1; /* rewind for pass 2 */
407 while ((o = getopt(argc, argv, opts)) != EOF) {
408 switch (o) {
409 case 'z': /* zone identifier */
410 break;
412 case 'q': /* message queue */
413 if ((ipc_id = msggetid(optarg)) < 0) {
414 err++;
415 } else if (msgctl(ipc_id, IPC_RMID, NULL_MSG) == -1) {
416 oops("msgctl", optarg);
417 err++;
419 break;
421 case 'm': /* shared memory */
422 if ((ipc_id = shmgetid(optarg)) < 0) {
423 err++;
424 } else if (shmctl(ipc_id, IPC_RMID, NULL_SHM) == -1) {
425 oops("shmctl", optarg);
426 err++;
428 break;
430 case 's': /* semaphores */
431 if ((ipc_id = semgetid(optarg)) < 0) {
432 err++;
433 } else if (semctl(ipc_id, 0, IPC_RMID, NULL_SEM) ==
434 -1) {
435 oops("semctl", optarg);
436 err++;
438 break;
440 case 'Q': /* message queue (by key) */
441 if ((ipc_id = msggetkey(optarg)) == -1) {
442 err++;
443 break;
445 if (msgctl(ipc_id, IPC_RMID, NULL_MSG) == -1) {
446 oops("msgctl", optarg);
447 err++;
449 break;
451 case 'M': /* shared memory (by key) */
452 if ((ipc_id = shmgetkey(optarg)) == -1) {
453 err++;
454 break;
456 if (shmctl(ipc_id, IPC_RMID, NULL_SHM) == -1) {
457 oops("shmctl", optarg);
458 err++;
460 break;
462 case 'S': /* semaphores (by key) */
463 if ((ipc_id = semgetkey(optarg)) == -1) {
464 err++;
465 break;
467 if (semctl(ipc_id, 0, IPC_RMID, NULL_SEM) == -1) {
468 oops("semctl", optarg);
469 err++;
471 break;
474 return (err);