1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "libbb.h"
23
24
25
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
33#else
34
35union 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
48typedef enum type_id {
49 SHM,
50 SEM,
51 MSG
52} type_id;
53
54static 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
87
88
89
90
91
92
93
94
95
96
97int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
98int ipcrm_main(int argc, char **argv)
99{
100 int c;
101 int error = 0;
102
103
104 if (argc == 1)
105 return 0;
106#if IPCRM_LEGACY
107
108
109 {
110 type_id what = 0;
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
137
138
139 while ((c = getopt(argc, argv, "q:m:s:Q:M:S:")) != -1) {
140 int result;
141 int id;
142 int iskey;
143
144 union semun arg;
145
146 if (c == '?')
147 bb_show_usage();
148
149 id = 0;
150 arg.val = 0;
151
152 iskey = !(c & 0x20);
153 if (iskey) {
154
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;
164
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
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
224 if (optind != argc) {
225 bb_show_usage();
226 }
227
228
229 return error;
230}
231