#include <ctype.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem"))
#define IPC_TO_STRING(x) (x == 'Q' ? "message queue" : \
(x == 'M' ? "shared memory segment" : "semaphore"))
volatile sig_atomic_t signaled;
static void usage(void) __dead2;
static int msgrm(key_t, int);
static int shmrm(key_t, int);
static int semrm(key_t, int);
static void not_configured(int);
static void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
"usage: ipcrm [-q msqid] [-m shmid] [-s semid]",
" [-Q msgkey] [-M shmkey] [-S semkey] ...");
exit(1);
}
static int
msgrm(key_t key, int id)
{
if (key) {
id = msgget(key, 0);
if (id == -1)
return -1;
}
return msgctl(id, IPC_RMID, NULL);
}
static int
shmrm(key_t key, int id)
{
if (key) {
id = shmget(key, 0, 0);
if (id == -1)
return -1;
}
return shmctl(id, IPC_RMID, NULL);
}
static int
semrm(key_t key, int id)
{
if (key) {
id = semget(key, 0, 0);
if (id == -1)
return -1;
}
return semctl(id, 0, IPC_RMID);
}
static void
not_configured(int signo __unused)
{
signaled++;
}
int
main(int argc, char **argv)
{
int c, result, errflg, target_id;
key_t target_key;
errflg = 0;
signal(SIGSYS, not_configured);
while ((c = getopt(argc, argv, ":q:m:s:Q:M:S:")) != -1) {
signaled = 0;
switch (c) {
case 'q':
case 'm':
case 's':
target_id = atoi(optarg);
if (c == 'q')
result = msgrm(0, target_id);
else if (c == 'm')
result = shmrm(0, target_id);
else
result = semrm(0, target_id);
if (result < 0) {
errflg++;
if (!signaled)
warn("%sid(%d)", IPC_TO_STR(toupper(c)), target_id);
else
warnx("%ss are not configured in the running kernel",
IPC_TO_STRING(toupper(c)));
}
break;
case 'Q':
case 'M':
case 'S':
target_key = atol(optarg);
if (target_key == IPC_PRIVATE) {
warnx("can't remove private %ss", IPC_TO_STRING(c));
continue;
}
if (c == 'Q')
result = msgrm(target_key, 0);
else if (c == 'M')
result = shmrm(target_key, 0);
else
result = semrm(target_key, 0);
if (result < 0) {
errflg++;
if (!signaled)
warn("%s key %ld aborted", IPC_TO_STR(c), target_key);
else
warnx("%ss are not configured in the running kernel",
IPC_TO_STRING(c));
}
break;
case ':':
warnx("option -%c requires an argument\n", optopt);
usage();
case '?':
warnx("unrecognized option: -%c\n", optopt);
usage();
}
}
if (optind != argc) {
warnx("unknown argument: %s\n", argv[optind]);
usage();
}
exit(errflg);
}