]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/lsipc.c
tests: fix ts_option helpers
[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>
28#include <features.h>
29#include <getopt.h>
30#include <sys/time.h>
31#include <unistd.h>
32
33#include <libsmartcols.h>
34
35#include "c.h"
36#include "nls.h"
37#include "closestream.h"
38#include "strutils.h"
39#include "optutils.h"
40#include "xalloc.h"
be475287 41#include "procutils.h"
9d20ffda
KZ
42#include "ipcutils.h"
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
9d20ffda
KZ
252static int parse_time_mode(const char *optarg)
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++) {
266 if (strcmp(timefmts[i].name, optarg) == 0)
267 return timefmts[i].val;
268 }
269 errx(EXIT_FAILURE, _("unknown time format: %s"), optarg);
270}
271
272static void __attribute__ ((__noreturn__)) usage(FILE * out)
273{
274 size_t i;
275
276 fputs(USAGE_HEADER, out);
9d20ffda
KZ
277 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
278
279 fputs(USAGE_SEPARATOR, out);
280 fputs(_("Show information on IPC facilities.\n"), out);
281
9d20ffda
KZ
282 fputs(USAGE_SEPARATOR, out);
283 fputs(_("Resource options:\n"), out);
284 fputs(_(" -m, --shmems shared memory segments\n"), out);
285 fputs(_(" -q, --queues message queues\n"), out);
286 fputs(_(" -s, --semaphores semaphores\n"), out);
32cfe498 287 fputs(_(" -g, --global info about system-wide usage (may be used with -m, -q and -s)\n"), out);
9d20ffda
KZ
288 fputs(_(" -i, --id <id> print details on resource identified by <id>\n"), out);
289
470a7332 290 fputs(USAGE_OPTIONS, out);
9d20ffda
KZ
291 fputs(_(" --noheadings don't print headings\n"), out);
292 fputs(_(" --notruncate don't truncate output\n"), out);
293 fputs(_(" --time-format=<type> display dates in short, full or iso format\n"), out);
294 fputs(_(" -b, --bytes print SIZE in bytes rather than in human readable format\n"), out);
295 fputs(_(" -c, --creator show creator and owner\n"), out);
296 fputs(_(" -e, --export display in an export-able output format\n"), out);
9d20ffda
KZ
297 fputs(_(" -J, --json use the JSON output format\n"), out);
298 fputs(_(" -n, --newline display each piece of information on a new line\n"), out);
2916afa3 299 fputs(_(" -l, --list force list output format (for example with --id)\n"), out);
9d20ffda
KZ
300 fputs(_(" -o, --output[=<list>] define the columns to output\n"), out);
301 fputs(_(" -P, --numeric-perms print numeric permissions (PERMS column)\n"), out);
302 fputs(_(" -r, --raw display in raw mode\n"), out);
303 fputs(_(" -t, --time show attach, detach and change times\n"), out);
2a7150ac
KZ
304
305 fputs(USAGE_SEPARATOR, out);
306 fputs(USAGE_HELP, out);
307 fputs(USAGE_VERSION, out);
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
329 fprintf(out, USAGE_MAN_TAIL("lsipc(1)"));
9d20ffda
KZ
330 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
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)
338 errx(EXIT_FAILURE, _("failed to initialize output table"));
339 if (ctl->noheadings)
340 scols_table_enable_noheadings(table, 1);
9d20ffda 341
d7500c6a 342 switch(ctl->outmode) {
9d20ffda
KZ
343 case OUT_NEWLINE:
344 scols_table_set_column_separator(table, "\n");
345 /* fallthrough */
346 case OUT_EXPORT:
347 scols_table_enable_export(table, 1);
348 break;
9d20ffda
KZ
349 case OUT_RAW:
350 scols_table_enable_raw(table, 1);
351 break;
352 case OUT_PRETTY:
353 scols_table_enable_noheadings(table, 1);
5de8fcfd
KZ
354 break;
355 case OUT_JSON:
356 scols_table_enable_json(table, 1);
357 break;
9d20ffda
KZ
358 default:
359 break;
360 }
624de257
KZ
361 return table;
362}
363
364static struct libscols_table *setup_table(struct lsipc_control *ctl)
365{
366 struct libscols_table *table = new_table(ctl);
367 size_t n;
9d20ffda 368
e0154173 369 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
370 int flags = coldescs[columns[n]].flag;
371
372 if (ctl->notrunc)
373 flags &= ~SCOLS_FL_TRUNC;
374
375 if (!scols_table_new_column(table,
376 coldescs[columns[n]].name,
377 coldescs[columns[n]].whint,
378 flags))
379 goto fail;
9d20ffda
KZ
380 }
381 return table;
382fail:
383 scols_unref_table(table);
384 return NULL;
385}
386
387static int print_pretty(struct libscols_table *table)
388{
389 struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD);
390 struct libscols_column *col;
391 struct libscols_cell *data;
392 struct libscols_line *ln;
624de257 393 const char *hstr, *dstr;
9d20ffda
KZ
394 int n = 0;
395
396 ln = scols_table_get_line(table, 0);
397 while (!scols_table_next_column(table, itr, &col)) {
398
399 data = scols_line_get_cell(ln, n);
400
401 hstr = N_(coldescs[columns[n]].pretty_name);
402 dstr = scols_cell_get_data(data);
403
404 if (dstr)
405 printf("%s:%*c%-36s\n", hstr, 35 - (int)strlen(hstr), ' ', dstr);
406 ++n;
407 }
408
409 /* this is used to pretty-print detailed info about a semaphore array */
410 if (ln) {
624de257
KZ
411 struct libscols_table *subtab = scols_line_get_userdata(ln);
412 if (subtab) {
413 printf(_("Elements:\n\n"));
414 scols_print_table(subtab);
9d20ffda
KZ
415 }
416 }
417
418 scols_free_iter(itr);
419 return 0;
420
421}
422
d7500c6a 423static int print_table(struct lsipc_control *ctl, struct libscols_table *tb)
9d20ffda 424{
d7500c6a 425 if (ctl->outmode == OUT_PRETTY)
9d20ffda
KZ
426 print_pretty(tb);
427 else
428 scols_print_table(tb);
429 return 0;
430}
431static struct timeval now;
432
433static int date_is_today(time_t t)
434{
435 if (now.tv_sec == 0)
436 gettimeofday(&now, NULL);
437 return t / (3600 * 24) == now.tv_sec / (3600 * 24);
438}
439
440static int date_is_thisyear(time_t t)
441{
442 if (now.tv_sec == 0)
443 gettimeofday(&now, NULL);
444 return t / (3600 * 24 * 365) == now.tv_sec / (3600 * 24 * 365);
445}
446
447static char *make_time(int mode, time_t time)
448{
449 char *s;
450 struct tm tm;
451 char buf[64] = {0};
452
453 localtime_r(&time, &tm);
454
455 switch(mode) {
456 case TIME_FULL:
457 asctime_r(&tm, buf);
458 if (*(s = buf + strlen(buf) - 1) == '\n')
459 *s = '\0';
460 break;
461 case TIME_SHORT:
462 if (date_is_today(time))
463 strftime(buf, sizeof(buf), "%H:%M", &tm);
464 else if (date_is_thisyear(time))
465 strftime(buf, sizeof(buf), "%b%d", &tm);
466 else
467 strftime(buf, sizeof(buf), "%Y-%b%d", &tm);
468 break;
469 case TIME_ISO:
470 strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &tm);
471 break;
472 default:
473 errx(EXIT_FAILURE, _("unsupported time type"));
474 }
475 return xstrdup(buf);
476}
477
32cfe498 478static void global_set_data(struct libscols_table *tb, const char *resource,
a4839bc7 479 const char *desc, uintmax_t used, uintmax_t limit, int usage)
32cfe498
KZ
480{
481 struct libscols_line *ln;
e0154173 482 size_t n;
32cfe498
KZ
483
484 ln = scols_table_new_line(tb, NULL);
485 if (!ln)
486 err_oom();
487
488 for (n = 0; n < ncolumns; n++) {
489 int rc = 0;
490 char *arg = NULL;
491
492 switch (columns[n]) {
493 case COL_RESOURCE:
494 rc = scols_line_set_data(ln, n, resource);
495 break;
496 case COL_DESC:
497 rc = scols_line_set_data(ln, n, desc);
498 break;
499 case COL_USED:
a4839bc7
KZ
500 if (usage) {
501 xasprintf(&arg, "%ju", used);
502 rc = scols_line_refer_data(ln, n, arg);
503 } else
504 rc = scols_line_set_data(ln, n, "-");
32cfe498 505 break;
1a311071 506 case COL_USEPERC:
a4839bc7
KZ
507 if (usage) {
508 xasprintf(&arg, "%2.2f%%", (double) used / limit * 100);
509 rc = scols_line_refer_data(ln, n, arg);
510 } else
511 rc = scols_line_set_data(ln, n, "-");
1a311071 512 break;
32cfe498
KZ
513 case COL_LIMIT:
514 xasprintf(&arg, "%ju", limit);
cdb4a946 515 rc = scols_line_refer_data(ln, n, arg);
32cfe498
KZ
516 break;
517 }
518
519 if (rc != 0)
520 err(EXIT_FAILURE, _("failed to set data"));
32cfe498
KZ
521 }
522}
523
624de257
KZ
524static void setup_sem_elements_columns(struct libscols_table *tb)
525{
526 scols_table_set_name(tb, "elements");
527 if (!scols_table_new_column(tb, "SEMNUM", 0, SCOLS_FL_RIGHT))
528 err_oom();
529 if (!scols_table_new_column(tb, "VALUE", 0, SCOLS_FL_RIGHT))
530 err_oom();
531 if (!scols_table_new_column(tb, "NCOUNT", 0, SCOLS_FL_RIGHT))
532 err_oom();
533 if (!scols_table_new_column(tb, "ZCOUNT", 0, SCOLS_FL_RIGHT))
534 err_oom();
535 if (!scols_table_new_column(tb, "PID", 0, SCOLS_FL_RIGHT))
536 err_oom();
537 if (!scols_table_new_column(tb, "COMMAND", 0, SCOLS_FL_RIGHT))
538 err_oom();
539}
540
9d20ffda
KZ
541static void do_sem(int id, struct lsipc_control *ctl, struct libscols_table *tb)
542{
9d20ffda
KZ
543 struct libscols_line *ln;
544 struct passwd *pw = NULL, *cpw = NULL;
545 struct group *gr = NULL, *cgr = NULL;
546 struct sem_data *semds, *semdsp;
cdb4a946 547 char *arg = NULL;
9d20ffda 548
5de8fcfd
KZ
549 scols_table_set_name(tb, "semaphores");
550
9d20ffda
KZ
551 if (ipc_sem_get_info(id, &semds) < 1) {
552 if (id > -1)
553 warnx(_("id %d not found"), id);
554 return;
555 }
556 for (semdsp = semds; semdsp->next != NULL || id > -1; semdsp = semdsp->next) {
e0154173 557 size_t n;
9d20ffda
KZ
558 ln = scols_table_new_line(tb, NULL);
559
e0154173
KZ
560 for (n = 0; n < ncolumns; n++) {
561 int rc = 0;
9d20ffda 562 switch (columns[n]) {
91c92cb5
KZ
563 case COL_KEY:
564 xasprintf(&arg, "0x%08x",semdsp->sem_perm.key);
cdb4a946 565 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
566 break;
567 case COL_ID:
568 xasprintf(&arg, "%d",semdsp->sem_perm.id);
cdb4a946 569 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
570 break;
571 case COL_OWNER:
71b63dc1
KZ
572 arg = get_username(&pw, semdsp->sem_perm.uid);
573 if (!arg)
91c92cb5 574 xasprintf(&arg, "%u", semdsp->sem_perm.uid);
cdb4a946 575 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
576 break;
577 case COL_PERMS:
578 if (ctl->numperms)
579 xasprintf(&arg, "%#o", semdsp->sem_perm.mode & 0777);
580 else {
581 arg = xmalloc(11);
582 strmode(semdsp->sem_perm.mode & 0777, arg);
583 }
cdb4a946 584 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
585 break;
586 case COL_CUID:
587 xasprintf(&arg, "%u", semdsp->sem_perm.cuid);
cdb4a946 588 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
589 break;
590 case COL_CUSER:
71b63dc1
KZ
591 arg = get_username(&cpw, semdsp->sem_perm.cuid);
592 if (arg)
cdb4a946 593 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
594 break;
595 case COL_CGID:
71b63dc1 596 xasprintf(&arg, "%u", semdsp->sem_perm.cgid);
cdb4a946 597 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
598 break;
599 case COL_CGROUP:
71b63dc1
KZ
600 arg = get_groupname(&cgr, semdsp->sem_perm.cgid);
601 if (arg)
cdb4a946 602 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
603 break;
604 case COL_UID:
605 xasprintf(&arg, "%u", semdsp->sem_perm.uid);
cdb4a946 606 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
607 break;
608 case COL_USER:
71b63dc1
KZ
609 arg = get_username(&pw, semdsp->sem_perm.uid);
610 if (arg)
cdb4a946 611 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
612 break;
613 case COL_GID:
71b63dc1 614 xasprintf(&arg, "%u", semdsp->sem_perm.gid);
cdb4a946 615 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
616 break;
617 case COL_GROUP:
71b63dc1
KZ
618 arg = get_groupname(&gr, semdsp->sem_perm.gid);
619 if (arg)
cdb4a946 620 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
621 break;
622 case COL_CTIME:
623 if (semdsp->sem_ctime != 0) {
cdb4a946
KZ
624 rc = scols_line_refer_data(ln, n,
625 make_time(ctl->time_mode,
91c92cb5 626 (time_t)semdsp->sem_ctime));
91c92cb5
KZ
627 }
628 break;
629 case COL_NSEMS:
630 xasprintf(&arg, "%ju", semdsp->sem_nsems);
cdb4a946 631 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
632 break;
633 case COL_OTIME:
634 if (semdsp->sem_otime != 0) {
cdb4a946
KZ
635 rc = scols_line_refer_data(ln, n,
636 make_time(ctl->time_mode,
91c92cb5 637 (time_t)semdsp->sem_otime));
91c92cb5
KZ
638 }
639 break;
9d20ffda
KZ
640 }
641 if (rc != 0)
642 err(EXIT_FAILURE, _("failed to set data"));
9d20ffda
KZ
643 arg = NULL;
644 }
9d20ffda 645
624de257
KZ
646 if (id > -1 && semds->sem_nsems) {
647 /* Create extra table with ID specific semaphore elements */
648 struct libscols_table *sub = new_table(ctl);
649 size_t i;
fadf556a 650 int rc = 0;
624de257
KZ
651
652 scols_table_enable_noheadings(sub, 0);
653 setup_sem_elements_columns(sub);
9d20ffda
KZ
654
655 for (i = 0; i < semds->sem_nsems; i++) {
656 struct sem_elem *e = &semds->elements[i];
624de257
KZ
657 struct libscols_line *sln = scols_table_new_line(sub, NULL);
658
659 /* SEMNUM */
660 xasprintf(&arg, "%zu", i);
fadf556a
KZ
661 rc = scols_line_refer_data(sln, 0, arg);
662 if (rc)
663 break;
624de257
KZ
664
665 /* VALUE */
666 xasprintf(&arg, "%d", e->semval);
fadf556a
KZ
667 rc = scols_line_refer_data(sln, 1, arg);
668 if (rc)
669 break;
624de257
KZ
670
671 /* NCOUNT */
672 xasprintf(&arg, "%d", e->ncount);
fadf556a
KZ
673 rc = scols_line_refer_data(sln, 2, arg);
674 if (rc)
675 break;
624de257
KZ
676
677 /* ZCOUNT */
678 xasprintf(&arg, "%d", e->zcount);
fadf556a
KZ
679 rc = scols_line_refer_data(sln, 3, arg);
680 if (rc)
681 break;
624de257
KZ
682
683 /* PID */
684 xasprintf(&arg, "%d", e->pid);
fadf556a
KZ
685 rc = scols_line_refer_data(sln, 4, arg);
686 if (rc)
687 break;
624de257
KZ
688
689 /* COMMAND */
690 arg = proc_get_command(e->pid);
fadf556a
KZ
691 rc = scols_line_refer_data(sln, 5, arg);
692 if (rc)
693 break;
9d20ffda 694 }
624de257 695
fadf556a
KZ
696 if (rc != 0)
697 err(EXIT_FAILURE, _("failed to set data"));
698
624de257 699 scols_line_set_userdata(ln, (void *)sub);
9d20ffda
KZ
700 break;
701 }
702 }
703 ipc_sem_free_info(semds);
704}
705
706static void do_sem_global(struct libscols_table *tb)
707{
708 struct sem_data *semds, *semdsp;
709 struct ipc_limits lim;
32cfe498 710 int nsems = 0, nsets = 0;
9d20ffda 711
9d20ffda
KZ
712 ipc_sem_get_limits(&lim);
713
32cfe498
KZ
714 if (ipc_sem_get_info(-1, &semds) > 0) {
715 for (semdsp = semds; semdsp->next != NULL; semdsp = semdsp->next) {
716 ++nsets;
717 nsems += semds->sem_nsems;
718 }
719 ipc_sem_free_info(semds);
9d20ffda 720 }
9d20ffda 721
a4839bc7
KZ
722 global_set_data(tb, "SEMMNI", _("Number of semaphore identifiers"), nsets, lim.semmni, 1);
723 global_set_data(tb, "SEMMNS", _("Total number of semaphores"), nsems, lim.semmns, 1);
724 global_set_data(tb, "SEMMSL", _("Max semaphores per semaphore set."), 0, lim.semmsl, 0);
725 global_set_data(tb, "SEMOPM", _("Max number of operations per semop(2)"), 0, lim.semopm, 0);
726 global_set_data(tb, "SEMVMX", _("Semaphore max value"), 0, lim.semvmx, 0);
9d20ffda
KZ
727}
728
729static void do_msg(int id, struct lsipc_control *ctl, struct libscols_table *tb)
730{
9d20ffda
KZ
731 struct libscols_line *ln;
732 struct passwd *pw = NULL;
733 struct group *gr = NULL;
734 struct msg_data *msgds, *msgdsp;
cdb4a946 735 char *arg = NULL;
9d20ffda
KZ
736
737 if (ipc_msg_get_info(id, &msgds) < 1) {
738 if (id > -1)
739 warnx(_("id %d not found"), id);
740 return;
741 }
5de8fcfd 742 scols_table_set_name(tb, "messages");
9d20ffda
KZ
743
744 for (msgdsp = msgds; msgdsp->next != NULL || id > -1 ; msgdsp = msgdsp->next) {
e0154173 745 size_t n;
9d20ffda
KZ
746 ln = scols_table_new_line(tb, NULL);
747
748 /* no need to call getpwuid() for the same user */
749 if (!(pw && pw->pw_uid == msgdsp->msg_perm.uid))
750 pw = getpwuid(msgdsp->msg_perm.uid);
751
752 /* no need to call getgrgid() for the same user */
753 if (!(gr && gr->gr_gid == msgdsp->msg_perm.gid))
754 gr = getgrgid(msgdsp->msg_perm.gid);
755
e0154173 756 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
757 int rc = 0;
758
759 switch (columns[n]) {
91c92cb5
KZ
760 case COL_KEY:
761 xasprintf(&arg, "0x%08x",msgdsp->msg_perm.key);
cdb4a946 762 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
763 break;
764 case COL_ID:
765 xasprintf(&arg, "%d",msgdsp->msg_perm.id);
cdb4a946 766 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
767 break;
768 case COL_OWNER:
71b63dc1
KZ
769 arg = get_username(&pw, msgdsp->msg_perm.uid);
770 if (!arg)
91c92cb5 771 xasprintf(&arg, "%u", msgdsp->msg_perm.uid);
cdb4a946 772 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
773 break;
774 case COL_PERMS:
775 if (ctl->numperms)
776 xasprintf(&arg, "%#o", msgdsp->msg_perm.mode & 0777);
777 else {
778 arg = xmalloc(11);
779 strmode(msgdsp->msg_perm.mode & 0777, arg);
cdb4a946 780 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
781 }
782 break;
783 case COL_CUID:
784 xasprintf(&arg, "%u", msgdsp->msg_perm.cuid);
cdb4a946 785 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
786 break;
787 case COL_CUSER:
71b63dc1
KZ
788 arg = get_username(&pw, msgdsp->msg_perm.cuid);
789 if (arg)
cdb4a946 790 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
791 break;
792 case COL_CGID:
793 xasprintf(&arg, "%u", msgdsp->msg_perm.cuid);
cdb4a946 794 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
795 break;
796 case COL_CGROUP:
71b63dc1
KZ
797 arg = get_groupname(&gr, msgdsp->msg_perm.cgid);
798 if (arg)
cdb4a946 799 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
800 break;
801 case COL_UID:
802 xasprintf(&arg, "%u", msgdsp->msg_perm.uid);
cdb4a946 803 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
804 break;
805 case COL_USER:
71b63dc1
KZ
806 arg = get_username(&pw, msgdsp->msg_perm.uid);
807 if (arg)
cdb4a946 808 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
809 break;
810 case COL_GID:
811 xasprintf(&arg, "%u", msgdsp->msg_perm.gid);
cdb4a946 812 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
813 break;
814 case COL_GROUP:
71b63dc1
KZ
815 arg = get_groupname(&gr,msgdsp->msg_perm.gid);
816 if (arg)
cdb4a946 817 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
818 break;
819 case COL_CTIME:
cdb4a946
KZ
820 if (msgdsp->q_ctime != 0)
821 rc = scols_line_refer_data(ln, n,
822 make_time(ctl->time_mode,
91c92cb5 823 (time_t)msgdsp->q_ctime));
91c92cb5
KZ
824 break;
825 case COL_USEDBYTES:
826 xasprintf(&arg, "%ju", msgdsp->q_cbytes);
cdb4a946 827 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
828 break;
829 case COL_MSGS:
830 xasprintf(&arg, "%ju", msgdsp->q_qnum);
cdb4a946 831 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
832 break;
833 case COL_SEND:
cdb4a946
KZ
834 if (msgdsp->q_stime != 0)
835 rc = scols_line_refer_data(ln, n,
836 make_time(ctl->time_mode,
91c92cb5 837 (time_t)msgdsp->q_stime));
91c92cb5
KZ
838 break;
839 case COL_RECV:
cdb4a946
KZ
840 if (msgdsp->q_rtime != 0)
841 rc = scols_line_refer_data(ln, n,
842 make_time(ctl->time_mode,
91c92cb5 843 (time_t)msgdsp->q_rtime));
91c92cb5
KZ
844 break;
845 case COL_LSPID:
846 xasprintf(&arg, "%u", msgdsp->q_lspid);
cdb4a946 847 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
848 break;
849 case COL_LRPID:
850 xasprintf(&arg, "%u", msgdsp->q_lrpid);
cdb4a946 851 rc = scols_line_refer_data(ln, n, arg);
91c92cb5 852 break;
9d20ffda
KZ
853 }
854 if (rc != 0)
855 err(EXIT_FAILURE, _("failed to set data"));
9d20ffda
KZ
856 arg = NULL;
857 }
858 if (id > -1)
859 break;
860 }
861 ipc_msg_free_info(msgds);
862}
863
32cfe498 864
9d20ffda
KZ
865static void do_msg_global(struct libscols_table *tb)
866{
867 struct msg_data *msgds, *msgdsp;
868 struct ipc_limits lim;
32cfe498 869 int msgqs = 0;
9d20ffda 870
9d20ffda
KZ
871 ipc_msg_get_limits(&lim);
872
32cfe498
KZ
873 /* count number of used queues */
874 if (ipc_msg_get_info(-1, &msgds) > 0) {
875 for (msgdsp = msgds; msgdsp->next != NULL; msgdsp = msgdsp->next)
876 ++msgqs;
877 ipc_msg_free_info(msgds);
9d20ffda
KZ
878 }
879
a4839bc7
KZ
880 global_set_data(tb, "MSGMNI", _("Number of message queues"), msgqs, lim.msgmni, 1);
881 global_set_data(tb, "MSGMAX", _("Max size of message (bytes)"), 0, lim.msgmax, 0);
882 global_set_data(tb, "MSGMNB", _("Default max size of queue (bytes)"), 0, lim.msgmnb, 0);
9d20ffda
KZ
883}
884
d8461c4e 885
9d20ffda
KZ
886static void do_shm(int id, struct lsipc_control *ctl, struct libscols_table *tb)
887{
9d20ffda
KZ
888 struct libscols_line *ln;
889 struct passwd *pw = NULL;
890 struct group *gr = NULL;
891 struct shm_data *shmds, *shmdsp;
cdb4a946 892 char *arg = NULL;
9d20ffda
KZ
893
894 if (ipc_shm_get_info(id, &shmds) < 1) {
895 if (id > -1)
896 warnx(_("id %d not found"), id);
897 return;
898 }
899
5de8fcfd
KZ
900 scols_table_set_name(tb, "sharedmemory");
901
9d20ffda 902 for (shmdsp = shmds; shmdsp->next != NULL || id > -1 ; shmdsp = shmdsp->next) {
e0154173 903 size_t n;
9d20ffda 904 ln = scols_table_new_line(tb, NULL);
32cfe498
KZ
905 if (!ln)
906 err_oom();
9d20ffda 907
e0154173 908 for (n = 0; n < ncolumns; n++) {
9d20ffda
KZ
909 int rc = 0;
910
911 switch (columns[n]) {
91c92cb5
KZ
912 case COL_KEY:
913 xasprintf(&arg, "0x%08x",shmdsp->shm_perm.key);
cdb4a946 914 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
915 break;
916 case COL_ID:
917 xasprintf(&arg, "%d",shmdsp->shm_perm.id);
cdb4a946 918 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
919 break;
920 case COL_OWNER:
d8461c4e
KZ
921 arg = get_username(&pw, shmdsp->shm_perm.uid);
922 if (!arg)
7458c061 923 xasprintf(&arg, "%u", shmdsp->shm_perm.uid);
cdb4a946 924 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
925 break;
926 case COL_PERMS:
927 if (ctl->numperms)
928 xasprintf(&arg, "%#o", shmdsp->shm_perm.mode & 0777);
929 else {
930 arg = xmalloc(11);
931 strmode(shmdsp->shm_perm.mode & 0777, arg);
932 }
cdb4a946 933 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
934 break;
935 case COL_CUID:
936 xasprintf(&arg, "%u", shmdsp->shm_perm.cuid);
cdb4a946 937 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
938 break;
939 case COL_CUSER:
d8461c4e
KZ
940 arg = get_username(&pw, shmdsp->shm_perm.cuid);
941 if (arg)
cdb4a946 942 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
943 break;
944 case COL_CGID:
945 xasprintf(&arg, "%u", shmdsp->shm_perm.cuid);
cdb4a946 946 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
947 break;
948 case COL_CGROUP:
d8461c4e
KZ
949 arg = get_groupname(&gr, shmdsp->shm_perm.cgid);
950 if (arg)
cdb4a946 951 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
952 break;
953 case COL_UID:
954 xasprintf(&arg, "%u", shmdsp->shm_perm.uid);
cdb4a946 955 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
956 break;
957 case COL_USER:
d8461c4e
KZ
958 arg = get_username(&pw, shmdsp->shm_perm.uid);
959 if (arg)
cdb4a946 960 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
961 break;
962 case COL_GID:
963 xasprintf(&arg, "%u", shmdsp->shm_perm.gid);
cdb4a946 964 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
965 break;
966 case COL_GROUP:
d8461c4e
KZ
967 arg = get_groupname(&gr, shmdsp->shm_perm.gid);
968 if (arg)
cdb4a946 969 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
970 break;
971 case COL_CTIME:
cdb4a946
KZ
972 if (shmdsp->shm_ctim != 0)
973 rc = scols_line_refer_data(ln, n,
974 make_time(ctl->time_mode,
91c92cb5 975 (time_t)shmdsp->shm_ctim));
91c92cb5
KZ
976 break;
977 case COL_SIZE:
978 if (ctl->bytes)
979 xasprintf(&arg, "%ju", shmdsp->shm_segsz);
980 else
981 arg = size_to_human_string(SIZE_SUFFIX_1LETTER, shmdsp->shm_segsz);
cdb4a946 982 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
983 break;
984 case COL_NATTCH:
985 xasprintf(&arg, "%ju", shmdsp->shm_nattch);
cdb4a946 986 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
987 break;
988 case COL_STATUS: {
989 int comma = 0;
990 size_t offt = 0;
9380fbef
KZ
991
992 free(arg);
91c92cb5
KZ
993 arg = xcalloc(1, sizeof(char) * strlen(_("dest"))
994 + strlen(_("locked"))
995 + strlen(_("hugetlb"))
996 + strlen(_("noreserve")) + 4);
21ce5a5d 997#ifdef SHM_DEST
91c92cb5
KZ
998 if (shmdsp->shm_perm.mode & SHM_DEST) {
999 offt += sprintf(arg, "%s", _("dest"));
1000 comma++;
9d20ffda 1001 }
21ce5a5d
KZ
1002#endif
1003#ifdef SHM_LOCKED
91c92cb5
KZ
1004 if (shmdsp->shm_perm.mode & SHM_LOCKED) {
1005 if (comma)
1006 arg[offt++] = ',';
1007 offt += sprintf(arg + offt, "%s", _("locked"));
9d20ffda 1008 }
21ce5a5d
KZ
1009#endif
1010#ifdef SHM_HUGETLB
91c92cb5
KZ
1011 if (shmdsp->shm_perm.mode & SHM_HUGETLB) {
1012 if (comma)
1013 arg[offt++] = ',';
1014 offt += sprintf(arg + offt, "%s", _("hugetlb"));
1015 }
21ce5a5d
KZ
1016#endif
1017#ifdef SHM_NORESERVE
91c92cb5
KZ
1018 if (shmdsp->shm_perm.mode & SHM_NORESERVE) {
1019 if (comma)
1020 arg[offt++] = ',';
9380fbef 1021 sprintf(arg + offt, "%s", _("noreserve"));
9d20ffda 1022 }
21ce5a5d 1023#endif
cdb4a946 1024 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1025 }
1026 break;
1027 case COL_ATTACH:
cdb4a946
KZ
1028 if (shmdsp->shm_atim != 0)
1029 rc = scols_line_refer_data(ln, n,
1030 make_time(ctl->time_mode,
91c92cb5 1031 (time_t)shmdsp->shm_atim));
91c92cb5
KZ
1032 break;
1033 case COL_DETACH:
cdb4a946
KZ
1034 if (shmdsp->shm_dtim != 0)
1035 rc = scols_line_refer_data(ln, n,
1036 make_time(ctl->time_mode,
91c92cb5 1037 (time_t)shmdsp->shm_dtim));
91c92cb5
KZ
1038 break;
1039 case COL_CPID:
1040 xasprintf(&arg, "%u", shmdsp->shm_cprid);
cdb4a946 1041 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1042 break;
1043 case COL_LPID:
1044 xasprintf(&arg, "%u", shmdsp->shm_lprid);
cdb4a946 1045 rc = scols_line_refer_data(ln, n, arg);
91c92cb5
KZ
1046 break;
1047 case COL_COMMAND:
1048 arg = proc_get_command(shmdsp->shm_cprid);
cdb4a946 1049 rc = scols_line_refer_data(ln, n, arg);
91c92cb5 1050 break;
9d20ffda
KZ
1051 }
1052 if (rc != 0)
1053 err(EXIT_FAILURE, _("failed to set data"));
9d20ffda
KZ
1054 arg = NULL;
1055 }
1056 if (id > -1)
1057 break;
1058 }
1059 ipc_shm_free_info(shmds);
1060}
1061
1062static void do_shm_global(struct libscols_table *tb)
1063{
1064 struct shm_data *shmds, *shmdsp;
32cfe498 1065 uint64_t nsegs = 0, sum_segsz = 0;
9d20ffda 1066 struct ipc_limits lim;
9d20ffda 1067
9d20ffda
KZ
1068 ipc_shm_get_limits(&lim);
1069
32cfe498
KZ
1070 if (ipc_shm_get_info(-1, &shmds) > 0) {
1071 for (shmdsp = shmds; shmdsp->next != NULL; shmdsp = shmdsp->next) {
1072 ++nsegs;
1073 sum_segsz += shmdsp->shm_segsz;
1074 }
9d20ffda
KZ
1075 }
1076
a4839bc7
KZ
1077 global_set_data(tb, "SHMMNI", _("Shared memory segments"), nsegs, lim.shmmni, 1);
1078 global_set_data(tb, "SHMALL", _("Shared memory pages"), sum_segsz / getpagesize(), lim.shmall, 1);
1079 global_set_data(tb, "SHMMAX", _("Max size of shared memory segment (bytes)"), 0, lim.shmmax, 0);
1080 global_set_data(tb, "SHMMIN", _("Min size of shared memory segment (bytes)"), 0, lim.shmmin, 0);
9d20ffda
KZ
1081
1082 ipc_shm_free_info(shmds);
1083}
1084
1085int main(int argc, char *argv[])
1086{
e0154173 1087 int opt, msg = 0, sem = 0, shm = 0, id = -1;
9d20ffda
KZ
1088 int show_time = 0, show_creat = 0, global = 0;
1089 size_t i;
1090 struct lsipc_control *ctl = xcalloc(1, sizeof(struct lsipc_control));
1091 static struct libscols_table *tb;
e0154173 1092 char *outarg = NULL;
9d20ffda
KZ
1093
1094 /* long only options. */
1095 enum {
1096 OPT_NOTRUNC = CHAR_MAX + 1,
1097 OPT_NOHEAD,
2a7150ac 1098 OPT_TIME_FMT
9d20ffda
KZ
1099 };
1100
1101 static const struct option longopts[] = {
1102 { "bytes", no_argument, 0, 'b' },
9d20ffda
KZ
1103 { "creator", no_argument, 0, 'c' },
1104 { "export", no_argument, 0, 'e' },
1105 { "global", no_argument, 0, 'g' },
1106 { "help", no_argument, 0, 'h' },
1107 { "id", required_argument, 0, 'i' },
1108 { "json", no_argument, 0, 'J' },
2916afa3 1109 { "list", no_argument, 0, 'l' },
9d20ffda
KZ
1110 { "newline", no_argument, 0, 'n' },
1111 { "noheadings", no_argument, 0, OPT_NOHEAD },
1112 { "notruncate", no_argument, 0, OPT_NOTRUNC },
1113 { "numeric-perms", no_argument, 0, 'P' },
1114 { "output", required_argument, 0, 'o' },
1115 { "pid", no_argument, 0, 'p' },
9d20ffda
KZ
1116 { "queues", no_argument, 0, 'q' },
1117 { "raw", no_argument, 0, 'r' },
1118 { "semaphores", no_argument, 0, 's' },
1119 { "shmems", no_argument, 0, 'm' },
1120 { "time", no_argument, 0, 't' },
1121 { "time-format", required_argument, 0, OPT_TIME_FMT },
1122 { "version", no_argument, 0, 'V' },
1123 {NULL, 0, NULL, 0}
1124 };
1125
1126 static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
2916afa3
KZ
1127 { 'J', 'e', 'l', 'n', 'r' },
1128 { 'g', 'i' },
1129 { 'c', 'o', 't' },
9d20ffda
KZ
1130 { 'm', 'q', 's' },
1131 { 0 }
1132 };
1133 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
1134
1135 setlocale(LC_ALL, "");
1136 bindtextdomain(PACKAGE, LOCALEDIR);
1137 textdomain(PACKAGE);
1138 atexit(close_stdout);
1139
c8b47062 1140 ctl->time_mode = 0;
9d20ffda 1141
624de257
KZ
1142 scols_init_debug(0);
1143
2916afa3 1144 while ((opt = getopt_long(argc, argv, "bceghi:Jlmno:PqrstuV", longopts, NULL)) != -1) {
9d20ffda
KZ
1145
1146 err_exclusive_options(opt, longopts, excl, excl_st);
1147
1148 switch (opt) {
91c92cb5
KZ
1149 case 'b':
1150 ctl->bytes = 1;
1151 break;
1152 case 'i':
1153 id = strtos32_or_err(optarg, _("failed to parse IPC identifier"));
91c92cb5 1154 break;
91c92cb5 1155 case 'e':
d7500c6a 1156 ctl->outmode = OUT_EXPORT;
91c92cb5
KZ
1157 break;
1158 case 'r':
d7500c6a 1159 ctl->outmode = OUT_RAW;
91c92cb5
KZ
1160 break;
1161 case 'o':
1162 outarg = optarg;
1163 break;
1164 case 'g':
1165 global = 1;
2916afa3 1166 break;
91c92cb5
KZ
1167 case 'q':
1168 msg = 1;
1169 add_column(columns, ncolumns++, COL_KEY);
1170 add_column(columns, ncolumns++, COL_ID);
1171 add_column(columns, ncolumns++, COL_PERMS);
1172 add_column(columns, ncolumns++, COL_OWNER);
1173 add_column(columns, ncolumns++, COL_USEDBYTES);
1174 add_column(columns, ncolumns++, COL_MSGS);
1175 add_column(columns, ncolumns++, COL_LSPID);
1176 add_column(columns, ncolumns++, COL_LRPID);
1177 LOWER = COLDESC_IDX_MSG_FIRST;
1178 UPPER = COLDESC_IDX_MSG_LAST;
1179 break;
2916afa3
KZ
1180 case 'l':
1181 ctl->outmode = OUT_LIST;
1182 break;
91c92cb5
KZ
1183 case 'm':
1184 shm = 1;
1185 add_column(columns, ncolumns++, COL_KEY);
1186 add_column(columns, ncolumns++, COL_ID);
1187 add_column(columns, ncolumns++, COL_PERMS);
1188 add_column(columns, ncolumns++, COL_OWNER);
1189 add_column(columns, ncolumns++, COL_SIZE);
1190 add_column(columns, ncolumns++, COL_NATTCH);
1191 add_column(columns, ncolumns++, COL_STATUS);
1192 add_column(columns, ncolumns++, COL_CTIME);
1193 add_column(columns, ncolumns++, COL_CPID);
1194 add_column(columns, ncolumns++, COL_LPID);
1195 add_column(columns, ncolumns++, COL_COMMAND);
1196 LOWER = COLDESC_IDX_SHM_FIRST;
1197 UPPER = COLDESC_IDX_SHM_LAST;
1198 break;
1199 case 'n':
d7500c6a 1200 ctl->outmode = OUT_NEWLINE;
91c92cb5
KZ
1201 break;
1202 case 'P':
1203 ctl->numperms = 1;
1204 break;
1205 case 's':
1206 sem = 1;
1207 add_column(columns, ncolumns++, COL_KEY);
1208 add_column(columns, ncolumns++, COL_ID);
1209 add_column(columns, ncolumns++, COL_PERMS);
1210 add_column(columns, ncolumns++, COL_OWNER);
1211 add_column(columns, ncolumns++, COL_NSEMS);
1212 LOWER = COLDESC_IDX_SEM_FIRST;
1213 UPPER = COLDESC_IDX_SEM_LAST;
1214 break;
1215 case OPT_NOTRUNC:
1216 ctl->notrunc = 1;
1217 break;
1218 case OPT_NOHEAD:
1219 ctl->noheadings = 1;
1220 break;
1221 case OPT_TIME_FMT:
1222 ctl->time_mode = parse_time_mode(optarg);
1223 break;
1224 case 'J':
5de8fcfd 1225 ctl->outmode = OUT_JSON;
91c92cb5
KZ
1226 break;
1227 case 't':
1228 show_time = 1;
1229 break;
1230 case 'c':
1231 show_creat = 1;
1232 break;
1233 case 'h':
1234 usage(stdout);
1235 case 'V':
1236 printf(UTIL_LINUX_VERSION);
1237 return EXIT_SUCCESS;
91c92cb5
KZ
1238 default:
1239 usage(stderr);
9d20ffda
KZ
1240 }
1241 }
1242
25456d5d 1243 /* default is global */
8f405a5b 1244 if (msg + shm + sem == 0) {
25456d5d 1245 msg = shm = sem = global = 1;
2916afa3 1246 if (show_time || show_creat || id != -1)
62eea9ce 1247 errx(EXIT_FAILURE, _("--global is mutually exclusive with --creator, --id and --time"));
8f405a5b 1248 }
25456d5d
KZ
1249 if (global) {
1250 add_column(columns, ncolumns++, COL_RESOURCE);
1251 add_column(columns, ncolumns++, COL_DESC);
1252 add_column(columns, ncolumns++, COL_LIMIT);
1253 add_column(columns, ncolumns++, COL_USED);
1254 add_column(columns, ncolumns++, COL_USEPERC);
1255 LOWER = COLDESC_IDX_SUM_FIRST;
1256 UPPER = COLDESC_IDX_SUM_LAST;
1257 }
9d20ffda 1258
2916afa3
KZ
1259 /* default to pretty-print if --id specified */
1260 if (id != -1 && !ctl->outmode)
1261 ctl->outmode = OUT_PRETTY;
1262
c8b47062 1263 if (!ctl->time_mode)
d7500c6a 1264 ctl->time_mode = ctl->outmode == OUT_PRETTY ? TIME_FULL : TIME_SHORT;
c8b47062 1265
2916afa3 1266 if (ctl->outmode == OUT_PRETTY && !(optarg || show_creat || show_time)) {
e0154173
KZ
1267 /* all columns for lsipc --<RESOURCE> --id <ID> */
1268 for (ncolumns = 0, i = 0; i < ARRAY_SIZE(coldescs); i++)
1269 columns[ncolumns++] = i;
9d20ffda 1270 } else {
e0154173
KZ
1271 if (show_creat) {
1272 add_column(columns, ncolumns++, COL_CUID);
1273 add_column(columns, ncolumns++, COL_CGID);
1274 add_column(columns, ncolumns++, COL_UID);
1275 add_column(columns, ncolumns++, COL_GID);
1276 }
1277 if (msg && show_time) {
1278 add_column(columns, ncolumns++, COL_SEND);
1279 add_column(columns, ncolumns++, COL_RECV);
1280 add_column(columns, ncolumns++, COL_CTIME);
1281 }
1282 if (shm && show_time) {
1283 /* keep "COMMAND" as last column */
1284 size_t cmd = columns[ncolumns - 1] == COL_COMMAND;
1285
1286 if (cmd)
1287 ncolumns--;
1288 add_column(columns, ncolumns++, COL_ATTACH);
1289 add_column(columns, ncolumns++, COL_DETACH);
1290 if (cmd)
be475287 1291 add_column(columns, ncolumns++, COL_COMMAND);
e0154173
KZ
1292 }
1293 if (sem && show_time) {
1294 add_column(columns, ncolumns++, COL_OTIME);
1295 add_column(columns, ncolumns++, COL_CTIME);
9d20ffda
KZ
1296 }
1297 }
1298
e0154173
KZ
1299 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
1300 &ncolumns, column_name_to_id) < 0)
1301 return EXIT_FAILURE;
1302
9d20ffda
KZ
1303 tb = setup_table(ctl);
1304 if (!tb)
1305 return EXIT_FAILURE;
5de8fcfd
KZ
1306
1307 if (global)
1308 scols_table_set_name(tb, "ipclimits");
1309
9d20ffda
KZ
1310 if (msg) {
1311 if (global)
1312 do_msg_global(tb);
1313 else
1314 do_msg(id, ctl, tb);
32cfe498
KZ
1315 }
1316 if (shm) {
9d20ffda
KZ
1317 if (global)
1318 do_shm_global(tb);
1319 else
1320 do_shm(id, ctl, tb);
32cfe498
KZ
1321 }
1322 if (sem) {
9d20ffda
KZ
1323 if (global)
1324 do_sem_global(tb);
1325 else
32cfe498 1326 do_sem(id, ctl, tb);
9d20ffda
KZ
1327 }
1328
d7500c6a 1329 print_table(ctl, tb);
9d20ffda
KZ
1330
1331 scols_unref_table(tb);
1332 free(ctl);
1333
1334 return EXIT_SUCCESS;
1335}
1336