T168_111\system\Ethernet:第1~8

ethernet.c                。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define ETHERNET_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <stdio.h>
#include <ctype.h>
#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "XLib.h"
#include "XEMAC.h"
#include "XComm.h"
#include "XParser.h"
#include "XPrtEng.h"

#include "net\route.h"
#include "net\inet.h"
#include "net\confnet.h"
#include "net\socket.h"
#include "pro\dhcp.h"
#include "pro\wins.h"
#include "pro\ftpd.h"
#include "pro\httpd.h"
#include "netrx.h"
#include "ethernet.h"

#include "net\netdebug.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

#define LPR_INIT                    0
#define LPR_READ_LENGTH             1
#define LPR_QUEUE_OR_LENGTH           2
#define LPR_FILTERING_LENGTH          3
#define LPR_DATA                    4
#define LPR_FILTERING               5
#define LPR_FILTERING_COMMANDS       6
#define LPQ_READ_NAME                7
#define LPQ_END                        8

#define DEF_IP                        "192.168.1.100"
#define DEF_MASK                    "255.255.255.0"

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/*!
 * \brief TCP socket type.
 */
typedef struct tcp_service TCPSERVICE;

/*!
 * \brief TCP service information structure.
 */
struct tcp_service {
    char *name;        /*!< \brief String containing the symbolic name of the new thread. */
    u_short port;    /*!< \brief Port number in net byte order. */
    void (*protocol) (TCPSERVICE *);    /*!< \brief Protocol function. */
    size_t stack;    /*!< \brief Number of bytes of the stack space allocated for the new thread */

    TCPSOCKET *sock;
    FILE *istream;
    FILE *ostream;
    char connected;
    char output;
};

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

static void ServiceFtp(TCPSERVICE *);
static void ServiceTelnet(TCPSERVICE *);
static void ServiceHttp(TCPSERVICE *);
static void ServiceLPR(TCPSERVICE *);
static void ServiceRaw(TCPSERVICE *);

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static TCPSERVICE Service[] = {
    {"ftp(1)",   21, ServiceFtp,    NUT_THREAD_FTP_STACK},
    {"ftp(2)",   21, ServiceFtp,    NUT_THREAD_FTP_STACK},
    {"telnet",   23, ServiceTelnet, NUT_THREAD_TELNET_STACK},
    {"http(1)",  80, ServiceHttp,   NUT_THREAD_HTTP_STACK},
    {"http(2)",  80, ServiceHttp,   NUT_THREAD_HTTP_STACK},
    {"http(3)",  80, ServiceHttp,   NUT_THREAD_HTTP_STACK},
    {"lpr(1)",  515, ServiceLPR,    NUT_THREAD_LPR_STACK},
    {"lpr(2)",  515, ServiceLPR,    NUT_THREAD_LPR_STACK},
    {"raw(1)", 9100, ServiceRaw,    NUT_THREAD_RAW_STACK},
    {"raw(2)", 9100, ServiceRaw,    NUT_THREAD_RAW_STACK},
    {"raw(3)", 9100, ServiceRaw,    NUT_THREAD_RAW_STACK},
    {(char *)0, 0, 0, 0},
};

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/


static void ServiceFtp(TCPSERVICE *serv)
{
    /*
     * Maximum segment size. 
     *
     * Choose 536 up to 1460. Note, that segment sizes above 536 may result 
     * in fragmented packets. Remember, that Ethernut doesn't support TCP 
     * fragmentation.
     */
    u_short mss = 1460;

    /*
     * FTP timeout.
     *
     * The server will terminate the session, if no new command is received
     * within the specified number of milliseconds.
     */
    u_long tmo = 600000;

    /*
     * TCP buffer size.
     */
    u_short siz = 5840;

    /* 
     * Set specified socket options. 
     */
    NutTcpSetSockOpt(serv->sock, TCP_MAXSEG, &mss, sizeof(mss));
    NutTcpSetSockOpt(serv->sock, SO_RCVTIMEO, &tmo, sizeof(tmo));
    NutTcpSetSockOpt(serv->sock, SO_RCVBUF, &siz, sizeof(siz));

    NutFtpServerSession(serv->sock, serv->istream, serv->ostream);
}

static void ServiceTelnet(TCPSERVICE *serv)
{
    static const char help[] = "List of commands follows\r\n"
        "memory \tQueries number of RAM bytes free.\r\n"
        "threads\tLists all created threads.\r\n"
        "sockets\tLists all created sockets.\r\n"
        "receive\tList of receive queue.\r\n"
        "quit   \tTerminates connection.\r\n";

    char buff[64];
    char *cp;
    int got;

    /* Send a welcome banner. */
    fputs("Welcome to telnet. Type help to get help.\r\n", serv->ostream);
    for (;;) {

        fputs(".\r\n", serv->ostream);

        /* Flush output and read a line. */
        fflush(serv->ostream);
        if (fgets(buff, sizeof(buff), serv->istream) == 0)
            break;

        /* Chop off EOL. */
        if ((cp = strchr(buff, '\r')) != 0)
            *cp = 0;
        if ((cp = strchr(buff, '\n')) != 0)
            *cp = 0;

        /* Ignore blank lines. */
        got = strlen(buff);
        if (got == 0)
            continue;

        /* Memory info. */
        if (strncmp(buff, "memory", got) == 0) {
            fprintf(serv->ostream, "%u bytes RAM free\r\n", (u_int)NutHeapAvailable());
            continue;
        }

        /* List threads. */
        if (strncmp(buff, "threads", got) == 0) {
            NUTTHREADINFO *tdp;
            /* fmt 12345678 1234 12345 */
            fputs("Name     Prio State Free Memory\r\n", serv->ostream);
            for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
                static char *states[] = { "TERM","RUN","READY","SLEEP" };
                fprintf(serv->ostream, "%-8s %4u %-5s %-8lu %s\r\n",
                    tdp->td_name, tdp->td_priority, states[tdp->td_state],
                    (uptr_t) tdp->td_sp - (uptr_t) tdp->td_memory,
                    *((u_long *) tdp->td_memory) != DEADBEEF ? "FAIL" : "OK");
            }
            continue;
        }

        /* List sockets. */
        if (strncmp(buff, "sockets", got) == 0) {
            NutDumpSocketList(serv->ostream);
            continue;
        }

        /* List receive queue. */
        if (strncmp(buff, "receive", got) == 0) {
            NETRXBUF *rxbuf;
            TCPSOCKET *sock;
            /* fmt 000.000.000.000:12345 */
            fputs("Remote                Length\r\n", serv->ostream);
            for (rxbuf = NetRxBufList; rxbuf; rxbuf = rxbuf->next) {
                if (sock = rxbuf->sock) {
                    fprintf(serv->ostream, "%-15s:%-5u",
                        inet_ntoa(sock->so_remote_addr), ntohs(sock->so_remote_port));
                }
                else
                    fprintf(serv->ostream, "%-21s", "off-line");
                fprintf(serv->ostream, " %lu\r\n", rxbuf->length);
            }
            continue;
        }

        /* Quit connection. */
        if (strncmp("quit", buff, got) == 0) {
            break;
        }

        /* Display help text on any unknown command. */
        fputs(help, serv->ostream);
    }
}

static void ServiceHttp(TCPSERVICE *serv)
{
    /*
     * This API call saves us a lot of work. It will parse the
     * client's HTTP request, send any requested file from the
     * registered file system or handle CGI requests by calling
     * our registered CGI routine.
     */
    NutHttpProcessRequest(serv->istream, serv->ostream);
}

static void ServiceLPR(TCPSERVICE *serv)
{
    int status = LPR_INIT;
    int length = 0;
    int queuename = 0;
    int got;
    u_char data;
    NETRXBUF *rxbuf;

    while ((rxbuf = NetRxCreate()) == 0)
        NutSleep(100);

    rxbuf->sock = serv->sock;

    for (;;) {

        if (status == LPQ_END)
            break;

        /* Flush output and get a char. */
        fflush(serv->ostream);
        if ((got = fgetc(serv->istream)) == (-1))
            break;
        data = got;

        switch (status) {
        case LPR_INIT:
            if (data == 0x2) {
                status = LPR_QUEUE_OR_LENGTH;
                length = 0;
                queuename = 1;
            }
            if (data == 0x3) {
                status = LPR_READ_LENGTH;
                length = 0;
                if (!queuename)
                    status = LPQ_READ_NAME;
            }
            if (data == 0x4) {
                status = LPQ_READ_NAME;  
            }
            if (data == 'H' ||
                data == 'P' ||
                data == 'J' ||
                data == 'f' ||
                data == 'l' ||
                data == 'U' ||
                data == 'N')
                status = LPR_FILTERING;
            break;

        case LPR_QUEUE_OR_LENGTH:
            if (isdigit(data)) {
                length = length * 10 + (data & 0xf);
            }
            else if (data == 0xa) {            // Support numeric queue name
                fputc(0, serv->ostream);    // Acknowledge
                status = LPR_INIT;
            }
            else
                status = LPR_FILTERING;
            break;

        case LPR_FILTERING_COMMANDS:
            if (--length == 0) {
                fputc(0, serv->ostream);    // Acknowledge
                status = LPR_INIT;
            }
            break;

        case LPR_FILTERING:
            if (data == 0xa) {
                fputc(0, serv->ostream);    // Acknowledge
                status = LPR_INIT;
                if (length)
                    status = LPR_FILTERING_COMMANDS;
            }
            break;

        case LPR_READ_LENGTH:
            if (isdigit(data))
                length = length * 10 + (data & 0xf);
            else
                status = LPR_FILTERING_LENGTH;
            break;

        case LPR_FILTERING_LENGTH:
            if (data == 0xa) {
                fputc(0, serv->ostream);    // Acknowledge
                status = LPR_DATA;
            }
            break;

        case LPR_DATA:
            NetRxDataIn(&data, 1, rxbuf);
            if (--length == 0 ) {
                fputc(0, serv->ostream);    // Acknowledge
                status = LPR_INIT;
            }
            break;

        case LPQ_READ_NAME:
            if (data == 0xa) {
                _eMotorStatus motor = GetMotorStatus();
                u_short joberr = GetJobErrorState();
                char response[64] = "Online";
                char name[64];

                if (CheckJobLock())
                    strcpy(response, "On Pause");
                else if (motor == STATUS_MOTOR_FORWARD || motor == STATUS_MOTOR_BACKWARD)
                    strcat(response, ", Printing");
                else if (joberr & ERROR_TPH_OPEN)
                    strcat(response, ", Carriage Opened");
                else if (joberr & ERROR_PAPER_JAM)
                    strcat(response, ", Paper Jam");
                else if (joberr & ERROR_PAPER_EMPTY)
                    strcat(response, ", Out of Paper");
                else if (joberr & ERROR_RIBBON_JAM || joberr & ERROR_RIBBON_EMPTY)
                    strcat(response, ", Out of Ribbon");
                else if (joberr & ERROR_CUTTER)
                    strcat(response, ", Cutter Error");
                else if (joberr & ERROR_TPH_OVERHEAT || joberr & ERROR_MOTOR_OVERHEAT)
                    strcat(response, ", Over Heat");

                sprintf(name, "Printer Status:  %s\n", response);
                fputs(name, serv->ostream);

                status = LPQ_END;
                NutSleep(200);
            }
            break;
        }
    }

    rxbuf->sock = 0;
    if (rxbuf->length == 0)
        NetRxDestroy(rxbuf);
}

static void ServiceRaw(TCPSERVICE *serv)
{
    NETRXBUF *rxbuf;
    char buf[5];
    int got;
    int len;

    serv->output = 1;

    while ((rxbuf = NetRxCreate()) == 0)
        NutSleep(100);

    rxbuf->sock = serv->sock;

    for (;;) {

        /* Flush output and get a char. */
        fflush(serv->ostream);
        if ((got = fgetc(serv->istream)) == (-1))
            break;

        len = CheckImmedCmd((u_char)got, buf, ETHERNET_PORT);
        NetRxDataIn((u_char *)buf, len, rxbuf);
    }

    rxbuf->sock = 0;
    if (rxbuf->length == 0)
        NetRxDestroy(rxbuf);

    serv->output = 0;
}

THREAD(NutService, arg)
{
    TCPSERVICE *serv = arg;

    serv->connected = 0;
    serv->output = 0;

    /* Now loop endless for connections. */
    for (;;) {

        /* Create a socket. */
        if ((serv->sock = NutTcpCreateSocket()) != 0) {
            /* Listen on port. If we return, we got a client. */
            if (NutTcpAccept(serv->sock, serv->port) == 0) {

                /* Associate a stream with the socket so we can use standard I/O calls. */
                serv->istream = _fdopen((int) serv->sock, "rb");
                serv->ostream = _fdopen((int) serv->sock, "wb");
                if (serv->istream && serv->ostream) {
                    /* Process client requests. */
                    serv->connected = 1;
                    serv->protocol(serv);
                    serv->connected = 0;
                }
                /* Close the stream. */
                if (serv->istream)
                    fclose(serv->istream);
                if (serv->ostream)
                    fclose(serv->ostream);
            }
            /* Close our socket. */
            NutTcpCloseSocket(serv->sock);
        }
    }
}

THREAD(Ethernet, arg)
{
    TCPSERVICE *serv = Service;
    u_char *mac  = NutNetGetMAC();
    u_short port = NutNetGetPort();
    char *name = NutGetPrintServerName();

    /*
     * Register Realtek controller at address 8300 hex
     * and interrupt 5.
     */
     //debug_printf("Ethernet:\n");
    if (NutRegisterDevice(&DEV_ETHER, 0x8300, 5) == -1) {
            //debug_printf("end:error\n");
        NutThreadExit();
    }
        debug_printf("end\n");
#ifdef NUTDEBUG
    NutTraceTcp(stdout, 1);
#endif

    NutNetLoadConfig(DEV_ETHER_NAME);
    memcpy(confnet.cdn_mac, mac, 6);
    NutNetSaveConfig();

    NutLoadConfig();
    memcpy(confos.hostname, name, 16);
    NutSaveConfig();

    /*
     * Setup the ethernet device. Try DHCP first. If this is
     * the first time boot with empty EEPROM and no DHCP server
     * was found, use hardcoded values.
     */
    if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
        if (NutDhcpIfConfig(DEV_ETHER_NAME, mac, 60000)) {
            u_long ip_addr = inet_addr(DEF_IP);
            u_long ip_mask = inet_addr(DEF_MASK);

            NutNetIfConfig(DEV_ETHER_NAME, mac, ip_addr, ip_mask);
            /* If not in a local network, we must also call 
               NutIpRouteAdd() to configure the routing. */
        }
    }

    /*
     * Register UROM, CGI, SSI and ASP handler
     */
    NutRegisterHttp();

    /*
     * Start another service thread to allow
     * two concurrent connections.
     */
    while (serv->name) {
        if (serv->protocol == ServiceRaw)
            serv->port = port;
        NutThreadCreate(serv->name, NutService, serv, serv->stack);
        serv++;
    }

    NutRegisterSntp();
    NutRegisterMail();
    NutRegisterUtility();
    NutRegisterSnmp();

    for (;;) {
        if (NutWinsNameQuery(confos.hostname, confnet.cdn_ip_addr) == -1) {
            NutSleep(1000);
        }
    }
}

void InitialEthernet(void)
{
    NutThreadCreate("ethernet", Ethernet, 0, NUT_THREAD_ETHERNET_STACK);
}

int NetWrite(CONST void * buf, int size)
{
    TCPSERVICE *serv = Service;

    while (serv->name) {
        if (serv->connected && serv->output) {
            NutTcpDeviceWrite(serv->sock, buf, size);
            NutTcpDeviceWrite(serv->sock, 0, 0);
        //    fwrite(buf, sizeof(u_char), size, serv->ostream);
        //    fflush(serv->ostream);
        }
        serv++;
    }
    return size;
}

int NetQueryIP(u_long * ip_addr, u_long * ip_mask, u_long * gateway)
{
    NUTDEVICE *dev;

    if (ip_addr)
        *ip_addr = 0;
    if (ip_mask)
        *ip_mask = 0;

    if ((dev = NutIpRouteQuery(0, gateway)) == 0) {
        /* Return the first interface if the IP is broadcast. */
        dev = NutIpRouteQuery(0xFFFFFFFF, 0);
    }
    if (dev != 0) {
        IFNET *nif = dev->dev_icb;
        *ip_addr = nif->if_local_ip;
        *ip_mask = nif->if_mask;
        return 0;
    }
    return -1;
}

#endif

ethernet.h                 。。。。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef ETHERNET_H

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define ETHERNET_H

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <time.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "net\confnet.h"
#include "net\if_ether.h"
#include "net\ether.h"
#include "net\inet.h"
#include "netrx.h"

#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif    /* __cplusplus */

/******************************************************************************
 *                                                                            *
 *                        G L O B A L   D E F I N E S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                 S T R U C T U R E   D E F I N I T I O N S                  *
 *                                                                            *
 ******************************************************************************/

typedef struct _CONFSMTP CONFSMTP;
struct _CONFSMTP {
    u_char size;            // Size of this structure
    char magic[5];            // Magic cookie
    char notify;            // E-mail notification
    char auth;                // SMTP authentication
    char server[32];        // SMTP server address
    char username[32];        // E-mail Account Name
    char password[32];        // E-mail Account Password
    char sender[32];        // Sender e-mail address
    char receiver[32];        // Receiver e-mail address
};

typedef struct _CONFSNTP CONFSNTP;
struct _CONFSNTP {
    u_char size;            // Size of this structure
    char magic[5];            // Magic cookie
    char sync;                // Synchronize the clock with an internet time server
    long interval;            // Automatic update interval in seconds
    long timezone;            // Time zones
    long timediffer;        // Time differences
    char server[3][32];        // SNTP server address
};

typedef struct _CONFWEB CONFWEB;
struct _CONFWEB {
    u_char size;            // Size of this structure
    char magic[5];            // Magic cookie
    char rootname[16];        // Root directory login user name
    char rootpass[16];        // Root directory login password
    char adminname[16];        // Administrator login user name
    char adminpass[16];        // Administrator login password
};

/******************************************************************************
 *                                                                            *
 *    G L O B A L   V A R I A B L E S   -   N O   I N I T I A L I Z E R S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *       G L O B A L   V A R I A B L E S   -   I N I T I A L I Z E R S        *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                   F U N C T I O N   P R O T O T Y P E S                    *
 *                                                                            *
 ******************************************************************************/

void NutRegisterHttp(void);
void NutRegisterSntp(void);
void NutRegisterMail(void);
void NutRegisterUtility(void);
void NutRegisterSnmp(void);

/* in ethernet.c */
void InitialEthernet(void);
int NetWrite(CONST void *, int);
int NetQueryIP(u_long *, u_long *, u_long *);

#ifdef __cplusplus
}                       /* End of extern "C" { */
#endif    /* __cplusplus */

#endif

httpserv.c                         。。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define HTTPSERV_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "XLib.h"
#include "XADC.h"
#include "XFileSys.h"
#include "XAppVer.h"
#include "XProFile.h"
#include "XVarBank.h"
#include "XCodepage.h"
#include "XFunction.h"
#include "XParser.h"

#include "net\inet.h"
#include "net\socket.h"
#include "pro\httpd.h"
#include "pro\ssi.h"
#include "pro\asp.h"
#include "netrx.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

#define HTTP_MAX_DATA_SIZE 512

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

typedef struct {
    long Index;
    long Difference;
    const char *Description;
} TIMEZONE;

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static const char SetupHead[] =
{
    "<HTML>"
    "<HEAD>"
    "<META http-equiv=Content-Type content=text/html; charset=windows-1252>"
    "<STYLE type=text/css>"
    "A:link    {FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px;COLOR:blue}"
    "A:visited {FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px;COLOR:blue}"
    ".maintext {FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px}"
    ".redtext  {FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px;FONT-WEIGHT:bold;COLOR:red}"
    ".greentext{FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px;FONT-WEIGHT:bold;COLOR:green}"
    ".whitetext{FONT-FAMILY:Arial,Helvetica,sans-serif;FONT-SIZE:12px;FONT-WEIGHT:bold;COLOR:white}"
    "</STYLE>"
    "</HEAD>"
    "<BODY bgColor=white>"
    "<TABLE cellSpacing=0 cellPadding=2 width=500 bgColor=#0061A3 border=0><TBODY><TR><TD>"
    "<TABLE class=maintext cellSpacing=0 cellPadding=3 width=100% bgColor=#DDDDFF border=0><TBODY>"
};

static const char SetupFoot[] = "</TBODY></TABLE></TD></TR></TBODY></TABLE></BODY></HTML>";
static const char SetupTitle[] = "<TR bgColor=#0061A3><TD class=whitetext width=%s>%s</TD><TD></TD></TR>";

static const char SubmitHead[] = "<FORM action=%s method=post %s>";
static const char SubmitFoot[] =
{
    "<TR><TD><INPUT type=submit value='  Set  '></TD>"
    "<TD><INPUT type=button value='Refresh' onClick=window.location.href=window.location.href></TD>"
    "</TR></FORM>"
};

static const char AutoHead[] =
{
    "<TR><TD vAlign=top>%s</TD>"
    "<TD><TABLE class=maintext width=100%% border=1><TBODY>"
    "<TR><TD><INPUT type=radio %s value='%s' name=%s>%s</TD></TR>"
    "<TR><TD><INPUT type=radio %s value='%s' name=%s>%s"
    "<TABLE class=maintext cellSpacing=0 cellPadding=3 border=0><TBODY>"
};

static const char AutoFoot[] = "</TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>";

static const char InputFloat[] = "<TR><TD>%s</TD><TD><INPUT size=%d value=%.2f name=%s> %s</TD></TR>";
static const char InputDigit[] = "<TR><TD>%s</TD><TD><INPUT size=%d value=%d name=%s></TD></TR>";
static const char InputText[] = "<TR><TD>%s</TD><TD><INPUT size=%d value='%s' name=%s></TD></TR>";
static const char InputFile[] = "<TR><TD>%s</TD><TD><INPUT type=file size=%d name=%s></TD></TR>";

static const char SelectHead[] = "<TR><TD>%s</TD><TD><SELECT name=%s>";
static const char SelectFoot[] = "</SELECT>%s</TD></TR>";
static const char SelectDigit[] = "<OPTION %s>%d</OPTION>";
static const char SelectText[] = "<OPTION %s>%s</OPTION>";
static const char *Selected[] = { "", "SELECTED" };

static const char CheckHead[] = "<TR><TD>%s</TD><TD>";
static const char CheckFoot[] = "</TD></TR>";
static const char CheckText[] = "<INPUT type=radio %s %s>%s ";
static const char *Checked[] = { "", "CHECKED" };

static const char ListHead[] =
{
    "<TR><TD vAlign=top>%s</TD>"
    "<TD><TABLE class=maintext width=100%% border=1><TBODY><TR>"
    "<TD><TABLE class=maintext cellSpacing=0 cellPadding=3 border=0><TBODY>"
    "<TR><TD><INPUT type=button value='Format' onClick=window.location.href='/admin/cgi-bin/file.cgi?%s'></TD></TR>"
};

static const char ListFoot[] = "</TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>";
static const char ListIcon[] = "<A href='/admin/cgi-bin/file.cgi?%s%s' target=content><IMG SRC=%s border=0></A>";

static const char ListFile[] =
{
    "<TR><TD width=160>%s</TD>"
    "<TD width=100 align=right>%lu</TD><TD>KB</TD><TD>"
};

static const char ListCard[] =
{
    "<TR><TD width=160><A href=/card-dev/%s target=_blank>%s</A></TD>"
    "<TD width=100 align=right>%lu</TD><TD>KB</TD><TD>"
};

static const char FunctionSubmit[] = "<TD><INPUT type=submit value='%s'></TD>";
static const char FunctionButton[] = "<TD><INPUT type=button value='%s' onClick=window.location.href='%s'></TD>";

static const TIMEZONE ZoneList[] = {
    {  0, -43200, "(GMT-12:00) International Date Line West"},
    {  1, -39600, "(GMT-11:00) Midway Island, Samoa"},
    {  2, -36000, "(GMT-10:00) Hawaii"},
    {  3, -32400, "(GMT-09:00) Alaska"},
    {  4, -28800, "(GMT-08:00) Pacific Time (US and Canada), Tijuana"},
    { 10, -25200, "(GMT-07:00) Mountain Time (US and Canada)"},
    { 13, -25200, "(GMT-07:00) Chihuahua, La Paz, Mazatlan"},
    { 15, -25200, "(GMT-07:00) Arizona"},
    { 20, -21600, "(GMT-06:00) Central Time (US and Canada)"},
    { 25, -21600, "(GMT-06:00) Saskatchewan"},
    { 30, -21600, "(GMT-06:00) Guadalajara, Mexico City, Monterrey"},
    { 33, -21600, "(GMT-06:00) Central America"},
    { 35, -18000, "(GMT-05:00) Eastern Time (US and Canada)"},
    { 40, -18000, "(GMT-05:00) Indiana (East)"},
    { 45, -18000, "(GMT-05:00) Bogota, Lima, Quito"},
    { 50, -14400, "(GMT-04:00) Atlantic Time (Canada)"},
    { 55, -14400, "(GMT-04:00) Caracas, La Paz"},
    { 56, -14400, "(GMT-04:00) Santiago"},
    { 60, -12600, "(GMT-03:30) Newfoundland and Labrador"},
    { 65, -10800, "(GMT-03:00) Brasilia"},
    { 70, -10800, "(GMT-03:00) Buenos Aires, Georgetown"},
    { 73, -10800, "(GMT-03:00) Greenland"},
    { 75,  -7200, "(GMT-02:00) Mid-Atlantic"},
    { 80,  -3600, "(GMT-01:00) Azores"},
    { 83,  -3600, "(GMT-01:00) Cape Verde Islands"},
    { 85,      0, "(GMT) Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London"},
    { 90,      0, "(GMT) Casablanca, Monrovia"},
    { 95,   3600, "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague"},
    {100,   3600, "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb"},
    {105,   3600, "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris"},
    {110,   3600, "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"},
    {113,   3600, "(GMT+01:00) West Central Africa"},
    {115,   7200, "(GMT+02:00) Bucharest"},
    {120,   7200, "(GMT+02:00) Cairo"},
    {125,   7200, "(GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius"},
    {130,   7200, "(GMT+02:00) Athens, Istanbul, Minsk"},
    {135,   7200, "(GMT+02:00) Jerusalem"},
    {140,   7200, "(GMT+02:00) Harare, Pretoria"},
    {145,  10800, "(GMT+03:00) Moscow, St. Petersburg, Volgograd"},
    {150,  10800, "(GMT+03:00) Kuwait, Riyadh"},
    {155,  10800, "(GMT+03:00) Nairobi"},
    {158,  10800, "(GMT+03:00) Baghdad"},
    {160,  12600, "(GMT+03:30) Tehran"},
    {165,  14400, "(GMT+04:00) Abu Dhabi, Muscat"},
    {170,  14400, "(GMT+04:00) Baku, Tbilisi, Yerevan"},
    {175,  14400, "(GMT+04:30) Kabul"},
    {180,  18000, "(GMT+05:00) Ekaterinburg"},
    {185,  18000, "(GMT+05:00) Islamabad, Karachi, Tashkent"},
    {190,  19800, "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi"},
    {193,  20700, "(GMT+05:45) Kathmandu"},
    {195,  21600, "(GMT+06:00) Astana, Dhaka"},
    {200,  21600, "(GMT+06:00) Sri Jayawardenepura"},
    {201,  21600, "(GMT+06:00) Almaty, Novosibirsk"},
    {203,  23400, "(GMT+06:30) Yangon Rangoon"},
    {205,  25200, "(GMT+07:00) Bangkok, Hanoi, Jakarta"},
    {207,  25200, "(GMT+07:00) Krasnoyarsk"},
    {210,  28800, "(GMT+08:00) Beijing, Chongqing, Hong Kong SAR, Urumqi"},
    {215,  28800, "(GMT+08:00) Kuala Lumpur, Singapore"},
    {220,  28800, "(GMT+08:00) Taipei"},
    {225,  28800, "(GMT+08:00) Perth"},
    {227,  28800, "(GMT+08:00) Irkutsk, Ulaanbaatar"},
    {230,  32400, "(GMT+09:00) Seoul"},
    {235,  32400, "(GMT+09:00) Osaka, Sapporo, Tokyo"},
    {240,  32400, "(GMT+09:00) Yakutsk"},
    {245,  34200, "(GMT+09:30) Darwin"},
    {250,  34200, "(GMT+09:30) Adelaide"},
    {255,  36000, "(GMT+10:00) Canberra, Melbourne, Sydney"},
    {260,  36000, "(GMT+10:00) Brisbane"},
    {265,  36000, "(GMT+10:00) Hobart"},
    {270,  36000, "(GMT+10:00) Vladivostok"},
    {275,  36000, "(GMT+10:00) Guam, Port Moresby"},
    {280,  39600, "(GMT+11:00) Magadan, Solomon Islands, New Caledonia"},
    {285,  43200, "(GMT+12:00) Fiji Islands, Kamchatka, Marshall Islands"},
    {290,  43200, "(GMT+12:00) Auckland, Wellington"},
    {300,  46800, "(GMT+13:00) Nuku'alofa"},
};

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/


/**************************************************************/
/*  AspCallback                                               */
/*                                                            */
/* This routine must have been registered by                  */
/* NutRegisterAspCallback() and is automatically called by    */
/* NutHttpProcessFileRequest() when the server process a page */
/* with an asp function.                                      */
/*                                                            */
/* Return 0 on success, -1 otherwise.                         */
/**************************************************************/

static int AspCallback(char *func, FILE *stream)
{
    _PrintCfg *cfg = GrabPrintConfig();
    _PrintRecord *rec = GrabPrintRecord();
    char buf[32];

    if (strcmp(func, "nut_host_name") == 0) {
        fputs(confos.hostname, stream);
        return (0);
    }
    if (strcmp(func, "nut_cip_addr") == 0) {
        fputs(inet_ntoa(confnet.cdn_cip_addr), stream);
        return (0);
    }
    if (strcmp(func, "model_name") == 0) {
        fputs(ModelName, stream);
        return (0);
    }
    if (strcmp(func, "ext_name") == 0) {
        fputs(ExtModelName, stream);
        return (0);
    }
    if (strcmp(func, "var_name") == 0) {
        fputs(VerName, stream);
        return (0);
    }
    if (strcmp(func, "checksum") == 0) {
        fprintf(stream, "%08X", CalculateCheckSum());
        return (0);
    }
    if (strcmp(func, "milage") == 0) {
        fprintf(stream, "%.3f", (float)rec->DotMilage / (MM_DOT * 1000000));
        return (0);
    }
    if (strcmp(func, "logo") == 0) {
        if (GetProfileString("MODELNAME", buf))
            fputs("/oemlogo.gif", stream);
        else
            fputs("/tsclogo.gif", stream);
        return (0);
    }
    if (strcmp(func, "icon") == 0) {
        if (GetProfileString("MODELNAME", buf))
            fputs("/oemicon.ico", stream);
        else
            fputs("/tscicon.ico", stream);
        return (0);
    }

    return (-1);
}

THREAD(NutPrintTest, arg)
{
    REPORT *Report;

    Report = SelfTestReport(NULL, FALSE, OUTPUT_LABEL);
    Report = IpConfigReport(Report, FALSE, OUTPUT_LABEL);
    Report = BtConfigReport(Report, FALSE, OUTPUT_LABEL);
    Report = FileReport(Report, TRUE, OUTPUT_LABEL);
    WaitWorkJobEnd();
    if (arg) *(int *)arg = 0;
    NutThreadExit();
}

THREAD(NutRestart, arg)
{
    NutSleep(1000);

    /* To restart the printer */
    PrinterReboot();
    NutThreadExit();
}

static int SetupGeneral(FILE * stream, REQUEST * req)
{
    static const char *Removal[] = {"OFF","TEAR","PEEL","CUTTER"};

    _PrintCfg *cfg = GrabPrintConfig();
    int CodePageTotal = GetCodePageTotal();
    int CountryTotal = GetCountryTotal();
    int i, j, count;

    if (req->req_query) {
        char *name, *value;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "speed") == 0)
                cfg->Speed = SpeedRange(atof(value));
            if (strcmp(name, "density") == 0)
                cfg->fDensity = atof(value);
            if (strcmp(name, "direction") == 0)
                cfg->Direction = atoi(value);
            if (strcmp(name, "code_page") == 0)
                SetCodePage(value);
            if (strcmp(name, "country") == 0)
                SetCountry(value);
            if (strcmp(name, "removal") == 0) {
                if (strcmp(value, Removal[0]) == 0)
                    cfg->PrintOutMode = OFF_MODE;
                if (strcmp(value, Removal[1]) == 0)
                    cfg->PrintOutMode = TEAR_MODE;
                if (strcmp(value, Removal[2]) == 0)
                    cfg->PrintOutMode = PEEL_MODE;
                if (strcmp(value, Removal[3]) == 0)
                    cfg->PrintOutMode = CUTTER_MODE;
            }
            if (strcmp(name, "cut_piece") == 0)
                cfg->CutterPieces = atoi(value);
            if (strcmp(name, "cut_back") == 0)
                cfg->CutterBack = atoi(value);
            if (strcmp(name, "mirror") == 0)
                cfg->Mirror = atoi(value);
            if (strcmp(name, "head") == 0)
                cfg->CarriageOpen = atoi(value);
            if (strcmp(name, "reprint") == 0)
                cfg->Reprint = atoi(value);
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "General Setup");
    //fprintf(stream, SetupTitle, "30%", "通用设置");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/general.cgi", "");

    fprintf(stream, InputText, "Speed :", 4, ToSpeedString(cfg->Speed), "speed");

    fprintf(stream, SelectHead, "Density :", "density");
    for (i = DensityMin; i <= DensityMax; i++)
        fprintf(stream, SelectDigit, Selected[cfg->fDensity == (float)i], i);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Direction :", "direction");
    for (i = 0; i <= 1; i++)
        fprintf(stream, SelectDigit, Selected[cfg->Direction == i], i);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Code Page :", "code_page");
    for (i = 0; i < CodePageTotal; i++)
        fprintf(stream, SelectText, Selected[cfg->CodePage == i], CodePageNameTable[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Country Code :", "country");
    for (i = 0; i < CountryTotal; i++)
        fprintf(stream, SelectText, Selected[cfg->Country == i], CountryNameTable[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Post-Print Action :", "removal");
    for (i = 0; i < sizeof(Removal) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->PrintOutMode == i], Removal[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, InputDigit, "Cut Piece :", 4, cfg->CutterPieces, "cut_piece");

    fprintf(stream, CheckHead, "Cut Back :");
    fprintf(stream, CheckText, Checked[cfg->CutterBack == 1], "value=1 name=cut_back", "ON");
    fprintf(stream, CheckText, Checked[cfg->CutterBack == 0], "value=0 name=cut_back", "OFF");
    fputs(CheckFoot, stream);

    fprintf(stream, CheckHead, "Mirror :");
    fprintf(stream, CheckText, Checked[cfg->Mirror == 1], "value=1 name=mirror", "ON");
    fprintf(stream, CheckText, Checked[cfg->Mirror == 0], "value=0 name=mirror", "OFF");
    fputs(CheckFoot, stream);

    fprintf(stream, CheckHead, "Head-up Sensor :");
    fprintf(stream, CheckText, Checked[cfg->CarriageOpen == 1], "value=1 name=head", "ON");
    fprintf(stream, CheckText, Checked[cfg->CarriageOpen == 0], "value=0 name=head", "OFF");
    fputs(CheckFoot, stream);

    fprintf(stream, CheckHead, "Reprint After Error :");
    fprintf(stream, CheckText, Checked[cfg->Reprint == 1], "value=1 name=reprint", "ON");
    fprintf(stream, CheckText, Checked[cfg->Reprint == 0], "value=0 name=reprint", "OFF");
    fputs(CheckFoot, stream);

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupAdjust(FILE * stream, REQUEST * req)
{
    _PrintCfg *cfg = GrabPrintConfig();
    int i, count;

    if (req->req_query) {
        char *name, *value;
        int adjust;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "offset") == 0) {
                adjust = atoi(value);
                if (abs(adjust) <= (int)TPH_DPI)
                    cfg->OffsetDis = adjust;
            }
            if (strcmp(name, "ref_x") == 0) {
                adjust = atoi(value);
                if (adjust >= 0)
                    cfg->ReferenceX = adjust;
            }
            if (strcmp(name, "ref_y") == 0) {
                adjust = atoi(value);
                if (adjust >= 0)
                    cfg->ReferenceY = adjust;
            }
            if (strcmp(name, "shift_x") == 0)
                cfg->ShiftDisX = atoi(value);
            if (strcmp(name, "shift_y") == 0)
                cfg->ShiftDisY = atoi(value);
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Adjust Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/adjust.cgi", "");

    fprintf(stream, InputDigit, "Offset :", 4, cfg->OffsetDis, "offset");
    fprintf(stream, InputDigit, "Reference X :", 4, cfg->ReferenceX, "ref_x");
    fprintf(stream, InputDigit, "Reference Y :", 4, cfg->ReferenceY, "ref_y");
    fprintf(stream, InputDigit, "Shift X :", 4, cfg->ShiftDisX, "shift_x");
    fprintf(stream, InputDigit, "Shift Y :", 4, cfg->ShiftDisY, "shift_y");

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupMedia(FILE * stream, REQUEST * req)
{
    static const char *Sensor[] = {"Gap","Black Mark","Continuous"};
    static const char *Ribbon[] = {"Direct-Thermal","Thermal-Transfer"};
    static const char *UnitDescr[] = {"inch","mm"};
    static const float UnitValue[] = {TPH_DPI,MM_DOT};
    static int unit = 0;

    _PrintCfg *cfg = GrabPrintConfig();
    int i, count;

    if (req->req_query) {
        char *name, *value;
        int change = 0;
        float size;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "unit") == 0)
                unit = atoi(value);
            if (strcmp(name, "width") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= TPH_WIDTH_DOT)
                    cfg->PaperWidth = (u_short)size;
            }
            if (strcmp(name, "height") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= MAX_IMAGE_LENGTH)
                    cfg->fPaperSize = size;
                change = 1;
            }
            if (strcmp(name, "gap_size") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= (TPH_DPI * 5))
                    cfg->fGapSize = size;
                change = 1;
            }
            if (strcmp(name, "gap_offset") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= (TPH_DPI * 5))
                    cfg->fGapOffset = size;
            }
            if (strcmp(name, "bline_size") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= (TPH_DPI * 5))
                    cfg->fBlineSize = size;
                change = 1;
            }
            if (strcmp(name, "bline_offset") == 0) {
                size = atof(value) * UnitValue[unit];
                if (size > 0 && size <= (TPH_DPI * 5))
                    cfg->fBlineOffset = size;
            }
            if (strcmp(name, "sensor") == 0) {
                if (strcmp(value, Sensor[0]) == 0)
                    cfg->SensorMode = GAP_MODE;
                if (strcmp(value, Sensor[1]) == 0)
                    cfg->SensorMode = BLINE_MODE;
                if (strcmp(value, Sensor[2]) == 0) {
                    if (cfg->SensorMode != CONTINUE_MODE_T)
                        DetectContinuousInten(cfg);
                    cfg->SensorMode = CONTINUE_MODE_T;
                }
                change = 1;
            }
            if (strcmp(name, "ribbon") == 0) {
                if (strcmp(value, Ribbon[0]) == 0)
                    cfg->RibbonFlag = 0;
#if defined(RIBBON_MODEL)
                if (strcmp(value, Ribbon[1]) == 0) {
                    if (cfg->RibbonFlag == 0) {
                        WaitWorkJobEnd();
                        CheckRibbonExists(FALSE, FALSE);
                    }
                    StopTryRibbonEncoder();
                    cfg->RibbonFlag = 1;
                }
#endif
            }
        }
        if (change == 1) {
            size = CalculateLabelSize(cfg);
            ReallocImageBuffer(&sImageBuffer, (u_short)size);
            InitialCalibration();
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Media Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/media.cgi", "");

    fprintf(stream, CheckHead, "Unit :");
    fprintf(stream, CheckText, Checked[unit == 0], "onClick=window.location.href='/cgi-bin/media.cgi?unit=0'", UnitDescr[0]);
    fprintf(stream, CheckText, Checked[unit == 1], "onClick=window.location.href='/cgi-bin/media.cgi?unit=1'", UnitDescr[1]);
    fputs(CheckFoot, stream);

    fprintf(stream, InputFloat, "Paper Width :", 6, cfg->PaperWidth / UnitValue[unit], "width", UnitDescr[unit]);
    fprintf(stream, InputFloat, "Paper Height :", 6, cfg->fPaperSize / UnitValue[unit], "height", UnitDescr[unit]);
    fprintf(stream, InputFloat, "Gap Size :", 6, cfg->fGapSize / UnitValue[unit], "gap_size", UnitDescr[unit]);
    fprintf(stream, InputFloat, "Gap Offset :", 6, cfg->fGapOffset / UnitValue[unit], "gap_offset", UnitDescr[unit]);
    fprintf(stream, InputFloat, "Black Mark Size :", 6, cfg->fBlineSize / UnitValue[unit], "bline_size", UnitDescr[unit]);
    fprintf(stream, InputFloat, "Black Mark Offset :", 6, cfg->fBlineOffset / UnitValue[unit], "bline_offset", UnitDescr[unit]);

    fprintf(stream, SelectHead, "Sensor Type :", "sensor");
    for (i = 0; i < sizeof(Sensor) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->SensorMode == i], Sensor[i]);
    fprintf(stream, SelectFoot, "");

#if defined(RIBBON_MODEL)
    fprintf(stream, SelectHead, "Print Method :", "ribbon");
    for (i = 0; i < sizeof(Ribbon) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->RibbonFlag == i], Ribbon[i]);
    fprintf(stream, SelectFoot, "");
#endif

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupCalibrate(FILE * stream, REQUEST * req)
{
    _PrintCfg *cfg = GrabPrintConfig();
    int i, count;

    if (req->req_query) {
        char *name, *value;
        u_int sensor;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "gap_inten") == 0) {
                sensor = atoi(value);
                if (sensor < GAP_SENSOR_SCALE)
                    cfg->GapInten = sensor;
            }
            if (strcmp(name, "bline_inten") == 0) {
                sensor = atoi(value);
                if (sensor < BLINE_SENSOR_SCALE)
                    cfg->BlineInten = sensor;
            }
            if (strcmp(name, "cont_inten") == 0) {
                sensor = atoi(value);
                if (sensor < GAP_SENSOR_SCALE)
                    cfg->ContinuousInten = sensor;
            }
            if (strcmp(name, "auto") == 0)
                cfg->AutoSensorRef = atoi(value);
            if (strcmp(name, "gap_ref") == 0) {
                sensor = atoi(value);
                if (sensor < AD_SCALE)
                    cfg->GapRef = sensor;
            }
            if (strcmp(name, "bline_ref") == 0) {
                sensor = atoi(value);
                if (sensor < AD_SCALE)
                    cfg->BlineRef = sensor;
            }
            if (strcmp(name, "cont_ref") == 0) {
                sensor = atoi(value);
                if (sensor < AD_SCALE)
                    cfg->ContinuousRef = sensor;
            }
        }
        InitialCalibration();
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Calibration Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/calibrate.cgi", "");

    fprintf(stream, InputDigit, "Gap Intension :", 4, cfg->GapInten, "gap_inten");
    fprintf(stream, InputDigit, "Black Mark Intension :", 4, cfg->BlineInten, "bline_inten");
    fprintf(stream, InputDigit, "Continuous Intension :", 4, cfg->ContinuousInten, "cont_inten");

    fprintf(stream, AutoHead, "Sensor Reference :",
        Checked[cfg->AutoSensorRef == 1], "1", "auto", "Automatically",
        Checked[cfg->AutoSensorRef == 0], "0", "auto", "Manually");
    fprintf(stream, InputDigit, "--- Gap Reference :", 4, cfg->GapRef, "gap_ref");
    fprintf(stream, InputDigit, "--- Black Mark Reference :", 4, cfg->BlineRef, "bline_ref");
    fprintf(stream, InputDigit, "--- Continuous Reference :", 4, cfg->ContinuousRef, "cont_ref");
    fputs(AutoFoot, stream);

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupSerial(FILE * stream, REQUEST * req)
{
    static const char *baud[]    = {"0","1200","2400","4800","9600","19200","38400","57600","115200"};
    static const char *dataBit[] = {"7","8"};
    static const char *parity[]  = {"None","Odd","Even"};
    static const char *stopBit[] = {"1","2"};

    _PrintCfg *cfg = GrabPrintConfig();
    int i, count;

    if (req->req_query) {
        char *name, *value;
        long  valueBaud   = atol(baud[cfg->UartSetting.Baud]);
        short valueData   = atoi(dataBit[cfg->UartSetting.DataBits]);
        char  valueParity = *parity[cfg->UartSetting.Parity];
        short valueStop   = atoi(stopBit[cfg->UartSetting.Stop]);

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "rate") == 0)
                valueBaud = atol(value);
            if (strcmp(name, "data") == 0)
                valueData = atoi(value);
            if (strcmp(name, "parity") == 0)
                valueParity = *value;
            if (strcmp(name, "stop") == 0)
                valueStop = atoi(value);
        }
        SetSerialPort(valueBaud, valueData, valueParity, valueStop);
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Serial Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/serial.cgi", "");

    fprintf(stream, SelectHead, "Baud Rate :", "rate");
    for (i = 1; i < sizeof(baud) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->UartSetting.Baud == i], baud[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Data Bits :", "data");
    for (i = 0; i < sizeof(dataBit) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->UartSetting.DataBits == i], dataBit[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Parity :", "parity");
    for (i = 0; i < sizeof(parity) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->UartSetting.Parity == i], parity[i]);
    fprintf(stream, SelectFoot, "");

    fprintf(stream, SelectHead, "Stop Bit(s) :", "stop");
    for (i = 0; i < sizeof(stopBit) / sizeof(char *); i++)
        fprintf(stream, SelectText, Selected[cfg->UartSetting.Stop == i], stopBit[i]);
    fprintf(stream, SelectFoot, "");

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupNetwork(FILE * stream, REQUEST * req)
{
    int i, count;

    if (req->req_query) {
        char *name, *value;
        u_long address;
        int assign = confnet.cdn_cip_addr ? 1 : 0;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "name") == 0) {
                strncpy(confos.hostname, value, sizeof(confos.hostname) - 1);
                confos.hostname[sizeof(confos.hostname) - 1] = 0;
            }
            if (strcmp(name, "assign") == 0)
                assign = atoi(value);
            if (strcmp(name, "address") == 0) {
                if ((address = inet_addr(value)) != (u_long)-1)
                    confnet.cdn_cip_addr = address;
            }
            if (strcmp(name, "mask") == 0) {
                if ((address = inet_addr(value)) != (u_long)-1)
                    confnet.cdn_ip_mask = address;
            }
            if (strcmp(name, "gateway") == 0) {
                if ((address = inet_addr(value)) != (u_long)-1)
                    confnet.cdn_gateway = address;
            }
            if (strcmp(name, "primary") == 0) {
                if ((address = inet_addr(value)) != (u_long)-1)
                    confnet.cdn_pdns = address;
            }
            if (strcmp(name, "second") == 0) {
                if ((address = inet_addr(value)) != (u_long)-1)
                    confnet.cdn_sdns = address;
            }
        }
        if (assign == 0)
            confnet.cdn_cip_addr = 0;

        NutSaveConfig();
        NutNetSaveConfig();
        NutSetPrintServerName(confos.hostname);
        NutThreadCreate("restart", NutRestart, 0, NUT_THREAD_MAIN_STACK);

        fputs(SetupHead, stream);
        fprintf(stream, SetupTitle, "80%", "Network Setup");
        fputs("<TR><TD>Restart ...</TD><TD></TD></TR>", stream);
        fputs(SetupFoot, stream);
        fflush(stream);
        return 0;
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Network Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/network.cgi", "");

    fprintf(stream, InputText, "Printer Name :", 20, confos.hostname, "name");

    fprintf(stream, AutoHead, "IP Address :",
        Checked[confnet.cdn_cip_addr == 0], "0", "assign", "DHCP",
        Checked[confnet.cdn_cip_addr != 0], "1", "assign", "Static IP");
    fprintf(stream, InputText, "--- IP Address :", 20, inet_ntoa(confnet.cdn_ip_addr), "address");
    fprintf(stream, InputText, "--- Subnet Mask :", 20, inet_ntoa(confnet.cdn_ip_mask), "mask");
    fprintf(stream, InputText, "--- Default Gateway :", 20, inet_ntoa(confnet.cdn_gateway), "gateway");
    fputs(AutoFoot, stream);

    fprintf(stream, InputText, "Primary DNS Server :", 20, inet_ntoa(confnet.cdn_pdns), "primary");
    fprintf(stream, InputText, "Secondary DNS Server :", 20, inet_ntoa(confnet.cdn_sdns), "second");

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupMail(FILE * stream, REQUEST * req)
{
    _PrintCfg *cfg = GrabPrintConfig();
    CONFSMTP *smtp = &cfg->confsmtp;
    int i, count;

    if (req->req_query) {
        char *name, *value;
        u_long address;
        int assign = confnet.cdn_cip_addr ? 1 : 0;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "smtp") == 0) {
                strncpy(smtp->server, value, sizeof(smtp->server) - 1);
                smtp->server[sizeof(smtp->server) - 1] = 0;
            }
            if (strcmp(name, "auth") == 0)
                smtp->auth = atoi(value);
            if (strcmp(name, "user") == 0) {
                strncpy(smtp->username, value, sizeof(smtp->username) - 1);
                smtp->username[sizeof(smtp->username) - 1] = 0;
            }
            if (strcmp(name, "pass") == 0) {
                strncpy(smtp->password, value, sizeof(smtp->password) - 1);
                smtp->password[sizeof(smtp->password) - 1] = 0;
            }
            if (strcmp(name, "sender") == 0) {
                strncpy(smtp->sender, value, sizeof(smtp->sender) - 1);
                smtp->sender[sizeof(smtp->sender) - 1] = 0;
            }
            if (strcmp(name, "rcvr") == 0) {
                strncpy(smtp->receiver, value, sizeof(smtp->receiver) - 1);
                smtp->receiver[sizeof(smtp->receiver) - 1] = 0;
            }
            if (strcmp(name, "notify") == 0)
                smtp->notify = atoi(value);
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Mail Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/mail.cgi", "");

    fprintf(stream, InputText, "SMTP Server :", 40, smtp->server, "smtp");

    fprintf(stream, AutoHead, "SMTP Authentication :",
        Checked[smtp->auth == 0], "0", "auth", "Disable",
        Checked[smtp->auth == 1], "1", "auth", "Enable");
    fprintf(stream, InputText, "--- User Name :", 20, smtp->username, "user");
    fprintf(stream, InputText, "--- Password :", 20, smtp->password, "pass");
    fputs(AutoFoot, stream);

    fprintf(stream, InputText, "Sender E-mail Address :", 40, smtp->sender, "sender");

    fprintf(stream, InputText, "Receiver E-mail Address :", 40, smtp->receiver, "rcvr");

    fprintf(stream, CheckHead, "E-mail Notification :");
    fprintf(stream, CheckText, Checked[smtp->notify == 1], "value=1 name=notify", "ON");
    fprintf(stream, CheckText, Checked[smtp->notify == 0], "value=0 name=notify", "OFF");
    fputs(CheckFoot, stream);

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupClock(FILE * stream, REQUEST * req)
{
    _PrintCfg *cfg = GrabPrintConfig();
    CONFSNTP *sntp = &cfg->confsntp;
    int i, j, count;

    if (req->req_query) {
        char *name, *value;
        int hour = 0, minute = 0;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "sync") == 0)
                sntp->sync = atoi(value);
            if (strcmp(name, "sntp_1") == 0) {
                strncpy(sntp->server[0], value, sizeof(sntp->server[0]) - 1);
                sntp->server[0][sizeof(sntp->server[0]) - 1] = 0;
            }
            if (strcmp(name, "sntp_2") == 0) {
                strncpy(sntp->server[1], value, sizeof(sntp->server[1]) - 1);
                sntp->server[1][sizeof(sntp->server[1]) - 1] = 0;
            }
            if (strcmp(name, "sntp_3") == 0) {
                strncpy(sntp->server[2], value, sizeof(sntp->server[2]) - 1);
                sntp->server[2][sizeof(sntp->server[2]) - 1] = 0;
            }
            if (strcmp(name, "interval_hour") == 0)
                sntp->interval = (hour = atoi(value)) * 3600 + minute * 60;
            if (strcmp(name, "interval_minute") == 0)
                sntp->interval = hour * 3600 + (minute = atoi(value)) * 60;
            if (strcmp(name, "time_zone") == 0) {
                for (j = 0; j < sizeof(ZoneList) / sizeof(TIMEZONE); j++) {
                    if (strcmp(ZoneList[j].Description, value) == 0) {
                        sntp->timezone = ZoneList[j].Index;
                        sntp->timediffer = ZoneList[j].Difference;
                        break;
                    }
                }
            }
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Clock Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/clock.cgi", "");

    fprintf(stream, CheckHead, "Synchronized Clock :");
    fprintf(stream, CheckText, Checked[sntp->sync == 1], "value=1 name=sync", "ON");
    fprintf(stream, CheckText, Checked[sntp->sync == 0], "value=0 name=sync", "OFF");
    fputs(CheckFoot, stream);

    fprintf(stream, InputText, "SNTP Server 1 :", 40, sntp->server[0], "sntp_1");
    fprintf(stream, InputText, "SNTP Server 2 :", 40, sntp->server[1], "sntp_2");
    fprintf(stream, InputText, "SNTP Server 3 :", 40, sntp->server[2], "sntp_3");

    fprintf(stream, CheckHead, "Update Interval :");
    fprintf(stream, "<INPUT size=4 value=%d name=interval_hour> Hour    ", sntp->interval / 3600);
    fprintf(stream, "<INPUT size=4 value=%d name=interval_minute> Minute", sntp->interval / 60 % 60);
    fputs(CheckFoot, stream);

    fprintf(stream, SelectHead, "Time Zone :", "time_zone");
    for (i = 0; i < sizeof(ZoneList) / sizeof(TIMEZONE); i++)
        fprintf(stream, SelectText, Selected[sntp->timezone == ZoneList[i].Index], ZoneList[i].Description);
    fprintf(stream, SelectFoot, "");

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int SetupPassword(FILE * stream, REQUEST * req)
{
    _PrintCfg *cfg = GrabPrintConfig();
    CONFWEB *web = &cfg->confweb;
    int i, count;

    if (req->req_query) {
        char *name, *value;
        int reset = 0;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "rootname") == 0 && strcmp(web->rootname, value) != 0) {
                strncpy(web->rootname, value, sizeof(web->rootname) - 1);
                web->rootname[sizeof(web->rootname) - 1] = 0;
                reset = 1;
            }
            if (strcmp(name, "rootpass") == 0 && strcmp(web->rootpass, value) != 0) {
                strncpy(web->rootpass, value, sizeof(web->rootpass) - 1);
                web->rootpass[sizeof(web->rootpass) - 1] = 0;
                reset = 1;
            }
            if (strcmp(name, "adminname") == 0 && strcmp(web->adminname, value) != 0) {
                strncpy(web->adminname, value, sizeof(web->adminname) - 1);
                web->adminname[sizeof(web->adminname) - 1] = 0;
                reset = 1;
            }
            if (strcmp(name, "adminpass") == 0 && strcmp(web->adminpass, value) != 0) {
                strncpy(web->adminpass, value, sizeof(web->adminpass) - 1);
                web->adminpass[sizeof(web->adminpass) - 1] = 0;
                reset = 1;
            }
        }

        if (reset == 1) {
            NutThreadCreate("restart", NutRestart, 0, NUT_THREAD_MAIN_STACK);

            fputs(SetupHead, stream);
            fprintf(stream, SetupTitle, "80%", "Password Setup");
            fputs("<TR><TD>Restart ...</TD><TD></TD></TR>", stream);
            fputs(SetupFoot, stream);
            fflush(stream);
            return 0;
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Password Setup");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/password.cgi", "");

    fprintf(stream, InputText, "User Name :", 20, web->rootname, "rootname");
    fprintf(stream, InputText, "User Password :", 20, web->rootpass, "rootpass");
    fprintf(stream, InputText, "Administrator Name :", 20, web->adminname, "adminname");
    fprintf(stream, InputText, "Administrator Password :", 20, web->adminpass, "adminpass");

    fputs(SubmitFoot, stream);
    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int PrinterFunction(FILE * stream, REQUEST * req)
{
    static int printing = 0;

    _PrintCfg *cfg = GrabPrintConfig();
    int i, count, got;

    if (req->req_stream && (req->req_query = NutHeapAlloc(req->req_length + 1)) != NULL) {
        for (i = 0; i < req->req_length; i += got) {
            got = fread(req->req_query + i, sizeof(char), req->req_length - i, req->req_stream);
            if (got <= 0) {
                NutHeapFree(req->req_query);
                req->req_query = NULL;
                break;
            }
        }
    }

    if (req->req_query) {
        char *name, *value;
        int reset = 0;
        int report = 0;

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            if (strcmp(name, "func") == 0) {
                if (strcmp(value, "reset") == 0)
                    reset = 1;
                if (strcmp(value, "default") == 0) {
                    InitialDefaultVar();
                    reset = 1;
                }
                if (strcmp(value, "report") == 0)
                    report = 1;
                if (strcmp(value, "ignore") == 0) {
                    cfg->IgnoreAutoRun = TRUE;
                    reset = 1;
                }
            }
        }
        if (reset == 1) {
            NutThreadCreate("restart", NutRestart, 0, NUT_THREAD_MAIN_STACK);

            fputs(SetupHead, stream);
            fprintf(stream, SetupTitle, "80%", "Printer Function");
            fputs("<TR><TD>Restart ...</TD><TD></TD></TR>", stream);
            fputs(SetupFoot, stream);
            fflush(stream);
            return 0;
        }
        if (report == 1) {
            if (printing == 0 && !IsMotion() && !CheckJobLock() && !GetJobErrorState()) {
                printing = 1;
                NutThreadCreate("report", NutPrintTest, &printing, NUT_THREAD_MAIN_STACK);
            }
        }

        if (req->req_type && strstr(req->req_type, "multipart/form-data") != NULL) {
            char *content = NULL;
            int index, separate, length;

            separate = strcspn(req->req_query, "\r\n");

            for (index = separate; index < req->req_length; index++) {
                /* Empty line marks the end of the header. */
                if (memcmp(req->req_query + index, "\r\n\r\n", 4) == 0 ||
                    memcmp(req->req_query + index, "\n\r\n\r", 4) == 0) {
                    content = req->req_query + index + 4;
                    for (length = 0; index + length + 4 < req->req_length; length++) {
                        if (memcmp(content + length, req->req_query + index + 2, 2) == 0 &&
                            memcmp(content + length + 2, req->req_query, separate) == 0)
                            break;
                    }
                    break;
                }
                if (memcmp(req->req_query + index, "\r\r", 2) == 0 ||
                    memcmp(req->req_query + index, "\n\n", 2) == 0) {
                    content = req->req_query + index + 2;
                    for (length = 0; index + length + 2 < req->req_length; length++) {
                        if (memcmp(content + length, req->req_query + index + 1, 1) == 0 &&
                            memcmp(content + length + 1, req->req_query, separate) == 0)
                            break;
                    }
                    break;
                }
            }

            if (content && length) {
                NETRXBUF *rxbuf;
                while ((rxbuf = NetRxCreate()) == 0)
                    NutSleep(100);
                rxbuf->sock = (TCPSOCKET *)_fileno(stream);
                NetRxDataIn((u_char *)content, length, rxbuf);
                rxbuf->sock = 0;
                if (rxbuf->length == 0)
                    NetRxDestroy(rxbuf);
            }
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "40%", "Printer Function");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/function.cgi", "encType=multipart/form-data");

    fputs("<TR>", stream);
    fprintf(stream, FunctionButton, "Reset Printer", "/admin/cgi-bin/function.cgi?func=reset");
    fprintf(stream, FunctionButton, "Factory Default", "/admin/cgi-bin/function.cgi?func=default");
    fputs("</TR>", stream);

    fputs("<TR>", stream);
    fprintf(stream, FunctionButton, "Print Configuration", "/admin/cgi-bin/function.cgi?func=report");
    fprintf(stream, FunctionButton, "Ignore AUTO.BAS", "/admin/cgi-bin/function.cgi?func=ignore");
    fputs("</TR>", stream);

    fputs("<TR>", stream);
    fprintf(stream, FunctionSubmit, "Send File to Printer");
    fputs("<TD><INPUT type=file size=30 name=send></TD>", stream);
    fputs("</TR></FORM>", stream);

    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int PrinterUpgrade(FILE * stream, REQUEST * req)
{
    char *message = "Invalid file.";
    long size = HTTP_MAX_DATA_SIZE;
    long length = req->req_length;
    NETRXBUF *rxbuf = NULL;
    int first, got;

    if (req->req_stream && (req->req_query = NutHeapAlloc(size)) != NULL) {
        /* Parse the header lines */
        while (length > 0) {
            /* Read a line and chop off CR/LF */
            if (fgets(req->req_query, size, req->req_stream) == NULL)
                break;
            length -= strlen(req->req_query);
            /* Empty line marks the end of the header */
            if (req->req_query == strchr(req->req_query, '\r') ||
                req->req_query == strchr(req->req_query, '\n'))
            break;
        }

        /* Load the data to the receive buffer */
        first = length;
        while (length > 0) {
            if (size > length)
                size = length;
            if ((got = fread(req->req_query, sizeof(char), size, req->req_stream)) <= 0)
                break;
            /* Check prefix if the update file */
            if (first == length && memcmp(req->req_query, "Fuse", 4) == 0) {
                /* Create the receive buffer */
                while ((rxbuf = NetRxCreate()) == 0)
                    NutSleep(100);
                rxbuf->sock = (TCPSOCKET *)_fileno(stream);
            }
            if (rxbuf)
                NetRxDataIn((u_char *)req->req_query, got, rxbuf);
            length -= got;
        }
        if (rxbuf) {
            rxbuf->sock = 0;
            if (rxbuf->length == 0)
                NetRxDestroy(rxbuf);
            if (length == 0)
                message = "Your printer is performing firmware upgrade, please wait.";
        }

        fputs(SetupHead, stream);
        fprintf(stream, SetupTitle, "80%", "Printer Upgrade");
        fprintf(stream, "<TR><TD>%s</TD><TD></TD></TR>", message);
        fputs(SetupFoot, stream);
        fflush(stream);
        return 0;
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Printer Upgrade");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/upgrade.cgi", "encType=multipart/form-data");

    fprintf(stream, InputFile, "Select a Firmware File :", 30, "upgrade");

    fputs("<TR>", stream);
    fprintf(stream, FunctionSubmit, "Upgrade");
    fprintf(stream, FunctionButton, "Cancel", "window.location.href");
    fputs("</TR></FORM>", stream);

    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int PrinterStatus(FILE * stream, REQUEST * req)
{
    _eMotorStatus motor = GetMotorStatus();
    u_short error = GetJobErrorState();
    int lock = CheckJobLock();
    char *color = "class=redtext";
    char *status = "Ready";

    if (motor == STATUS_MOTOR_FORWARD || motor == STATUS_MOTOR_BACKWARD)
        status = "Printing";
    if (lock)
        status = "Pause";
    if (IsMemoryFailed())
        status = "Out of Memory";
    if (error & ERROR_TPH_OPEN)
        status = "Carriage Open";
    if (error & ERROR_TPH_OVERHEAT || error & ERROR_MOTOR_OVERHEAT)
        status = "Over Heat";
    if (error & ERROR_PAPER_JAM)
        status = "Paper Jam";
    if (error & ERROR_PAPER_EMPTY)
        status = "Paper Empty";
    if (error & ERROR_RIBBON_JAM || error & ERROR_RIBBON_EMPTY)
        status = "Ribbon Error";
    if (error & ERROR_CUTTER)
        status = "Cutter Error";

    if (strcmp(status, "Ready") == 0 || strcmp(status, "Printing") == 0)
        color = "class=greentext";

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Printer Status");

    fprintf(stream, "<TR><TD %s>%s</TD>", color, status);
    fprintf(stream, FunctionButton, "Refresh", "/cgi-bin/status.cgi");
    fputs("</TR>", stream);

    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

static int PrinterFile(FILE * stream, REQUEST * req)
{
    _eFileDevice device = NO_SELECT_DEVICE;
    _FileHandle * handle;
    _FileList list;
    int i, count, got;

    if (req->req_stream && (req->req_query = NutHeapAlloc(req->req_length + 1)) != NULL) {
        for (i = 0; i < req->req_length; i += got) {
            got = fread(req->req_query + i, sizeof(char), req->req_length - i, req->req_stream);
            if (got <= 0) {
                NutHeapFree(req->req_query);
                req->req_query = NULL;
                break;
            }
        }
    }

    if (req->req_query) {

        count = NutHttpGetParameterCount(req);

        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            char *name = NutHttpGetParameterName(req, i);
            char *value = NutHttpGetParameterValue(req, i);
            char *status = NULL;

            if (CheckJobLock())
                status = "paused";
            if (IsMotion())
                status = "is busy";
            if (GetJobErrorState())
                status = "error";

            if (status == NULL) {
                if (memcmp(value, "DRAM", 4) == 0)
                    device = DRAM_DEVICE;
                if (memcmp(value, "FLASH", 5) == 0)
                    device = FLASH_DEVICE;
                if (memcmp(value, "CARD", 4) == 0)
                    device = CARD_DEVICE;

                if (strcmp(name, "format") == 0)
                    ErasingFile(device, "*");
                if (strcmp(name, "del") == 0)
                    ErasingFile(device, strchr(value, ':') + 1);
                if (strcmp(name, "run") == 0) {
                    if (RunBasicFile(device, strchr(value, ':') + 1) == FALSE)
                        status = "is busy";
                }
            }

            if (status) {
                fputs(SetupHead, stream);
                fprintf(stream, SetupTitle, "80%", "Printer File");
                fprintf(stream, "<TR><TD>Printer %s ...</TD><TD></TD></TR>", status);
                fputs(SetupFoot, stream);
                fflush(stream);
                return 0;
            }
        }

        if (req->req_type && strstr(req->req_type, "multipart/form-data") != NULL) {
            char *cp, *filename = NULL, *content = NULL;
            int index, separate, length;

            separate = strcspn(req->req_query, "\r\n");

            for (index = separate; index < req->req_length; index++) {
                if (memcmp(req->req_query + index, "DRAM", 4) == 0)
                    device = DRAM_DEVICE;
                if (memcmp(req->req_query + index, "FLASH", 5) == 0)
                    device = FLASH_DEVICE;
                if (memcmp(req->req_query + index, "CARD", 4) == 0)
                    device = CARD_DEVICE;
                /* Succeeded in finding. */
                if (device != NO_SELECT_DEVICE)
                    break;
            }

            for (index = separate; index < req->req_length; index++) {
                if (memcmp(req->req_query + index, "filename", 8) == 0) {
                    filename = strpbrk(req->req_query + index, "'\"") + 1;
                    *strchr(filename, *(filename - 1)) = 0;
                    if (cp = strrchr(filename, '\\'))
                        filename = cp + 1;
                    if (cp = strrchr(filename, '/'))
                        filename = cp + 1;
                    break;
                }
            }

            for (; index < req->req_length; index++) {
                /* Empty line marks the end of the header. */
                if (memcmp(req->req_query + index, "\r\n\r\n", 4) == 0 ||
                    memcmp(req->req_query + index, "\n\r\n\r", 4) == 0) {
                    content = req->req_query + index + 4;
                    for (length = 0; index + length + 4 < req->req_length; length++) {
                        if (memcmp(content + length, req->req_query + index + 2, 2) == 0 &&
                            memcmp(content + length + 2, req->req_query, separate) == 0)
                            break;
                    }
                    break;
                }
                if (memcmp(req->req_query + index, "\r\r", 2) == 0 ||
                    memcmp(req->req_query + index, "\n\n", 2) == 0) {
                    content = req->req_query + index + 2;
                    for (length = 0; index + length + 2 < req->req_length; length++) {
                        if (memcmp(content + length, req->req_query + index + 1, 1) == 0 &&
                            memcmp(content + length + 1, req->req_query, separate) == 0)
                            break;
                    }
                    break;
                }
            }

            if (device != NO_SELECT_DEVICE && filename && content && length) {
                Remove(device, filename);
                handle = Fopen(device, filename, "w");
                length -= Fwrite(content, sizeof(CHAR), length, handle);
                Fclose(handle);
                if (length)
                    Remove(device, filename);
            }
        }
    }

    fputs(SetupHead, stream);
    fprintf(stream, SetupTitle, "30%", "Printer File");
    fprintf(stream, SubmitHead, "/admin/cgi-bin/file.cgi", "encType=multipart/form-data");

    fprintf(stream, ListHead, "DRAM Device :", "format=DRAM");
    OpenList(&list, DRAM_DEVICE);
    while (NextFile(&list, "*.*")) {
        fprintf(stream, ListFile, list.FileName, (list.FileSize + 1023) / 1024);
        fprintf(stream, ListIcon, "del=DRAM:", list.FileName, "/del.png");
        if (strstr(list.FileName, ".BAS") != NULL)
            fprintf(stream, ListIcon, "run=DRAM:", list.FileName, "/run.png");
        fputs("</TD></TR>", stream);
    }
    fputs(ListFoot, stream);

    fprintf(stream, ListHead, "FLASH Device :", "format=FLASH");
    OpenList(&list, FLASH_DEVICE);
    while (NextFile(&list, "*.*")) {
        fprintf(stream, ListFile, list.FileName, (list.FileSize + 1023) / 1024);
        fprintf(stream, ListIcon, "del=FLASH:", list.FileName, "/del.png");
        if (strstr(list.FileName, ".BAS") != NULL)
            fprintf(stream, ListIcon, "run=FLASH:", list.FileName, "/run.png");
        fputs("</TD></TR>", stream);
    }
    fputs(ListFoot, stream);

    fprintf(stream, ListHead, "CARD Device :", "format=CARD");
    OpenList(&list, CARD_DEVICE);
    while (NextFile(&list, "*.*")) {
        fprintf(stream, ListCard, list.FileName, list.FileName, (list.FileSize + 1023) / 1024);
        fprintf(stream, ListIcon, "del=CARD:", list.FileName, "/del.png");
        if (strstr(list.FileName, ".BAS") != NULL)
            fprintf(stream, ListIcon, "run=CARD:", list.FileName, "/run.png");
        fputs("</TD></TR>", stream);
    }
    fputs(ListFoot, stream);

    fprintf(stream, SelectHead, "Upload File :", "device");
    fprintf(stream, SelectText, "", "DRAM");
    fprintf(stream, SelectText, "", "FLASH");
    fprintf(stream, SelectText, "", "CARD");
    fprintf(stream, SelectFoot, "<INPUT type=file size=20 name=file>");

    fputs("<TR>", stream);
    fprintf(stream, FunctionSubmit, "Upload");
    fprintf(stream, FunctionButton, "Refresh", "/cgi-bin/file.cgi");
    fputs("</TR></FORM>", stream);

    fputs(SetupFoot, stream);
    fflush(stream);
    return 0;
}

void NutRegisterHttp(void)
{
    _PrintCfg *cfg = GrabPrintConfig();
    CONFWEB *web = &cfg->confweb;
    char adminlogin[32] = "", rootlogin[32] = "";

    /*
     * Register our device for the file system.
     */
    NutRegisterDevice(&DEV_UROM, 0, 0);
    NutRegisterDevice(&DEV_CARD, 0, 0);

    /*
     * Register our CGI function. This will be called
     * by http://host/cgi-bin/test.cgi?anyparams
     */
    NutRegisterCgiBinPath("cgi-bin/;admin/cgi-bin/");

    NutRegisterCgi("general.cgi", SetupGeneral);
    NutRegisterCgi("adjust.cgi", SetupAdjust);
    NutRegisterCgi("media.cgi", SetupMedia);
    NutRegisterCgi("calibrate.cgi", SetupCalibrate);
    NutRegisterCgi("serial.cgi", SetupSerial);
    NutRegisterCgi("network.cgi", SetupNetwork);
    NutRegisterCgi("mail.cgi", SetupMail);
    NutRegisterCgi("clock.cgi", SetupClock);
    NutRegisterCgi("password.cgi", SetupPassword);

    NutRegisterCgi("function.cgi", PrinterFunction);
    NutRegisterCgi("upgrade.cgi", PrinterUpgrade);
    NutRegisterCgi("status.cgi", PrinterStatus);
    NutRegisterCgi("file.cgi", PrinterFile);

    /*
     * Protect the directory with user and password.
     */
    if (strlen(web->adminname) != 0 && strlen(web->adminpass) != 0) {
        sprintf(adminlogin, "%s:%s", web->adminname, web->adminpass);
        NutRegisterAuth("admin", adminlogin);
        NutRegisterAuth("admin", "admin:admin");
    }
    if (strlen(web->rootname) != 0 && strlen(web->rootpass) != 0) {
        sprintf(rootlogin, "%s:%s", web->rootname, web->rootpass);
        NutRegisterAuth(".", rootlogin);
        if (strlen(adminlogin) != 0)
            NutRegisterAuth(".", adminlogin);
        NutRegisterAuth(".", "root:root");
    }

    /*
     * Register SSI and ASP handler
     */
//    NutRegisterSsi();
    NutRegisterAsp();
    NutRegisterAspCallback(AspCallback);
}

#endif

mail.c                      。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define MAIL_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XVarBank.h"

#include "net\inet.h"
#include "net\socket.h"
#include "net\netdb.h"
#include "pro\dencode.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

#define B64LINE                57

#define MAX_MAIL            4

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

typedef struct {
    // these items can be set default by MailInit()
    u_short port;
    int auth;
    int result;
    const char *charset;
    // follwoing items must be set before calling MailSend()
    const char *smtp;
    const char *user;
    const char *pass;
    const char *sender;
    const char *sendname;
    const char *context;
    const char *subject;
    const char *rcvr[MAX_MAIL];
    const char *cc[MAX_MAIL];
    const char *bcc[MAX_MAIL];
    const char *attach[MAX_MAIL];
    // these items is used internally, do access
    TCPSOCKET *sock;
} MAIL;

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/


// SMTP server reply "NNN-Text\r\n" or "NNN Text\r\n"
// POP server reply "+OK Text\r\n" or "-ERR Text\r\n"
static const char *MailRead(TCPSOCKET * fd, char *buf)
{
    char c;

    for (buf[0] = 0; NutTcpReceive(fd, buf, 4) == 4; buf[0] = 0) {
        for (c = 0; NutTcpReceive(fd, &c, 1) >= 0; c = 0) {
            if (c == '\n')
                break;
        }
        if (c != '\n' || buf[3] != '-')
            break;
    }
    for (c = 0; c < 4; c++) {
        if(buf[c] == 0 || buf[c] == ' ' || buf[c] == '\r' || buf[c] == '\n')
            break;
    }
    buf[c] = 0;
    return buf;
}

static int MailWrite(TCPSOCKET * fd, const char *data, int left)
{
    int out;

    for (out = 0; left > 0; left -= out) {
        if ((out = NutTcpSend(fd, data += out, left)) < 0)
            return out;
    }
    return 0;
}

static int MailWrite64(TCPSOCKET * fd, const char *data, int size)
{
    char buf[B64LINE * 4 / 3 + 1];
    int total;
    int len, len64;

    for (total = 0; total < size; total += len) {
        if (total > 0 && MailWrite(fd, "\r\n", 2) < 0)
            return -1;

        if ((len = size - total) > B64LINE)
            len = B64LINE;

        len64 = NutEncodeBase64(data + total, len, buf);
        if (MailWrite(fd, buf, len64) < 0)
            return -1;
    }
    return 0;
}

static int MailWriteFmt(TCPSOCKET * fd, const char *fmt, ...)
{
    int len;
    char buf[512];

    va_list args;
    va_start(args, fmt);
    len = vsprintf(buf, fmt, args);
    va_end(args);

    return MailWrite(fd, buf, len);
}

static int MailCommand(TCPSOCKET * fd, const char *code, const char *fmt, ...)
{
    int len;
    char buf[512];

    va_list args;
    va_start(args, fmt);
    len = vsprintf(buf, fmt, args);
    va_end(args);

    if (MailWrite(fd, buf, len) < 0 || MailWrite(fd, "\r\n", 2) < 0)
        return -1;
    MailRead(fd, buf);

    if (code && strcmp(code, buf))
        return -1;

    return 0;
}

static TCPSOCKET * MailConnect(const char *ip, u_short port)
{
    u_long addr;
    TCPSOCKET *sock;
    char dummy[6];

    if ((addr = inet_addr(ip)) == (u_long)-1) {
        if ((addr = NutDnsGetHostByName((const u_char *)ip)) == 0)
            return 0;
    }
    if ((sock = NutTcpCreateSocket()) == 0)
        return 0;

    if (NutTcpConnect(sock, addr, port) == -1) {
        NutTcpCloseSocket(sock);
        return 0;
    }

    // don't remove this
    MailRead(sock, dummy);
    return sock;
}

static int MailDisconnect(MAIL *m, int err)
{
    if (m->sock != 0) {
        NutTcpCloseSocket(m->sock);
        m->sock = 0;
    }
    return (m->result = err);
}

static int MailSmtpLogin(MAIL *m)
{
    char buf[64];

    if (MailCommand(m->sock, "250", "ehlo MAPI1.0") < 0)
        return -11;

    if (m->auth == 0)
        return 0;

    if (MailCommand(m->sock, "334", "auth login") < 0)
        return -12;

    if (NutEncodeBase64(m->user, strlen(m->user), buf) == 0)
        return -13;

    if (MailCommand(m->sock, "334", buf) < 0)
        return -14;

    if (NutEncodeBase64(m->pass, strlen(m->pass), buf) == 0)
        return -15;

    if (MailCommand(m->sock, "235", buf) < 0)
        return -16;

    return 0;
}

static int MailSmtpHead(MAIL *m)
{
    int i;

    if (MailCommand(m->sock, "250", "mail from: <%s>", m->sender) < 0)
        return -21;

    for (i = 0; i < MAX_MAIL; i++) {
        if (m->rcvr[i][0]) {
            if (MailCommand(m->sock, 0, "rcpt to: <%s>", m->rcvr[i]) < 0)
                return -22;
        }
    }
    for (i = 0; i < MAX_MAIL; i++) {
        if (m->cc[i][0]) {
            if (MailCommand(m->sock, 0, "rcpt to: <%s>", m->cc[i]) < 0)
                return -23;
        }
    }
    for (i = 0; i < MAX_MAIL; i++) {
        if (m->bcc[i][0]) {
            if (MailCommand(m->sock, 0, "rcpt to: <%s>", m->bcc[i]) < 0)
                return -24;
        }
    }
    if (MailCommand(m->sock, 0, "data") == -1)
        return -25;

    return 0;
}

static int MailHttpHead(MAIL *m)
{
    int i;

    static const char *mime = 
    {
        "MIME-Version:1.0\r\n"
        "Content-Type: multipart/mixed; "
        "boundary=\"--=NextPart_QMAIL.MAPI1.0\"\r\n"
        "X-Status: Alpha\r\n"
        "X-Mailer: Fitivision Mail API V1.0\r\n\r\n"
        "This is a multi-part message in MIME format.\r\n\r\n"
    };

    if (MailWriteFmt(m->sock, "From: %s<%s>\r\n", m->sendname, m->sender) < 0)
        return -31;

    if (MailWrite(m->sock, "To: ", 4) < 0)
        return -32;

    for (i = 0; i < MAX_MAIL; i++) {
        if (m->rcvr[i][0]) {
            if (MailWriteFmt(m->sock, "%s<%s>", i ? ",": "", m->rcvr[i]) < 0)
                return -33;
        }
    }
    if (MailWrite(m->sock, "\r\n", 2) < 0)
        return -34;

    if (MailWrite(m->sock, "Cc: ", 4) < 0)
        return -35;

    for (i = 0; i < MAX_MAIL; i++) {
        if (m->cc[i][0]) {
            if (MailWriteFmt(m->sock, "%s<%s>", i ? ",": "", m->cc[i]) < 0)
                return -36;
        }
    }
    for (i = 0; i < MAX_MAIL; i++) {
        if (m->bcc[i][0]) {
            if (MailWriteFmt(m->sock, ",<%s>", m->bcc[i]) < 0)
                return -37;
        }
    }
    if (MailWrite(m->sock, "\r\n", 2) < 0)
        return -38;

    if ((i = strlen(m->subject)) > 0 && m->subject[i - 1] == '\n')
        i--;

    if (i > 0 && m->subject[i - 1] == '\r')
        i--;

    if (MailWrite(m->sock, "Subject: ", strlen("Subject: ")) < 0)
        return -39;

    // RFC2047
    if (m->charset[0] == 0) {
        if (MailWrite(m->sock, m->subject, i) < 0)
            return -40;
    }
    else {    // charset specified
        if (MailWriteFmt(m->sock, "=?%s?B?", m->charset) < 0)
            return -41;

        if (MailWrite64(m->sock, m->subject, i) < 0)
            return -42;

        if (MailWrite(m->sock, "?=", 2) < 0)
            return -43;
    }
    if (MailWrite(m->sock, "\r\n", 2) < 0)
        return -44;

    if (MailWrite(m->sock, mime, strlen(mime)) < 0)
        return -45;

    return 0;
}

static int MailHttpContext(MAIL *m)
{
    static const char *context =
    {
        "----=NextPart_QMAIL.MAPI1.0\r\n"
        "Content-Type: text/plain"
    };
    static const char *context1 =
    {
        "\r\nContent-Transfer-Encoding: base64\r\n\r\n"
    };

    if (MailWrite(m->sock, context, strlen(context)) < 0)
        return -51;

    if (m->charset[0] && MailWriteFmt(m->sock, "; charset=%s", m->charset) < 0)
        return -52;

    if (MailWrite(m->sock, context1, strlen(context1)) < 0)
        return -53;

    if (MailWrite64(m->sock, m->context, strlen(m->context)) < 0)
        return -54;

    if (MailWrite(m->sock, "\r\n", 2) < 0)
        return -55;

    return 0;
}

static int MailHttpAttach(MAIL *m)
{
    int i;
    int j;
//    int k;
//    FILE *fp;
//    char buf[B64LINE];
//    const char *ext;
    const char *name;

    static const char *mime =
    {
        "\r\n\r\n----=NextPart_QMAIL.MAPI1.0\r\n"
        "Content-Disposition:attachment;filename=\"%s\"\r\n"
        "Content-Type:%s;name=\"%s\"\r\n"
        "Content-Transfer-Encoding: base64\r\n\r\n"
    };

    for (i = 0, j = 0; i < MAX_MAIL; i++) {
        if (strlen(name = m->attach[i]) < 1)
            continue;

    //    if ((fp = fopen(name, "rb")) == 0)
    //        return -61;

    //    ext = getext(name);

    //    if (MailWriteFmt(m->sock, mime, name, getmime(ext), name) < 0) {
    //        fclose(fp);
    //        return -62;
    //    }

    //    for (k = 0; (j = fread(buf, 1, sizeof(buf), fp)) > 0; k++) {
    //        if (MailWrite(m->sock, "\r\n", k ? 2: 0) < 0 || MailWrite64(m->sock, buf, j) < 0) {
    //            fclose(fp);
    //            return -63;
    //        }
    //    }
    //    fclose(fp);
    }
    return 0;
}

static int MailSmtpTail(MAIL *m)
{
    const char *boundary_end = "\r\n\r\n----=NextPart_QMAIL.MAPI1.0--";

    if (MailWrite(m->sock, boundary_end, strlen(boundary_end)) < 0)
        return -71;

    if (MailCommand(m->sock, 0, "\r\n.") < 0)
        return -72;

    if (MailCommand(m->sock, "221", "quit") < 0)
        return -73;

    return 0;
}

static int MailSend(MAIL *m)
{
    if ((m->sock = MailConnect(m->smtp, m->port)) == 0)
        return (m->result = -1);

    if (m->result = MailSmtpLogin(m))
        return MailDisconnect(m, m->result);

    if (m->result = MailSmtpHead(m))
        return MailDisconnect(m, m->result);

    if (m->result = MailHttpHead(m))
        return MailDisconnect(m, m->result);

    if (m->result = MailHttpContext(m))
        return MailDisconnect(m, m->result);

//    if (m->result = MailHttpAttach(m))
//        return MailDisconnect(m, m->result);
    
    if (m->result = MailSmtpTail(m))
        return MailDisconnect(m, m->result);

    return MailDisconnect(m, m->result);
}

static void MailInit(MAIL *m)
{
    int i;

    m->port = 25;
    m->auth = 0;
    m->result = -1;
    m->charset = "";
    m->smtp = "";
    m->user = "";
    m->pass = "";
    m->sender = "";
    m->sendname = "";
    m->context = "";
    m->subject = "Untitled";

    for (i = 0; i < MAX_MAIL; i++) {
        m->rcvr[i] = "";
        m->cc[i] = "";
        m->bcc[i] = "";
        m->attach[i] = "";
    }
}

THREAD(NutMail, arg)
{
    _PrintCfg *cfg = GrabPrintConfig();
    CONFSMTP *smtp = &cfg->confsmtp;
    char subject[64] = "";
    char context[32] = "";
    MAIL mail;

    NutThreadSetPriority(NUT_THREAD_MAIL_PRIORITY);

    MailInit(&mail);

    mail.smtp = smtp->server;
    mail.user = smtp->username;
    mail.pass = smtp->password;
    mail.sender = smtp->sender;
    mail.sendname = confos.hostname;
    mail.context = context;
    mail.subject = subject;
    mail.rcvr[0] = smtp->receiver;

    sprintf(subject, "%s(%s) Notification", confos.hostname, inet_ntoa(confnet.cdn_ip_addr));

    for (;;) {

        if (smtp->notify) {

            u_short JobError = GetJobErrorState();
            char status[32] = "";

            if (JobError & ERROR_TPH_OPEN)
                strcpy(status, "Carriage Open");
            if (JobError & ERROR_TPH_OVERHEAT || JobError & ERROR_MOTOR_OVERHEAT)
                strcpy(status, "Over Heat");
            if (JobError & ERROR_PAPER_JAM)
                strcpy(status, "Paper Jam");
            if (JobError & ERROR_PAPER_EMPTY)
                strcpy(status, "Paper Empty");
            if (JobError & ERROR_RIBBON_JAM || JobError & ERROR_RIBBON_EMPTY)
                strcpy(status, "Ribbon Error");
            if (JobError & ERROR_CUTTER)
                strcpy(status, "Cutter Error");

            if (strlen(status) == 0)
                strcpy(context, "");

            if (strcmp(context, status) != 0) {
                strcpy(context, status);

                mail.auth = smtp->auth;
                MailSend(&mail);
            }
        }

        NutSleep(5000);
    }
}

void NutRegisterMail(void)
{
    NutThreadCreate("mail", NutMail, 0, NUT_THREAD_MAIL_STACK);
}

#endif

mib2.h                                           。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef MIB2_H

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define MIB2_H

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "pro\snmp_mib.h"

#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif    /* __cplusplus */

/******************************************************************************
 *                                                                            *
 *                        G L O B A L   D E F I N E S                         *
 *                                                                            *
 ******************************************************************************/

#ifndef MAX_SYSSTR_LEN
#define MAX_SYSSTR_LEN        64
#endif

/******************************************************************************
 *                                                                            *
 *                 S T R U C T U R E   D E F I N I T I O N S                  *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *    G L O B A L   V A R I A B L E S   -   N O   I N I T I A L I Z E R S     *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *       G L O B A L   V A R I A B L E S   -   I N I T I A L I Z E R S        *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *                   F U N C T I O N   P R O T O T Y P E S                    *
 *                                                                            *
 ******************************************************************************/

extern int MibRegisterSysVars(void);
extern int MibRegisterIfVars(void);
extern int MibRegisterHrVars(void);
extern int MibRegisterPrtVars(void);
extern int MibRegisterHpVars(void);

#ifdef __cplusplus
}                       /* End of extern "C" { */
#endif    /* __cplusplus */

#endif

mib2hp.c                           。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define MIB2HP_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "XEMAC.h"
#include "XAppVer.h"

#include "net\route.h"
#include "net\confnet.h"
#include "pro\dhcp.h"
#include "pro\snmp.h"
#include "pro\snmp_api.h"
#include "mib2.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

enum {
    /* General Device Status */
    MAG_GD_STATUS_BYTES,
    MAG_GD_STATUS_LINE_STATE,
    MAG_GD_STATUS_PAPER_STATE,
    MAG_GD_STATUS_INTERVENTION_STATE,
    MAG_GD_STATUS_PERIPHERAL_ERROR,
    MAG_GD_STATUS_PAPER_OUT,
    MAG_GD_STATUS_PAPER_JAM,
    MAG_GD_STATUS_TONER_LOW,
    MAG_GD_STATUS_PAGE_PUNT,
    MAG_GD_STATUS_MEMORY_OUT,
    MAG_GD_STATUS_IO_ACTIVE,
    MAG_GD_STATUS_BUSY,
    MAG_GD_STATUS_WAIT,
    MAG_GD_STATUS_INITIALIZE,
    MAG_GD_STATUS_DOOR_OPEN,
    MAG_GD_STATUS_PRINTING,
    MAG_GD_STATUS_PAPER_OUTPUT,
    MAG_GD_STATUS_NOV_BUSY,
    MAG_GD_STATUS_LLC_BUSY,
    MAG_GD_STATUS_TCP_BUSY,
    MAG_GD_STATUS_AT_BUSY,
    MAG_GD_STATUS_DISPLAY,
    MAG_GD_STATUS_ID,
    MAG_GD_STATUS_JOB_TIMEOUT,
    MAG_GD_STATUS_PJL_USTATUS,
    MAG_GD_PASSWORDS,
    MAG_GD_STATUS_AT_PRINTER_NAME,
    MAG_GD_STATUS_AT_PRINTER_TYPE,
    /* Unknown */
    MAG_SERVICE_PASSWORD,
    MAG_ON_OFF_LINE,
    MAG_SERIAL_NUMBER,
    MAG_DEVICE_NAME,
    MAG_ASSET_NUMBER,
    MAG_JOB_INFO_NAME1,
    MAG_FIRMWARE_DOWNLOAD_WRITE_TIME,
    MAG_FIRMWARE_DOWNLOAD_CURRENT_STATE,
    MAG_FIRMWARE_DOWNLOAD_NAME,
    MAG_FIRMWARE_DOWNLOAD_VERSION,
    MAG_TOTAL_ENGINE_PAGE_COUNT,
    MAG_LOW_MARKING_AGENT_PROCESSING,
    /* Ieee8023Mac */
    MAG_IEEE8023_MAC_INDEX,
    /* System */
    MAG_NP_SYS_STATUS_MESSAGE,
    MAG_NP_SYS_TOTAL_BYTES_RECVS,
    MAG_NP_SYS_TOTAL_BYTES_SENTS,
    /* Card Connection Statistics */
    MAG_NP_CONNS_ACCEPTS,
    MAG_NP_CONNS_DENYS,
    MAG_NP_CONNS_ABORTS,
    MAG_NP_CONNS_IP,
    MAG_NP_CONNS_NM_CLOSE,
    MAG_NP_CONNS_BYTES_RECVDS,
    MAG_NP_CONNS_BYTES_SENTS,
    /* Card Configuration */
    MAG_NP_CFG_SOURCE,
    MAG_NP_CFG_YIADDR,
    MAG_NP_CFG_ACCESS_STATE,
    MAG_NP_CFG_IDLE_TIMEOUT,
    MAG_NP_CFG_SUBNET_MASK,
    MAG_NP_CFG_DEFAULT_GATEWAY,
    /* TCP */
    MAG_NP_TCP_IN_SEG_IN_ORDERS,
    MAG_NP_TCP_IN_SEG_OUT_OF_ORDERS,
    MAG_NP_TCP_IN_SEG_ZERO_PROBES,
    MAG_NP_TCP_IN_DISCARDS,
    /* Card Control */
    MAG_NP_CTL_RECONFIG_TIME,
    MAG_NP_CTL_RECONFIG,
    MAG_NP_CTL_PROTOCOL_SET,
    MAG_NP_CTL_STATUS_PAGE_LANG,
    /* HP Modular Input/Output (MIO) */
    MAG_NP_NPI_PAE_CLASS,
    MAG_NP_NPI_PAE_IDENTIFICATION,
    MAG_NP_NPI_PAE_REVISION,
    MAG_NP_NPI_PAE_MULTICHAN_FLAG,
    MAG_NP_NPI_CAE_CLASS,
    /* IPX */
    MAG_NP_IPX_GET_UNIT_CFG_RESP,
    MAG_NP_IPX_8022_FRAMETYPE,
    MAG_NP_IPX_SNAP_FRAMETYPE,
    MAG_NP_IPX_ETHERNET_FRAMETYPE,
    MAG_NP_IPX_8023_RAW_FRAMETYPE,
    MAG_NP_IPX_SAP_INFO,
    MAG_NP_IPX_GET_UNIT_CFG_RESP2,
    MAG_NP_IPX_UNIT_NAME,
    MAG_NP_IPX_NDS_TREE_NAME,
    MAG_NP_IPX_NDS_FULLY_QUALIFIED_NAME1,
    /* Direct Mode */
    MAG_NP_DM_CONN_SUPP,
    /* LLC Connection State */
    MAG_LLC_CONNECTION_STATE,
    MAG_NP_LLC_SERVER_ADDRESS,
    /* Parallel Port  */
    MAG_NP_PORT_NUM_PORTS,
    MAG_NP_PORT_TYPE,
    /* DHCP */
    MAG_NP_DHCP_CONFIG,
    MAG_NP_DHCP_SERVER,
    /* Community */
    MAG_SET_COMMUNITY_NAME,
    MAG_GET_COMMUNITY_NAME,
};

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

static u_char *MibVarsHpGet(CONST SNMPVAR *, OID *, size_t *, int, size_t *, WMETHOD **);

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static OID base_oid[] = { SNMP_OID_ENTERPRISES, 11, 2 };
static size_t base_oidlen = sizeof(base_oid) / sizeof(OID);

static SNMPVAR mib_variables[] = {
    /* General Device Status */
    {MAG_GD_STATUS_BYTES,                  ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {3, 9, 1, 1, 1}},
    {MAG_GD_STATUS_LINE_STATE,             ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 1}},
    {MAG_GD_STATUS_PAPER_STATE,            ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 2}},
    {MAG_GD_STATUS_INTERVENTION_STATE,     ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 3}},
    {MAG_GD_STATUS_PERIPHERAL_ERROR,       ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 6}},
    {MAG_GD_STATUS_PAPER_OUT,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 8}},
    {MAG_GD_STATUS_PAPER_JAM,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 9}},
    {MAG_GD_STATUS_TONER_LOW,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 10}},
    {MAG_GD_STATUS_PAGE_PUNT,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 11}},
    {MAG_GD_STATUS_MEMORY_OUT,             ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 12}},
    {MAG_GD_STATUS_IO_ACTIVE,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 13}},
    {MAG_GD_STATUS_BUSY,                   ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 14}},
    {MAG_GD_STATUS_WAIT,                   ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 15}},
    {MAG_GD_STATUS_INITIALIZE,             ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 16}},
    {MAG_GD_STATUS_DOOR_OPEN,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 17}},
    {MAG_GD_STATUS_PRINTING,               ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 18}},
    {MAG_GD_STATUS_PAPER_OUTPUT,           ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 19}},
    {MAG_GD_STATUS_NOV_BUSY,               ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 21}},
    {MAG_GD_STATUS_LLC_BUSY,               ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 22}},
    {MAG_GD_STATUS_TCP_BUSY,               ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 23}},
    {MAG_GD_STATUS_AT_BUSY,                ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {3, 9, 1, 1, 2, 24}},
    {MAG_GD_STATUS_DISPLAY,                ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 5, {3, 9, 1, 1, 3}},
    {MAG_GD_STATUS_ID,                     ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 5, {3, 9, 1, 1, 7}},
    {MAG_GD_STATUS_JOB_TIMEOUT,            ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 5, {3, 9, 1, 1, 10}},
    {MAG_GD_STATUS_PJL_USTATUS,            ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 5, {3, 9, 1, 1, 11}},
    {MAG_GD_PASSWORDS,                     ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 5, {3, 9, 1, 1, 13}},
    {MAG_GD_STATUS_AT_PRINTER_NAME,        ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 5, {3, 9, 1, 1, 18}},
    {MAG_GD_STATUS_AT_PRINTER_TYPE,        ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 5, {3, 9, 1, 1, 19}},
    /* Unknown */
    {MAG_SERVICE_PASSWORD,                 ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 1, 9}},
    {MAG_ON_OFF_LINE,                      ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 2, 5}},
    {MAG_SERIAL_NUMBER,                    ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 3, 3}},
    {MAG_DEVICE_NAME,                      ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 3, 10}},
    {MAG_ASSET_NUMBER,                     ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 3, 12}},
    {MAG_JOB_INFO_NAME1,                   ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 10, {3, 9, 4, 2, 1, 1, 6, 5, 1, 2}},
    {MAG_FIRMWARE_DOWNLOAD_WRITE_TIME,     ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 18, 2}},
    {MAG_FIRMWARE_DOWNLOAD_CURRENT_STATE,  ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 18, 4}},
    {MAG_FIRMWARE_DOWNLOAD_NAME,           ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 18, 6}},
    {MAG_FIRMWARE_DOWNLOAD_VERSION,        ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 8,  {3, 9, 4, 2, 1, 1, 18, 7}},
    {MAG_TOTAL_ENGINE_PAGE_COUNT,          ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 9,  {3, 9, 4, 2, 1, 4, 1, 2, 5}},
    {MAG_LOW_MARKING_AGENT_PROCESSING,     ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 10, {3, 9, 4, 2, 1, 4, 1, 5, 1, 3}},
    /* Ieee8023Mac */
    {MAG_IEEE8023_MAC_INDEX,               ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 6, {4, 1, 1, 1, 1, 1}},
    /* System */
    {MAG_NP_SYS_STATUS_MESSAGE,            ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 1, 2}},
    {MAG_NP_SYS_TOTAL_BYTES_RECVS,         ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 1, 7}},
    {MAG_NP_SYS_TOTAL_BYTES_SENTS,         ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 1, 8}},
    /* Card Connection Statistics */
    {MAG_NP_CONNS_ACCEPTS,                 ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 1}},
    {MAG_NP_CONNS_DENYS,                   ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 3}},
    {MAG_NP_CONNS_ABORTS,                  ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 5}},
    {MAG_NP_CONNS_IP,                      ASN_IPADDRESS, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 11}},
    {MAG_NP_CONNS_NM_CLOSE,                ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 15}},
    {MAG_NP_CONNS_BYTES_RECVDS,            ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 16}},
    {MAG_NP_CONNS_BYTES_SENTS,             ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 4, 17}},
    /* Card Configuration */
    {MAG_NP_CFG_SOURCE,                    ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 5, 1}},
    {MAG_NP_CFG_YIADDR,                    ASN_IPADDRESS, ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 5, 2}},
    {MAG_NP_CFG_ACCESS_STATE,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 5, 7}},
    {MAG_NP_CFG_IDLE_TIMEOUT,              ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 5, 10}},
    {MAG_NP_CFG_SUBNET_MASK,               ASN_IPADDRESS, ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 5, 12}},
    {MAG_NP_CFG_DEFAULT_GATEWAY,           ASN_IPADDRESS, ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 5, 13}},
    /* TCP */
    {MAG_NP_TCP_IN_SEG_IN_ORDERS,          ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 6, 1}},
    {MAG_NP_TCP_IN_SEG_OUT_OF_ORDERS,      ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 6, 2}},
    {MAG_NP_TCP_IN_SEG_ZERO_PROBES,        ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 6, 3}},
    {MAG_NP_TCP_IN_DISCARDS,               ASN_COUNTER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 6, 4}},
    /* Card Control */
    {MAG_NP_CTL_RECONFIG_TIME,             ASN_TIMETICKS, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 7, 3}},
    {MAG_NP_CTL_RECONFIG,                  ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 7, 8}},
    {MAG_NP_CTL_PROTOCOL_SET,              ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 7, 9}},
    {MAG_NP_CTL_STATUS_PAGE_LANG,          ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 7, 10}},
    /* HP Modular Input/Output (MIO) */
    {MAG_NP_NPI_PAE_CLASS,                 ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {4, 3, 8, 3, 2}},
    {MAG_NP_NPI_PAE_IDENTIFICATION,        ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {4, 3, 8, 3, 3}},
    {MAG_NP_NPI_PAE_REVISION,              ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {4, 3, 8, 3, 4}},
    {MAG_NP_NPI_PAE_MULTICHAN_FLAG,        ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {4, 3, 8, 3, 8}},
    {MAG_NP_NPI_CAE_CLASS,                 ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 5, {4, 3, 8, 4, 2}},
    /* IPX */
    {MAG_NP_IPX_GET_UNIT_CFG_RESP,         ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 1}},
    {MAG_NP_IPX_8022_FRAMETYPE,            ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 2}},
    {MAG_NP_IPX_SNAP_FRAMETYPE,            ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 3}},
    {MAG_NP_IPX_ETHERNET_FRAMETYPE,        ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 4}},
    {MAG_NP_IPX_8023_RAW_FRAMETYPE,        ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 5}},
    {MAG_NP_IPX_SAP_INFO,                  ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 6}},
    {MAG_NP_IPX_GET_UNIT_CFG_RESP2,        ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 10, 7}},
    {MAG_NP_IPX_UNIT_NAME,                 ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 10, 8}},
    {MAG_NP_IPX_NDS_TREE_NAME,             ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 10, 9}},
    {MAG_NP_IPX_NDS_FULLY_QUALIFIED_NAME1, ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 5, {4, 3, 10, 10, 1}},
    /* Direct Mode */
    {MAG_NP_DM_CONN_SUPP,                  ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 11, 1}},
    /* LLC Connection State */
    {MAG_LLC_CONNECTION_STATE,             ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 12, 7}},
    {MAG_NP_LLC_SERVER_ADDRESS,            ASN_OCTET_STR, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 12, 8}},
    /* Parallel Port */
    {MAG_NP_PORT_NUM_PORTS,                ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 13, 1}},
    {MAG_NP_PORT_TYPE,                     ASN_INTEGER,   ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 13, 2}},
    /* DHCP */
    {MAG_NP_DHCP_CONFIG,                   ASN_INTEGER,   ACL_RWRITE, MibVarsHpGet, 4, {4, 3, 16, 1}},
    {MAG_NP_DHCP_SERVER,                   ASN_IPADDRESS, ACL_RONLY,  MibVarsHpGet, 4, {4, 3, 16, 2}},
    /* Community */
    {MAG_SET_COMMUNITY_NAME,               ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 3, {15, 1, 1}},
    {MAG_GET_COMMUNITY_NAME,               ASN_OCTET_STR, ACL_RWRITE, MibVarsHpGet, 3, {15, 1, 2}},
};

/* General Device Status */
static long gdStatusBytes = 32;
static long gdStatusLineState = 0;
static long gdStatusPaperState = 0;
static long gdStatusInterventionState = 0;
static long gdStatusPeripheralError = 0;
static long gdStatusPaperOut = 0;
static long gdStatusPaperJam = 0;
static long gdStatusTonerLow = 0;
static long gdStatusPagePunt = 0;
static long gdStatusMemoryOut = 0;
static long gdStatusIoActive = 0;
static long gdStatusBusy = 0;
static long gdStatusWait = 0;
static long gdStatusInitialize = 0;
static long gdStatusDoorOpen = 0;
static long gdStatusPrinting = 0;
static long gdStatusPaperOutput = 0;
static long gdStatusNovBusy = 0;
static long gdStatusLlcBusy = 0;
static long gdStatusTcpBusy = 0;
static long gdStatusAtBusy = 0;
static char *gdStatusDisplay = "Online";
static char gdStatusId[128];
static long gdStatusJobTimeout = 30;
static long gdStatusPjlUstatus = 1;
static char gdPasswords[256] = "";
static char gdStatusAtPrinterName[256] = "gdStatusAtPrinterName";
static char *gdStatusAtPrinterType = "gdStatusAtPrinterType";
/* Unknown */
static long service_password = 0;
static long on_off_line = 1;    /* eOnline */
static char *serial_number = "0000000000000000";
static char device_name[64] = "\x01\x15""Barcode Printer";
static char *asset_number = "0000000000000000";
static char *job_info_name1 = "";
static long firmware_download_write_time = 180;
static long firmware_download_current_state = 1;    /* eIdle */
static char *firmware_download_name = "Barcode Printer";
static char *firmware_download_version = "V1.00";
static long total_engine_page_count = 0;
static long low_marking_agent_processing = 0;
/* Ieee8023Mac */
static long ieee8023MacIndex = 1;
/* System */
static char *npSysStatusMessage = "ready to print";
static long npSysTotalBytesRecvs = 7;
static long npSysTotalBytesSents = 8;
/* Card Connection Statistics */
static long npConnsAccepts = 1;
static long npConnsDenys = 3;
static long npConnsAborts = 5;
static u_long npConnsIP = 0;    /* ipaddress */
static long npConnsNmClose = 15;
static long npConnsBytesRecvds = 16;
static long npConnsBytesSents = 17;
/* Card Configuration */
static long npCfgSource = 3;    /* manual-three */
static u_long npCfgYiaddr;    /* ipaddress */
static long npCfgAccessState = 1;    /* allowed */
static long npCfgIdleTimeout = 180;
static u_long npCfgSubnetMask;    /* ipaddress */
static u_long npCfgDefaultGateway ;    /* ipaddress */
/* TCP */
static long npTcpInSegInOrders = 1;
static long npTcpInSegOutOfOrders = 2;
static long npTcpInSegZeroProbes = 3;
static long npTcpInDiscards = 0;
/* Card Control */
static long npCtlReconfigTime = 0;    /* timeticks */
static long npCtlReconfig = 0;
static long npCtlProtocolSet = 1140850697;    /* 32-bit protocol */
static long npCtlStatusPageLang = 2;    /* ascii */
/* HP Modular Input/Output (MIO) */
static long npNpiPaeClass = 1;    /* printer */
static long npNpiPaeIdentification = 5;    /* laserjet-4SI */
static long npNpiPaeRevision = 1281;
static long npNpiPaeMultichanFlag = 1;
static long npNpiCaeClass = 3;
/* IPX */
static u_char npIpxGetUnitCfgResp[78];
static long npIpx8022frametype = 0;
static long npIpxSNAPframetype = 0;
static long npIpxEthernetframetype = 0;
static long npIpx8023Rawframetype = 0;
static u_char npIpxSapInfo[50];
static u_char npIpxGetUnitCfgResp2[78];
static char npIpxUnitName[30] = "";
static char npIpxNdsTreeName[33] = "";
static char npIpxNdsFullyQualifiedName1[261] = "";
/* Direct Mode */
static long npDmConnSupp = 1;
/* LLC Connection State */
static long llcConnectionstate = 7;
static char *npLlcServerAddress = "npLlcServerAddress";
/* Parallel Port  */
static long npPortNumPorts = 1;
static long npPortType = 5;    /* centronics */
/* DHCP */
static long npDHCPconfig = 1;    /* dhcpDisable */
static u_long npDHCPserver = 0;    /* ipaddress */
/* Community */
static char setCommunityName[256] = "NOT_SET";
static char getCommunityName[256] = "NOT_SET";

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/


/*!
 * \brief Register HP-MIB variables.
 *
 * \note Preliminary code with hard coded values.
 */
int MibRegisterHpVars(void)
{
    sprintf(gdStatusId, "MANUFACTURER:TSC;COMMAND SET:EZ;MODEL:%s;CLASS:PRINTER;DESCRIPTION:Barcode Printer;", ModelName);

    npCfgYiaddr = confnet.cdn_ip_addr;
    npCfgSubnetMask = confnet.cdn_ip_mask;
    npCfgDefaultGateway = confnet.cdn_gateway;

    return SnmpMibRegister(base_oid, base_oidlen, mib_variables, sizeof(mib_variables) / sizeof(SNMPVAR));
}

static int MibVarsHpSet(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, OID * name, size_t name_len)
{
    size_t len = SNMP_MAX_LEN;
    size_t size = sizeof(u_long);
    u_long value;

    if (action != SNMP_ACT_COMMIT) {
        return 0;
    }

    if (var_val_type != ASN_IPADDRESS)
        return SNMP_ERR_WRONGTYPE;
    if (var_val_len > sizeof(u_long))
        return SNMP_ERR_WRONGLENGTH;

    AsnOctetStringParse(var_val, &len, &var_val_type, (u_char *) &value, &size);

    NutDhcpRelease(DEV_ETHER_NAME, 6000);

    switch (name[11]) {
    case 2:
        confnet.cdn_cip_addr = npCfgYiaddr = value;
        break;
    case 12:
        confnet.cdn_ip_mask  = npCfgSubnetMask = value;
        break;
    case 13:
        confnet.cdn_gateway  = npCfgDefaultGateway = value;
        break;
    }

    if (confnet.cdn_cip_addr & confnet.cdn_ip_mask) {
        confnet.cdn_ip_addr = confnet.cdn_cip_addr;
        NutNetIfConfig2(DEV_ETHER_NAME, confnet.cdn_mac, confnet.cdn_ip_addr, confnet.cdn_ip_mask, confnet.cdn_gateway);
    }

    return 0;
}

static u_char *MibVarsHpGet(CONST SNMPVAR * vp, OID * name, size_t * namelen, int exact, size_t * varlen, WMETHOD ** wmethod)
{
    int rc;
    OID *fullname;
    size_t fullnamelen = base_oidlen + vp->var_namelen + 1;

    if ((fullname = NutHeapAlloc(fullnamelen * sizeof(OID))) == NULL) {
        return NULL;
    }
    memcpy(fullname, base_oid, base_oidlen * sizeof(OID));
    memcpy(fullname + base_oidlen, vp->var_name, vp->var_namelen * sizeof(OID));
    *(fullname + fullnamelen - 1) = 0;

    rc = SnmpOidCmp(name, *namelen, fullname, fullnamelen);
    if ((exact && rc) || (!exact && rc >= 0)) {
        NutHeapFree(fullname);
        return NULL;
    }
    memcpy(name, fullname, fullnamelen * sizeof(OID));
    *namelen = fullnamelen;
    NutHeapFree(fullname);

    *wmethod = NULL;
    *varlen = sizeof(long);
    switch (vp->var_magic) {
    /* General Device Status */
    case MAG_GD_STATUS_BYTES:
        return (u_char *) & gdStatusBytes;
    case MAG_GD_STATUS_LINE_STATE:
        return (u_char *) & gdStatusLineState;
    case MAG_GD_STATUS_PAPER_STATE:
        return (u_char *) & gdStatusPaperState;
    case MAG_GD_STATUS_INTERVENTION_STATE:
        return (u_char *) & gdStatusInterventionState;
    case MAG_GD_STATUS_PERIPHERAL_ERROR:
        return (u_char *) & gdStatusPeripheralError;
    case MAG_GD_STATUS_PAPER_OUT:
        return (u_char *) & gdStatusPaperOut;
    case MAG_GD_STATUS_PAPER_JAM:
        return (u_char *) & gdStatusPaperJam;
    case MAG_GD_STATUS_TONER_LOW:
        return (u_char *) & gdStatusTonerLow;
    case MAG_GD_STATUS_PAGE_PUNT:
        return (u_char *) & gdStatusPagePunt;
    case MAG_GD_STATUS_MEMORY_OUT:
        return (u_char *) & gdStatusMemoryOut;
    case MAG_GD_STATUS_IO_ACTIVE:
        return (u_char *) & gdStatusIoActive;
    case MAG_GD_STATUS_BUSY:
        return (u_char *) & gdStatusBusy;
    case MAG_GD_STATUS_WAIT:
        return (u_char *) & gdStatusWait;
    case MAG_GD_STATUS_INITIALIZE:
        return (u_char *) & gdStatusInitialize;
    case MAG_GD_STATUS_DOOR_OPEN:
        return (u_char *) & gdStatusDoorOpen;
    case MAG_GD_STATUS_PRINTING:
        return (u_char *) & gdStatusPrinting;
    case MAG_GD_STATUS_PAPER_OUTPUT:
        return (u_char *) & gdStatusPaperOutput;
    case MAG_GD_STATUS_NOV_BUSY:
        return (u_char *) & gdStatusNovBusy;
    case MAG_GD_STATUS_LLC_BUSY:
        return (u_char *) & gdStatusLlcBusy;
    case MAG_GD_STATUS_TCP_BUSY:
        return (u_char *) & gdStatusTcpBusy;
    case MAG_GD_STATUS_AT_BUSY:
        return (u_char *) & gdStatusAtBusy;
    case MAG_GD_STATUS_DISPLAY:
        *varlen = strlen(gdStatusDisplay);
        return (u_char *) gdStatusDisplay;
    case MAG_GD_STATUS_ID:
        *varlen = strlen(gdStatusId);
        return (u_char *) gdStatusId;
    case MAG_GD_STATUS_JOB_TIMEOUT:
        return (u_char *) & gdStatusJobTimeout;
    case MAG_GD_STATUS_PJL_USTATUS:
        return (u_char *) & gdStatusPjlUstatus;
    case MAG_GD_PASSWORDS:
        *varlen = strlen(gdPasswords);
        return (u_char *) gdPasswords;
    case MAG_GD_STATUS_AT_PRINTER_NAME:
        *varlen = strlen(gdStatusAtPrinterName);
        return (u_char *) gdStatusAtPrinterName;
    case MAG_GD_STATUS_AT_PRINTER_TYPE:
        *varlen = strlen(gdStatusAtPrinterType);
        return (u_char *) gdStatusAtPrinterType;
    /* Unknown */
    case MAG_SERVICE_PASSWORD:
        return (u_char *) & service_password;
    case MAG_ON_OFF_LINE:
        return (u_char *) & on_off_line;
    case MAG_SERIAL_NUMBER:
        *varlen = strlen(serial_number);
        return (u_char *) serial_number;
    case MAG_DEVICE_NAME:
        *varlen = strlen(device_name);
        return (u_char *) device_name;
    case MAG_ASSET_NUMBER:
        *varlen = strlen(asset_number);
        return (u_char *) asset_number;
    case MAG_JOB_INFO_NAME1:
        *varlen = strlen(job_info_name1);
        return (u_char *) job_info_name1;
    case MAG_FIRMWARE_DOWNLOAD_WRITE_TIME:
        return (u_char *) & firmware_download_write_time;
    case MAG_FIRMWARE_DOWNLOAD_CURRENT_STATE:
        return (u_char *) & firmware_download_current_state;
    case MAG_FIRMWARE_DOWNLOAD_NAME:
        *varlen = strlen(firmware_download_name);
        return (u_char *) firmware_download_name;
    case MAG_FIRMWARE_DOWNLOAD_VERSION:
        *varlen = strlen(firmware_download_version);
        return (u_char *) firmware_download_version;
    case MAG_TOTAL_ENGINE_PAGE_COUNT:
        return (u_char *) & total_engine_page_count;
    case MAG_LOW_MARKING_AGENT_PROCESSING:
        return (u_char *) & low_marking_agent_processing;
    /* Ieee8023Mac */
    case MAG_IEEE8023_MAC_INDEX:
        return (u_char *) & ieee8023MacIndex;
    /* System */
    case MAG_NP_SYS_STATUS_MESSAGE:
        *varlen = strlen(npSysStatusMessage);
        return (u_char *) npSysStatusMessage;
    case MAG_NP_SYS_TOTAL_BYTES_RECVS:
        return (u_char *) & npSysTotalBytesRecvs;
    case MAG_NP_SYS_TOTAL_BYTES_SENTS:
        return (u_char *) & npSysTotalBytesSents;
    /* Card Connection Statistics */
    case MAG_NP_CONNS_ACCEPTS:
        return (u_char *) & npConnsAccepts;
    case MAG_NP_CONNS_DENYS:
        return (u_char *) & npConnsDenys;
    case MAG_NP_CONNS_ABORTS:
        return (u_char *) & npConnsAborts;
    case MAG_NP_CONNS_IP:
        return (u_char *) & npConnsIP;
    case MAG_NP_CONNS_NM_CLOSE:
        return (u_char *) & npConnsNmClose;
    case MAG_NP_CONNS_BYTES_RECVDS:
        return (u_char *) & npConnsBytesRecvds;
    case MAG_NP_CONNS_BYTES_SENTS:
        return (u_char *) & npConnsBytesSents;
    /* Card Configuration */
    case MAG_NP_CFG_SOURCE:
        return (u_char *) & npCfgSource;
    case MAG_NP_CFG_YIADDR:
        *wmethod = MibVarsHpSet;
        return (u_char *) & npCfgYiaddr;
    case MAG_NP_CFG_ACCESS_STATE:
        return (u_char *) & npCfgAccessState;
    case MAG_NP_CFG_IDLE_TIMEOUT:
        return (u_char *) & npCfgIdleTimeout;
    case MAG_NP_CFG_SUBNET_MASK:
        *wmethod = MibVarsHpSet;
        return (u_char *) & npCfgSubnetMask;
    case MAG_NP_CFG_DEFAULT_GATEWAY:
        *wmethod = MibVarsHpSet;
        return (u_char *) & npCfgDefaultGateway;
    /* TCP */
    case MAG_NP_TCP_IN_SEG_IN_ORDERS:
        return (u_char *) & npTcpInSegInOrders;
    case MAG_NP_TCP_IN_SEG_OUT_OF_ORDERS:
        return (u_char *) & npTcpInSegOutOfOrders;
    case MAG_NP_TCP_IN_SEG_ZERO_PROBES:
        return (u_char *) & npTcpInSegZeroProbes;
    case MAG_NP_TCP_IN_DISCARDS:
        return (u_char *) & npTcpInDiscards;
    /* Card Control */
    case MAG_NP_CTL_RECONFIG_TIME:
        return (u_char *) & npCtlReconfigTime;
    case MAG_NP_CTL_RECONFIG:
        return (u_char *) & npCtlReconfig;
    case MAG_NP_CTL_PROTOCOL_SET:
        return (u_char *) & npCtlProtocolSet;
    case MAG_NP_CTL_STATUS_PAGE_LANG:
        return (u_char *) & npCtlStatusPageLang;
    /* HP Modular Input/Output (MIO) */
    case MAG_NP_NPI_PAE_CLASS:
        return (u_char *) & npNpiPaeClass;
    case MAG_NP_NPI_PAE_IDENTIFICATION:
        return (u_char *) & npNpiPaeIdentification;
    case MAG_NP_NPI_PAE_REVISION:
        return (u_char *) & npNpiPaeRevision;
    case MAG_NP_NPI_PAE_MULTICHAN_FLAG:
        return (u_char *) & npNpiPaeMultichanFlag;
    case MAG_NP_NPI_CAE_CLASS:
        return (u_char *) & npNpiCaeClass;
    /* IPX */
    case MAG_NP_IPX_GET_UNIT_CFG_RESP:
        *varlen = sizeof(npIpxGetUnitCfgResp);
        return (u_char *) npIpxGetUnitCfgResp;
    case MAG_NP_IPX_8022_FRAMETYPE:
        return (u_char *) & npIpx8022frametype;
    case MAG_NP_IPX_SNAP_FRAMETYPE:
        return (u_char *) & npIpxSNAPframetype;
    case MAG_NP_IPX_ETHERNET_FRAMETYPE:
        return (u_char *) & npIpxEthernetframetype;
    case MAG_NP_IPX_8023_RAW_FRAMETYPE:
        return (u_char *) & npIpx8023Rawframetype;
    case MAG_NP_IPX_SAP_INFO:
        *varlen = sizeof(npIpxSapInfo);
        return (u_char *) npIpxSapInfo;
    case MAG_NP_IPX_GET_UNIT_CFG_RESP2:
        *varlen = sizeof(npIpxGetUnitCfgResp2);
        return (u_char *) npIpxGetUnitCfgResp2;
    case MAG_NP_IPX_UNIT_NAME:
        *varlen = strlen(npIpxUnitName);
        return (u_char *) npIpxUnitName;
    case MAG_NP_IPX_NDS_TREE_NAME:
        *varlen = strlen(npIpxNdsTreeName);
        return (u_char *) npIpxNdsTreeName;
    case MAG_NP_IPX_NDS_FULLY_QUALIFIED_NAME1:
        *varlen = strlen(npIpxNdsFullyQualifiedName1);
        return (u_char *) npIpxNdsFullyQualifiedName1;
    /* Direct Mode */
    case MAG_NP_DM_CONN_SUPP:
        return (u_char *) & npDmConnSupp;
    /* LLC Connection State */
    case MAG_LLC_CONNECTION_STATE:
        return (u_char *) & llcConnectionstate;
    case MAG_NP_LLC_SERVER_ADDRESS:
        *varlen = strlen(npLlcServerAddress);
        return (u_char *) npLlcServerAddress;
    /* Parallel Port  */
    case MAG_NP_PORT_NUM_PORTS:
        return (u_char *) & npPortNumPorts;
    case MAG_NP_PORT_TYPE:
        return (u_char *) & npPortType;
    /* DHCP */
    case MAG_NP_DHCP_CONFIG:
        return (u_char *) & npDHCPconfig;
    case MAG_NP_DHCP_SERVER:
        return (u_char *) & npDHCPserver;
    /* Community */
    case MAG_SET_COMMUNITY_NAME:
        *varlen = strlen(setCommunityName);
        return (u_char *) setCommunityName;
    case MAG_GET_COMMUNITY_NAME:
        *varlen = strlen(getCommunityName);
        return (u_char *) getCommunityName;
    }
    return NULL;
}

#endif

mib2hr.c                 。。。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define MIB2HR_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "XAppVer.h"
#include "XPrtEng.h"

#include "net\confnet.h"
#include "pro\snmp.h"
#include "pro\snmp_api.h"
#include "mib2.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

#define MAG_HR_DEVICE_TABLE_INDEX                21
#define MAG_HR_DEVICE_TABLE_DESCR                23
#define MAG_HR_DEVICE_TABLE_STATUS                25

#define MAG_HR_DEVICE_PRINTER_STATUS            51
#define MAG_HR_DEVICE_PRINTER_ERRORSTATE        52

#define DEVICE_STATUS_UNKNOWN                    1
#define DEVICE_STATUS_RUNNING                    2
#define DEVICE_STATUS_WARNING                    3
#define DEVICE_STATUS_TESTING                    4
#define DEVICE_STATUS_DOWN                        5

#define PRINTER_STATUS_OTHER                    1
#define PRINTER_STATUS_UNKNOWN                    2
#define PRINTER_STATUS_IDLE                        3
#define PRINTER_STATUS_PRINTING                    4
#define PRINTER_STATUS_WARMUP                    5

#define PRINTER_ERROR_LOW_PAPER                    (1 << 7)
#define PRINTER_ERROR_NO_PAPER                    (1 << 6)
#define PRINTER_ERROR_LOW_TONER                    (1 << 5)
#define PRINTER_ERROR_NO_TONER                    (1 << 4)
#define PRINTER_ERROR_DOOR_OPEN                    (1 << 3)
#define PRINTER_ERROR_JAMMED                    (1 << 2)
#define PRINTER_ERROR_OFFLINE                    (1 << 1)
#define PRINTER_ERROR_SERVICE_REQUESTED            (1 << 0)

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

static u_char *MibVarsHrGet(CONST SNMPVAR *, OID *, size_t *, int, size_t *, WMETHOD **);

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static OID base_oid[] = { SNMP_OID_MIB2, 25 };
static size_t base_oidlen = sizeof(base_oid) / sizeof(OID);

static SNMPVAR mib_variables[] = {
    {MAG_HR_DEVICE_TABLE_INDEX, ASN_INTEGER, ACL_RONLY, MibVarsHrGet, 4, {3, 2, 1, 1}},
    {MAG_HR_DEVICE_TABLE_DESCR, ASN_OCTET_STR, ACL_RONLY, MibVarsHrGet, 4, {3, 2, 1, 3}},
    {MAG_HR_DEVICE_TABLE_STATUS, ASN_INTEGER, ACL_RONLY, MibVarsHrGet, 4, {3, 2, 1, 5}},
    {MAG_HR_DEVICE_PRINTER_STATUS, ASN_INTEGER, ACL_RONLY, MibVarsHrGet, 4, {3, 5, 1, 1}},
    {MAG_HR_DEVICE_PRINTER_ERRORSTATE, ASN_OCTET_STR, ACL_RONLY, MibVarsHrGet, 4, {3, 5, 1, 2}},
};

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static long dev_index;
static char dev_descr[64];
static long dev_status;
static long prn_status;
static u_char prn_errstate;

static long GetDeviceStatus(void)
{
    u_short JobError = GetJobErrorState();
    int JobLock = CheckJobLock();

    if (JobLock || JobError)
        return DEVICE_STATUS_DOWN;

    return DEVICE_STATUS_RUNNING;
}

static long GetPrinterStatus(void)
{
    _eMotorStatus MotorStatus = GetMotorStatus();
    u_short JobError = GetJobErrorState();
    int JobLock = CheckJobLock();

    if (JobLock || JobError)
        return PRINTER_STATUS_OTHER;

    if (MotorStatus == STATUS_MOTOR_FORWARD || MotorStatus == STATUS_MOTOR_BACKWARD)
        return PRINTER_STATUS_PRINTING;

    return PRINTER_STATUS_IDLE;
}

static u_char GetPrinterErrorState(void)
{
    u_short JobError = GetJobErrorState();
    int JobLock = CheckJobLock();
    u_char errstate = 0x00;

    if (JobLock)
        errstate |= PRINTER_ERROR_OFFLINE;
    if (JobError & ERROR_TPH_OPEN)
        errstate |= PRINTER_ERROR_OFFLINE | PRINTER_ERROR_DOOR_OPEN;
    if (JobError & ERROR_PAPER_JAM)
        errstate |= PRINTER_ERROR_OFFLINE | PRINTER_ERROR_JAMMED;
    if (JobError & ERROR_PAPER_EMPTY)
        errstate |= PRINTER_ERROR_OFFLINE | PRINTER_ERROR_NO_PAPER;
    if (JobError & ERROR_RIBBON_JAM || JobError & ERROR_RIBBON_EMPTY)
        errstate |= PRINTER_ERROR_OFFLINE | PRINTER_ERROR_NO_TONER;;
    if (JobError & ERROR_CUTTER)
        errstate |= PRINTER_ERROR_OFFLINE | PRINTER_ERROR_JAMMED;
    if (JobError & ERROR_TPH_OVERHEAT || JobError & ERROR_MOTOR_OVERHEAT)
        errstate |= PRINTER_ERROR_OFFLINE;

    return errstate;
}

/*!
 * \brief Register MIB II host variables.
 *
 * \note Preliminary code with hard coded values.
 */
int MibRegisterHrVars(void)
{
    dev_index = 1;
    sprintf(dev_descr, "%s V%s %s", ModelName, VerName, ExtModelName);
    dev_status = DEVICE_STATUS_UNKNOWN;

    prn_status = PRINTER_STATUS_UNKNOWN;
    prn_errstate = 0x00;

    return SnmpMibRegister(base_oid, base_oidlen, mib_variables, sizeof(mib_variables) / sizeof(SNMPVAR));
}

static int MibVarsHrSet(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, OID * name, size_t name_len)
{
    if (action != SNMP_ACT_COMMIT) {
        return 0;
    }
    return 0;
}

static u_char *MibVarsHrGet(CONST SNMPVAR * vp, OID * name, size_t * namelen, int exact, size_t * varlen, WMETHOD ** wmethod)
{
    int rc;
    int devc = 0;
    OID *fullname;
    size_t fullnamelen = base_oidlen + vp->var_namelen + 1;

    if ((fullname = NutHeapAlloc(fullnamelen * sizeof(OID))) == NULL) {
        return NULL;
    }
    memcpy(fullname, base_oid, base_oidlen * sizeof(OID));
    memcpy(fullname + base_oidlen, vp->var_name, vp->var_namelen * sizeof(OID));

    /* Determine the device number. */
    *(fullname + fullnamelen - 1) = devc + 1;
    rc = SnmpOidCmp(name, *namelen, fullname, fullnamelen);
    if ((exact && rc) || (!exact && rc >= 0)) {
        NutHeapFree(fullname);
        return NULL;
    }
    memcpy(name, fullname, fullnamelen * sizeof(OID));
    *namelen = fullnamelen;
    NutHeapFree(fullname);

    *wmethod = NULL;
    *varlen = sizeof(long);
    switch (vp->var_magic) {
    case MAG_HR_DEVICE_TABLE_INDEX:
        return (u_char *) & dev_index;
    case MAG_HR_DEVICE_TABLE_DESCR:
        *varlen = strlen(dev_descr);
        return (u_char *) dev_descr;
    case MAG_HR_DEVICE_TABLE_STATUS:
        dev_status = GetDeviceStatus();
        return (u_char *) & dev_status;
    case MAG_HR_DEVICE_PRINTER_STATUS:
        prn_status = GetPrinterStatus();
        return (u_char *) & prn_status;
    case MAG_HR_DEVICE_PRINTER_ERRORSTATE:
        prn_errstate = GetPrinterErrorState();
        *varlen = sizeof(prn_errstate);
        return (u_char *) & prn_errstate;
    }
    return NULL;
}

#endif

mib2if.c                      。。。。。。。。。。。。。。。。。。。。。。。。。。。

/******************************************************************************
 *                                                                            *
 *                         M O D U L E   D E F I N E                          *
 *                                                                            *
 ******************************************************************************/

#define MIB2IF_C

/******************************************************************************
 *                                                                            *
 *        C O M P I L E R   D E F I N E D   I N C L U D E   F I L E S         *
 *                                                                            *
 ******************************************************************************/

#include <string.h>

/******************************************************************************
 *                                                                            *
 *            U S E R   D E F I N E D   I N C L U D E   F I L E S             *
 *                                                                            *
 ******************************************************************************/

#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"

#include "net\confnet.h"
#include "pro\snmp.h"
#include "pro\snmp_api.h"
#include "mib2.h"

#if defined(NUTNET)

/******************************************************************************
 *                                                                            *
 *                         L O C A L   D E F I N E S                          *
 *                                                                            *
 ******************************************************************************/

#define MAG_IF_NUMBER           0
#define MAG_IF_INDEX            1
#define MAG_IF_DESCR            2
#define MAG_IF_TYPE             3
#define MAG_IF_MTU              4
#define MAG_IF_SPEED            5
#define MAG_IF_PHYSADDRESS      6
#define MAG_IF_ADMINSTATUS      7
#define MAG_IF_OPERSTATUS       8
#define MAG_IF_LASTCHANGE       9
#define MAG_IF_INOCTETS         10
#define MAG_IF_INUCASTPKTS      11
#define MAG_IF_INNUCASTPKTS     12
#define MAG_IF_INDISCARDS       13
#define MAG_IF_INERRORS         14
#define MAG_IF_INUNKNOWNPROTOS  15
#define MAG_IF_OUTOCTETS        16
#define MAG_IF_OUTUCASTPKTS     17
#define MAG_IF_OUTNUCASTPKTS    18
#define MAG_IF_OUTDISCARDS      19
#define MAG_IF_OUTERRORS        20
#define MAG_IF_OUTQLEN          21
#define MAG_IF_SPECIFIC         22

#define MIB_IF_ENTRIES          4

/******************************************************************************
 *                                                                            *
 *                        L O C A L   T Y P E D E F S                         *
 *                                                                            *
 ******************************************************************************/

/* None */

/******************************************************************************
 *                                                                            *
 *             L O C A L   F U N C T I O N   P R O T O T Y P E S              *
 *                                                                            *
 ******************************************************************************/

static u_char *MibVarsIfGet(CONST SNMPVAR *, OID *, size_t *, int, size_t *, WMETHOD **);

/******************************************************************************
 *                                                                            *
 *    L O C A L   I N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static OID base_oid[] = { SNMP_OID_MIB2, 2 };
static size_t base_oidlen = sizeof(base_oid) / sizeof(OID);

static SNMPVAR mib_variables[] = {
    {MAG_IF_NUMBER, ASN_INTEGER, ACL_RONLY, MibVarsIfGet, 1, {1}},
    {MAG_IF_INDEX, ASN_INTEGER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 1}},
    {MAG_IF_DESCR, ASN_OCTET_STR, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 2}},
    {MAG_IF_TYPE, ASN_INTEGER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 3}},
    {MAG_IF_MTU, ASN_INTEGER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 4}},
    {MAG_IF_SPEED, ASN_GAUGE, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 5}},
    {MAG_IF_PHYSADDRESS, ASN_OCTET_STR, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 6}},
    {MAG_IF_ADMINSTATUS, ASN_INTEGER, ACL_RWRITE, MibVarsIfGet, 3, {2, 1, 7}},
    {MAG_IF_OPERSTATUS, ASN_INTEGER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 8}},
    {MAG_IF_LASTCHANGE, ASN_TIMETICKS, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 9}},
    {MAG_IF_INOCTETS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 10}},
    {MAG_IF_INUCASTPKTS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 11}},
    {MAG_IF_INNUCASTPKTS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 12}},
    {MAG_IF_INDISCARDS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 13}},
    {MAG_IF_INERRORS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 14}},
    {MAG_IF_INUNKNOWNPROTOS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 15}},
    {MAG_IF_OUTOCTETS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 16}},
    {MAG_IF_OUTUCASTPKTS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 17}},
    {MAG_IF_OUTNUCASTPKTS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 18}},
    {MAG_IF_OUTDISCARDS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 19}},
    {MAG_IF_OUTERRORS, ASN_COUNTER, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 20}},
    {MAG_IF_OUTQLEN, ASN_GAUGE, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 21}},
    {MAG_IF_SPECIFIC, ASN_OBJECT_ID, ACL_RONLY, MibVarsIfGet, 3, {2, 1, 22}}
};

static char *if_descr = "DM9161A 10/100 Mbps Fast Ethernet";

static OID if_specific[] = { 0, 0 };

/******************************************************************************
 *                                                                            *
 *    L O C A L   U N I T I A L I Z E D   D A T A   D E F I N I T I O N S     *
 *                                                                            *
 ******************************************************************************/

static long if_number;
static long if_type;
static long if_mtu;
static u_long if_speed;
static long if_index;

static long if_admin_status[MIB_IF_ENTRIES];

/*!
 * \brief Register MIB II variables of the interfaces.
 *
 * \note Preliminary code with hard coded values.
 */
int MibRegisterIfVars(void)
{
    int i;

    if_number = 1;
    for (i = 0; i < if_number; i++) {
        if_admin_status[i] = 1;
    }
    if_type = 6;
    if_mtu = 1500;
    if_speed = 100000000UL;
    if_index = 1;

    return SnmpMibRegister(base_oid, base_oidlen, mib_variables, sizeof(mib_variables) / sizeof(SNMPVAR));
}

static int MibVarsIfSet(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, OID * name, size_t name_len)
{
    size_t bigsize = 1000;
    u_long value = 0;

    if (action != SNMP_ACT_COMMIT) {
        return 0;
    }
    switch (name[9]) {
    case 7:
        if (var_val_type != ASN_INTEGER)
            return SNMP_ERR_WRONGTYPE;
        if (var_val_len > sizeof(u_long))
            return SNMP_ERR_WRONGLENGTH;
        AsnUnsignedParse(var_val, &bigsize, &var_val_type, &value);
        if (name[10] > 0 && name[10] < MIB_IF_ENTRIES) {
            if_admin_status[name[10] - 1] = value;
        }
        break;
    }
    return 0;
}

static u_char *MibVarsIfGet(CONST SNMPVAR * vp, OID * name, size_t * namelen, int exact, size_t * varlen, WMETHOD ** wmethod)
{
    int rc;
    int ifc = 0;
    OID index = 0;
    static long zero = 0;
    OID *fullname;
    size_t fullnamelen = base_oidlen + vp->var_namelen + 1;

    if ((fullname = NutHeapAlloc(fullnamelen * sizeof(OID))) == NULL) {
        return NULL;
    }
    memcpy(fullname, base_oid, base_oidlen * sizeof(OID));
    memcpy(fullname + base_oidlen, vp->var_name, vp->var_namelen * sizeof(OID));

    if (vp->var_magic == MAG_IF_NUMBER) {
        /* Determine the number of interfaces. */
        *(fullname + fullnamelen - 1) = index;
        rc = SnmpOidCmp(name, *namelen, fullname, fullnamelen);
        if ((exact && rc) || (!exact && rc >= 0)) {
            NutHeapFree(fullname);
            return NULL;
        }
    } else {
        /* Determine the interface number. */
        for (; ifc < if_number; ifc++) {
            *(fullname + fullnamelen - 1) = ifc + 1;
            rc = SnmpOidCmp(name, *namelen, fullname, fullnamelen);
            if ((exact && rc == 0) || (!exact && rc < 0)) {
                index = ifc + 1;
                break;
            }
        }
        if (index == 0) {
            NutHeapFree(fullname);
            return NULL;
        }
    }
    memcpy(name, fullname, fullnamelen * sizeof(OID));
    *namelen = fullnamelen;
    NutHeapFree(fullname);

    *wmethod = NULL;
    *varlen = sizeof(long);
    switch (vp->var_magic) {
    case MAG_IF_NUMBER:
        return (u_char *) & if_number;
    case MAG_IF_INDEX:
        return (u_char *) & if_index;
    case MAG_IF_DESCR:
        *varlen = strlen(if_descr);
        return (u_char *) if_descr;
    case MAG_IF_TYPE:
        return (u_char *) & if_type;
    case MAG_IF_MTU:
        return (u_char *) & if_mtu;
    case MAG_IF_SPEED:
        return (u_char *) & if_speed;
    case MAG_IF_PHYSADDRESS:
        *varlen = 6;
        return confnet.cdn_mac;
    case MAG_IF_ADMINSTATUS:
    case MAG_IF_OPERSTATUS:
        *wmethod = MibVarsIfSet;
        return (u_char *) & if_admin_status[ifc];
    case MAG_IF_LASTCHANGE:
    case MAG_IF_INOCTETS:
    case MAG_IF_INUCASTPKTS:
    case MAG_IF_INNUCASTPKTS:
    case MAG_IF_INDISCARDS:
    case MAG_IF_INERRORS:
    case MAG_IF_INUNKNOWNPROTOS:
    case MAG_IF_OUTOCTETS:
    case MAG_IF_OUTUCASTPKTS:
    case MAG_IF_OUTNUCASTPKTS:
    case MAG_IF_OUTDISCARDS:
    case MAG_IF_OUTERRORS:
    case MAG_IF_OUTQLEN:
        return (u_char *) & zero;
    case MAG_IF_SPECIFIC:
        *varlen = sizeof(if_specific);
        return (u_char *) if_specific;
    }
    return NULL;
}

#endif

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值