3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or (at your option)
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 Set the global per context limit of a resource (memory, file handle).
21 This utility can do it either for the current context or a selected
24 It uses the same options as ulimit, when possible
43 #include <sys/resource.h>
46 { #X, required_argument, 0, 2048|X }
47 #define RESLIM(RES,V) \
48 { #RES, required_argument, 0, 2048|RLIMIT_##V }
50 static struct option const
52 { "help", no_argument, 0, 'h' },
53 { "version", no_argument, 0, 'v' },
54 { "all", no_argument, 0, 'a' },
55 NUMLIM( 0), NUMLIM( 1), NUMLIM( 2), NUMLIM( 3),
56 NUMLIM( 4), NUMLIM( 5), NUMLIM( 6), NUMLIM( 7),
57 NUMLIM( 8), NUMLIM( 9), NUMLIM(10), NUMLIM(11),
58 NUMLIM(12), NUMLIM(13), NUMLIM(14), NUMLIM(15),
59 NUMLIM(16), NUMLIM(17), NUMLIM(18), NUMLIM(19),
60 NUMLIM(20), NUMLIM(21), NUMLIM(22), NUMLIM(23),
61 NUMLIM(24), NUMLIM(25), NUMLIM(26), NUMLIM(27),
62 NUMLIM(28), NUMLIM(29), NUMLIM(30), NUMLIM(31),
70 RESLIM(nofile, NOFILE),
71 RESLIM(memlock, MEMLOCK),
77 #define REV_RESLIM(X) [RLIMIT_##X] = #X
78 static char const * const LIMIT_STR[] = {
79 REV_RESLIM(CPU), REV_RESLIM(FSIZE), REV_RESLIM(DATA), REV_RESLIM(STACK),
80 REV_RESLIM(CORE), REV_RESLIM(RSS), REV_RESLIM(NPROC), REV_RESLIM(NOFILE),
81 REV_RESLIM(MEMLOCK), REV_RESLIM(AS), REV_RESLIM(LOCKS)
85 showHelp(int fd, char const *cmd, int res)
87 VSERVER_DECLARE_CMD(cmd);
89 WRITE_MSG(fd, "Usage: ");
92 " -c <xid> [-nd] [-a|--all] [[-MSH] --(<resource>|<nr>) <value>]*\n\n"
94 " -c <xid> ... operate on context <xid>\n"
95 " -a|--all ... show all available limits\n"
96 " -n ... do not resolve limit-names\n"
97 " -d ... show limits in decimal\n"
98 " -M ... set Minimum limit\n"
99 " -S ... set Soft limit\n"
100 " -H ... set Hard limit (assumed by default, when neither\n"
101 " M nor S was requested)\n"
102 " --<resource>|<nr> <value>\n"
103 " ... set specified (MSH) limit for <resource> to <value>\n\n"
104 "Valid values for resource are cpu, fsize, data, stack, core, rss, nproc,\n"
105 "nofile, memlock, as and locks.\n\n"
106 "Please report bugs to " PACKAGE_BUGREPORT "\n");
114 "vlimit " VERSION " -- limits context-resources\n"
115 "This program is part of " PACKAGE_STRING "\n\n"
116 "Copyright (C) 2003 Enrico Scholz\n"
117 VERSION_COPYRIGHT_DISCLAIMER);
122 fmtHex(char *ptr, vc_limit_t lim)
124 memcpy(ptr, "0x", 2);
125 return utilvserver_fmt_xuint64(ptr+2, lim) + 2;
128 static bool do_resolve = true;
129 static size_t (*fmt_func)(char *, vc_limit_t) = fmtHex;
132 appendLimit(char *ptr, bool do_it, vc_limit_t lim)
137 if (lim==VC_LIM_INFINITY) {
142 ptr += (*fmt_func)(ptr, lim);
147 memcpy(ptr, "N/A", 3);
157 struct vc_rlimit_mask mask;
160 if (vc_get_rlimit_mask(ctx, &mask)==-1) {
161 perror("vc_get_rlimit_mask()");
165 for (i=0; i<32; ++i) {
166 uint32_t bitmask = (1<<i);
167 struct vc_rlimit limit;
168 char buf[128], *ptr=buf;
170 if (((mask.min|mask.soft|mask.hard) & bitmask)==0) continue;
171 if (vc_get_rlimit(ctx, i, &limit)==-1) {
172 perror("vc_get_rlimit()");
176 memset(buf, ' ', sizeof buf);
177 if (do_resolve && i<DIM_OF(LIMIT_STR)) {
178 size_t l = strlen(LIMIT_STR[i]);
179 memcpy(ptr, LIMIT_STR[i], l);
183 ptr += utilvserver_fmt_uint(ptr, i);
187 ptr = appendLimit(buf+10, mask.min &bitmask, limit.min);
188 ptr = appendLimit(buf+30, mask.soft&bitmask, limit.soft);
189 ptr = appendLimit(buf+50, mask.hard&bitmask, limit.hard);
192 write(1, buf, ptr-buf);
197 setLimits(int ctx, struct vc_rlimit const limits[], uint32_t mask)
200 for (i=0; i<32; ++i) {
201 if ((mask & (1<<i))==0) continue;
202 if (vc_set_rlimit(ctx, i, limits+i)) {
203 perror("vc_set_rlimit()");
208 int main (int argc, char *argv[])
210 // overall used limits
211 uint32_t lim_mask = 0;
213 struct vc_rlimit limits[32];
214 bool show_all = false;
215 xid_t ctx = VC_NOCTX;
219 for (i=0; i<32; ++i) {
220 limits[i].min = VC_LIM_KEEP;
221 limits[i].soft = VC_LIM_KEEP;
222 limits[i].hard = VC_LIM_KEEP;
227 int c = getopt_long(argc, argv, "MSHndhvac:", CMDLINE_OPTIONS, 0);
230 if (2048<=c && c<2048+32) {
234 if (strcmp(optarg, "inf")==0) val = VC_LIM_INFINITY;
235 else val = atoll(optarg);
237 if (set_mask==0) set_mask=4;
239 if (set_mask & 1) limits[id].min = val;
240 if (set_mask & 2) limits[id].soft = val;
241 if (set_mask & 4) limits[id].hard = val;
247 case 'h' : showHelp(1, argv[0], 0);
248 case 'v' : showVersion();
249 case 'c' : ctx = atoi(optarg); break;
250 case 'a' : show_all = true; break;
251 case 'n' : do_resolve = false; break;
252 case 'd' : fmt_func = utilvserver_fmt_uint64; break;
257 case 'M' : set_mask |= 1; break;
258 case 'S' : set_mask |= 2; break;
259 case 'H' : set_mask |= 4; break;
260 default : assert(false);
265 WRITE_MSG(2, "Try '");
266 WRITE_STR(2, argv[0]);
267 WRITE_MSG(2, " --help\" for more information.\n");
274 WRITE_MSG(2, "No context specified; try '--help' for more information\n");
278 setLimits(ctx, limits, lim_mask);
279 if (show_all) showAll(ctx);