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

jmp_buf child_env;


/*
 *  c o n n e c t
 *
 *  Establish a virtual terminal connection with the remote host
 *
 */

connect()
{
   int   pid;                             /* Child process ID */
   int   toglog();
   char  c,
         got_escape,
         nul = '\0',
         save_descr[20];

   nooutput = FALSE;                      /* we should see something */
   strcpy(save_descr,tty_descr);          /* Save old port */
   if (numprm > 1)
   {
      close_port(FALSE,TRUE);             /* must close old one first */
      call_baud = TRUE;                   /* baudrate must be set again */
      strcpy(tty_descr,params[1]);        /* Get new port */
      if (!open_port(TRUE,FALSE))         /* Try to open the port */
      {
         prterr(ER_POPNERR);
         strcpy(tty_descr,save_descr);    /* Restore old port */
         return;                          /* Error in port setting */
      }
   }
   else
      if (!open_port(TRUE,FALSE))
      {
         prterr(ER_POPNERR);
         return;
      }
   if (remote)
   {
      close_port(FALSE,TRUE);
      prterr(ER_NOLINE);                  /* We're remote.... */
   }
   else
   {
      if (logfileopen)
         logging = TRUE;                  /* if file available, turn log on */
      pid = fork();                       /* Start child task */
      if (pid)
      {                                   /* Parent task */
         fputs("Connected...\n\l",stdout);
         cflg = TRUE;                     /* Put us in "connect mode" */
         purgeline(ttyfd);                /* eat pending input */
         got_escape = FALSE;              /* no escape char received yet */
         while (cflg)                     /* do as long as we're connected */
         {
            read(0,&c,1);                 /* get character from console */
            if (((c&0177) == escchr) || (got_escape)) /* chk for escape char */
            {
               if (!(got_escape = ~got_escape))
               {
                  if ((c&=0177) == escchr)/* maybe another one */
                  {
                     write(ttyfd,&c,1);   /* yes, echo it */
                     if (!fulldup)
                     {
                        write(1,&c,1);    /* echo if half duplex */
                        write_log(c);     /* send to log file as well */
                     }
                  }
                  else
                     switch (tolower(c&0177)) /* special character */
                     {
                        case '0':
                           write(ttyfd,&nul,1); /* send NULL */
                           break;

                        case 'b':
                           send_break(ttyfd); /* send BREAK */
                           break;

                        case 'c':
                           cflg = FALSE;      /* disconnect */
                           kwrite(1,"\r\l",0);
                           break;

                        case 'h':
                           kwrite(1,"\r\lYes, I'm still here...\r\l",0);
                           break;            /* tell him i'm still available */

                        case 'q':
                           if (logfileopen)
                           {
                              if (logging)
                              {
                                 logging = FALSE;
                                 kill(pid,12);    /* Send interrupt to child */
                              }
                              kwrite(1,"\r\lLogging suspended\r\l",0);
                           }
                           else
                              kwrite(1,"\r\lLog file is not open\r\l",0);
                           break;

                        case 'r':
                           if (logfileopen)
                           {
                              if (!logging)
                              {
                                 logging = TRUE;
                                 kill(pid,12);    /* Send interrupt to child */
                              }
                              kwrite(1,"\r\lLogging resumed\r\l",0);
                           }
                           else
                              kwrite(1,"\r\lLog file is not open\r\l",0);
                           break;

                        case 's':
                           kwrite(1,"\r\lLog file status: ",0);
                           if (logfileopen)
                              kwrite(1,"open\r\l",0);
                           else
                              kwrite(1,"closed\r\l",0);
                           kwrite(1,"Logging status:  ",0);
                           if (logging)
                              kwrite(1,"on\r\l",0);
                           else
                              kwrite(1,"off\r\l",0);
                           break;

                        case '?':         /* display commands */
                           kwrite(1,"\r\lArguments available:\r\l\l",0);
                           kwrite(1,"? - Show this help message\r\l",0);
                           kwrite(1,"0 - Transmit NULL\r\l",0);
                           kwrite(1,"b - Transmit 'BREAK'\r\l",0);
                           kwrite(1,"c - Close connection\r\l",0);
                           kwrite(1,"h - Report availability\r\l",0);
                           kwrite(1,"q - Quit logging (if started)\r\l",0);
                           kwrite(1,"r - Resume logging\r\l",0);
                           kwrite(1,"s - Show status of connection\r\l",0);
                           break;

                        default:
                           write(ttyfd,&c,1);  /* write it out */
                           if (!fulldup)
                           {
                              write(1,&c,1);   /* to console if half duplex */
                              write_log(c);    /* send to logfile */
                           }
                           break;
                  }
               }
            }
            else
            {
               write(ttyfd,&c,1);              /* write it out */
               if (!fulldup)
               {
                  write(1,&c,1);               /* to console if half duplex */
                  write_log(c);                /* send to logfile */
               }
            }
         }
         kill(pid,SIGKILL);                    /* Done, kill the child */
         wait(0);
         if (numprm > 1)
            close_port(FALSE,TRUE);     /* Real close for commandline port */
         else
            close_port(FALSE,FALSE);
         fputs("Disconnected.\n",stdout);
         strcpy(tty_descr,save_descr);         /* Restore old port */
         return;
      }
      else
      {
         setjmp(child_env);                /* Re-enter here after interrupt */
         signal(12,toglog);
         while(TRUE)
         {
            read(ttyfd,&c,1);              /* get character */
            write(1,&c,1);                 /* send to local screen */
            write_log(c);                  /* and to logfile */
         }
      }
   }
}

toglog()
{
   if (logging)
      logging = FALSE;                         /* Toggle logging flag */
   else
      logging = TRUE;
   longjmp(child_env,0);                       /* Start again */
}

/*
 * Write data to log file
 */

write_log(chr)
char chr;
{
   if (logging && logfileopen && chr != CR)
   {
      if (chr == LF)                         /* convert LF to CR */
         chr = CR;
      if ((putc(chr, lfp) == EOF) && (chr != 0xff)) /* write to file */
      {
         prterr(ER_LOGWRTER);                /* Log file write error */
         fclose(lfp);
         logging = logfileopen = FALSE;      /* no more logging */
         logfile[0] = '\0';                  /* Zap filename */
      }
   }
}
