+// $Id: vdlimit.c,v 1.2 2005/03/24 12:44:17 ensc Exp $ --*- c -*--
+
+// Copyright (C) 2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-/*
-** (c) 2004 Herbert Poetzl
-**
-** V0.01 ioctls so far
-**
-*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "compat.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include "util.h"
+#include <lib_internal/sys_clone.h>
+#include <lib/internal.h>
+
+#include <vserver.h>
+
+#include <getopt.h>
+#include <libgen.h>
#include <errno.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-
-#include "vserver.h"
-#include "vserver-internal.h"
-#include "dlimit.h"
-
-#ifdef O_LARGEFILE
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
-#else
-#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
-#endif
+#include <signal.h>
+#include <sched.h>
-static char err_flag = 0;
+#define ENSC_WRAPPERS_PREFIX "vdlimit: "
+#define ENSC_WRAPPERS_UNISTD 1
+#define ENSC_WRAPPERS_VSERVER 1
+#include <wrappers.h>
-static char opt_xid = 0;
-static char opt_flag = 0;
-static char opt_vers = 0;
-static char opt_add = 0;
-static char opt_rem = 0;
-static char opt_set = 0;
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
-static char * cmd_name = NULL;
-static char * set_arg = NULL;
+int wrapper_exit_code = 1;
-static int num_xid = 0;
-static int num_flag = 0;
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "xid", required_argument, 0, 'x' },
+ { "set", required_argument, 0, 's' },
+ { "remove", no_argument, 0, 'd' },
+ { "flags", required_argument, 0, 'f' },
+ {0,0,0,0}
+};
+static void
+showHelp(int fd, char const *cmd)
+{
+ WRITE_MSG(fd, "Usage: ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " --xid <xid> [--flags <flags>] (--set <limit>=<value>|--remove) <mount point>\n"
+ "\n"
+ " --set|-s <limit>=<value> ... set <limit> to <value>, where limit is \n"
+ " one of: space_used, space_total, inodes_used,\n"
+ " inodes_total, reserved\n"
+ " --remove|-d ... removes the disk limit for <xid> from <mount point>\n"
+ "\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+ exit(0);
+}
+static void
+showVersion()
+{
+ WRITE_MSG(1,
+ "vdlimit " VERSION " -- manages disk limits\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2005 Enrico Scholz\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
-#define OPTIONS "+hadf:x:S:V"
+static void
+setDlimit(char const *filename, xid_t xid, uint32_t flags, struct vc_ctx_dlimit const *limit)
+{
+ if (vc_get_dlimit(filename, xid, flags, 0) == -1) {
+ if (vc_add_dlimit(filename, xid, flags) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_add_dlimit()");
+ exit(wrapper_exit_code);
+ }
+ }
+ if (vc_set_dlimit(filename, xid, flags, limit) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_set_dlimit()");
+ exit(wrapper_exit_code);
+ }
+}
-int main(int argc, char *argv[])
+static void
+remDlimit(char const *filename, xid_t xid, uint32_t flags)
{
- extern int optind;
- extern char *optarg;
- char c, errflg = 0;
- int r;
-
-
- cmd_name = argv[0];
- while ((c = getopt(argc, argv, OPTIONS)) != EOF) {
- switch (c) {
- case 'h':
- fprintf(stderr,
- "This is %s " VERSION "\n"
- "options are:\n"
- "-h print this help message\n"
- "-a add dlimit entry\n"
- "-d delete dlimit entry\n"
- "-f <num> flag value in decimal\n"
- "-x <num> context id\n"
- "-S <vals> current/limit values\n"
- "-V verify interface version\n"
- "-- end of options\n"
- ,cmd_name);
- exit(0);
- break;
- case 'a':
- opt_add = 1;
- break;
- case 'd':
- opt_rem = 1;
- break;
- case 'f':
- num_flag = atol(optarg);
- opt_flag = 1;
- break;
- case 'x':
- num_xid = atol(optarg);
- opt_xid = 1;
- break;
- case 'S':
- set_arg = optarg;
- opt_set = 1;
- break;
- case 'V':
- opt_vers = 1;
- break;
- case '?':
- default:
- errflg++;
- break;
- }
- }
- if (errflg) {
- fprintf(stderr,
- "Usage: %s -[" OPTIONS "] <path> ...\n"
- "%s -h for help.\n",
- cmd_name, cmd_name);
- exit(2);
- }
-
- if (opt_vers) {
- r = vc_get_version();
- if (r<0)
- perror("vc_get_version");
- else
- printf("version: %04x:%04x\n",
- (r>>16)&0xFFFF, r&0xFFFF);
- }
+ if (vc_rem_dlimit(filename, xid, flags) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()");
+ exit(wrapper_exit_code);
+ }
+}
- for (; optind < argc; optind++) {
- struct vcmd_ctx_dlimit_base_v0 init;
- struct vcmd_ctx_dlimit_v0 data;
-
- init.name = argv[optind];
- init.flags = num_flag;
-
- if (opt_rem) {
- r = vserver(VCMD_rem_dlimit, num_xid, &init);
- if (r<0)
- perror("vc_rem_dlimit");
- }
- if (opt_add) {
- r = vserver(VCMD_add_dlimit, num_xid, &init);
- if (r<0)
- perror("vc_add_dlimit");
- }
-
- memset(&data, 0, sizeof(data));
- data.name = argv[optind];
- data.flags = num_flag;
-
- if (opt_set) {
- sscanf(set_arg, "%u,%u,%u,%u,%u",
- &data.space_used, &data.space_total,
- &data.inodes_used, &data.inodes_total,
- &data.reserved);
-
- r = vserver(VCMD_set_dlimit, num_xid, &data);
- if (r<0)
- perror("vc_set_dlimit");
- }
-
- memset(&data, 0, sizeof(data));
- data.name = argv[optind];
- data.flags = num_flag;
-
- r = vserver(VCMD_get_dlimit, num_xid, &data);
- if (r<0)
- perror("vc_get_dlimit");
-
- printf("%s: %u,%u,%u,%u,%u\n", argv[optind],
- data.space_used, data.space_total,
- data.inodes_used, data.inodes_total,
- data.reserved);
- }
-
- exit((err_flag)?1:0);
+static void
+writeInt(int fd, char const *prefix, int val)
+{
+ char buf[sizeof(val)*3 + 2];
+ size_t len = utilvserver_fmt_int(buf, val);
+
+ if (prefix)
+ WRITE_STR(fd, prefix);
+ Vwrite(fd, buf, len);
+}
+
+static void
+printDlimit(char const *filename, xid_t xid, uint32_t flags, bool formatted)
+{
+ struct vc_ctx_dlimit limit;
+
+ if (vc_get_dlimit(filename, xid, flags, &limit) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_get_dlimit()");
+ exit(wrapper_exit_code);
+ }
+
+ if (formatted) {
+ writeInt (1, 0, xid);
+ WRITE_MSG(1, " ");
+ WRITE_STR(1, filename);
+ writeInt (1, "\nspace_used=", limit.space_used);
+ writeInt (1, "\nspace_total=", limit.space_total);
+ writeInt (1, "\ninodes_used=", limit.inodes_used);
+ writeInt (1, "\ninodes_total=", limit.inodes_total);
+ writeInt (1, "\nreserved=", limit.reserved);
+ WRITE_MSG(1, "\n");
+ }
+ else {
+ writeInt (1, 0, xid);
+ writeInt (1, " ", limit.space_used);
+ writeInt (1, " ", limit.space_total);
+ writeInt (1, " ", limit.inodes_used);
+ writeInt (1, " ", limit.inodes_total);
+ writeInt (1, " ", limit.reserved);
+ WRITE_MSG(1, " ");
+ WRITE_STR(1, filename);
+ WRITE_MSG(1, "\n");
+ }
}
+
+static bool
+setDLimitField(struct vc_ctx_dlimit *dst, char const *opt)
+{
+ uint_least32_t *ptr;
+ char const * const orig_opt = opt;
+
+#define GET_VAL_PTR(CMP, VAL) \
+ (strncmp(opt, CMP "=", sizeof(CMP))==0) ? \
+ (opt+=sizeof(CMP), &VAL) : 0
+
+ if ((ptr=GET_VAL_PTR("space_used", dst->space_used))!=0) {}
+ else if ((ptr=GET_VAL_PTR("space_total", dst->space_total))!=0) {}
+ else if ((ptr=GET_VAL_PTR("inodes_used", dst->inodes_used))!=0) {}
+ else if ((ptr=GET_VAL_PTR("inodes_total", dst->inodes_total))!=0) {}
+ else if ((ptr=GET_VAL_PTR("reserved", dst->reserved))!=0) {}
+ else ptr=0;
+
+#undef GET_VAL_PTR
+
+ if (ptr!=0 && *ptr==VC_CDLIM_KEEP) {
+ char *endptr;
+ long val = strtol(opt, &endptr, 0);
+
+ if (*opt==0 || *endptr!='\0') {
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not parse number in '");
+ WRITE_STR(2, orig_opt);
+ WRITE_MSG(2, "'\n");
+ return false;
+ }
+
+ *ptr = val;
+ }
+ else if (ptr!=0) {
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "value already set in '");
+ WRITE_STR(2, orig_opt);
+ WRITE_MSG(2, "'\n");
+ return false;
+ }
+ else {
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unknown limit in '");
+ WRITE_STR(2, orig_opt);
+ WRITE_MSG(2, "'\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ bool do_set = false;
+ bool do_remove = false;
+ xid_t xid = VC_NOCTX;
+ uint32_t flags = 0;
+ char *endptr;
+ int sum = 0;
+
+ struct vc_ctx_dlimit limit = {
+ .space_used = VC_CDLIM_KEEP,
+ .space_total = VC_CDLIM_KEEP,
+ .inodes_used = VC_CDLIM_KEEP,
+ .inodes_total = VC_CDLIM_KEEP,
+ .reserved = VC_CDLIM_KEEP
+ };
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+x:s:df:", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0]);
+ case CMD_VERSION : showVersion();
+ case 'x' : xid = Evc_xidopt2xid(optarg, true); break;
+ case 's' :
+ if (!setDLimitField(&limit, optarg))
+ return EXIT_FAILURE;
+ else
+ do_set = true;
+ break;
+ case 'd' : do_remove = true; break;
+ case 'f' :
+ {
+ flags = strtol(optarg, &endptr, 0);
+ if ((flags == 0 && errno != 0) || *endptr != '\0') {
+ WRITE_MSG(2, "Invalid flags argument: '");
+ WRITE_STR(2, optarg);
+ WRITE_MSG(2, "'; try '--help' for more information\n");
+ return EXIT_FAILURE;
+ }
+ }
+ break;
+
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help' for more information.\n");
+ return EXIT_FAILURE;
+ break;
+ }
+ }
+
+ sum = ((do_set ? 1 : 0) + (do_remove ? 1 : 0));
+
+ if (sum>1)
+ WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
+ else if (optind==argc)
+ WRITE_MSG(2, "No mount point specified; try '--help' for more information\n");
+ else if (xid==VC_NOCTX)
+ WRITE_MSG(2, "No xid specified; try '--help' for more information\n");
+ else {
+ for (; optind < argc; ++optind) {
+ if (do_set) setDlimit(argv[optind], xid, flags, &limit);
+ else if (do_remove) remDlimit(argv[optind], xid, flags);
+ else printDlimit(argv[optind], xid, flags, true);
+ }
+
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}
-// $Id: vlimit.c,v 1.1.2.3 2004/02/20 19:35:50 ensc Exp $
+// $Id: vlimit.c,v 1.20 2005/03/24 12:44:17 ensc Exp $
// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
//
#include "compat.h"
#include "vserver.h"
-#include "vserver-internal.h"
+#include "internal.h"
+#include "util.h"
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ctype.h>
-#define VERSION_COPYRIGHT_DISCLAIMER
+#define ENSC_WRAPPERS_PREFIX "vlimit: "
+#define ENSC_WRAPPERS_UNISTD 1
+#define ENSC_WRAPPERS_VSERVER 1
+#include <wrappers.h>
-inline static void UNUSED
-writeStr(int fd, char const *cmd)
-{
- (void)write(fd, cmd, strlen(cmd));
-}
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
+#define CMD_XID 0x4000
+#define CMD_DIR 0x8000
+#define CMD_MISSINGOK 0x8001
-#define WRITE_MSG(FD,X) (void)(write(FD,X,sizeof(X)-1))
-#define WRITE_STR(FD,X) writeStr(FD,X)
+int wrapper_exit_code = 255;
#define NUMLIM(X) \
{ #X, required_argument, 0, 2048|X }
+#define OPT_RESLIM(RES,V) \
+ { #RES, required_argument, 0, 2048|RLIMIT_##V }
static struct option const
CMDLINE_OPTIONS[] = {
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'v' },
- { "all", no_argument, 0, 'a' },
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "all", no_argument, 0, 'a' },
+ { "xid", required_argument, 0, CMD_XID },
+ { "dir", required_argument, 0, CMD_DIR },
+ { "missingok", no_argument, 0, CMD_MISSINGOK },
NUMLIM( 0), NUMLIM( 1), NUMLIM( 2), NUMLIM( 3),
NUMLIM( 4), NUMLIM( 5), NUMLIM( 6), NUMLIM( 7),
NUMLIM( 8), NUMLIM( 9), NUMLIM(10), NUMLIM(11),
NUMLIM(20), NUMLIM(21), NUMLIM(22), NUMLIM(23),
NUMLIM(24), NUMLIM(25), NUMLIM(26), NUMLIM(27),
NUMLIM(28), NUMLIM(29), NUMLIM(30), NUMLIM(31),
+ OPT_RESLIM(cpu, CPU),
+ OPT_RESLIM(fsize, FSIZE),
+ OPT_RESLIM(data, DATA),
+ OPT_RESLIM(stack, STACK),
+ OPT_RESLIM(core, CORE),
+ OPT_RESLIM(rss, RSS),
+ OPT_RESLIM(nproc, NPROC),
+ OPT_RESLIM(nofile, NOFILE),
+ OPT_RESLIM(memlock, MEMLOCK),
+ OPT_RESLIM(as, AS),
+ OPT_RESLIM(locks, LOCKS),
{ 0,0,0,0 }
};
+#define REV_RESLIM(X) [RLIMIT_##X] = #X
+static char const * const LIMIT_STR[] = {
+ REV_RESLIM(CPU), REV_RESLIM(FSIZE), REV_RESLIM(DATA), REV_RESLIM(STACK),
+ REV_RESLIM(CORE), REV_RESLIM(RSS), REV_RESLIM(NPROC), REV_RESLIM(NOFILE),
+ REV_RESLIM(MEMLOCK), REV_RESLIM(AS), REV_RESLIM(LOCKS)
+};
+
static void
showHelp(int fd, char const *cmd, int res)
{
+ VSERVER_DECLARE_CMD(cmd);
+
WRITE_MSG(fd, "Usage: ");
WRITE_STR(fd, cmd);
WRITE_MSG(fd,
- " -c <xid> [-a|--all] [-MSH --<nr> <value>]*\n"
+ " [--xid|-c <xid>] [-nd] [-a|--all] [[-MSH] --(<resource>|<nr>) <value>]*\n"
+ " [--dir <pathname> [--missingok]] [--] [<program> <args>*]\n\n"
+ "Options:\n"
+ " -c|--xid <xid>\n"
+ " ... operate on context <xid>\n"
+ " -a|--all ... show all available limits\n"
+ " -n ... do not resolve limit-names\n"
+ " -d ... show limits in decimal\n"
+ " -M ... set Minimum limit\n"
+ " -S ... set Soft limit\n"
+ " -H ... set Hard limit (assumed by default, when neither\n"
+ " M nor S was requested)\n"
+ " --dir <pathname>\n"
+ " ... read limits from <pathname>/; allowed filenames are\n"
+ " <resource> and <resource>.{min,soft,hard}. When a limit\n"
+ " was set by the CLI already, the corresponding file\n"
+ " will be ignored\n"
+ " --missingok ... do not fail when <pathname> does not exist\n"
+ " --<resource>|<nr> <value>\n"
+ " ... set specified (MSH) limit for <resource> to <value>\n\n"
+ "Valid values for resource are cpu, fsize, data, stack, core, rss, nproc,\n"
+ "nofile, memlock, as and locks.\n\n"
"Please report bugs to " PACKAGE_BUGREPORT "\n");
exit(res);
}
exit(0);
}
+static size_t
+fmtHex(char *ptr, vc_limit_t lim)
+{
+ memcpy(ptr, "0x", 2);
+ return utilvserver_fmt_xuint64(ptr+2, lim) + 2;
+}
+
+static bool do_resolve = true;
+static size_t (*fmt_func)(char *, vc_limit_t) = fmtHex;
+
static void *
appendLimit(char *ptr, bool do_it, vc_limit_t lim)
{
ptr += 2;
if (do_it) {
if (lim==VC_LIM_INFINITY) {
- strcpy(ptr, "INF");
+ strcpy(ptr, "inf");
ptr += 3;
}
else {
- memcpy(ptr, "0x", 2);
- ptr += 2;
-
- ptr += utilvserver_uint2str(ptr, 20, (lim>>32), 16);
- ptr += utilvserver_uint2str(ptr, 20, lim&0xffffffff, 16);
+ ptr += (*fmt_func)(ptr, lim);
*ptr = ' ';
}
}
if (vc_get_rlimit_mask(ctx, &mask)==-1) {
perror("vc_get_rlimit_mask()");
- exit(1);
+ exit(wrapper_exit_code);
}
for (i=0; i<32; ++i) {
uint32_t bitmask = (1<<i);
struct vc_rlimit limit;
- char buf[100], *ptr=buf;
-
+ char buf[128], *ptr=buf;
+
if (((mask.min|mask.soft|mask.hard) & bitmask)==0) continue;
if (vc_get_rlimit(ctx, i, &limit)==-1) {
perror("vc_get_rlimit()");
}
memset(buf, ' ', sizeof buf);
- ptr += utilvserver_uint2str(ptr, 100, i, 10);
- *ptr = ' ';
+ if (do_resolve && i<DIM_OF(LIMIT_STR)) {
+ size_t l = strlen(LIMIT_STR[i]);
+ memcpy(ptr, LIMIT_STR[i], l);
+ ptr += l;
+ }
+ else {
+ ptr += utilvserver_fmt_uint(ptr, i);
+ *ptr = ' ';
+ }
ptr = appendLimit(buf+10, mask.min &bitmask, limit.min);
ptr = appendLimit(buf+30, mask.soft&bitmask, limit.soft);
ptr = appendLimit(buf+50, mask.hard&bitmask, limit.hard);
*ptr++ = '\n';
- write(1, buf, ptr-buf);
- }
+ Vwrite(1, buf, ptr-buf);
+ }
}
static void
- setLimits(int ctx, struct vc_rlimit const limits[], uint32_t mask)
+setLimits(int ctx, struct vc_rlimit const limits[], uint32_t mask)
{
size_t i;
for (i=0; i<32; ++i) {
}
}
+static vc_limit_t
+readValue(int fd, char const *filename)
+{
+ char buf[128];
+ size_t len = Eread(fd, buf, sizeof(buf)-1);
+ vc_limit_t res;
+
+ buf[len] = '\0';
+
+ if (!vc_parseLimit(buf, &res)) {
+ WRITE_MSG(2, "Invalid limit in '");
+ WRITE_STR(2, filename);
+ WRITE_STR(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+
+ return res;
+}
+
+static bool
+readFile(char const *file, char *base, char const *suffix,
+ vc_limit_t *limit)
+{
+ int fd;
+
+ strcpy(base, suffix);
+ fd = open(file, O_RDONLY);
+ if (fd!=-1) {
+ *limit = readValue(fd, file);
+ Eclose(fd);
+ }
+
+ return fd!=-1;
+}
+
+static void
+readFromDir(struct vc_rlimit limits[32], uint_least32_t *mask,
+ char const *pathname, bool missing_ok)
+{
+ struct stat st;
+ size_t i;
+ size_t l_pathname = strlen(pathname);
+ char buf[l_pathname + sizeof("/memlock.hard") + 32];
+
+ if (stat(pathname, &st)==-1) {
+ if (errno==ENOENT && missing_ok) return;
+ PERROR_Q("vlimit: fstat", pathname);
+ exit(wrapper_exit_code);
+ }
+
+ memcpy(buf, pathname, l_pathname);
+ if (l_pathname>0 && pathname[l_pathname-1]!='/')
+ buf[l_pathname++] = '/';
+
+ for (i=0; i<DIM_OF(LIMIT_STR); ++i) {
+ size_t l_res;
+ char * ptr = buf+l_pathname;
+
+ // ignore unimplemented limits
+ if (LIMIT_STR[i]==0) continue;
+
+ // ignore limits set on cli already
+ if (*mask & (1<<i)) continue;
+
+ l_res = strlen(LIMIT_STR[i]);
+ memcpy(ptr, LIMIT_STR[i], l_res+1);
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ ++ptr;
+ }
+
+ if (readFile(buf, ptr, "", &limits[i].min)) {
+ limits[i].soft = limits[i].hard = limits[i].min;
+ *mask |= (1<<i);
+ }
+
+ if (readFile(buf, ptr, ".min", &limits[i].min))
+ *mask |= (1<<i);
+
+ if (readFile(buf, ptr, ".soft", &limits[i].soft))
+ *mask |= (1<<i);
+
+ if (readFile(buf, ptr, ".hard", &limits[i].hard))
+ *mask |= (1<<i);
+ }
+}
+
int main (int argc, char *argv[])
{
// overall used limits
uint32_t lim_mask = 0;
int set_mask = 0;
struct vc_rlimit limits[32];
- bool show_all = false;
- xid_t ctx = VC_NOCTX;
+ bool show_all = false;
+ xid_t ctx = VC_NOCTX;
+ char const * dir = 0;
+ bool missing_ok = false;
{
size_t i;
}
while (1) {
- int c = getopt_long(argc, argv, "MSHhvac:", CMDLINE_OPTIONS, 0);
+ int c = getopt_long(argc, argv, "+MSHndac:", CMDLINE_OPTIONS, 0);
if (c==-1) break;
if (2048<=c && c<2048+32) {
int id = c-2048;
vc_limit_t val;
- if (strcmp(optarg, "inf")==0) val = VC_LIM_INFINITY;
- else val = atoll(optarg);
+ if (!vc_parseLimit(optarg, &val)) {
+ WRITE_MSG(2, "Can not parse limit '");
+ WRITE_STR(2, optarg);
+ WRITE_STR(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+ if (set_mask==0) set_mask=4;
+
if (set_mask & 1) limits[id].min = val;
if (set_mask & 2) limits[id].soft = val;
if (set_mask & 4) limits[id].hard = val;
set_mask = 0;
}
else switch (c) {
- case 'h' : showHelp(1, argv[0], 0);
- case 'v' : showVersion();
- case 'c' : ctx = atoi(optarg); break;
- case 'a' : show_all = true; break;
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case 'a' : show_all = true; break;
+ case 'n' : do_resolve = false; break;
+ case CMD_DIR : dir = optarg; break;
+ case CMD_MISSINGOK: missing_ok = true; break;
+ case CMD_XID : /*@fallthrough@*/
+ case 'c' : ctx = Evc_xidopt2xid(optarg,true); break;
+ case 'd' : fmt_func = utilvserver_fmt_uint64; break;
case 'M' :
case 'S' :
case 'H' :
WRITE_MSG(2, "Try '");
WRITE_STR(2, argv[0]);
WRITE_MSG(2, " --help\" for more information.\n");
- return EXIT_FAILURE;
+ exit(wrapper_exit_code) ;
break;
}
}
- if (ctx==VC_NOCTX) {
- WRITE_MSG(2, "No context specified; try '--help' for more information\n");
- return EXIT_FAILURE;
- }
+ if (ctx==VC_NOCTX)
+ ctx = Evc_get_task_xid(0);
+
+ if (dir)
+ readFromDir(limits, &lim_mask, dir, missing_ok);
setLimits(ctx, limits, lim_mask);
if (show_all) showAll(ctx);
+ if (optind<argc)
+ EexecvpD(argv[optind], argv+optind);
+
return EXIT_SUCCESS;
}