~vcs-imports/busybox/trunk

« back to all changes in this revision

Viewing changes to util-linux/ipcrm.c

  • Committer: Eric Andersen
  • Date: 1999-11-24 09:04:33 UTC
  • Revision ID: git-v1:b99df0fd65abe3245fa2d04115326100847f865e
First draft

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 source tree.
9
 
 */
10
 
//config:config IPCRM
11
 
//config:       bool "ipcrm (3.5 kb)"
12
 
//config:       default y
13
 
//config:       help
14
 
//config:       The ipcrm utility allows the removal of System V interprocess
15
 
//config:       communication (IPC) objects and the associated data structures
16
 
//config:       from the system.
17
 
 
18
 
//applet:IF_IPCRM(APPLET_NOEXEC(ipcrm, ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP, ipcrm))
19
 
 
20
 
//kbuild:lib-$(CONFIG_IPCRM) += ipcrm.o
21
 
 
22
 
#include "libbb.h"
23
 
 
24
 
/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
25
 
/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
26
 
#include <sys/ipc.h>
27
 
#include <sys/shm.h>
28
 
#include <sys/msg.h>
29
 
#include <sys/sem.h>
30
 
 
31
 
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
32
 
/* union semun is defined by including <sys/sem.h> */
33
 
#else
34
 
/* according to X/OPEN we have to define it ourselves */
35
 
union semun {
36
 
        int val;
37
 
        struct semid_ds *buf;
38
 
        unsigned short *array;
39
 
        struct seminfo *__buf;
40
 
};
41
 
#endif
42
 
 
43
 
#define IPCRM_LEGACY 1
44
 
 
45
 
 
46
 
#if IPCRM_LEGACY
47
 
 
48
 
typedef enum type_id {
49
 
        SHM,
50
 
        SEM,
51
 
        MSG
52
 
} type_id;
53
 
 
54
 
static int remove_ids(type_id type, char **argv)
55
 
{
56
 
        unsigned long id;
57
 
        int nb_errors = 0;
58
 
        union semun arg;
59
 
 
60
 
        arg.val = 0;
61
 
 
62
 
        while (argv[0]) {
63
 
                id = bb_strtoul(argv[0], NULL, 10);
64
 
                if (errno || id > INT_MAX) {
65
 
                        bb_error_msg("invalid id: %s", argv[0]);
66
 
                        nb_errors++;
67
 
                } else {
68
 
                        int ret = 0;
69
 
                        if (type == SEM)
70
 
                                ret = semctl(id, 0, IPC_RMID, arg);
71
 
                        else if (type == MSG)
72
 
                                ret = msgctl(id, IPC_RMID, NULL);
73
 
                        else if (type ==  SHM)
74
 
                                ret = shmctl(id, IPC_RMID, NULL);
75
 
 
76
 
                        if (ret) {
77
 
                                bb_perror_msg("can't remove id %s", argv[0]);
78
 
                                nb_errors++;
79
 
                        }
80
 
                }
81
 
                argv++;
82
 
        }
83
 
 
84
 
        return nb_errors;
85
 
}
86
 
#endif /* IPCRM_LEGACY */
87
 
 
88
 
//usage:#define ipcrm_trivial_usage
89
 
//usage:       "[-MQS key] [-mqs id]"
90
 
//usage:#define ipcrm_full_usage "\n\n"
91
 
//usage:       "Upper-case options MQS remove an object by shmkey value.\n"
92
 
//usage:       "Lower-case options remove an object by shmid value.\n"
93
 
//usage:     "\n        -mM     Remove memory segment after last detach"
94
 
//usage:     "\n        -qQ     Remove message queue"
95
 
//usage:     "\n        -sS     Remove semaphore"
96
 
 
97
 
int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
98
 
int ipcrm_main(int argc, char **argv)
99
 
{
100
 
        int c;
101
 
        int error = 0;
102
 
 
103
 
        /* if the command is executed without parameters, do nothing */
104
 
        if (argc == 1)
105
 
                return 0;
106
 
#if IPCRM_LEGACY
107
 
        /* check to see if the command is being invoked in the old way if so
108
 
           then run the old code. Valid commands are msg, shm, sem. */
109
 
        {
110
 
                type_id what = 0; /* silence gcc */
111
 
                char w;
112
 
 
113
 
                w = argv[1][0];
114
 
                if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
115
 
                       || (argv[1][0] == 's'
116
 
                           && ((w = argv[1][1]) == 'h' || w == 'e')
117
 
                           && argv[1][2] == 'm')
118
 
                     ) && argv[1][3] == '\0'
119
 
                ) {
120
 
                        if (argc < 3)
121
 
                                bb_show_usage();
122
 
 
123
 
                        if (w == 'h')
124
 
                                what = SHM;
125
 
                        else if (w == 'm')
126
 
                                what = MSG;
127
 
                        else if (w == 'e')
128
 
                                what = SEM;
129
 
 
130
 
                        if (remove_ids(what, &argv[2]))
131
 
                                fflush_stdout_and_exit(EXIT_FAILURE);
132
 
                        puts("resource(s) deleted");
133
 
                        return 0;
134
 
                }
135
 
        }
136
 
#endif /* IPCRM_LEGACY */
137
 
 
138
 
        /* process new syntax to conform with SYSV ipcrm */
139
 
        while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) {
140
 
                int result;
141
 
                int id;
142
 
                int iskey;
143
 
                /* needed to delete semaphores */
144
 
                union semun arg;
145
 
 
146
 
                if (c == '?') /* option not in the string */
147
 
                        bb_show_usage();
148
 
 
149
 
                id = 0;
150
 
                arg.val = 0;
151
 
 
152
 
                iskey = !(c & 0x20); /* uppercase? */
153
 
                if (iskey) {
154
 
                        /* keys are in hex or decimal */
155
 
                        key_t key = xstrtoul(optarg, 0);
156
 
 
157
 
                        if (key == IPC_PRIVATE) {
158
 
                                error++;
159
 
                                bb_error_msg("illegal key (%s)", optarg);
160
 
                                continue;
161
 
                        }
162
 
 
163
 
                        c |= 0x20; /* lowercase. c is 'q', 'm' or 's' now */
164
 
                        /* convert key to id */
165
 
                        id = ((c == 'q') ? msgget(key, 0) :
166
 
                                (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
167
 
 
168
 
                        if (id < 0) {
169
 
                                const char *errmsg;
170
 
 
171
 
                                error++;
172
 
                                switch (errno) {
173
 
                                case EACCES:
174
 
                                        errmsg = "permission denied for";
175
 
                                        break;
176
 
                                case EIDRM:
177
 
                                        errmsg = "already removed";
178
 
                                        break;
179
 
                                case ENOENT:
180
 
                                        errmsg = "invalid";
181
 
                                        break;
182
 
                                default:
183
 
                                        errmsg = "unknown error in";
184
 
                                        break;
185
 
                                }
186
 
                                bb_error_msg("%s %s (%s)", errmsg, "key", optarg);
187
 
                                continue;
188
 
                        }
189
 
                } else {
190
 
                        /* ids are in decimal */
191
 
                        id = xatoul(optarg);
192
 
                }
193
 
 
194
 
                result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
195
 
                                (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
196
 
                                semctl(id, 0, IPC_RMID, arg));
197
 
 
198
 
                if (result) {
199
 
                        const char *errmsg;
200
 
                        const char *const what = iskey ? "key" : "id";
201
 
 
202
 
                        error++;
203
 
                        switch (errno) {
204
 
                        case EACCES:
205
 
                        case EPERM:
206
 
                                errmsg = "permission denied for";
207
 
                                break;
208
 
                        case EINVAL:
209
 
                                errmsg = "invalid";
210
 
                                break;
211
 
                        case EIDRM:
212
 
                                errmsg = "already removed";
213
 
                                break;
214
 
                        default:
215
 
                                errmsg = "unknown error in";
216
 
                                break;
217
 
                        }
218
 
                        bb_error_msg("%s %s (%s)", errmsg, what, optarg);
219
 
                        continue;
220
 
                }
221
 
        }
222
 
 
223
 
        /* print usage if we still have some arguments left over */
224
 
        if (optind != argc) {
225
 
                bb_show_usage();
226
 
        }
227
 
 
228
 
        /* exit value reflects the number of errors encountered */
229
 
        return error;
230
 
}