busybox/util-linux/ipcrm.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * ipcrm.c - utility to allow removal of IPC objects and data structures.
   4 *
   5 * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
   6 * Adapted for busybox from util-linux-2.12a.
   7 *
   8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
   9 */
  10
  11#include "libbb.h"
  12
  13/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
  14/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
  15#include <sys/ipc.h>
  16#include <sys/shm.h>
  17#include <sys/msg.h>
  18#include <sys/sem.h>
  19
  20#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
  21/* union semun is defined by including <sys/sem.h> */
  22#else
  23/* according to X/OPEN we have to define it ourselves */
  24union semun {
  25        int val;
  26        struct semid_ds *buf;
  27        unsigned short *array;
  28        struct seminfo *__buf;
  29};
  30#endif
  31
  32#define IPCRM_LEGACY 1
  33
  34
  35#if IPCRM_LEGACY
  36
  37typedef enum type_id {
  38        SHM,
  39        SEM,
  40        MSG
  41} type_id;
  42
  43static int remove_ids(type_id type, int argc, char **argv)
  44{
  45        unsigned long id;
  46        int ret = 0;            /* silence gcc */
  47        int nb_errors = 0;
  48        union semun arg;
  49
  50        arg.val = 0;
  51
  52        while (argc) {
  53                id = bb_strtoul(argv[0], NULL, 10);
  54                if (errno || id > INT_MAX) {
  55                        bb_error_msg("invalid id: %s", argv[0]);
  56                        nb_errors++;
  57                } else {
  58                        if (type == SEM)
  59                                ret = semctl(id, 0, IPC_RMID, arg);
  60                        else if (type == MSG)
  61                                ret = msgctl(id, IPC_RMID, NULL);
  62                        else if (type ==  SHM)
  63                                ret = shmctl(id, IPC_RMID, NULL);
  64
  65                        if (ret) {
  66                                bb_perror_msg("can't remove id %s", argv[0]);
  67                                nb_errors++;
  68                        }
  69                }
  70                argc--;
  71                argv++;
  72        }
  73
  74        return nb_errors;
  75}
  76#endif /* IPCRM_LEGACY */
  77
  78
  79int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  80int ipcrm_main(int argc, char **argv)
  81{
  82        int c;
  83        int error = 0;
  84
  85        /* if the command is executed without parameters, do nothing */
  86        if (argc == 1)
  87                return 0;
  88#if IPCRM_LEGACY
  89        /* check to see if the command is being invoked in the old way if so
  90           then run the old code. Valid commands are msg, shm, sem. */
  91        {
  92                type_id what = 0; /* silence gcc */
  93                char w;
  94
  95                w=argv[1][0];
  96                if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
  97                       || (argv[1][0] == 's'
  98                           && ((w=argv[1][1]) == 'h' || w == 'e')
  99                           && argv[1][2] == 'm')
 100                     ) && argv[1][3] == '\0'
 101                ) {
 102
 103                        if (argc < 3)
 104                                bb_show_usage();
 105
 106                        if (w == 'h')
 107                                what = SHM;
 108                        else if (w == 'm')
 109                                what = MSG;
 110                        else if (w == 'e')
 111                                what = SEM;
 112
 113                        if (remove_ids(what, argc-2, &argv[2]))
 114                                fflush_stdout_and_exit(EXIT_FAILURE);
 115                        printf("resource(s) deleted\n");
 116                        return 0;
 117                }
 118        }
 119#endif /* IPCRM_LEGACY */
 120
 121        /* process new syntax to conform with SYSV ipcrm */
 122        while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) {
 123                int result;
 124                int id = 0;
 125                int iskey = isupper(c);
 126
 127                /* needed to delete semaphores */
 128                union semun arg;
 129
 130                arg.val = 0;
 131
 132                if ((c == '?') || (c == 'h')) {
 133                        bb_show_usage();
 134                }
 135
 136                /* we don't need case information any more */
 137                c = tolower(c);
 138
 139                /* make sure the option is in range: allowed are q, m, s */
 140                if (c != 'q' && c != 'm' && c != 's') {
 141                        bb_show_usage();
 142                }
 143
 144                if (iskey) {
 145                        /* keys are in hex or decimal */
 146                        key_t key = xstrtoul(optarg, 0);
 147
 148                        if (key == IPC_PRIVATE) {
 149                                error++;
 150                                bb_error_msg("illegal key (%s)", optarg);
 151                                continue;
 152                        }
 153
 154                        /* convert key to id */
 155                        id = ((c == 'q') ? msgget(key, 0) :
 156                                  (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
 157
 158                        if (id < 0) {
 159                                const char *errmsg;
 160
 161                                error++;
 162                                switch (errno) {
 163                                case EACCES:
 164                                        errmsg = "permission denied for";
 165                                        break;
 166                                case EIDRM:
 167                                        errmsg = "already removed";
 168                                        break;
 169                                case ENOENT:
 170                                        errmsg = "invalid";
 171                                        break;
 172                                default:
 173                                        errmsg = "unknown error in";
 174                                        break;
 175                                }
 176                                bb_error_msg("%s %s (%s)", errmsg, "key", optarg);
 177                                continue;
 178                        }
 179                } else {
 180                        /* ids are in decimal */
 181                        id = xatoul(optarg);
 182                }
 183
 184                result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
 185                                  (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
 186                                  semctl(id, 0, IPC_RMID, arg));
 187
 188                if (result) {
 189                        const char *errmsg;
 190                        const char *const what = iskey ? "key" : "id";
 191
 192                        error++;
 193                        switch (errno) {
 194                        case EACCES:
 195                        case EPERM:
 196                                errmsg = "permission denied for";
 197                                break;
 198                        case EINVAL:
 199                                errmsg = "invalid";
 200                                break;
 201                        case EIDRM:
 202                                errmsg = "already removed";
 203                                break;
 204                        default:
 205                                errmsg = "unknown error in";
 206                                break;
 207                        }
 208                        bb_error_msg("%s %s (%s)", errmsg, what, optarg);
 209                        continue;
 210                }
 211        }
 212
 213        /* print usage if we still have some arguments left over */
 214        if (optind != argc) {
 215                bb_show_usage();
 216        }
 217
 218        /* exit value reflects the number of errors encountered */
 219        return error;
 220}
 221