/***************************************************************************
 *                                                                         *
 *   GALICOIN.C                                                            *
 *                                                                         *
 *   Copyright (c) 1995-1997 Galacticomm, Inc.  All rights reserved.       *
 *                                                                         *
 *   This utility installs and configures necessary elements for the       *
 *   proper operation of ICO V2.0.                                         *
 *                                                                         *
 *                                           - C. Dunn  9/12/95            *
 *                                                                         *
 *   Changes for SLIP-to-ISP support.                                      *
 *                                                                         *
 *                                           - C. Dunn  1/31/96            *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "process.h"
#include "errno.h"
#include "datstm.h"

#pragma inline

#define PKTIDT "PKT DRVR"          /* packet driver identifier             */
#define LSLIDT "LINKSUP$"          /* LSL loaded identifier                */
#define FLGFIL "GALICOIN.FLG"      /* flag file for successful install     */
#define MSGDNS "GALDNS.MSG"        /* GALDNS.MSG file name                 */
#define MSGFTP "GALFTP.MSG"        /* GALFTP.MSG file name                 */
#define MSGSLP "GALSLISP.MSG"      /* GALSLISP.MSG file name               */
#define MSGTCP "GALTCPIP.MSG"      /* GALTCPIP.MSG file name               */
#define MSGBBS "WGSMAJOR.MSG"      /* BBSMAJOR.MSG file name               */
#define MSGWEB "GALWEBD.MSG"       /* GALWEBD.MSG file name                */
#define ETHER2 "ETHERNET_II"       /* Frame/envelope type for TCP/IP       */
#define APPLST "GALINTAP.LST"      /* list file containing internet apps   */
#define INTRUN "wgsint.run"        /* file to trigger WGSINT to run again  */
#define DMDEXT ".DMD"              /* disabled module extension            */
#define BAKEXT ".BAK"              /* backup file name extension           */
#define PKTLEN 8                   /* packet driver identifier length      */
#define LSLLEN 8                   /* LSL identifier length                */
#define LSLVCT 0x2F                /* LSL interrupt vector                 */
#define TCPLEN 16                  /* maximum length of TCP/IP addr        */
#define PVCLEN 5                   /* maximum length of pkt vector         */
#define HSTLEN 19                  /* maximum length of host name          */
#define DMNLEN 40                  /* maximum length of domain name        */
#define MAXPKT 5                   /* max. no. of packet drivers installed */
#define YNOLEN 4                   /* maximum length of yes/no answer      */
#define NUMSCN 8                   /* number of screen image files used    */
#define MAXDVR 5                   /* max number of link drivers supported */
#define TYPLEN 12                  /* max. length of ISP connection type   */
#define FNMLEN (8+1+3+1)           /* file name length (w/extension and 0) */
#define PRTLEN 6                   /* maximum length of ISP protocol       */
#define PHOLEN 16                  /* maximum length of ISP phone number   */
#define NAMLEN 35                  /* maximum length of ISP account name   */
#define PSWLEN 10                  /* maximum length of ISP acct password  */
#define CHNLEN 3                   /* maximum length of channel number     */

                                   /* edtval() field indexes (IP config)   */
#define IPAFLD 0                   /*   asking for system IP address       */
#define NETFLD 1                   /*   asking for system net mask         */
#define HSTFLD 2                   /*   asking for system host name        */
#define DMNFLD 3                   /*   asking for system domain name      */
#define IPRFLD 4                   /*   asking for router IP address       */
#define IPNFLD 5                   /*   asking for name server IP address  */
#define SAVFLD 6                   /*   asking to save/abort installation  */

                                   /* edtval() field indexes (Script)      */
#define PRTFLD 0                   /*   asking for protocol                */
#define CHNFLD 1                   /*   asking for channel number          */
#define PHOFLD 2                   /*   asking for ISP phone number        */
#define NAMFLD 3                   /*   asking for account name            */
#define PSWFLD 4                   /*   asking for account password        */

struct lslent {                    /* LSL entry points                     */
     VOID (*pspapi)(VOID);         /*   protocol support API entry point   */
     VOID (*genapi)(VOID);         /*   general services API entry point   */
} lslent;

static INT brdnum;                 /* board number for odipkt parameter    */
static INT curfld;                 /* current field being edited           */
static INT drvidx;                 /* link driver index                    */
static INT intnum[MAXPKT];         /* array of packet vector interrupts    */
static INT numpkt;                 /* number of packet drivers found       */
static INT srvchn;                 /* server channel for ISP connection    */

static GBOOL hasodi;                /* is ODI being used on this machine?   */
static GBOOL newins;                /* is this a new ICO installation?      */
static GBOOL lan2isp;               /* are we connecting to ISP via LAN?    */

static CHAR cfgpth[GCMAXPTH];      /* full path for NET.CFG file           */
static CHAR cfgbak[GCMAXPTH];      /* full path for NET.BAK file if needed */
static CHAR savscn[GVIDSCNSIZ];    /* DOS image save area                  */
static CHAR icoscn[GVIDSCNSIZ];    /* install program image save area      */
static CHAR pktvec[PVCLEN];        /* packet vector used                   */
static CHAR ipadr[TCPLEN];         /* system IP address                    */
static CHAR netmsk[TCPLEN];        /* system netmask                       */
static CHAR iprout[TCPLEN];        /* router IP address                    */
static CHAR hstnam[HSTLEN];        /* host name of Worldgroup machine      */
static CHAR ipnsvr[TCPLEN];        /* name server IP address               */
static CHAR domain[DMNLEN];        /* system domain name                   */
static CHAR yesno[YNOLEN];         /* yes/no answer for installation       */
static CHAR *pktchc[MAXPKT];       /* array of packet drivers for choose() */
static CHAR *drvchc[MAXDVR];       /* array of link drivers for choose()   */
static CHAR inbuf[BUFSIZ];         /* general purpose file input buffer    */
static CHAR contyp[TYPLEN];        /* connection type to ISP               */
static CHAR ispprt[PRTLEN];        /* protocol method for ISP              */
static CHAR isppho[PHOLEN];        /* ISP dial-up phone number             */
static CHAR ispnam[NAMLEN];        /* ISP account name                     */
static CHAR isppsw[PSWLEN];        /* ISP account password                 */
static CHAR ispchn[CHNLEN];        /* channel number to connect with ISP   */
static CHAR scrfnm[GCMAXPTH];      /* script file name                     */
static CHAR scrtmp[]={             /* script file template                 */
     ";\n"
     "; Script used for dialing Internet Service Provider.\n"
     ";\n"
     "USER ON\n"
     "TRACE OFF\n"
     "CASE IGNORE\n"
     "LOG GALSLISP.LOG\n"
     ";\n"
     "; Dial the number\n"
     ";\n"
     "TIMEOUT 60\n"
     "SEND ATDT %s^M\n"
     ";\n"
     "; Enter User-ID\n"
     ";\n"
     "WATCH 1 MBUSY  BUSY\n"
     "WATCH 2 MNOANS NO ANSWER\n"
     "WATCH 3 USERID Username\n"
     "WATCH 4 USERID login\n"
     "WAITFOR        User-ID\n"
     ":USERID\n"
     "WATCH 1\n"
     "WATCH 2\n"
     "WATCH 3\n"
     "WATCH 4\n"
     "TIMEOUT 30\n"
     "SEND %s^M\n"
     ";\n"
     "; Enter password\n"
     ";\n"
     "WATCH 1 UINVAL no such\n"
     "WATCH 2 UALRDY already\n"
     "WAITFOR        password\n"
     "WATCH 1\n"
     "WATCH 2\n"
     "TIMEOUT 30\n"
     "SEND %s^M\n"
     ";\n"
     "; Begin session\n"
     ";\n"
     "WATCH 1 PINVAL incorrect\n"
     "WATCH 2 LINVAL login\n"
     "WATCH 3 LINVAL Username\n"
     "WATCH 4 UACCSS don't have access\n"
     "WATCH 5 ONLINE Entering\n"
     "WATCH 6 ONLINE Starting\n"
     "WAITFOR        Beginning\n"
     ":ONLINE\n"
     "WATCH 1\n"
     "WATCH 2\n"
     "WATCH 3\n"
     "WATCH 4\n"
     "WATCH 5\n"
     "WATCH 6\n"
     "PAUSE 1\n"
     "EXIT\n"
     ";\n"
     "; Error conditions\n"
     ";\n"
     ":MBUSY\n"
     "ERROR ISP line is busy!\n"
     "\n"
     ":MNOANS\n"
     "ERROR ISP line is not answering!\n"
     "\n"
     ":UINVAL\n"
     "ERROR No such USER-ID!\n"
     "\n"
     ":PINVAL\n"
     "ERROR Incorrect Password!\n"
     "\n"
     ":LINVAL\n"
     "ERROR Not accepting User-ID and Password!\n"
     "\n"
     ":UALRDY\n"
     "ERROR User is already online!\n"
     "\n"
     ":UACCSS\n"
     "ERROR User doesn't have access!\n"
};

static VOID (*lslihdl)(VOID);      /* LSL init handler                     */

extern CHAR scntbl[][GVIDSCNSIZ];      /* array of images via makescns         */

static VOID getcpth(VOID);
static CHAR *msscan(CHAR *msgfil,CHAR *vblnam);
static CHAR *mtscan(CHAR *msgfil,CHAR *vblnam,INT maxsiz);
static VOID rstimg(VOID);
static VOID shtdwn(GBOOL instok);
static VOID getival(VOID);
static VOID dspival(VOID);
static GBOOL chkvalc(VOID);
static VOID savinf(VOID);
static GBOOL ipval(INT c,CHAR *stg);
static GBOOL nipval(INT c,CHAR *stg);
static GBOOL hdmval(INT c,CHAR *stg);
static GBOOL isipadr(CHAR *addr);
static VOID escabt(VOID);
static VOID updncfg(VOID);
static GBOOL conval(INT c,CHAR *stg);
static VOID disint(VOID);
static VOID cfglan(VOID);
static VOID cfgpho(VOID);
static VOID movweb(VOID);
static GBOOL prtval(INT c,CHAR *stg);
static GBOOL phoval(INT c,CHAR *stg);
static GBOOL namval(INT c,CHAR *stg);
static GBOOL chnval(INT c,CHAR *stg);
static VOID savscr(VOID);
static VOID dispsval(VOID);
static GBOOL chksvlc(VOID);
static VOID enaint(VOID);

CHAR *substi(CHAR *filein,CHAR *fileout,INT nchgs,CHAR *tobechgd[],
     CHAR *chgemto[]);

INT
main(                              /* main program loop                    */
INT argc,
CHAR *argv[])
{
     INT i;
     CHAR *ivect;
     GBOOL editng;

     initvid();
     if (argc > 1 && sameas(argv[1],"movweb")) {
          movweb();
          clsvid();
          return(0);
     }
     if (argc > 1 && sameas(argv[1],"disint")) {
          disint();
          clsvid();
          return(0);
     }
     if (argc > 1 && sameas(argv[1],"enaint")) {
          enaint();
          clsvid();
          return(0);
     }
     cursiz(GVIDNOCURS);
     scn2mem(savscn,0,GVIDSCNSIZ);
     imonorcol();
     for (i=0 ; i < NUMSCN ; i++) {
          cvtscn(scntbl[i]);
     }
     explodem=FALSE;
     explodeto(scntbl[4],0,0,79,24,0,0);
     explodem=TRUE;
     scn2mem(icoscn,0,GVIDSCNSIZ);
     for (i=0x20,numpkt=0 ; i < 0xFF ; i++) {
          ivect=(CHAR *)getvect(i);
          if (memcmp(PKTIDT,ivect+3,PKTLEN) == 0) {
               pktchc[numpkt]=alcdup(spr("The packet driver at INT 0x%02X ",i));
               intnum[numpkt]=i;
               numpkt++;
          }
          if (numpkt == MAXPKT) {
               break;
          }
     }
     explodeto(scntbl[2],0,15,64,23,7,8);
     strcpy(contyp,"ETHERNET");
     if (!edtval(44,7,TYPLEN,contyp,conval,USEPOFF+MCHOICE)) {
          shtdwn(FALSE);
     }
     if (sameas(contyp,"NONE")) {
          disint();
          rstimg();
          explodeto(scntbl[6],0,0,57,5,10,8);
          getchc();
          shtdwn(FALSE);
     }
     if (sameas(contyp,"ETHERNET")) {
          lan2isp=TRUE;
          enaint();
          getcpth();
          getival();
          cfglan();
     }
     else {
          lan2isp=FALSE;
          enaint();
          getival();
          cfgpho();
     }
     rstimg();
     if (newins) {
          explodeto(scntbl[1],0,0,69,14,4,8);
     }
     else {
          explodeto(scntbl[5],0,0,69,14,4,8);
     }
     dspival();
     curfld=IPAFLD;
     editng=TRUE;
     while (editng) {
          switch (curfld) {
          case IPAFLD:
               edtval(29,6,TCPLEN,ipadr,ipval,USEPOFF+MULTIEX);
               chkvalc();
               break;
          case NETFLD:
               edtval(29,7,TCPLEN,netmsk,nipval,USEPOFF+MULTIEX+ALLCAPS);
               chkvalc();
               break;
          case HSTFLD:
               edtval(29,8,HSTLEN,hstnam,hdmval,USEPOFF+MULTIEX);
               chkvalc();
               break;
          case DMNFLD:
               edtval(29,9,DMNLEN,domain,hdmval,USEPOFF+MULTIEX);
               chkvalc();
               break;
          case IPRFLD:
               edtval(29,10,TCPLEN,iprout,ipval,USEPOFF+MULTIEX);
               chkvalc();
               break;
          case IPNFLD:
               edtval(29,11,TCPLEN,ipnsvr,ipval,USEPOFF+MULTIEX);
               chkvalc();
               break;
          case SAVFLD:
               edtval(29,12,YNOLEN,yesno,validyn,USEPOFF+MCHOICE+MULTIEX);
               if (chkvalc()) {
                    editng=FALSE;
                    if (sameas(yesno,"YES")) {
                         savinf();
                         shtdwn(TRUE);
                    }
                    else {
                         escabt();
                    }
               }
               break;
          }
     }
     clsvid();
     return(0);
}

static VOID
getcpth(VOID)                      /* get full path to NET.CFG file        */
{
     INT slot;
     union REGS regs;
     struct SREGS sregs;

     if (getvect(LSLVCT) == NULL) {
          hasodi=FALSE;
          return;
     }
     for (slot=0xC0 ; slot <= 0xFF ; slot++) {
          regs.h.ah=slot;
          regs.h.al=0;
          segread(&sregs);
          int86x(LSLVCT,&regs,&regs,&sregs);
          if (regs.h.al == 0xFF
           && memcmp(MK_FP(sregs.es,regs.x.si),LSLIDT,LSLLEN) == 0) {
               break;
          }
     }
     if (slot > 0xFF) {
          hasodi=FALSE;
          return;
     }
     lslihdl=(VOID (*)(VOID))MK_FP(regs.x.dx,regs.x.bx);
     asm  push ds
     asm  push ds
     asm  pop  es
     asm  mov  si,offset lslent
     asm  mov  bx,2
     asm  call dword ptr [lslihdl]
     asm  pop  ds
     asm  push ds
     asm  mov  bx,7
     asm  call dword ptr [lslent.genapi]
     asm  mov  ax,ds
     asm  pop  ds
     stlcpy(cfgpth,(CHAR *)MK_FP(_AX,_DX),GCMAXPTH);
     stlcpy(cfgbak,cfgpth,GCMAXPTH);
     hasodi=TRUE;
}

static CHAR *                      /*   return "" instead of NULL on error */
msscan(                            /* our own flavor of msgscan()          */
CHAR *msgfil,                      /*   .MSG file to search                */
CHAR *vblnam)                      /*   variable name to search for        */
{
     CHAR *retbuf;

     if ((retbuf=msgscan(msgfil,vblnam)) != NULL) {
          return(retbuf);
     }
     return("");
}

static CHAR *                      /*   return "" instead of NULL on error */
mtscan(                            /* our own flavor of mstscan()          */
CHAR *msgfil,                      /*   .MSG file to search                */
CHAR *vblnam,                      /*   variable name to search for        */
INT maxsiz)                        /*   maximum length of variable content */
{
     CHAR *retbuf;

     if ((retbuf=mstscan(msgfil,vblnam,maxsiz)) != NULL) {
          return(retbuf);
     }
     return("");
}

static VOID
rstimg(VOID)                       /* restore original DOS screen image    */
{
     mem2scn(icoscn,0,GVIDSCNSIZ);
}

static VOID
shtdwn(                            /* shutdown installation process        */
GBOOL instok)                       /*   was installation completed OK?     */
{
     if (instok) {
#         ifdef ICOBLD
               rstimg();
               explodeto(scntbl[2],0,0,54,7,12,8);
               getchc();
#         endif
          if (hasodi && lan2isp) {
               rstimg();
               explodeto(scntbl[5],0,15,48,23,15,8);
               getchc();
          }
          rstimg();
          explodeto(scntbl[0],0,10,35,14,21,8);
          getchc();
     }
     movweb();
     mem2scn(savscn,0,GVIDSCNSIZ);
     locate(0,24);
     cursiz(GVIDLILCURS);
     clsvid();
     exit(0);
}

static VOID
getival(VOID)                      /* get initial values for .MSG options  */
{
     stlcpy(hstnam,mtscan(MSGDNS,"HOSTNAM",HSTLEN),HSTLEN);
     stlcpy(ipnsvr,mtscan(MSGDNS,"IPNSVR",TCPLEN),TCPLEN);
     stlcpy(domain,mtscan(MSGDNS,"DOMAIN",DMNLEN),DMNLEN);
     stlcpy(scrfnm,mtscan(MSGSLP,"SCRFNM",GCMAXPTH),GCMAXPTH);
     stlcpy(ispchn,msscan(MSGSLP,"ISPCHAN"),CHNLEN);
     stlcpy(pktvec,mtscan(MSGTCP,hasodi ? "ODIVEC" : "PKTVEC",PVCLEN),PVCLEN);
     stlcpy(ipadr,mtscan(MSGTCP,"IPADDR",TCPLEN),TCPLEN);
     stlcpy(netmsk,mtscan(MSGTCP,"NETMASK",TCPLEN),TCPLEN);
     stlcpy(iprout,mtscan(MSGTCP,"IPROUT",TCPLEN),TCPLEN);
     stlcpy(ispprt,msscan(MSGTCP,"IMETH"),PRTLEN);
     stlcpy(yesno,"Yes",YNOLEN);
     newins=((ipadr[0] == '\0' || !isipadr(ipadr))
         || (lan2isp
          && (netmsk[0] == '\0' || (!isipadr(netmsk)
                                && !sameas(netmsk,"AUTO"))))
         || (lan2isp && (iprout[0] == '\0' || !isipadr(iprout)))
         || (ipnsvr[0] == '\0' || !isipadr(ipnsvr))
         || hstnam[0] == '\0'
         || domain[0] == '\0');
     if (!newins) {
          if (!isipadr(ipadr)) {
               ipadr[0]='\0';
          }
          if (!lan2isp || (!sameas(netmsk,"AUTO") && !isipadr(netmsk))) {
               netmsk[0]='\0';
          }
          if (!lan2isp || !isipadr(iprout)) {
               iprout[0]='\0';
          }
          if (!isipadr(ipnsvr)) {
               ipnsvr[0]='\0';
          }
     }
}

static VOID
dspival(VOID)                      /* display initial values for .MSG opts */
{
     CHAR notreq[]="(not required for phone connection)";

     setatr(0x1E);
     prat(29,6,"%s",ipadr);
     if (lan2isp) {
          prat(29,7,"%s",netmsk);
     }
     else {
          setatr(0x13);
          prat(29,7,"%-39.39s",notreq);
          setatr(0x1E);
     }
     prat(29,8,"%s",hstnam);
     prat(29,9,"%s",domain);
     if (lan2isp) {
          prat(29,10,"%s",iprout);
     }
     else {
          setatr(0x13);
          prat(29,10,"%-39.39s",notreq);
          setatr(0x1E);
     }
     prat(29,11,"%s",ipnsvr);
     prat(29,12,"%s",yesno);
}

static GBOOL
chkvalc(VOID)                      /* check/act on edtvalc character       */
{
     switch (edtvalc) {
     case CRSRDN:
     case TAB:
     case 10:
     case 13:
          switch (curfld) {
          case IPAFLD:
               if (!isipadr(ipadr)) {
                    ipadr[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=(lan2isp ? NETFLD : HSTFLD);
               }
               return(TRUE);
          case NETFLD:
               if (!sameas(netmsk,"AUTO") && !isipadr(netmsk)) {
                    netmsk[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=HSTFLD;
               }
               return(TRUE);
          case HSTFLD:
               if (hstnam[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=DMNFLD;
               }
               return(TRUE);
          case DMNFLD:
               if (domain[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=(lan2isp ? IPRFLD : IPNFLD);
               }
               return(TRUE);
          case IPRFLD:
               if (!isipadr(iprout)) {
                    iprout[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=IPNFLD;
               }
               return(TRUE);
          case IPNFLD:
               if (!isipadr(ipnsvr)) {
                    ipnsvr[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=SAVFLD;
               }
               return(TRUE);
          case SAVFLD:
               if (edtvalc == TAB || edtvalc == CRSRDN) {
                    curfld=IPAFLD;
                    return(FALSE);
               }
               return(TRUE);
          }
          break;
     case CRSRUP:
     case BAKTAB:
          switch (curfld) {
          case IPAFLD:
               if (!isipadr(ipadr)) {
                    ipadr[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=SAVFLD;
               }
               return(TRUE);
          case NETFLD:
               if (!sameas(netmsk,"AUTO") && !isipadr(netmsk)) {
                    netmsk[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=IPAFLD;
               }
               return(TRUE);
          case HSTFLD:
               if (hstnam[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=(lan2isp ? NETFLD : IPAFLD);
               }
               return(TRUE);
          case DMNFLD:
               if (domain[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=HSTFLD;
               }
               return(TRUE);
          case IPRFLD:
               if (!isipadr(iprout)) {
                    iprout[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=DMNFLD;
               }
               return(TRUE);
          case IPNFLD:
               if (!isipadr(ipnsvr)) {
                    ipnsvr[0]='\0';
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=(lan2isp ? IPRFLD : DMNFLD);
               }
               return(TRUE);
          case SAVFLD:
               curfld=IPNFLD;
               return(FALSE);
          }
          return(TRUE);
     case ESC:
          escabt();
          return(TRUE);
     }
     return(TRUE);
}

static VOID
savinf(VOID)                       /* save information into .MSG files     */
{
     setcnf("ISPCHAN",ispchn);
     setcnf("SCRFNM",scrfnm);
     applyem(MSGSLP);
     setcnf("IMETH",lan2isp ? "ETHER" : ispprt);
     setcnf(hasodi ? "ODIVEC" : "PKTVEC",pktvec);
     setcnf("IPADDR",ipadr);
     setcnf("NETMASK",netmsk);
     setcnf("IPROUT",iprout);
     applyem(MSGTCP);
     setcnf("HOSTNAM",hstnam);
     setcnf("IPNSVR",ipnsvr);
     setcnf("DOMAIN",domain);
     applyem(MSGDNS);
     setcnf("MAILDMN",domain);
     applyem(MSGFTP);
}

static GBOOL
ipval(                             /* IP address validation routine        */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return((c >= '0' && c <= '9') || c == '.');
}

static GBOOL
nipval(                            /* netmask IP address validation rou.   */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return((c >= '0' && c <= '9')
         || c == '.'
         || c == 'a'
         || c == 'u'
         || c == 't'
         || c == 'o'
         || c == 'A'
         || c == 'U'
         || c == 'T'
         || c == 'O');
}

static GBOOL
hdmval(                            /* host/domain name validation routine  */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return(c >= 32 && c <= 255);
}

static GBOOL
isipadr(                           /* is this a valid IP address?          */
CHAR *addr)
{
     INT i,j,len;
     CHAR *ptr,*secptr,savadr[TCPLEN];

     stlcpy(savadr,addr,TCPLEN);
     for (i=0,ptr=savadr ; ptr != NULL ; i++,ptr=secptr) {
          if ((secptr=strchr(ptr,'.')) != NULL) {
               *secptr++='\0';
          }
          if ((len=strlen(ptr)) > 3 || len == 0) {
               return(FALSE);
          }
          for (j=0 ; j < len ; j++) {
               if (!isdigit(ptr[j])) {
                    return(FALSE);
               }
          }
          if (atoi(ptr) > 255) {
               return(FALSE);
          }
     }
     if (i == 4) {
          return(TRUE);
     }
     return(FALSE);
}

static VOID
escabt(VOID)                       /* abort installation: user hit ESC     */
{
     rstimg();
     if (newins) {
          explodeto(scntbl[0],0,15,48,24,15,8);
     }
     else {
          explodeto(scntbl[1],0,15,48,21,15,8);
     }
     getchc();
     shtdwn(FALSE);
}

static VOID
updncfg(VOID)                      /* update NET.CFG file if necessary     */
{
     CHAR *ptr;
     LONG oldpos;
     FILE *bakfp,*cfgfp;
     INT bufarg1,bufarg2,dvrchc;
     GBOOL gahead,gotbuf,gotlsp,gotfrm;

     if ((ptr=strrchr(cfgbak,'.')) != NULL) {
          *ptr='\0';
          stlcat(cfgbak,".BAK",GCMAXPTH);
     }
     unlink(cfgbak);
     if (rename(cfgpth,cfgbak) == -1) {
          return;
     }
     if ((bakfp=fopen(cfgbak,FOPRA)) != NULL
      && (cfgfp=fopen(cfgpth,FOPWA)) != NULL) {
          gotlsp=FALSE;
          brdnum=-1;
          drvidx=0;
          while (fgets(inbuf,BUFSIZ,bakfp) != NULL) {
               oldpos=ftell(bakfp);
               if (sameto("Link Support",inbuf)) {
                    gotlsp=TRUE;
                    gahead=TRUE;
                    gotbuf=FALSE;
                    fprintf(cfgfp,"%s",inbuf);
                    do {
                         oldpos=ftell(bakfp);
                         if (fgets(inbuf,BUFSIZ,bakfp) == NULL
                          || !isspace(inbuf[0])) {
                              fseek(bakfp,oldpos,SEEK_SET);
                              gahead=FALSE;
                         }
                         else {
                              ptr=skptwht(inbuf);
                              if (sameto("Buffers",ptr)) {
                                   gotbuf=TRUE;
                                   if (sscanf(skptwht(ptr+7),"%d %d",
                                              &bufarg1,&bufarg2) != 2) {
                                        fprintf(cfgfp,"     Buffers 6 1600\n");
                                   }
                                   else {
                                        if (bufarg1 < 6) {
                                             bufarg1=6;
                                        }
                                        if (bufarg2 < 1600) {
                                             bufarg2=1600;
                                        }
                                        fprintf(cfgfp,"     Buffers %d %d\n",
                                                bufarg1,bufarg2);
                                   }
                              }
                              else {
                                   fprintf(cfgfp,"%s\n",inbuf);
                              }
                         }
                    } while (gahead && !gotbuf);
               }
               else if (drvidx != MAXDVR
                && sameto("Link Driver",inbuf)) {
                    drvchc[drvidx++]=alcdup(spr("The link driver for %s ",
                                            lastwd(inbuf)));
                    gahead=TRUE;
                    gotfrm=FALSE;
                    fprintf(cfgfp,"%s",inbuf);
                    do {
                         oldpos=ftell(bakfp);
                         if (fgets(inbuf,BUFSIZ,bakfp) == NULL
                          || !isspace(inbuf[0])) {
                              gahead=FALSE;
                              fseek(bakfp,oldpos,SEEK_SET);
                         }
                         else {
                              ptr=skptwht(inbuf);
                              if (sameto("Frame",ptr)
                               || sameto("Envelope type",ptr)) {
                                   if (!gotfrm) {
                                        brdnum++;
                                   }
                                   if (samend(unpad(ptr),ETHER2)) {
                                        gotfrm=TRUE;
                                   }
                                   fprintf(cfgfp,"%s\n",inbuf);
                              }
                              else if (gahead) {
                                   fprintf(cfgfp,"%s",inbuf);
                              }
                         }
                    } while (gahead);
               }
               else {
                    fprintf(cfgfp,"%s",inbuf);
               }
          }
          if (!gotlsp) {
               fseek(cfgfp,0L,SEEK_END);
               fprintf(cfgfp,"\nLink Support\n");
               fprintf(cfgfp,"     Buffers 6 1600\n");
          }
          fclose(bakfp);
          fclose(cfgfp);
          if (!gotfrm) {
               if ((ptr=strrchr(cfgbak,'.')) != NULL) {
                    *ptr='\0';
                    stlcat(cfgbak,".$$$",GCMAXPTH);
               }
               unlink(cfgbak);
               if (rename(cfgpth,cfgbak) == -1) {
                    return;
               }
               if ((bakfp=fopen(cfgbak,FOPRA)) != NULL
                && (cfgfp=fopen(cfgpth,FOPWA)) != NULL) {
                    brdnum=-1;
                    if (drvidx > 1) {
                         rstimg();
                         explodeto(scntbl[3],0,12,48,23,15,8);
                         setatr(0x1E);
                         prat(18,2,"%d",drvidx);
                         if ((dvrchc=choose(drvidx,drvchc,10,5,
                           37,4+drvidx,TRUE)) == -ESC) {
                              escabt();
                         }
                         else {
                              dvrchc++;
                         }
                    }
                    else {
                         dvrchc=1;
                    }
                    drvidx=0;
                    while (fgets(inbuf,BUFSIZ,bakfp) != NULL) {
                         gahead=TRUE;
                         if (sameto("Link Driver",inbuf)) {
                              fprintf(cfgfp,"%s",inbuf);
                              do {
                                   if (sameto("Link Driver",inbuf)) {
                                        drvidx++;
                                   }
                                   if (fgets(inbuf,BUFSIZ,bakfp) == NULL
                                    || inbuf[0] == '\0') {
                                        gahead=FALSE;
                                        if (!gotfrm) {
                                             brdnum++;
                                             fprintf(cfgfp,"     Frame %s\n",
                                                     ETHER2);
                                        }
                                   }
                                   else if ((!isspace(inbuf[0])
                                    || strlen(inbuf) <= 1)
                                    && drvidx == dvrchc) {
                                        gahead=FALSE;
                                        gotfrm=TRUE;
                                        brdnum++;
                                        fprintf(cfgfp,"     Frame %s\n",
                                                ETHER2);
                                        fprintf(cfgfp,"%s",inbuf);
                                   }
                                   else {
                                        ptr=skptwht(inbuf);
                                        if ((sameto("Frame",ptr)
                                         || sameto("Envelope type",ptr))
                                         && !gotfrm) {
                                             brdnum++;
                                        }
                                        fprintf(cfgfp,"%s",inbuf);
                                   }
                              } while (gahead);
                         }
                         else {
                              fprintf(cfgfp,"%s",inbuf);
                         }
                    }
                    fclose(cfgfp);
                    fclose(bakfp);
                    unlink(cfgbak);
               }
          }
     }
}

static GBOOL
conval(                            /* edtval() valrou for connection type  */
INT c,
CHAR *stg)
{
     switch (toupper(c)) {
     case ' ':
          switch (toupper(stg[0])) {
          case 'E':
               strcpy(stg,"PHONE LINE");
               break;
          case 'P':
               strcpy(stg,"NONE");
               break;
          case 'N':
               strcpy(stg,"ETHERNET");
               break;
          }
          break;
     case 'E':
          strcpy(stg,"ETHERNET");
          break;
     case 'P':
          strcpy(stg,"PHONE LINE");
          break;
     case 'N':
          strcpy(stg,"NONE");
          break;
     default:
          belper(800);
          printf("\7");
          break;
     }
     return(FALSE);
}

static VOID
disint(VOID)                       /* disables all Internet applications   */
{
     FILE *lstfp;
     CHAR *ptr,dmdnam[FNMLEN];

     if ((lstfp=fopen(APPLST,FOPRA)) == NULL) {
          catastro("Error opening GALINTAP.LST for input!");
     }
     while (fgets(inbuf,BUFSIZ,lstfp) != NULL) {
          depad(inbuf);
          stlcpy(dmdnam,inbuf,FNMLEN);
          if ((ptr=strrchr(dmdnam,'.')) != NULL) {
               *ptr='\0';
               stlcat(dmdnam,DMDEXT,FNMLEN);
          }
          if (access(dmdnam,0) != -1 && access(inbuf,0) != -1) {
               unlink(inbuf);
          }
          else {
               rename(inbuf,dmdnam);
          }
     }
     fclose(lstfp);
     if ((lstfp=fopen(INTRUN,FOPWA)) != NULL) {
          fprintf(lstfp,"Run it again!\n");
          fclose(lstfp);
     }
}

static VOID
cfglan(VOID)                       /* configure LAN setup parameters       */
{
     if (hasodi) {
          rstimg();
          explodeto(scntbl[2],0,8,53,14,12,8);
          if (getchc() == ESC) {
               escabt();
          }
          updncfg();
     }
     if (numpkt == 0) {
          if (!hasodi) {
               rstimg();
               explodeto(scntbl[0],0,0,45,9,16,8);
               getchc();
               shtdwn(FALSE);
          }
          else {
               setcnf("ETHMETH","ODI");
               setcnf("ODIVEC","69");
               setcnf("ODIBRD",spr("%d",brdnum));
          }
     }
     else if (numpkt > 1) {
          rstimg();
          explodeto(scntbl[3],0,0,50,11,14,8);
          setatr(0x1E);
          prat(22,1,"%d",numpkt);
          if (hasodi && brdnum != -1) {
               setcnf("ETHMETH","ODI");
               setcnf("ODIBRD",spr("%d",brdnum));
          }
          else {
               setcnf("ETHMETH","PACKET");
          }
          switch (choose(numpkt,pktchc,10,5,38,4+numpkt,TRUE)) {
          case 0:
               setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[0]));
               break;
          case 1:
               setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[1]));
               break;
          case 2:
               setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[2]));
               break;
          case 3:
               setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[3]));
               break;
          case 4:
               setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[4]));
               break;
          case -ESC:
               escabt();
               break;
          }
     }
     else {
          setcnf(hasodi ? "ODIVEC" : "PKTVEC",spr("%02X",intnum[0]));
          if (hasodi && brdnum != -1) {
               setcnf("ETHMETH","ODI");
               setcnf("ODIBRD",spr("%d",brdnum));
          }
          else {
               setcnf("ETHMETH","PACKET");
          }
     }
     applyem(MSGTCP);
}

static VOID
cfgpho(VOID)                       /* configure phone line method setup    */
{
     GBOOL editng;
     INT nchans;

     rstimg();
     explodeto(scntbl[7],0,17,50,24,14,7);
     getchc();
     rstimg();
     if (sameas(ispprt,"ETHER") || ispprt[0] == '\0') {
          stlcpy(ispprt,"PPP",PRTLEN);
     }
     strcpy(yesno,"Yes");
     explodeto(scntbl[6],0,9,66,21,6,8);
     editng=TRUE;
     curfld=PRTFLD;
     dispsval();
     while (editng) {
          switch (curfld) {
          case PRTFLD:
               edtval(25,5,PRTLEN,ispprt,prtval,USEPOFF+MCHOICE+MULTIEX);
               chksvlc();
               break;
          case CHNFLD:
               edtval(25,6,CHNLEN,ispchn,chnval,USEPOFF+ALLCAPS+MULTIEX);
               chksvlc();
               break;
          case PHOFLD:
               edtval(25,7,PHOLEN,isppho,phoval,USEPOFF+ALLCAPS+MULTIEX);
               chksvlc();
               break;
          case NAMFLD:
               edtval(25,8,NAMLEN,ispnam,namval,USEPOFF+MULTIEX);
               chksvlc();
               break;
          case PSWFLD:
               edtval(25,9,PSWLEN,isppsw,namval,USEPOFF+MULTIEX);
               chksvlc();
               break;
          case SAVFLD:
               edtval(25,10,YNOLEN,yesno,validyn,USEPOFF+MCHOICE+MULTIEX);
               if (chksvlc()) {
                    editng=FALSE;
                    if (sameas(yesno,"YES")) {
                         savscr();
                         if (getchc() == ESC) {
                              escabt();
                         }
                         if (sameas(msscan(MSGBBS,"GROUP1"),"TCP/IP")) {
                              nchans=atoi(msscan(MSGBBS,"NUMBR1"));
                              if (nchans == 8 || nchans == 2) {
                                   setcnf("NUMBR1",spr("%d",nchans-1));
                                   applyem(MSGBBS);
                              }
                         }
                    }
                    else {
                         escabt();
                    }
               }
               break;
          }
     }
}

static VOID
movweb(VOID)                       /* move web pages from NEWPAGES         */
{
     CHAR *host,*domain,*retval;
     struct ffblk fb;
     static CHAR *olddom[]={"<domain name>"};
     static CHAR *newdom[1];
     CHAR webdir[GCMAXPTH];
     CHAR *webptr;

     if (*(host=mtscan(MSGDNS,"HOSTNAM",HSTLEN)) == '\0') {
          return;
     }
     host=alcdup(host);
     if (*(domain=mtscan(MSGDNS,"DOMAIN",DMNLEN)) == '\0') {
          free(host);
          return;
     }
     stzcpy(webdir,"WEBPAGES",GCMAXPTH);

     if ((webptr=mstscan(MSGWEB,"WEBROOT",GCMAXPTH)) != NULL
      && strlen(webptr) > 0) {
          stlcpy(webdir,webptr,GCMAXPTH);
          if (webdir[strlen(webdir)-1] == '\\') {
               webdir[strlen(webdir)-1]='\0';
          }
     }
     gmkdir(webdir);

     newdom[0]=alcmem(HSTLEN+DMNLEN+1);
     stlcpy(newdom[0],host,HSTLEN);
     stlcat(newdom[0],".",HSTLEN+DMNLEN);
     stlcat(newdom[0],domain,HSTLEN+DMNLEN);
     if (fnd1st(&fb,"NEWPAGES\\*.*",0)) {
          do {
               if (access(spr("WEBPAGES\\%s",fb.ff_name),0) == -1) {
                    if (samend(fb.ff_name,".HTM")) {
                         retval=substi(spr("NEWPAGES\\%s",fb.ff_name),
                                       spr("%s\\%s",webdir,fb.ff_name),1,
                                       olddom,newdom);
                         if (retval != NULL) {
                              catastro("movweb(): %s",retval);
                         }
                    }
                    else {
                         cpyutl(spr("NEWPAGES\\%s",fb.ff_name),
                                spr("%s\\%s",webdir,fb.ff_name),FOPRA,FOPWA);
                    }
                    unlink(spr("NEWPAGES\\%s",fb.ff_name));
               }
          } while (fndnxt(&fb));
     }
     free(host);
     free(newdom[0]);
}

static GBOOL
prtval(                            /* edtval() valrou for ISP protocol     */
INT c,
CHAR *stg)
{
     switch (toupper(c)) {
     case ' ':
          switch (toupper(stg[0])) {
          case 'S':
               strcpy(stg,"CSLIP");
               break;
          case 'C':
               strcpy(stg,"PPP");
               break;
          case 'P':
               strcpy(stg,"SLIP");
               break;
          }
          break;
     case 'S':
          strcpy(stg,"SLIP");
          break;
     case 'C':
          strcpy(stg,"CSLIP");
          break;
     case 'P':
          strcpy(stg,"PPP");
          break;
     default:
          belper(800);
          printf("\7");
          break;
     }
     return(FALSE);
}

static GBOOL
phoval(                            /* edtval() valrou for ISP phone number */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return(validig(c) || c == '-' || c == ',' || c == '*' || c == '#');
}

static GBOOL
namval(                            /* edtval() valrou for name/password    */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return(c >= 32 && c <= 255);
}

static GBOOL
chnval(                            /* edtval() valrou for server channel   */
INT c,
CHAR *stg)
{
     (VOID)stg;
     return(validig(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}

static VOID
savscr(VOID)                       /* save script file to disk             */
{
     FILE *scrfp;
     INT x,bx;
     GBOOL renfil;
     CHAR *ptr,*bakfil,*savmsg,*bakmsg;
     static CHAR scrbak[GCMAXPTH];
     CHAR fnwext[GCMAXFNM];

     if (scrfnm[0] == '\0') {
          strcpy(scrfnm,"GALSLISP.SCR");
          bakfil=NULL;
     }
     else {
          strcpy(scrbak,scrfnm);
          if ((ptr=strrchr(scrbak,'\\')) != NULL
           && (ptr=strrchr(ptr,'.')) != NULL) {
               *ptr='\0';
          }
          else if ((ptr=strrchr(scrbak,'.')) != NULL) {
               *ptr='\0';
          }
          stlcat(scrbak,".*",GCMAXPTH);
          bakfil=uniqfn(scrbak);
     }
     if (access(scrfnm,0) != -1) {
          renfil=TRUE;
     }
     else {
          renfil=FALSE;
     }
     if (bakfil != NULL && renfil && rename(scrfnm,bakfil) == -1) {
          catastro("savscr(): Error renaming script file!");
     }
     if ((scrfp=fopen(scrfnm,FOPWA)) == NULL) {
          catastro("savscr(): Error opening script file for output!");
     }
     fprintf(scrfp,scrtmp,isppho,ispnam,isppsw);
     fclose(scrfp);
     fileparts(GCPART_FNAM,scrfnm,fnwext,GCMAXFNM);
     savmsg=spr("New script created in file %s.",fnwext);
     x=(50-strlen(savmsg))/2;
     rstimg();
     setatr(0x1F);
     if (bakfil != NULL && renfil) {
          fileparts(GCPART_FNAM,bakfil,fnwext,GCMAXFNM);
          bakmsg=spr("Backup saved in file %s.",fnwext);
          bx=(50-strlen(bakmsg))/2;
          explodeto(scntbl[7],0,5,50,10,14,8);
          prat(x,1,"%s",savmsg);
          prat(bx,2,"%s",bakmsg);

     }
     else {
          explodeto(scntbl[7],0,0,50,4,14,8);
          prat(x,1,"%s",savmsg);
     }
}

static VOID
dispsval(VOID)                     /* display initial script values        */
{
     setatr(0x1E);
     prat(25,5,"%s",ispprt);
     prat(25,6,"%s",ispchn);
     prat(25,10,"%s",yesno);
}

static GBOOL
chksvlc(VOID)                      /* check/act upon edtvalc (script)      */
{
     switch (edtvalc) {
     case CRSRDN:
     case TAB:
     case 10:
     case 13:
          switch (curfld) {
          case PRTFLD:
               curfld=CHNFLD;
               return(TRUE);
          case CHNFLD:
               if (ispchn[0] == '\0' || sscanf(ispchn,"%X",&srvchn) != 1) {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=PHOFLD;
               }
               return(TRUE);
          case PHOFLD:
               if (isppho[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=NAMFLD;
               }
               return(TRUE);
          case NAMFLD:
               if (ispnam[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=PSWFLD;
               }
               return(TRUE);
          case PSWFLD:
               if (isppsw[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=SAVFLD;
               }
               return(TRUE);
          case SAVFLD:
               if (edtvalc == TAB || edtvalc == CRSRDN) {
                    curfld=PRTFLD;
                    return(FALSE);
               }
               return(TRUE);
          }
          break;
     case CRSRUP:
     case BAKTAB:
          switch (curfld) {
          case PRTFLD:
               curfld=SAVFLD;
               return(TRUE);
          case CHNFLD:
               if (ispchn[0] == '\0' || sscanf(ispchn,"%X",&srvchn) != 1) {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=PRTFLD;
               }
               return(TRUE);
          case PHOFLD:
               if (isppho[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=CHNFLD;
               }
               return(TRUE);
          case NAMFLD:
               if (ispnam[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=PHOFLD;
               }
               return(TRUE);
          case PSWFLD:
               if (isppsw[0] == '\0') {
                    belper(800);
                    printf("\x07");
               }
               else {
                    curfld=NAMFLD;
               }
               return(TRUE);
          case SAVFLD:
               curfld=PSWFLD;
               return(FALSE);
          }
          return(TRUE);
     case ESC:
          escabt();
          return(TRUE);
     }
     return(TRUE);
}

static VOID
enaint(VOID)                       /* enable Internet apps, if necessary   */
{
     FILE *lstfp;
     CHAR *ptr,dmdnam[FNMLEN];

     if (access("GALTCPIP.DMD",0) != -1) {
          if ((lstfp=fopen(APPLST,FOPRA)) == NULL) {
               catastro("enaint(): Error opening list file for input!");
          }
          while (fgets(inbuf,BUFSIZ,lstfp) != NULL) {
               depad(inbuf);
               stlcpy(dmdnam,inbuf,FNMLEN);
               if ((ptr=strrchr(dmdnam,'.')) != NULL) {
                    *ptr='\0';
                    stlcat(dmdnam,DMDEXT,FNMLEN);
               }
               unlink(inbuf);
               rename(dmdnam,inbuf);
          }
          fclose(lstfp);
     }
}
