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]
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 */
33 * Remove specified message queues,
34 * semaphore sets and shared memory ids.
37 #include <sys/types.h>
43 #include <sys/ipc_impl.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
;
67 static int *idlist
, nids
;
70 oops(char *thing
, char *arg
)
75 case ENOENT
: /* key not found */
76 case EINVAL
: /* id not found */
81 e
= "permission denied";
87 (void) fprintf(stderr
, gettext("ipcrm: %s(%s): %s\n"), thing
, arg
, e
);
90 /* convert string to numeric key */
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"),
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
112 getids(int (*idsfunc
)(int *, uint_t
, uint_t
*))
117 if (idsfunc(idlist
, nids
, &n
) != 0)
118 goto err
; /* should never happen */
121 idlist
= reallocarray(idlist
, (nids
= n
), sizeof (int));
137 struct msqid_ds64 qds
;
142 if (msgctl64(id
, IPC_STAT64
, &qds
) < 0) {
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
166 struct msqid_ds64 qds
;
168 if ((k
= getkey(kp
)) == 0)
172 /* lookup in local zone is simple */
173 if ((id
= msgget(k
, 0)) == -1)
180 /* search for right key and zone combination */
181 for (i
= 0; i
< n
; i
++) {
183 if (msgctl64(id
, IPC_STAT64
, &qds
) < 0)
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
);
196 struct semid_ds64 sds
;
199 struct semid_ds64
*buf
;
207 if (semctl64(id
, 0, IPC_STAT64
, semarg
) < 0) {
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
231 struct semid_ds64 sds
;
234 struct semid_ds64
*buf
;
238 if ((k
= getkey(kp
)) == 0)
242 /* lookup in local zone is simple */
243 if ((id
= semget(k
, 0, 0)) == -1)
251 /* search for right key and zone combination */
252 for (i
= 0; i
< n
; i
++) {
255 if (semctl64(id
, 0, IPC_STAT64
, semarg
) < 0)
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
);
269 struct shmid_ds64 mds
;
274 if (shmctl64(id
, IPC_STAT64
, &mds
) < 0) {
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
298 struct shmid_ds64 mds
;
300 if ((k
= getkey(kp
)) == 0)
304 /* lookup in local zone is simple */
305 if ((id
= shmget(k
, 0, 0)) == -1)
312 /* search for right key and zone combination */
313 for (i
= 0; i
< n
; i
++) {
316 if (shmctl64(id
, IPC_STAT64
, &mds
) < 0)
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
);
326 /* convert string containing zone name or id to a numeric id */
332 if (zone_get_id(arg
, &zoneid
) != 0) {
333 (void) fprintf(stderr
, gettext("ipcrm: unknown zone: %s\n"),
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.
372 while ((o
= getopt(argc
, argv
, opts
)) != EOF
) {
376 zoneid
= getzone(optarg
);
379 case 'q': /* skip the rest of the flags */
387 case '?': /* anything else is an error */
394 if (err
|| (optind
< argc
)) {
395 (void) fprintf(stderr
, gettext(USAGE
));
400 (void) fprintf(stderr
,
401 gettext("multiple -z options not allowed\n"));
402 (void) fprintf(stderr
, gettext(USAGE
));
406 optind
= 1; /* rewind for pass 2 */
407 while ((o
= getopt(argc
, argv
, opts
)) != EOF
) {
409 case 'z': /* zone identifier */
412 case 'q': /* message queue */
413 if ((ipc_id
= msggetid(optarg
)) < 0) {
415 } else if (msgctl(ipc_id
, IPC_RMID
, NULL_MSG
) == -1) {
416 oops("msgctl", optarg
);
421 case 'm': /* shared memory */
422 if ((ipc_id
= shmgetid(optarg
)) < 0) {
424 } else if (shmctl(ipc_id
, IPC_RMID
, NULL_SHM
) == -1) {
425 oops("shmctl", optarg
);
430 case 's': /* semaphores */
431 if ((ipc_id
= semgetid(optarg
)) < 0) {
433 } else if (semctl(ipc_id
, 0, IPC_RMID
, NULL_SEM
) ==
435 oops("semctl", optarg
);
440 case 'Q': /* message queue (by key) */
441 if ((ipc_id
= msggetkey(optarg
)) == -1) {
445 if (msgctl(ipc_id
, IPC_RMID
, NULL_MSG
) == -1) {
446 oops("msgctl", optarg
);
451 case 'M': /* shared memory (by key) */
452 if ((ipc_id
= shmgetkey(optarg
)) == -1) {
456 if (shmctl(ipc_id
, IPC_RMID
, NULL_SHM
) == -1) {
457 oops("shmctl", optarg
);
462 case 'S': /* semaphores (by key) */
463 if ((ipc_id
= semgetkey(optarg
)) == -1) {
467 if (semctl(ipc_id
, 0, IPC_RMID
, NULL_SEM
) == -1) {
468 oops("semctl", optarg
);