/*
 * 4m v2.15 (parse.c)
 * (C) Copyright 1990 by Carrick Sean Casey
 * (C) Copyright 1993 by Scott Chasin and Michaeljon Miller
 *
 * 3-24-93 See file COPYING for copyright information.
 *
 * Command input and alias parsing
 */

#include "4m.h"
#include "externs.h"
#include <ctype.h>

#ifdef HAS_STRINGS
# include <strings.h>
#endif

#ifdef HAS_STRING
# include <string.h>
#endif

char *nextword();

static char *parse_argv[50];
static int parse_argc;

extern void c_quit(), 
            c_hclear(), 
            c_hush(), 
            c_log(), 
            c_replay(),
            c_shell(), 
            c_time(), 
            c_server(), 
            s_cmd(), 
            set(), 
            c_alias(),
            c_send(), 
            c_get(), 
            c_clear(), 
            c_eclear(), 
            c_chdir(), 
            c_pwd(),
            s_personal(), 
            c_pipe(), 
            c_finger(), 
            c_version(), 
            c_chat(),
            c_history();

table verbs[] = {
    /* { */ "?", s_cmd, "?" /* } */,
    /* { */ "a", s_cmd, "action" /* } */,
    /* { */ "action", s_cmd, "action" /* } */,
    /* { */ "al", c_alias, NULL /* } */,
    /* { */ "alias", c_alias, NULL /* } */,
    /* { */ "announce", s_cmd, "announce" /* } */,
    /* { */ "aw", s_cmd, "away" /* } */,
    /* { */ "away", s_cmd, "away" /* } */,
    /* { */ "b", s_cmd, "beep" /* } */,
    /* { */ "ba", s_cmd, "ban" /* } */,
    /* { */ "ban", s_cmd, "ban" /* } */,
    /* { */ "beep", s_cmd, "beep" /* } */,
    /* { */ "bye", c_quit, NULL /* } */,
    /* { */ "c", c_clear, NULL /* } */,
    /* { */ "ca", s_cmd, "cancel" /* } */,
    /* { */ "cancel", s_cmd, "cancel" /* } */,
    /* { */ "ch", c_chat, NULL /* } */,
    /* { */ "chat", c_chat, NULL /* } */,
    /* { */ "cl", s_cmd, "claim" /* } */,
    /* { */ "claim", s_cmd, "claim" /* } */,
    /* { */ "clear", c_clear, NULL /* } */,
    /* { */ "connect", s_cmd, "connect" /* } */,
    /* { */ "debug", s_cmd, "debug" /* } */,
    /* { */ "disconnect", s_cmd, "disconnect" /* } */,
    /* { */ "drop", s_cmd, "drop" /* } */,
    /* { */ "e", s_cmd, "echoback" /* } */,
    /* { */ "ec", c_eclear, NULL /* } */,
    /* { */ "echoback", s_cmd, "echoback" /* } */,
    /* { */ "eclear", c_eclear, NULL /* } */,
    /* { */ "exit", c_quit, NULL /* } */,
    /* { */ "finger", c_finger, NULL /* } */,
    /* { */ "g", s_cmd, "join" /* } */,
    /* { */ "get", c_get, NULL /* } */,
    /* { */ "ghost", s_cmd, "ghost" /* } */,
    /* { */ "ginfo", s_cmd, "ginfo" /* } */,
    /* { */ "gr", s_cmd, "groups" /* } */,
    /* { */ "group", s_cmd, "join" /* } */,
    /* { */ "groups", s_cmd, "groups" /* } */,
    /* { */ "h", c_hush, NULL /* } */,
    /* { */ "help", s_cmd, "help" /* } */,
    /* { */ "hush", c_hush, NULL /* } */,
    /* { */ "history", c_history, NULL /* } */,
    /* { */ "i", s_cmd, "invite" /* } */,
    /* { */ "invite", s_cmd, "invite" /* } */,
    /* { */ "j", s_cmd, "join" /* } */,
    /* { */ "join", s_cmd, "join" /* } */,
    /* { */ "k", s_cmd, "kick" /* } */,
    /* { */ "kick", s_cmd, "kick" /* } */,
    /* { */ "kill", s_cmd, "drop" /* } */,
    /* { */ "la", s_cmd, "last" /* } */,
    /* { */ "last", s_cmd, "last" /* } */,
    /* { */ "lcd", c_chdir, NULL /* } */,
    /* { */ "lights", s_cmd, "lights" /* } */,
    /* { */ "link", s_cmd, "link" /* } */,
    /* { */ "log", c_log, NULL /* } */,
    /* { */ "logout", c_quit, NULL /* } */,
    /* { */ "m", s_personal, NULL /* } */,
    /* { */ "me", s_cmd, "me" /* } */,
    /* { */ "members", s_cmd, "members" /* } */,
    /* { */ "mesg", s_cmd, "mesg" /* } */,
    /* { */ "mjoin", s_cmd, "mjoin" /* } */,
    /* { */ "mo", s_cmd, "mode" /* } */,
    /* { */ "mode", s_cmd, "mode" /* } */,
    /* { */ "monitor", s_cmd, "monitor" /* } */,
    /* { */ "motd", s_cmd, "motd" /* } */,
    /* { */ "msg", s_personal, NULL /* } */,
    /* { */ "n", s_cmd, "name" /* } */,
    /* { */ "nick", s_cmd, "name" /* } */,
    /* { */ "no", s_cmd, "notify" /* } */,
    /* { */ "notify", s_cmd, "notify" /* } */,
    /* { */ "o", s_cmd, "oper" /* } */,
    /* { */ "oper", s_cmd, "oper" /* } */,
    /* { */ "p", s_cmd, "promote" /* } */,
    /* { */ "part", s_cmd, NULL /* } */,
    /* { */ "pipe", c_pipe, NULL /* } */,
    /* { */ "promote", s_cmd, "promote" /* } */,
    /* { */ "pwd", c_pwd, NULL /* } */,
    /* { */ "q", c_quit, NULL /* } */,
    /* { */ "quit", c_quit, NULL /* } */,
    /* { */ "r", c_replay, NULL /* } */,
    /* { */ "replay", c_replay, NULL /* } */,
    /* { */ "send", c_send, NULL /* } */,
    /* { */ "server", c_server, NULL /* } */,
    /* { */ "servers", s_cmd, "servers" /* } */,
    /* { */ "set", set, NULL /* } */,
    /* { */ "shell", c_shell, NULL /* } */,
    /* { */ "shutdown", s_cmd, "shutdown" /* } */,
    /* { */ "signoff", c_quit, NULL /* } */,
    /* { */ "summon", s_cmd, "summon" /* } */,
    /* { */ "t", s_cmd, "topic" /* } */,
    /* { */ "tab", c_hclear, NULL /* } */,
    /* { */ "tabclear", c_hclear, NULL /* } */,
    /* { */ "time", c_time, NULL /* } */,
    /* { */ "topic", s_cmd, "topic" /* } */,
    /* { */ "uptime", s_cmd, "uptime" /* } */,
    /* { */ "users", s_cmd, "users" /* } */,
    /* { */ "ver", s_cmd, "version" /* } */,
    /* { */ "version", c_version, NULL /* } */,
    /* { */ "w", s_cmd, "who" /* } */,
    /* { */ "wall", s_cmd, "wall" /* } */,
    /* { */ "wh", s_cmd, "whois" /* } */,
    /* { */ "who", s_cmd, "who" /* } */,
    /* { */ "whois", s_cmd, "whois" /* } */
};

int numcom = sizeof(verbs) / sizeof(*verbs);

extern void putl ();
extern int c_sendopen ();
extern void parse ();
extern int wordcmp ();
extern void sendpersonal ();
extern void errormsg ();
void mkargs ();
int alias_check ();
extern int nlcount ();
extern char *nlget ();

int parse_packet(s)
     char *s;
{
    int i;

    char cmdargs[1024], cmd[20];
    char *line = s;

 /* see if it's just text meant for the group */
    if (*s != gv.cmdchar || *s == PERMCMDCHAR) {
        putl(s, PL_LOG | PL_BUF);
        c_sendopen(s);
        return;
    }

 /* first char must have been the command char, skip over it */
    s++;
    parse(s);

    if (first == '@') {
       s++;
       c_histget (s);
       return -1;
    }

 /* Add command to the history list */
    sprintf (mbuf, "/%s", s);
    nlput (cmd_history, mbuf);

 /* check to see if it's a personal */
    if (!wordcmp(s, "m") || !wordcmp(s, "msg")) {
        putl(line, PL_LOG | PL_BUF);  /* already written to screen */
        sendpersonal(nextword(s));
        return;
    } else
    /* check to see if it's a shell command */
    /* what a mess, but it works */
    if (*s == '!') {
        char *w;

        s++;

        if (gv.restricted) {
            errormsg("No shell commands in restricted mode.");
            return;
        }

        if ((*s == ' ' || *s == '\t') && ((w = nextword(s)) != NULL)) {
            parse_argv[0] = "c_shell";
            parse_argv[1] = w;
            parse_argv[2] = NULL;
            c_shell(2, parse_argv);
        } else if (*s != '\0') {
            parse_argv[0] = "c_shell";
            parse_argv[1] = s;
            parse_argv[2] = NULL;
            c_shell(2, parse_argv);
        } else {
            parse_argv[0] = "c_shell";
            parse_argv[1] = NULL;
            c_shell(1, parse_argv);
        }
        return;

    } else
    /* a doubled command char means use it literally */
    if (first == gv.cmdchar) {
        putl(s, PL_LOG | PL_BUF);
        c_sendopen(s);
        return;
    }

    for (i = 0; i < numcom; i++)
        if (!strcasecmp(verbs[i].name, *words)) {
            mkargs(0, s);
            if (verbs[i].command)
                strcpy(parse_argv[0], verbs[i].command);
            (*verbs[i].function) (parse_argc, parse_argv);
            return;
        }

    if (*args)
        strcpy(cmdargs, args);
    else
        cmdargs[0] = '\0';

    strcpy(cmd, words[0]);

    if (alias_check(cmd, cmdargs))
        return;

    errormsg("Invalid command, /help for a listing.");
    putl(line, PL_LOG);

    return;
}


/* starting at a word, find the start of the next one */
char *
nextword(s)
     char *s;
{
    while (*s != ' ' && *s != '\t' && *s != '\0')
        s++;

    while ((*s == ' ' || *s == '\t') && *s != '\0')
        s++;


    return (*s == 0 ? 0 : s);
}

int countwords(s)
     char *s;
{
    int i = 0;

    for (; *s != '\0'; s++) {
        if (*s == ' ') {
            i++;
        }
    }

    return (i);
}

void mkargs(i, ptr)
     int i;
     char *ptr;
{
    int wordcount = i;

    while (*ptr) {
        while (*ptr && isspace(*ptr)) {
            ptr++;
        }
        if (*ptr)
            parse_argv[wordcount++] = ptr;
        while (*ptr && !isspace(*ptr)) {
            ptr++;
        }

        if (*ptr) {
            *(ptr++) = '\0';
        }
    }

    parse_argv[wordcount] = (char *) 0;
    parse_argc = wordcount;

    return;
}

int alias_check(cmd, cmdargs)
     char *cmd;
     char *cmdargs;
{
    int i, x, count = 0;
    char *cp, *alias, *command, *cmdbuf, buf[255];

    count = nlcount(cmdalias);

    memset(mbuf, 0, strlen(mbuf));

    for (i = 0; i < count; i++) {
        cp = nlget(cmdalias);
        parse(cp);
        alias = words[0];
        command = words[1];
        if (!strcasecmp(alias, cmd)) {
            for (x = 0; x < numcom; x++) {
                if (!strcasecmp(verbs[x].name, command)) {
                    parse(args);
                    if (*args) {
                        cmdbuf = args;
                        strcpy(mbuf, cmdbuf);
                    /* mbuf = cmdbuf; */
                    }
                    if (*cmdargs) {
                        if (*args) {
                            sprintf(mbuf, "%s %s", cmdbuf, cmdargs);
                        }
                        else
                            strcpy(mbuf, cmdargs);
                    /* mbuf = cmdargs; */
                    }
                    args = mbuf;
                    if (*mbuf) {
                        strcpy(buf, mbuf);
                        mkargs(1, buf);
                    }
                    if (verbs[x].command)
                        parse_argv[0] = verbs[x].command;
                    (*verbs[x].function) (parse_argc, parse_argv);
                    return 1;
                }
            }
        }
    }
    return 0;
}
