/*
 *  K e r m i t  File Transfer Utility
 *
 *  UniFLEX Kermit...  Adapted from UNIX version by
 *
 *    Jur van der Burg
 *    Nettelhorst 56
 *    2402 LS Alphen aan den Rijn
 *    The Netherlands
 *
 *    Telephone: (0)1720 - 34057
 *
 */

#include "ufk.h"
#include <signal.h>

#asm
 info UniFLEX Kermit
 info Author Jur van der Burg
 info Nettelhorst 56
 info 2402 LS  Alphen aan den Rijn
 info The Netherlands
 info Version: V 1.5
#endasm

/*
 * Main command table
 */

TABLE  command_table[] =
{
   "send", 1,
   "receive", 2,
   "connect", 3,
   "get", 4,
   "set", 5,
   "show", 6,
   "server", 7,
   "help", 8,
   "exit", 9,
   "quit", 10,
   "bye", 11,
   "finish", 12,
   "transmit", 13,
   "local", 14,
   "statistics", 15,
   "take", 16,
   "chd", 17,
   "free", 18,
   "", 0
};

/*
 * Start of main program
 */

main(argc,argv)
int   argc;
char  *argv[];
{
   char  input[257],                      /* Command input */
         save_screen;
   int   kerm_exit();

   setbuf(stdout,0);                      /* Don't buffer stdout */
   pffinit();                             /* Link code for floating point */
   pflinit();                             /* Link code for long printout */

   init_par();                            /* Setup parameters */
   parse_flags(argc,argv);                /* Select correct options */
   signal(SIGTERM,kerm_exit);             /* Catch TERMINATE interrupt */
   signal(SIGHUP,kerm_exit);              /* Catch HANGUP interrupt */

   nooutput = TRUE;        /* Don't generate output if called with options */
   save_screen = screen;                  /* Save for later */
   screen = FALSE;
   if (cflg)
      connect();                          /* connect to line */
   else if (rflg == 1)
      recfile();                          /* receive file */
   else if (rflg == 2)
      getfile();                          /* Get file from server */
   else if (sflg == 1)
      sendfile();                         /* send file */
   else if (sflg == 2)
      server();                           /* server mode */
   else
   {
      nooutput = FALSE;   /* Generate output if not called with optiAns */
      screen = save_screen;               /* restore screen value */
      for (;;)                            /* Do this forever */
      {
         do
         {
            fputs(prompt,stdout);         /* Prompt user */
            if (fgets(input,256,stdin) == NULL) /* Get response */
            {
               fputs("\n",stdout);
               kerm_exit();               /* E O F */
            }
            input[strlen(input) - 1] = '\0'; /* Zap newline */
         }
         while (!input[0] || (input[0] == COMMENT));/* Blank command line */
         kerm_command(input);             /* Process command */
      }
   }
}


parse_flags(argc,argv)
int argc;
char *argv[];
{
   int do_startup,                        /* Start file flag */
       verbose,                           /* Echo startup file */
       j;
   char *s,
        *userfile,
        *malloc();

   do_startup = TRUE;                     /* Use startup command file */
   verbose = FALSE;                       /* Don't echo startup file */
   cflg = sflg = rflg = FALSE;            /* Turn off all flags */
   userfile = NULL;                       /* Nothing specified yet */

   if (argc > 1)
   {
      s = *++argv;                        /* Setup pointers to arguments */
      argv++;
      argc -= 2;
      while (*s != '\0')                  /* loop until end of string */
         switch(*s++)
         {
            case 'c':
                     cflg++;              /* 'connect' mode */
                     break;
            case 'r':
                     rflg = 1;            /* 'receive' mode */
                     break;
            case 'g':
                     rflg = 2;            /* 'get' mode */
                     break;
            case 's':
                     sflg = 1;            /* 'send' mode */
                     break;
            case 'x':
                     sflg = 2;            /* 'server' mode */
                     break;
            case 'l':
                     strcpy(tty_descr,"/dev/modem"); /* Use local line */
                     break;
            case 't':
                     if (argc--)          /* Use specified terminal */
                        strcpy(tty_descr,*argv++);
                     else
                        usage();
                     break;
            case 'o':
                     maskflag = TRUE;     /* Turn on image mode */
                     break;
            case 'i':
                     image = TRUE;        /* Turn on image mode */
                     break;
            case 'f':
                     mapping = FALSE;     /* Turn off filename case mapping */
                     break;
            case 'e':
                     if (argc--)
                        escchr = **argv++;/* Get new escape character */
                     else
                        usage();
                     break;
            case 'n':
                     do_startup = FALSE;  /* Don't get commands from file */
                     break;
            case 'v':
                     verbose = TRUE;      /* Echo startup file */
                     break;
            case 'u':
                     if (argc--)          /* Use specified command file */
                        userfile = *argv++;
                     else
                        usage();
                     break;
            case 'b':
                     if (argc--)          /* Use specified terminal */
                     {
                        if (set_baud(TRUE,argv++)) /* Set baud rate */
                           usage();
                     }
                     else
                        usage();
                     break;
            default:
                     usage();             /* Tell him how to do it */
         }

      if ((sflg && rflg) ||               /* check for illegal combinations */
          (sflg && cflg) ||
          (rflg && cflg))
         usage();
      prt_ident();
      if ((do_startup) && !(sflg || rflg || cflg))
         if (userfile == 0)
         {
            if (take(INITFILE,verbose) != NULL) /* Execute default init file */
               take(INITFILE1,verbose);  /* Try alternate name */
         }
         else
            if ((j = take(userfile,verbose)) != NULL)/* Exec user init file */
               prterr(j);
      if (cflg || rflg || sflg)
      {
         call_baud = FALSE;         /* Don't set baudrate anymore */
         numprm = argc + 1;
         if (argc != 0)
         {
            if ((params = malloc(numprm * sizeof(char *))) == NULL)
            {                       /* get space for parameters */
               prterr(ER_NOMEM);
               kerm_exit();
            }
            for (j = 1; j < numprm; j++)
               params[j] = *argv++; /* Setup correct parameter pointers */
         }
      }
   }
   else
   {
      prt_ident();
      if (take(INITFILE,verbose) != NULL) /* Execute default init file */
         take(INITFILE1,verbose);  /* Try alternate name */
   }
}

prt_ident()
{
   if (!cflg && !rflg && !sflg)
   {
      fputs(IDENT,stdout);                /* Tell him we're on the air! */
      fputs(VERSION,stdout);              /* With this version */
      fputs("\n\n",stdout);
   }
}

init_par()
{
   /*  Initialize these values and hope the first packet will get across OK */

   mypackstart = I_MYPACKSTART;           /* Start of packet character */
   maxpacksiz = I_MAXPACKSIZ;             /* Maximum packet size */
   maxtry = I_MAXTRY;                     /* Times to retry a packet */
   myquote = I_MYQUOTE;                   /* Quote character I will use */
   mypad = I_MYPAD;                       /* Number of padding chars I need */
   mypchar = I_MYPCHAR;                   /* Padding character I need (NULL) */
   myeol = I_MYEOL;                       /* End-Of-Line character I need */
   mytime = I_MYTIME;                     /* My timeout in seconds */
   myblock_check_type = I_BLOCKCHECKTYPE; /* Block check type */
   myrptquote = I_MYRPTQUOTE;             /* Repeat count quote character */
   myeightquote = I_MYEIGHTQUOTE;         /* Eight bit quote character */
   send_delay = I_SEND_DELAY;             /* Delay before sending */
   attribute = FALSE;                     /* No attribute packets yet */
   allowattr = TRUE;                      /* Do allow them */

   strcpy(prompt,DEFPROMPT);              /* Setup prompt */
   logfile[0] = '\0';                     /* No log filename yet */
   logfileopen = FALSE;                   /* No logging done yet */
   speed = 1200;                          /* Default line speed */
   maskflag = FALSE;                      /* Use default mask for RTS & DCD */
   config = 5;                            /* 8 bits, 1 stop, no parity */
   image = FALSE;                         /* Translation */
   save_file = FALSE;                     /* Don't save file on abort */
   prvsetdone = FALSE;                    /* privileged task setup done */
   call_baud = TRUE;                      /* call 'baud' on line open */
   escchr = ESCCHR;                       /* Default escape character */
   fulldup = TRUE;                        /* Default is full duplex */
   warning = TRUE;                        /* File conflict warning */
   mapping = TRUE;                        /* Filename case mapping */
   auto_recover = TRUE;                   /* Recovery for extended packets */
   t_chr_sent = t_dchr_sent = t_nak_sent = 0; /* reset counters */
   t_chr_rec = t_dchr_rec = t_nak_rec = 0;
   tabsleft = TABSIZE;                    /* Default tab setting */
   dstop = XOFF;                          /* Init handshake characters */
   dstart = XON;
   dbgfil = ERROR;                        /* No debug file */
   fp = ERROR;                            /* Indicate no file open yet */
   strcpy(tty_descr,"Remote");
   aborted = FALSE;                       /* Not yet aborted */
   port_open = FALSE;                     /* Port closed now */
   timint = I_MYTIME;                     /* Setup timeout value */
   recpkt = 0;                            /* Invalidate memory pointers */
   sndpkt = 0;
   screen = terminit();                   /* Set TRUE if screen control */
   init_crc_table();                      /* Setup table for CRC calculation */
   bg = check_bg();                       /* Test if we're in the background */
}

/*
 * Process kermit command
 */

kerm_command(instrng)
char *instrng;
{
   int funcpoint;
   char *free();

   if (split(instrng))                    /* Split command line */
   {                                      /* into seperate strings */
      cflg = sflg = rflg = 0;             /* Turn off all flags */
      tabsleft = TABSIZE;                 /* Default tab setting */
      aborted = FALSE;                    /* Not yet aborted */
      timint = I_MYTIME;                  /* Setup timeout value */

      funcpoint = parse(params[0], command_table);/* Find routine address */
      if (funcpoint == NULL)              /* Ambiguous */
         prterr(ER_AMBIG);
      else if (funcpoint == ERROR)        /* Unknown */
         prterr(ER_UNKNOWN);
      else
         switch(funcpoint)                /* Process command */
         {
            case 1:
                     sendfile();
                     break;
            case 2:
                     recfile();
                     break;
            case 3:
                     connect();
                     break;
            case 4:
                     getfile();
                     break;
            case 5:
                     set();
                     break;
            case 6:
                     show();
                     break;
            case 7:
                     server();
                     break;
            case 8:
                     help();
                     break;
            case 9:
            case 10:
                     kerm_exit();
                     break;
            case 11:
                     bye();
                     break;
            case 12:
                     finish();
                     break;
            case 13:
                     trnsmit();
                     break;
            case 14:
                     do_uniflex();
                     break;
            case 15:
                     statistics();
                     break;
            case 16:
                     take(0,TRUE);
                     break;
            case 17:
                     chd();
                     break;
            case 18:
                     disk_free();
                     break;
         }
      dealloc_pkt();                      /* Release allocated memory */
      if (fp != ERROR)
      {
         fclose(fp);                      /* Close file if we're aborted */
         fp = ERROR;                      /* Indicate no file open yet */
      }
   }
   while (numprm)
      free(params[--numprm]);             /* Free command string memory */
   free(params);                          /* get rid of pointer table */
}

usage()
{
   char **dp;
   static char *doc[] = {
   "Usage: kermit n  Disable startup command file",
   "              v  Verbose startup, echo commands",
   "              u  Use specified command file",
   "              c  Connect to line",
   "              r  Receive file(s)",
   "              g  Get file(s) from server",
   "              s  Send file(s)",
   "              x  Start server mode",
   "              l  Use local device ('/dev/modem')",
   "              t  Use specified device",
   "              i  Turn on image mode",
   "              f  Turn off filename mapping",
   "              e  Use new escape character",
   "              b  Set new baud rate",
   "              o  Ignore DCD and force RTS in port usage",
   "",
   "Kermit enters interactive mode if no parameters to",
   "send or receive files are specified.",
   0 };

   for (dp = doc; *dp; dp++)
      fprintf(stderr,"%s\n",*dp);
   exit(1);
}

kerm_exit()
{
   if (port_open)
      close_port(FALSE,TRUE);
   sup_exit();                          /* stop support task */
   exit(0);
}
