Bump version to 1.32.0
[oweals/busybox.git] / procps / pmap.c
1 /*
2  * pmap implementation for busybox
3  *
4  * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5  * Written by Alexander Shishkin <virtuoso@slind.org>
6  *
7  * Licensed under GPLv2 or later, see the LICENSE file in this source tree
8  * for details.
9  */
10 //config:config PMAP
11 //config:       bool "pmap (6 kb)"
12 //config:       default y
13 //config:       help
14 //config:       Display processes' memory mappings.
15
16 //applet:IF_PMAP(APPLET(pmap, BB_DIR_USR_BIN, BB_SUID_DROP))
17
18 //kbuild:lib-$(CONFIG_PMAP) += pmap.o
19
20 //usage:#define pmap_trivial_usage
21 //usage:       "[-xq] PID..."
22 //usage:#define pmap_full_usage "\n\n"
23 //usage:       "Display process memory usage"
24 //usage:     "\n"
25 //usage:     "\n        -x      Show details"
26 //usage:     "\n        -q      Quiet"
27
28 #include "libbb.h"
29
30 #if ULONG_MAX == 0xffffffff
31 # define TABS "\t"
32 # define AFMT "8"
33 # define DASHES ""
34 #else
35 # define TABS "\t\t"
36 # define AFMT "16"
37 # define DASHES "--------"
38 #endif
39
40 #if ULLONG_MAX == 0xffffffff
41 # define AFMTLL "8"
42 #else
43 # define AFMTLL "16"
44 #endif
45
46 enum {
47         OPT_x = 1 << 0,
48         OPT_q = 1 << 1,
49 };
50
51 static void print_smaprec(struct smaprec *currec, void *data)
52 {
53         unsigned opt = (uintptr_t)data;
54
55         printf("%0" AFMTLL "llx ", currec->smap_start);
56
57         if (opt & OPT_x)
58                 printf("%7lu %7lu %7lu %7lu ",
59                         currec->smap_size,
60                         currec->smap_pss,
61                         currec->private_dirty,
62                         currec->smap_swap);
63         else
64                 printf("%7luK", currec->smap_size);
65
66         printf(" %.4s  %s\n", currec->smap_mode, currec->smap_name);
67 }
68
69 static int procps_get_maps(pid_t pid, unsigned opt)
70 {
71         struct smaprec total;
72         int ret;
73         char buf[256];
74
75         read_cmdline(buf, sizeof(buf), pid, NULL);
76         printf("%u: %s\n", (int)pid, buf);
77
78         if (!(opt & OPT_q) && (opt & OPT_x))
79                 puts("Address" TABS "  Kbytes     PSS   Dirty    Swap  Mode  Mapping");
80
81         memset(&total, 0, sizeof(total));
82
83         ret = procps_read_smaps(pid, &total, print_smaprec, (void*)(uintptr_t)opt);
84         if (ret)
85                 return ret;
86
87         if (!(opt & OPT_q)) {
88                 if (opt & OPT_x)
89                         printf("--------" DASHES "  ------  ------  ------  ------\n"
90                                 "total" TABS " %7lu %7lu %7lu %7lu\n",
91                                 total.smap_size, total.smap_pss, total.private_dirty, total.smap_swap);
92                 else
93                         printf("mapped: %luK\n", total.smap_size);
94         }
95
96         return 0;
97 }
98
99 int pmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
100 int pmap_main(int argc UNUSED_PARAM, char **argv)
101 {
102         unsigned opts;
103         int ret;
104
105         opts = getopt32(argv, "^" "xq" "\0" "-1"); /* min one arg */
106         argv += optind;
107
108         ret = 0;
109         while (*argv) {
110                 pid_t pid = xatoi_positive(*argv++);
111                 /* GNU pmap returns 42 if any of the pids failed */
112                 if (procps_get_maps(pid, opts) != 0)
113                         ret = 42;
114         }
115
116         return ret;
117 }