/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* ipcrm - IPC remove
*
* Remove specified message queues,
* semaphore sets and shared memory ids.
*/
#include <errno.h>
#include <sys/ipc_impl.h>
#include <zone.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <locale.h>
"[-s semid]\n\t [-Q msgkey] [-M shmkey] [-S semkey] ... ]\n"
extern char *optarg; /* arg pointer for getopt */
extern int optind; /* option index for getopt */
static int zflg;
static void
{
char *e;
switch (errno) {
case ENOENT: /* key not found */
case EINVAL: /* id not found */
e = "not found";
break;
case EPERM:
e = "permission denied";
break;
default:
e = "unknown error";
}
}
/* convert string to numeric key */
static key_t
{
key_t k;
kp);
return (0);
}
return (k);
}
/*
* Gets list of all IPC ids (of a particular type) visible in the
* caller's zone. Returns number of ids retrieved. On return, idlist
* is set to point to an array of ids at least as large as the number
* retrieved.
*/
static uint_t
{
uint_t n;
for (;;) {
goto err; /* should never happen */
if (n <= nids)
break;
goto err;
}
return (n);
err:
perror("ipcrm");
exit(1);
/* NOTREACHED */
}
static int
{
if (!zflg)
return (id);
return (-1);
}
/*
* Not in right zone, pretend the call failed.
* Message should be the same as that returned if
* msggetid succeeds but the subsequent IPC_RMID fails
* with EINVAL.
*/
return (-1);
}
return (id);
}
static int
{
key_t k;
int id, i;
uint_t n;
return (-1);
if (!zflg) {
/* lookup in local zone is simple */
return (id);
}
/* search for right key and zone combination */
for (i = 0; i < n; i++) {
continue;
return (id); /* found it, no need to look further */
}
return (-1);
}
static int
{
union semun {
int val;
} semarg;
if (!zflg)
return (id);
return (-1);
}
/*
* Not in right zone, pretend the call failed.
* Message should be the same as that returned if
* semgetid succeeds but the subsequent IPC_RMID fails
* with EINVAL.
*/
return (-1);
}
return (id);
}
static int
{
key_t k;
int id, i;
uint_t n;
union semun {
int val;
} semarg;
return (-1);
if (!zflg) {
/* lookup in local zone is simple */
return (id);
}
/* search for right key and zone combination */
for (i = 0; i < n; i++) {
int id;
continue;
return (id); /* found it, no need to look further */
}
return (-1);
}
static int
{
if (!zflg)
return (id);
return (-1);
}
/*
* Not in right zone, pretend the call failed.
* Message should be the same as that returned if
* shmgetid succeeds but the subsequent IPC_RMID fails
* with EINVAL.
*/
return (-1);
}
return (id);
}
static int
{
key_t k;
int id, i;
uint_t n;
return (-1);
if (!zflg) {
/* lookup in local zone is simple */
return (id);
}
/* search for right key and zone combination */
for (i = 0; i < n; i++) {
int id;
continue;
return (id); /* found it, no need to look further */
}
return (-1);
}
/* convert string containing zone name or id to a numeric id */
static zoneid_t
{
arg);
exit(1);
}
return (zoneid);
}
int
{
int o; /* option flag */
(void) textdomain(TEXT_DOMAIN);
/*
* If one or more of the IPC modules is not
* included in the kernel, the corresponding
* system calls will incur SIGSYS. Ignoring
* that signal makes the system call appear
* to fail with errno == EINVAL, which can be
* interpreted appropriately in oops().
*/
/*
* If no -z argument is specified, only objects in the current
* zone can be removed with keys.
*/
/*
* Go through the options. The first pass looks only for -z
* since this option can affect the processing of keys. The
* second pass looks for the other options and ignores -z.
*/
err = 0;
switch (o) {
case 'z':
zflg++;
break;
case 'q': /* skip the rest of the flags */
case 'm':
case 's':
case 'Q':
case 'M':
case 'S':
break;
case '?': /* anything else is an error */
default:
err++;
break;
}
}
return (err);
}
if (zflg > 1) {
gettext("multiple -z options not allowed\n"));
return (1);
}
switch (o) {
case 'z': /* zone identifier */
break;
case 'q': /* message queue */
err++;
err++;
}
break;
case 'm': /* shared memory */
err++;
err++;
}
break;
case 's': /* semaphores */
err++;
-1) {
err++;
}
break;
case 'Q': /* message queue (by key) */
err++;
break;
}
err++;
}
break;
case 'M': /* shared memory (by key) */
err++;
break;
}
err++;
}
break;
case 'S': /* semaphores (by key) */
err++;
break;
}
err++;
}
break;
}
}
return (err);
}