#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/syslimits.h>
#include <sys/unistd.h>
#include <machine/limits.h>
#include <proto/exec.h>
#include <proto/dos.h>


/* add the offset from UNIX to AmigaOS time system */
#define OFFSET_FROM_1970 (8*365+2)


double ldexp(double x, int y)
{
    union { double d; unsigned long long int i; } c;
    c.i = (unsigned long long int) (y + 1023) << (13*4);
    return x * c.d;
}


int gettimeofday(struct timeval *tp, struct timezone *tzp)
{
    int omask;

    if (tp)
    {
        struct DateStamp ds;
        DateStamp(&ds);

        tp->tv_usec = (ds.ds_Tick % TICKS_PER_SECOND) * 20000;
        tp->tv_sec = (ds.ds_Days + OFFSET_FROM_1970) * 86400 + ds.ds_Minute * 60 + ds.ds_Tick / TICKS_PER_SECOND;
    }

    if (tzp)
    {
        /* since AmigaOS doesn't support timezones, we always return
        ** GMT... */
        tzp->tz_minuteswest = 0;
        tzp->tz_dsttime = DST_NONE;
    }
    return 0;
}


int getrlimit(int resource, struct rlimit *rlp)
{
    struct Task *me = FindTask(NULL);

    if (resource < RLIMIT_CPU || resource > RLIMIT_RSS || !rlp)
    {
        errno = EINVAL;
        return -1;
    }

    switch (resource)
    {
        case RLIMIT_CPU:
        case RLIMIT_FSIZE:
        case RLIMIT_CORE:
        case RLIMIT_RSS:
        case RLIMIT_DATA:
            rlp->rlim_cur = rlp->rlim_max = RLIM_INFINITY;
            break;
        case RLIMIT_STACK:
            rlp->rlim_cur = rlp->rlim_max = me->tc_SPUpper - me->tc_SPLower;
            break;
    }

    return 0;
}


int setrlimit(int resource, const struct rlimit *rlp)
{
    if (resource < RLIMIT_CPU || resource > RLIMIT_RSS || !rlp)
    {
        errno = EINVAL;
        return -1;
    }
    return 0;
}


long sysconf (int name)
{
    switch (name)
    {
        case _SC_ARG_MAX:
            return ARG_MAX;

        case _SC_CHILD_MAX:
            return CHILD_MAX;

        case _SC_CLK_TCK:
            return CLK_TCK;

        case _SC_NGROUPS_MAX:
            return NGROUPS_MAX;

        case _SC_OPEN_MAX:
            return FD_SETSIZE; /* Was OPEN_MAX. See comments before getdtablesize()
                               ** why this was changed. */

        case _SC_JOB_CONTROL:
            return _POSIX_JOB_CONTROL;

        case _SC_SAVED_IDS:
            return _POSIX_SAVED_IDS;

        case _SC_VERSION:
            return _POSIX_VERSION;

        default:
            errno = EINVAL;
            return -1;
    }
}


uid_t getuid(void)
{
    return 0;
}


gid_t getgid (void)
{
    return 0;
}


mode_t umask (mode_t mode)
{
    return 0666;
}


