/* Copyright (C) 1997-1999 NEC Research Institute.
 * Please see the file LICENSE for license information.
 */
#ifndef _MLTON_POSIX_H
#define _MLTON_POSIX_H

#if defined(_WIN32)
// Of course Windows does not provide the Unix-style file permissions
#define S_IRGRP 0
#define S_IWGRP 0
#define S_IROTH 0
#define S_IWOTH 0

// And Windows does not support symlinks either
#define S_ISLNK(m) 0
#define lstat(path, buf) stat(path,buf)
#define readlink(path, buf, bufsiz) 0 // FIXME: Not implemented - hopefully not called!

#else
// Windows defines these - they should be ignored in Unix
#define O_BINARY 0
#define O_TEXT   0
#endif

#include "mlton-lib.h"

#define MLTON_errno() errno
#define MLTON_clearErrno() errno = 0

#if defined(_WIN32)
extern char **environ;
#else
extern char **environ;
#endif

void MLTON_init_posix();

/* ------------------------------------------------- */
/*                       Error                       */
/* ------------------------------------------------- */

#define MLTON_strerror(n) ((cpointer)(strerror(n)))

#ifndef ECANCELED
#define ECANCELED 0
#endif

#ifndef ENOTSUP
#define ENOTSUP 0
#endif

/* ------------------------------------------------- */
/*                      FileSys                      */
/* ------------------------------------------------- */

#define MLTON_opendir(p) ((cpointer)(opendir((char*)(p))))
#define MLTON_readdir(d) ((cpointer)(readdir((DIR*)(d))))
#define MLTON_rewinddir(p) ((void)(rewinddir((DIR*)(p))))
#define MLTON_closedir(p) ((int)(closedir((DIR*)(p))))

#define MLTON_dirent_name(d) ((cpointer)(((struct dirent*)(d))->d_name))

#define MLTON_fstat(f,s) ((int)(fstat((f), (struct stat*)(s))))
#define MLTON_lstat(f,s) ((int)(lstat((char*)(f), (struct stat*)(s))))
#define MLTON_stat(f,s) ((int)(stat((char*)(f), (struct stat*)(s))))

extern struct stat MLTON_stat;

#define MLTON_stat_dev(p) ((uint)(((struct stat*)(p))->st_dev))
#define MLTON_stat_ino(p) ((int)(((struct stat*)(p))->st_ino))
#define MLTON_stat_mode(p) ((uint)(((struct stat*)(p))->st_mode))
#define MLTON_stat_nlink(p) ((int)(((struct stat*)(p))->st_nlink))
#define MLTON_stat_uid(p) ((uint)(((struct stat*)(p))->st_uid))
#define MLTON_stat_gid(p) ((uint)(((struct stat*)(p))->st_gid))
#define MLTON_stat_rdev(p) ((uint)(((struct stat*)(p))->st_rdev))
#define MLTON_stat_size(p) ((int)(((struct stat*)(p))->st_size))
#define MLTON_stat_atime(p) ((int)(((struct stat*)(p))->st_atime))
#define MLTON_stat_mtime(p) ((int)(((struct stat*)(p))->st_mtime))
#define MLTON_stat_ctime(p) ((int)(((struct stat*)(p))->st_ctime))

#define MLTON_utime(s,u) ((int)(utime((char*)(s), (struct utimbuf*)(u))))

extern struct utimbuf MLTON_utimbuf;

#define MLTON_set_utimbuf_actime(p,x) (((struct utimbuf*)(p))->actime) = (x)
#define MLTON_set_utimbuf_modtime(p,x) (((struct utimbuf*)(p))->modtime) = (x)

#define MLTON_access(f,w) ((int)(access((char*)(f), (w))))
#define MLTON_chdir(p) ((int)(chdir((char*)(p))))
#define MLTON_chmod(p,m) ((int)(chmod((char*)(p), (m))))
#define MLTON_getcwd(buf,n) ((cpointer)(getcwd((buf),(n))))
#define MLTON_link(p1,p2) ((int)(link((char*)(p1), (char*)(p2))))
#define MLTON_mkdir(p,w) ((int)(mkdir((char*)(p), (w))))
#define MLTON_mkfifo(p,w) ((int)(mkfifo((char*)(p), (w))))
#define MLTON_open(p,w,m) ((int)(open((char*)(p), (w), (m))))
#define MLTON_pathconf(p,n) ((int)(pathconf((char*)(p), (n))))
#define MLTON_readlink(p,b,n) ((int)(readlink((char*)(p), (b), (n))))
#define MLTON_rename(p1,p2) ((int)(rename((char*)(p1), (char*)(p2))))
#define MLTON_rmdir(p) ((int)(rmdir((char*)(p))))
#define MLTON_symlink(p1,p2) ((int)(symlink((char*)(p1), (char*)(p2))))
#define MLTON_unlink(p) ((int)(unlink((char*)(p))))

/* ------------------------------------------------- */
/*                        IO                         */
/* ------------------------------------------------- */

#define MLTON_read(fd, b, i, s) ((int)(read((fd), (void*)((char*)(b) + (i)), (s))))
#define MLTON_write(fd, b, i, s) ((int)(write((fd), (void*)((char*)(b) + (i)), (s))))
#define MLTON_pipe(p) ((int)(pipe((int*)(p))))

#if defined(_WIN32)
#else
extern struct flock MLTON_flock;

#define MLTON_flock_type(p) ((int)(((struct flock*)(p))->l_type))
#define MLTON_flock_whence(p) ((int)(((struct flock*)(p))->l_whence))
#define MLTON_flock_start(p) ((int)(((struct flock*)(p))->l_start))
#define MLTON_flock_len(p) ((int)(((struct flock*)(p))->l_len))
#define MLTON_flock_pid(p) ((int)(((struct flock*)(p))->l_pid))

#define MLTON_set_flock_type(p,x) (((struct flock*)(p))->l_type) = (x)
#define MLTON_set_flock_whence(p,x) (((struct flock*)(p))->l_whence) = (x)
#define MLTON_set_flock_start(p,x) (((struct flock*)(p))->l_start) = (x)
#define MLTON_set_flock_len(p,x) (((struct flock*)(p))->l_len) = (x)
#define MLTON_set_flock_pid(p,x) (((struct flock*)(p))->l_pid) = (x)
#endif

/* ------------------------------------------------- */
/*                      ProcEnv                      */
/* ------------------------------------------------- */

extern pointer MLTON_environ;

#if defined(_WIN32)
#else
#define MLTON_times(t) ((int)(times((struct tms*)(t))))

extern struct tms MLTON_tms;

#define MLTON_tms_utime(p) ((int)(((struct tms*)(p))->tms_utime))
#define MLTON_tms_stime(p) ((int)(((struct tms*)(p))->tms_stime))
#define MLTON_tms_cutime(p) ((int)(((struct tms*)(p))->tms_cutime))
#define MLTON_tms_cstime(p) ((int)(((struct tms*)(p))->tms_cstime))

extern struct utsname MLTON_utsname;

#define MLTON_uname(u) uname((struct utsname*)(u))

#define MLTON_uname_sysname(p) ((cpointer)(((struct utsname*)(p))->sysname))
#define MLTON_uname_nodename(p) ((cpointer)(((struct utsname*)(p))->nodename))
#define MLTON_uname_release(p) ((cpointer)(((struct utsname*)(p))->release))
#define MLTON_uname_version(p) ((cpointer)(((struct utsname*)(p))->version))
#define MLTON_uname_machine(p) ((cpointer)(((struct utsname*)(p))->machine))
#endif

#define MLTON_numgroups 100
int MLTON_getgroups(pointer groups);
#define MLTON_getlogin() ((cpointer)(getlogin()))

#define MLTON_ctermid() ((cpointer)ctermid((string)NULL))
#define MLTON_getenv(s) ((cpointer)getenv((string)(s)))
#define MLTON_ttyname(fd) ((cpointer)ttyname(fd))

/* ------------------------------------------------- */
/*                      Process                      */
/* ------------------------------------------------- */

#define MLTON_waitpid(pid, status, options) ((int)(waitpid((pid), (int*)(status), (options))))

int MLTON_exec(pointer path, pointer args);
int MLTON_exece(pointer path, pointer args, pointer env);
int MLTON_execp(pointer file, pointer args);

/* ------------------------------------------------- */
/*                       SysDB                       */
/* ------------------------------------------------- */

#define MLTON_getpwnam(p) ((cpointer)(getpwnam((char*)(p))))
#define MLTON_getpwuid(u) ((cpointer)(getpwuid((uid_t)(u))))

#define MLTON_passwd_name(p) ((cpointer)(((struct passwd*)(p))->pw_name))
#define MLTON_passwd_uid(p) ((uint)(((struct passwd*)(p))->pw_uid))
#define MLTON_passwd_gid(p) ((uint)(((struct passwd*)(p))->pw_gid))
#define MLTON_passwd_dir(p) ((cpointer)(((struct passwd*)(p))->pw_dir))
#define MLTON_passwd_shell(p) ((cpointer)(((struct passwd*)(p))->pw_shell))

#define MLTON_getgrgid(g) ((cpointer)(getgrgid((gid_t)(g))))
#define MLTON_getgrnam(s) ((cpointer)(getgrnam((char*)(s))))

#define MLTON_group_name(p) ((cpointer)(((struct group*)(p))->gr_name))
#define MLTON_group_gid(p) ((uint)(((struct group*)(p))->gr_gid))
#define MLTON_group_mem(p) ((cpointer)(((struct group*)(p))->gr_mem))

/* ------------------------------------------------- */
/*                        TTY                        */
/* ------------------------------------------------- */

#if defined(_WIN32)
#else
extern struct termios MLTON_termios;

#define MLTON_termios_iflag(t) ((uint)(((struct termios*)(t))->c_iflag))
#define MLTON_termios_oflag(t) ((uint)(((struct termios*)(t))->c_oflag))
#define MLTON_termios_cflag(t) ((uint)(((struct termios*)(t))->c_cflag))
#define MLTON_termios_lflag(t) ((uint)(((struct termios*)(t))->c_lflag))
#define MLTON_termios_cc(t) ((cpointer)(((struct termios*)(t))->c_cc))

#define MLTON_set_termios_iflag(t,x) (((struct termios*)(t))->c_iflag) = (x)
#define MLTON_set_termios_oflag(t,x) (((struct termios*)(t))->c_oflag) = (x)
#define MLTON_set_termios_cflag(t,x) (((struct termios*)(t))->c_cflag) = (x)
#define MLTON_set_termios_lflag(t,x) (((struct termios*)(t))->c_lflag) = (x)

#define MLTON_tcgetattr(f,t) ((int)(tcgetattr((f), (struct termios*)(t))))
#define MLTON_tcsetattr(f,a,t) ((int)(tcsetattr((f), (a), (struct termios*)(t))))
#define MLTON_cfgetospeed(t) ((int)(cfgetospeed((struct termios*)(t))))
#define MLTON_cfsetospeed(t,s) ((int)(cfsetospeed((struct termios*)(t), (s))))
#define MLTON_cfgetispeed(t) ((int)(cfgetispeed((struct termios*)(t))))
#define MLTON_cfsetispeed(t,s) ((int)(cfsetispeed((struct termios*)(t), (s))))
#endif

/* ------------------------------------------------- */
/*                      Signals                      */
/* ------------------------------------------------- */

#define MLTON_sigemptyset(s) ((int)(sigemptyset((sigset_t*)(s))))
#define MLTON_sigfillset(s) ((int)(sigfillset((sigset_t*)(s))))
#define MLTON_sigaddset(a,b) ((int)(sigaddset((sigset_t*)(a),(b))))
#define MLTON_sigdelset(a,b) ((int)(sigdelset((sigset_t*)(a),(b))))
#define MLTON_sigismember(a,b) ((int)(sigismember((sigset_t*)(a),(b))))
#define MLTON_sigpending(s) ((int)(sigpending((sigset_t*)(s))))
#define MLTON_sigprocmask(a,b) ((int)(sigprocmask((a),(sigset_t*)(b),(sigset_t*)NULL)))
#define MLTON_sigsuspend(a) ((int)(sigsuspend((sigset_t*)(a))))

#endif /* #ifndef _MLTON_POSIX_H */


