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.
This commit is contained in:
parent
6d13f9a708
commit
944d729639
@ -35,7 +35,7 @@
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)builtins 8.1 (Berkeley) 5/31/93
|
||||
# $Id$
|
||||
# $Id: builtins,v 1.2 1994/09/24 02:57:23 davidg Exp $
|
||||
|
||||
#
|
||||
# This file lists all the builtin commands. The first column is the name
|
||||
@ -83,6 +83,7 @@ setvarcmd setvar
|
||||
shiftcmd shift
|
||||
trapcmd trap
|
||||
truecmd : true
|
||||
ulimitcmd ulimit
|
||||
umaskcmd umask
|
||||
unaliascmd unalias
|
||||
unsetcmd unset
|
||||
|
@ -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 */
|
||||
|
54
bin/sh/sh.1
54
bin/sh/sh.1
@ -33,7 +33,9 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)sh.1 8.4 (Berkeley) 4/18/94
|
||||
.\" $Id: sh.1,v 1.2 1994/09/24 02:58:13 davidg Exp $
|
||||
.\" $Id: sh.1,v 1.3 1995/05/05 16:49:15 adam Exp $
|
||||
.\"
|
||||
.\"
|
||||
.\"
|
||||
.na
|
||||
.TH SH 1
|
||||
@ -1277,6 +1279,56 @@ resets trapped (but not ignored) signals to the
|
||||
default action. The trap command has no effect on
|
||||
signals that were ignored on entry to the shell.
|
||||
.TP
|
||||
ulimit [ -HSacdflmnpst ] [ limit ]
|
||||
Set or display resource limits (see getrlimit(2)).
|
||||
If ``limit'' is specified, the named resource will be set;
|
||||
otherwise the current resource value will be displayed.
|
||||
.br
|
||||
If ``-H'' is specified, the hard limits will be
|
||||
set or displayed. While everybody is allowed to reduce a
|
||||
hard limit, only the superuser can increase it. Option ``-S''
|
||||
specifies the soft limits instead. When displaying limits,
|
||||
only one of ``-S'' or ``-H'' can be given. The default is
|
||||
to display the soft limits, and to set both, the hard and
|
||||
the soft limits.
|
||||
.br
|
||||
Option ``-a'' requests to display all resources. The parameter
|
||||
``limit'' is not acceptable in this mode.
|
||||
.br
|
||||
The remaining options specify which resource value is to be
|
||||
displayed or modified. They are mutually exclusive.
|
||||
.RS +.7i
|
||||
.TP 2
|
||||
-c coredumpsize
|
||||
The maximal size of core dump files, in 512-byte blocks.
|
||||
.TP 2
|
||||
-d datasize
|
||||
The maximal size of the data segment of a process, in kilobytes.
|
||||
.TP 2
|
||||
-f filesize
|
||||
The maximal size of a file, in 512-byte blocks. This is the
|
||||
default.
|
||||
.TP 2
|
||||
-l lockedmem
|
||||
The maximal size of memory that can be locked by a process, in
|
||||
kilobytes.
|
||||
.TP 2
|
||||
-m memoryuse
|
||||
The maximal resident set size of a process, in kilobytes.
|
||||
.TP 2
|
||||
-n nofiles
|
||||
The maximal number of descriptors that could be opened by a process.
|
||||
.TP 2
|
||||
-p procmax
|
||||
The maximal number of simultaneous processes for this user ID.
|
||||
.TP 2
|
||||
-s stacksize
|
||||
The maximal size of the stack segment, in kilobytes.
|
||||
.TP 2
|
||||
-t time
|
||||
The maximal amount of CPU time to be used by each process, in seconds.
|
||||
.RE
|
||||
.TP
|
||||
umask [ mask ]
|
||||
Set the value of umask (see umask(2)) to the specified octal value.
|
||||
If the argument is omitted, the
|
||||
|
Loading…
Reference in New Issue
Block a user