summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys-utils/ipcrm.18
-rw-r--r--sys-utils/ipcrm.c92
2 files changed, 97 insertions, 3 deletions
diff --git a/sys-utils/ipcrm.1 b/sys-utils/ipcrm.1
index 02bff1bbc..6cf74a510 100644
--- a/sys-utils/ipcrm.1
+++ b/sys-utils/ipcrm.1
@@ -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),
diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c
index 4065c8a05..0ff07969e 100644
--- a/sys-utils/ipcrm.c
+++ b/sys-utils/ipcrm.c
@@ -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);
}