diff options
author | Rob Landley <rob@landley.net> | 2005-06-20 08:30:36 +0400 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2005-06-20 08:30:36 +0400 |
commit | 6eb1e416743c597f8ecd3b595ddb00d3aa42c1f4 (patch) | |
tree | b88e5e3d34a2edea9bd2a9c59fd1cf84a62ddf4d /util-linux/ipcrm.c | |
parent | df1eda82b90d1c179b34d27f2825264efed10045 (diff) |
Rodney Radford submitted ipcs and ipcrm (system V IPC stuff). They could use
some more work to shrink them down.
Diffstat (limited to 'util-linux/ipcrm.c')
-rw-r--r-- | util-linux/ipcrm.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c new file mode 100644 index 000000000..9e18752a3 --- /dev/null +++ b/util-linux/ipcrm.c @@ -0,0 +1,273 @@ +/* + * ipcrm.c -- utility to allow removal of IPC objects and data structures. + * + * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com> + * Adapted for busybox from util-linux-2.12a. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- Pre-busybox history from util-linux-2.12a ------------------------ + * + * 1999-04-02 frank zago + * - can now remove several id's in the same call + * + * 1999-02-22 Arkadiusz Mi˙kiewicz <misiek@pld.ORG.PL> + * - added Native Language Support + * + * Original author - krishna balasubramanian 1993 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/msg.h> +#include <sys/sem.h> + +/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */ +/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */ +/* for getopt */ +#include <unistd.h> + +/* for tolower and isupper */ +#include <ctype.h> + +#include "busybox.h" + +#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) +/* union semun is defined by including <sys/sem.h> */ +#else +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; +#endif + +typedef enum type_id { + SHM, + SEM, + MSG +} type_id; + +static int +remove_ids(type_id type, int argc, char **argv) { + int id; + int ret = 0; /* for gcc */ + char *end; + int nb_errors = 0; + union semun arg; + + arg.val = 0; + + while(argc) { + + id = strtoul(argv[0], &end, 10); + + if (*end != 0) { + bb_printf ("invalid id: %s\n", argv[0]); + 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) { + bb_printf ("cannot remove id %s (%s)\n", + argv[0], strerror(errno)); + nb_errors ++; + } + } + argc--; + argv++; + } + + return(nb_errors); +} + +static int deprecated_main(int argc, char **argv) +{ + if (argc < 3) { + bb_show_usage(); + bb_fflush_stdout_and_exit(1); + } + + if (!strcmp(argv[1], "shm")) { + if (remove_ids(SHM, argc-2, &argv[2])) + bb_fflush_stdout_and_exit(1); + } + else if (!strcmp(argv[1], "msg")) { + if (remove_ids(MSG, argc-2, &argv[2])) + bb_fflush_stdout_and_exit(1); + } + else if (!strcmp(argv[1], "sem")) { + if (remove_ids(SEM, argc-2, &argv[2])) + bb_fflush_stdout_and_exit(1); + } + else { + bb_printf ("unknown resource type: %s\n", argv[1]); + bb_show_usage(); + bb_fflush_stdout_and_exit(1); + } + + bb_printf ("resource(s) deleted\n"); + return 0; +} + + +int ipcrm_main(int argc, char **argv) +{ + int c; + int error = 0; + char *prog = argv[0]; + + /* if the command is executed without parameters, do nothing */ + if (argc == 1) + return 0; + + /* 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); + + /* process new syntax to conform with SYSV ipcrm */ + while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) { + int result; + int id = 0; + int iskey = isupper(c); + + /* needed to delete semaphores */ + union semun arg; + arg.val = 0; + + if ((c == '?') || (c == 'h')) + { + bb_show_usage(); + return 0; + } + + /* 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') { + bb_show_usage(); + error++; + return error; + } + + if (iskey) { + /* keys are in hex or decimal */ + key_t key = strtoul(optarg, NULL, 0); + if (key == IPC_PRIVATE) { + error++; + bb_fprintf(stderr, "%s: illegal key (%s)\n", + prog, optarg); + continue; + } + + /* convert key to id */ + id = ((c == 'q') ? msgget(key, 0) : + (c == 'm') ? shmget(key, 0, 0) : + semget(key, 0, 0)); + + 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: + errmsg = "unknown error in key"; + break; + } + bb_fprintf(stderr, "%s: %s (%s)\n", + prog, errmsg, optarg); + continue; + } + } 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"; + break; + case EIDRM: + errmsg = iskey + ? "already removed key" + : "already removed id"; + break; + default: + errmsg = iskey + ? "unknown error in key" + : "unknown error in id"; + break; + } + bb_fprintf(stderr, "%s: %s (%s)\n", + prog, errmsg, optarg); + continue; + } + } + + /* print usage if we still have some arguments left over */ + if (optind != argc) { + bb_show_usage(); + } + + /* exit value reflects the number of errors encountered */ + return error; +} |