]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/ipcutils.c
ipcs: fix shmctl() usage
[thirdparty/util-linux.git] / sys-utils / ipcutils.c
CommitLineData
058e8154
SK
1#include <inttypes.h>
2
e5995acd 3#include "c.h"
b5504a3d 4#include "nls.h"
058e8154 5#include "xalloc.h"
e5995acd
SK
6#include "path.h"
7#include "pathnames.h"
8#include "ipcutils.h"
56692a67 9#include "strutils.h"
e5995acd
SK
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
19int 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
41int 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
71int 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 {
929c2575
KZ
84 struct shminfo *shminfo;
85 struct shmid_ds shmbuf;
e5995acd 86
929c2575 87 if (shmctl(0, IPC_INFO, &shmbuf) < 0)
e5995acd 88 return 1;
929c2575
KZ
89 shminfo = (struct shminfo *) &shmbuf;
90 lim->shmmni = shminfo->shmmni;
91 lim->shmall = shminfo->shmall;
92 lim->shmmax = shminfo->shmmax;
e5995acd
SK
93 }
94
95 return 0;
96}
058e8154 97
61e14b4a 98int ipc_shm_get_info(int id, struct shm_data **shmds)
058e8154
SK
99{
100 FILE *f;
7d8ea9df 101 int i = 0, maxid;
058e8154 102 struct shm_data *p;
3ce29d6d 103 struct shmid_ds dummy;
058e8154 104
7d94d1ce 105 p = *shmds = xcalloc(1, sizeof(struct shm_data));
058e8154
SK
106 p->next = NULL;
107
108 f = path_fopen("r", 0, _PATH_PROC_SYSV_SHM);
109 if (!f)
9bcacde1 110 goto shm_fallback;
058e8154
SK
111
112 while (fgetc(f) != '\n'); /* skip header */
113
7d94d1ce 114 while (feof(f) == 0) {
058e8154
SK
115 if (fscanf(f,
116 "%d %d %o %"SCNu64 " %u %u "
278e7203 117 "%"SCNu64 " %u %u %u %u %"SCNi64 " %"SCNi64 " %"SCNi64
058e8154
SK
118 " %"SCNu64 " %"SCNu64 "\n",
119 &p->shm_perm.key,
120 &p->shm_perm.id,
121 &p->shm_perm.mode,
122 &p->shm_segsz,
123 &p->shm_cprid,
124 &p->shm_lprid,
125 &p->shm_nattch,
126 &p->shm_perm.uid,
127 &p->shm_perm.gid,
128 &p->shm_perm.cuid,
129 &p->shm_perm.cgid,
130 &p->shm_atim,
131 &p->shm_dtim,
132 &p->shm_ctim,
133 &p->shm_rss,
134 &p->shm_swp) != 16)
135 continue;
136
7d94d1ce
KZ
137 if (id > -1) {
138 /* ID specified */
139 if (id == p->shm_perm.id) {
140 i = 1;
141 break;
142 } else
143 continue;
058e8154 144 }
7d94d1ce
KZ
145
146 p->next = xcalloc(1, sizeof(struct shm_data));
147 p = p->next;
148 p->next = NULL;
149 i++;
058e8154
SK
150 }
151
152 if (i == 0)
153 free(*shmds);
154 fclose(f);
155 return i;
156
157 /* Fallback; /proc or /sys file(s) missing. */
9bcacde1 158shm_fallback:
3ce29d6d 159 maxid = shmctl(0, SHM_INFO, &dummy);
61e14b4a 160
b507e426 161 for (int j = 0; j <= maxid; j++) {
058e8154
SK
162 int shmid;
163 struct shmid_ds shmseg;
164 struct ipc_perm *ipcp = &shmseg.shm_perm;
165
b507e426
RM
166 shmid = shmctl(j, SHM_STAT, &shmseg);
167 if (shmid < 0 || (id > -1 && shmid != id)) {
058e8154
SK
168 continue;
169 }
170
b507e426 171 i++;
058e8154
SK
172 p->shm_perm.key = ipcp->KEY;
173 p->shm_perm.id = shmid;
174 p->shm_perm.mode = ipcp->mode;
175 p->shm_segsz = shmseg.shm_segsz;
176 p->shm_cprid = shmseg.shm_cpid;
177 p->shm_lprid = shmseg.shm_lpid;
178 p->shm_nattch = shmseg.shm_nattch;
179 p->shm_perm.uid = ipcp->uid;
180 p->shm_perm.gid = ipcp->gid;
181 p->shm_perm.cuid = ipcp->cuid;
182 p->shm_perm.cgid = ipcp->cuid;
183 p->shm_atim = shmseg.shm_atime;
184 p->shm_dtim = shmseg.shm_dtime;
185 p->shm_ctim = shmseg.shm_ctime;
186 p->shm_rss = 0xdead;
187 p->shm_swp = 0xdead;
188
189 if (id < 0) {
7d94d1ce 190 p->next = xcalloc(1, sizeof(struct shm_data));
058e8154
SK
191 p = p->next;
192 p->next = NULL;
058e8154 193 } else
b507e426 194 break;
058e8154
SK
195 }
196
b507e426
RM
197 if (i == 0)
198 free(*shmds);
058e8154
SK
199 return i;
200}
201
202void ipc_shm_free_info(struct shm_data *shmds)
203{
204 while (shmds) {
205 struct shm_data *next = shmds->next;
206 free(shmds);
207 shmds = next;
208 }
209}
210
b5504a3d
SK
211static void get_sem_elements(struct sem_data *p)
212{
213 size_t i;
214
215 if (!p || !p->sem_nsems || p->sem_perm.id < 0)
216 return;
217
218 p->elements = xcalloc(p->sem_nsems, sizeof(struct sem_elem));
219
220 for (i = 0; i < p->sem_nsems; i++) {
221 struct sem_elem *e = &p->elements[i];
222 union semun arg = { .val = 0 };
223
224 e->semval = semctl(p->sem_perm.id, i, GETVAL, arg);
225 if (e->semval < 0)
226 err(EXIT_FAILURE, _("%s failed"), "semctl(GETVAL)");
227
228 e->ncount = semctl(p->sem_perm.id, i, GETNCNT, arg);
229 if (e->ncount < 0)
230 err(EXIT_FAILURE, _("%s failed"), "semctl(GETNCNT)");
231
232 e->zcount = semctl(p->sem_perm.id, i, GETZCNT, arg);
233 if (e->zcount < 0)
234 err(EXIT_FAILURE, _("%s failed"), "semctl(GETZCNT)");
235
236 e->pid = semctl(p->sem_perm.id, i, GETPID, arg);
237 if (e->pid < 0)
238 err(EXIT_FAILURE, _("%s failed"), "semctl(GETPID)");
239 }
240}
241
1e2418a2
SK
242int ipc_sem_get_info(int id, struct sem_data **semds)
243{
244 FILE *f;
7d8ea9df 245 int i = 0, maxid;
1e2418a2
SK
246 struct sem_data *p;
247 struct seminfo dummy;
248 union semun arg;
249
250 p = *semds = xcalloc(1, sizeof(struct sem_data));
251 p->next = NULL;
252
253 f = path_fopen("r", 0, _PATH_PROC_SYSV_SEM);
254 if (!f)
255 goto sem_fallback;
256
257 while (fgetc(f) != '\n') ; /* skip header */
258
259 while (feof(f) == 0) {
260 if (fscanf(f,
278e7203
KZ
261 "%d %d %o %" SCNu64 " %u %u %u %u %"
262 SCNi64 " %" SCNi64 "\n",
1e2418a2
SK
263 &p->sem_perm.key,
264 &p->sem_perm.id,
265 &p->sem_perm.mode,
266 &p->sem_nsems,
267 &p->sem_perm.uid,
268 &p->sem_perm.gid,
269 &p->sem_perm.cuid,
270 &p->sem_perm.cgid,
271 &p->sem_otime,
272 &p->sem_ctime) != 10)
273 continue;
274
275 if (id > -1) {
276 /* ID specified */
277 if (id == p->sem_perm.id) {
b5504a3d 278 get_sem_elements(p);
1e2418a2
SK
279 i = 1;
280 break;
281 } else
282 continue;
283 }
284
285 p->next = xcalloc(1, sizeof(struct sem_data));
286 p = p->next;
287 p->next = NULL;
288 i++;
289 }
290
291 if (i == 0)
292 free(*semds);
293 fclose(f);
294 return i;
295
296 /* Fallback; /proc or /sys file(s) missing. */
9bcacde1 297sem_fallback:
1e2418a2
SK
298 arg.array = (ushort *) (void *)&dummy;
299 maxid = semctl(0, 0, SEM_INFO, arg);
1e2418a2 300
5078a0d3 301 for (int j = 0; j <= maxid; j++) {
1e2418a2
SK
302 int semid;
303 struct semid_ds semseg;
304 struct ipc_perm *ipcp = &semseg.sem_perm;
305 arg.buf = (struct semid_ds *)&semseg;
306
5078a0d3
RM
307 semid = semctl(j, 0, SEM_STAT, arg);
308 if (semid < 0 || (id > -1 && semid != id)) {
1e2418a2
SK
309 continue;
310 }
311
5078a0d3 312 i++;
1e2418a2
SK
313 p->sem_perm.key = ipcp->KEY;
314 p->sem_perm.id = semid;
315 p->sem_perm.mode = ipcp->mode;
316 p->sem_nsems = semseg.sem_nsems;
317 p->sem_perm.uid = ipcp->uid;
318 p->sem_perm.gid = ipcp->gid;
319 p->sem_perm.cuid = ipcp->cuid;
320 p->sem_perm.cgid = ipcp->cuid;
321 p->sem_otime = semseg.sem_otime;
322 p->sem_ctime = semseg.sem_ctime;
323
324 if (id < 0) {
325 p->next = xcalloc(1, sizeof(struct sem_data));
326 p = p->next;
327 p->next = NULL;
328 i++;
b5504a3d
SK
329 } else {
330 get_sem_elements(p);
5078a0d3 331 break;
b5504a3d 332 }
1e2418a2
SK
333 }
334
5078a0d3
RM
335 if (i == 0)
336 free(*semds);
1e2418a2
SK
337 return i;
338}
339
340void ipc_sem_free_info(struct sem_data *semds)
341{
342 while (semds) {
343 struct sem_data *next = semds->next;
b5504a3d 344 free(semds->elements);
1e2418a2
SK
345 free(semds);
346 semds = next;
347 }
348}
349
35118dfc
SK
350int ipc_msg_get_info(int id, struct msg_data **msgds)
351{
352 FILE *f;
7d8ea9df 353 int i = 0, maxid;
35118dfc
SK
354 struct msg_data *p;
355 struct msqid_ds dummy;
2bd2f79d 356 struct msqid_ds msgseg;
35118dfc
SK
357
358 p = *msgds = xcalloc(1, sizeof(struct msg_data));
359 p->next = NULL;
360
361 f = path_fopen("r", 0, _PATH_PROC_SYSV_MSG);
362 if (!f)
363 goto msg_fallback;
364
365 while (fgetc(f) != '\n') ; /* skip header */
366
367 while (feof(f) == 0) {
368 if (fscanf(f,
278e7203
KZ
369 "%d %d %o %" SCNu64 " %" SCNu64
370 " %u %u %u %u %u %u %" SCNi64 " %" SCNi64 " %" SCNi64 "\n",
35118dfc
SK
371 &p->msg_perm.key,
372 &p->msg_perm.id,
373 &p->msg_perm.mode,
374 &p->q_cbytes,
375 &p->q_qnum,
376 &p->q_lspid,
377 &p->q_lrpid,
378 &p->msg_perm.uid,
379 &p->msg_perm.gid,
380 &p->msg_perm.cuid,
381 &p->msg_perm.cgid,
382 &p->q_stime,
383 &p->q_rtime,
384 &p->q_ctime) != 14)
385 continue;
386
387 if (id > -1) {
388 /* ID specified */
389 if (id == p->msg_perm.id) {
2bd2f79d
SK
390 /*
391 * FIXME: q_qbytes are not in /proc
392 *
393 */
394 if (msgctl(id, IPC_STAT, &msgseg) != -1)
395 p->q_qbytes = msgseg.msg_qbytes;
35118dfc
SK
396 i = 1;
397 break;
398 } else
399 continue;
400 }
401
402 p->next = xcalloc(1, sizeof(struct msg_data));
403 p = p->next;
404 p->next = NULL;
405 i++;
406 }
407
408 if (i == 0)
409 free(*msgds);
410 fclose(f);
411 return i;
412
413 /* Fallback; /proc or /sys file(s) missing. */
9bcacde1 414msg_fallback:
08e7d10b 415 maxid = msgctl(0, MSG_INFO, &dummy);
35118dfc 416
08e7d10b 417 for (int j = 0; j <= maxid; j++) {
35118dfc 418 int msgid;
35118dfc
SK
419 struct ipc_perm *ipcp = &msgseg.msg_perm;
420
08e7d10b
RM
421 msgid = msgctl(j, MSG_STAT, &msgseg);
422 if (msgid < 0 || (id > -1 && msgid != id)) {
35118dfc
SK
423 continue;
424 }
425
08e7d10b 426 i++;
35118dfc
SK
427 p->msg_perm.key = ipcp->KEY;
428 p->msg_perm.id = msgid;
429 p->msg_perm.mode = ipcp->mode;
430 p->q_cbytes = msgseg.msg_cbytes;
431 p->q_qnum = msgseg.msg_qnum;
432 p->q_lspid = msgseg.msg_lspid;
433 p->q_lrpid = msgseg.msg_lrpid;
434 p->msg_perm.uid = ipcp->uid;
435 p->msg_perm.gid = ipcp->gid;
436 p->msg_perm.cuid = ipcp->cuid;
437 p->msg_perm.cgid = ipcp->cgid;
438 p->q_stime = msgseg.msg_stime;
439 p->q_rtime = msgseg.msg_rtime;
440 p->q_ctime = msgseg.msg_ctime;
2bd2f79d 441 p->q_qbytes = msgseg.msg_qbytes;
35118dfc
SK
442
443 if (id < 0) {
444 p->next = xcalloc(1, sizeof(struct msg_data));
445 p = p->next;
446 p->next = NULL;
35118dfc 447 } else
08e7d10b 448 break;
35118dfc
SK
449 }
450
08e7d10b
RM
451 if (i == 0)
452 free(*msgds);
35118dfc
SK
453 return i;
454}
455
456void ipc_msg_free_info(struct msg_data *msgds)
457{
458 while (msgds) {
459 struct msg_data *next = msgds->next;
460 free(msgds);
461 msgds = next;
462 }
463}
464
058e8154
SK
465void ipc_print_perms(FILE *f, struct ipc_stat *is)
466{
467 struct passwd *pw;
468 struct group *gr;
469
470 fprintf(f, "%-10d %-10o", is->id, is->mode & 0777);
471
472 if ((pw = getpwuid(is->cuid)))
473 fprintf(f, " %-10s", pw->pw_name);
474 else
475 fprintf(f, " %-10u", is->cuid);
476
477 if ((gr = getgrgid(is->cgid)))
478 fprintf(f, " %-10s", gr->gr_name);
479 else
480 fprintf(f, " %-10u", is->cgid);
481
482 if ((pw = getpwuid(is->uid)))
483 fprintf(f, " %-10s", pw->pw_name);
484 else
485 fprintf(f, " %-10u", is->uid);
486
487 if ((gr = getgrgid(is->gid)))
488 fprintf(f, " %-10s\n", gr->gr_name);
489 else
490 fprintf(f, " %-10u\n", is->gid);
491}
56692a67 492
873e7a59 493void ipc_print_size(int unit, char *msg, uint64_t size, const char *end,
56692a67
SK
494 int width)
495{
873e7a59 496 char format[32];
56692a67
SK
497
498 if (!msg)
499 /* NULL */ ;
500 else if (msg[strlen(msg) - 1] == '=')
501 printf("%s", msg);
502 else if (unit == IPC_UNIT_BYTES)
503 printf(_("%s (bytes) = "), msg);
504 else if (unit == IPC_UNIT_KB)
505 printf(_("%s (kbytes) = "), msg);
506 else
507 printf("%s = ", msg);
508
509 switch (unit) {
510 case IPC_UNIT_DEFAULT:
511 case IPC_UNIT_BYTES:
873e7a59 512 sprintf(format, "%%%dju", width);
56692a67
SK
513 printf(format, size);
514 break;
515 case IPC_UNIT_KB:
873e7a59 516 sprintf(format, "%%%dju", width);
56692a67
SK
517 printf(format, size / 1024);
518 break;
519 case IPC_UNIT_HUMAN:
520 sprintf(format, "%%%ds", width);
521 printf(format, size_to_human_string(SIZE_SUFFIX_1LETTER, size));
522 break;
523 default:
524 /* impossible occurred */
525 abort();
526 }
527
528 if (end)
529 printf("%s", end);
530}