mux2.0/game/
mux2.0/game/data/
mux2.0/src/tools/
// file_c.cpp -- File cache management.
//
// $Id: file_c.cpp,v 1.1 2000/04/11 07:14:44 sdennis Exp $
//

#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"

#include "interface.h"
#include "mudconf.h"
#include "command.h"
#include "file_c.h"
#include "alloc.h"

typedef struct filecache_block_hdr FBLKHDR;
typedef struct filecache_block FBLOCK;

struct filecache_block
{
    struct filecache_block_hdr
    {
        struct filecache_block *nxt;
        unsigned int nchars;
    } hdr;
    char data[MBUF_SIZE - sizeof(struct filecache_block_hdr)];
};

struct filecache_hdr
{
    char **ppFilename;
    FBLOCK *fileblock;
    const char *desc;
};

typedef struct filecache_hdr FCACHE;

#define FBLOCK_SIZE (MBUF_SIZE - sizeof(FBLKHDR))

FCACHE fcache[] =
{
    { &mudconf.conn_file,    NULL,   "Conn" },
    { &mudconf.site_file,    NULL,   "Conn/Badsite" },
    { &mudconf.down_file,    NULL,   "Conn/Down" },
    { &mudconf.full_file,    NULL,   "Conn/Full" },
    { &mudconf.guest_file,   NULL,   "Conn/Guest" },
    { &mudconf.creg_file,    NULL,   "Conn/Reg" },
    { &mudconf.crea_file,    NULL,   "Crea/Newuser" },
    { &mudconf.regf_file,    NULL,   "Crea/RegFaill" },
    { &mudconf.motd_file,    NULL,   "Motd" },
    { &mudconf.wizmotd_file, NULL,   "Wizmotd" },
    { &mudconf.quit_file,    NULL,   "Quit" },
    { NULL,                  NULL,   NULL }
};

NAMETAB list_files[] =
{
    {(char *)"badsite_connect", 1,  CA_WIZARD,  FC_CONN_SITE},
    {(char *)"connect",     2,  CA_WIZARD,  FC_CONN},
    {(char *)"create_register", 2,  CA_WIZARD,  FC_CREA_REG},
    {(char *)"down",        1,  CA_WIZARD,  FC_CONN_DOWN},
    {(char *)"full",        1,  CA_WIZARD,  FC_CONN_FULL},
    {(char *)"guest_motd",      1,  CA_WIZARD,  FC_CONN_GUEST},
    {(char *)"motd",        1,  CA_WIZARD,  FC_MOTD},
    {(char *)"newuser",     1,  CA_WIZARD,  FC_CREA_NEW},
    {(char *)"quit",        1,  CA_WIZARD,  FC_QUIT},
    {(char *)"register_connect",    1,  CA_WIZARD,  FC_CONN_REG},
    {(char *)"wizard_motd",     1,  CA_WIZARD,  FC_WIZMOTD},
    { NULL,             0,  0,      0}
};

void do_list_file(dbref player, dbref cause, int extra, char *arg)
{
    int flagvalue;

    flagvalue = search_nametab(player, list_files, arg);
    if (flagvalue < 0) {
        display_nametab(player, list_files,
                (char *)"Unknown file.  Use one of:", 1);
        return;
    }
    fcache_send(player, flagvalue);
}

static FBLOCK *fcache_fill(FBLOCK *fp, char ch)
{
    FBLOCK *tfp;

    if (fp->hdr.nchars >= sizeof(fp->data))
    {
        // We filled the current buffer.  Go get a new one.
        //
        tfp = fp;
        fp = (FBLOCK *) alloc_mbuf("fcache_fill");
        fp->hdr.nxt = NULL;
        fp->hdr.nchars = 0;
        tfp->hdr.nxt = fp;
    }
    fp->data[fp->hdr.nchars++] = ch;
    return fp;
}

static int fcache_read(FBLOCK **cp, char *filename)
{
    int n, nmax, tchars, fd;
    char *buff;
    FBLOCK *fp, *tfp;

    /*
     * Free a prior buffer chain 
     */

    fp = *cp;
    while (fp != NULL) {
        tfp = fp->hdr.nxt;
        free_mbuf(fp);
        fp = tfp;
    }
    *cp = NULL;

    /*
     * Read the text file into a new chain 
     */

    if ((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
    {
        // Failure: log the event 
        //
        STARTLOG(LOG_PROBLEMS, "FIL", "OPEN");
        buff = alloc_mbuf("fcache_read.LOG");
        sprintf(buff, "Couldn't open file '%s'.", filename);
        log_text(buff);
        free_mbuf(buff);
        ENDLOG
        return -1;
    }
    DebugTotalFiles++;
    buff = alloc_lbuf("fcache_read.temp");

    /*
     * Set up the initial cache buffer to make things easier 
     */

    fp = (FBLOCK *) alloc_mbuf("fcache_read.first");
    fp->hdr.nxt = NULL;
    fp->hdr.nchars = 0;
    *cp = fp;
    tchars = 0;

    /*
     * Process the file, one lbuf at a time 
     */

    nmax = read(fd, buff, LBUF_SIZE);
    while (nmax > 0) {

        for (n = 0; n < nmax; n++)
        {
            switch (buff[n])
            {
            case '\n':
                fp = fcache_fill(fp, '\r');
                fp = fcache_fill(fp, '\n');
                tchars += 2;
            case '\0':
            case '\r':
                break;
            default:
                fp = fcache_fill(fp, buff[n]);
                tchars++;
            }
        }
        nmax = read(fd, buff, LBUF_SIZE);
    }
    free_lbuf(buff);
    if (close(fd) == 0)
    {
        DebugTotalFiles--;
    }

    /*
     * If we didn't read anything in, toss the initial buffer 
     */

    if (fp->hdr.nchars == 0)
    {
        *cp = NULL;
        free_mbuf(fp);
    }
    return tchars;
}

void fcache_rawdump(SOCKET fd, int num)
{
    int cnt, remaining;
    char *start;
    FBLOCK *fp;

    if ((num < 0) || (num > FC_LAST))
        return;
    fp = fcache[num].fileblock;

    while (fp != NULL) {
        start = fp->data;
        remaining = fp->hdr.nchars;
        while (remaining > 0) {

            cnt = SOCKET_WRITE(fd, start, remaining, 0);
            if (cnt < 0)
                return;
            remaining -= cnt;
            start += cnt;
        }
        fp = fp->hdr.nxt;
    }
    return;
}

void fcache_dump(DESC *d, int num)
{
    FBLOCK *fp;

    if ((num < 0) || (num > FC_LAST))
        return;
    fp = fcache[num].fileblock;

    while (fp != NULL) {
        queue_write(d, fp->data, fp->hdr.nchars);
        fp = fp->hdr.nxt;
    }
}

void fcache_send(dbref player, int num)
{
    DESC *d;

    DESC_ITER_PLAYER(player, d)
    {
        fcache_dump(d, num);
    }
}

void fcache_load(dbref player)
{
    FCACHE *fp;
    char *buff, *bufc, *sbuf;

    buff = bufc = alloc_lbuf("fcache_load.lbuf");
    sbuf = alloc_sbuf("fcache_load.sbuf");
    for (fp = fcache; fp->ppFilename; fp++)
    {
        int i = fcache_read(&fp->fileblock, *fp->ppFilename);
        if ((player != NOTHING) && !Quiet(player))
        {
            Tiny_ltoa(i, sbuf);
            if (fp == fcache)
                safe_str((char *)"File sizes: ", buff, &bufc);
            else
                safe_str((char *)"  ", buff, &bufc);
            safe_str((char *)fp->desc, buff, &bufc);
            safe_str((char *)"...", buff, &bufc);
            safe_str(sbuf, buff, &bufc);
        }
    }
    *bufc = '\0';
    if ((player != NOTHING) && !Quiet(player)) {
        notify(player, buff);
    }
    free_lbuf(buff);
    free_sbuf(sbuf);
}

void NDECL(fcache_init)
{
    FCACHE *fp = fcache;
    for (fp = fcache; fp->ppFilename; fp++)
    {
        fp->fileblock = NULL;
    }

    fcache_load(NOTHING);
}