--- /dev/null
+
+/* -------------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <netdb.h>
+#include <dirent.h>
+
+/* -------------------------------------------------------------------------- */
+
+static fd_set rd_fd_set;
+static fd_set wr_fd_set;
+static fd_set ex_fd_set;
+
+/* -------------------------------------------------------------------------- */
+
+static void signal_terminate(int);
+static void signal_alarm(int);
+static void signal_other(int);
+static void set_timeval_ms(struct timeval* t, int ms);
+
+/* -------------------------------------------------------------------------- */
+
+void init_thread(void)
+{
+ signal(SIGTERM, signal_terminate);
+ signal(SIGINT, signal_terminate);
+ signal(SIGQUIT, signal_terminate);
+ signal(SIGALRM, signal_alarm);
+ signal(SIGPIPE, signal_other);
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+}
+
+void init_gl(void)
+{
+}
+
+void init_net(void)
+{
+ FD_ZERO(&rd_fd_set);
+ FD_ZERO(&wr_fd_set);
+ FD_ZERO(&ex_fd_set);
+}
+
+/* -------------------------------------------------------------------------- */
+
+OTHER_THREAD void signal_terminate(int signum)
+{
+ c_running(0);
+}
+
+OTHER_THREAD void signal_alarm(int signum)
+{
+ c_signal(signum);
+}
+
+OTHER_THREAD void signal_other(int signum)
+{
+ c_signal(signum);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void set_callback(k_channel* chan, int rdwr)
+{
+ if(rdwr & SETCB_RD) FD_SET(chan->priv->SOCK, &rd_fd_set);
+ if(rdwr & SETCB_WR) FD_SET(chan->priv->SOCK, &wr_fd_set);
+}
+
+void un_set_callback(k_channel* chan, int rdwr)
+{
+ if(rdwr & SETCB_RD) FD_CLR(chan->priv->SOCK, &rd_fd_set);
+ if(rdwr & SETCB_WR) FD_CLR(chan->priv->SOCK, &wr_fd_set);
+}
+
+void poller(int no_block)
+{
+ fd_set rd=rd_fd_set;
+ fd_set wr=wr_fd_set;
+ fd_set ex=ex_fd_set;
+
+ k_channel* chan;
+
+ int highest=0;
+ for(chan=k_channels; chan; chan=chan->next){
+ if(chan->priv->state==CHAN_CLOSE) continue;
+ if(highest < chan->priv->SOCK) highest=chan->priv->SOCK;
+ }
+
+ struct timeval t;
+ struct timeval* tp=&t;
+ set_timeval_ms(tp, no_block? 0: LOOP_TICK);
+
+ if(highest==0){
+ select(0, 0, 0, 0, tp);
+ next_keys();
+ if(!no_block) do_regular_things();
+ return;
+ }
+
+ int len=select(highest+1, &rd, &wr, &ex, tp);
+ GETERRNO(len);
+
+ next_keys();
+
+ if(len==0){
+ do_regular_things();
+ return;
+ }
+ if(len== -1){
+ if(ERRNO==INTERRUPTED) return;
+ log_net_err("select", ERRNO);
+ sleep(1);
+ do_regular_things();
+ return;
+ }
+
+ for(chan=k_channels; chan; chan=chan->next){
+ if(FD_ISSET(chan->priv->SOCK, &ex)){
+ exception_socket(chan);
+ continue;
+ }
+ if(FD_ISSET(chan->priv->SOCK, &wr)){
+ int err; socklen_t len=sizeof(int);
+ if(getsockopt(chan->priv->SOCK,
+ SOL_SOCKET,
+ SO_ERROR, &err, &len) || err){
+ exception_socket(chan);
+ continue;
+ }
+ else{
+ writeable_socket(chan);
+ }
+ }
+ if(FD_ISSET(chan->priv->SOCK, &rd)){
+ readable_socket(chan);
+ }
+ }
+}
+
+void set_timeval_ms(struct timeval* t, int ms)
+{
+ t->tv_sec=ms/1000;
+ t->tv_usec=(ms-(t->tv_sec)*1000)*1000;
+}
+
+char* str_error(int e)
+{
+ return strerror(e);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void stat_only(char* fullname, k_stat* kstat)
+{
+ kstat->type=0;
+ struct stat s;
+ if(stat(fullname, &s)) return;
+ kstat->type=s.st_mode & 0170000;
+ kstat->size=s.st_size;
+ kstat->time=s.st_mtime;
+ kstat->perm=s.st_mode & 0007777;
+}
+
+FILE_T stat_open(char* fullname, k_stat* kstat)
+{
+ stat_only(fullname, kstat);
+ if(!kstat->type) return 0;
+ FILE_T filehandle=open(fullname, O_RDONLY);
+ if(filehandle<0) return 0;
+ return filehandle;
+}
+
+FILE_T open_only(char* fullname, int wr)
+{
+ int rw=wr? O_RDWR|O_CREAT|O_TRUNC: O_RDONLY;
+ FILE_T filehandle=open(fullname, rw, 0644);
+ if(filehandle<0) return 0;
+ return filehandle;
+}
+
+void* mmap_malloc(void* s, size_t size, int prot, int f, char* fullname, int o)
+{
+ FILE_T fh=open(fullname, O_RDONLY, 0644);
+ if(fh<0) return MAP_FAILED;
+
+ char* data=k_malloc(size);
+ int charsread=0;
+ int len;
+ do{
+ len=read(fh, data+charsread, size-charsread);
+ if(len< 0 && FERRNO(len)==EINTR) continue;
+ if(len<=0) break;
+ charsread+=len;
+ } while(charsread<size);
+
+ close(fh);
+ if(len<0 || charsread!=size){ k_free(data); return MAP_FAILED; }
+ return data;
+}
+
+void* mmap_name(void* s, size_t size, int prot, int f, char* fullname, int o)
+{
+ if(!size) return MAP_FAILED;
+ int w=(prot & PROT_WRITE);
+ FILE_T fh=open(fullname, (w? O_RDWR|O_CREAT: O_RDONLY), 0644);
+ if(fh<0) return MAP_FAILED;
+ return mmap(s, size, prot, f, fh, o);
+}
+
+/* -------------------------------------------------------------------------- */
+
+EXPORT void k_random_bytes(char* buf, size_t size)
+{
+ *(short*)buf=getpid();
+ if(size!=2) k_log_err("Linux randomness not implemented yet!");
+}
+
+/* -------------------------------------------------------------------------- */
+
+EXPORT void* k_malloc(size_t size)
+{
+ void* p=malloc(size);
+ if(!p){
+ k_fatal(OOM_STRING);
+ }
+ return p;
+}
+
+EXPORT void* k_realloc(void* o, size_t size)
+{
+ void* p=realloc(o, size);
+ if(!p){
+ k_fatal(OOM_STRING);
+ }
+ return p;
+}
+
+EXPORT void k_free(void* o)
+{
+ if(o) free(o);
+}
+
+EXPORT char* k_strdup(char* s)
+{
+ if(!s) return 0;
+ char* p=strdup(s);
+ if(!p){
+ k_fatal(OOM_STRING);
+ }
+ return p;
+}
+
+EXPORT void* k_memdup(void* s, size_t size)
+{
+ void* p=malloc(size);
+ if(!p){
+ k_fatal(OOM_STRING);
+ }
+ memcpy(p, s, size);
+ return p;
+}
+
+/* -------------------------------------------------------------------------- */
+