]>
Commit | Line | Data |
---|---|---|
8fa223da KZ |
1 | /* |
2 | * choom - Change OOM score setting | |
3 | * | |
4 | * Copyright (C) 2018 Karel Zak <kzak@redhat.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it would be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along | |
17 | * with this program; if not, write to the Free Software Foundation, Inc., | |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 | */ | |
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
23 | #include <unistd.h> | |
24 | #include <getopt.h> | |
25 | #include <errno.h> | |
26 | ||
8fa223da KZ |
27 | #include "nls.h" |
28 | #include "c.h" | |
29 | #include "path.h" | |
30 | #include "strutils.h" | |
31 | #include "closestream.h" | |
32 | ||
33 | static void __attribute__((__noreturn__)) usage(void) | |
34 | { | |
35 | FILE *out = stdout; | |
36 | fputs(USAGE_HEADER, out); | |
37 | fprintf(out, | |
38 | _(" %1$s [options] -p pid\n" | |
39 | " %1$s [options] -n number -p pid\n" | |
0c493067 | 40 | " %1$s [options] -n number [--] command [args...]]\n"), |
8fa223da KZ |
41 | program_invocation_short_name); |
42 | ||
43 | fputs(USAGE_SEPARATOR, out); | |
44 | fputs(_("Display and adjust OOM-killer score.\n"), out); | |
45 | ||
46 | fputs(USAGE_OPTIONS, out); | |
47 | fputs(_(" -n, --adjust <num> specify the adjust score value\n"), out); | |
48 | fputs(_(" -p, --pid <num> process ID\n"), out); | |
49 | fputs(USAGE_SEPARATOR, out); | |
50 | printf(USAGE_HELP_OPTIONS(24)); | |
51 | printf(USAGE_MAN_TAIL("choom(1)")); | |
52 | exit(EXIT_SUCCESS); | |
53 | } | |
54 | ||
bd5f7f2e | 55 | static int get_score(struct path_cxt *pc) |
8fa223da | 56 | { |
bd5f7f2e | 57 | int ret; |
8fa223da | 58 | |
bd5f7f2e KZ |
59 | if (ul_path_read_s32(pc, &ret, "oom_score") != 0) |
60 | err(EXIT_FAILURE, _("failed to read OOM score value")); | |
61 | ||
62 | return ret; | |
8fa223da KZ |
63 | } |
64 | ||
bd5f7f2e | 65 | static int get_score_adj(struct path_cxt *pc) |
8fa223da | 66 | { |
bd5f7f2e | 67 | int ret; |
8fa223da | 68 | |
bd5f7f2e KZ |
69 | if (ul_path_read_s32(pc, &ret, "oom_score_adj") != 0) |
70 | err(EXIT_FAILURE, _("failed to read OOM score adjust value")); | |
8fa223da | 71 | |
bd5f7f2e KZ |
72 | return ret; |
73 | } | |
74 | ||
75 | static int set_score_adj(struct path_cxt *pc, int adj) | |
76 | { | |
c455cdb3 | 77 | return ul_path_write_s64(pc, adj, "oom_score_adj"); |
8fa223da KZ |
78 | } |
79 | ||
80 | int main(int argc, char **argv) | |
81 | { | |
82 | pid_t pid = 0; | |
83 | int c, adj = 0, has_adj = 0; | |
bd5f7f2e | 84 | struct path_cxt *pc = NULL; |
8fa223da KZ |
85 | |
86 | static const struct option longopts[] = { | |
87 | { "adjust", required_argument, NULL, 'n' }, | |
88 | { "pid", required_argument, NULL, 'p' }, | |
89 | { "help", no_argument, NULL, 'h' }, | |
90 | { "version", no_argument, NULL, 'V' }, | |
91 | { NULL, 0, NULL, 0 } | |
92 | }; | |
93 | ||
94 | setlocale(LC_ALL, ""); | |
95 | bindtextdomain(PACKAGE, LOCALEDIR); | |
96 | textdomain(PACKAGE); | |
2c308875 | 97 | close_stdout_atexit(); |
8fa223da KZ |
98 | |
99 | while ((c = getopt_long(argc, argv, "hn:p:V", longopts, NULL)) != -1) { | |
100 | switch (c) { | |
101 | case 'p': | |
102 | pid = strtos32_or_err(optarg, _("invalid PID argument")); | |
103 | break; | |
104 | case 'n': | |
105 | adj = strtos32_or_err(optarg, _("invalid adjust argument")); | |
106 | has_adj = 1; | |
107 | break; | |
2c308875 | 108 | |
8fa223da | 109 | case 'V': |
2c308875 | 110 | print_version(EXIT_SUCCESS); |
8fa223da KZ |
111 | case 'h': |
112 | usage(); | |
113 | default: | |
114 | errtryhelp(EXIT_FAILURE); | |
115 | } | |
116 | } | |
117 | ||
118 | if (optind < argc && pid) { | |
119 | warnx(_("invalid argument: %s"), argv[optind]); | |
120 | errtryhelp(EXIT_FAILURE); | |
121 | } | |
122 | if (!pid && argc - optind < 1) { | |
123 | warnx(_("no PID or COMMAND specified")); | |
124 | errtryhelp(EXIT_FAILURE); | |
125 | } | |
126 | if (optind < argc && !has_adj) { | |
127 | warnx(_("no OOM score adjust value specified")); | |
128 | errtryhelp(EXIT_FAILURE); | |
129 | } | |
130 | ||
bd5f7f2e KZ |
131 | pc = ul_new_path("/proc/%d", (int) (pid ? pid : getpid())); |
132 | ||
8fa223da KZ |
133 | /* Show */ |
134 | if (!has_adj) { | |
bd5f7f2e KZ |
135 | printf(_("pid %d's current OOM score: %d\n"), pid, get_score(pc)); |
136 | printf(_("pid %d's current OOM score adjust value: %d\n"), pid, get_score_adj(pc)); | |
8fa223da KZ |
137 | |
138 | /* Change */ | |
139 | } else if (pid) { | |
bd5f7f2e | 140 | int old = get_score_adj(pc); |
8fa223da | 141 | |
bd5f7f2e | 142 | if (set_score_adj(pc, adj)) |
8fa223da KZ |
143 | err(EXIT_FAILURE, _("failed to set score adjust value")); |
144 | ||
145 | printf(_("pid %d's OOM score adjust value changed from %d to %d\n"), pid, old, adj); | |
146 | ||
147 | /* Start new process */ | |
148 | } else { | |
bd5f7f2e | 149 | if (set_score_adj(pc, adj)) |
106876b9 | 150 | err(EXIT_FAILURE, _("failed to set score adjust value")); |
bd5f7f2e | 151 | ul_unref_path(pc); |
8fa223da KZ |
152 | argv += optind; |
153 | execvp(argv[0], argv); | |
154 | errexec(argv[0]); | |
155 | } | |
156 | ||
bd5f7f2e | 157 | ul_unref_path(pc); |
8fa223da KZ |
158 | return EXIT_SUCCESS; |
159 | } |