xref: /drstd/dlibc/src/unix/header/unistd/mod.rs (revision 9670759b785600bf6315e4173e46a602f16add7a)
1 //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
2 
3 use core::{convert::TryFrom, mem, ptr, slice};
4 
5 use crate::unix::{
6     c_str::CStr,
7     header::{
8         errno, fcntl, limits, stdlib::getenv, sys_ioctl, sys_time, sys_utsname, termios,
9     },
10 };
11 use alloc::collections::LinkedList;
12 use crate::unix::platform;
13 pub use self::{brk::*, getopt::*, pathconf::*, sysconf::*};
14 
15 use ioctl;
16 use TIOCSPGRP;
17 use TIOCGPGRP;
18 use TCXONC;
19 
20 use O_WRONLY;
21 
22 mod brk;
23 mod getopt;
24 mod pathconf;
25 mod sysconf;
26 
27 pub use self::brk::*;
28 
29 pub const F_OK: ::c_int = 0;
30 pub const R_OK: ::c_int = 4;
31 pub const W_OK: ::c_int = 2;
32 pub const X_OK: ::c_int = 1;
33 
34 pub const SEEK_SET: ::c_int = 0;
35 pub const SEEK_CUR: ::c_int = 1;
36 pub const SEEK_END: ::c_int = 2;
37 
38 pub const F_ULOCK: ::c_int = 0;
39 pub const F_LOCK: ::c_int = 1;
40 pub const F_TLOCK: ::c_int = 2;
41 pub const F_TEST: ::c_int = 3;
42 
43 pub const STDIN_FILENO: ::c_int = 0;
44 pub const STDOUT_FILENO: ::c_int = 1;
45 pub const STDERR_FILENO: ::c_int = 2;
46 
47 #[cfg(not(target_os = "dragonos"))]
48 #[thread_local]
49 pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
50 
51 /// due to dragonos not supporting thread_local, we need to use a static directly
52 #[cfg(target_os = "dragonos")]
53 pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
54 
55 unsafe fn init_fork_hooks<'a>() -> &'a mut [LinkedList<extern "C" fn()>; 3] {
56     // Transmute the lifetime so we can return here. Should be safe as
57     // long as one does not access the original fork_hooks.
58     mem::transmute(
59         fork_hooks_static
60             .get_or_insert_with(|| [LinkedList::new(), LinkedList::new(), LinkedList::new()]),
61     )
62 }
63 
64 #[no_mangle]
65 pub extern "C" fn _exit(status: ::c_int) {
66     platform::pal::exit(status)
67 }
68 
69 pub unsafe fn access(path: *const ::c_char, mode: ::c_int) -> ::c_int {
70     platform::pal::access(path, mode)
71 }
72 
73 #[no_mangle]
74 pub extern "C" fn alarm(seconds: ::c_uint) -> ::c_uint {
75     let mut timer = sys_time::itimerval {
76         it_value: sys_time::timeval {
77             tv_sec: seconds as ::time_t,
78             tv_usec: 0,
79         },
80         ..Default::default()
81     };
82     let errno_backup = unsafe { platform::errno };
83     let secs = if ::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
84         0
85     } else {
86         timer.it_value.tv_sec as ::c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
87     };
88     unsafe {
89         platform::errno = errno_backup;
90     }
91 
92     secs
93 }
94 
95 // #[no_mangle]
96 // pub unsafe extern "C" fn chdir(path: *const ::c_char) -> ::c_int {
97 //     platform::pal::chdir(path)
98 // }
99 
100 #[no_mangle]
101 pub extern "C" fn chroot(path: *const ::c_char) -> ::c_int {
102     // TODO: Implement
103     unsafe {
104         platform::errno = crate::unix::header::errno::EPERM;
105     }
106 
107     -1
108 }
109 
110 // #[no_mangle]
111 // pub unsafe extern "C" fn chown(path: *const ::c_char, owner: ::uid_t, group: ::gid_t) -> ::c_int {
112 //     platform::pal::chown(path, owner, group)
113 // }
114 
115 // #[no_mangle]
116 // pub extern "C" fn close(fildes: ::c_int) -> ::c_int {
117 //     platform::pal::close(fildes)
118 // }
119 
120 // #[no_mangle]
121 // pub extern "C" fn confstr(name: ::c_int, buf: *mut ::c_char, len: ::size_t) -> ::size_t {
122 //     unimplemented!();
123 // }
124 
125 // #[no_mangle]
126 // pub extern "C" fn crypt(key: *const ::c_char, salt: *const ::c_char) -> *mut ::c_char {
127 //     unimplemented!();
128 // }
129 
130 // #[no_mangle]
131 // pub extern "C" fn dup(fildes: ::c_int) -> ::c_int {
132 //     platform::pal::dup(fildes)
133 // }
134 
135 // #[no_mangle]
136 // pub extern "C" fn dup2(fildes: ::c_int, fildes2: ::c_int) -> ::c_int {
137 //     platform::pal::dup2(fildes, fildes2)
138 // }
139 
140 // #[no_mangle]
141 // pub extern "C" fn encrypt(block: [::c_char; 64], edflag: ::c_int) {
142 //     unimplemented!();
143 // }
144 
145 // #[no_mangle]
146 // pub extern "C" fn execl(path: *const ::c_char, args: *const *mut ::c_char) -> ::c_int {
147 //     unimplemented!();
148 // }
149 
150 // #[no_mangle]
151 // pub extern "C" fn execle(
152 //   path: *const ::c_char,
153 //   args: *const *mut ::c_char,
154 //   envp: *const *mut ::c_char,
155 // ) -> ::c_int {
156 //     unimplemented!();
157 // }
158 
159 // #[no_mangle]
160 // pub extern "C" fn execlp(file: *const ::c_char, args: *const *mut ::c_char) -> ::c_int {
161 //     unimplemented!();
162 // }
163 
164 #[no_mangle]
165 pub unsafe extern "C" fn execv(path: *const ::c_char, argv: *const *const ::c_char) -> ::c_int {
166     ::execve(path, argv, platform::environ as *const *const ::c_char)
167 }
168 
169 // #[no_mangle]
170 // pub unsafe extern "C" fn execve(
171 //     path: *const ::c_char,
172 //     argv: *const *mut ::c_char,
173 //     envp: *const *mut ::c_char,
174 // ) -> ::c_int {
175 //     platform::pal::execve(path, argv as *const *const i8, envp as *const *const i8)
176 // }
177 
178 #[cfg(target_os = "linux")]
179 const PATH_SEPARATOR: u8 = b':';
180 
181 #[cfg(target_os = "dragonos")]
182 const PATH_SEPARATOR: u8 = b':';
183 
184 #[cfg(target_os = "redox")]
185 const PATH_SEPARATOR: u8 = b';';
186 
187 #[no_mangle]
188 pub unsafe extern "C" fn execvp(file: *const ::c_char, argv: *const *const ::c_char) -> ::c_int {
189     let file = CStr::from_ptr(file);
190 
191     if file.to_bytes().contains(&b'/')
192         || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':'))
193     {
194         execv(file.as_ptr(), argv)
195     } else {
196         let mut error = errno::ENOENT;
197 
198         let path_env = getenv(c_str!("PATH\0").as_ptr());
199         if !path_env.is_null() {
200             let path_env = CStr::from_ptr(path_env);
201             for path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
202                 let mut program = path.to_vec();
203                 program.push(b'/');
204                 program.extend_from_slice(file.to_bytes());
205                 program.push(b'\0');
206 
207                 let program_c = CStr::from_bytes_with_nul(&program).unwrap();
208                 execv(program_c.as_ptr(), argv);
209 
210                 match platform::errno {
211                     errno::ENOENT => (),
212                     other => error = other,
213                 }
214             }
215         }
216 
217         platform::errno = error;
218         -1
219     }
220 }
221 
222 // #[no_mangle]
223 // pub extern "C" fn fchown(fildes: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int {
224 //     platform::pal::fchown(fildes, owner, group)
225 // }
226 
227 // #[no_mangle]
228 // pub extern "C" fn fchdir(fildes: ::c_int) -> ::c_int {
229 //     platform::pal::fchdir(fildes)
230 // }
231 
232 // #[no_mangle]
233 pub extern "C" fn fdatasync(fildes: ::c_int) -> ::c_int {
234     unimplemented!();
235 }
236 
237 #[no_mangle]
238 pub extern "C" fn fork() -> ::pid_t {
239     let fork_hooks = unsafe { init_fork_hooks() };
240     for prepare in &fork_hooks[0] {
241         prepare();
242     }
243     let pid = platform::pal::fork();
244     if pid == 0 {
245         for child in &fork_hooks[2] {
246             child();
247         }
248     } else if pid != -1 {
249         for parent in &fork_hooks[1] {
250             parent();
251         }
252     }
253     pid
254 }
255 
256 // #[no_mangle]
257 // pub extern "C" fn fsync(fildes: ::c_int) -> ::c_int {
258 //     platform::pal::fsync(fildes)
259 // }
260 
261 // #[no_mangle]
262 // pub extern "C" fn ftruncate(fildes: ::c_int, length: ::off_t) -> ::c_int {
263 //     platform::pal::ftruncate(fildes, length)
264 // }
265 
266 #[no_mangle]
267 pub extern "C" fn getcwd(mut buf: *mut ::c_char, mut size: ::size_t) -> *mut ::c_char {
268     let alloc = buf.is_null();
269     let mut stack_buf = [0; limits::PATH_MAX];
270     if alloc {
271         buf = stack_buf.as_mut_ptr();
272         size = stack_buf.len();
273     }
274 
275     let ret = platform::pal::getcwd(buf, size);
276     if ret.is_null() {
277         return ptr::null_mut();
278     }
279 
280     if alloc {
281         let len = stack_buf
282             .iter()
283             .position(|b| *b == 0)
284             .expect("no nul-byte in getcwd string")
285             + 1;
286         let heap_buf = unsafe { platform::alloc(len) as *mut ::c_char };
287         for i in 0..len {
288             unsafe {
289                 *heap_buf.add(i) = stack_buf[i];
290             }
291         }
292         heap_buf
293     } else {
294         ret
295     }
296 }
297 
298 // #[no_mangle]
299 pub extern "C" fn getdtablesize() -> ::c_int {
300     unimplemented!();
301 }
302 
303 // #[no_mangle]
304 // pub extern "C" fn getegid() -> ::gid_t {
305 //     platform::pal::getegid()
306 // }
307 
308 // #[no_mangle]
309 // pub extern "C" fn geteuid() -> ::uid_t {
310 //     platform::pal::geteuid()
311 // }
312 
313 // #[no_mangle]
314 // pub extern "C" fn getgid() -> ::gid_t {
315 //     platform::pal::getgid()
316 // }
317 
318 // #[no_mangle]
319 // pub extern "C" fn getgroups(gidsetsize: ::c_int, grouplist: *mut ::gid_t) -> ::c_int {
320 //     unimplemented!();
321 // }
322 
323 // #[no_mangle]
324 // pub extern "C" fn gethostid() -> ::c_long {
325 //     unimplemented!();
326 // }
327 
328 #[no_mangle]
329 pub unsafe extern "C" fn gethostname(mut name: *mut ::c_char, mut len: ::size_t) -> ::c_int {
330     let mut uts = mem::MaybeUninit::<::utsname>::uninit();
331     let err = platform::pal::uname(uts.as_mut_ptr());
332     if err < 0 {
333         mem::forget(uts);
334         return err;
335     }
336     for c in uts.assume_init().nodename.iter() {
337         if len == 0 {
338             break;
339         }
340         len -= 1;
341 
342         *name = *c;
343 
344         if *name == 0 {
345             // We do want to copy the zero also, so we check this after the copying.
346             break;
347         }
348 
349         name = name.offset(1);
350     }
351     0
352 }
353 
354 #[no_mangle]
355 pub unsafe extern "C" fn getlogin() -> *mut ::c_char {
356     static mut LOGIN: [::c_char; 256] = [0; 256];
357     if getlogin_r(LOGIN.as_mut_ptr(), LOGIN.len()) == 0 {
358         LOGIN.as_mut_ptr()
359     } else {
360         ptr::null_mut()
361     }
362 }
363 
364 #[no_mangle]
365 pub extern "C" fn getlogin_r(name: *mut ::c_char, namesize: ::size_t) -> ::c_int {
366     //TODO: Determine correct getlogin result on Redox
367     unsafe { platform::errno = errno::ENOENT };
368     -1
369 }
370 
371 #[no_mangle]
372 pub extern "C" fn getpagesize() -> ::c_int {
373     match ::c_int::try_from(sysconf(_SC_PAGESIZE)) {
374         Ok(page_size) => page_size,
375         Err(_) => {
376             /* Behavior not specified by POSIX for this case. The -1
377              * value mimics sysconf()'s behavior, though.
378              *
379              * As specified for the limits.h header, the minimum
380              * acceptable value for {PAGESIZE} is 1. The -1 value thus
381              * cannot be mistaken for an acceptable value.
382              *
383              * POSIX does not specify any possible errors for this
384              * function, hence no errno setting. */
385             -1
386         }
387     }
388 }
389 
390 // #[no_mangle]
391 // pub extern "C" fn getpass(prompt: *const ::c_char) -> *mut ::c_char {
392 //     unimplemented!();
393 // }
394 
395 // #[no_mangle]
396 // pub extern "C" fn getpgid(pid: ::pid_t) -> ::pid_t {
397 //     platform::pal::getpgid(pid)
398 // }
399 
400 #[no_mangle]
401 pub extern "C" fn getpgrp() -> ::pid_t {
402     platform::pal::getpgid(platform::pal::getpid())
403 }
404 
405 // #[no_mangle]
406 // pub extern "C" fn getpid() -> ::pid_t {
407 //     platform::pal::getpid()
408 // }
409 
410 // #[no_mangle]
411 // pub extern "C" fn getppid() -> ::pid_t {
412 //     platform::pal::getppid()
413 // }
414 
415 // #[no_mangle]
416 // pub extern "C" fn getsid(pid: ::pid_t) -> ::pid_t {
417 //     platform::pal::getsid(pid)
418 // }
419 
420 // #[no_mangle]
421 // pub extern "C" fn getuid() -> ::uid_t {
422 //     platform::pal::getuid()
423 // }
424 
425 #[no_mangle]
426 pub extern "C" fn getwd(path_name: *mut ::c_char) -> *mut ::c_char {
427     getcwd(path_name, limits::PATH_MAX)
428 }
429 
430 #[no_mangle]
431 pub extern "C" fn isatty(fd: ::c_int) -> ::c_int {
432     let mut t = termios::termios::default();
433     if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } {
434         1
435     } else {
436         0
437     }
438 }
439 
440 // #[no_mangle]
441 // pub unsafe extern "C" fn lchown(path: *const ::c_char, owner: ::uid_t, group: ::gid_t) -> ::c_int {
442 //     platform::pal::lchown(path, owner, group)
443 // }
444 
445 // #[no_mangle]
446 // pub unsafe extern "C" fn link(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int {
447 //     platform::pal::link(path1, path2)
448 // }
449 
450 // #[no_mangle]
451 // pub extern "C" fn lockf(fildes: ::c_int, function: ::c_int, size: ::off_t) -> ::c_int {
452 //     unimplemented!();
453 // }
454 
455 // #[no_mangle]
456 // pub extern "C" fn lseek(fildes: ::c_int, offset: ::off_t, whence: ::c_int) -> ::off_t {
457 //     platform::pal::lseek(fildes, offset, whence)
458 // }
459 
460 // #[no_mangle]
461 pub extern "C" fn nice(incr: ::c_int) -> ::c_int {
462     unimplemented!();
463 }
464 
465 // #[no_mangle]
466 pub extern "C" fn pause() -> ::c_int {
467     unimplemented!();
468 }
469 
470 #[no_mangle]
471 pub unsafe extern "C" fn pipe(fildes: *mut ::c_int) -> ::c_int {
472     ::pipe2(fildes, 0)
473 }
474 
475 // #[no_mangle]
476 // pub unsafe extern "C" fn pipe2(fildes: *mut ::c_int, flags: ::c_int) -> ::c_int {
477 //     platform::pal::pipe2(fildes, flags)
478 // }
479 
480 #[no_mangle]
481 pub unsafe extern "C" fn pread(fildes: ::c_int, buf: *mut ::c_void, nbyte: ::size_t, offset: ::off_t) -> ::ssize_t {
482     //TODO: better pread using system calls
483 
484     let previous = ::lseek(fildes, offset, SEEK_SET);
485     if previous == -1 {
486         return -1;
487     }
488 
489     let res = ::read(fildes, buf, nbyte);
490     if res < 0 {
491         return res;
492     }
493 
494     if ::lseek(fildes, previous, SEEK_SET) == -1 {
495         return -1;
496     }
497 
498     res
499 }
500 
501 #[no_mangle]
502 pub extern "C" fn pthread_atfork(
503     prepare: Option<extern "C" fn()>,
504     parent: Option<extern "C" fn()>,
505     child: Option<extern "C" fn()>,
506 ) -> ::c_int {
507     let fork_hooks = unsafe { init_fork_hooks() };
508     if let Some(prepare) = prepare {
509         fork_hooks[0].push_back(prepare);
510     }
511     if let Some(parent) = parent {
512         fork_hooks[1].push_back(parent);
513     }
514     if let Some(child) = child {
515         fork_hooks[2].push_back(child);
516     }
517     0
518 }
519 
520 #[no_mangle]
521 pub unsafe extern "C" fn pwrite(
522     fildes: ::c_int,
523     buf: *const ::c_void,
524     nbyte: ::size_t,
525     offset: ::off_t,
526 ) -> ::ssize_t {
527     //TODO: better pwrite using system calls
528 
529     let previous = ::lseek(fildes, offset, SEEK_SET);
530     if previous == -1 {
531         return -1;
532     }
533 
534     let res = ::write(fildes, buf, nbyte);
535     if res < 0 {
536         return res;
537     }
538 
539     if ::lseek(fildes, previous, SEEK_SET) == -1 {
540         return -1;
541     }
542 
543     res
544 }
545 
546 // #[no_mangle]
547 // pub extern "C" fn read(fildes: ::c_int, buf: *const ::c_void, nbyte: ::size_t) -> ::ssize_t {
548 //     trace_expr!(
549 //         platform::pal::read(fildes, buf as *mut ::c_void,nbyte),
550 //         "read({}, {:p}, {})",
551 //         fildes,
552 //         buf,
553 //         nbyte
554 //     )
555 // }
556 
557 // #[no_mangle]
558 // pub unsafe extern "C" fn readlink(
559 //     path: *const ::c_char,
560 //     buf: *mut ::c_char,
561 //     bufsize: ::size_t,
562 // ) -> ::ssize_t {
563 //     platform::pal::readlink(path, buf,bufsize)
564 // }
565 
566 // #[no_mangle]
567 // pub unsafe extern "C" fn rmdir(path: *const ::c_char) -> ::c_int {
568 //     platform::pal::rmdir(path)
569 // }
570 
571 #[no_mangle]
572 pub extern "C" fn setgid(gid: ::gid_t) -> ::c_int {
573     platform::pal::setregid(gid, gid)
574 }
575 
576 // #[no_mangle]
577 // pub extern "C" fn setpgid(pid: ::pid_t, pgid: ::pid_t) -> ::c_int {
578 //     platform::pal::setpgid(pid, pgid)
579 // }
580 
581 #[no_mangle]
582 pub unsafe extern "C" fn setpgrp() -> ::pid_t {
583     ::setpgid(0, 0)
584 }
585 
586 // #[no_mangle]
587 // pub extern "C" fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int {
588 //     platform::pal::setregid(rgid, egid)
589 // }
590 
591 // #[no_mangle]
592 // pub extern "C" fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int {
593 //     platform::pal::setreuid(ruid, euid)
594 // }
595 
596 // #[no_mangle]
597 // pub extern "C" fn setsid() -> ::pid_t {
598 //     unimplemented!();
599 // }
600 
601 // #[no_mangle]
602 // pub extern "C" fn setuid(uid: ::uid_t) -> ::c_int {
603 //     platform::pal::setreuid(uid, uid)
604 // }
605 
606 #[no_mangle]
607 pub extern "C" fn sleep(seconds: ::c_uint) -> ::c_uint {
608     let rqtp = ::timespec {
609         tv_sec: seconds as ::time_t,
610         tv_nsec: 0,
611     };
612     let rmtp = ptr::null_mut();
613     platform::pal::nanosleep(&rqtp, rmtp);
614     0
615 }
616 
617 #[no_mangle]
618 pub extern "C" fn swab(src: *const ::c_void, dest: *mut ::c_void, nbytes: ::ssize_t) {
619     if nbytes <= 0 {
620         return;
621     }
622     let number_of_swaps = nbytes / 2;
623     let mut offset = 0;
624     for i in 0..number_of_swaps {
625         unsafe {
626             src.offset(offset).copy_to(dest.offset(offset + 1), 1);
627             src.offset(offset + 1).copy_to(dest.offset(offset), 1);
628         }
629         offset += 2;
630     }
631 }
632 
633 // #[no_mangle]
634 // pub unsafe extern "C" fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int {
635 //     platform::pal::symlink(path1, path2)
636 // }
637 
638 // #[no_mangle]
639 pub extern "C" fn sync() {
640     unimplemented!();
641 }
642 
643 #[no_mangle]
644 pub extern "C" fn tcgetpgrp(fd: ::c_int) -> ::pid_t {
645     let mut pgrp = 0;
646     if unsafe { ioctl(fd, TIOCGPGRP, &mut pgrp as *mut ::pid_t as *mut ::c_void) } < 0 {
647         return -1;
648     }
649     pgrp
650 }
651 
652 #[no_mangle]
653 pub extern "C" fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int {
654     if unsafe { ioctl(fd, TIOCSPGRP, &pgrp as *const ::pid_t as *mut ::c_void) } < 0 {
655         return -1;
656     }
657     pgrp
658 }
659 
660 #[no_mangle]
661 pub extern "C" fn truncate(path: *const ::c_char, length: ::off_t) -> ::c_int {
662     let fd = platform::pal::open(path, ::O_WRONLY, 0);
663     if fd < 0 {
664         return -1;
665     }
666 
667     let res = unsafe{::ftruncate(fd, length)};
668 
669     platform::pal::close(fd);
670 
671     res
672 }
673 
674 #[no_mangle]
675 pub unsafe extern "C" fn ttyname(fildes: ::c_int) -> *mut ::c_char {
676     static mut TTYNAME: [::c_char; 4096] = [0; 4096];
677     if ttyname_r(fildes, TTYNAME.as_mut_ptr(), TTYNAME.len()) == 0 {
678         TTYNAME.as_mut_ptr()
679     } else {
680         ptr::null_mut()
681     }
682 }
683 
684 #[no_mangle]
685 pub extern "C" fn ttyname_r(fildes: ::c_int, name: *mut ::c_char, namesize: ::size_t) -> ::c_int {
686     let name = unsafe { slice::from_raw_parts_mut(name as *mut u8, namesize) };
687     if name.is_empty() {
688         return errno::ERANGE;
689     }
690 
691     let len = platform::pal::fpath(fildes,
692         (&mut name[..namesize - 1]).as_ptr() as *const i8
693     );
694     if len < 0 {
695         return unsafe { -platform::errno };
696     }
697     name[len as usize] = 0;
698 
699     0
700 }
701 
702 #[no_mangle]
703 pub extern "C" fn ualarm(usecs: ::useconds_t, interval: ::useconds_t) -> ::useconds_t {
704     let mut timer = sys_time::itimerval {
705         it_value: sys_time::timeval {
706             tv_sec: 0,
707             tv_usec: usecs as ::suseconds_t,
708         },
709         it_interval: sys_time::timeval {
710             tv_sec: 0,
711             tv_usec: interval as ::suseconds_t,
712         },
713     };
714     let errno_backup = unsafe { platform::errno };
715     let ret = if ::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
716         0
717     } else {
718         timer.it_value.tv_sec as ::useconds_t * 1_000_000 + timer.it_value.tv_usec as ::useconds_t
719     };
720     unsafe {
721         platform::errno = errno_backup;
722     }
723 
724     ret
725 }
726 
727 // #[no_mangle]
728 // pub unsafe extern "C" fn unlink(path: *const ::c_char) -> ::c_int {
729 //     platform::pal::unlink(path)
730 // }
731 
732 #[no_mangle]
733 pub extern "C" fn usleep(useconds: ::useconds_t) -> ::c_int {
734     let rqtp = ::timespec {
735         tv_sec: (useconds / 1_000_000) as ::time_t,
736         tv_nsec: ((useconds % 1_000_000) * 1000) as ::c_long,
737     };
738     let rmtp = ptr::null_mut();
739     platform::pal::nanosleep(&rqtp, rmtp)
740 }
741 
742 // #[no_mangle]
743 // pub extern "C" fn vfork() -> ::pid_t {
744 //     unimplemented!();
745 // }
746 
747 // #[no_mangle]
748 // pub extern "C" fn write(fildes: ::c_int, buf: *const ::c_void, nbyte: ::size_t) -> ::ssize_t {
749 //     platform::pal::write(fildes, buf, nbyte)
750 // }
751