]>
Commit | Line | Data |
---|---|---|
e5995acd | 1 | |
058e8154 SK |
2 | #include <inttypes.h> |
3 | ||
e5995acd | 4 | #include "c.h" |
b5504a3d | 5 | #include "nls.h" |
058e8154 | 6 | #include "xalloc.h" |
e5995acd SK |
7 | #include "path.h" |
8 | #include "pathnames.h" | |
9 | #include "ipcutils.h" | |
10 | ||
11 | #ifndef SEMVMX | |
12 | # define SEMVMX 32767 /* <= 32767 semaphore maximum value */ | |
13 | #endif | |
14 | #ifndef SHMMIN | |
15 | # define SHMMIN 1 /* min shared segment size in bytes */ | |
16 | #endif | |
17 | ||
18 | ||
19 | int ipc_msg_get_limits(struct ipc_limits *lim) | |
20 | { | |
21 | if (path_exist(_PATH_PROC_IPC_MSGMNI) && | |
22 | path_exist(_PATH_PROC_IPC_MSGMNB) && | |
23 | path_exist(_PATH_PROC_IPC_MSGMAX)) { | |
24 | ||
25 | lim->msgmni = path_read_s32(_PATH_PROC_IPC_MSGMNI); | |
26 | lim->msgmnb = path_read_s32(_PATH_PROC_IPC_MSGMNB); | |
27 | lim->msgmax = path_read_s32(_PATH_PROC_IPC_MSGMAX); | |
28 | } else { | |
29 | struct msginfo msginfo; | |
30 | ||
31 | if (msgctl(0, IPC_INFO, (struct msqid_ds *) &msginfo) < 0) | |
32 | return 1; | |
33 | lim->msgmni = msginfo.msgmni; | |
34 | lim->msgmnb = msginfo.msgmnb; | |
35 | lim->msgmax = msginfo.msgmax; | |
36 | } | |
37 | ||
38 | return 0; | |
39 | } | |
40 | ||
41 | int ipc_sem_get_limits(struct ipc_limits *lim) | |
42 | { | |
43 | FILE *f; | |
44 | int rc = 0; | |
45 | ||
46 | lim->semvmx = SEMVMX; | |
47 | ||
48 | f = path_fopen("r", 0, _PATH_PROC_IPC_SEM); | |
49 | if (f) { | |
50 | rc = fscanf(f, "%d\t%d\t%d\t%d", | |
51 | &lim->semmsl, &lim->semmns, &lim->semopm, &lim->semmni); | |
52 | fclose(f); | |
53 | ||
54 | } | |
55 | ||
56 | if (rc == 4) { | |
57 | struct seminfo seminfo; | |
58 | union semun arg = { .array = (ushort *) &seminfo }; | |
59 | ||
60 | if (semctl(0, 0, IPC_INFO, arg) < 0) | |
61 | return 1; | |
62 | lim->semmni = seminfo.semmni; | |
63 | lim->semmsl = seminfo.semmsl; | |
64 | lim->semmns = seminfo.semmns; | |
65 | lim->semopm = seminfo.semopm; | |
66 | } | |
67 | ||
68 | return 0; | |
69 | } | |
70 | ||
71 | int ipc_shm_get_limits(struct ipc_limits *lim) | |
72 | { | |
73 | lim->shmmin = SHMMIN; | |
74 | ||
75 | if (path_exist(_PATH_PROC_IPC_SHMALL) && | |
76 | path_exist(_PATH_PROC_IPC_SHMMAX) && | |
77 | path_exist(_PATH_PROC_IPC_SHMMNI)) { | |
78 | ||
79 | lim->shmall = path_read_u64(_PATH_PROC_IPC_SHMALL); | |
80 | lim->shmmax = path_read_u64(_PATH_PROC_IPC_SHMMAX); | |
81 | lim->shmmni = path_read_u64(_PATH_PROC_IPC_SHMMNI); | |
82 | ||
83 | } else { | |
84 | struct shminfo shminfo; | |
85 | ||
86 | if (shmctl(0, IPC_INFO, (struct shmid_ds *) &shminfo) < 0) | |
87 | return 1; | |
88 | lim->shmmni = shminfo.shmmni; | |
89 | lim->shmall = shminfo.shmall; | |
90 | } | |
91 | ||
92 | return 0; | |
93 | } | |
058e8154 | 94 | |
61e14b4a | 95 | int ipc_shm_get_info(int id, struct shm_data **shmds) |
058e8154 SK |
96 | { |
97 | FILE *f; | |
61e14b4a | 98 | int i, maxid; |
058e8154 | 99 | struct shm_data *p; |
61e14b4a | 100 | struct shm_info dummy; |
058e8154 | 101 | |
7d94d1ce | 102 | p = *shmds = xcalloc(1, sizeof(struct shm_data)); |
058e8154 SK |
103 | p->next = NULL; |
104 | ||
105 | f = path_fopen("r", 0, _PATH_PROC_SYSV_SHM); | |
106 | if (!f) | |
107 | goto fallback; | |
108 | ||
109 | while (fgetc(f) != '\n'); /* skip header */ | |
110 | ||
7d94d1ce | 111 | while (feof(f) == 0) { |
058e8154 SK |
112 | if (fscanf(f, |
113 | "%d %d %o %"SCNu64 " %u %u " | |
114 | "%"SCNu64 " %u %u %u %u %"SCNu64 " %"SCNu64 " %"SCNu64 | |
115 | " %"SCNu64 " %"SCNu64 "\n", | |
116 | &p->shm_perm.key, | |
117 | &p->shm_perm.id, | |
118 | &p->shm_perm.mode, | |
119 | &p->shm_segsz, | |
120 | &p->shm_cprid, | |
121 | &p->shm_lprid, | |
122 | &p->shm_nattch, | |
123 | &p->shm_perm.uid, | |
124 | &p->shm_perm.gid, | |
125 | &p->shm_perm.cuid, | |
126 | &p->shm_perm.cgid, | |
127 | &p->shm_atim, | |
128 | &p->shm_dtim, | |
129 | &p->shm_ctim, | |
130 | &p->shm_rss, | |
131 | &p->shm_swp) != 16) | |
132 | continue; | |
133 | ||
7d94d1ce KZ |
134 | if (id > -1) { |
135 | /* ID specified */ | |
136 | if (id == p->shm_perm.id) { | |
137 | i = 1; | |
138 | break; | |
139 | } else | |
140 | continue; | |
058e8154 | 141 | } |
7d94d1ce KZ |
142 | |
143 | p->next = xcalloc(1, sizeof(struct shm_data)); | |
144 | p = p->next; | |
145 | p->next = NULL; | |
146 | i++; | |
058e8154 SK |
147 | } |
148 | ||
149 | if (i == 0) | |
150 | free(*shmds); | |
151 | fclose(f); | |
152 | return i; | |
153 | ||
154 | /* Fallback; /proc or /sys file(s) missing. */ | |
155 | fallback: | |
156 | i = id < 0 ? 0 : id; | |
157 | ||
61e14b4a KZ |
158 | maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) &dummy); |
159 | if (maxid < 0) | |
160 | return 0; | |
161 | ||
058e8154 SK |
162 | while (i <= maxid) { |
163 | int shmid; | |
164 | struct shmid_ds shmseg; | |
165 | struct ipc_perm *ipcp = &shmseg.shm_perm; | |
166 | ||
167 | shmid = shmctl(i, SHM_STAT, &shmseg); | |
168 | if (shmid < 0) { | |
169 | if (-1 < id) { | |
170 | free(*shmds); | |
171 | return 0; | |
172 | } | |
173 | i++; | |
174 | continue; | |
175 | } | |
176 | ||
177 | p->shm_perm.key = ipcp->KEY; | |
178 | p->shm_perm.id = shmid; | |
179 | p->shm_perm.mode = ipcp->mode; | |
180 | p->shm_segsz = shmseg.shm_segsz; | |
181 | p->shm_cprid = shmseg.shm_cpid; | |
182 | p->shm_lprid = shmseg.shm_lpid; | |
183 | p->shm_nattch = shmseg.shm_nattch; | |
184 | p->shm_perm.uid = ipcp->uid; | |
185 | p->shm_perm.gid = ipcp->gid; | |
186 | p->shm_perm.cuid = ipcp->cuid; | |
187 | p->shm_perm.cgid = ipcp->cuid; | |
188 | p->shm_atim = shmseg.shm_atime; | |
189 | p->shm_dtim = shmseg.shm_dtime; | |
190 | p->shm_ctim = shmseg.shm_ctime; | |
191 | p->shm_rss = 0xdead; | |
192 | p->shm_swp = 0xdead; | |
193 | ||
194 | if (id < 0) { | |
7d94d1ce | 195 | p->next = xcalloc(1, sizeof(struct shm_data)); |
058e8154 SK |
196 | p = p->next; |
197 | p->next = NULL; | |
198 | i++; | |
199 | } else | |
200 | return 1; | |
201 | } | |
202 | ||
203 | return i; | |
204 | } | |
205 | ||
206 | void ipc_shm_free_info(struct shm_data *shmds) | |
207 | { | |
208 | while (shmds) { | |
209 | struct shm_data *next = shmds->next; | |
210 | free(shmds); | |
211 | shmds = next; | |
212 | } | |
213 | } | |
214 | ||
b5504a3d SK |
215 | static void get_sem_elements(struct sem_data *p) |
216 | { | |
217 | size_t i; | |
218 | ||
219 | if (!p || !p->sem_nsems || p->sem_perm.id < 0) | |
220 | return; | |
221 | ||
222 | p->elements = xcalloc(p->sem_nsems, sizeof(struct sem_elem)); | |
223 | ||
224 | for (i = 0; i < p->sem_nsems; i++) { | |
225 | struct sem_elem *e = &p->elements[i]; | |
226 | union semun arg = { .val = 0 }; | |
227 | ||
228 | e->semval = semctl(p->sem_perm.id, i, GETVAL, arg); | |
229 | if (e->semval < 0) | |
230 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETVAL)"); | |
231 | ||
232 | e->ncount = semctl(p->sem_perm.id, i, GETNCNT, arg); | |
233 | if (e->ncount < 0) | |
234 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETNCNT)"); | |
235 | ||
236 | e->zcount = semctl(p->sem_perm.id, i, GETZCNT, arg); | |
237 | if (e->zcount < 0) | |
238 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETZCNT)"); | |
239 | ||
240 | e->pid = semctl(p->sem_perm.id, i, GETPID, arg); | |
241 | if (e->pid < 0) | |
242 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETPID)"); | |
243 | } | |
244 | } | |
245 | ||
1e2418a2 SK |
246 | int ipc_sem_get_info(int id, struct sem_data **semds) |
247 | { | |
248 | FILE *f; | |
249 | int i, maxid; | |
250 | struct sem_data *p; | |
251 | struct seminfo dummy; | |
252 | union semun arg; | |
253 | ||
254 | p = *semds = xcalloc(1, sizeof(struct sem_data)); | |
255 | p->next = NULL; | |
256 | ||
257 | f = path_fopen("r", 0, _PATH_PROC_SYSV_SEM); | |
258 | if (!f) | |
259 | goto sem_fallback; | |
260 | ||
261 | while (fgetc(f) != '\n') ; /* skip header */ | |
262 | ||
263 | while (feof(f) == 0) { | |
264 | if (fscanf(f, | |
265 | "%d %d %o %" SCNu64 " %u %u %u %u %" SCNu64 " %" SCNu64 "\n", | |
266 | &p->sem_perm.key, | |
267 | &p->sem_perm.id, | |
268 | &p->sem_perm.mode, | |
269 | &p->sem_nsems, | |
270 | &p->sem_perm.uid, | |
271 | &p->sem_perm.gid, | |
272 | &p->sem_perm.cuid, | |
273 | &p->sem_perm.cgid, | |
274 | &p->sem_otime, | |
275 | &p->sem_ctime) != 10) | |
276 | continue; | |
277 | ||
278 | if (id > -1) { | |
279 | /* ID specified */ | |
280 | if (id == p->sem_perm.id) { | |
b5504a3d | 281 | get_sem_elements(p); |
1e2418a2 SK |
282 | i = 1; |
283 | break; | |
284 | } else | |
285 | continue; | |
286 | } | |
287 | ||
288 | p->next = xcalloc(1, sizeof(struct sem_data)); | |
289 | p = p->next; | |
290 | p->next = NULL; | |
291 | i++; | |
292 | } | |
293 | ||
294 | if (i == 0) | |
295 | free(*semds); | |
296 | fclose(f); | |
297 | return i; | |
298 | ||
299 | /* Fallback; /proc or /sys file(s) missing. */ | |
300 | sem_fallback: | |
301 | i = id < 0 ? 0 : id; | |
302 | ||
303 | arg.array = (ushort *) (void *)&dummy; | |
304 | maxid = semctl(0, 0, SEM_INFO, arg); | |
305 | if (maxid < 0) | |
306 | return 0; | |
307 | ||
308 | while (i <= maxid) { | |
309 | int semid; | |
310 | struct semid_ds semseg; | |
311 | struct ipc_perm *ipcp = &semseg.sem_perm; | |
312 | arg.buf = (struct semid_ds *)&semseg; | |
313 | ||
314 | semid = semctl(i, 0, SEM_STAT, arg); | |
315 | if (semid < 0) { | |
316 | if (-1 < id) { | |
317 | free(*semds); | |
318 | return 0; | |
319 | } | |
320 | i++; | |
321 | continue; | |
322 | } | |
323 | ||
324 | p->sem_perm.key = ipcp->KEY; | |
325 | p->sem_perm.id = semid; | |
326 | p->sem_perm.mode = ipcp->mode; | |
327 | p->sem_nsems = semseg.sem_nsems; | |
328 | p->sem_perm.uid = ipcp->uid; | |
329 | p->sem_perm.gid = ipcp->gid; | |
330 | p->sem_perm.cuid = ipcp->cuid; | |
331 | p->sem_perm.cgid = ipcp->cuid; | |
332 | p->sem_otime = semseg.sem_otime; | |
333 | p->sem_ctime = semseg.sem_ctime; | |
334 | ||
335 | if (id < 0) { | |
336 | p->next = xcalloc(1, sizeof(struct sem_data)); | |
337 | p = p->next; | |
338 | p->next = NULL; | |
339 | i++; | |
b5504a3d SK |
340 | } else { |
341 | get_sem_elements(p); | |
1e2418a2 | 342 | return 1; |
b5504a3d | 343 | } |
1e2418a2 SK |
344 | } |
345 | ||
346 | return i; | |
347 | } | |
348 | ||
349 | void ipc_sem_free_info(struct sem_data *semds) | |
350 | { | |
351 | while (semds) { | |
352 | struct sem_data *next = semds->next; | |
b5504a3d | 353 | free(semds->elements); |
1e2418a2 SK |
354 | free(semds); |
355 | semds = next; | |
356 | } | |
357 | } | |
358 | ||
35118dfc SK |
359 | int ipc_msg_get_info(int id, struct msg_data **msgds) |
360 | { | |
361 | FILE *f; | |
362 | int i, maxid; | |
363 | struct msg_data *p; | |
364 | struct msqid_ds dummy; | |
2bd2f79d | 365 | struct msqid_ds msgseg; |
35118dfc SK |
366 | |
367 | p = *msgds = xcalloc(1, sizeof(struct msg_data)); | |
368 | p->next = NULL; | |
369 | ||
370 | f = path_fopen("r", 0, _PATH_PROC_SYSV_MSG); | |
371 | if (!f) | |
372 | goto msg_fallback; | |
373 | ||
374 | while (fgetc(f) != '\n') ; /* skip header */ | |
375 | ||
376 | while (feof(f) == 0) { | |
377 | if (fscanf(f, | |
378 | "%d %d %o %" SCNu64 " %" SCNu64 " %u %u %u %u %u %u %" SCNu64 " %" SCNu64 " %" SCNu64 "\n", | |
379 | &p->msg_perm.key, | |
380 | &p->msg_perm.id, | |
381 | &p->msg_perm.mode, | |
382 | &p->q_cbytes, | |
383 | &p->q_qnum, | |
384 | &p->q_lspid, | |
385 | &p->q_lrpid, | |
386 | &p->msg_perm.uid, | |
387 | &p->msg_perm.gid, | |
388 | &p->msg_perm.cuid, | |
389 | &p->msg_perm.cgid, | |
390 | &p->q_stime, | |
391 | &p->q_rtime, | |
392 | &p->q_ctime) != 14) | |
393 | continue; | |
394 | ||
395 | if (id > -1) { | |
396 | /* ID specified */ | |
397 | if (id == p->msg_perm.id) { | |
2bd2f79d SK |
398 | /* |
399 | * FIXME: q_qbytes are not in /proc | |
400 | * | |
401 | */ | |
402 | if (msgctl(id, IPC_STAT, &msgseg) != -1) | |
403 | p->q_qbytes = msgseg.msg_qbytes; | |
35118dfc SK |
404 | i = 1; |
405 | break; | |
406 | } else | |
407 | continue; | |
408 | } | |
409 | ||
410 | p->next = xcalloc(1, sizeof(struct msg_data)); | |
411 | p = p->next; | |
412 | p->next = NULL; | |
413 | i++; | |
414 | } | |
415 | ||
416 | if (i == 0) | |
417 | free(*msgds); | |
418 | fclose(f); | |
419 | return i; | |
420 | ||
421 | /* Fallback; /proc or /sys file(s) missing. */ | |
422 | msg_fallback: | |
423 | i = id < 0 ? 0 : id; | |
424 | ||
425 | maxid = msgctl(id, MSG_STAT, &dummy); | |
426 | if (maxid < 0) | |
427 | return 0; | |
428 | ||
429 | while (i <= maxid) { | |
430 | int msgid; | |
35118dfc SK |
431 | struct ipc_perm *ipcp = &msgseg.msg_perm; |
432 | ||
2bd2f79d | 433 | msgid = msgctl(i, MSG_STAT, &msgseg); |
35118dfc SK |
434 | if (msgid < 0) { |
435 | if (-1 < id) { | |
436 | free(*msgds); | |
437 | return 0; | |
438 | } | |
439 | i++; | |
440 | continue; | |
441 | } | |
442 | ||
443 | p->msg_perm.key = ipcp->KEY; | |
444 | p->msg_perm.id = msgid; | |
445 | p->msg_perm.mode = ipcp->mode; | |
446 | p->q_cbytes = msgseg.msg_cbytes; | |
447 | p->q_qnum = msgseg.msg_qnum; | |
448 | p->q_lspid = msgseg.msg_lspid; | |
449 | p->q_lrpid = msgseg.msg_lrpid; | |
450 | p->msg_perm.uid = ipcp->uid; | |
451 | p->msg_perm.gid = ipcp->gid; | |
452 | p->msg_perm.cuid = ipcp->cuid; | |
453 | p->msg_perm.cgid = ipcp->cgid; | |
454 | p->q_stime = msgseg.msg_stime; | |
455 | p->q_rtime = msgseg.msg_rtime; | |
456 | p->q_ctime = msgseg.msg_ctime; | |
2bd2f79d | 457 | p->q_qbytes = msgseg.msg_qbytes; |
35118dfc SK |
458 | |
459 | if (id < 0) { | |
460 | p->next = xcalloc(1, sizeof(struct msg_data)); | |
461 | p = p->next; | |
462 | p->next = NULL; | |
463 | i++; | |
464 | } else | |
465 | return 1; | |
466 | } | |
467 | ||
468 | return i; | |
469 | } | |
470 | ||
471 | void ipc_msg_free_info(struct msg_data *msgds) | |
472 | { | |
473 | while (msgds) { | |
474 | struct msg_data *next = msgds->next; | |
475 | free(msgds); | |
476 | msgds = next; | |
477 | } | |
478 | } | |
479 | ||
058e8154 SK |
480 | void ipc_print_perms(FILE *f, struct ipc_stat *is) |
481 | { | |
482 | struct passwd *pw; | |
483 | struct group *gr; | |
484 | ||
485 | fprintf(f, "%-10d %-10o", is->id, is->mode & 0777); | |
486 | ||
487 | if ((pw = getpwuid(is->cuid))) | |
488 | fprintf(f, " %-10s", pw->pw_name); | |
489 | else | |
490 | fprintf(f, " %-10u", is->cuid); | |
491 | ||
492 | if ((gr = getgrgid(is->cgid))) | |
493 | fprintf(f, " %-10s", gr->gr_name); | |
494 | else | |
495 | fprintf(f, " %-10u", is->cgid); | |
496 | ||
497 | if ((pw = getpwuid(is->uid))) | |
498 | fprintf(f, " %-10s", pw->pw_name); | |
499 | else | |
500 | fprintf(f, " %-10u", is->uid); | |
501 | ||
502 | if ((gr = getgrgid(is->gid))) | |
503 | fprintf(f, " %-10s\n", gr->gr_name); | |
504 | else | |
505 | fprintf(f, " %-10u\n", is->gid); | |
506 | } |