summaryrefslogtreecommitdiffstats
path: root/sys-utils/ipcrm.c
diff options
context:
space:
mode:
authorSami Kerola2011-08-28 20:24:07 +0200
committerSami Kerola2011-09-17 14:25:14 +0200
commit8b69b6d6de3dc2aa1a4678e0c8c5053efd279c2f (patch)
treedea8bca774284b6278641295a7877668901d9e70 /sys-utils/ipcrm.c
parentipcrm: exit if unknown error occurs (diff)
downloadkernel-qcow2-util-linux-8b69b6d6de3dc2aa1a4678e0c8c5053efd279c2f.tar.gz
kernel-qcow2-util-linux-8b69b6d6de3dc2aa1a4678e0c8c5053efd279c2f.tar.xz
kernel-qcow2-util-linux-8b69b6d6de3dc2aa1a4678e0c8c5053efd279c2f.zip
ipcrm: refactor new and old main to share code
The code is now much more tidy, and as a bonus old main has shares error printing with the `new' code. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'sys-utils/ipcrm.c')
-rw-r--r--sys-utils/ipcrm.c338
1 files changed, 193 insertions, 145 deletions
diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c
index 3ee1d5137..664960627 100644
--- a/sys-utils/ipcrm.c
+++ b/sys-utils/ipcrm.c
@@ -22,6 +22,7 @@
#include <sys/sem.h>
#include "c.h"
#include "nls.h"
+#include "strutils.h"
/* for getopt */
#include <unistd.h>
@@ -64,81 +65,168 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-static int
-remove_ids(type_id type, int argc, char **argv) {
- int id;
- int ret = 0; /* for gcc */
- char *end;
- int nb_errors = 0;
+int remove_id(int type, int iskey, int id)
+{
+ char *errmsg;
+ /* needed to delete semaphores */
union semun arg;
-
arg.val = 0;
- while(argc) {
+ /* do the removal */
+ switch (type) {
+ case SHM:
+ shmctl(id, IPC_RMID, NULL);
+ break;
+ case MSG:
+ msgctl(id, IPC_RMID, NULL);
+ break;
+ case SEM:
+ semctl(id, 0, IPC_RMID, arg);
+ break;
+ default:
+ errx(EXIT_FAILURE, "impossible occurred");
+ }
- id = strtoul(argv[0], &end, 10);
+ /* how did the removal go? */
+ switch (errno) {
+ case 0:
+ return 0;
+ case EACCES:
+ case EPERM:
+ errmsg = iskey ? _("permission denied for key") : _("permission denied for id");
+ break;
+ case EINVAL:
+ errmsg = iskey ? _("invalid key") : _("invalid id");
+ break;
+ case EIDRM:
+ errmsg = iskey ? _("already removed key") : _("already removed id");
+ break;
+ default:
+ if (iskey)
+ err(EXIT_FAILURE, _("key failed"));
+ err(EXIT_FAILURE, _("id failed"));
+ }
+ warnx("%s (%d)", errmsg, id);
+ return 1;
+}
+static int remove_arg_list(type_id type, int argc, char **argv)
+{
+ int id;
+ char *end;
+ int nb_errors = 0;
+
+ do {
+ id = strtoul(argv[0], &end, 10);
if (*end != 0) {
warnx(_("invalid id: %s"), argv[0]);
- nb_errors ++;
+ nb_errors++;
} else {
- switch(type) {
- case SEM:
- ret = semctl (id, 0, IPC_RMID, arg);
- break;
-
- case MSG:
- ret = msgctl (id, IPC_RMID, NULL);
- break;
-
- case SHM:
- ret = shmctl (id, IPC_RMID, NULL);
- break;
- }
-
- if (ret) {
- warn(_("cannot remove id %s"), argv[0]);
- nb_errors ++;
- }
+ if (remove_id(type, 0, id))
+ nb_errors++;
}
argc--;
argv++;
- }
-
- return(nb_errors);
+ } while (argc);
+ return (nb_errors);
}
static int deprecated_main(int argc, char **argv)
{
- if (argc < 3)
- usage(stderr);
-
- if (!strcmp(argv[1], "shm")) {
- if (remove_ids(SHM, argc-2, &argv[2]))
- exit(1);
- }
- else if (!strcmp(argv[1], "msg")) {
- if (remove_ids(MSG, argc-2, &argv[2]))
- exit(1);
- }
- else if (!strcmp(argv[1], "sem")) {
- if (remove_ids(SEM, argc-2, &argv[2]))
- exit(1);
- }
- else {
- warnx(_("unknown resource type: %s"), argv[1]);
+ type_id type;
+
+ if (!strcmp(argv[1], "shm"))
+ type = SHM;
+ else if (!strcmp(argv[1], "msg"))
+ type = MSG;
+ else if (!strcmp(argv[1], "sem"))
+ type = SEM;
+ else
+ return 0;
+
+ if (argc < 3) {
+ warnx(_("not enough arguments"));
usage(stderr);
}
- printf (_("resource(s) deleted\n"));
+ if (remove_arg_list(type, argc - 2, &argv[2]))
+ exit(EXIT_FAILURE);
+
+ printf(_("resource(s) deleted\n"));
+ return 1;
+}
+
+unsigned long strtokey(const char *str, const char *errmesg)
+{
+ unsigned long num;
+ char *end = NULL;
+
+ if (str == NULL || *str == '\0')
+ goto err;
+ errno = 0;
+ /* keys are in hex or decimal */
+ num = strtoul(str, &end, 0);
+
+ if (errno || str == end || (end && *end))
+ goto err;
+
+ return num;
+ err:
+ if (errno)
+ err(EXIT_FAILURE, "%s: '%s'", errmesg, str);
+ else
+ errx(EXIT_FAILURE, "%s: '%s'", errmesg, str);
return 0;
}
+static int key_to_id(type_id type, char *optarg)
+{
+ int id;
+ /* keys are in hex or decimal */
+ key_t key = strtokey(optarg, "failed to parse argument");
+ if (key == IPC_PRIVATE) {
+ warnx(_("illegal key (%s)"), optarg);
+ return -1;
+ }
+ switch (type) {
+ case SHM:
+ id = shmget(key, 0, 0);
+ break;
+ case MSG:
+ id = msgget(key, 0);
+ break;
+ case SEM:
+ id = semget(key, 0, 0);
+ break;
+ default:
+ errx(EXIT_FAILURE, "impossible occurred");
+ }
+ if (id < 0) {
+ char *errmsg;
+ switch (errno) {
+ case EACCES:
+ errmsg = _("permission denied for key");
+ break;
+ case EIDRM:
+ errmsg = _("already removed key");
+ break;
+ case ENOENT:
+ errmsg = _("invalid key");
+ break;
+ default:
+ err(EXIT_FAILURE, _("key failed"));
+ }
+ warnx("%s (%s)", errmsg, optarg);
+ }
+ return id;
+}
int main(int argc, char **argv)
{
- int c;
- int error = 0;
+ int c;
+ int ret = 0;
+ int id = -1;
+ int iskey;
static const struct option longopts[] = {
{"shmem-id", required_argument, NULL, 'm'},
@@ -161,107 +249,67 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
/* check to see if the command is being invoked in the old way if so
- then run the old code */
- if (strcmp(argv[1], "shm") == 0 ||
- strcmp(argv[1], "msg") == 0 ||
- strcmp(argv[1], "sem") == 0)
- return deprecated_main(argc, argv);
+ * then remove argument list */
+ if (deprecated_main(argc, argv))
+ return EXIT_SUCCESS;
/* process new syntax to conform with SYSV ipcrm */
- while ((c = getopt_long(argc, argv, "q:m:s:Q:M:S:hV", longopts, NULL)) != -1) {
- int result;
- int id = 0;
- int iskey = isupper(c);
-
- /* needed to delete semaphores */
- union semun arg;
- arg.val = 0;
-
- /* --help & --version */
- if (c == 'h')
- usage(stdout);
- if (c == 'V') {
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
- }
-
- /* we don't need case information any more */
- c = tolower(c);
-
- /* make sure the option is in range */
- if (c != 'q' && c != 'm' && c != 's') {
- usage(stderr);
- }
-
- if (iskey) {
- /* keys are in hex or decimal */
- key_t key = strtoul(optarg, NULL, 0);
- if (key == IPC_PRIVATE) {
- error++;
- warnx(_("illegal key (%s)"), optarg);
- continue;
+ for (id = -1;
+ (c = getopt_long(argc, argv, "q:m:s:Q:M:S:hV", longopts, NULL)) != -1;
+ id = -1) {
+ switch (c) {
+ case 'M':
+ iskey = 0;
+ id = key_to_id(SHM, optarg);
+ if (id < 0) {
+ ret++;
+ break;
}
-
- /* convert key to id */
- id = ((c == 'q') ? msgget(key, 0) :
- (c == 'm') ? shmget(key, 0, 0) :
- semget(key, 0, 0));
-
+ case 'm':
if (id < 0) {
- char *errmsg;
- error++;
- switch(errno) {
- case EACCES:
- errmsg = _("permission denied for key");
- break;
- case EIDRM:
- errmsg = _("already removed key");
- break;
- case ENOENT:
- errmsg = _("invalid key");
- break;
- default:
- err(EXIT_FAILURE, _("key failed"));
- }
- warnx("%s (%s)", errmsg, optarg);
- continue;
+ iskey = 1;
+ id = strtoll_or_err(optarg, _("failed to parse argument"));
}
- } else {
- /* ids are in decimal */
- id = strtoul(optarg, NULL, 10);
- }
-
- result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
- (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
- semctl(id, 0, IPC_RMID, arg));
-
- if (result < 0) {
- char *errmsg;
- error++;
- switch(errno) {
- case EACCES:
- case EPERM:
- errmsg = iskey
- ? _("permission denied for key")
- : _("permission denied for id");
- break;
- case EINVAL:
- errmsg = iskey
- ? _("invalid key")
- : _("invalid id");
+ if (remove_id(SHM, iskey, id))
+ ret++;
+ break;
+ case 'Q':
+ iskey = 0;
+ id = key_to_id(MSG, optarg);
+ if (id < 0) {
+ ret++;
break;
- case EIDRM:
- errmsg = iskey
- ? _("already removed key")
- : _("already removed id");
+ }
+ case 'q':
+ if (id < 0) {
+ iskey = 1;
+ id = strtoll_or_err(optarg, _("failed to parse argument"));
+ }
+ if (remove_id(MSG, iskey, id))
+ ret++;
+ break;
+ case 'S':
+ iskey = 0;
+ id = key_to_id(SEM, optarg);
+ if (id < 0) {
+ ret++;
break;
- default:
- if (iskey)
- err(EXIT_FAILURE, _("key failed"));
- err(EXIT_FAILURE, _("id failed"));
}
- warnx("%s (%s)", errmsg, optarg);
- continue;
+ case 's':
+ if (id < 0) {
+ iskey = 1;
+ id = strtoll_or_err(optarg, _("failed to parse argument"));
+ }
+ if (remove_id(SEM, iskey, id))
+ ret++;
+ break;
+ case 'h':
+ usage(stdout);
+ case 'V':
+ printf(UTIL_LINUX_VERSION);
+ return EXIT_SUCCESS;
+ default:
+ usage(stderr);
}
}
@@ -271,5 +319,5 @@ int main(int argc, char **argv)
usage(stderr);
}
- if (error == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}