10f66f451Sopenharmony_ci/* ulimit.c - Modify resource limits 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2015 Rob Landley <rob@landley.net> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ulimit.html 60f66f451Sopenharmony_ci * And man prlimit(2). 70f66f451Sopenharmony_ci * 80f66f451Sopenharmony_ci * Deviations from posix: The units on -f are supposed to be 512 byte 90f66f451Sopenharmony_ci * "blocks" (no other options are specified, and even hard drives don't 100f66f451Sopenharmony_ci * do that anymore). Bash uses 1024 byte blocks, so they don't care either. 110f66f451Sopenharmony_ci * We consistently use bytes everywhere we can. 120f66f451Sopenharmony_ci * 130f66f451Sopenharmony_ci * Deviations from bash: Sizes are in bytes (instead of -p 512 and -f 1024). 140f66f451Sopenharmony_ci * Bash's -p value has been wrong since 2010 (git 35f3d14dbbc5). 150f66f451Sopenharmony_ci * The kernel implementation of RLIMIT_LOCKS (-x) was removed from Linux in 160f66f451Sopenharmony_ci * 2003. Bash never implemented -b (it's in the help but unrecognized at 170f66f451Sopenharmony_ci * runtime). We support -P to affect processes other than us. 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ciUSE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN)) 200f66f451Sopenharmony_ciUSE_ULIMIT(OLDTOY(prlimit, ulimit, TOYFLAG_USR|TOYFLAG_BIN)) 210f66f451Sopenharmony_ci 220f66f451Sopenharmony_ciconfig ULIMIT 230f66f451Sopenharmony_ci bool "ulimit" 240f66f451Sopenharmony_ci default y 250f66f451Sopenharmony_ci depends on TOYBOX_PRLIMIT 260f66f451Sopenharmony_ci help 270f66f451Sopenharmony_ci usage: ulimit [-P PID] [-SHRacdefilmnpqrstuv] [LIMIT] 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci Print or set resource limits for process number PID. If no LIMIT specified 300f66f451Sopenharmony_ci (or read-only -ap selected) display current value (sizes in bytes). 310f66f451Sopenharmony_ci Default is ulimit -P $PPID -Sf" (show soft filesize of your shell). 320f66f451Sopenharmony_ci 330f66f451Sopenharmony_ci -S Set/show soft limit -H Set/show hard (maximum) limit 340f66f451Sopenharmony_ci -a Show all limits -c Core file size 350f66f451Sopenharmony_ci -d Process data segment -e Max scheduling priority 360f66f451Sopenharmony_ci -f Output file size -i Pending signal count 370f66f451Sopenharmony_ci -l Locked memory -m Resident Set Size 380f66f451Sopenharmony_ci -n Number of open files -p Pipe buffer 390f66f451Sopenharmony_ci -q Posix message queue -r Max Real-time priority 400f66f451Sopenharmony_ci -R Realtime latency (usec) -s Stack size 410f66f451Sopenharmony_ci -t Total CPU time (in seconds) -u Maximum processes (under this UID) 420f66f451Sopenharmony_ci -v Virtual memory size -P PID to affect (default $PPID) 430f66f451Sopenharmony_ci*/ 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_ci#define FOR_ulimit 460f66f451Sopenharmony_ci#include "toys.h" 470f66f451Sopenharmony_ci 480f66f451Sopenharmony_ciGLOBALS( 490f66f451Sopenharmony_ci long P; 500f66f451Sopenharmony_ci) 510f66f451Sopenharmony_ci 520f66f451Sopenharmony_ci// This is a linux kernel syscall added in 2.6.36 (git c022a0acad53) which 530f66f451Sopenharmony_ci// glibc only exports a wrapper prototype for if you #define _FSF_HURD_RULZE. 540f66f451Sopenharmony_ciint prlimit(pid_t pid, int resource, const struct rlimit *new_limit, 550f66f451Sopenharmony_ci struct rlimit *old_limit); 560f66f451Sopenharmony_ci 570f66f451Sopenharmony_ci// I'd like to sort the RLIMIT values 0-15, but mips, alpha and sparc 580f66f451Sopenharmony_ci// override the asm-generic values for 5-9. Also, the kernel implementation 590f66f451Sopenharmony_ci// of RLIMIT_LOCKS (-x) was removed from Linux in 2003. 600f66f451Sopenharmony_civoid ulimit_main(void) 610f66f451Sopenharmony_ci{ 620f66f451Sopenharmony_ci struct rlimit rr; 630f66f451Sopenharmony_ci int i; 640f66f451Sopenharmony_ci // Order is cdefilmnqRrstuv 650f66f451Sopenharmony_ci char map[] = {RLIMIT_CORE, RLIMIT_DATA, RLIMIT_NICE, RLIMIT_FSIZE, 660f66f451Sopenharmony_ci RLIMIT_SIGPENDING, RLIMIT_MEMLOCK, RLIMIT_RSS, RLIMIT_NOFILE, 0, 670f66f451Sopenharmony_ci RLIMIT_MSGQUEUE, RLIMIT_RTTIME, RLIMIT_RTPRIO, RLIMIT_STACK, 680f66f451Sopenharmony_ci RLIMIT_CPU, RLIMIT_NPROC, RLIMIT_AS}; 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci if (!(toys.optflags&(FLAG_H-1))) toys.optflags |= FLAG_f; 710f66f451Sopenharmony_ci if ((FLAG(a)||FLAG(p)) && toys.optc) error_exit("can't set -ap"); 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci // Fetch data 740f66f451Sopenharmony_ci if (!FLAG(P)) TT.P = getppid(); 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_ci for (i=0; i<sizeof(map); i++) { 770f66f451Sopenharmony_ci char *flags="cdefilmnpqRrstuv"; 780f66f451Sopenharmony_ci 790f66f451Sopenharmony_ci int get = toys.optflags&(FLAG_a|(1<<i)); 800f66f451Sopenharmony_ci 810f66f451Sopenharmony_ci if (get && prlimit(TT.P, map[i], 0, &rr)) perror_exit("-%c", flags[i]); 820f66f451Sopenharmony_ci if (!toys.optc) { 830f66f451Sopenharmony_ci if (FLAG(a)) printf("-%c: ", flags[i]); 840f66f451Sopenharmony_ci if (get) { 850f66f451Sopenharmony_ci if ((1<<i)&FLAG_p) { 860f66f451Sopenharmony_ci if (FLAG(H)) 870f66f451Sopenharmony_ci xreadfile("/proc/sys/fs/pipe-max-size", toybuf, sizeof(toybuf)); 880f66f451Sopenharmony_ci else { 890f66f451Sopenharmony_ci int pp[2]; 900f66f451Sopenharmony_ci 910f66f451Sopenharmony_ci xpipe(pp); 920f66f451Sopenharmony_ci sprintf(toybuf, "%d\n", fcntl(*pp, F_GETPIPE_SZ)); 930f66f451Sopenharmony_ci } 940f66f451Sopenharmony_ci printf("%s", toybuf); 950f66f451Sopenharmony_ci } else { 960f66f451Sopenharmony_ci rlim_t rl = FLAG(H) ? rr.rlim_max : rr.rlim_cur; 970f66f451Sopenharmony_ci 980f66f451Sopenharmony_ci if (rl == RLIM_INFINITY) printf("unlimited\n"); 990f66f451Sopenharmony_ci else printf("%ld\n", (long)rl); 1000f66f451Sopenharmony_ci } 1010f66f451Sopenharmony_ci } 1020f66f451Sopenharmony_ci } 1030f66f451Sopenharmony_ci if (toys.optflags&(1<<i)) break; 1040f66f451Sopenharmony_ci } 1050f66f451Sopenharmony_ci 1060f66f451Sopenharmony_ci if (FLAG(a)||FLAG(p)) return; 1070f66f451Sopenharmony_ci 1080f66f451Sopenharmony_ci if (toys.optc) { 1090f66f451Sopenharmony_ci rlim_t val; 1100f66f451Sopenharmony_ci 1110f66f451Sopenharmony_ci if (tolower(**toys.optargs) == 'u') val = RLIM_INFINITY; 1120f66f451Sopenharmony_ci else val = atolx_range(*toys.optargs, 0, LONG_MAX); 1130f66f451Sopenharmony_ci 1140f66f451Sopenharmony_ci if (FLAG(H)) rr.rlim_max = val; 1150f66f451Sopenharmony_ci else rr.rlim_cur = val; 1160f66f451Sopenharmony_ci if (prlimit(TT.P, map[i], &rr, 0)) perror_exit(0); 1170f66f451Sopenharmony_ci } 1180f66f451Sopenharmony_ci} 119