1 1.16 kamil /* $NetBSD: c_ulimit.c,v 1.16 2017/06/30 03:43:57 kamil Exp $ */ 2 1.2 tls 3 1.1 jtc /* 4 1.1 jtc ulimit -- handle "ulimit" builtin 5 1.1 jtc 6 1.1 jtc Reworked to use getrusage() and ulimit() at once (as needed on 7 1.7 mycroft some schizophrenic systems, eg, HP-UX 9.01), made argument parsing 8 1.1 jtc conform to at&t ksh, added autoconf support. Michael Rendell, May, '94 9 1.1 jtc 10 1.1 jtc Eric Gisin, September 1988 11 1.1 jtc Adapted to PD KornShell. Removed AT&T code. 12 1.1 jtc 13 1.1 jtc last edit: 06-Jun-1987 D A Gwyn 14 1.1 jtc 15 1.1 jtc This started out as the BRL UNIX System V system call emulation 16 1.1 jtc for 4.nBSD, and was later extended by Doug Kingston to handle 17 1.1 jtc the extended 4.nBSD resource limits. It now includes the code 18 1.1 jtc that was originally under case SYSULIMIT in source file "xec.c". 19 1.1 jtc */ 20 1.5 agc #include <sys/cdefs.h> 21 1.5 agc 22 1.5 agc #ifndef lint 23 1.16 kamil __RCSID("$NetBSD: c_ulimit.c,v 1.16 2017/06/30 03:43:57 kamil Exp $"); 24 1.5 agc #endif 25 1.5 agc 26 1.16 kamil #include <sys/time.h> 27 1.16 kamil #include <time.h> 28 1.1 jtc 29 1.1 jtc #include "sh.h" 30 1.1 jtc #ifdef HAVE_SYS_RESOURCE_H 31 1.1 jtc # include <sys/resource.h> 32 1.1 jtc #endif /* HAVE_SYS_RESOURCE_H */ 33 1.1 jtc #ifdef HAVE_ULIMIT_H 34 1.1 jtc # include <ulimit.h> 35 1.1 jtc #else /* HAVE_ULIMIT_H */ 36 1.1 jtc # ifdef HAVE_ULIMIT 37 1.1 jtc extern long ulimit(); 38 1.1 jtc # endif /* HAVE_ULIMIT */ 39 1.1 jtc #endif /* HAVE_ULIMIT_H */ 40 1.1 jtc 41 1.1 jtc #define SOFT 0x1 42 1.1 jtc #define HARD 0x2 43 1.1 jtc 44 1.4 hubertf #ifdef RLIM_INFINITY 45 1.4 hubertf # define KSH_RLIM_INFINITY RLIM_INFINITY 46 1.4 hubertf #else 47 1.4 hubertf # define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1) 48 1.4 hubertf #endif /* RLIM_INFINITY */ 49 1.4 hubertf 50 1.1 jtc int 51 1.1 jtc c_ulimit(wp) 52 1.1 jtc char **wp; 53 1.1 jtc { 54 1.1 jtc static const struct limits { 55 1.1 jtc const char *name; 56 1.1 jtc enum { RLIMIT, ULIMIT } which; 57 1.1 jtc int gcmd; /* get command */ 58 1.1 jtc int scmd; /* set command (or -1, if no set command) */ 59 1.1 jtc int factor; /* multiply by to get rlim_{cur,max} values */ 60 1.1 jtc char option; 61 1.1 jtc } limits[] = { 62 1.1 jtc /* Do not use options -H, -S or -a */ 63 1.1 jtc #ifdef RLIMIT_CPU 64 1.1 jtc { "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' }, 65 1.1 jtc #endif 66 1.1 jtc #ifdef RLIMIT_FSIZE 67 1.1 jtc { "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' }, 68 1.1 jtc #else /* RLIMIT_FSIZE */ 69 1.1 jtc # ifdef UL_GETFSIZE /* x/open */ 70 1.1 jtc { "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' }, 71 1.1 jtc # else /* UL_GETFSIZE */ 72 1.1 jtc # ifdef UL_GFILLIM /* svr4/xenix */ 73 1.1 jtc { "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' }, 74 1.1 jtc # else /* UL_GFILLIM */ 75 1.1 jtc { "file(blocks)", ULIMIT, 1, 2, 1, 'f' }, 76 1.1 jtc # endif /* UL_GFILLIM */ 77 1.1 jtc # endif /* UL_GETFSIZE */ 78 1.1 jtc #endif /* RLIMIT_FSIZE */ 79 1.1 jtc #ifdef RLIMIT_CORE 80 1.1 jtc { "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' }, 81 1.1 jtc #endif 82 1.1 jtc #ifdef RLIMIT_DATA 83 1.1 jtc { "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' }, 84 1.1 jtc #endif 85 1.1 jtc #ifdef RLIMIT_STACK 86 1.1 jtc { "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' }, 87 1.1 jtc #endif 88 1.1 jtc #ifdef RLIMIT_MEMLOCK 89 1.1 jtc { "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' }, 90 1.1 jtc #endif 91 1.1 jtc #ifdef RLIMIT_RSS 92 1.1 jtc { "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' }, 93 1.1 jtc #endif 94 1.1 jtc #ifdef RLIMIT_NOFILE 95 1.1 jtc { "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' }, 96 1.1 jtc #else /* RLIMIT_NOFILE */ 97 1.1 jtc # ifdef UL_GDESLIM /* svr4/xenix */ 98 1.1 jtc { "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' }, 99 1.1 jtc # endif /* UL_GDESLIM */ 100 1.1 jtc #endif /* RLIMIT_NOFILE */ 101 1.1 jtc #ifdef RLIMIT_NPROC 102 1.1 jtc { "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' }, 103 1.1 jtc #endif 104 1.10 christos #ifdef RLIMIT_NTHR 105 1.10 christos { "threads", RLIMIT, RLIMIT_NTHR, RLIMIT_NTHR, 1, 'r' }, 106 1.10 christos #endif 107 1.1 jtc #ifdef RLIMIT_VMEM 108 1.1 jtc { "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' }, 109 1.1 jtc #else /* RLIMIT_VMEM */ 110 1.1 jtc /* These are not quite right - really should subtract etext or something */ 111 1.1 jtc # ifdef UL_GMEMLIM /* svr4/xenix */ 112 1.1 jtc { "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' }, 113 1.1 jtc # else /* UL_GMEMLIM */ 114 1.1 jtc # ifdef UL_GETBREAK /* osf/1 */ 115 1.1 jtc { "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' }, 116 1.1 jtc # else /* UL_GETBREAK */ 117 1.1 jtc # endif /* UL_GETBREAK */ 118 1.1 jtc # endif /* UL_GMEMLIM */ 119 1.1 jtc #endif /* RLIMIT_VMEM */ 120 1.1 jtc #ifdef RLIMIT_SWAP 121 1.6 christos { "swap(kbytes)", RLIMIT, RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' }, 122 1.6 christos #endif 123 1.6 christos #ifdef RLIMIT_SBSIZE 124 1.6 christos { "sbsize(bytes)", RLIMIT, RLIMIT_SBSIZE, RLIMIT_SBSIZE, 1, 'b' }, 125 1.1 jtc #endif 126 1.8 christos { .name = NULL } 127 1.1 jtc }; 128 1.1 jtc static char options[3 + NELEM(limits)]; 129 1.1 jtc rlim_t UNINITIALIZED(val); 130 1.1 jtc int how = SOFT | HARD; 131 1.1 jtc const struct limits *l; 132 1.1 jtc int set, all = 0; 133 1.1 jtc int optc, what; 134 1.1 jtc #ifdef HAVE_SETRLIMIT 135 1.1 jtc struct rlimit limit; 136 1.1 jtc #endif /* HAVE_SETRLIMIT */ 137 1.3 mycroft 138 1.1 jtc if (!options[0]) { 139 1.1 jtc /* build options string on first call - yuck */ 140 1.1 jtc char *p = options; 141 1.1 jtc 142 1.1 jtc *p++ = 'H'; *p++ = 'S'; *p++ = 'a'; 143 1.1 jtc for (l = limits; l->name; l++) 144 1.1 jtc *p++ = l->option; 145 1.1 jtc *p = '\0'; 146 1.1 jtc } 147 1.1 jtc what = 'f'; 148 1.1 jtc while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) 149 1.1 jtc switch (optc) { 150 1.1 jtc case 'H': 151 1.1 jtc how = HARD; 152 1.1 jtc break; 153 1.1 jtc case 'S': 154 1.1 jtc how = SOFT; 155 1.1 jtc break; 156 1.1 jtc case 'a': 157 1.1 jtc all = 1; 158 1.1 jtc break; 159 1.1 jtc case '?': 160 1.1 jtc return 1; 161 1.1 jtc default: 162 1.1 jtc what = optc; 163 1.1 jtc } 164 1.1 jtc 165 1.1 jtc for (l = limits; l->name && l->option != what; l++) 166 1.1 jtc ; 167 1.1 jtc if (!l->name) { 168 1.1 jtc internal_errorf(0, "ulimit: %c", what); 169 1.1 jtc return 1; 170 1.1 jtc } 171 1.1 jtc 172 1.1 jtc wp += builtin_opt.optind; 173 1.1 jtc set = *wp ? 1 : 0; 174 1.1 jtc if (set) { 175 1.1 jtc if (all || wp[1]) { 176 1.1 jtc bi_errorf("too many arguments"); 177 1.1 jtc return 1; 178 1.1 jtc } 179 1.4 hubertf if (strcmp(wp[0], "unlimited") == 0) 180 1.4 hubertf val = KSH_RLIM_INFINITY; 181 1.4 hubertf else { 182 1.1 jtc long rval; 183 1.1 jtc 184 1.4 hubertf if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR)) 185 1.1 jtc return 1; 186 1.4 hubertf /* Avoid problems caused by typos that 187 1.4 hubertf * evaluate misses due to evaluating unset 188 1.4 hubertf * parameters to 0... 189 1.4 hubertf * If this causes problems, will have to 190 1.4 hubertf * add parameter to evaluate() to control 191 1.4 hubertf * if unset params are 0 or an error. 192 1.4 hubertf */ 193 1.4 hubertf if (!rval && !digit(wp[0][0])) { 194 1.4 hubertf bi_errorf("invalid limit: %s", wp[0]); 195 1.4 hubertf return 1; 196 1.4 hubertf } 197 1.9 sjg val = (u_long)rval * l->factor; 198 1.1 jtc } 199 1.1 jtc } 200 1.1 jtc if (all) { 201 1.1 jtc for (l = limits; l->name; l++) { 202 1.1 jtc #ifdef HAVE_SETRLIMIT 203 1.1 jtc if (l->which == RLIMIT) { 204 1.12 christos if (getrlimit(l->gcmd, &limit) == -1) { 205 1.12 christos bi_errorf("can't get limit: %s", 206 1.12 christos strerror(errno)); 207 1.12 christos return 1; 208 1.12 christos } 209 1.12 christos if (how & SOFT) 210 1.1 jtc val = limit.rlim_cur; 211 1.1 jtc else if (how & HARD) 212 1.1 jtc val = limit.rlim_max; 213 1.7 mycroft } else 214 1.1 jtc #endif /* HAVE_SETRLIMIT */ 215 1.1 jtc #ifdef HAVE_ULIMIT 216 1.1 jtc { 217 1.1 jtc val = ulimit(l->gcmd, (rlim_t) 0); 218 1.1 jtc } 219 1.1 jtc #else /* HAVE_ULIMIT */ 220 1.1 jtc ; 221 1.1 jtc #endif /* HAVE_ULIMIT */ 222 1.1 jtc shprintf("%-20s ", l->name); 223 1.1 jtc #ifdef RLIM_INFINITY 224 1.1 jtc if (val == RLIM_INFINITY) 225 1.1 jtc shprintf("unlimited\n"); 226 1.1 jtc else 227 1.1 jtc #endif /* RLIM_INFINITY */ 228 1.1 jtc { 229 1.1 jtc val /= l->factor; 230 1.1 jtc shprintf("%ld\n", (long) val); 231 1.1 jtc } 232 1.1 jtc } 233 1.1 jtc return 0; 234 1.1 jtc } 235 1.1 jtc #ifdef HAVE_SETRLIMIT 236 1.1 jtc if (l->which == RLIMIT) { 237 1.12 christos if (getrlimit(l->gcmd, &limit) == -1) { 238 1.12 christos bi_errorf("can't get limit: %s", strerror(errno)); 239 1.12 christos return 1; 240 1.12 christos } 241 1.1 jtc if (set) { 242 1.1 jtc if (how & SOFT) 243 1.1 jtc limit.rlim_cur = val; 244 1.1 jtc if (how & HARD) 245 1.1 jtc limit.rlim_max = val; 246 1.1 jtc if (setrlimit(l->scmd, &limit) < 0) { 247 1.4 hubertf if (errno == EPERM) 248 1.4 hubertf bi_errorf("exceeds allowable limit"); 249 1.4 hubertf else 250 1.4 hubertf bi_errorf("bad limit: %s", 251 1.4 hubertf strerror(errno)); 252 1.1 jtc return 1; 253 1.1 jtc } 254 1.1 jtc } else { 255 1.1 jtc if (how & SOFT) 256 1.1 jtc val = limit.rlim_cur; 257 1.1 jtc else if (how & HARD) 258 1.1 jtc val = limit.rlim_max; 259 1.1 jtc } 260 1.1 jtc } else 261 1.1 jtc #endif /* HAVE_SETRLIMIT */ 262 1.1 jtc #ifdef HAVE_ULIMIT 263 1.1 jtc { 264 1.1 jtc if (set) { 265 1.1 jtc if (l->scmd == -1) { 266 1.1 jtc bi_errorf("can't change limit"); 267 1.1 jtc return 1; 268 1.1 jtc } else if (ulimit(l->scmd, val) < 0) { 269 1.1 jtc bi_errorf("bad limit: %s", strerror(errno)); 270 1.1 jtc return 1; 271 1.1 jtc } 272 1.1 jtc } else 273 1.1 jtc val = ulimit(l->gcmd, (rlim_t) 0); 274 1.1 jtc } 275 1.1 jtc #else /* HAVE_ULIMIT */ 276 1.1 jtc ; 277 1.1 jtc #endif /* HAVE_ULIMIT */ 278 1.1 jtc if (!set) { 279 1.1 jtc #ifdef RLIM_INFINITY 280 1.1 jtc if (val == RLIM_INFINITY) 281 1.1 jtc shprintf("unlimited\n"); 282 1.1 jtc else 283 1.1 jtc #endif /* RLIM_INFINITY */ 284 1.1 jtc { 285 1.1 jtc val /= l->factor; 286 1.1 jtc shprintf("%ld\n", (long) val); 287 1.1 jtc } 288 1.1 jtc } 289 1.1 jtc return 0; 290 1.1 jtc } 291