// ===========================================================
// Author: Yee Hsu                                     #1-8748
// Instru: Dr. J. Wong
// Date:   May 2, 2001
//
// File: Com.cc
//
// Implementation of the Com class. Com is the
// communications interface between the user and the Server.
// It provides a user interface to prompt the user for
// commands to be executed by the Server.
// ===========================================================

#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include "Message.h"
#include "Com.h"

// ===========================================================
// Identifier:  Com()
//
// Comments:    Com default constructor. All variables/arrays
//              are pre-defined and initialized.
// ===========================================================

Com::Com()
{
    memset(m1.command,  '\0', COM_LENGTH);
    memset(m1.execName, '\0', EXE_LENGTH);

    this->m1.option     = '\0';

    for (int i = 0; i < MAX_ARGMNT; i++)
        memset(m1.arg[i], '\0', sizeof(m1.arg[i]));
}

// ===========================================================
// Identifier:  ~Com()
//
// Comments:    Com default destructor. All variables/arrays
//              are reset
// ===========================================================

Com::~Com()
{
    memset(m1.command,  '\0', COM_LENGTH);
    memset(m1.execName, '\0', EXE_LENGTH);

    this->m1.option     = '\0';

    for (int i = 0; i < MAX_ARGMNT; i++)
        memset(m1.arg[i], '\0', sizeof(m1.arg[i]));
}

// ===========================================================
// Identifier:  Execute(ComMsg&)
//
// Parameter:   &msg    -- Communication message (m1)
//
// Comments:    Resets the ComMsg msg.
//              Executes Com instructions.
//
// Calls:       ComPrompt()     -- prompts user input
//              Tokenizer()     -- tokenize command input
// ===========================================================

void Com::Execute(ComMsg &msg)
{
    memset(msg.command,  '\0', COM_LENGTH);
    memset(msg.execName, '\0', EXE_LENGTH);

    msg.option     = '\0';

    for (int i = 0; i < MAX_ARGMNT; i++)
        memset(msg.arg[i], '\0', sizeof(msg.arg[i]));

    this->~Com();
    this->ComPrompt();
    this->Tokenizer(msg);
}

// ===========================================================
// Identifier:  ComPrompt()
//
// Comments:    Prompts the user for input. Interface is
//              very similar to an OS console.
// ===========================================================

void Com::ComPrompt()
{
    cout << "SMVS> ";
    cout.flush();
    cin.getline(this->command, INP_LENGTH);
}

// ===========================================================
// Identifier:  Tokenizer(ComMsg&)
//
// Parameter:   &msg    -- Communication message (m1)
//
// Comments:    Tokenizer breaks down the input command
//              line into a series of tokens. These tokens
//              are stored into the ComMsg and later
//              transfered to the Server via a pipe.
// ===========================================================

void Com::Tokenizer(ComMsg &msg)
{
    char *tok = NULL;

    if (tok = strtok(this->command, " "))
    {
        memcpy(m1.command, tok, COM_LENGTH);

        if (!strcmp(tok, RUN))
        {
            int i = 0;
            tok = strtok(NULL, " ");

            if (*tok == '-')
            {
                this->m1.option = *(++tok);
                memcpy(m1.execName, strtok(NULL, " "), EXE_LENGTH);
            }
            else
                memcpy(m1.execName, tok, EXE_LENGTH);

            while ((tok = strtok(NULL, " ")) && i < MAX_ARGMNT)
            {
                memcpy(m1.arg[i], tok, sizeof(m1.arg[i]));
                i++;
            }
        }
        else if (!strcmp(tok, LS))
            ((tok = strtok(NULL, " ")) ? m1.option = *(++tok) : 0);
        else if (!strcmp(tok, EXIT))
        {
        }
        else
        {
            while (*tok != '\0') {cerr << *tok++;}
            cerr << ": Command not found\n";
        }
    }
    msg = this->m1;
}