The attached patch adds a new shell builtin, "prlimit", which is similar
to ulimit but can operate on any process (not just the current process),
by using Linux's prlimit() function.

prlimit takes a PID as a first argument, and then processes the rest of
its arguments identically to ulimit, e.g.:

        prlimit 3431 -c unlimited

Maybe this is of general interest?

--
"Don't be afraid to ask (λf.((λx.xx) (λr.f(rr))))."
diff --git a/shell/Config.src b/shell/Config.src
index b31e62d..8c3b2a5 100644
--- a/shell/Config.src
+++ b/shell/Config.src
@@ -145,5 +145,14 @@ config FEATURE_SH_HISTFILESIZE
 	  to set shell history size. Note that its max value is capped
 	  by "History size" setting in library tuning section.
 
+config FEATURE_PRLIMIT
+	bool "Enable prlimit builtin command"
+	default n
+	depends on ASH || HUSH
+	select PLATFORM_LINUX
+	help
+	  Enable prlimit, which is like ulimit but operates on any PID,
+	  not just the current process.
+
 
 endmenu
diff --git a/shell/ash.c b/shell/ash.c
index fbbdb06..7c8b20c 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9044,6 +9044,9 @@ static int trapcmd(int, char **) FAST_FUNC;
 static int umaskcmd(int, char **) FAST_FUNC;
 static int unsetcmd(int, char **) FAST_FUNC;
 static int ulimitcmd(int, char **) FAST_FUNC;
+#if ENABLE_FEATURE_PRLIMIT
+static int prlimitcmd(int, char **) FAST_FUNC;
+#endif
 
 #define BUILTIN_NOSPEC          "0"
 #define BUILTIN_SPECIAL         "1"
@@ -9117,6 +9120,9 @@ static const struct builtincmd builtintab[] = {
 #if ENABLE_ASH_BUILTIN_PRINTF
 	{ BUILTIN_REGULAR       "printf"  , printfcmd  },
 #endif
+#if ENABLE_FEATURE_PRLIMIT
+	{ BUILTIN_NOSPEC        "prlimit" , prlimitcmd },
+#endif
 	{ BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
 	{ BUILTIN_REGULAR       "read"    , readcmd    },
 	{ BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
@@ -12918,6 +12924,14 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv)
 	return shell_builtin_ulimit(argv);
 }
 
+#if ENABLE_FEATURE_PRLIMIT
+static int FAST_FUNC
+prlimitcmd(int argc UNUSED_PARAM, char **argv)
+{
+	return shell_builtin_ulimit(argv);
+}
+#endif
+
 /* ============ main() and helpers */
 
 /*
diff --git a/shell/hush.c b/shell/hush.c
index e2dc1e2..74721ad 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -940,6 +940,9 @@ static const struct built_in_command bltins1[] = {
 	BLTIN("trap"     , builtin_trap    , "Trap signals"),
 	BLTIN("type"     , builtin_type    , "Show command type"),
 	BLTIN("ulimit"   , shell_builtin_ulimit  , "Control resource limits"),
+#if ENABLE_FEATURE_PRLIMIT
+	BLTIN("prlimit"  , shell_builtin_ulimit  , "Control resource limits on other processes"),
+#endif
 	BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
 	BLTIN("unset"    , builtin_unset   , "Unset variables"),
 	BLTIN("wait"     , builtin_wait    , "Wait for process"),
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 0051f21..26a0392 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -390,6 +390,10 @@ static void printlim(unsigned opts, const struct rlimit *limit,
 int FAST_FUNC
 shell_builtin_ulimit(char **argv)
 {
+#if ENABLE_FEATURE_PRLIMIT
+	pid_t pid = 0;
+#endif
+
 	unsigned opts;
 	unsigned argc;
 
@@ -408,6 +412,24 @@ shell_builtin_ulimit(char **argv)
 #endif
 	/* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
 
+#if ENABLE_FEATURE_PRLIMIT
+	if (strcmp(argv[0], "prlimit") == 0) {
+		if (!argv[1]) {
+			bb_error_msg("no PID given");
+			return EXIT_FAILURE;
+		}
+
+		/* Mostly copied from procps/kill.c:kill_main(): */
+		pid = bb_strtoi(argv[1], NULL, 10);
+		if (errno && (errno != EINVAL)) {
+			bb_error_msg("invalid PID '%s'", argv[1]);
+			return EXIT_FAILURE;
+		}
+		argv++;
+		*argv = "ulimit";
+	}
+#endif
+
 	argc = 1;
 	while (argv[argc])
 		argc++;
@@ -431,7 +453,11 @@ shell_builtin_ulimit(char **argv)
 
 		if (opt_char == 'a') {
 			for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
+#if ENABLE_FEATURE_PRLIMIT
+				prlimit(pid, l->cmd, NULL, &limit);
+#else
 				getrlimit(l->cmd, &limit);
+#endif
 				printf("-%c: %-30s ", l->option, l->name);
 				printlim(opts, &limit, l);
 			}
@@ -444,7 +470,11 @@ shell_builtin_ulimit(char **argv)
 			if (opt_char == l->option) {
 				char *val_str;
 
+#if ENABLE_FEATURE_PRLIMIT
+				prlimit(pid, l->cmd, NULL, &limit);
+#else
 				getrlimit(l->cmd, &limit);
+#endif
 
 				val_str = optarg;
 				if (!val_str && argv[optind] && argv[optind][0] != '-')
@@ -478,7 +508,12 @@ shell_builtin_ulimit(char **argv)
 					if (opts & OPT_soft)
 						limit.rlim_cur = val;
 //bb_error_msg("setrlimit(%d, %lld, %lld)", l->cmd, (long long)limit.rlim_cur, (long long)limit.rlim_max);
-					if (setrlimit(l->cmd, &limit) < 0) {
+#if ENABLE_FEATURE_PRLIMIT
+					if (prlimit(pid, l->cmd, &limit, NULL) < 0)
+#else
+					if (setrlimit(l->cmd, &limit) < 0)
+#endif
+					{
 						bb_perror_msg("error setting limit");
 						return EXIT_FAILURE;
 					}
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to