source: MondoRescue/branches/3.3/mindi-busybox/util-linux/ipcrm.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

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