281 lines · 4.4 KB · C
RawDownload
#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 **mkenv(void);extern char **mkargv(word*);extern int mapfd(int); char	pathsep = ':'; 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 voideusage(void){	fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs);} #define Notset -4#define Unlimited -3#define Hard -2#define Soft -1 voidexeculimit(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);} voidexecumask(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. */longreadnb(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;}void Updenv(void){}void Execute(word *args, word *path){	char **argv=mkargv(args);	char **env=mkenv();	char file[1024];	int nc;	Updenv();	for(;path;path=path->next){		nc=strlen(path->word);		if(nc<1024){			strcpy(file, path->word);			if(file[0]){				strcat(file, "/");				nc++;			}			if(nc+strlen(argv[1])<1024){				strcat(file, argv[1]);				execve(file, argv+1, env);			}			else werrstr("command name too long");		}	}	rerrstr(file, sizeof file);	pfmt(err, "%s: %s\n", argv[1], file);	efree((char *)argv);}int Executable(char *file){	Dir *statbuf;	int ret; 	statbuf = dirstat(file);	if(statbuf == nil) return 0;	ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);	free(statbuf);	return ret;}