summaryrefslogtreecommitdiffstats
path: root/bin/sh/miscbltin.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1995-10-19 18:42:12 +0000
committerjoerg <joerg@FreeBSD.org>1995-10-19 18:42:12 +0000
commit944d72963926679a269cec39063fe921fdfb73ff (patch)
tree34fc9c6cecb8198ab3b89983e080bd34b2203ea9 /bin/sh/miscbltin.c
parent6d13f9a708f62766aa05501fc6b9b931ff1e726f (diff)
downloadFreeBSD-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.c215
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 */
OpenPOWER on IntegriCloud