96d64b755997c6ca5fcc8b1ffc10e1e3bc846aa8
[cilux] / src / platform / linux / osapi.c
1
2 /* -------------------------------------------------------------------------- */
3
4 #include <errno.h>
5 #include <dlfcn.h>
6 #include <stdarg.h>
7 #include <signal.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/mman.h>
11 #include <netdb.h>
12 #include <sys/types.h>
13 #include <dirent.h>
14 #include <unistd.h>
15
16 /* -------------------------------------------------------------------------- */
17
18 static fd_set rd_fd_set;
19 static fd_set wr_fd_set;
20 static fd_set ex_fd_set;
21
22 /* -------------------------------------------------------------------------- */
23
24 static void signal_terminate(int);
25 static void signal_alarm(int);
26 static void signal_other(int);
27 static void set_timeval_ms(struct timeval* t, int ms);
28
29 /* -------------------------------------------------------------------------- */
30
31 void init_thread(void)
32 {
33         signal(SIGTERM, signal_terminate);
34         signal(SIGINT,  signal_terminate);
35         signal(SIGQUIT, signal_terminate);
36         signal(SIGALRM, signal_alarm);
37         signal(SIGPIPE, signal_other);
38         signal(SIGCHLD, SIG_IGN);
39         signal(SIGHUP,  SIG_IGN);
40         signal(SIGUSR1, SIG_IGN);
41         signal(SIGUSR2, SIG_IGN);
42 }
43
44 void init_gl(void)
45 {
46 }
47
48 void init_net(void)
49 {
50         FD_ZERO(&rd_fd_set);
51         FD_ZERO(&wr_fd_set);
52         FD_ZERO(&ex_fd_set);
53 }
54
55 /* -------------------------------------------------------------------------- */
56
57 OTHER_THREAD void signal_terminate(int signum)
58 {
59         c_running(0);
60 }
61
62 OTHER_THREAD void signal_alarm(int signum)
63 {
64         c_signal(signum);
65 }
66
67 OTHER_THREAD void signal_other(int signum)
68 {
69         c_signal(signum);
70 }
71
72 /* -------------------------------------------------------------------------- */
73
74 void set_callback(k_channel* chan, int rdwr)
75 {
76         if(rdwr & SETCB_RD) FD_SET(chan->priv->SOCK, &rd_fd_set);
77         if(rdwr & SETCB_WR) FD_SET(chan->priv->SOCK, &wr_fd_set);
78 }
79
80 void un_set_callback(k_channel* chan, int rdwr)
81 {
82         if(rdwr & SETCB_RD) FD_CLR(chan->priv->SOCK, &rd_fd_set);
83         if(rdwr & SETCB_WR) FD_CLR(chan->priv->SOCK, &wr_fd_set);
84 }
85
86 void poller(int no_block)
87 {
88         fd_set rd=rd_fd_set;
89         fd_set wr=wr_fd_set;
90         fd_set ex=ex_fd_set;
91
92         k_channel* chan;
93
94         int highest=0;
95         for(chan=k_channels; chan; chan=chan->next){
96                 if(chan->priv->state==CHAN_CLOSE) continue;
97                 if(highest < chan->priv->SOCK) highest=chan->priv->SOCK;
98         }
99
100         struct timeval  t;
101         struct timeval* tp=&t;
102         set_timeval_ms(tp, no_block? 0: LOOP_TICK);
103
104         if(highest==0){
105                 select(0, 0, 0, 0, tp);
106                 next_keys();
107                 if(!no_block) do_regular_things();
108                 return;
109         }
110
111         int len=select(highest+1, &rd, &wr, &ex, tp);
112         GETERRNO(len);
113
114         next_keys();
115
116         if(len==0){
117                 do_regular_things();
118                 return;
119         }
120         if(len== -1){
121                 if(ERRNO==INTERRUPTED) return;
122                 log_net_err("select", ERRNO);
123                 sleep(1);
124                 do_regular_things();
125                 return;
126         }
127
128         for(chan=k_channels; chan; chan=chan->next){
129                 if(FD_ISSET(chan->priv->SOCK, &ex)){
130                         exception_socket(chan);
131                         continue;
132                 }
133                 if(FD_ISSET(chan->priv->SOCK, &wr)){
134                         int err; socklen_t len=sizeof(int);
135                         if(getsockopt(chan->priv->SOCK,
136                                       SOL_SOCKET,
137                                       SO_ERROR, &err, &len) || err){
138                                 exception_socket(chan);
139                                 continue;
140                         }
141                         else{
142                                 writeable_socket(chan);
143                         }
144                 }
145                 if(FD_ISSET(chan->priv->SOCK, &rd)){
146                         readable_socket(chan);
147                 }
148         }
149 }
150
151 void set_timeval_ms(struct timeval* t, int ms)
152 {
153         t->tv_sec=ms/1000;
154         t->tv_usec=(ms-(t->tv_sec)*1000)*1000;
155 }
156
157 char* str_error(int e)
158 {
159         return strerror(e);
160 }
161
162 /* -------------------------------------------------------------------------- */
163
164 void stat_only(char* fullname, k_stat* kstat)
165 {
166         kstat->type=0;
167         struct stat s;
168         if(stat(fullname, &s)) return;
169         kstat->type=s.st_mode & 0170000;
170         kstat->size=s.st_size;
171         kstat->time=s.st_mtime;
172         kstat->perm=s.st_mode & 0007777;
173 }
174
175 FILE_T stat_open(char* fullname, k_stat* kstat)
176 {
177         stat_only(fullname, kstat);
178         if(!kstat->type) return 0;
179         FILE_T filehandle=open(fullname, O_RDONLY);
180         if(filehandle<0) return 0;
181         return filehandle;
182 }
183
184 FILE_T open_only(char* fullname, int wr)
185 {
186         int rw=wr? O_RDWR|O_CREAT|O_TRUNC: O_RDONLY;
187         FILE_T filehandle=open(fullname, rw, 0644);
188         if(filehandle<0) return 0;
189         return filehandle;
190 }
191
192 void* mmap_malloc(void* s, size_t size, int prot, int f, char* fullname, int o)
193 {
194         FILE_T fh=open(fullname, O_RDONLY, 0644);
195         if(fh<0) return MAP_FAILED;
196
197         char* data=k_malloc(size);
198         int charsread=0;
199         int len;
200         do{
201                 len=read(fh, data+charsread, size-charsread);
202                 if(len< 0 && FERRNO(len)==EINTR) continue;
203                 if(len<=0) break;
204                 charsread+=len;
205         } while(charsread<size);
206
207         close(fh);
208         if(len<0 || charsread!=size){ k_free(data); return MAP_FAILED; }
209         return data;
210 }
211
212 void* mmap_name(void* s, size_t size, int prot, int f, char* fullname, int o)
213 {
214         if(!size) return MAP_FAILED;
215         int w=(prot & PROT_WRITE);
216         FILE_T fh=open(fullname, (w? O_RDWR|O_CREAT: O_RDONLY), 0644);
217         if(fh<0) return MAP_FAILED;
218         return mmap(s, size, prot, f, fh, o);
219 }
220
221 /* -------------------------------------------------------------------------- */
222
223 EXPORT void k_random_bytes(char* buf, size_t size)
224 {
225         *(short*)buf=getpid();
226         if(size!=2) k_log_err("Linux randomness not implemented yet!");
227 }
228
229 /* -------------------------------------------------------------------------- */
230
231 EXPORT void* k_malloc(size_t size)
232 {
233         void* p=malloc(size);
234         if(!p){
235                 k_fatal(OOM_STRING);
236         }
237         return p;
238 }
239
240 EXPORT void* k_realloc(void* o, size_t size)
241 {
242         void* p=realloc(o, size);
243         if(!p){
244                 k_fatal(OOM_STRING);
245         }
246         return p;
247 }
248
249 EXPORT void k_free(void* o)
250 {
251         if(o) free(o);
252 }
253
254 EXPORT char* k_strdup(char* s)
255 {
256         if(!s) return 0;
257         char* p=strdup(s);
258         if(!p){
259                 k_fatal(OOM_STRING);
260         }
261         return p;
262 }
263
264 EXPORT void* k_memdup(void* s, size_t size)
265 {
266         void* p=malloc(size);
267         if(!p){
268                 k_fatal(OOM_STRING);
269         }
270         memcpy(p, s, size);
271         return p;
272 }
273
274 /* -------------------------------------------------------------------------- */
275