blob: 9393fb23e98d14bf87c0265199d069085474740f [file] [log] [blame]
#include <u.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <errno.h>
#include <fcntl.h>
#include <libc.h>
#include "rc.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
#include "getflags.h"
extern char **mkargv(word*);
extern int mapfd(int);
static char *eargs = "cdflmnstuv";
static int rlx[] = {
RLIMIT_CORE,
RLIMIT_DATA,
RLIMIT_FSIZE,
#ifdef RLIMIT_MEMLOCK
RLIMIT_MEMLOCK,
#else
0,
#endif
#ifdef RLIMIT_RSS
RLIMIT_RSS,
#else
0,
#endif
RLIMIT_NOFILE,
RLIMIT_STACK,
RLIMIT_CPU,
#ifdef RLIMIT_NPROC
RLIMIT_NPROC,
#else
0,
#endif
#ifdef RLIMIT_RSS
RLIMIT_RSS,
#else
0,
#endif
};
static void
eusage(void)
{
fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs);
}
#define Notset -4
#define Unlimited -3
#define Hard -2
#define Soft -1
void
execulimit(void)
{
int fd, n, argc, sethard, setsoft, limit;
int flag[256];
char **argv, **oargv, *p;
char *argv0;
struct rlimit rl;
argv0 = nil;
setstatus("");
oargv = mkargv(runq->argv->words);
argv = oargv+1;
for(argc=0; argv[argc]; argc++)
;
memset(flag, 0, sizeof flag);
ARGBEGIN{
default:
if(strchr(eargs, ARGC()) == nil){
eusage();
return;
}
case 'S':
case 'H':
case 'a':
flag[ARGC()] = 1;
break;
}ARGEND
if(argc > 1){
eusage();
goto out;
}
fd = mapfd(1);
sethard = 1;
setsoft = 1;
if(flag['S'] && flag['H'])
;
else if(flag['S'])
sethard = 0;
else if(flag['H'])
setsoft = 0;
limit = Notset;
if(argc>0){
if(strcmp(argv[0], "unlimited") == 0)
limit = Unlimited;
else if(strcmp(argv[0], "hard") == 0)
limit = Hard;
else if(strcmp(argv[0], "soft") == 0)
limit = Soft;
else if((limit = strtol(argv[0], &p, 0)) < 0 || *p != 0){
eusage();
goto out;
}
}
if(flag['a']){
for(p=eargs; *p; p++){
getrlimit(rlx[p-eargs], &rl);
n = flag['H'] ? rl.rlim_max : rl.rlim_cur;
if(n == -1)
fprint(fd, "ulimit -%c unlimited\n", *p);
else
fprint(fd, "ulimit -%c %d\n", *p, n);
}
goto out;
}
for(p=eargs; *p; p++){
if(flag[(uchar)*p]){
n = 0;
getrlimit(rlx[p-eargs], &rl);
switch(limit){
case Notset:
n = flag['H'] ? rl.rlim_max : rl.rlim_cur;
if(n == -1)
fprint(fd, "ulimit -%c unlimited\n", *p);
else
fprint(fd, "ulimit -%c %d\n", *p, n);
break;
case Hard:
n = rl.rlim_max;
goto set;
case Soft:
n = rl.rlim_cur;
goto set;
case Unlimited:
n = -1;
goto set;
default:
n = limit;
set:
if(setsoft)
rl.rlim_cur = n;
if(sethard)
rl.rlim_max = n;
if(setrlimit(rlx[p-eargs], &rl) < 0)
fprint(mapfd(2), "setrlimit: %r\n");
}
}
}
out:
free(oargv);
poplist();
flush(err);
}
void
execumask(void)
{
int n, argc;
char **argv, **oargv, *p;
char *argv0;
argv0 = nil;
setstatus("");
oargv = mkargv(runq->argv->words);
argv = oargv+1;
for(argc=0; argv[argc]; argc++)
;
ARGBEGIN{
default:
usage:
fprint(mapfd(2), "usage: umask [mode]\n");
goto out;
}ARGEND
if(argc > 1)
goto usage;
if(argc == 1){
n = strtol(argv[0], &p, 8);
if(*p != 0 || p == argv[0])
goto usage;
umask(n);
goto out;
}
n = umask(0);
umask(n);
if(n < 0){
fprint(mapfd(2), "umask: %r\n");
goto out;
}
fprint(mapfd(1), "umask %03o\n", n);
out:
free(oargv);
poplist();
flush(err);
}
/*
* Cope with non-blocking read.
*/
long
readnb(int fd, char *buf, long cnt)
{
int n, didreset;
int flgs;
didreset = 0;
again:
n = read(fd, buf, cnt);
if(n == -1)
if(errno == EAGAIN){
if(!didreset){
if((flgs = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
flgs &= ~O_NONBLOCK;
if(fcntl(fd, F_SETFL, flgs) == -1)
return -1;
didreset = 1;
}
goto again;
}
return n;
}