Hogwarts Wand Docs: ../server/serv.c

Wand Sourcecode: ../server/serv.c

// 
// THIS FILE IS OBSOLETE - see ww.c instead
//
// Copyright (C) 2006  Nathan (Acorn) Pooley
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License (gpl.txt) for more details. 
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// 
// You can contact the author, Nathan (Acorn) Pooley, by writing
// to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA  94086, USA
// or through the form at http://www.rawbw.com/~acorn/wand/feedback.html
//
//
//
//
//#@DOC@ OBSOLETE - old server program - use ww.c instead
//
//
//
//
//
// serv.c - wand functions
// 

//###########################################################################
//############################### INCLUDES ##################################
//###########################################################################

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "ac_serialio.h"
#include "ac_fdio.h"

//###########################################################################
//############################### TYPEDEFS ##################################
//###########################################################################

#define CTRL(c)     ((c) & 0x1f)

//###########################################################################
//############################### TYPEDEFS ##################################
//###########################################################################

typedef enum WandStateEnum {
    WS_UNKNOWN,
    WS_RECOVER,
    WS_PROMPT,
    WS_CMD,
    WS_PROMPT_PLUS,
    WS_ECHO,
    WS_REPLY,
    WS_END
} WandState;

//###########################################################################
//############################### GLOBALS ###################################
//###########################################################################

int g_wand_fd = -1;

WandState g_wand_state = WS_UNKNOWN;
char g_wand_lastprompt[1000] = "?>";
char g_wand_line[1000] = "";
int g_wand_line_cnt = 0;

int g_debug = 0;
int g_wasprompt = 0;

//###########################################################################
//############################### PROTOTYPES ################################
//###########################################################################

static void wandRecover(void);

//###########################################################################
//############################### CODE ######################################
//###########################################################################

//===========================================================================
// stripCr() - remove cr/lf from end of line
//===========================================================================
void stripCr(char *s)
{
    while(1) {
        if (!*s || *s == '\n' || *s == '\r') {
            *s = 0;
            return;
        }
        s++;
    }
}


//===========================================================================
// makePrintable()
//===========================================================================
char *makePrintable(char *s)
{
    static char buf[2000];
    char *d = buf;

    while(*s) {
        if (*s < ' ' || *s > '}' || *s == '@') {
            d += sprintf(d,"\\%02x",*(unsigned char*)s);
        } else {
            *(d++) = *s;
        }
        s++;
    }
    *d = 0;
    return buf;
}

//===========================================================================
// prePrint()
//===========================================================================
void prePrint(void)
{
    if (g_wasprompt) {
        printf("\n");
        g_wasprompt = 0;
    }
}

//===========================================================================
// prompt()
//===========================================================================
void prompt(void)
{
    if (!g_wasprompt && g_wand_state == WS_PROMPT) {
        printf("%s",g_wand_lastprompt);
        fflush(stdout);
        g_wasprompt = 1;
    }
}

//===========================================================================
// wandPrintf()
//===========================================================================
int wandPrintf(const char *fmt, ...)
{
    int cnt;
    int scnt = 0;
    char *s;
    char buf[1000];
    va_list va;

    va_start(va, fmt);
    cnt = vsnprintf(buf,sizeof(buf)-5,fmt,va);
    va_end(va);


    buf[cnt] = 0;

    if (g_debug) {
        prePrint();
        printf("Send to wand: '%s'\n",makePrintable(buf));
    }

    s = buf;
    while(cnt) {
        int c;
#if 1
        c = write(g_wand_fd, s, cnt);
#else
        if (g_debug) {
            printf("Send to wand c=%02x\n",*(unsigned char*)s);
        }
        c = write(g_wand_fd, s, 1);
        if (g_debug) {
            printf("Send to wand c done\n");
        }
#endif
        if (c) {
            cnt -= c;
            scnt += c;
            //usleep(100);
            s += c;
        } else {
            prePrint();
            fprintf(stderr,"Error writing to wand\n");
            break;
        }
    }
    if (g_debug) {
        printf("Send to wand Done\n");
    }
    return scnt;
}

//===========================================================================
// wandCmdf()
//===========================================================================
int wandCmdf(const char *fmt, ...)
{
    int ccnt;
    va_list va;
    char cbuf[1000];
    char rbuf[1000];
    char *s;
    char *r;
    char *se;
    char *re;
    int timeout = 0;

    va_start(va, fmt);
    ccnt = vsnprintf(cbuf,sizeof(cbuf)-5,fmt,va);
    va_end(va);

    if (g_debug) {
        prePrint();
        printf("Got CMD: '%s'\n",cbuf);
    }

    if (g_wand_state != WS_PROMPT) {
        wandRecover();
    }

    g_wand_state = WS_CMD;

    if (ccnt) {
        s = cbuf;
        se = cbuf + ccnt;
        while(s != se) {
            s += write(g_wand_fd, s, ccnt);
        }

        s = cbuf;
        while(s != se) {
            int rcnt = read(g_wand_fd, rbuf, sizeof(rbuf));
            rbuf[rcnt] = 0;
            r = rbuf;
            re = r + rcnt;
            if (!rcnt) {
                if (++timeout > 3) {
                    return -1;  // timeout
                }
                usleep(10000);
            }
            while(r != re && s != se) {
                if (*r != *s) {
                    prePrint();
                    fprintf(stderr, "Error in command: '%s'\n",cbuf);
                    fprintf(stderr,
                        "Error: Wand sent: '%s' (bad echo)\n",
                        makePrintable(rbuf));
                    return -1;
                }
                s++;
                r++;
            }
        }

        if (r != re) {
            prePrint();
            fprintf(stderr, "Error in command: '%s'\n",cbuf);
            fprintf(stderr,
                "Error: Wand sent: '%s' (too many)\n",
                makePrintable(rbuf));
            return -1;
        }
    }

    if (g_debug) {
        printf("Sending LF\n");
    }
    cbuf[0] = 0xa;
    write(g_wand_fd, cbuf, 1);

    return 0;
}

//===========================================================================
// wandChar()
//===========================================================================
static void wandChar(int c)
{
    g_wand_line[g_wand_line_cnt++] = c;

    //
    // check for prompt
    //
    if (c == ' ' && 
        g_wand_line_cnt>2 && 
        g_wand_line[g_wand_line_cnt-2] == '>') {

        int i;
        for (i=0; ; i++) {
            if (i==g_wand_line_cnt-2) {
                //
                // got a prompt
                //
                memcpy(g_wand_lastprompt, g_wand_line, g_wand_line_cnt);
                g_wand_lastprompt[g_wand_line_cnt] = 0;
                g_wand_line_cnt = 0;
                if (g_debug) {
                    prePrint();
                    printf("Got prompt: '%s'\n",g_wand_lastprompt);
                }


                g_wand_state = WS_PROMPT;
                if (g_debug) {
                    prePrint();
                    printf("state=WS_PROMPT=%d\n",g_wand_state);
                }
                return;
            }
            if (!isalpha(g_wand_line[i])) break;
        }
    }

    //
    // check for end of line
    //
    if (c!=0xa && c!=0xd) {
        if (g_wand_state == WS_PROMPT) {
            g_wand_state = WS_PROMPT_PLUS;
            if (g_debug) {
                prePrint();
                printf("state=WS_PROMPT_PLUS=%d\n",g_wand_state);
            }
        }
        return;
    }

    g_wand_line[--g_wand_line_cnt] = 0;

    //
    // ignore blank lines
    //
    if (g_wand_line_cnt == 0) {
        return;
    }


    prePrint();
    printf("Wand: '%s'\n",g_wand_line);
    g_wand_line_cnt = 0;

    return;
}


//===========================================================================
// wandRecover() - recover o known state
//===========================================================================
static void wandRecover(void)
{
#if 0
    int cnt;
#endif
    char buf[1000];

    usleep(10000);
    buf[0] = CTRL('X');
    write(g_wand_fd, buf, 1);
    usleep(10000);

#if 0
    cnt = read(g_wand_fd, buf, sizeof(buf)-100);
    buf[cnt] = 0;
    prePrint();
    printf("From wand: '%s' (recover)\n",makePrintable(buf));

    g_wand_state = WS_PROMPT;
#endif
}

//===========================================================================
// handleSerial()
//===========================================================================
static void *handleSerial(int fd, void *data)
{
    char buf[1000];
    int cnt;
    
    cnt = read(fd, buf, sizeof(buf)-100);

    if (cnt) {
        int i;

        buf[cnt] = 0;

        if (g_debug) {
            prePrint();
            printf("From wand: '%s'\n",makePrintable(buf));
        }

        for (i=0; i<cnt; i++) {
            wandChar(buf[i]);
        }
    }

    prompt();

    return 0;
}

//===========================================================================
// handleStdin()
//===========================================================================
static void *handleStdin(int fd, void *data)
{
    char buf[1000];
    int cnt = read(fd, buf, sizeof(buf)-1);
    stripCr(buf);
    if (cnt > 0) {
        buf[cnt] = 0;

        g_wasprompt = 0;
        if (buf[0] == 'q' && buf[1] == 0) {
            return (void*)1;
        }

        //
        // send to wand
        //
        if (buf[0] == ':') {
            wandCmdf("%s",buf+1);
        }
    }
    prompt();

    return 0;
}

//===========================================================================
// main()
//===========================================================================
int main(int argc, char *argv[])
{
    AcSerial *sio;
    AcFdGroup *grp;

    sio = acSerialCreate("/dev/ttyS0", 9600);
    if (!sio) {
        fprintf(stderr,"Error in acSerialCreate\n");
        exit(1);
    }

    acSerialSetNonCanonical(sio, 1, 200);
    acSerialOpen(sio);
    g_wand_fd = acSerialGetFD(sio);
    if (g_wand_fd < 0) {
        fprintf(stderr,"Error in acSerialOpen\n");
        exit(1);
    }

    grp = AcFdGroupCreate();
    if (!grp) {
        fprintf(stderr,"Error in AcFdGroupCreate\n");
        exit(1);
    }

    //
    // add serial handler
    //
    AcFdGroupAdd(grp, g_wand_fd, handleSerial, 0);

    //
    // add stdin handler (fd=0)
    //
    AcFdGroupAdd(grp, 0, handleStdin, 0);

    wandRecover();

    AcFdGroupLoop(grp);

    wandRecover();

    AcFdGroupDestroy(grp);

    acSerialDestroy(sio);
    return 0;
}

This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:28:48 PDT 2007