| #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; | 
 | } |