1 #if defined(__APPLE__) && defined(__MACH__) && !defined(OS_X)
2 # define OS_X
3 #endif
4 
5 #include "rktio_platform.h"
6 
7 #ifdef RKTIO_SYSTEM_WINDOWS
8 # include <winsock2.h>
9 # include <windows.h>
10 #endif
11 #ifdef RKTIO_USE_PTHREADS
12 # include <pthread.h>
13 #endif
14 #ifdef RKTIO_USE_XLOCALE
15 # ifdef RKTIO_USE_XLOCALE_HEADER
16 #  include <xlocale.h>
17 # else
18 #  include <locale.h>
19 # endif
20 #endif
21 
22 #if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_STATIC_FDSET_SIZE)
23 # define USE_DYNAMIC_FDSET_SIZE
24 #endif
25 
26 #ifdef RKTIO_SYSTEM_WINDOWS
27 # define USE_FAR_RKTIO_FDCALLS
28 #endif
29 #ifdef USE_DYNAMIC_FDSET_SIZE
30 # define USE_FAR_RKTIO_FDCALLS
31 #endif
32 #ifdef HAVE_POLL_SYSCALL
33 # define USE_FAR_RKTIO_FDCALLS
34 #endif
35 
36 #if defined(RKTIO_SYSTEM_UNIX) && defined(RKTIO_USE_PTHREADS)
37 # define SUPPORT_BACKGROUND_SLEEP_THREAD
38 struct background_sleep_t;
39 #endif
40 
41 /*========================================================================*/
42 /* File-descriptor actions without a rktio_t                              */
43 /*========================================================================*/
44 
45 intptr_t rktio_internal_fd_system_fd(rktio_fd_t *rfd);
46 rktio_ok_t rktio_internal_close(rktio_t *rktio /* may be NULL */, rktio_fd_t *rfd, int set_error);
47 
48 /*========================================================================*/
49 /* Globals, as gathered into `rktio_t`                                    */
50 /*========================================================================*/
51 
52 struct rktio_t {
53   int errid;
54   int errkind;
55   int errstep;
56 #ifdef RKTIO_SYSTEM_WINDOWS
57   char *last_err_str;
58 #endif
59 
60 #ifdef RKTIO_SYSTEM_UNIX
61   struct group_member_cache_entry_t *group_member_cache;
62   int external_event_fd;
63   int put_external_event_fd;
64   int long_term_poll_set_fd;
65 #endif
66 #ifdef RKTIO_SYSTEM_WINDOWS
67   int windows_nt_or_later;
68   HANDLE break_semaphore;
69   int wsr_size;
70   struct rktio_socket_t *wsr_array;
71   int made_progress;
72   DWORD max_sleep_time;
73   int got_hires_freq;
74   LARGE_INTEGER hires_freq;
75 #endif
76 #ifdef USE_FAR_RKTIO_FDCALLS
77   /* A single fdset that can be reused for immediate actions: */
78   struct rktio_poll_set_t *rktio_global_poll_set;
79 #endif
80 #ifdef RKTIO_GROWABLE_FDSET
81   int max_fd_so_far;
82 #endif
83 
84 #if defined(RKTIO_SYSTEM_WINDOWS) || defined(RKTIO_USE_PTHREADS)
85   int ghbn_started, ghbn_run;
86   struct rktio_addrinfo_lookup_t *ghbn_requests;
87 # ifdef RKTIO_USE_PTHREADS
88   pthread_t ghbn_th;
89   pthread_mutex_t ghbn_lock;
90   pthread_cond_t ghbn_start;
91 # endif
92 # ifdef RKTIO_SYSTEM_WINDOWS
93   HANDLE ghbn_th;
94   HANDLE ghbn_lock;
95   HANDLE ghbn_start;
96 # endif
97 #endif
98 
99 #if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_USE_PTHREADS)
100   struct System_Child *system_children;
101   volatile int need_to_check_children;
102   int in_sigchld_chain;
103   struct rktio_t *next; /* chaining for SIGCHLD handling */
104 #endif
105 #ifdef RKTIO_SYSTEM_WINDOWS
106   uintptr_t process_children_msecs;
107   HANDLE process_job_object;
108 #endif
109 
110 #ifdef HAVE_INOTIFY_SYSCALL
111   struct rin_inotify_state_t *inotify_server;
112 #endif
113 
114 #ifdef RKTIO_SYSTEM_WINDOWS
115   intptr_t wide_buffer_size;
116   wchar_t *wide_buffer;
117 #endif
118 
119 #ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
120   struct rktio_hash_t *locked_fd_process_map;
121 #endif
122 
123 #ifdef RKTIO_SYSTEM_WINDOWS
124   HANDLE hEventLog;
125 #endif
126 
127   int pending_os_signals[RKTIO_NUM_OS_SIGNALS];
128 
129   int processor_count;
130 
131   struct rktio_dll_t *all_dlls;
132   struct rktio_hash_t *dlls_by_name;
133 #ifdef RKTIO_SYSTEM_UNIX
134   char *dll_error;
135 #endif
136 
137 #ifdef SUPPORT_BACKGROUND_SLEEP_THREAD
138   struct background_sleep_t *background;
139 #endif
140 
141 #ifdef OS_X
142   int macos_kernel_version; /* e.g., 10 => 10.6, 15 => 10.11 */
143 #endif
144 
145 #ifdef RKTIO_USE_XLOCALE
146   locale_t locale;
147 #endif
148 };
149 
150 /*========================================================================*/
151 /* Poll sets                                                              */
152 /*========================================================================*/
153 
154 void rktio_alloc_global_poll_set(rktio_t *rktio);
155 void rktio_free_global_poll_set(rktio_t *rktio);
156 int rktio_initialize_signal(rktio_t *rktio);
157 void rktio_free_signal(rktio_t *rktio);
158 
159 #ifdef USE_FAR_RKTIO_FDCALLS
160 
161 rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos);
162 void rktio_fdzero(rktio_poll_set_t *fd);
163 void rktio_fdset(rktio_poll_set_t *fd, intptr_t n);
164 void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n);
165 int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n);
166 
167 # define DECL_FDSET(n, c) rktio_poll_set_t *n
168 # define INIT_DECL_FDSET(r, w, e) { \
169    r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 ); \
170    w = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 ); \
171    e = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 ); \
172  }
173 # define INIT_DECL_RD_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 0 )
174 # define INIT_DECL_WR_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 1 )
175 # define INIT_DECL_ER_FDSET(r) r = RKTIO_GET_FDSET(rktio->rktio_global_poll_set, 2 )
176 
177 # define RKTIO_GET_FDSET(p, n) rktio_get_fdset(p, n)
178 # define RKTIO_FD_ZERO(p) rktio_fdzero(p)
179 # define RKTIO_FD_SET(n, p) rktio_fdset(p, n)
180 # define RKTIO_FD_CLR(n, p) rktio_fdclr(p, n)
181 # define RKTIO_FD_ISSET(n, p) rktio_fdisset(p, n)
182 
183 # if !defined(HAVE_POLL_SYSCALL) && !defined(RKTIO_SYSTEM_WINDOWS)
184 #  ifdef RKTIO_GROWABLE_FDSET
185 #   define RKTIO_FDS(p) ((fd_set *)rktio_resolve_fds(p))
186 void *rktio_resolve_fds(rktio_poll_set_t *fd);
187 #  else
188 #   define RKTIO_FDS(p) ((fd_set *)p)
189 #  endif
190 # endif
191 
192 #else
193 
194 #include <sys/select.h>
195 struct rktio_poll_set_t { fd_set data; int nosleep; };
196 
197 /* Need "far" call to fdzero to deal with `nosleep`: */
198 void rktio_fdzero(rktio_poll_set_t *fd);
199 
200 # define DECL_FDSET(n, c) rktio_poll_set_t n[c]
201 # define INIT_DECL_FDSET(r, w, e) /* empty */
202 # define INIT_DECL_RD_FDSET(r) /* empty */
203 # define INIT_DECL_WR_FDSET(r) /* empty */
204 # define INIT_DECL_ER_FDSET(r) /* empty */
205 
206 # define RKTIO_FDS(p) (&(p)->data)
207 
208 # define RKTIO_GET_FDSET(p, n) ((p)+(n))
209 # define RKTIO_FD_ZERO(p) rktio_fdzero(p)
210 # define RKTIO_FD_SET(n, p) FD_SET(n, RKTIO_FDS(p))
211 # define RKTIO_FD_CLR(n, p) FD_CLR(n, RKTIO_FDS(p))
212 # define RKTIO_FD_ISSET(n, p) FD_ISSET(n, RKTIO_FDS(p))
213 
214 #endif
215 
216 void rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds);
217 void rktio_clean_fd_set(rktio_poll_set_t *fds);
218 int rktio_get_fd_limit(rktio_poll_set_t *fds);
219 
220 #if defined(HAVE_KQUEUE_SYSCALL) || defined(HAVE_EPOLL_SYSCALL)
221 int rktio_ltps_get_fd(rktio_ltps_t *lt);
222 #else
223 rktio_poll_set_t *rktio_ltps_get_fd_set(rktio_ltps_t *lt);
224 #endif
225 
226 #if defined(HAVE_POLL_SYSCALL)
227 int rktio_get_poll_count(rktio_poll_set_t *fds);
228 struct pollfd *rktio_get_poll_fd_array(rktio_poll_set_t *fds);
229 #endif
230 
231 /*========================================================================*/
232 /* Network                                                                */
233 /*========================================================================*/
234 
235 void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd);
236 
237 int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error);
238 void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd);
239 void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd);
240 rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd);
241 
242 int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
243 int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
244 
245 intptr_t rktio_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t len);
246 intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len);
247 
248 void rktio_free_ghbn(rktio_t *rktio);
249 
250 const char *rktio_gai_strerror(rktio_t *rktio, int errnum);
251 
252 /*========================================================================*/
253 /* Processes                                                              */
254 /*========================================================================*/
255 
256 int rktio_process_init(rktio_t *rktio);
257 void rktio_process_deinit(rktio_t *rktio);
258 
259 /*========================================================================*/
260 /* Strings                                                                */
261 /*========================================================================*/
262 
263 #ifdef RKTIO_SYSTEM_WINDOWS
264 # define MSC_IZE(n) _ ## n
265 # define MSC_W_IZE(n) _w ## n
266 # define MSC_WIDE_PATH_temp(n) WIDE_PATH_temp(n)
267 #else
268 # define MSC_IZE(n) n
269 # define MSC_W_IZE(n) MSC_IZE(n)
270 # define MSC_WIDE_PATH_temp(n) n
271 #endif
272 
273 #ifdef RKTIO_SYSTEM_WINDOWS
274 
275 wchar_t *rktio_convert_to_wchar(rktio_t *rktio, const char *s, int do_copy);
276 char *rktio_convert_from_wchar(const wchar_t *ws, int free_given);
277 
278 # define WIDE_PATH_temp(s) rktio_convert_to_wchar(rktio, s, 0)
279 # define WIDE_PATH_copy(s) rktio_convert_to_wchar(rktio, s, 1)
280 
281 # define NARROW_PATH_copy(ws) rktio_convert_from_wchar(ws, 0)
282 # define NARROW_PATH_copy_then_free(ws) rktio_convert_from_wchar(ws, 1)
283 
284 typedef wchar_t WIDE_PATH_t;
285 
286 #else
287 
288 typedef char WIDE_PATH_t;
289 
290 #endif
291 
292 void rktio_convert_init(rktio_t *rktio);
293 void rktio_convert_deinit(rktio_t *rktio);
294 
295 /*========================================================================*/
296 /* Hash table                                                             */
297 /*========================================================================*/
298 
299 /* Maps keys that aren't -1 to non-NULL values */
300 
301 typedef struct rktio_hash_t rktio_hash_t;
302 
303 rktio_hash_t *rktio_hash_new(void);
304 void rktio_hash_free(rktio_hash_t *ht, int free_values);
305 int rktio_hash_is_empty(rktio_hash_t *ht);
306 void *rktio_hash_get(rktio_hash_t *ht, intptr_t key);
307 void rktio_hash_remove(rktio_hash_t *ht, intptr_t key, int dont_rehash);
308 void rktio_hash_set(rktio_hash_t *ht, intptr_t key, void *v);
309 
310 intptr_t rktio_hash_size(rktio_hash_t *ht);
311 intptr_t rktio_hash_get_key(rktio_hash_t *ht, intptr_t i);
312 
313 intptr_t rktio_hash_string(const char *s);
314 
315 /*========================================================================*/
316 /* Misc                                                                   */
317 /*========================================================================*/
318 
319 /* On Mac OS, for example, `read` and `write` expect a value less than
320    2GB. Use 32MB as a limit that is very large, but still likely small
321    enough for all OSes. */
322 #define MAX_READ_WRITE_REQUEST_BYTES (32 * 1048576)
323 #define LIMIT_REQUEST_SIZE(n) (((n) > MAX_READ_WRITE_REQUEST_BYTES) ? MAX_READ_WRITE_REQUEST_BYTES : (n))
324 
325 void rktio_get_posix_error(rktio_t *rktio);
326 #define get_posix_error() rktio_get_posix_error(rktio)
327 
328 void rktio_set_racket_error(rktio_t *rktio, int errid);
329 #define set_racket_error(e) rktio_set_racket_error(rktio, e)
330 
331 #ifdef RKTIO_SYSTEM_WINDOWS
332 void rktio_get_windows_error(rktio_t *rktio);
333 # define get_windows_error() rktio_get_windows_error(rktio)
334 void rktio_set_windows_error(rktio_t *rktio, int errid);
335 # define set_windows_error(errid) rktio_set_windows_error(rktio, errid)
336 #endif
337 
338 void rktio_error_clean(rktio_t *rktio);
339 
340 void rktio_dll_clean(rktio_t *rktio);
341 #ifdef RKTIO_SYSTEM_WINDOWS
342 HANDLE rktio_load_library(rktio_const_string_t name);
343 void *rktio_get_proc_address(HANDLE m, rktio_const_string_t name);
344 #endif
345 
346 #if defined(USE_FNDELAY_O_NONBLOCK)
347 # define RKTIO_NONBLOCKING FNDELAY
348 #else
349 # define RKTIO_NONBLOCKING O_NONBLOCK
350 #endif
351 
352 #ifndef RKTIO_BINARY
353 # define RKTIO_BINARY 0
354 #endif
355 
356 #ifdef RKTIO_SYSTEM_UNIX
357 int rktio_reliably_close_err(intptr_t s);
358 void rktio_reliably_close(intptr_t s);
359 int rktio_close_fds_len();
360 void rktio_close_fds_after_fork(int len, int skip1, int skip2, int skip3);
361 #endif
362 
363 int rktio_system_fd_is_terminal(rktio_t *rktio, intptr_t fd);
364 
365 #if defined(RKTIO_USE_PTHREADS) && !defined(NO_PTHREAD_CANCEL)
366 # define RKTIO_USE_PENDING_OPEN
367 #endif
368 
369 #ifdef RKTIO_USE_PENDING_OPEN
370 struct open_in_thread_t;
371 rktio_fd_t *rktio_pending_system_fd(rktio_t *rktio, struct open_in_thread_t *oit, int modes);
372 void rktio_update_system_fd(rktio_t *rktio, rktio_fd_t *rfd, int fd, int modes);
373 int rktio_fd_is_pending_open(rktio_t *rktio, rktio_fd_t *rfd);
374 int rktio_pending_open_poll(rktio_t *rktio, rktio_fd_t *rfd, struct open_in_thread_t *oit);
375 void rktio_poll_add_pending_open(rktio_t *rktio, rktio_fd_t *rfd, struct open_in_thread_t *oit, rktio_poll_set_t *fds);
376 void rktio_pending_open_detach(rktio_t *rktio, struct open_in_thread_t *oit);
377 void rktio_pending_open_attach(rktio_t *rktio, struct open_in_thread_t *oit);
378 void rktio_pending_open_retain(rktio_t *rktio, struct open_in_thread_t *oit);
379 int rktio_pending_open_release(rktio_t *rktio, struct open_in_thread_t *oit);
380 #endif
381 
382 void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars);
383 
384 void rktio_stop_fs_change(rktio_t *rktio);
385 
386 void rktio_init_time(rktio_t *rktio);
387 
388 void rktio_init_cpu(rktio_t *rktio);
389 
390 #ifdef RKTIO_SYSTEM_WINDOWS
391 int rktio_winsock_init(rktio_t *rktio);
392 void rktio_winsock_done(rktio_t *rktio);
393 #endif
394 void rktio_init_wide(rktio_t *rktio);
395 
396 #ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
397 void rktio_release_lockf(rktio_t *rktio, int fd);
398 #endif
399 
400 int rktio_make_os_pipe(rktio_t *rktio, intptr_t *a, int flags);
401 
402 #ifdef RKTIO_SYSTEM_UNIX
403 char **rktio_get_environ_array(void);
404 #endif
405 
406 void rktio_syslog_init(rktio_t* rktio);
407 void rktio_syslog_clean(rktio_t* rktio);
408 
409 void rktio_stop_background(rktio_t *rktio);
410 
411 #ifdef USE_TRANSITIONAL_64_FILE_OPS
412 # define BIG_OFF_T_IZE(n) n ## 64
413 #else
414 # define BIG_OFF_T_IZE(n) n
415 #endif
416 
417 char *rktio_strndup(char *s, intptr_t len);
418 
419 #ifdef RKTIO_SYSTEM_UNIX
420 void rktio_set_signal_handler(int sig_id, void (*proc)(int));
421 void rktio_restore_modified_signal_handlers();
422 #endif
423 void rktio_forget_os_signal_handler(rktio_t *rktio);
424 
425 
426 #ifdef RKTIO_SYSTEM_WINDOWS
427 int rktio_system_time_is_dst(SYSTEMTIME *st, TIME_ZONE_INFORMATION *_tz);
428 #endif
429 
430 #ifdef RKTIO_SYSTEM_WINDOWS
431 void rktio_console_ctl_c(void);
432 void rktio_set_console_handler(void);
433 #endif
434