Sigrid Solveig Haflínudóttirposix: sys: uname may return > 0 on success (wtf)f1b48d82 months agoHistory
444 lines · 7.3 KB · C
RawDownload
#include "inc/priv.h"#include "inc/process.h"#include "inc/time.h"#include <errno.h>#include <fcntl.h>#include <locale.h>#include <signal.h>#include <sys/mman.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/utsname.h>#include <sys/wait.h>#include <time.h> static usize pagesize = 4096;#define PAGEALIGNED(x) (((x) + pagesize-1) & ~(pagesize-1)) #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)#define MAP_ANONYMOUS MAP_ANON#endif #if !defined(O_PATH)#define O_PATH 0#endif void *sl_segalloc(usize sz){	sz = PAGEALIGNED(sz);	void *s = mmap(nil, sz, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);	if(s == (void*)-1)		s = nil;	return s;} voidsl_segfree(void *s, usize sz){	if(s == nil)		return;	sz = PAGEALIGNED(sz);	if(munmap(s, sz) != 0)		abort();} voidsl_segused(void *s, usize sz, usize used){	sz = PAGEALIGNED(sz);	used = PAGEALIGNED(used);	// it's fine if this fails	posix_madvise((u8int*)s+used, sz-used, POSIX_MADV_DONTNEED);} u64intsec_realtime(void){	struct timespec now;	if(clock_gettime(CLOCK_REALTIME, &now) != 0)		return 0;	return (u64int)now.tv_sec*Nsec + (u64int)now.tv_nsec;} u64intnanosec_monotonic(void){	static s64int z;	struct timespec now; 	if(clock_gettime(CLOCK_MONOTONIC, &now) != 0)		return 0;	if(z == 0){		z = now.tv_sec*Nsec + now.tv_nsec;		return 0;	}	return now.tv_sec*Nsec + now.tv_nsec - z;} voidtimestr(u64int ns, char *buf, int sz){	time_t tme = ns/Nsec;	struct tm tm; 	*buf = 0;	if(localtime_r(&tme, &tm) != nil)		strftime(buf, sz, "%a %b %e %H:%M:%S %Y", &tm);} voidsleep_ms(int ms){	if(ms != 0){		struct timeval timeout;		timeout.tv_sec = ms/1000;		timeout.tv_usec = (ms % 1000) * 1000;		select(0, nil, nil, nil, &timeout);	}} void __attribute__((noinline))sys_setcurrpc(int dummy){	USED(dummy);	sys_setcallpc(dummy);} voidsys_seed(void *p, int sz){	u8int *o = p;	int f; 	if((f = open("/dev/urandom", O_RDONLY)) >= 0){		while(sz > 0){			ssize_t n = read(f, o, sz);			if(n < 0)				break;			o += n;			sz -= n;		}		close(f);	}	// not sure what kind of OS that would be where it fails. have fun with that, anyway} static int_enonfatal(int err){	return err == 0 || err == EAGAIN || err == EINPROGRESS || err == EINTR || err == EWOULDBLOCK;} intsys_read(int fd, u8int *buf, usize n, usize *nread){	ssize r; 	while(1){		errno = 0;		r = read(fd, buf, n);		if(r > -1){			*nread = (usize)r;			break;		}		if(!_enonfatal(errno)){			*nread = 0;			return errno;		}		sleep_ms(1);	}	return 0;} intsys_write(int fd, const void *buf, usize n, usize *nwritten){	ssize r; 	while(1){		errno = 0;		r = write(fd, buf, n);		if(r > -1){			*nwritten = (usize)r;			break;		}		if(!_enonfatal(errno)){			*nwritten = 0;			return errno;		}		sleep_ms(1);	}	return 0;} intsys_open(const char *fname, ios_flags flags, usize mode){	int of =		(flags & IOS_WRITE)		? ((flags & IOS_READ) ? O_RDWR : O_WRONLY)		: O_RDONLY;	if(flags & IOS_TRUNC)		of |= O_TRUNC;	if(flags & IOS_CREATE)		of |= O_CREAT;	if(flags & IOS_APPEND)		of |= O_APPEND;	if(flags & IOS_EXCL)		of |= O_EXCL;	if(flags & IOS_DIR)		of |= O_DIRECTORY | O_PATH;	of |= O_CLOEXEC;	return open(fname, of, mode);} intsys_mkdir(const char *path, usize mode){	if(mkdir(path, mode) == 0)		return 0;	char *p = MEM_STRDUP(path);	if(p == nil)		return -1;	int r = -1;	for(char *s = p+1; (s = strchr(s, '/')) != nil;){		struct stat sb = {0};		*s = 0;		if(stat(p, &sb) == 0){			if((sb.st_mode & S_IFMT) != S_IFDIR)				goto done;		}else if(mkdir(p, mode) != 0 && errno != EEXIST)			goto done;		*s++ = '/';		while(*s == '/')			s++;	}	if((r = mkdir(path, mode)) != 0 && errno == EEXIST)		r = 0;done:	MEM_FREE(p);	return r;} voidsys_fd_setup(int fd){	USED(fd);} intsys_rename(const char *old, const char *new){	return rename(old, new);} soffsetsys_seek(int fd, soffset offset, int whence){	return lseek(fd, offset, whence);} intsys_close(int fd){	return close(fd);} intsys_dup(int oldfd, int newfd){	while(1){		int r = dup2(oldfd, newfd);		if(r >= 0)			return r;		if(errno != EBUSY && errno != EINTR)			return -1;	}} intsys_exec(const char *path, char *const argv[], char *env[]){	if(env == nil)		return execv(path, argv);	return execve(path, argv, env);} intsys_fork(fork_flags flags){	// note: nothing needs to be done for FORK_CLEAR_ENV since the only	// use of sys_fork is make-process, which is using sys_exec after and	// passes the new environment	USED(flags);	return fork();} char *sys_getcwd(void){	char tmp[4096];	if(getcwd(tmp, sizeof(tmp)) != nil)		return MEM_STRDUP(tmp);	return nil;} intsys_pipe(int fd[2], bool rd, bool wr){	if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)		return -1;	if(!rd){		shutdown(fd[0], SHUT_RD);		shutdown(fd[1], SHUT_WR);	}	if(!wr){		shutdown(fd[0], SHUT_WR);		shutdown(fd[1], SHUT_RD);	}	return 0;} char *sys_find_program(const char *p){	if((p[0] == '/') ||	   (p[0] == '.' && p[1] == '/') ||	   (p[0] == '.' && p[1] == '.' && p[2] == '/'))		return MEM_STRDUP(p); 	char *path = getenv("PATH");	if(path == nil)		return nil;	path = MEM_STRDUP(path); 	char *s, *e;	for(s = path; s != nil;){		e = strchr(s, ':');		if(e != nil)			*e = 0;		int dir = open(s, O_RDONLY|O_DIRECTORY|O_PATH);		if(dir >= 0){			int r = faccessat(dir, p, X_OK, AT_EACCESS);			close(dir);			if(r == 0)				break;		}		s = e != nil ? e+1 : nil;	} 	if(s != nil){		int n = strlen(s);		e = MEM_ALLOC(n+1+strlen(p)+1);		memcpy(e, s, n);		e[n] = '/';		strcpy(e+n+1, p);		s = e;	}	free(path);	return s;} intsys_postnote(int pid, const char *note, const char *sig){	static const struct {		const char *str;		int sig;	}sigs[] = {		{"ABRT", SIGABRT},		{"ALRM", SIGALRM},		{"CONT", SIGCONT},		{"HUP", SIGHUP},		{"INT", SIGINT},		{"KILL", SIGKILL},		{"QUIT", SIGQUIT},		{"STOP", SIGSTOP},		{"TERM", SIGTERM},		{"USR1", SIGUSR1},		{"USR2", SIGUSR2},	}; 	USED(note);	if(strncmp(sig, "SIG", 3) != 0)		return -1;	sig += 3;	for(int i = 0; i < nelem(sigs); i++){		if(strcmp(sig, sigs[i].str) == 0)			return kill(pid, sigs[i].sig);	}	return -1;} BUILTIN("getpid", getpid){	USED(args);	noargs();	return fixnum(getpid());} static voidsigchld(int sig, siginfo_t *info, void *ucontext){	USED(sig);	USED(ucontext); 	waitpid(info->si_pid, nil, WUNTRACED|WCONTINUED); 	int state;	switch(info->si_code){	case CLD_EXITED:		state = PSTATE_EXITED;		break;	case CLD_DUMPED:		state = PSTATE_DUMPED;		break;	case CLD_STOPPED:		state = PSTATE_STOPPED;		break;	case CLD_CONTINUED:		state = PSTATE_RUNNING;		break;	case CLD_KILLED:		state = PSTATE_SIGNALED;		break;	case CLD_TRAPPED:	default:		return;	}	int code = info->si_status;	char msg[16];	if(code != 0)		snprintf(msg, sizeof(msg), "%d", code);	process_update(info->si_pid, state, code, code != 0 ? msg : nil);} voidsys_init(void){	struct sigaction s = {		.sa_sigaction = sigchld,		.sa_flags = SA_SIGINFO,	};	sigaction(SIGCHLD, &s, nil);} static const u8int boot[] = {#include "sl.boot.h"}; char *os_version; intmain(int argc, char **argv){	setlocale(LC_NUMERIC, "C");	struct utsname u;	os_version = strdup(uname(&u) >= 0 ? u.release : "");	long p = sysconf(_SC_PAGE_SIZE);	if(p > 0)		pagesize = p;	slmain(boot, sizeof(boot), argc, argv);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t