diff options
author | joerg <joerg@FreeBSD.org> | 1995-10-19 18:42:12 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1995-10-19 18:42:12 +0000 |
commit | 944d72963926679a269cec39063fe921fdfb73ff (patch) | |
tree | 34fc9c6cecb8198ab3b89983e080bd34b2203ea9 /bin/sh/miscbltin.c | |
parent | 6d13f9a708f62766aa05501fc6b9b931ff1e726f (diff) | |
download | FreeBSD-src-944d72963926679a269cec39063fe921fdfb73ff.zip FreeBSD-src-944d72963926679a269cec39063fe921fdfb73ff.tar.gz |
Implement the "ulimit" builtin. This is the analogon to csh's "limit"
command and badly needed in sh(1) for everybody who wants to modify
the system-wide limits from inside /etc/rc.
The options are similar to other system's implemantations of this
command, with the FreeBSD additions for -m (memoryuse) and -p (max
processes) that are not available on other systems.
Diffstat (limited to 'bin/sh/miscbltin.c')
-rw-r--r-- | bin/sh/miscbltin.c | 215 |
1 files changed, 214 insertions, 1 deletions
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c index 52a66e7..be7f0f7 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -4,6 +4,7 @@ * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. + * The ulimit() builtin has been contributed by Joerg Wunsch. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: miscbltin.c,v 1.2 1994/09/24 02:57:52 davidg Exp $ */ #ifndef lint @@ -52,6 +53,18 @@ static char sccsid[] = "@(#)miscbltin.c 8.2 (Berkeley) 4/16/94"; #include "error.h" #include "mystring.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#if BSD +#include <limits.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#endif + #undef eflag extern char **argptr; /* argument list for builtin command */ @@ -166,3 +179,203 @@ umaskcmd(argc, argv) char **argv; { } return 0; } + + +#if BSD +struct restab { + int resource; + int scale; + char *descript; +}; + +/* multi-purpose */ +#define RLIMIT_UNSPEC (-2) + +/* resource */ +#define RLIMIT_ALL (-1) + +/* mode */ +#define RLIMIT_SHOW 0 +#define RLIMIT_SET 1 + +/* what */ +#define RLIMIT_SOFT 1 +#define RLIMIT_HARD 2 + +static struct restab restab[] = { + {RLIMIT_CORE, 512, "coredump(512-blocks) "}, + {RLIMIT_CPU, 1, "time(seconds) "}, + {RLIMIT_DATA, 1024, "datasize(kilobytes) "}, + {RLIMIT_FSIZE, 512, "filesize(512-blocks) "}, + {RLIMIT_MEMLOCK, 1024, "lockedmem(kilobytes) "}, + {RLIMIT_NOFILE, 1, "nofiles(descriptors) "}, + {RLIMIT_NPROC, 1, "processes(max) "}, + {RLIMIT_RSS, 1024, "memoryuse(kilobytes) "}, + {RLIMIT_STACK, 1024, "stacksize(kilobytes) "} +}; + +/* get entry into above table */ +static struct restab * +find_resource(resource) { + int i; + struct restab *rp; + + for(i = 0, rp = restab; + i < sizeof restab / sizeof(struct restab); + i++, rp++) + if(rp->resource == resource) + return rp; + error("internal error: resource not in table"); + return 0; +} + +static void +print_resource(rp, what, with_descript) struct restab *rp; { + struct rlimit rlim; + quad_t val; + + (void)getrlimit(rp->resource, &rlim); + val = (what == RLIMIT_SOFT)? + rlim.rlim_cur: rlim.rlim_max; + if(with_descript) + out1str(rp->descript); + if(val == RLIM_INFINITY) + out1str("unlimited\n"); + else { + val /= (quad_t)rp->scale; + if(val > (quad_t)ULONG_MAX) + out1fmt("> %lu\n", (unsigned long)ULONG_MAX); + else + out1fmt("%lu\n", (unsigned long)val); + } +} + +ulimitcmd(argc, argv) char **argv; { + struct rlimit rlim; + char *p; + int i; + int resource = RLIMIT_UNSPEC; + quad_t val; + int what = RLIMIT_UNSPEC; + int mode = RLIMIT_UNSPEC; + int errs = 0, arg = 1; + struct restab *rp; + extern int optreset; /* XXX should be declared in <stdlib.h> */ + + opterr = 0; /* use own error processing */ + optreset = 1; + optind = 1; + while ((i = getopt(argc, argv, "HSacdfnstmlp")) != EOF) { + arg++; + switch(i) { + case 'H': + if(what == RLIMIT_UNSPEC) what = 0; + what |= RLIMIT_HARD; + break; + case 'S': + if(what == RLIMIT_UNSPEC) what = 0; + what |= RLIMIT_SOFT; + break; + case 'a': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_ALL; + mode = RLIMIT_SHOW; + break; + case 'c': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_CORE; + break; + case 'd': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_DATA; + break; + case 'f': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_FSIZE; + break; + case 'n': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_NOFILE; + break; + case 's': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_STACK; + break; + case 't': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_CPU; + break; + case 'm': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_RSS; + break; + case 'l': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_MEMLOCK; + break; + case 'p': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_NPROC; + break; + case '?': + error("illegal option -%c", optopt); + } + } + + argc -= optind; + argv += optind; + if(argc > 1) + error("too many arguments"); + if(argc == 0) + mode = RLIMIT_SHOW; + else if (resource == RLIMIT_ALL) + errs++; + else + mode = RLIMIT_SET; + if(mode == RLIMIT_UNSPEC) + mode = RLIMIT_SHOW; + if(resource == RLIMIT_UNSPEC) + resource = RLIMIT_FSIZE; + if(what == RLIMIT_UNSPEC) + what = (mode == RLIMIT_SHOW)? + RLIMIT_SOFT: (RLIMIT_SOFT|RLIMIT_HARD); + if(mode == RLIMIT_SHOW && what == (RLIMIT_SOFT|RLIMIT_HARD)) + errs++; + if(errs) + error("Wrong option combination"); + + if(resource == RLIMIT_ALL) + for(i = 0; i < sizeof restab / sizeof(struct restab); i++) + print_resource(restab + i, what, 1); + else if(mode == RLIMIT_SHOW) + print_resource(find_resource(resource), what, 0); + else { + rp = find_resource(resource); + if(strcmp(argv[0], "unlimited") == 0) + val = RLIM_INFINITY; + else { + val = 0; + p = argv[0]; + do { + if((i = *p - '0') < 0 || i > 9) + error("Illegal number: %s", argv[0]); + val = (10 * val) + (quad_t)i; + } while (*++p != '\0'); + val *= (quad_t)rp->scale; + } + (void)getrlimit(resource, &rlim); + if(what & RLIMIT_HARD) + rlim.rlim_max = val; + if(what & RLIMIT_SOFT) + rlim.rlim_cur = val; + if(setrlimit(resource, &rlim) == -1) { + outfmt(&errout, "ulimit: bad limit: %s\n", + strerror(errno)); + return 1; + } + } + return 0; +} +#else /* !BSD */ +#error ulimit() not implemented +#endif /* BSD */ |