]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/lsipc.c
Merge branch 'maybe-for-v2.32' of https://github.com/rudimeier/util-linux
[thirdparty/util-linux.git] / sys-utils / lsipc.c
CommitLineData
9d20ffda
KZ
1/*
2 * lsipc - List information about IPC instances employed in the system
3 *
4 * Copyright (C) 2015 Ondrej Oprala <ooprala@redhat.com>
5 * Copyright (C) 2015 Karel Zak <ooprala@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 *
22 * lsipc is inspired by the ipcs utility. The aim is to create
23 * a utility unencumbered by a standard to provide more flexible
24 * means of controlling the output.
25 */
26
27#include <errno.h>
9d20ffda
KZ
28#include <getopt.h>
29#include <sys/time.h>
30#include <unistd.h>
31
32#include <libsmartcols.h>
33
34#include "c.h"
35#include "nls.h"
36#include "closestream.h"
37#include "strutils.h"
38#include "optutils.h"
39#include "xalloc.h"
be475287 40#include "procutils.h"
9d20ffda 41#include "ipcutils.h"
bbdfcbe9 42#include "timeutils.h"
9d20ffda
KZ
43
44/*
45 * time modes
46 * */
47enum {
48 TIME_INVALID = 0,
49 TIME_SHORT,
50 TIME_FULL,
c8b47062 51 TIME_ISO
9d20ffda
KZ
52};
53
54/*
55 * IDs
56 */
57enum {
470a7332
KZ
58 /* generic */
59 COLDESC_IDX_GEN_FIRST = 0,
60 COL_KEY = COLDESC_IDX_GEN_FIRST,
61 COL_ID,
62 COL_OWNER,
63 COL_PERMS,
64 COL_CUID,
7458c061 65 COL_CUSER,
470a7332 66 COL_CGID,
7458c061 67 COL_CGROUP,
470a7332 68 COL_UID,
7458c061 69 COL_USER,
470a7332 70 COL_GID,
7458c061 71 COL_GROUP,
470a7332
KZ
72 COL_CTIME,
73 COLDESC_IDX_GEN_LAST = COL_CTIME,
74
9d20ffda 75 /* msgq-specific */
470a7332
KZ
76 COLDESC_IDX_MSG_FIRST,
77 COL_USEDBYTES = COLDESC_IDX_MSG_FIRST,
78 COL_MSGS,
79 COL_SEND,
80 COL_RECV,
81 COL_LSPID,
82 COL_LRPID,
83 COLDESC_IDX_MSG_LAST = COL_LRPID,
84
9d20ffda 85 /* shm-specific */
470a7332
KZ
86 COLDESC_IDX_SHM_FIRST,
87 COL_SIZE = COLDESC_IDX_SHM_FIRST,
88 COL_NATTCH,
89 COL_STATUS,
90 COL_ATTACH,
91 COL_DETACH,
92 COL_COMMAND,
93 COL_CPID,
94 COL_LPID,
95 COLDESC_IDX_SHM_LAST = COL_LPID,
96
9d20ffda 97 /* sem-specific */
470a7332
KZ
98 COLDESC_IDX_SEM_FIRST,
99 COL_NSEMS = COLDESC_IDX_SEM_FIRST,
100 COL_OTIME,
101 COLDESC_IDX_SEM_LAST = COL_OTIME,
102
103 /* summary (--global) */
104 COLDESC_IDX_SUM_FIRST,
32cfe498 105 COL_RESOURCE = COLDESC_IDX_SUM_FIRST,
470a7332 106 COL_DESC,
470a7332 107 COL_LIMIT,
1a311071
KZ
108 COL_USED,
109 COL_USEPERC,
110 COLDESC_IDX_SUM_LAST = COL_USEPERC
9d20ffda
KZ
111};
112
9d20ffda
KZ
113/* not all columns apply to all options, so we specify a legal range for each */
114static size_t LOWER, UPPER;
115
116/*
117 * output modes
118 */
119enum {
2a7150ac 120 OUT_EXPORT = 1,
9d20ffda
KZ
121 OUT_NEWLINE,
122 OUT_RAW,
5de8fcfd 123 OUT_JSON,
2916afa3
KZ
124 OUT_PRETTY,
125 OUT_LIST
9d20ffda
KZ
126};
127
128struct lsipc_control {
d7500c6a 129 int outmode;
9d20ffda
KZ
130 unsigned int noheadings : 1, /* don't print header line */
131 notrunc : 1, /* don't truncate columns */
9d20ffda
KZ
132 bytes : 1, /* SIZE in bytes */
133 numperms : 1, /* numeric permissions */
134 time_mode : 2;
135};
136
137struct lsipc_coldesc {
138 const char *name;
139 const char *help;
140 const char *pretty_name;
141
142 double whint; /* width hint */
143 long flag;
144};
145
146static const struct lsipc_coldesc coldescs[] =
147{
148 /* common */
149 [COL_KEY] = { "KEY", N_("Resource key"), N_("Key"), 1},
150 [COL_ID] = { "ID", N_("Resource ID"), N_("ID"), 1},
d8461c4e 151 [COL_OWNER] = { "OWNER", N_("Owner's username or UID"), N_("Owner"), 1, SCOLS_FL_RIGHT},
9d20ffda 152 [COL_PERMS] = { "PERMS", N_("Permissions"), N_("Permissions"), 1, SCOLS_FL_RIGHT},
7458c061
KZ
153 [COL_CUID] = { "CUID", N_("Creator UID"), N_("Creator UID"), 1, SCOLS_FL_RIGHT},
154 [COL_CUSER] = { "CUSER", N_("Creator user"), N_("Creator user"), 1 },
155 [COL_CGID] = { "CGID", N_("Creator GID"), N_("Creator GID"), 1, SCOLS_FL_RIGHT},
156 [COL_CGROUP] = { "CGROUP", N_("Creator group"), N_("Creator group"), 1 },
9d20ffda 157 [COL_UID] = { "UID", N_("User ID"), N_("UID"), 1, SCOLS_FL_RIGHT},
7458c061 158 [COL_USER] = { "USER", N_("User name"), N_("User name"), 1},
9d20ffda 159 [COL_GID] = { "GID", N_("Group ID"), N_("GID"), 1, SCOLS_FL_RIGHT},
7458c061 160 [COL_GROUP] = { "GROUP", N_("Group name"), N_("Group name"), 1},
9d20ffda
KZ
161 [COL_CTIME] = { "CTIME", N_("Time of the last change"), N_("Last change"), 1, SCOLS_FL_RIGHT},
162
163 /* msgq-specific */
164 [COL_USEDBYTES] = { "USEDBYTES",N_("Bytes used"), N_("Bytes used"), 1, SCOLS_FL_RIGHT},
165 [COL_MSGS] = { "MSGS", N_("Number of messages"), N_("Messages"), 1},
166 [COL_SEND] = { "SEND", N_("Time of last msg sent"), N_("Msg sent"), 1, SCOLS_FL_RIGHT},
167 [COL_RECV] = { "RECV", N_("Time of last msg received"), N_("Msg received"), 1, SCOLS_FL_RIGHT},
168 [COL_LSPID] = { "LSPID", N_("PID of the last msg sender"), N_("Msg sender"), 1, SCOLS_FL_RIGHT},
169 [COL_LRPID] = { "LRPID", N_("PID of the last msg receiver"), N_("Msg receiver"), 1, SCOLS_FL_RIGHT},
170
171 /* shm-specific */
172 [COL_SIZE] = { "SIZE", N_("Segment size"), N_("Segment size"), 1, SCOLS_FL_RIGHT},
173 [COL_NATTCH] = { "NATTCH", N_("Number of attached processes"), N_("Attached processes"), 1, SCOLS_FL_RIGHT},
174 [COL_STATUS] = { "STATUS", N_("Status"), N_("Status"), 1, SCOLS_FL_NOEXTREMES},
175 [COL_ATTACH] = { "ATTACH", N_("Attach time"), N_("Attach time"), 1, SCOLS_FL_RIGHT},
176 [COL_DETACH] = { "DETACH", N_("Detach time"), N_("Detach time"), 1, SCOLS_FL_RIGHT},
be475287 177 [COL_COMMAND] = { "COMMAND", N_("Creator command line"), N_("Creator command"), 0, SCOLS_FL_TRUNC},
9d20ffda
KZ
178 [COL_CPID] = { "CPID", N_("PID of the creator"), N_("Creator PID"), 1, SCOLS_FL_RIGHT},
179 [COL_LPID] = { "LPID", N_("PID of last user"), N_("Last user PID"), 1, SCOLS_FL_RIGHT},
180
181 /* sem-specific */
182 [COL_NSEMS] = { "NSEMS", N_("Number of semaphores"), N_("Semaphores"), 1, SCOLS_FL_RIGHT},
183 [COL_OTIME] = { "OTIME", N_("Time of the last operation"), N_("Last operation"), 1, SCOLS_FL_RIGHT},
184
185 /* cols for summarized information */
186 [COL_RESOURCE] = { "RESOURCE", N_("Resource name"), N_("Resource"), 1 },
187 [COL_DESC] = { "DESCRIPTION",N_("Resource description"), N_("Description"), 1 },
32cfe498 188 [COL_USED] = { "USED", N_("Currently used"), N_("Used"), 1, SCOLS_FL_RIGHT },
1a311071 189 [COL_USEPERC] = { "USE%", N_("Currently use percentage"), N_("Use"), 1, SCOLS_FL_RIGHT },
9d20ffda
KZ
190 [COL_LIMIT] = { "LIMIT", N_("System-wide limit"), N_("Limit"), 1, SCOLS_FL_RIGHT },
191};
192
193
194/* columns[] array specifies all currently wanted output column. The columns
195 * are defined by coldescs[] array and you can specify (on command line) each
196 * column twice. That's enough, dynamically allocated array of the columns is
197 * unnecessary overkill and over-engineering in this case */
198static int columns[ARRAY_SIZE(coldescs) * 2];
e0154173 199static size_t ncolumns;
9d20ffda
KZ
200
201static inline size_t err_columns_index(size_t arysz, size_t idx)
202{
203 if (idx >= arysz)
204 errx(EXIT_FAILURE, _("too many columns specified, "
205 "the limit is %zu columns"),
206 arysz - 1);
207 return idx;
208}
209
210#define add_column(ary, n, id) \
211 ((ary)[ err_columns_index(ARRAY_SIZE(ary), (n)) ] = (id))
212
213static int column_name_to_id(const char *name, size_t namesz)
214{
215 size_t i;
216
217 for (i = 0; i < ARRAY_SIZE(coldescs); i++) {
218 const char *cn = coldescs[i].name;
219
220 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) {
221 if (i > COL_CTIME) {
222 if (i >= LOWER && i <= UPPER)
223 return i;
224 else {
225 warnx(_("column %s does not apply to the specified IPC"), name);
226 return -1;
227 }
228 } else
229 return i;
230 }
231 }
232 warnx(_("unknown column: %s"), name);
233 return -1;
234}
235
71b63dc1
KZ
236static char *get_username(struct passwd **pw, uid_t id)
237{
238 if (!*pw || (*pw)->pw_uid != id)
239 *pw = getpwuid(id);
240
241 return *pw ? xstrdup((*pw)->pw_name) : NULL;
242}
243
244static char *get_groupname(struct group **gr, gid_t id)
245{
246 if (!*gr || (*gr)->gr_gid != id)
247 *gr = getgrgid(id);
248
249 return *gr ? xstrdup((*gr)->gr_name) : NULL;
250}
251
eb2306e6 252static int parse_time_mode(const char *s)
9d20ffda
KZ
253{
254 struct lsipc_timefmt {
255 const char *name;
256 const int val;
257 };
258 static const struct lsipc_timefmt timefmts[] = {
259 {"iso", TIME_ISO},
260 {"full", TIME_FULL},
261 {"short", TIME_SHORT},
262 };
263 size_t i;
264
265 for (i = 0; i < ARRAY_SIZE(timefmts); i++) {
eb2306e6 266 if (strcmp(timefmts[i].name, s) == 0)
9d20ffda
KZ
267 return timefmts[i].val;
268 }
eb2306e6 269 errx(EXIT_FAILURE, _("unknown time format: %s"), s);
9d20ffda
KZ
270}
271
9325dbfd 272static void __attribute__((__noreturn__)) usage(void)
9d20ffda 273{
9325dbfd 274 FILE *out = stdout;
9d20ffda
KZ
275 size_t i;
276
277 fputs(USAGE_HEADER, out);
9d20ffda
KZ
278 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
279
280 fputs(USAGE_SEPARATOR, out);
281 fputs(_("Show information on IPC facilities.\n"), out);
282
9d20ffda
KZ
283 fputs(USAGE_SEPARATOR, out);
284 fputs(_("Resource options:\n"), out);
285 fputs(_(" -m, --shmems shared memory segments\n"), out);
286 fputs(_(" -q, --queues message queues\n"), out);
287 fputs(_(" -s, --semaphores semaphores\n"), out);
32cfe498 288 fputs(_(" -g, --global info about system-wide usage (may be used with -m, -q and -s)\n"), out);
9d20ffda
KZ
289 fputs(_(" -i, --id <id> print details on resource identified by <id>\n"), out);
290
470a7332 291 fputs(USAGE_OPTIONS, out);
9d20ffda
KZ
292 fputs(_(" --noheadings don't print headings\n"), out);
293 fputs(_(" --notruncate don't truncate output\n"), out);
294 fputs(_(" --time-format=<type> display dates in short, full or iso format\n"), out);
295 fputs(_(" -b, --bytes print SIZE in bytes rather than in human readable format\n"), out);
296 fputs(_(" -c, --creator show creator and owner\n"), out);
297 fputs(_(" -e, --export display in an export-able output format\n"), out);
9d20ffda
KZ
298 fputs(_(" -J, --json use the JSON output format\n"), out);
299 fputs(_(" -n, --newline display each piece of information on a new line\n"), out);
2916afa3 300 fputs(_(" -l, --list force list output format (for example with --id)\n"), out);
9d20ffda
KZ
301 fputs(_(" -o, --output[=<list>] define the columns to output\n"), out);
302 fputs(_(" -P, --numeric-perms print numeric permissions (PERMS column)\n"), out);
303 fputs(_(" -r, --raw display in raw mode\n"), out);
304 fputs(_(" -t, --time show attach, detach and change times\n"), out);
2a7150ac
KZ
305
306 fputs(USAGE_SEPARATOR, out);
f45f3ec3 307 printf(USAGE_HELP_OPTIONS(26));
9d20ffda 308
470a7332 309 fprintf(out, _("\nGeneric columns:\n"));
32cfe498 310 for (i = COLDESC_IDX_GEN_FIRST; i <= COLDESC_IDX_GEN_LAST; i++)
470a7332 311 fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
9d20ffda 312
62eea9ce 313 fprintf(out, _("\nShared-memory columns (--shmems):\n"));
32cfe498 314 for (i = COLDESC_IDX_SHM_FIRST; i <= COLDESC_IDX_SHM_LAST; i++)
470a7332 315 fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
9d20ffda 316
62eea9ce 317 fprintf(out, _("\nMessage-queue columns (--queues):\n"));
32cfe498 318 for (i = COLDESC_IDX_MSG_FIRST; i <= COLDESC_IDX_MSG_LAST; i++)
470a7332 319 fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
9d20ffda 320
62eea9ce 321 fprintf(out, _("\nSemaphore columns (--semaphores):\n"));
32cfe498 322 for (i = COLDESC_IDX_SEM_FIRST; i <= COLDESC_IDX_SEM_LAST; i++)
470a7332
KZ
323 fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
324
325 fprintf(out, _("\nSummary columns (--global):\n"));
32cfe498 326 for (i = COLDESC_IDX_SUM_FIRST; i <= COLDESC_IDX_SUM_LAST; i++)
470a7332
KZ
327 fprintf(out, " %14s %s\n", coldescs[i].name, _(coldescs[i].help));
328
f45f3ec3 329 printf(USAGE_MAN_TAIL("lsipc(1)"));
9325dbfd 330 exit(EXIT_SUCCESS);
9d20ffda
KZ
331}
332
624de257 333static struct libscols_table *new_table(struct lsipc_control *ctl)
9d20ffda
KZ
334{
335 struct libscols_table *table = scols_new_table();
9d20ffda
KZ
336
337 if (!table)
780ce22c
KZ
338 err(EXIT_FAILURE, _("failed to allocate output table"));
339
9d20ffda
KZ
340 if (ctl->noheadings)
341 scols_table_enable_noheadings(table, 1);
9d20ffda 342
d7500c6a 343 switch(ctl->outmode) {
9d20ffda
KZ
344 case OUT_NEWLINE:
345 scols_table_set_column_separator(table, "\n");
346 /* fallthrough */
347 case OUT_EXPORT:
348 scols_table_enable_export(table, 1);
349 break;
9d20ffda
KZ
350 case OUT_RAW:
351 scols_table_enable_raw(table, 1);
352 break;
353 case OUT_PRETTY:
354 scols_table_enable_noheadings(table, 1);
5de8fcfd
KZ
355 break;
356 case OUT_JSON:
357 scols_table_enable_json(table, 1);
358 break;
9d20ffda
KZ
359 default:
360 break;
361 }
624de257
KZ
362 return table;
363}
364
365static struct libscols_table *setup_table(struct lsipc_control *ctl)
366{
367 struct libscols_table *table = new_table(ctl);
368 size_t n;
9d20ffda 369
e0154173 370 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
371 int flags = coldescs[columns[n]].flag;
372
373 if (ctl->notrunc)
374 flags &= ~SCOLS_FL_TRUNC;
375
376 if (!scols_table_new_column(table,
377 coldescs[columns[n]].name,
378 coldescs[columns[n]].whint,
379 flags))
380 goto fail;
9d20ffda
KZ
381 }
382 return table;
383fail:
384 scols_unref_table(table);
385 return NULL;
386}
387
388static int print_pretty(struct libscols_table *table)
389{
390 struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD);
391 struct libscols_column *col;
392 struct libscols_cell *data;
393 struct libscols_line *ln;
624de257 394 const char *hstr, *dstr;
9d20ffda
KZ
395 int n = 0;
396
397 ln = scols_table_get_line(table, 0);
398 while (!scols_table_next_column(table, itr, &col)) {
399
400 data = scols_line_get_cell(ln, n);
401
402 hstr = N_(coldescs[columns[n]].pretty_name);
403 dstr = scols_cell_get_data(data);
404
405 if (dstr)
406 printf("%s:%*c%-36s\n", hstr, 35 - (int)strlen(hstr), ' ', dstr);
407 ++n;
408 }
409
410 /* this is used to pretty-print detailed info about a semaphore array */
411 if (ln) {
624de257
KZ
412 struct libscols_table *subtab = scols_line_get_userdata(ln);
413 if (subtab) {
414 printf(_("Elements:\n\n"));
415 scols_print_table(subtab);
9d20ffda
KZ
416 }
417 }
418
419 scols_free_iter(itr);
420 return 0;
421
422}
423
d7500c6a 424static int print_table(struct lsipc_control *ctl, struct libscols_table *tb)
9d20ffda 425{
d7500c6a 426 if (ctl->outmode == OUT_PRETTY)
9d20ffda
KZ
427 print_pretty(tb);
428 else
429 scols_print_table(tb);
430 return 0;
431}
432static struct timeval now;
433
9d20ffda
KZ
434static char *make_time(int mode, time_t time)
435{
9d20ffda
KZ
436 char buf[64] = {0};
437
9d20ffda
KZ
438 switch(mode) {
439 case TIME_FULL:
bcf72069
KZ
440 {
441 struct tm tm;
442 char *s;
443
444 localtime_r(&time, &tm);
9d20ffda
KZ
445 asctime_r(&tm, buf);
446 if (*(s = buf + strlen(buf) - 1) == '\n')
447 *s = '\0';
448 break;
bcf72069 449 }
9d20ffda 450 case TIME_SHORT:
bcf72069 451 strtime_short(&time, &now, 0, buf, sizeof(buf));
9d20ffda
KZ
452 break;
453 case TIME_ISO:
4111bb3a 454 strtime_iso(&time, ISO_TIMESTAMP_T, buf, sizeof(buf));
9d20ffda
KZ
455 break;
456 default:
457 errx(EXIT_FAILURE, _("unsupported time type"));
458 }
459 return xstrdup(buf);
460}
461
32cfe498 462static void global_set_data(struct libscols_table *tb, const char *resource,
a4839bc7 463 const char *desc, uintmax_t used, uintmax_t limit, int usage)
32cfe498
KZ
464{
465 struct libscols_line *ln;
e0154173 466 size_t n;
32cfe498
KZ
467
468 ln = scols_table_new_line(tb, NULL);
469 if (!ln)
780ce22c 470 err(EXIT_FAILURE, _("failed to allocate output line"));
32cfe498
KZ
471
472 for (n = 0; n < ncolumns; n++) {
473 int rc = 0;
474 char *arg = NULL;
475
476 switch (columns[n]) {
477 case COL_RESOURCE:
478 rc = scols_line_set_data(ln, n, resource);
479 break;
480 case COL_DESC:
481 rc = scols_line_set_data(ln, n, desc);
482 break;
483 case COL_USED:
a4839bc7
KZ
484 if (usage) {
485 xasprintf(&arg, "%ju", used);
486 rc = scols_line_refer_data(ln, n, arg);
487 } else
488 rc = scols_line_set_data(ln, n, "-");
32cfe498 489 break;
1a311071 490 case COL_USEPERC:
a4839bc7
KZ
491 if (usage) {
492 xasprintf(&arg, "%2.2f%%", (double) used / limit * 100);
493 rc = scols_line_refer_data(ln, n, arg);
494 } else
495 rc = scols_line_set_data(ln, n, "-");
1a311071 496 break;
32cfe498
KZ
497 case COL_LIMIT:
498 xasprintf(&arg, "%ju", limit);
cdb4a946 499 rc = scols_line_refer_data(ln, n, arg);
32cfe498
KZ
500 break;
501 }
502
503 if (rc != 0)
780ce22c 504 err(EXIT_FAILURE, _("failed to add output data"));
32cfe498
KZ
505 }
506}
507
624de257
KZ
508static void setup_sem_elements_columns(struct libscols_table *tb)
509{
510 scols_table_set_name(tb, "elements");
511 if (!scols_table_new_column(tb, "SEMNUM", 0, SCOLS_FL_RIGHT))
512 err_oom();
513 if (!scols_table_new_column(tb, "VALUE", 0, SCOLS_FL_RIGHT))
514 err_oom();
515 if (!scols_table_new_column(tb, "NCOUNT", 0, SCOLS_FL_RIGHT))
516 err_oom();
517 if (!scols_table_new_column(tb, "ZCOUNT", 0, SCOLS_FL_RIGHT))
518 err_oom();
519 if (!scols_table_new_column(tb, "PID", 0, SCOLS_FL_RIGHT))
520 err_oom();
521 if (!scols_table_new_column(tb, "COMMAND", 0, SCOLS_FL_RIGHT))
522 err_oom();
523}
524
9d20ffda
KZ
525static void do_sem(int id, struct lsipc_control *ctl, struct libscols_table *tb)
526{
9d20ffda
KZ
527 struct libscols_line *ln;
528 struct passwd *pw = NULL, *cpw = NULL;
529 struct group *gr = NULL, *cgr = NULL;
530 struct sem_data *semds, *semdsp;
cdb4a946 531 char *arg = NULL;
9d20ffda 532
5de8fcfd
KZ
533 scols_table_set_name(tb, "semaphores");
534
9d20ffda
KZ
535 if (ipc_sem_get_info(id, &semds) < 1) {
536 if (id > -1)
537 warnx(_("id %d not found"), id);
538 return;
539 }
540 for (semdsp = semds; semdsp->next != NULL || id > -1; semdsp = semdsp->next) {
e0154173 541 size_t n;
780ce22c 542
9d20ffda 543 ln = scols_table_new_line(tb, NULL);
780ce22c
KZ
544 if (!ln)
545 err(EXIT_FAILURE, _("failed to allocate output line"));
9d20ffda 546
e0154173
KZ
547 for (n = 0; n < ncolumns; n++) {
548 int rc = 0;
9d20ffda 549 switch (columns[n]) {
91c92cb5
KZ
550 case COL_KEY:
551 xasprintf(&arg, "0x%08x",semdsp->sem_perm.key);
cdb4a946 552 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
553 break;
554 case COL_ID:
555 xasprintf(&arg, "%d",semdsp->sem_perm.id);
cdb4a946 556 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
557 break;
558 case COL_OWNER:
71b63dc1
KZ
559 arg = get_username(&pw, semdsp->sem_perm.uid);
560 if (!arg)
91c92cb5 561 xasprintf(&arg, "%u", semdsp->sem_perm.uid);
cdb4a946 562 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
563 break;
564 case COL_PERMS:
565 if (ctl->numperms)
566 xasprintf(&arg, "%#o", semdsp->sem_perm.mode & 0777);
567 else {
568 arg = xmalloc(11);
b0b24b11 569 xstrmode(semdsp->sem_perm.mode & 0777, arg);
91c92cb5 570 }
cdb4a946 571 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
572 break;
573 case COL_CUID:
574 xasprintf(&arg, "%u", semdsp->sem_perm.cuid);
cdb4a946 575 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
576 break;
577 case COL_CUSER:
71b63dc1
KZ
578 arg = get_username(&cpw, semdsp->sem_perm.cuid);
579 if (arg)
cdb4a946 580 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
581 break;
582 case COL_CGID:
71b63dc1 583 xasprintf(&arg, "%u", semdsp->sem_perm.cgid);
cdb4a946 584 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
585 break;
586 case COL_CGROUP:
71b63dc1
KZ
587 arg = get_groupname(&cgr, semdsp->sem_perm.cgid);
588 if (arg)
cdb4a946 589 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
590 break;
591 case COL_UID:
592 xasprintf(&arg, "%u", semdsp->sem_perm.uid);
cdb4a946 593 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
594 break;
595 case COL_USER:
71b63dc1
KZ
596 arg = get_username(&pw, semdsp->sem_perm.uid);
597 if (arg)
cdb4a946 598 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
599 break;
600 case COL_GID:
71b63dc1 601 xasprintf(&arg, "%u", semdsp->sem_perm.gid);
cdb4a946 602 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
603 break;
604 case COL_GROUP:
71b63dc1
KZ
605 arg = get_groupname(&gr, semdsp->sem_perm.gid);
606 if (arg)
cdb4a946 607 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
608 break;
609 case COL_CTIME:
610 if (semdsp->sem_ctime != 0) {
cdb4a946
KZ
611 rc = scols_line_refer_data(ln, n,
612 make_time(ctl->time_mode,
91c92cb5 613 (time_t)semdsp->sem_ctime));
91c92cb5
KZ
614 }
615 break;
616 case COL_NSEMS:
617 xasprintf(&arg, "%ju", semdsp->sem_nsems);
cdb4a946 618 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
619 break;
620 case COL_OTIME:
621 if (semdsp->sem_otime != 0) {
cdb4a946
KZ
622 rc = scols_line_refer_data(ln, n,
623 make_time(ctl->time_mode,
91c92cb5 624 (time_t)semdsp->sem_otime));
91c92cb5
KZ
625 }
626 break;
9d20ffda
KZ
627 }
628 if (rc != 0)
780ce22c 629 err(EXIT_FAILURE, _("failed to add output data"));
9d20ffda
KZ
630 arg = NULL;
631 }
9d20ffda 632
624de257
KZ
633 if (id > -1 && semds->sem_nsems) {
634 /* Create extra table with ID specific semaphore elements */
635 struct libscols_table *sub = new_table(ctl);
636 size_t i;
fadf556a 637 int rc = 0;
624de257
KZ
638
639 scols_table_enable_noheadings(sub, 0);
640 setup_sem_elements_columns(sub);
9d20ffda
KZ
641
642 for (i = 0; i < semds->sem_nsems; i++) {
643 struct sem_elem *e = &semds->elements[i];
624de257
KZ
644 struct libscols_line *sln = scols_table_new_line(sub, NULL);
645
780ce22c
KZ
646 if (!sln)
647 err(EXIT_FAILURE, _("failed to allocate output line"));
648
624de257
KZ
649 /* SEMNUM */
650 xasprintf(&arg, "%zu", i);
fadf556a
KZ
651 rc = scols_line_refer_data(sln, 0, arg);
652 if (rc)
653 break;
624de257
KZ
654
655 /* VALUE */
656 xasprintf(&arg, "%d", e->semval);
fadf556a
KZ
657 rc = scols_line_refer_data(sln, 1, arg);
658 if (rc)
659 break;
624de257
KZ
660
661 /* NCOUNT */
662 xasprintf(&arg, "%d", e->ncount);
fadf556a
KZ
663 rc = scols_line_refer_data(sln, 2, arg);
664 if (rc)
665 break;
624de257
KZ
666
667 /* ZCOUNT */
668 xasprintf(&arg, "%d", e->zcount);
fadf556a
KZ
669 rc = scols_line_refer_data(sln, 3, arg);
670 if (rc)
671 break;
624de257
KZ
672
673 /* PID */
674 xasprintf(&arg, "%d", e->pid);
fadf556a
KZ
675 rc = scols_line_refer_data(sln, 4, arg);
676 if (rc)
677 break;
624de257
KZ
678
679 /* COMMAND */
680 arg = proc_get_command(e->pid);
fadf556a
KZ
681 rc = scols_line_refer_data(sln, 5, arg);
682 if (rc)
683 break;
9d20ffda 684 }
624de257 685
fadf556a
KZ
686 if (rc != 0)
687 err(EXIT_FAILURE, _("failed to set data"));
688
624de257 689 scols_line_set_userdata(ln, (void *)sub);
9d20ffda
KZ
690 break;
691 }
692 }
693 ipc_sem_free_info(semds);
694}
695
696static void do_sem_global(struct libscols_table *tb)
697{
698 struct sem_data *semds, *semdsp;
699 struct ipc_limits lim;
32cfe498 700 int nsems = 0, nsets = 0;
9d20ffda 701
9d20ffda
KZ
702 ipc_sem_get_limits(&lim);
703
32cfe498
KZ
704 if (ipc_sem_get_info(-1, &semds) > 0) {
705 for (semdsp = semds; semdsp->next != NULL; semdsp = semdsp->next) {
706 ++nsets;
707 nsems += semds->sem_nsems;
708 }
709 ipc_sem_free_info(semds);
9d20ffda 710 }
9d20ffda 711
a4839bc7
KZ
712 global_set_data(tb, "SEMMNI", _("Number of semaphore identifiers"), nsets, lim.semmni, 1);
713 global_set_data(tb, "SEMMNS", _("Total number of semaphores"), nsems, lim.semmns, 1);
714 global_set_data(tb, "SEMMSL", _("Max semaphores per semaphore set."), 0, lim.semmsl, 0);
715 global_set_data(tb, "SEMOPM", _("Max number of operations per semop(2)"), 0, lim.semopm, 0);
716 global_set_data(tb, "SEMVMX", _("Semaphore max value"), 0, lim.semvmx, 0);
9d20ffda
KZ
717}
718
719static void do_msg(int id, struct lsipc_control *ctl, struct libscols_table *tb)
720{
9d20ffda
KZ
721 struct libscols_line *ln;
722 struct passwd *pw = NULL;
723 struct group *gr = NULL;
724 struct msg_data *msgds, *msgdsp;
cdb4a946 725 char *arg = NULL;
9d20ffda
KZ
726
727 if (ipc_msg_get_info(id, &msgds) < 1) {
728 if (id > -1)
729 warnx(_("id %d not found"), id);
730 return;
731 }
5de8fcfd 732 scols_table_set_name(tb, "messages");
9d20ffda
KZ
733
734 for (msgdsp = msgds; msgdsp->next != NULL || id > -1 ; msgdsp = msgdsp->next) {
e0154173 735 size_t n;
9d20ffda
KZ
736 ln = scols_table_new_line(tb, NULL);
737
780ce22c
KZ
738 if (!ln)
739 err(EXIT_FAILURE, _("failed to allocate output line"));
740
9d20ffda
KZ
741 /* no need to call getpwuid() for the same user */
742 if (!(pw && pw->pw_uid == msgdsp->msg_perm.uid))
743 pw = getpwuid(msgdsp->msg_perm.uid);
744
745 /* no need to call getgrgid() for the same user */
746 if (!(gr && gr->gr_gid == msgdsp->msg_perm.gid))
747 gr = getgrgid(msgdsp->msg_perm.gid);
748
e0154173 749 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
750 int rc = 0;
751
752 switch (columns[n]) {
91c92cb5
KZ
753 case COL_KEY:
754 xasprintf(&arg, "0x%08x",msgdsp->msg_perm.key);
cdb4a946 755 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
756 break;
757 case COL_ID:
758 xasprintf(&arg, "%d",msgdsp->msg_perm.id);
cdb4a946 759 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
760 break;
761 case COL_OWNER:
71b63dc1
KZ
762 arg = get_username(&pw, msgdsp->msg_perm.uid);
763 if (!arg)
91c92cb5 764 xasprintf(&arg, "%u", msgdsp->msg_perm.uid);
cdb4a946 765 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
766 break;
767 case COL_PERMS:
768 if (ctl->numperms)
769 xasprintf(&arg, "%#o", msgdsp->msg_perm.mode & 0777);
770 else {
771 arg = xmalloc(11);
b0b24b11 772 xstrmode(msgdsp->msg_perm.mode & 0777, arg);
cdb4a946 773 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
774 }
775 break;
776 case COL_CUID:
777 xasprintf(&arg, "%u", msgdsp->msg_perm.cuid);
cdb4a946 778 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
779 break;
780 case COL_CUSER:
71b63dc1
KZ
781 arg = get_username(&pw, msgdsp->msg_perm.cuid);
782 if (arg)
cdb4a946 783 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
784 break;
785 case COL_CGID:
786 xasprintf(&arg, "%u", msgdsp->msg_perm.cuid);
cdb4a946 787 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
788 break;
789 case COL_CGROUP:
71b63dc1
KZ
790 arg = get_groupname(&gr, msgdsp->msg_perm.cgid);
791 if (arg)
cdb4a946 792 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
793 break;
794 case COL_UID:
795 xasprintf(&arg, "%u", msgdsp->msg_perm.uid);
cdb4a946 796 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
797 break;
798 case COL_USER:
71b63dc1
KZ
799 arg = get_username(&pw, msgdsp->msg_perm.uid);
800 if (arg)
cdb4a946 801 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
802 break;
803 case COL_GID:
804 xasprintf(&arg, "%u", msgdsp->msg_perm.gid);
cdb4a946 805 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
806 break;
807 case COL_GROUP:
71b63dc1
KZ
808 arg = get_groupname(&gr,msgdsp->msg_perm.gid);
809 if (arg)
cdb4a946 810 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
811 break;
812 case COL_CTIME:
cdb4a946
KZ
813 if (msgdsp->q_ctime != 0)
814 rc = scols_line_refer_data(ln, n,
815 make_time(ctl->time_mode,
91c92cb5 816 (time_t)msgdsp->q_ctime));
91c92cb5
KZ
817 break;
818 case COL_USEDBYTES:
819 xasprintf(&arg, "%ju", msgdsp->q_cbytes);
cdb4a946 820 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
821 break;
822 case COL_MSGS:
823 xasprintf(&arg, "%ju", msgdsp->q_qnum);
cdb4a946 824 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
825 break;
826 case COL_SEND:
cdb4a946
KZ
827 if (msgdsp->q_stime != 0)
828 rc = scols_line_refer_data(ln, n,
829 make_time(ctl->time_mode,
91c92cb5 830 (time_t)msgdsp->q_stime));
91c92cb5
KZ
831 break;
832 case COL_RECV:
cdb4a946
KZ
833 if (msgdsp->q_rtime != 0)
834 rc = scols_line_refer_data(ln, n,
835 make_time(ctl->time_mode,
91c92cb5 836 (time_t)msgdsp->q_rtime));
91c92cb5
KZ
837 break;
838 case COL_LSPID:
839 xasprintf(&arg, "%u", msgdsp->q_lspid);
cdb4a946 840 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
841 break;
842 case COL_LRPID:
843 xasprintf(&arg, "%u", msgdsp->q_lrpid);
cdb4a946 844 rc = scols_line_refer_data(ln, n, arg);
91c92cb5 845 break;
9d20ffda
KZ
846 }
847 if (rc != 0)
848 err(EXIT_FAILURE, _("failed to set data"));
9d20ffda
KZ
849 arg = NULL;
850 }
851 if (id > -1)
852 break;
853 }
854 ipc_msg_free_info(msgds);
855}
856
32cfe498 857
9d20ffda
KZ
858static void do_msg_global(struct libscols_table *tb)
859{
860 struct msg_data *msgds, *msgdsp;
861 struct ipc_limits lim;
32cfe498 862 int msgqs = 0;
9d20ffda 863
9d20ffda
KZ
864 ipc_msg_get_limits(&lim);
865
32cfe498
KZ
866 /* count number of used queues */
867 if (ipc_msg_get_info(-1, &msgds) > 0) {
868 for (msgdsp = msgds; msgdsp->next != NULL; msgdsp = msgdsp->next)
869 ++msgqs;
870 ipc_msg_free_info(msgds);
9d20ffda
KZ
871 }
872
a4839bc7
KZ
873 global_set_data(tb, "MSGMNI", _("Number of message queues"), msgqs, lim.msgmni, 1);
874 global_set_data(tb, "MSGMAX", _("Max size of message (bytes)"), 0, lim.msgmax, 0);
875 global_set_data(tb, "MSGMNB", _("Default max size of queue (bytes)"), 0, lim.msgmnb, 0);
9d20ffda
KZ
876}
877
d8461c4e 878
9d20ffda
KZ
879static void do_shm(int id, struct lsipc_control *ctl, struct libscols_table *tb)
880{
9d20ffda
KZ
881 struct libscols_line *ln;
882 struct passwd *pw = NULL;
883 struct group *gr = NULL;
884 struct shm_data *shmds, *shmdsp;
cdb4a946 885 char *arg = NULL;
9d20ffda
KZ
886
887 if (ipc_shm_get_info(id, &shmds) < 1) {
888 if (id > -1)
889 warnx(_("id %d not found"), id);
890 return;
891 }
892
5de8fcfd
KZ
893 scols_table_set_name(tb, "sharedmemory");
894
9d20ffda 895 for (shmdsp = shmds; shmdsp->next != NULL || id > -1 ; shmdsp = shmdsp->next) {
e0154173 896 size_t n;
9d20ffda 897 ln = scols_table_new_line(tb, NULL);
780ce22c 898
32cfe498 899 if (!ln)
780ce22c 900 err(EXIT_FAILURE, _("failed to allocate output line"));
9d20ffda 901
e0154173 902 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
903 int rc = 0;
904
905 switch (columns[n]) {
91c92cb5
KZ
906 case COL_KEY:
907 xasprintf(&arg, "0x%08x",shmdsp->shm_perm.key);
cdb4a946 908 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
909 break;
910 case COL_ID:
911 xasprintf(&arg, "%d",shmdsp->shm_perm.id);
cdb4a946 912 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
913 break;
914 case COL_OWNER:
d8461c4e
KZ
915 arg = get_username(&pw, shmdsp->shm_perm.uid);
916 if (!arg)
7458c061 917 xasprintf(&arg, "%u", shmdsp->shm_perm.uid);
cdb4a946 918 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
919 break;
920 case COL_PERMS:
921 if (ctl->numperms)
922 xasprintf(&arg, "%#o", shmdsp->shm_perm.mode & 0777);
923 else {
924 arg = xmalloc(11);
b0b24b11 925 xstrmode(shmdsp->shm_perm.mode & 0777, arg);
91c92cb5 926 }
cdb4a946 927 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
928 break;
929 case COL_CUID:
930 xasprintf(&arg, "%u", shmdsp->shm_perm.cuid);
cdb4a946 931 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
932 break;
933 case COL_CUSER:
d8461c4e
KZ
934 arg = get_username(&pw, shmdsp->shm_perm.cuid);
935 if (arg)
cdb4a946 936 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
937 break;
938 case COL_CGID:
939 xasprintf(&arg, "%u", shmdsp->shm_perm.cuid);
cdb4a946 940 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
941 break;
942 case COL_CGROUP:
d8461c4e
KZ
943 arg = get_groupname(&gr, shmdsp->shm_perm.cgid);
944 if (arg)
cdb4a946 945 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
946 break;
947 case COL_UID:
948 xasprintf(&arg, "%u", shmdsp->shm_perm.uid);
cdb4a946 949 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
950 break;
951 case COL_USER:
d8461c4e
KZ
952 arg = get_username(&pw, shmdsp->shm_perm.uid);
953 if (arg)
cdb4a946 954 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
955 break;
956 case COL_GID:
957 xasprintf(&arg, "%u", shmdsp->shm_perm.gid);
cdb4a946 958 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
959 break;
960 case COL_GROUP:
d8461c4e
KZ
961 arg = get_groupname(&gr, shmdsp->shm_perm.gid);
962 if (arg)
cdb4a946 963 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
964 break;
965 case COL_CTIME:
cdb4a946
KZ
966 if (shmdsp->shm_ctim != 0)
967 rc = scols_line_refer_data(ln, n,
968 make_time(ctl->time_mode,
91c92cb5 969 (time_t)shmdsp->shm_ctim));
91c92cb5
KZ
970 break;
971 case COL_SIZE:
972 if (ctl->bytes)
973 xasprintf(&arg, "%ju", shmdsp->shm_segsz);
974 else
975 arg = size_to_human_string(SIZE_SUFFIX_1LETTER, shmdsp->shm_segsz);
cdb4a946 976 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
977 break;
978 case COL_NATTCH:
979 xasprintf(&arg, "%ju", shmdsp->shm_nattch);
cdb4a946 980 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
981 break;
982 case COL_STATUS: {
983 int comma = 0;
984 size_t offt = 0;
9380fbef
KZ
985
986 free(arg);
91c92cb5
KZ
987 arg = xcalloc(1, sizeof(char) * strlen(_("dest"))
988 + strlen(_("locked"))
989 + strlen(_("hugetlb"))
990 + strlen(_("noreserve")) + 4);
21ce5a5d 991#ifdef SHM_DEST
91c92cb5
KZ
992 if (shmdsp->shm_perm.mode & SHM_DEST) {
993 offt += sprintf(arg, "%s", _("dest"));
994 comma++;
9d20ffda 995 }
21ce5a5d
KZ
996#endif
997#ifdef SHM_LOCKED
91c92cb5
KZ
998 if (shmdsp->shm_perm.mode & SHM_LOCKED) {
999 if (comma)
1000 arg[offt++] = ',';
1001 offt += sprintf(arg + offt, "%s", _("locked"));
9d20ffda 1002 }
21ce5a5d
KZ
1003#endif
1004#ifdef SHM_HUGETLB
91c92cb5
KZ
1005 if (shmdsp->shm_perm.mode & SHM_HUGETLB) {
1006 if (comma)
1007 arg[offt++] = ',';
1008 offt += sprintf(arg + offt, "%s", _("hugetlb"));
1009 }
21ce5a5d
KZ
1010#endif
1011#ifdef SHM_NORESERVE
91c92cb5
KZ
1012 if (shmdsp->shm_perm.mode & SHM_NORESERVE) {
1013 if (comma)
1014 arg[offt++] = ',';
9380fbef 1015 sprintf(arg + offt, "%s", _("noreserve"));
9d20ffda 1016 }
21ce5a5d 1017#endif
cdb4a946 1018 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1019 }
1020 break;
1021 case COL_ATTACH:
cdb4a946
KZ
1022 if (shmdsp->shm_atim != 0)
1023 rc = scols_line_refer_data(ln, n,
1024 make_time(ctl->time_mode,
91c92cb5 1025 (time_t)shmdsp->shm_atim));
91c92cb5
KZ
1026 break;
1027 case COL_DETACH:
cdb4a946
KZ
1028 if (shmdsp->shm_dtim != 0)
1029 rc = scols_line_refer_data(ln, n,
1030 make_time(ctl->time_mode,
91c92cb5 1031 (time_t)shmdsp->shm_dtim));
91c92cb5
KZ
1032 break;
1033 case COL_CPID:
1034 xasprintf(&arg, "%u", shmdsp->shm_cprid);
cdb4a946 1035 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1036 break;
1037 case COL_LPID:
1038 xasprintf(&arg, "%u", shmdsp->shm_lprid);
cdb4a946 1039 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1040 break;
1041 case COL_COMMAND:
1042 arg = proc_get_command(shmdsp->shm_cprid);
cdb4a946 1043 rc = scols_line_refer_data(ln, n, arg);
91c92cb5 1044 break;
9d20ffda
KZ
1045 }
1046 if (rc != 0)
1047 err(EXIT_FAILURE, _("failed to set data"));
9d20ffda
KZ
1048 arg = NULL;
1049 }
1050 if (id > -1)
1051 break;
1052 }
1053 ipc_shm_free_info(shmds);
1054}
1055
1056static void do_shm_global(struct libscols_table *tb)
1057{
1058 struct shm_data *shmds, *shmdsp;
32cfe498 1059 uint64_t nsegs = 0, sum_segsz = 0;
9d20ffda 1060 struct ipc_limits lim;
9d20ffda 1061
9d20ffda
KZ
1062 ipc_shm_get_limits(&lim);
1063
32cfe498
KZ
1064 if (ipc_shm_get_info(-1, &shmds) > 0) {
1065 for (shmdsp = shmds; shmdsp->next != NULL; shmdsp = shmdsp->next) {
1066 ++nsegs;
1067 sum_segsz += shmdsp->shm_segsz;
1068 }
90a9b991 1069 ipc_shm_free_info(shmds);
9d20ffda
KZ
1070 }
1071
a4839bc7
KZ
1072 global_set_data(tb, "SHMMNI", _("Shared memory segments"), nsegs, lim.shmmni, 1);
1073 global_set_data(tb, "SHMALL", _("Shared memory pages"), sum_segsz / getpagesize(), lim.shmall, 1);
1074 global_set_data(tb, "SHMMAX", _("Max size of shared memory segment (bytes)"), 0, lim.shmmax, 0);
1075 global_set_data(tb, "SHMMIN", _("Min size of shared memory segment (bytes)"), 0, lim.shmmin, 0);
9d20ffda
KZ
1076}
1077
1078int main(int argc, char *argv[])
1079{
e0154173 1080 int opt, msg = 0, sem = 0, shm = 0, id = -1;
9d20ffda
KZ
1081 int show_time = 0, show_creat = 0, global = 0;
1082 size_t i;
1083 struct lsipc_control *ctl = xcalloc(1, sizeof(struct lsipc_control));
1084 static struct libscols_table *tb;
e0154173 1085 char *outarg = NULL;
9d20ffda
KZ
1086
1087 /* long only options. */
1088 enum {
1089 OPT_NOTRUNC = CHAR_MAX + 1,
1090 OPT_NOHEAD,
2a7150ac 1091 OPT_TIME_FMT
9d20ffda
KZ
1092 };
1093
1094 static const struct option longopts[] = {
87918040
SK
1095 { "bytes", no_argument, NULL, 'b' },
1096 { "creator", no_argument, NULL, 'c' },
1097 { "export", no_argument, NULL, 'e' },
1098 { "global", no_argument, NULL, 'g' },
1099 { "help", no_argument, NULL, 'h' },
1100 { "id", required_argument, NULL, 'i' },
1101 { "json", no_argument, NULL, 'J' },
1102 { "list", no_argument, NULL, 'l' },
1103 { "newline", no_argument, NULL, 'n' },
1104 { "noheadings", no_argument, NULL, OPT_NOHEAD },
1105 { "notruncate", no_argument, NULL, OPT_NOTRUNC },
1106 { "numeric-perms", no_argument, NULL, 'P' },
1107 { "output", required_argument, NULL, 'o' },
87918040
SK
1108 { "queues", no_argument, NULL, 'q' },
1109 { "raw", no_argument, NULL, 'r' },
1110 { "semaphores", no_argument, NULL, 's' },
1111 { "shmems", no_argument, NULL, 'm' },
1112 { "time", no_argument, NULL, 't' },
1113 { "time-format", required_argument, NULL, OPT_TIME_FMT },
1114 { "version", no_argument, NULL, 'V' },
9d20ffda
KZ
1115 {NULL, 0, NULL, 0}
1116 };
1117
1118 static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
2916afa3
KZ
1119 { 'J', 'e', 'l', 'n', 'r' },
1120 { 'g', 'i' },
1121 { 'c', 'o', 't' },
9d20ffda
KZ
1122 { 'm', 'q', 's' },
1123 { 0 }
1124 };
1125 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
1126
1127 setlocale(LC_ALL, "");
1128 bindtextdomain(PACKAGE, LOCALEDIR);
1129 textdomain(PACKAGE);
1130 atexit(close_stdout);
1131
c8b47062 1132 ctl->time_mode = 0;
9d20ffda 1133
624de257
KZ
1134 scols_init_debug(0);
1135
1b71d08c 1136 while ((opt = getopt_long(argc, argv, "bceghi:Jlmno:PqrstV", longopts, NULL)) != -1) {
9d20ffda
KZ
1137
1138 err_exclusive_options(opt, longopts, excl, excl_st);
1139
1140 switch (opt) {
91c92cb5
KZ
1141 case 'b':
1142 ctl->bytes = 1;
1143 break;
1144 case 'i':
1145 id = strtos32_or_err(optarg, _("failed to parse IPC identifier"));
91c92cb5 1146 break;
91c92cb5 1147 case 'e':
d7500c6a 1148 ctl->outmode = OUT_EXPORT;
91c92cb5
KZ
1149 break;
1150 case 'r':
d7500c6a 1151 ctl->outmode = OUT_RAW;
91c92cb5
KZ
1152 break;
1153 case 'o':
1154 outarg = optarg;
1155 break;
1156 case 'g':
1157 global = 1;
2916afa3 1158 break;
91c92cb5
KZ
1159 case 'q':
1160 msg = 1;
1161 add_column(columns, ncolumns++, COL_KEY);
1162 add_column(columns, ncolumns++, COL_ID);
1163 add_column(columns, ncolumns++, COL_PERMS);
1164 add_column(columns, ncolumns++, COL_OWNER);
1165 add_column(columns, ncolumns++, COL_USEDBYTES);
1166 add_column(columns, ncolumns++, COL_MSGS);
1167 add_column(columns, ncolumns++, COL_LSPID);
1168 add_column(columns, ncolumns++, COL_LRPID);
1169 LOWER = COLDESC_IDX_MSG_FIRST;
1170 UPPER = COLDESC_IDX_MSG_LAST;
1171 break;
2916afa3
KZ
1172 case 'l':
1173 ctl->outmode = OUT_LIST;
1174 break;
91c92cb5
KZ
1175 case 'm':
1176 shm = 1;
1177 add_column(columns, ncolumns++, COL_KEY);
1178 add_column(columns, ncolumns++, COL_ID);
1179 add_column(columns, ncolumns++, COL_PERMS);
1180 add_column(columns, ncolumns++, COL_OWNER);
1181 add_column(columns, ncolumns++, COL_SIZE);
1182 add_column(columns, ncolumns++, COL_NATTCH);
1183 add_column(columns, ncolumns++, COL_STATUS);
1184 add_column(columns, ncolumns++, COL_CTIME);
1185 add_column(columns, ncolumns++, COL_CPID);
1186 add_column(columns, ncolumns++, COL_LPID);
1187 add_column(columns, ncolumns++, COL_COMMAND);
1188 LOWER = COLDESC_IDX_SHM_FIRST;
1189 UPPER = COLDESC_IDX_SHM_LAST;
1190 break;
1191 case 'n':
d7500c6a 1192 ctl->outmode = OUT_NEWLINE;
91c92cb5
KZ
1193 break;
1194 case 'P':
1195 ctl->numperms = 1;
1196 break;
1197 case 's':
1198 sem = 1;
1199 add_column(columns, ncolumns++, COL_KEY);
1200 add_column(columns, ncolumns++, COL_ID);
1201 add_column(columns, ncolumns++, COL_PERMS);
1202 add_column(columns, ncolumns++, COL_OWNER);
1203 add_column(columns, ncolumns++, COL_NSEMS);
1204 LOWER = COLDESC_IDX_SEM_FIRST;
1205 UPPER = COLDESC_IDX_SEM_LAST;
1206 break;
1207 case OPT_NOTRUNC:
1208 ctl->notrunc = 1;
1209 break;
1210 case OPT_NOHEAD:
1211 ctl->noheadings = 1;
1212 break;
1213 case OPT_TIME_FMT:
1214 ctl->time_mode = parse_time_mode(optarg);
1215 break;
1216 case 'J':
5de8fcfd 1217 ctl->outmode = OUT_JSON;
91c92cb5
KZ
1218 break;
1219 case 't':
1220 show_time = 1;
1221 break;
1222 case 'c':
1223 show_creat = 1;
1224 break;
1225 case 'h':
9325dbfd 1226 usage();
91c92cb5
KZ
1227 case 'V':
1228 printf(UTIL_LINUX_VERSION);
1229 return EXIT_SUCCESS;
91c92cb5 1230 default:
9325dbfd 1231 errtryhelp(EXIT_FAILURE);
9d20ffda
KZ
1232 }
1233 }
1234
25456d5d 1235 /* default is global */
8f405a5b 1236 if (msg + shm + sem == 0) {
25456d5d 1237 msg = shm = sem = global = 1;
2916afa3 1238 if (show_time || show_creat || id != -1)
62eea9ce 1239 errx(EXIT_FAILURE, _("--global is mutually exclusive with --creator, --id and --time"));
8f405a5b 1240 }
25456d5d
KZ
1241 if (global) {
1242 add_column(columns, ncolumns++, COL_RESOURCE);
1243 add_column(columns, ncolumns++, COL_DESC);
1244 add_column(columns, ncolumns++, COL_LIMIT);
1245 add_column(columns, ncolumns++, COL_USED);
1246 add_column(columns, ncolumns++, COL_USEPERC);
1247 LOWER = COLDESC_IDX_SUM_FIRST;
1248 UPPER = COLDESC_IDX_SUM_LAST;
1249 }
9d20ffda 1250
2916afa3
KZ
1251 /* default to pretty-print if --id specified */
1252 if (id != -1 && !ctl->outmode)
1253 ctl->outmode = OUT_PRETTY;
1254
c8b47062 1255 if (!ctl->time_mode)
d7500c6a 1256 ctl->time_mode = ctl->outmode == OUT_PRETTY ? TIME_FULL : TIME_SHORT;
c8b47062 1257
2916afa3 1258 if (ctl->outmode == OUT_PRETTY && !(optarg || show_creat || show_time)) {
e0154173
KZ
1259 /* all columns for lsipc --<RESOURCE> --id <ID> */
1260 for (ncolumns = 0, i = 0; i < ARRAY_SIZE(coldescs); i++)
1261 columns[ncolumns++] = i;
9d20ffda 1262 } else {
e0154173
KZ
1263 if (show_creat) {
1264 add_column(columns, ncolumns++, COL_CUID);
1265 add_column(columns, ncolumns++, COL_CGID);
1266 add_column(columns, ncolumns++, COL_UID);
1267 add_column(columns, ncolumns++, COL_GID);
1268 }
1269 if (msg && show_time) {
1270 add_column(columns, ncolumns++, COL_SEND);
1271 add_column(columns, ncolumns++, COL_RECV);
1272 add_column(columns, ncolumns++, COL_CTIME);
1273 }
1274 if (shm && show_time) {
1275 /* keep "COMMAND" as last column */
1276 size_t cmd = columns[ncolumns - 1] == COL_COMMAND;
1277
1278 if (cmd)
1279 ncolumns--;
1280 add_column(columns, ncolumns++, COL_ATTACH);
1281 add_column(columns, ncolumns++, COL_DETACH);
1282 if (cmd)
be475287 1283 add_column(columns, ncolumns++, COL_COMMAND);
e0154173
KZ
1284 }
1285 if (sem && show_time) {
1286 add_column(columns, ncolumns++, COL_OTIME);
1287 add_column(columns, ncolumns++, COL_CTIME);
9d20ffda
KZ
1288 }
1289 }
1290
e0154173
KZ
1291 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
1292 &ncolumns, column_name_to_id) < 0)
1293 return EXIT_FAILURE;
1294
9d20ffda
KZ
1295 tb = setup_table(ctl);
1296 if (!tb)
1297 return EXIT_FAILURE;
5de8fcfd
KZ
1298
1299 if (global)
1300 scols_table_set_name(tb, "ipclimits");
1301
9d20ffda
KZ
1302 if (msg) {
1303 if (global)
1304 do_msg_global(tb);
1305 else
1306 do_msg(id, ctl, tb);
32cfe498
KZ
1307 }
1308 if (shm) {
9d20ffda
KZ
1309 if (global)
1310 do_shm_global(tb);
1311 else
1312 do_shm(id, ctl, tb);
32cfe498
KZ
1313 }
1314 if (sem) {
9d20ffda
KZ
1315 if (global)
1316 do_sem_global(tb);
1317 else
32cfe498 1318 do_sem(id, ctl, tb);
9d20ffda
KZ
1319 }
1320
d7500c6a 1321 print_table(ctl, tb);
9d20ffda
KZ
1322
1323 scols_unref_table(tb);
1324 free(ctl);
1325
1326 return EXIT_SUCCESS;
1327}
1328