/** file_contents : f:string -> string <doc>Read the content of the file [f] and return it.</doc> **/ static value file_contents( value name ) { buffer s; int len; int p; val_check(name,string); fio f(val_filename(name)); const char *fname = val_string(name); gc_enter_blocking(); f.io = fopen(fname,"rb"); if( f.io == NULL ) file_error("file_contents",&f); fseek(f.io,0,SEEK_END); len = ftell(f.io); fseek(f.io,0,SEEK_SET); gc_exit_blocking(); s = alloc_buffer_len(len); p = 0; gc_enter_blocking(); while( len > 0 ) { int d; POSIX_LABEL(file_contents); d = (int)fread((char*)buffer_data(s)+p,1,len,f.io); if( d <= 0 ) { HANDLE_FINTR(f.io,file_contents); fclose(f.io); file_error("file_contents",&f); } p += d; len -= d; } fclose(f.io); gc_exit_blocking(); return buffer_val(s); }
/** sys_create_dir : string -> mode:int -> void <doc>Create a directory with the specified rights</doc> **/ static value sys_create_dir( value path, value mode ) { #if defined(EPPC) || defined(KORE_CONSOLE) return alloc_bool(true); #else val_check(path,string); val_check(mode,int); #ifdef NEKO_WINDOWS const wchar_t* _path = val_wstring(path); gc_enter_blocking(); if( _wmkdir(_path) != 0 ) { gc_exit_blocking(); return alloc_null(); } #else const char* _path = val_string(path); gc_enter_blocking(); if( mkdir(val_string(path),val_int(mode)) != 0 ) { gc_exit_blocking(); return alloc_null(); } #endif gc_exit_blocking(); return alloc_bool(true); #endif }
/** sys_getch : bool -> int <doc>Read a character from stdin with or without echo</doc> **/ static value sys_getch( value b ) { #if defined(HX_WINRT) || defined(EMSCRIPTEN) || defined(EPPC) return alloc_null(); #elif defined(NEKO_WINDOWS) val_check(b,bool); gc_enter_blocking(); int result = val_bool(b)?getche():getch(); gc_exit_blocking(); return alloc_int( result ); #else // took some time to figure out how to do that // without relying on ncurses, which clear the // terminal on initscr() int c; struct termios term, old; val_check(b,bool); gc_enter_blocking(); tcgetattr(fileno(stdin), &old); term = old; cfmakeraw(&term); tcsetattr(fileno(stdin), 0, &term); c = getchar(); tcsetattr(fileno(stdin), 0, &old); if( val_bool(b) ) fputc(c,stdout); gc_exit_blocking(); return alloc_int(c); # endif }
/** socket_poll_events : 'poll -> timeout:float -> void <doc> Update the read/write flags arrays that were created with [socket_poll_prepare]. </doc> **/ static value socket_poll_events( value pdata, value timeout ) { polldata *p; # ifdef NEKO_WINDOWS unsigned int i; int k = 0; struct timeval t; val_check_kind(pdata,k_poll); p = val_poll(pdata); memcpy(p->outr,p->fdr,FDSIZE(p->fdr->fd_count)); memcpy(p->outw,p->fdw,FDSIZE(p->fdw->fd_count)); val_check(timeout,number); init_timeval(val_number(timeout),&t); gc_enter_blocking(); if( p->fdr->fd_count + p->fdw->fd_count != 0 && select(0,p->outr,p->outw,NULL,&t) == SOCKET_ERROR ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->fdr->fd_count;i++) if( FD_ISSET(p->fdr->fd_array[i],p->outr) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k,alloc_int(-1)); k = 0; for(i=0;i<p->fdw->fd_count;i++) if( FD_ISSET(p->fdw->fd_array[i],p->outw) ) val_array_set_i(p->widx,k++, alloc_int(i)); val_array_set_i(p->widx,k,alloc_int(-1)); #else int i,k; int tot; val_check_kind(pdata,k_poll); val_check(timeout,number); p = val_poll(pdata); tot = p->rcount + p->wcount; gc_enter_blocking(); POSIX_LABEL(poll_events_again); if( poll(p->fds,tot,(int)(val_number(timeout) * 1000)) < 0 ) { HANDLE_EINTR(poll_events_again); gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->rcount;i++) if( p->fds[i].revents & (POLLIN|POLLHUP) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k, alloc_int(-1)); k = 0; for(;i<tot;i++) if( p->fds[i].revents & (POLLOUT|POLLHUP) ) val_array_set_i(p->widx,k++, alloc_int(i - p->rcount)); val_array_set_i(p->widx,k, alloc_int(-1)); #endif return val_null; }
/** sys_file_type : string -> string <doc> Return the type of the file. The current values are possible : <ul> <li>[file]</li> <li>[dir]</li> <li>[symlink]</li> <li>[sock]</li> <li>[char]</li> <li>[block]</li> <li>[fifo]</li> </ul> </doc> **/ static value sys_file_type( value path ) { #if defined(EPPC) || defined(KORE_CONSOLE) return alloc_null(); #else val_check(path,string); #ifdef NEKO_WINDOWS const wchar_t* _path = val_wstring(path); gc_enter_blocking(); WIN32_FILE_ATTRIBUTE_DATA data; if( !GetFileAttributesExW(_path,GetFileExInfoStandard,&data) ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { return alloc_string("dir"); } else { return alloc_string("file"); } #else struct stat s; gc_enter_blocking(); if( stat(val_string(path),&s) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); if( s.st_mode & S_IFREG ) return alloc_string("file"); if( s.st_mode & S_IFDIR ) return alloc_string("dir"); if( s.st_mode & S_IFCHR ) return alloc_string("char"); #ifndef NEKO_WINDOWS if( s.st_mode & S_IFLNK ) return alloc_string("symlink"); if( s.st_mode & S_IFBLK ) return alloc_string("block"); if( s.st_mode & S_IFIFO ) return alloc_string("fifo"); if( s.st_mode & S_IFSOCK ) return alloc_string("sock"); #endif #endif return alloc_null(); #endif }
static value sys_sleep( value f ) { val_check(f,number); gc_enter_blocking(); #if defined(NEKO_WINDOWS) && !defined(KORE_CONSOLE) Sleep((DWORD)(val_number(f) * 1000)); #elif defined(EPPC) || defined(KORE_CONSOLE) //TODO: Implement sys_sleep for EPPC #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) { gc_exit_blocking(); return alloc_null(); } t = tmp; } } #endif gc_exit_blocking(); return alloc_bool(true); }
static value socket_recv_from( value o, value dataBuf, value pos, value len, value addr ) { int p,l,ret; int retry = 0; struct sockaddr_in saddr; SockLen slen = sizeof(saddr); val_check_kind(o,k_socket); val_check(dataBuf,buffer); buffer buf = val_to_buffer(dataBuf); char *data = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(addr,object); p = val_int(pos); l = val_int(len); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(recv_from_again); if( retry++ > NRETRYS ) { ret = recv(sock,data+p,l,MSG_NOSIGNAL); } else ret = recvfrom(sock, data + p , l, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_from_again); return block_error(); } gc_exit_blocking(); alloc_field(addr,f_host,alloc_int32(*(int*)&saddr.sin_addr)); alloc_field(addr,f_port,alloc_int(ntohs(saddr.sin_port))); return alloc_int(ret); }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value dataBuf, value pos, value len, value vaddr ) { int p,l; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); buffer buf = val_to_buffer(dataBuf); const char *cdata = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int); val_check(port,int); p = val_int(pos); l = val_int(len); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(send_again); dlen = sendto(sock, cdata + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } gc_exit_blocking(); return alloc_int(dlen); }
/** process_exit : 'process -> int <doc> Wait until the process terminate, then returns its exit code. </doc> **/ static value process_exit( value vp ) { vprocess *p; val_check_kind(vp,k_process); p = val_process(vp); gc_enter_blocking(); # ifdef NEKO_WINDOWS { DWORD rval; WaitForSingleObject(p->pinf.hProcess,INFINITE); gc_exit_blocking(); if( !GetExitCodeProcess(p->pinf.hProcess,&rval) ) return alloc_null(); return alloc_int(rval); } # else int rval; while( waitpid(p->pid,&rval,0) != p->pid ) { if( errno == EINTR ) continue; gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); if( !WIFEXITED(rval) ) return alloc_null(); return alloc_int(WEXITSTATUS(rval)); # endif }
static value socket_set_blocking( value o, value b ) { SOCKET sock = val_sock(o); val_check(b,bool); gc_enter_blocking(); #ifdef NEKO_WINDOWS { unsigned long arg = val_bool(b)?0:1; if( ioctlsocket(sock,FIONBIO,&arg) != 0 ) { gc_exit_blocking(); return alloc_null(); } } #else { int rights = fcntl(sock,F_GETFL); if( rights == -1 ) { gc_exit_blocking(); return alloc_null(); } if( val_bool(b) ) rights &= ~O_NONBLOCK; else rights |= O_NONBLOCK; if( fcntl(sock,F_SETFL,rights) == -1 ) { gc_exit_blocking(); return alloc_null(); } } #endif gc_exit_blocking(); return alloc_bool(true); }
/** file_read : 'file -> s:string -> p:int -> l:int -> int <doc> Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). </doc> **/ static value file_read( value o, value s, value pp, value n ) { fio *f; int p; int len; int buf_len; val_check_kind(o,k_file); val_check(s,buffer); buffer buf = val_to_buffer(s); buf_len = buffer_size(buf); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > buf_len || p + len > buf_len ) return alloc_null(); gc_enter_blocking(); while( len > 0 ) { int d; POSIX_LABEL(file_read_again); d = (int)fread(buffer_data(buf)+p,1,len,f->io); if( d <= 0 ) { int size = val_int(n) - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f); return alloc_int(size); } p += d; len -= d; } gc_exit_blocking(); return n; }
/** process_stdout_read : 'process -> buf:string -> pos:int -> len:int -> int <doc> Read up to [len] bytes in [buf] starting at [pos] from the process stdout. Returns the number of bytes readed this way. Raise an exception if this process stdout is closed and no more data is available for reading. For hxcpp, the input buffer is in bytes, not characters </doc> **/ static value process_stdout_read( value vp, value str, value pos, value len ) { CHECK_ARGS(); gc_enter_blocking(); # ifdef NEKO_WINDOWS { DWORD nbytes; if( !ReadFile(p->oread,buffer_data(buf)+val_int(pos),val_int(len),&nbytes,NULL) ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_int(nbytes); } # else int nbytes = read(p->oread,buffer_data(buf) + val_int(pos),val_int(len)); if( nbytes <= 0 ) { gc_exit_blocking(); alloc_null(); } gc_exit_blocking(); return alloc_int(nbytes); # endif }
static value sys_sleep( value f ) { val_check(f,number); gc_enter_blocking(); #ifdef HX_WINRT if (!tlsSleepEvent) tlsSleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); WaitForSingleObjectEx(tlsSleepEvent, (int)(val_number(f)*1000), false); #elif defined(NEKO_WINDOWS) Sleep((DWORD)(val_number(f) * 1000)); #elif defined(EPPC) //TODO: Implement sys_sleep for EPPC #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) { gc_exit_blocking(); return alloc_null(); } t = tmp; } } #endif gc_exit_blocking(); return alloc_bool(true); }
/** socket_set_timeout : 'socket -> timout:number? -> void <doc>Set the socket send and recv timeout in seconds to the given value (or null for blocking)</doc> **/ static value socket_set_timeout( value o, value t ) { SOCKET sock = val_sock(o); #ifdef NEKO_WINDOWS int time; if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif gc_enter_blocking(); if( setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } if( setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_bool(true); }
/** sys_stat : string -> { gid => int, uid => int, atime => 'int32, mtime => 'int32, ctime => 'int32, dev => int, ino => int, nlink => int, rdev => int, mode => int, size => int } <doc>Run the [stat] command on the given file or directory.</doc> **/ static value sys_stat( value path ) { #ifdef EPPC return alloc_null(); #else struct stat s; value o; val_check(path,string); gc_enter_blocking(); if( stat(val_string(path),&s) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); o = alloc_empty_object( ); STATF(gid); STATF(uid); STATF32(atime); STATF32(mtime); STATF32(ctime); STATF(dev); STATF(ino); STATF(mode); STATF(nlink); STATF(rdev); STATF(size); STATF(mode); return o; #endif }
/** sys_file_type : string -> string <doc> Return the type of the file. The current values are possible : <ul> <li>[file]</li> <li>[dir]</li> <li>[symlink]</li> <li>[sock]</li> <li>[char]</li> <li>[block]</li> <li>[fifo]</li> </ul> </doc> **/ static value sys_file_type( value path ) { #ifdef EPPC return alloc_null(); #else struct stat s; val_check(path,string); gc_enter_blocking(); if( stat(val_string(path),&s) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); if( s.st_mode & S_IFREG ) return alloc_string("file"); if( s.st_mode & S_IFDIR ) return alloc_string("dir"); if( s.st_mode & S_IFCHR ) return alloc_string("char"); #ifndef NEKO_WINDOWS if( s.st_mode & S_IFLNK ) return alloc_string("symlink"); if( s.st_mode & S_IFBLK ) return alloc_string("block"); if( s.st_mode & S_IFIFO ) return alloc_string("fifo"); if( s.st_mode & S_IFSOCK ) return alloc_string("sock"); #endif return alloc_null(); #endif }
/** host_resolve : string -> 'int32 <doc>Resolve the given host string into an IP address.</doc> **/ static value host_resolve( value host ) { unsigned int ip; val_check(host,string); const char *hostName = val_string(host); gc_enter_blocking(); ip = inet_addr(hostName); if( ip == INADDR_NONE ) { struct hostent *h; # if defined(NEKO_WINDOWS) || defined(NEKO_MAC) || defined(BLACKBERRY) h = gethostbyname(hostName); # else struct hostent hbase; char buf[1024]; int errcode; gethostbyname_r(hostName,&hbase,buf,1024,&h,&errcode); # endif if( h == NULL ) { gc_exit_blocking(); return alloc_null(); } ip = *((unsigned int*)h->h_addr); } gc_exit_blocking(); return alloc_int32(ip); }
/** host_resolve : 'string -> string <doc>Resolve the given host string into an IP address.</doc> **/ static value host_resolve( value host ) { char address[INET6_ADDRSTRLEN]; val_check(host,string); gc_enter_blocking(); const char *hostName = val_string(host); struct addrinfo* addr_result; int result = getaddrinfo(hostName, NULL, NULL, &addr_result); if (result == 0) { if (addr_result->ai_family == AF_INET) { inet_ntop(AF_INET, &((struct sockaddr_in *)addr_result->ai_addr)->sin_addr, address, sizeof(address)); } else { inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr_result->ai_addr)->sin6_addr, address, sizeof(address)); } freeaddrinfo(addr_result); } gc_exit_blocking(); return alloc_string( address ); }
// Finalizer for context void finalize_context( value v) { gc_enter_blocking(); int ret = zmq_term( val_data(v)); gc_exit_blocking(); if (ret != 0) { int err = zmq_errno(); val_throw(alloc_int(err)); } }
/** sys_exists : string -> bool <doc>Returns true if the file or directory exists.</doc> **/ static value sys_exists( value path ) { #if defined(EPPC) || defined(KORE_CONSOLE) return alloc_bool(true); #else val_check(path,string); #ifdef NEKO_WINDOWS const wchar_t* _path = val_wstring(path); gc_enter_blocking(); bool result = GetFileAttributesW(_path) != INVALID_FILE_ATTRIBUTES; #else struct stat st; gc_enter_blocking(); bool result = stat(val_string(path),&st) == 0; #endif gc_exit_blocking(); return alloc_bool(result); #endif }
/** sys_remove_dir : string -> void <doc>Remove a directory. Exception on error</doc> **/ static value sys_remove_dir( value path ) { #if defined(EPPC) || defined(KORE_CONSOLE) return alloc_bool(true); #else val_check(path,string); #ifdef NEKO_WINDOWS const wchar_t* _path = val_wstring(path); gc_enter_blocking(); bool ok = _wrmdir(_path) != 0; #else const char* _path = val_string(path); gc_enter_blocking(); bool ok = rmdir(_path) != 0; #endif gc_exit_blocking(); return alloc_bool(ok); #endif }
value socket_set_fast_send( value o, value b ) { SOCKET sock = val_sock(o); val_check(b,bool); int fast = val_bool(b); gc_enter_blocking(); setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char*)&fast,sizeof(fast)); gc_exit_blocking(); return alloc_null(); }
/** file_flush : 'file -> void <doc>Flush the file buffer</doc> **/ static value file_flush( value o ) { fio *f; val_check_kind(o,k_file); f = val_file(o); gc_enter_blocking(); if( fflush( f->io ) != 0 ) file_error("file_flush",f); gc_exit_blocking(); return alloc_bool(true); }
/** host_local : void -> string <doc>Return the local host name.</doc> **/ static value host_local() { char buf[256]; gc_enter_blocking(); if( gethostname(buf,256) == SOCKET_ERROR ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_string(buf); }
/** sys_remove_dir : string -> void <doc>Remove a directory. Exception on error</doc> **/ static value sys_remove_dir( value path ) { #ifdef EPPC return alloc_bool(true); #else val_check(path,string); gc_enter_blocking(); bool ok = rmdir(val_string(path)) != 0; gc_exit_blocking(); return alloc_bool(ok); #endif }
/** file_seek : 'file -> pos:int -> mode:int -> void <doc>Use [fseek] to move the file pointer.</doc> **/ static value file_seek( value o, value pos, value kind ) { fio *f; val_check_kind(o,k_file); val_check(pos,int); val_check(kind,int); f = val_file(o); gc_enter_blocking(); if( fseek(f->io,val_int(pos),val_int(kind)) != 0 ) file_error("file_seek",f); gc_exit_blocking(); return alloc_bool(true); }
static value socket_accept( value o ) { SOCKET sock = val_sock(o); struct sockaddr_in addr; SockLen addrlen = sizeof(addr); SOCKET s; gc_enter_blocking(); s = accept(sock,(struct sockaddr*)&addr,&addrlen); if( s == INVALID_SOCKET ) return block_error(); gc_exit_blocking(); return alloc_abstract(k_socket,(void *)(socket_int)s); }
/** sys_rename : from:string -> to:string -> void <doc>Rename the file or directory. Exception on error.</doc> **/ static value sys_rename( value path, value newname ) { val_check(path,string); val_check(newname,string); gc_enter_blocking(); if( rename(val_string(path),val_string(newname)) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_bool(true); }
/** sys_exists : string -> bool <doc>Returns true if the file or directory exists.</doc> **/ static value sys_exists( value path ) { #ifdef EPPC return alloc_bool(true); #else struct stat st; val_check(path,string); gc_enter_blocking(); bool result = stat(val_string(path),&st) == 0; gc_exit_blocking(); return alloc_bool(result); #endif }
/** file_tell : 'file -> int <doc>Return the current position in the file</doc> **/ static value file_tell( value o ) { int p; fio *f; val_check_kind(o,k_file); f = val_file(o); gc_enter_blocking(); p = ftell(f->io); if( p == -1 ) file_error("file_tell",f); gc_exit_blocking(); return alloc_int(p); }