ipcrm: add --all option

An --all option will remove all ipc entries. The option takes
optional resource argument, which limits the removal to be
applied only the given resource entries.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2011-09-12 18:56:30 +02:00
parent 5ccc85be82
commit 3d0fc72d65
2 changed files with 97 additions and 3 deletions

View File

@ -64,6 +64,14 @@ removes the semaphore created with
\fB\-s\fR, \fB\-\-semaphore\-id\fR \fIsemid\fR
removes the semaphore identified by
.IR semid .
.TP
\fB-a\fR, \fB\-\-all\fR [\fIshm msg sem\fR]
Remove all resources. When option argument is provided the removal is
performed only to for the specified resource types. Warning! Do not use
.B \-a
if you are unsure how the software using resources might react on missing
objects. Some programs create these resources at start up and may not have
any code to deal unexpected disappearance.
.LP
The details of the removes are described in
.IR msgctl (2),

View File

@ -18,6 +18,7 @@
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/types.h>
#include "c.h"
#include "nls.h"
#include "strutils.h"
@ -35,7 +36,8 @@ union semun {
typedef enum type_id {
SHM,
SEM,
MSG
MSG,
ALL
} type_id;
/* print the new usage */
@ -51,6 +53,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
fputs(_(" -Q, --queue-key <key> remove message queue by key\n"), out);
fputs(_(" -s, --semaphore-id <id> remove semaprhore by id\n"), out);
fputs(_(" -S, --semaphore-key <key> remove semaprhore by key\n"), out);
fputs(_(" -a, --all[=<shm|msg|sem>] remove all\n"), out);
fprintf(out, USAGE_HELP);
fprintf(out, USAGE_VERSION);
fprintf(out, USAGE_BEGIN_TAIL);
@ -191,6 +194,8 @@ static int key_to_id(type_id type, char *optarg)
case SEM:
id = semget(key, 0, 0);
break;
case ALL:
abort();
default:
errx(EXIT_FAILURE, "impossible occurred");
}
@ -214,12 +219,72 @@ static int key_to_id(type_id type, char *optarg)
return id;
}
int remove_all(type_id type)
{
int ret = 0;
int id, rm_me, maxid;
struct shmid_ds shmseg;
struct shm_info shm_info;
struct semid_ds semary;
struct seminfo seminfo;
union semun arg;
struct msqid_ds msgque;
struct msginfo msginfo;
if (type == SHM || type == ALL) {
maxid =
shmctl(0, SHM_INFO, (struct shmid_ds *)(void *)&shm_info);
if (maxid < 0)
errx(EXIT_FAILURE,
_("kernel not configured for shared memory"));
for (id = 0; id <= maxid; id++) {
rm_me = shmctl(id, SHM_STAT, &shmseg);
if (rm_me < 0)
continue;
ret |= remove_id(SHM, 0, rm_me);
}
}
if (type == SEM || type == ALL) {
arg.array = (ushort *) (void *)&seminfo;
maxid = semctl(0, 0, SEM_INFO, arg);
if (maxid < 0)
errx(EXIT_FAILURE,
_("kernel not configured for semaphores"));
for (id = 0; id <= maxid; id++) {
arg.buf = (struct semid_ds *)&semary;
rm_me = semctl(id, 0, SEM_STAT, arg);
if (rm_me < 0)
continue;
ret |= remove_id(SEM, 0, rm_me);
}
}
if (type == MSG || type == ALL) {
maxid =
msgctl(0, MSG_INFO, (struct msqid_ds *)(void *)&msginfo);
if (maxid < 0)
errx(EXIT_FAILURE,
_("kernel not configured for message queues"));
for (id = 0; id <= maxid; id++) {
rm_me = msgctl(id, MSG_STAT, &msgque);
if (rm_me < 0)
continue;
ret |= remove_id(MSG, 0, rm_me);
}
}
return ret;
}
int main(int argc, char **argv)
{
int c;
int ret = 0;
int id = -1;
int iskey;
int rm_all = 0;
type_id what_all;
static const struct option longopts[] = {
{"shmem-id", required_argument, NULL, 'm'},
@ -228,6 +293,7 @@ int main(int argc, char **argv)
{"queue-key", required_argument, NULL, 'Q'},
{"semaphore-id", required_argument, NULL, 's'},
{"semaphore-key", required_argument, NULL, 'S'},
{"all", optional_argument, NULL, 'a'},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
@ -248,7 +314,7 @@ int main(int argc, char **argv)
/* process new syntax to conform with SYSV ipcrm */
for (id = -1;
(c = getopt_long(argc, argv, "q:m:s:Q:M:S:hV", longopts, NULL)) != -1;
(c = getopt_long(argc, argv, "q:m:s:Q:M:S:a::hV", longopts, NULL)) != -1;
id = -1) {
switch (c) {
case 'M':
@ -296,6 +362,22 @@ int main(int argc, char **argv)
if (remove_id(SEM, iskey, id))
ret++;
break;
case 'a':
rm_all = 1;
if (optarg) {
if (!strcmp(optarg, "shm"))
what_all = SHM;
else if (!strcmp(optarg, "msg"))
what_all = MSG;
else if (!strcmp(optarg, "sem"))
what_all = SEM;
else
errx(EXIT_FAILURE,
_("unknown argument: %s"), optarg);
} else {
what_all = ALL;
}
break;
case 'h':
usage(stdout);
case 'V':
@ -306,8 +388,12 @@ int main(int argc, char **argv)
}
}
if (rm_all)
if (remove_all(what_all))
ret++;
/* print usage if we still have some arguments left over */
if (optind != argc) {
if (optind < argc) {
warnx(_("unknown argument: %s"), argv[optind]);
usage(stderr);
}