Based on the ulimit bultin from shell/ash.c

Signed-off-by: Tobias Klauser <[email protected]>
---
 shell/Config.in |    7 ++
 shell/hush.c    |  188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 193 insertions(+), 2 deletions(-)

diff --git a/shell/Config.in b/shell/Config.in
index 3b16506..4bd1cdd 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -243,6 +243,13 @@ config HUSH_RANDOM_SUPPORT
          Enable pseudorandom generator and dynamic variable "$RANDOM".
          Each read of "$RANDOM" will generate a new pseudorandom value.
 
+config HUSH_ULIMIT
+       bool "ulimit builtin"
+       default n
+       depends on HUSH
+       help
+         Enable ulimit builtin in hush.
+
 config LASH
        bool "lash (deprecated: aliased to hush)"
        default n
diff --git a/shell/hush.c b/shell/hush.c
index 0310b02..9a06502 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -57,7 +57,6 @@
  *
  * TODOs:
  *      grep for "TODO" and fix (some of them are easy)
- *      builtins: ulimit
  *      special variables (done: PWD)
  *      follow IFS rules more precisely, including update semantics
  *      export builtin should be special, its arguments are assignments
@@ -613,6 +612,9 @@ static int builtin_continue(char **argv) FAST_FUNC;
 #if ENABLE_HUSH_FUNCTIONS
 static int builtin_return(char **argv) FAST_FUNC;
 #endif
+#ifdef ENABLE_HUSH_ULIMIT
+static int builtin_ulimit(char **argv) FAST_FUNC;
+#endif
 
 /* Table of built-in functions.  They can be forked or not, depending on
  * context: within pipes, they fork.  As simple commands, they do not.
@@ -671,7 +673,7 @@ static const struct built_in_command bltins1[] = {
        BLTIN("shift"    , builtin_shift   , "Shift positional parameters"),
        BLTIN("trap"     , builtin_trap    , "Trap signals"),
        BLTIN("type"     , builtin_type    , "Write a description of command 
type"),
-//     BLTIN("ulimit"   , builtin_ulimit  , "Control resource limits"),
+       BLTIN("ulimit"   , builtin_ulimit  , "Control resource limits"),
        BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
        BLTIN("unset"    , builtin_unset   , "Unset variables"),
        BLTIN("wait"     , builtin_wait    , "Wait for process"),
@@ -8095,3 +8097,185 @@ static int FAST_FUNC builtin_return(char **argv)
        return rc;
 }
 #endif
+
+#if ENABLE_HUSH_ULIMIT
+struct limits {
+       uint8_t cmd;                    /* RLIMIT_xxx fit into it */
+       uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
+       char option;
+       const char *name;
+};
+
+static const struct limits limits_tbl[] = {
+#ifdef RLIMIT_CPU
+       { RLIMIT_CPU,           0,      't',    "cpu time (seconds)" },
+#endif
+#ifdef RLIMIT_FSIZE
+       { RLIMIT_FSIZE,         9,      'f',    "file size (blocks)" },
+#endif
+#ifdef RLIMIT_DATA
+       { RLIMIT_DATA,          10,     'd',    "data seg size (kb)" },
+#endif
+#ifdef RLIMIT_STACK
+       { RLIMIT_STACK,         10,     's',    "stack size (kb)" },
+#endif
+#ifdef RLIMIT_CORE
+       { RLIMIT_CORE,          9,      'c',    "core file size (blocks)" },
+#endif
+#ifdef RLIMIT_RSS
+       { RLIMIT_RSS,           10,     'm',    "resident set size (kb)" },
+#endif
+#ifdef RLIMIT_MEMLOCK
+       { RLIMIT_MEMLOCK,       10,     'l',    "locked memory (kb)" },
+#endif
+#ifdef RLIMIT_NPROC
+       { RLIMIT_NPROC,         0,      'p',    "processes" },
+#endif
+#ifdef RLIMIT_NOFILE
+       { RLIMIT_NOFILE,        0,      'n',    "file descriptors" },
+#endif
+#ifdef RLIMIT_AS
+       { RLIMIT_AS,            10,     'v',    "address space (kb)" },
+#endif
+#ifdef RLIMIT_LOCKS
+       { RLIMIT_LOCKS,         0,      'w',    "locks" },
+#endif
+};
+
+enum limtype { SOFT = 0x1, HARD = 0x2 };
+
+static void printlim(enum limtype how, const struct rlimit *limit,
+                       const struct limits *l)
+{
+       rlim_t val;
+
+       val = limit->rlim_max;
+       if (how & SOFT)
+               val = limit->rlim_cur;
+
+       if (val == RLIM_INFINITY)
+               printf("unlimited\n");
+       else {
+               val >>= l->factor_shift;
+               printf("%lld\n", (long long) val);
+       }
+}
+
+static const char ulimit_opt_string[] = "!HSa"
+#ifdef RLIMIT_CPU
+                       "t"
+#endif
+#ifdef RLIMIT_FSIZE
+                       "f"
+#endif
+#ifdef RLIMIT_DATA
+                       "d"
+#endif
+#ifdef RLIMIT_STACK
+                       "s"
+#endif
+#ifdef RLIMIT_CORE
+                       "c"
+#endif
+#ifdef RLIMIT_RSS
+                       "m"
+#endif
+#ifdef RLIMIT_MEMLOCK
+                       "l"
+#endif
+#ifdef RLIMIT_NPROC
+                       "p"
+#endif
+#ifdef RLIMIT_NOFILE
+                       "n"
+#endif
+#ifdef RLIMIT_AS
+                       "v"
+#endif
+#ifdef RLIMIT_LOCKS
+                       "w"
+#endif
+                       ;
+
+static int FAST_FUNC builtin_ulimit(char **argv)
+{
+       uint32_t flags;
+       int set, all = 0;
+       enum limtype how = SOFT | HARD;
+       const struct limits *l;
+       rlim_t val;
+       struct rlimit limit;
+
+       l = &limits_tbl[1];     /* default to '-f' */
+       flags = getopt32(argv, ulimit_opt_string);
+       if (flags == (uint32_t)-1)
+               return EXIT_FAILURE;
+       if (flags & 1)
+               how = HARD;
+       if (flags & 2)
+               how = SOFT;
+       if (flags & 4)
+               all = 1;
+
+       if (all && (flags & ~0x7)) {
+               bb_error_msg("ulimit: no limits allowed with -a");
+               return EXIT_FAILURE;
+       }
+
+       flags >>= 3;
+       l = limits_tbl;
+       for ( ; flags; flags >>= 1, l++) {
+               /* Only consider the first matching option */
+               if (flags & 1)
+                       break;
+       }
+
+       argv += optind;
+       set = *argv ? 1 : 0;
+       val = 0;
+       if (set) {
+               char *p = *argv;
+
+               if (strncmp(p, "unlimited", 9) == 0)
+                       val = RLIM_INFINITY;
+               else {
+                       if (sizeof(val) == sizeof(int))
+                               val = bb_strtou(p, NULL, 10);
+                       else if (sizeof(val) == sizeof(long))
+                               val = bb_strtoul(p, NULL, 10);
+                       else
+                               val = bb_strtoull(p, NULL, 10);
+                       if (errno) {
+                               bb_error_msg("ulimit: bad number");
+                               return EXIT_FAILURE;
+                       }
+                       val <<= l->factor_shift;
+               }
+       }
+
+       if (all) {
+               for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; 
l++) {
+                       getrlimit(l->cmd, &limit);
+                       printf("-%c: %-30s ", l->option, l->name);
+                       printlim(how, &limit, l);
+               }
+               return 0;
+       }
+
+       getrlimit(l->cmd, &limit);
+       if (set) {
+               if (how & HARD)
+                       limit.rlim_max = val;
+               if (how & SOFT)
+                       limit.rlim_cur = val;
+               if (setrlimit(l->cmd, &limit) < 0) {
+                       bb_error_msg("ulimit: error setting limit");
+                       return EXIT_FAILURE;
+               }
+       } else {
+               printlim(how, &limit, l);
+       }
+
+       return 0;
+}
+#endif
-- 
1.6.3.3

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to