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