#ifndef _UNISTD_H
#define _UNISTD_H

#include <bits/macros.h>
#include <bits/seek.h>
#include <luna/os-limits.h>
#include <sys/types.h>

#define STDIN_FILENO 0  // The standard input stream.
#define STDOUT_FILENO 1 // The standard output stream.
#define STDERR_FILENO 2 // The standard error stream.

#define F_OK 0 // Check for a file's existence.
#define R_OK 1 // Check whether a file is readable.
#define W_OK 2 // Check whether a file is writable.
#define X_OK 4 // Check whether a file is executable.

#ifdef __cplusplus
extern "C"
{
#endif

    /* Executes the program program, passing the arguments in the argument list argv. On success, does not return. */
    int execv(const char* program, char* const argv[]);

    /* Not implemented. */
    int execve(const char*, char* const[], char* const[]);
    /* Not implemented. */
    int execvp(const char*, char* const[]);

    /* Creates an identical copy (child) of the current process (parent). Returns 0 to the child, and the child's PID to
     * the parent. */
    pid_t fork(void);

    /* Returns the current process' process ID. */
    pid_t getpid(void);

    /* Returns the current process' parent's process ID. */
    pid_t getppid(void);

    /* Returns the current process' real user ID. */
    uid_t getuid(void);

    /* Returns the current process' effective user ID. */
    uid_t geteuid(void);

    /* Returns the current process' real group ID. */
    gid_t getgid(void);

    /* Returns the current process' effective group ID. */
    gid_t getegid(void);

    /* Sets the current process' real and effective user IDs. */
    int setuid(uid_t uid);

    /* Sets the current process' effective user ID. */
    int seteuid(uid_t uid);

    /* Sets the current process' real and effective group IDs. */
    int setgid(gid_t gid);

    /* Sets the current process' effective group ID. */
    int setegid(gid_t gid);

    /* Terminates the program with the status code status. */
    __lc_noreturn void _exit(int status);

    /* Calls the kernel for a specific service, determined by number. */
    long syscall(long number, ...);

    /* Suspends execution for a chosen amount of seconds. */
    unsigned int sleep(unsigned int seconds);

    /* Reads count bytes from the file descriptor fd into the memory at buf. */
    ssize_t read(int fd, void* buf, size_t count);

    /* Writes count bytes of the memory at buf to the file descriptor fd. */
    ssize_t write(int fd, const void* buf, size_t count);

    /* Closes the file descriptor fd. */
    int close(int fd);

    /* Moves the read/write file offset for fd to offset, depending on whence. */
    off_t lseek(int fd, off_t offset, int whence);

    /* Returns a copy of the file descriptor fd. */
    int dup(int fd);

    /* Causes the file descriptor fd2 to refer to the file descriptor fd. */
    int dup2(int fd, int fd2);

    /* Checks if the current program can access the file or directory at path. */
    int access(const char* path, int amode);

    /* Checks if the file descriptor fd refers to a terminal. */
    int isatty(int fd);

    /* Writes the current process's current working directory to buf. */
    char* getcwd(char* buf, size_t size);

    int unlink(const char* path); // Not implemented.

#ifdef __cplusplus
}
#endif

#endif