toybox/toys/posix/ulimit.c
<<
>>
Prefs
   1/* ulimit.c - Modify resource limits
   2 *
   3 * Copyright 2015 Rob Landley <rob@landley.net>
   4 *
   5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ulimit.html
   6 * And man prlimit(2).
   7 *
   8 * Deviations from posix: The units on -f are supposed to be 512 byte
   9 * "blocks" (no other options are specified, and even hard drives don't
  10 * do that anymore). Bash uses 1024 byte blocks, so they don't care either.
  11 * We consistently use bytes everywhere we can.
  12 *
  13 * Deviations from bash: Sizes are in bytes (instead of -p 512 and -f 1024).
  14 * Bash's -p value has been wrong since 2010 (git 35f3d14dbbc5).
  15 * The kernel implementation of RLIMIT_LOCKS (-x) was removed from Linux in
  16 * 2003. Bash never implemented -b (it's in the help but unrecognized at
  17 * runtime). We support -P to affect processes other than us.
  18
  19USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
  20USE_ULIMIT(OLDTOY(prlimit, ulimit, TOYFLAG_USR|TOYFLAG_BIN))
  21
  22config ULIMIT
  23  bool "ulimit"
  24  default y
  25  depends on TOYBOX_PRLIMIT
  26  help
  27    usage: ulimit [-P PID] [-SHRacdefilmnpqrstuv] [LIMIT]
  28
  29    Print or set resource limits for process number PID. If no LIMIT specified
  30    (or read-only -ap selected) display current value (sizes in bytes).
  31    Default is ulimit -P $PPID -Sf" (show soft filesize of your shell).
  32    
  33    -S  Set/show soft limit          -H  Set/show hard (maximum) limit
  34    -a  Show all limits              -c  Core file size
  35    -d  Process data segment         -e  Max scheduling priority
  36    -f  Output file size             -i  Pending signal count
  37    -l  Locked memory                -m  Resident Set Size
  38    -n  Number of open files         -p  Pipe buffer
  39    -q  Posix message queue          -r  Max Real-time priority
  40    -R  Realtime latency (usec)      -s  Stack size
  41    -t  Total CPU time (in seconds)  -u  Maximum processes (under this UID)
  42    -v  Virtual memory size          -P  PID to affect (default $PPID)
  43*/
  44
  45#define FOR_ulimit
  46#include "toys.h"
  47
  48GLOBALS(
  49  long P;
  50)
  51
  52// This is a linux kernel syscall added in 2.6.36 (git c022a0acad53) which
  53// glibc only exports a wrapper prototype for if you #define _FSF_HURD_RULZE.
  54int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,
  55  struct rlimit *old_limit);
  56
  57// I'd like to sort the RLIMIT values 0-15, but mips, alpha and sparc
  58// override the asm-generic values for 5-9. Also, the kernel implementation
  59// of RLIMIT_LOCKS (-x) was removed from Linux in 2003.
  60void ulimit_main(void)
  61{
  62  struct rlimit rr;
  63  int i;
  64  // Order is cdefilmnqRrstuv
  65  char map[] = {RLIMIT_CORE, RLIMIT_DATA, RLIMIT_NICE, RLIMIT_FSIZE,
  66                RLIMIT_SIGPENDING, RLIMIT_MEMLOCK, RLIMIT_RSS, RLIMIT_NOFILE, 0,
  67                RLIMIT_MSGQUEUE, RLIMIT_RTTIME, RLIMIT_RTPRIO, RLIMIT_STACK,
  68                RLIMIT_CPU, RLIMIT_NPROC, RLIMIT_AS};
  69
  70  if (!(toys.optflags&(FLAG_H-1))) toys.optflags |= FLAG_f;
  71  if ((toys.optflags&(FLAG_a|FLAG_p)) && toys.optc) error_exit("can't set -ap");
  72
  73  // Fetch data
  74  if (!(toys.optflags&FLAG_P)) TT.P = getppid();
  75
  76  for (i=0; i<sizeof(map); i++) {
  77    char *flags="cdefilmnpqRrstuv";
  78
  79    int get = toys.optflags&(FLAG_a|(1<<i));
  80
  81    if (get && prlimit(TT.P, map[i], 0, &rr)) perror_exit("-%c", flags[i]);
  82    if (!toys.optc) {
  83      if (toys.optflags&FLAG_a) printf("-%c: ", flags[i]);
  84      if (get) {
  85        if ((1<<i)&FLAG_p) {
  86          if (toys.optflags&FLAG_H)
  87            xreadfile("/proc/sys/fs/pipe-max-size", toybuf, sizeof(toybuf));
  88          else {
  89            int pp[2];
  90
  91            xpipe(pp);
  92            sprintf(toybuf, "%d\n", fcntl(*pp, F_GETPIPE_SZ));
  93          }
  94          printf("%s", toybuf);
  95        } else {
  96          rlim_t rl = (toys.optflags&FLAG_H) ? rr.rlim_max : rr.rlim_cur;
  97
  98          if (rl == RLIM_INFINITY) printf("unlimited\n");
  99          else printf("%ld\n", (long)rl);
 100        }
 101      }
 102    }
 103    if (toys.optflags&(1<<i)) break;
 104  }
 105
 106  if (toys.optflags&(FLAG_a|FLAG_p)) return;
 107
 108  if (toys.optc) {
 109    rlim_t val;
 110
 111    if (tolower(**toys.optargs) == 'u') val = RLIM_INFINITY;
 112    else val = atolx_range(*toys.optargs, 0, LONG_MAX);
 113
 114    if (toys.optflags&FLAG_H) rr.rlim_max = val;
 115    else rr.rlim_cur = val;
 116    if (prlimit(TT.P, map[i], &rr, 0)) perror_exit(0);
 117  }
 118}
 119