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