1 | /*
|
---|
2 | * ipcrm.c -- utility to allow removal of IPC objects and data structures.
|
---|
3 | *
|
---|
4 | * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
|
---|
5 | * Adapted for busybox from util-linux-2.12a.
|
---|
6 | *
|
---|
7 | * This program is free software; you can redistribute it and/or modify
|
---|
8 | * it under the terms of the GNU General Public License as published by
|
---|
9 | * the Free Software Foundation; either version 2 of the License, or
|
---|
10 | * (at your option) any later version.
|
---|
11 | *
|
---|
12 | * This program is distributed in the hope that it will be useful,
|
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
15 | * General Public License for more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU General Public License
|
---|
18 | * along with this program; if not, write to the Free Software
|
---|
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
---|
20 | *
|
---|
21 | * --- Pre-busybox history from util-linux-2.12a ------------------------
|
---|
22 | *
|
---|
23 | * 1999-04-02 frank zago
|
---|
24 | * - can now remove several id's in the same call
|
---|
25 | *
|
---|
26 | * 1999-02-22 Arkadiusz Miÿkiewicz <misiek@pld.ORG.PL>
|
---|
27 | * - added Native Language Support
|
---|
28 | *
|
---|
29 | * Original author - krishna balasubramanian 1993
|
---|
30 | */
|
---|
31 |
|
---|
32 | #include <stdio.h>
|
---|
33 | #include <stdlib.h>
|
---|
34 | #include <string.h>
|
---|
35 | #include <errno.h>
|
---|
36 |
|
---|
37 | #include <sys/types.h>
|
---|
38 | #include <sys/ipc.h>
|
---|
39 | #include <sys/shm.h>
|
---|
40 | #include <sys/msg.h>
|
---|
41 | #include <sys/sem.h>
|
---|
42 |
|
---|
43 | /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
|
---|
44 | /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
|
---|
45 | /* for getopt */
|
---|
46 | #include <unistd.h>
|
---|
47 |
|
---|
48 | /* for tolower and isupper */
|
---|
49 | #include <ctype.h>
|
---|
50 |
|
---|
51 | #include "busybox.h"
|
---|
52 |
|
---|
53 | #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
|
---|
54 | /* union semun is defined by including <sys/sem.h> */
|
---|
55 | #else
|
---|
56 | /* according to X/OPEN we have to define it ourselves */
|
---|
57 | union semun {
|
---|
58 | int val;
|
---|
59 | struct semid_ds *buf;
|
---|
60 | unsigned short int *array;
|
---|
61 | struct seminfo *__buf;
|
---|
62 | };
|
---|
63 | #endif
|
---|
64 |
|
---|
65 | typedef enum type_id {
|
---|
66 | SHM,
|
---|
67 | SEM,
|
---|
68 | MSG
|
---|
69 | } type_id;
|
---|
70 |
|
---|
71 | static int
|
---|
72 | remove_ids(type_id type, int argc, char **argv) {
|
---|
73 | int id;
|
---|
74 | int ret = 0; /* for gcc */
|
---|
75 | char *end;
|
---|
76 | int nb_errors = 0;
|
---|
77 | union semun arg;
|
---|
78 |
|
---|
79 | arg.val = 0;
|
---|
80 |
|
---|
81 | while(argc) {
|
---|
82 |
|
---|
83 | id = strtoul(argv[0], &end, 10);
|
---|
84 |
|
---|
85 | if (*end != 0) {
|
---|
86 | bb_printf ("invalid id: %s\n", argv[0]);
|
---|
87 | nb_errors ++;
|
---|
88 | } else {
|
---|
89 | switch(type) {
|
---|
90 | case SEM:
|
---|
91 | ret = semctl (id, 0, IPC_RMID, arg);
|
---|
92 | break;
|
---|
93 |
|
---|
94 | case MSG:
|
---|
95 | ret = msgctl (id, IPC_RMID, NULL);
|
---|
96 | break;
|
---|
97 |
|
---|
98 | case SHM:
|
---|
99 | ret = shmctl (id, IPC_RMID, NULL);
|
---|
100 | break;
|
---|
101 | }
|
---|
102 |
|
---|
103 | if (ret) {
|
---|
104 | bb_printf ("cannot remove id %s (%s)\n",
|
---|
105 | argv[0], strerror(errno));
|
---|
106 | nb_errors ++;
|
---|
107 | }
|
---|
108 | }
|
---|
109 | argc--;
|
---|
110 | argv++;
|
---|
111 | }
|
---|
112 |
|
---|
113 | return(nb_errors);
|
---|
114 | }
|
---|
115 |
|
---|
116 | static int deprecated_main(int argc, char **argv)
|
---|
117 | {
|
---|
118 | if (argc < 3) {
|
---|
119 | bb_show_usage();
|
---|
120 | bb_fflush_stdout_and_exit(1);
|
---|
121 | }
|
---|
122 |
|
---|
123 | if (!strcmp(argv[1], "shm")) {
|
---|
124 | if (remove_ids(SHM, argc-2, &argv[2]))
|
---|
125 | bb_fflush_stdout_and_exit(1);
|
---|
126 | }
|
---|
127 | else if (!strcmp(argv[1], "msg")) {
|
---|
128 | if (remove_ids(MSG, argc-2, &argv[2]))
|
---|
129 | bb_fflush_stdout_and_exit(1);
|
---|
130 | }
|
---|
131 | else if (!strcmp(argv[1], "sem")) {
|
---|
132 | if (remove_ids(SEM, argc-2, &argv[2]))
|
---|
133 | bb_fflush_stdout_and_exit(1);
|
---|
134 | }
|
---|
135 | else {
|
---|
136 | bb_printf ("unknown resource type: %s\n", argv[1]);
|
---|
137 | bb_show_usage();
|
---|
138 | bb_fflush_stdout_and_exit(1);
|
---|
139 | }
|
---|
140 |
|
---|
141 | bb_printf ("resource(s) deleted\n");
|
---|
142 | return 0;
|
---|
143 | }
|
---|
144 |
|
---|
145 |
|
---|
146 | int ipcrm_main(int argc, char **argv)
|
---|
147 | {
|
---|
148 | int c;
|
---|
149 | int error = 0;
|
---|
150 | char *prog = argv[0];
|
---|
151 |
|
---|
152 | /* if the command is executed without parameters, do nothing */
|
---|
153 | if (argc == 1)
|
---|
154 | return 0;
|
---|
155 |
|
---|
156 | /* check to see if the command is being invoked in the old way if so
|
---|
157 | then run the old code */
|
---|
158 | if (strcmp(argv[1], "shm") == 0 ||
|
---|
159 | strcmp(argv[1], "msg") == 0 ||
|
---|
160 | strcmp(argv[1], "sem") == 0)
|
---|
161 | return deprecated_main(argc, argv);
|
---|
162 |
|
---|
163 | /* process new syntax to conform with SYSV ipcrm */
|
---|
164 | while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) {
|
---|
165 | int result;
|
---|
166 | int id = 0;
|
---|
167 | int iskey = isupper(c);
|
---|
168 |
|
---|
169 | /* needed to delete semaphores */
|
---|
170 | union semun arg;
|
---|
171 | arg.val = 0;
|
---|
172 |
|
---|
173 | if ((c == '?') || (c == 'h'))
|
---|
174 | {
|
---|
175 | bb_show_usage();
|
---|
176 | return 0;
|
---|
177 | }
|
---|
178 |
|
---|
179 | /* we don't need case information any more */
|
---|
180 | c = tolower(c);
|
---|
181 |
|
---|
182 | /* make sure the option is in range */
|
---|
183 | if (c != 'q' && c != 'm' && c != 's') {
|
---|
184 | bb_show_usage();
|
---|
185 | error++;
|
---|
186 | return error;
|
---|
187 | }
|
---|
188 |
|
---|
189 | if (iskey) {
|
---|
190 | /* keys are in hex or decimal */
|
---|
191 | key_t key = strtoul(optarg, NULL, 0);
|
---|
192 | if (key == IPC_PRIVATE) {
|
---|
193 | error++;
|
---|
194 | bb_fprintf(stderr, "%s: illegal key (%s)\n",
|
---|
195 | prog, optarg);
|
---|
196 | continue;
|
---|
197 | }
|
---|
198 |
|
---|
199 | /* convert key to id */
|
---|
200 | id = ((c == 'q') ? msgget(key, 0) :
|
---|
201 | (c == 'm') ? shmget(key, 0, 0) :
|
---|
202 | semget(key, 0, 0));
|
---|
203 |
|
---|
204 | if (id < 0) {
|
---|
205 | char *errmsg;
|
---|
206 | error++;
|
---|
207 | switch(errno) {
|
---|
208 | case EACCES:
|
---|
209 | errmsg = "permission denied for key";
|
---|
210 | break;
|
---|
211 | case EIDRM:
|
---|
212 | errmsg = "already removed key";
|
---|
213 | break;
|
---|
214 | case ENOENT:
|
---|
215 | errmsg = "invalid key";
|
---|
216 | break;
|
---|
217 | default:
|
---|
218 | errmsg = "unknown error in key";
|
---|
219 | break;
|
---|
220 | }
|
---|
221 | bb_fprintf(stderr, "%s: %s (%s)\n",
|
---|
222 | prog, errmsg, optarg);
|
---|
223 | continue;
|
---|
224 | }
|
---|
225 | } else {
|
---|
226 | /* ids are in decimal */
|
---|
227 | id = strtoul(optarg, NULL, 10);
|
---|
228 | }
|
---|
229 |
|
---|
230 | result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
|
---|
231 | (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
|
---|
232 | semctl(id, 0, IPC_RMID, arg));
|
---|
233 |
|
---|
234 | if (result < 0) {
|
---|
235 | char *errmsg;
|
---|
236 | error++;
|
---|
237 | switch(errno) {
|
---|
238 | case EACCES:
|
---|
239 | case EPERM:
|
---|
240 | errmsg = iskey
|
---|
241 | ? "permission denied for key"
|
---|
242 | : "permission denied for id";
|
---|
243 | break;
|
---|
244 | case EINVAL:
|
---|
245 | errmsg = iskey
|
---|
246 | ? "invalid key"
|
---|
247 | : "invalid id";
|
---|
248 | break;
|
---|
249 | case EIDRM:
|
---|
250 | errmsg = iskey
|
---|
251 | ? "already removed key"
|
---|
252 | : "already removed id";
|
---|
253 | break;
|
---|
254 | default:
|
---|
255 | errmsg = iskey
|
---|
256 | ? "unknown error in key"
|
---|
257 | : "unknown error in id";
|
---|
258 | break;
|
---|
259 | }
|
---|
260 | bb_fprintf(stderr, "%s: %s (%s)\n",
|
---|
261 | prog, errmsg, optarg);
|
---|
262 | continue;
|
---|
263 | }
|
---|
264 | }
|
---|
265 |
|
---|
266 | /* print usage if we still have some arguments left over */
|
---|
267 | if (optind != argc) {
|
---|
268 | bb_show_usage();
|
---|
269 | }
|
---|
270 |
|
---|
271 | /* exit value reflects the number of errors encountered */
|
---|
272 | return error;
|
---|
273 | }
|
---|