/
Genesis-1.0p36-DEV/
Genesis-1.0p36-DEV/bin/
Genesis-1.0p36-DEV/doc/
Genesis-1.0p36-DEV/etc/
Genesis-1.0p36-DEV/src/data/
/*
// Full copyright information is available in the file ../doc/CREDITS
*/

#define NATIVE_MODULE

#include "cdc.h"

#include "cdc_db.h"
#include <time.h>
#ifdef __UNIX__
#include <sys/time.h>    /* for mtime(), getrusage() */
#include <sys/resource.h>      /* getrusage()  25-Jan-95 BJG */
#endif
#include "util.h"
#include "net.h"
#include "dns.h"

#ifdef __Win32__
#define FTIME _lstrftime
#else
#define FTIME strftime
#endif

NATIVE_METHOD(strftime) {
    char        s[LINE];
    char      * fmt;
    time_t      tt;
    struct tm * t;

    INIT_1_OR_2_ARGS(STRING, INTEGER);

#ifdef __BORLANDC__
    if (argc == 2) {
        if (INT2 < 18000) {
            THROW((type_id,
         "Borland's time util is broken, and requires time values above 18000"))
        }
        tt = (time_t) INT2;
    } else {
        tt = time(NULL);
    }
#else
    tt = ((argc == 2) ? (time_t) INT2 : time(NULL));
#endif
    t  = localtime(&tt);
 
    fmt = string_chars(STR1);

    /* some OS's are weird and do odd things when you end in %
       (accidentally or no) */
    if (fmt[strlen(fmt)] == '%')
        fmt[strlen(fmt)] = (char) NULL;

    if (FTIME(s, LINE, fmt, t) == (size_t) 0)
       THROW((range_id,"Format results in a string longer than 80 characters."))

    CLEAN_RETURN_STRING(string_from_chars(s, strlen(s)));
}

NATIVE_METHOD(next_objnum) {
    INIT_NO_ARGS();

    CLEAN_RETURN_OBJNUM(db_top);
}

#ifdef HAVE_GETRUSAGE
#if defined(sys_solaris) || defined(sys_ultrix)
extern int getrusage(int, struct rusage *);
#endif
#endif

NATIVE_METHOD(status) {
#ifdef HAVE_GETRUSAGE
    struct rusage r;
#endif
    cList *status;
    cData *d;
    Int x;

    INIT_NO_ARGS();

#define __LLENGTH__ 19

    status = list_new(__LLENGTH__);
    d = list_empty_spaces(status, __LLENGTH__);
    for (x=0; x < __LLENGTH__; x++)
        d[x].type = INTEGER;

#ifndef HAVE_GETRUSAGE

    for (x=0; x < __LLENGTH__ - 1; x++)
        d[x].u.val = -1;

#else

    getrusage(RUSAGE_SELF, &r);
    d[0].u.val = (cNum) r.ru_utime.tv_sec; /* user time used (seconds) */
    d[1].u.val = (cNum) r.ru_utime.tv_usec;/* user time used (microseconds) */
    d[2].u.val = (cNum) r.ru_stime.tv_sec; /* system time used (seconds) */
    d[3].u.val = (cNum) r.ru_stime.tv_usec;/* system time used (microseconds) */
    d[4].u.val = (cNum) r.ru_maxrss;
    d[7].u.val = (cNum) r.ru_idrss;       /* integral unshared data size */
    d[8].u.val = (cNum) r.ru_minflt;      /* page reclaims */
    d[9].u.val = (cNum) r.ru_majflt;      /* page faults */
    d[10].u.val = (cNum) r.ru_nswap;       /* swaps */
    d[11].u.val = (cNum) r.ru_inblock;     /* block input operations */
    d[12].u.val = (cNum) r.ru_oublock;     /* block output operations */
    d[13].u.val = (cNum) r.ru_msgsnd;      /* messages sent */
    d[14].u.val = (cNum) r.ru_msgrcv;      /* messages received */
    d[15].u.val = (cNum) r.ru_nsignals;    /* signals received */
    d[16].u.val = (cNum) r.ru_nvcsw;       /* voluntary context switches */
    d[17].u.val = (cNum) r.ru_nivcsw;      /* involuntary context switches */

#endif

    d[18].u.val = (cNum) atomic;
#undef __LLENGTH__

    CLEAN_RETURN_LIST(status);
}

NATIVE_METHOD(version) {
    cList *version;
    cData *d;

    INIT_NO_ARGS();

    /* Construct a list of the version numbers and push it. */
    version = list_new(4);
    d = list_empty_spaces(version, 4);
    d[0].type = d[1].type = d[2].type = INTEGER;
    d[0].u.val = VERSION_MAJOR;
    d[1].u.val = VERSION_MINOR;
    d[2].u.val = VERSION_PATCH;
    d[3].type = STRING;
    d[3].u.str = string_dup(str_release);

    CLEAN_RETURN_LIST(version);
}

/*
// -----------------------------------------------------------------
*/
NATIVE_METHOD(hostname) {
    cStr * name;
    char   buf[DNS_MAXLEN+1];

    INIT_0_OR_1_ARGS(STRING);

    if (!argc) {
        name = string_dup(str_hostname);
    } else {
        switch (lookup_name_by_ip(string_chars(STR1), buf)) {
            case DNS_INVADDR:
                THROW((address_id, "Invalid IP Address: %S", STR1))
            case DNS_NORESOLV:
                THROW((failed_id, "No name for IP Address %S", STR1))
            case DNS_OVERFLOW:
                THROW((range_id, "DNS Response overflows DNS_MAXLEN!"))
        }
        name = string_from_chars(buf, strlen(buf));
    }

    CLEAN_RETURN_STRING(name);
}

/*
// -----------------------------------------------------------------
*/
NATIVE_METHOD(ip) {
    cStr * sip;
    char   buf[DNS_MAXLEN+1];
    char * p;

    INIT_0_OR_1_ARGS(STRING);

    if (!argc)
        p = string_chars(str_hostname);
    else
        p = string_chars(STR1);

    switch (lookup_ip_by_name(string_chars(STR1), buf)) {
        case DNS_NORESOLV:
            THROW((failed_id, "Address %S does not resolv", STR1))
        case DNS_OVERFLOW:
            THROW((range_id, "DNS Response overflows DNS_MAXLEN!"))
    }
    sip = string_from_chars(buf, strlen(buf));

    CLEAN_RETURN_STRING(sip);
}