@global unix; @global linuxns; _unameres = nil; { @local u,r,a,o,w; u=uname(); o=u[0]; a=u[3]; r=myrootns(); w=sizeof(r`long); switch([o,a,w]) { case ["Linux","x86_64",8]: eval("@include "); break; case ["Darwin","x86_64",8]: eval("@include "); break; case ["Linux","x86_64",4]: case ["Darwin","x86_64",4]: default: // no direct syscalls for you fprintf(stderr,"Unsupported OS: %a\n",[o,a,w]); } _unameres = u; }; sys_open = @lambda(filename,oflag,rest ...) { @local m,r; m=malloc(length(filename)+1); putbytes(m,filename); m[length(filename)]=0; if(oflag & unix`O_CREAT) { r=syscall(unix`open,m,oflag,rest[0]); } else { r=syscall(unix`open,m,oflag); } return r; }; sys_close = @lambda(fd) { syscall(unix`close,fd); }; sys_read = @lambda(fd,buf,len) { @local m,r,c; m=malloc(len); r=syscall(unix`read,fd,m,len); if(r>0) { c=getbytes(m,r); putbytes(buf,c); } return r; }; sys_write = @lambda(fd,buf,len) { @local m,r; m=malloc(len); if(isstring(buf)) { if(length(buf) > len) { putbytes(m,substr(buf,0,len)); } else { putbytes(m,buf); } } else { memcpy(m,buf,len); } r=syscall(unix`write,fd,m,len); return r; }; sys_lseek = @lambda(fd,pos,whence) { @local r; r=syscall(unix`lseek,fd,pos,whence); return r; }; sys_ioctl = @lambda(fd,req,data) { @local r; r=syscall(unix`ioctl,fd,req,data); return r; }; sys_dup2 = @lambda(fd1,fd2) { return syscall(unix`dup2,fd1,fd2); }; posix = @names myrootns() { enum Stat_modes { S_IFMT = 00170000, S_IFSOCK = 0140000, S_IFLNK = 0120000, S_IFREG = 0100000, S_IFBLK = 0060000, S_IFDIR = 0040000, S_IFCHR = 0020000, S_IFIFO = 0010000, S_ISUID = 0004000, S_ISGID = 0002000, S_ISVTX = 0001000, }; }; //S_ISREG = @lambda(statbuf) { //}; S_ISDIR = @lambda(statbuf) { return (statbuf->st_mode & posix`S_IFDIR) ? 1 : 0; }; S_ISCHR = @lambda(statbuf) { return (statbuf->st_mode & posix`S_IFCHR) ? 1 : 0; }; S_ISBLK = @lambda(statbuf) { return (statbuf->st_mode & posix`S_IFBLK) ? 1 : 0; }; S_ISFIFO = @lambda(statbuf) { return (statbuf->st_mode & posix`S_IFIFO) ? 1 : 0; }; S_ISLNK = @lambda(statbuf) { return (statbuf->st_mode & posix`S_ISLNK) ? 1 : 0; }; //S_ISSOC = @lambda(m) { //}; sys_fstat = @lambda(fd,statbuf) { @local m,r,l; l=sizeof(struct unix`stat); m=malloc(l); if(0 > m) error("fstat: couldn't allocate stat buf"); if(isstring(statbuf)) { if(length(statbuf) > l) { putbytes(m,substr(statbuf,0,l)); } else { putbytes(m,statbuf); } } else { memcpy(m,statbuf,l); } r=syscall(unix`fstat,fd,m); m=(struct unix`stat *)m; if(!r) { putbytes(statbuf,getbytes(m,sizeof(*m))); } return r; }; FD_ALLOC=@lambda() { return (unsigned char *)malloc(128); }; FD_ISSET=@lambda(fd,set) { @local bit,byte; byte=(fd+1)>>3; bit=1<<(fd - (byte*8)); if(set[byte]&bit) { return 1; } else { return 0; } }; FD_SET=@lambda(fd,set) { @local bit,byte; byte=(fd+1)>>3; bit=1<<(fd - (byte*8)); set[byte]|=bit; }; @global sys_pselect; @global sys_select; if(looksym(unix,'select)) { sys_pselect = @lambda(n,rfds,wfds,xfds,timeout,sigmask) { @local rfds_foo,wfds_foo,xfds_foo,timeout_foo,r,x,rr,rw,rx; @local maxbyte; rfds_foo=FD_ALLOC(); wfds_foo=FD_ALLOC(); xfds_foo=FD_ALLOC(); maxbyte=n>>3; for(x=0;x<=maxbyte;x++) { rfds_foo[x]=0; wfds_foo[x]=0; xfds_foo[x]=0; } if(timeout != 0) { timeout_foo=(unsigned char *)malloc(128); timeout_foo[0]=0; timeout_foo[1]=0; timeout_foo[2]=0; timeout_foo[3]=0; timeout_foo[4]=0; timeout_foo[5]=0; timeout_foo[6]=0; timeout_foo[7]=0; } else { timeout_foo=(unix`unsigned char *)0; } foreach(@lambda(v) { FD_SET(v,rfds_foo); },rfds); foreach(@lambda(v) { FD_SET(v,wfds_foo); },wfds); foreach(@lambda(v) { FD_SET(v,xfds_foo); },xfds); r=syscall(unix`select,n,rfds_foo,wfds_foo,xfds_foo,timeout_foo); if(r==-1) { return [[],[],[]]; } rr=[]; foreach(@lambda(v) { if(FD_ISSET(v,rfds_foo)) { append(rr,v); } },rfds); rw=[]; foreach(@lambda(v) { if(FD_ISSET(v,wfds_foo)) { append(rw,v); } },wfds); rx=[]; foreach(@lambda(v) { if(FD_ISSET(v,xfds_foo)) { append(rx,v); } },xfds); return [rr,rw,rx]; }; sys_select = @lambda(n,rfds,wfds,xfds,timeout) { return sys_pselect(n,rfds,wfds,xfds,timeout,0); }; } sys_unlink = @lambda(filename) { @local m; m=malloc(length(filename)+1); putbytes(m,filename); m[length(filename)]=0; return syscall(unix`unlink,m); }; @global sys_mmap; if(unix.looksym('mmap2)) { sys_mmap = @lambda(addr,length,prot,flags,fd,offset) { return (linuxns`void *)syscall(unix`mmap2,addr,length,prot,flags,fd,offset>>12); }; } else { sys_mmap = @lambda(addr,length,prot,flags,fd,offset) { return (unix`void *)syscall(unix`mmap,addr,length,prot,flags,fd,offset); }; } sys_msync=@lambda(addr,size,flags) { return syscall(unix`msync,addr,size,flags); }; sys_munmap=@lambda(addr,length) { return syscall(unix`munmap,addr,length); }; sys_socket = @lambda(domain,type,protocol) { return syscall(unix`socket,domain,type,protocol); }; sys_connect = @lambda(fd,sockaddr,size) { @local sa; if(isnil(size)) { size=sizeof(*sockaddr); } sa=malloc(size); if(!sa) return nil; putbytes(sa,getbytes(sockaddr,size)); return syscall(unix`connect,fd,sa,size); }; sys_bind = @lambda(fd,sockaddr,size) { @local sa; if(isnil(size)) { size=sizeof(*sockaddr); } sa=malloc(size); if(!sa) return nil; putbytes(sa,getbytes(sockaddr,size)); return syscall(unix`bind,fd,sa,size); }; sys_listen = @lambda(fd,backlog) { return syscall(unix`listen,fd,backlog); }; sys_accept = @lambda(fd,sockaddr,size) { @local sa,ss; if(isnil(size)) { size=sizeof(*sockaddr); } else { size=*size; } sa=malloc(size); if(!sa) return nil; putbytes(sa,getbytes(sockaddr,size)); ss=malloc(sizeof(linuxns`int)); if(!ss) return nil; ss=(linuxns`int *)ss; *ss=size; return syscall(unix`accept,fd,sa,ss); }; sys_getsockname = @lambda(fd,sa,len) { return syscall(unix`getsockname,fd,sa,len); }; sys_setsockopt = @lambda(socket,level,option_name,option_value,option_len) { return syscall(unix`setsockopt,socket,level,option_name,option_value,option_len); }; /* * Process calls */ sys_exit = @lambda(status) { syscall(unix`exit,status); }; @global sys_fork; if(_unameres[0] == "Darwin") { sys_fork = @lambda() { @local r,p; r=syscall(unix`fork); p=sys_getpid(); if(0 > r) { return r; } else if(r == p) { // this is the child. return 0; } else { return r; } }; } else { sys_fork = @lambda() { syscall(unix`fork); }; } @global sys_wait4; if(looksym(unix,'wait4)) { sys_wait4 = @lambda(pid,status,options,rusage) { syscall(unix`wait4,pid,status,options,rusage); }; } sys_getpid = @lambda() { syscall(unix`getpid); }; sys_getppid = @lambda() { syscall(unix`getppid); }; sys_getpgid = @lambda(pid) { syscall(unix`getpgid,pid); }; sys_setpgid = @lambda(pid,pgid) { syscall(unix`setpgid,pid,pgid); }; sys_sleep = @lambda(secs) { @local r,m,m2; m=malloc(sizeof(struct unix`timespec)); m=(struct unix`timespec *)m; m->tv_sec=secs; m->tv_nsec=0; m2=malloc(sizeof(struct unix`timespec)); m2=(struct unix`timespec *)m2; r=syscall(unix`nanosleep,m,m2); if(!r) { return r; } else { return m2->tv_sec; } }; sys_reboot = @lambda(magic, magic2, cmd, arg) { @local r; r=syscall(unix`reboot, magic, magic2, cmd, arg); return r; }; sys_sched_getaffinity = @lambda(pid, cpusetsize, mask) { @local m,r; m=(unsigned char *)malloc(cpusetsize); memset(m,0,cpusetsize); r=syscall(unix`sched_getaffinity,pid,cpusetsize,m); return r; }; sys_sched_setaffinity = @lambda(pid, cpusetsize, mask) { @local m,r; if(isstring(mask) && length(mask) <= cpusetsize) { m=(unsigned char *)malloc(cpusetsize); putbytes(m,mask); } else { error("BAD MASK!\n"); } r=syscall(unix`sched_setaffinity,pid,cpusetsize,m); return r; }; // MPOL_DEFAULT, MPOL_BIND, MPOL_INTERLEAVE or MPOL_PREFERRED. All modes except MPOL_DEFAULT sys_getmempolicy = @lambda(mode, nodemask, maxnode,addr,flags) { @local m,r; if(isstring(nodemask)) { m=(unsigned char *)malloc(length(nodemask)); putbytes(m,nodemask); } else { error("nodemask should be a string"); } r=syscall(unix`get_mempolicy,mode, m, maxnode, addr, flags); return r; }; sys_setmempolicy = @lambda(mode, nodemask, maxnode) { @local m,r; if(isstring(nodemask)) { m=(unsigned char *)malloc(length(nodemask)); putbytes(m,nodemask); } else { error("nodemask should be a string"); } r=syscall(unix`get_setpolicy,mode, m, maxnode); return r; }; sys_getuid = @lambda() { return syscall(unix`getuid); }; sys_geteuid = @lambda() { return syscall(unix`geteuid); }; sys_setuid = @lambda(uid) { return syscall(unix`setuid,uid); }; sys_getgid = @lambda() { return syscall(unix`getgid); }; sys_getegid = @lambda() { return syscall(unix`getegid); }; sys_setgid = @lambda(gid) { return syscall(unix`setgid,gid); }; /* filename: a string filename for the executable to run argv: a list of the string arguments envp: a list of environment assignment strings see man execve example usage: execve("/bin/echo",["/bin/echo","hello","world"],[]); is the same as running: $ /bin/echo hello world */ @define sys_execve(filename,argv,envp) { @local f,fl,a,e; if(iscvalue(filename) && isptr(@typeof(filename))) { @local fl; fl=strlen(filename); f=(unsigned char *)malloc(fl + 1); putbytes(f,getbytes(filename,fl)); f[fl]=0; } else if(isstring(filename)) { fl=length(filename); f=(unsigned char *)malloc(fl+1); putbytes(f,filename); f[fl]=0; } else { error("filename must be a string or a cptr"); } [a,e] = map(@lambda(ary) { @local ret,i,len,strs; len = sizeof(char*) * (length(ary)+1); foreach(@lambda(v) { if (isstring(v)) len += length(v)+1; else len += sizeof(v); },ary); ret=(char**)malloc(len); strs = (char*)&ret[length(ary)+1]; for(i=0; i