home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / DataScope 2.0.3 / DataScope2l / TCPSource / confile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  30.3 KB  |  1,442 lines  |  [TEXT/MPS ]

  1. /*
  2. *   Confile.c
  3. *   Split from util.c 5/88
  4. *   Reads and stores the appropriate information for the config file
  5. *
  6. */
  7. #include "stdio.h"
  8. #include "memory.h"
  9. #include "whatami.h"
  10. #include "hostform.h"
  11.  
  12. #ifdef PC
  13. #include "string.h"
  14. #else
  15. #define strchr(A,B) index(A,B)
  16. #endif
  17.  
  18. #define NUMSPECS 131
  19.  
  20. char                             /* special function types */
  21.             *neterrstring();
  22. int32 time();                    /* don't forget this sucker! */
  23.  
  24. static struct machinfo *Smachlist,*Smptr;
  25. struct machinfo *Sns=NULL;
  26.  
  27. static unsigned char *Smachfile = {"config.tel"},
  28.             Sflags[NUMSPECS-95],    /* which parms we have or have not */
  29.             *Sspace;
  30.  
  31. struct config Scon = {
  32.         0,0,0,0,
  33.         0,
  34.         3,
  35.         127,0,0,1,
  36.         "",
  37.         7,1,0x70,
  38.         "atalk",
  39.         "ega",
  40.         0,
  41.         1,
  42.         1,
  43.         1,
  44.         0,
  45.         "DEC-VT100",
  46.         "*",
  47.         NULL,
  48.         NULL,
  49.         NULL,
  50.         NULL,
  51.         NULL,
  52.         NULL,
  53.         1,
  54.         4,
  55.         3,
  56.         -1,
  57.         120,
  58.         0x0d000,
  59.         0x0300
  60. };
  61.  
  62. int
  63. Sxxnf[3] = NFDEF,
  64. Sxxnb[3] = NBDEF,
  65. Sxxbf[3] = BFDEF,
  66. Sxxbb[3] = BBDEF,
  67. Sxxuf[3] = UFDEF,
  68. Sxxub[3] = UBDEF;
  69.  
  70. static int
  71.         mno=0,                    /* how many machines in host file */
  72.         lineno,                    /* line number in hosts file */
  73.         position,                /* position for scanning string */
  74.         constate,                /* state for config file parser */
  75.         inquote;                /* flag, inside quotes now */
  76.  
  77. /*
  78. *   States for config file reading state machine.
  79. *   One for each type of keyword and some for controlling.
  80. */
  81.  
  82. #define    CONNAME    101
  83. #define CONHOST    102
  84. #define CONIP    103
  85. #define CONGATE    104
  86. #define CONCOLOR 105
  87. #define CONBKSP    106
  88. #define CONBKSC    107
  89. #define CONRETR    108
  90. #define CONWIND    109
  91. #define CONSEG    110
  92. #define CONMTU    111
  93. #define CONNS    112
  94. #define CONTO    113
  95. #define CONCRMAP 114
  96. #define CONDUP  115
  97. #define CONWRAP 116
  98. #define CONWIDE 117
  99. #define CONFONT 118
  100. #define CONFSIZE 119
  101. #define CONNF 120
  102. #define CONNB 121
  103. #define CONBF 122
  104. #define CONBB 123
  105. #define CONUF 124
  106. #define CONUB 125
  107. #define CONRF 126
  108. #define CONRB 127
  109. #define CONCLMODE 128
  110. #define CONPORT 129
  111. #define CONLINES 130
  112. #define CONLKEYS 131
  113. /*
  114. *  above this line are per machine entries, below are configuration entries
  115. */
  116. #define CONMYIP    132
  117. #define CONHPF  133
  118. #define CONPSF  134
  119. #define CONTEKF 135
  120. #define CONJTIME 136
  121. #define CONME    137
  122. #define CONCCOL    138
  123. #define CONHW    139
  124. #define CONADDR    140
  125. #define CONIOA    141
  126. #define CONDEF  142
  127. #define CONCKEYS 143
  128. #define CONINT    144
  129. #define CONBIOS    145
  130. #define CONTEK    146
  131. #define CONVIDEO    147
  132. #define CONFTP    148
  133. #define CONRCP    149
  134. #define CONPASS    150
  135. #define CONCAP    151
  136. #define CONTTYPE    152
  137. #define CONNSTYPE     153
  138. #define CONFROM    154
  139. #define CONARPTO 155
  140. #define CONZONE 156
  141. #define CONNDOM  157
  142. #define CONDOMTO 158
  143. #define CONBLOCK 159
  144. #define    CONMASK    160
  145.  
  146.  
  147. char *Skeyw[] = {
  148.         "",    
  149.         "name",                            /* name of session */
  150.         "host",                            /* name of host */
  151.         "hostip",                        /* IP number */
  152.         "gateway",                        /* gateway level */
  153.         "color",                        /* color code  ==5== */
  154.         "erase",                        /* value to use for backspace */
  155.         "scrollback",                    /* how many lines to backscroll */
  156.         "retrans",                        /* initial retrans time */
  157.         "rwin",                            /* window to allow for this host */
  158.         "maxseg",                        /* maximum transfer size (in) ==10== */
  159.         "mtu",                            /* transfer unit (out) */
  160.         "nameserver",                    /* name server level */
  161.         "contime",                        /* timeout for opening connection */
  162.         "crmap",                        /* map for Berkeley 4.3 compatibility */
  163.         "duplex",                        /* half duplex for IBM machines */
  164.         "vtwrap",                        /* should VT wrap? */
  165.         "vtwidth",                        /* width of VT100 screen */
  166.         "font",                            /* font to use, when given a choice */
  167.         "fsize",                        /* font size, in points */
  168.         "nfcolor",                        /* normal foreground color */
  169.         "nbcolor",                        /* normal background color */
  170.         "bfcolor",                        /* blink foreground color */
  171.         "bbcolor",                        /* blink background color */
  172.         "ufcolor",                        /* underline foreground color */
  173.         "ubcolor",                        /* underline background color */
  174.         "rfcolor",                        /* reverse foreground color */
  175.         "rbcolor",                        /* reverse background color */
  176.         "clearsave",                    /* clear screen saves lines */
  177.         "port",                            /* TCP port to go for */
  178.         "vtlines",                        /* number of lines for the VT100 window */
  179.         "localkeys",                    /* keys to use for int,susp,resume */
  180.  
  181. /*
  182. *  following are one-time entries, above are part of the data structure
  183. */
  184.         "myip",                            /* local machine's IP # */
  185.         "hpfile",                        /* HPGL output file */
  186.         "psfile",                        /* postscript output file */
  187.         "tekfile",                        /* tektronix output file */
  188.         "timeslice",                    /* timer slice for multi-tasking */
  189.         "myname",                        /* identifying info ==15==*/
  190.         "concolor",                        /* console colors */
  191.         "hardware",                        /* network hardware */
  192.         "address",                        /* Address of hardware */
  193.         "ioaddr",                        /* ioaddress of hardware */
  194.         "domain",                        /* default domain for lookup */
  195.         "commandkeys",                    /* use command keys on mac */
  196.         "interrupt",                    /* interrupt request 3 or 5 */
  197.         "bios",                            /* use BIOS screen */
  198.         "tek",                            /* tektronix graphics ==20==*/
  199.         "video",                        /* type of video hardware */
  200.         "ftp",                            /* enable ftp? */
  201.         "rcp",                            /* enable rcp? */
  202.         "passfile",                        /* password file name */
  203.         "capfile",                        /* capture file name */
  204.         "termtype",                        /* terminal type */
  205.         "nameservertype",                /* nameserver type */
  206.         "copyfrom",                        /* copy from another machine */
  207.         "arptime",                        /* time-out for ARPs */
  208.         "zone",                            /* NBP zone for Macs */
  209.         "domainretry",                    /* # of retries */
  210.         "domaintime",                    /* time-out for DOMAIN */
  211.         "block",                        /* blocking for network update */
  212.         "netmask",                        /* subnetting mask */
  213.         ""
  214.     };
  215.  
  216.  
  217.  
  218. /************************************************************************/
  219. /*  Sgetconfig
  220. *   copy the configuration information into the user's data structure
  221. *   directly.  The user can do with it what he feels like.
  222. */
  223. Sgetconfig(cp)
  224.     struct config *cp;
  225.     {
  226.  
  227.     movenbytes(cp,&Scon,sizeof(struct config));
  228.     return(0);
  229.  
  230. }
  231.  
  232. /************************************************************************/
  233. /*  Sreadhosts
  234. *   read in the hosts file into our in-memory data structure.
  235. *   Handle everything by keyword, see docs for specifications about file.
  236. */
  237. Sreadhosts()
  238.     {
  239.     FILE *fp;
  240.     int c,retval;
  241.  
  242.     Smachlist = Smptr = NULL;
  243.     mno = 0;
  244.  
  245.     Sspace = (char *)NewPtr(256);                /* get room for gathering stuff */
  246.     if (Sspace == NULL) {
  247.         Serrline(901);
  248.         return(1);
  249.     }
  250.     position = constate = inquote = lineno = 0;   /* state vars */    
  251.  
  252.     if (NULL == (fp = fopen(Smachfile,"r"))) {
  253.         Serrline(900);
  254.         return(1);
  255.     }
  256.  
  257.     retval = 0;
  258.     while (!retval) {
  259.         c = fgetc(fp);
  260.         if (c == '#' && !inquote) {
  261.             while (c != EOF && c != '\n' && c != '\r')        /* skip to EOL */
  262.                 c = fgetc(fp);
  263.         }
  264.         if (c == '\n' || c == '\r')
  265.             lineno++;
  266.         retval = Scontoken(c);
  267.     }
  268.  
  269.     fclose(fp);
  270.     DisposPtr ((Ptr)Sspace);
  271.  
  272.     Smadd("default");                /* make sure name is in list */
  273.  
  274.     if (retval == EOF)                /* EOF is normal end */
  275.         return(0);
  276.     else
  277.         return(retval);
  278.  
  279. }
  280.  
  281.  
  282. /************************************************************************/
  283. /*  ncstrcmp
  284. *   No case string compare.
  285. *   Only returns 0=match, 1=no match, does not compare greater or less
  286. *   There is a tiny bit of overlap with the | 32 trick, but shouldn't be
  287. *   a problem.  It causes some different symbols to match.
  288. */
  289. ncstrcmp(sa,sb)
  290.     char *sa,*sb;
  291.     {
  292.  
  293.     while (*sa && *sa < 33)        /* don't compare leading spaces */
  294.         sa++;
  295.     while (*sb && *sb < 33)
  296.         sb++;
  297.  
  298.     while (*sa && *sb) {
  299.         if ((*sa != *sb) && ((*sa | 32) != (*sb | 32)))
  300.             return(1);
  301.         sa++;sb++;
  302.     }
  303.     if (!*sa && !*sb)        /* if both at end of string */
  304.         return(0);
  305.     else
  306.         return(1);
  307. }
  308.  
  309. /************************************************************************/
  310. /*  Serrline
  311. *   prints the line number of the host file error and posts the event
  312. *   for the line number error and posts the hosts file error.
  313. */
  314.  
  315. Serrline(n)
  316.     int n;
  317.     {
  318.     char *p;
  319.  
  320.     p = neterrstring(-1);
  321.     sprintf(p,"Config file: error in line %4d",lineno+1);
  322.     netposterr(-1);
  323.  
  324.     netposterr(n);
  325. }
  326.  
  327. /************************************************************************/
  328. /* Scontoken
  329. *  tokenize the strings which get passed to Sconfile.
  330. *  Handles quotes and uses separators:  <33, ;:=
  331. */
  332. Scontoken(c)
  333.     int c;
  334.     {
  335.     int retval;
  336.  
  337.     if (c == EOF) {
  338.         Sspace[position++] = '\0';
  339.         Sconfile(Sspace);
  340.         if (!Sflags[0]) {            /* make sure last entry gets copied */
  341.             if (ncstrcmp("default",Smptr->sname))
  342.                 Scopyfrom("default");
  343.             else
  344.                 Scopyfrom("==");
  345.         }
  346.         return(-1);
  347.     }
  348.  
  349.     if (!position && Sissep(c))        /* skip over junk before token */
  350.         return(0);
  351.  
  352.     if (inquote || !Sissep(c)) {
  353.  
  354.         if (position > 200) {
  355.             Serrline(903);
  356.             return(1);
  357.         }
  358. /*
  359. *  check for quotes, a little mixed up here, could be reorganized
  360. */
  361.         if (c == '"' ) {
  362.             if (!inquote) {            /* beginning of quotes */
  363.                 inquote = 1;
  364.                 return(0);
  365.             }
  366.             else
  367.                 inquote = 0;        /* turn off flag and drop through */
  368.  
  369.         }
  370.         else {                        
  371.             if (c == '\n') {            /* check for EOL inside quotes */
  372.                 Serrline(904);
  373.                 return(1);
  374.             }
  375.             Sspace[position++] = c;    /* include in current string */
  376.             return(0);
  377.         }
  378.                 
  379.     }
  380.  
  381.     Sspace[position++] = '\0';
  382.  
  383.     retval = Sconfile(Sspace);            /* pass the token along */
  384.  
  385.     position = 0;
  386.     inquote = 0;
  387.     Sspace[0] = '\0';
  388.  
  389.     return(retval);
  390. }
  391.  
  392. /************************************************************************/
  393. /*  Sconfile
  394. *   take the characters read from the file and parse them for keywords
  395. *   which require configuration action.
  396. */
  397. Sconfile(s)
  398.     char *s;
  399.     {
  400.     int i,a,b,c,d;
  401.  
  402.     switch (constate) {
  403.         case 0:                                /* lookup keyword */
  404.             if (!(*s))                        /* empty token */
  405.                 return(0);
  406.  
  407.  
  408.             for (i=1; *Skeyw[i] && ncstrcmp(Skeyw[i],s); i++)
  409.                     ;
  410.             if (!(*Skeyw[i])) {            /* not in list */
  411.                 Serrline(902);
  412.                 return(0);                /* don't die - helps backward compatibility */
  413.             }
  414.             constate = 100+i;    /* change to state for keyword */
  415. /*
  416. *  check if this is a machine specific parm without a machine to
  417. *  give it to.  "name" being the only machine specific parm allowed, of course
  418. */
  419.             if (Smptr == NULL && constate > 101 && constate <= NUMSPECS) {
  420.                 Serrline(905);
  421.                 return(1);
  422.             }
  423.             break;
  424.  
  425.         case CONNAME:
  426. /*
  427. *  allocate space for upcoming parameters
  428. */
  429.             if (Smachlist == NULL) {
  430.                 Smachlist = (struct machinfo *)NewPtr(sizeof(struct machinfo));
  431.                 Smptr = Smachlist;
  432.                 Smptr->sname = NULL;
  433.                 Smptr->hname = NULL;
  434.             }
  435.             else {
  436.                 if (!Sflags[0]) {
  437.                     if (ncstrcmp("default",Smptr->sname))
  438.                         Scopyfrom("default");
  439.                     else
  440.                         Scopyfrom("==");    /* to make sure 'default' gets set */
  441.                 }
  442.                 Smptr->next = 
  443.                     (struct machinfo *)NewPtr(sizeof(struct machinfo));
  444.                 Smptr = Smptr->next;
  445.             }
  446.             Smptr->next = NULL;
  447.             Smptr->hname = NULL;                /* guarantee to be null */
  448.             Smptr->sname = (char *)NewPtr(position);    /* size of name string */
  449.             strcpy(Smptr->sname,s);                /* keep name field */
  450.             constate = 0;                        /* back to new keyword */
  451.             for (i=0; i<NUMSPECS-99; i++)
  452.                 Sflags[i] = 0;                    /* we have no parms */
  453.             Smptr->mno = ++mno;                    /* new machine number */
  454.             break;
  455.  
  456.         case CONHOST:                            /* also a name */
  457.             Smptr->hname = (char *)NewPtr(position);
  458.             strcpy(Smptr->hname,s);
  459.             constate = 0;
  460.             Sflags[CONHOST-100] = 1;
  461.             break;
  462.  
  463.         case CONIP:                                /* IP number for host */
  464.             if ( 4 != sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d)) {
  465.                 Serrline(906);
  466.                 return(3);
  467.             }
  468.             Smptr->hostip[0]=a; Smptr->hostip[1] =b;     /* keep number */
  469.             Smptr->hostip[2]=c; Smptr->hostip[3] =d;
  470.             Smptr->mstat = HFILE;
  471.             constate = 0;
  472.             Sflags[CONIP-100] = 1;
  473.             break;
  474.  
  475.         case CONGATE:
  476.             Smptr->gateway = atoi(s);            /* gateway level */
  477.             constate = 0;
  478.             Sflags[CONGATE-100] = 1;
  479.             break;
  480.  
  481.         case CONCOLOR:                    /* support old format */
  482.             Smptr->nfcolor[0] = s[1]-48;
  483.             Smptr->nbcolor[0] = s[0]-48;
  484.             Smptr->bfcolor[0] = s[5]-48;
  485.             Smptr->bbcolor[0] = s[4]-48;
  486.             Smptr->ufcolor[0] = s[3]-48;
  487.             Smptr->ubcolor[0] = s[2]-48;
  488.             constate = 0;
  489.             Sflags[CONNF-100] = 1;        /* sets them all at one shot */
  490.             Sflags[CONNB-100] = 1;
  491.             Sflags[CONBF-100] = 1;
  492.             Sflags[CONBB-100] = 1;
  493.             Sflags[CONUF-100] = 1;
  494.             Sflags[CONUB-100] = 1;
  495.             break;
  496.  
  497.         case CONNF:                        /* foreground normal color */
  498.             if (Scolorset(Smptr->nfcolor,s))
  499.                 Sflags[CONNF-100] = 1;
  500.             constate = 0;
  501.             break;
  502.         case CONNB:                        /* background normal color */
  503.             if (Scolorset(Smptr->nbcolor,s))
  504.                 Sflags[CONNB-100] = 1;
  505.             constate = 0;
  506.             break;
  507.         case CONRF:
  508.         case CONBF:                        /* blink foreg color */
  509.             if (Scolorset(Smptr->bfcolor,s))
  510.                 Sflags[CONBF-100] = 1;    /* in copyfrom, r's are really b's */
  511.             constate = 0;
  512.             break;
  513.         case CONRB:
  514.         case CONBB:                        /* blink bg color */
  515.             if (Scolorset(Smptr->bbcolor,s))
  516.                 Sflags[CONBB-100] = 1;
  517.             constate = 0;
  518.             break;
  519.         case CONUF:                        /* foreground underline color */
  520.             if (Scolorset(Smptr->ufcolor,s))
  521.                 Sflags[CONUF-100] = 1;
  522.             constate = 0;
  523.             break;
  524.         case CONUB:                        /* bg underline color */
  525.             if (Scolorset(Smptr->ubcolor,s))
  526.                 Sflags[CONUB-100] = 1;
  527.             constate = 0;
  528.             break;
  529.  
  530.         case CONLKEYS:                    /* local key bindings */
  531.             { int a,b,c;
  532.                 if (3!=sscanf(s,"{%d,%d,%d}", &a, &b, &c))
  533.                     Smptr->ckey = Smptr->skey = Smptr->qkey = 0;    /* default = off */
  534.                 else {
  535.                     Smptr->ckey = a;
  536.                     Smptr->skey = b;
  537.                     Smptr->qkey = c;
  538.                 }
  539.             }
  540.             Sflags[CONLKEYS-100] = 1;
  541.             constate = 0;
  542.             break;
  543.  
  544.         case CONBKSP:
  545.             if (!ncstrcmp(s,"backspace"))
  546.                 Smptr->bksp = 8;
  547.             else
  548.                 Smptr->bksp = 127;
  549.             constate = 0;
  550.             Sflags[CONBKSP-100] = 1;
  551.             break;
  552.  
  553.         case CONBKSC:
  554.             Smptr->bkscroll = atoi(s);
  555.             constate = 0;
  556.             Sflags[CONBKSC-100] = 1;
  557.             break;
  558.  
  559.         case CONRETR:
  560.             Smptr->retrans = atoi(s);
  561.             constate = 0;
  562.             Sflags[CONRETR-100] = 1;
  563.             break;
  564.  
  565.         case CONWIND:
  566.             Smptr->window = atoi(s);
  567.             constate = 0;
  568.             Sflags[CONWIND-100] = 1;
  569.             break;
  570.  
  571.         case CONSEG:
  572.             Smptr->maxseg = atoi(s);
  573.             constate = 0;
  574.             Sflags[CONSEG-100] = 1;
  575.             break;
  576.  
  577.         case CONMTU:
  578.             Smptr->mtu = atoi(s);
  579.             constate = 0;
  580.             Sflags[CONMTU-100] = 1;
  581.             break;
  582.  
  583.         case CONNS:
  584.             Smptr->nameserv = atoi(s);
  585.             if (!Sns || (Sns->nameserv > Smptr->nameserv))    /* keep NS */
  586.                 Sns = Smptr;
  587.             constate = 0;
  588.             Sflags[CONNS-100] = 1;
  589.             break;
  590.  
  591.         case CONTO:
  592.             i = atoi(s);
  593.             if (i > 2) {
  594.                 Smptr->conto = i;
  595.                 Sflags[CONTO-100] = 1;
  596.             }
  597.             constate = 0;
  598.             break;
  599.  
  600.         case CONCRMAP:
  601.             if (!ncstrcmp(s,"4.3BSDCRNUL")) 
  602.                 Smptr->crmap = 0;
  603.             else
  604.                 Smptr->crmap = 10;
  605.             Sflags[CONCRMAP-100] = 1;
  606.             constate = 0;
  607.             break;
  608.  
  609.         case CONDUP:
  610.             if (!ncstrcmp(s,"half")) {
  611.                 Smptr->halfdup = 1;
  612.                 Sflags[CONDUP-100] = 1;
  613.             }
  614.             constate = 0;
  615.             break;
  616.  
  617.         case CONWRAP:
  618.             if ('Y' == toupper(s[0])) 
  619.                 Smptr->vtwrap = 1;
  620.             else
  621.                 Smptr->vtwrap = 0;
  622.             Sflags[CONWRAP-100] = 1;
  623.             constate = 0;
  624.             break;
  625.  
  626.         case CONCLMODE:
  627.             if ('N' == toupper(s[0])) 
  628.                 Smptr->clearsave = 0;
  629.             else
  630.                 Smptr->clearsave = 1;
  631.             Sflags[CONCLMODE-100] = 1;
  632.             constate = 0;
  633.             break;
  634.  
  635.         case CONFONT:
  636.             Smptr->font = (char *)NewPtr(position);
  637.             strcpy(Smptr->font,s);
  638.             Sflags[CONFONT-100] = 1;
  639.             constate = 0;
  640.             break;
  641.  
  642.         case CONFSIZE:
  643.             Smptr->fsize = atoi(s);
  644.             Sflags[CONFSIZE-100] = 1;
  645.             constate = 0;
  646.             break;
  647.  
  648.         case CONWIDE:
  649.             if (132 == atoi(s)) 
  650.                 Smptr->vtwidth = 132;
  651.             else
  652.                 Smptr->vtwidth = 80;
  653.  
  654.             Sflags[CONWIDE-100] = 1;
  655.             constate = 0;
  656.             break;
  657.  
  658.         case CONLINES:
  659.             i = atoi(s);
  660.             if (i > 6 && i < 100)
  661.                 Smptr->nlines = i;
  662.             else
  663.                 Smptr->nlines = 24;            /* default is 24 lines */
  664.             Sflags[CONLINES-100] = 1;
  665.             constate = 0;
  666.             break;
  667.  
  668.         case CONPORT:                        /* File name for Tek dump */
  669.             i = atoi(s);
  670.             if (i < 1)
  671.                 i = 23;
  672.             Smptr->port = i;
  673.             Sflags[CONPORT-100] = 1;
  674.             constate = 0;
  675.             break;
  676.  
  677. /*
  678. *  now the one-time entries
  679. *  Generally this information goes into the "Scon" structure for later
  680. *  retrieval by other routines.
  681. *
  682. */
  683. #ifdef PC
  684.         case CONMASK:
  685.             if ( 4 != sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d)) {
  686.                 Serrline(907);
  687.                 return(3);
  688.             }
  689.             Scon.netmask[0]=a; Scon.netmask[1] =b;     
  690.             Scon.netmask[2]=c; Scon.netmask[3] =d;
  691.             Scon.havemask=1;
  692.             constate = 0;
  693.             break;
  694.  
  695.         case CONMYIP:
  696.             constate = 0;
  697.             if (!ncstrcmp(s,"rarp")) {
  698.                 movebytes(Scon.myipnum,s,4);
  699.                 netsetip("RARP");
  700.                 break;
  701.             }
  702.             if ( 4 != sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d)) {
  703.                 Serrline(908);
  704.                 return(3);
  705.             }
  706.             Scon.myipnum[0]=a; Scon.myipnum[1] =b;     /* put number back in s */
  707.             Scon.myipnum[2]=c; Scon.myipnum[3] =d;
  708.             netsetip(Scon.myipnum);        /* make permanent set */
  709.             break;
  710. #endif
  711.         case CONME:                /* what my name is  */
  712.             strncpy(Scon.me,s,30);
  713.             Scon.me[30] = '\0';
  714.             constate = 0;
  715.             break;
  716.  
  717.         case CONHW:                /* what hardware are we using? */
  718.             i = strlen(s);
  719.             if (i > 9) i = 9;
  720.             s[i] = '\0';
  721.             i--;
  722.             while (i--)
  723.                 s[i] = tolower(s[i]);
  724.             strcpy(Scon.hw,s);
  725.             constate = 0;
  726.             break;
  727.  
  728. #ifdef PC
  729.         case CONINT:            /* what IRQ to use */
  730.             sscanf(s,"%x",&i);
  731.             Scon.irqnum = i;
  732.             constate = 0;
  733.             break;
  734.  
  735.         case CONBIOS:
  736.             if (toupper(*s) == 'Y') {
  737.                 Scwritemode(0);
  738.                 Scon.bios = 1;
  739.             }
  740.             constate = 0;
  741.             break;
  742.  
  743.         case CONADDR:                /* segment address for board */
  744.             sscanf(s,"%x",&i);
  745.             Scon.address = i;
  746.             constate = 0;
  747.             break;
  748.  
  749.         case CONIOA:                /* io address for board */
  750.             sscanf(s,"%x",&i);
  751.             Scon.ioaddr = i;
  752.             constate = 0;
  753.             break;
  754. #endif
  755. #ifdef MAC
  756.         case CONCKEYS:
  757.             if (toupper(*s) == 'Y') {
  758.                 Scon.comkeys = 1;
  759.             }
  760.             constate = 0;
  761.             break;
  762.  
  763.         case CONZONE:
  764.             Scon.zone = (char *)NewPtr(position);    /* space for name */
  765.             strcpy(Scon.zone,s);            /* copy it in */
  766.             constate = 0;
  767.             break;
  768.  
  769.         case CONJTIME:                /* Time slice */
  770.             i = atoi(s);
  771.             if (i > 1)
  772.                 Scon.timesl = i;
  773.             constate = 0;
  774.             break;
  775. #endif        
  776.  
  777.         case CONTEK:
  778.             if (toupper(*s) == 'N') {
  779.                 Stekmode(0);
  780.                 Scon.tek = 0;
  781.             }
  782.             constate = 0;
  783.             break;
  784.  
  785.         case CONVIDEO:
  786.             i = strlen(s);
  787.             if (i > 9) i = 9;
  788.             s[i] = '\0';
  789.             strcpy(Scon.video,s);
  790.             i--;
  791.             while (i--)
  792.                 s[i] = tolower(s[i]);
  793.             constate = 0;
  794.             break;
  795.  
  796.         case CONTTYPE:
  797.             Scon.termtype = (char *)NewPtr(position);
  798.             strcpy(Scon.termtype,s);
  799.             constate = 0;
  800.             break;
  801.  
  802.         case CONCCOL:
  803.             for (i=0; i<3; i++)
  804.                 Scon.color[i] = ((s[i*2]-48)<<4) + (s[i*2+1]-48);
  805.             constate = 0;
  806.             break;
  807.  
  808.         case CONFTP:
  809.             if (toupper(*s) == 'N') 
  810.                 Scon.ftp = 0;    
  811.             constate = 0;
  812.             break;
  813.  
  814.         case CONRCP:
  815.             if (toupper(*s) == 'N')
  816.                 Scon.rcp = 0;
  817.             constate = 0;
  818.             break;
  819.  
  820.         case CONPASS:
  821.             Scon.pass = (char *)NewPtr(position);    /* space for name */
  822.             strcpy(Scon.pass,s);            /* copy it in */
  823.             constate = 0;
  824.             break;
  825.  
  826.         case CONDEF:                        /* default domain */
  827.             Scon.defdom = (char *)NewPtr(position);    /* space for name */
  828.             strcpy(Scon.defdom,s);            /* copy it in */
  829.             constate = 0;
  830.             break;
  831.  
  832.         case CONCAP:                        /* capture file name */
  833.             Snewcap(s);
  834.             constate = 0;
  835.             break;
  836.  
  837.         case CONFROM:                        /* copy the rest from another */
  838.                                             /* entry in the table */
  839.             if (Scopyfrom(s))
  840.                 return(1);
  841.             Sflags[0] = 1;                    /* indicate did copy from */
  842.             constate = 0;
  843.             break;
  844.  
  845.         case CONARPTO:                        /* need to lengthen arp time-out (secs) */
  846.             i = atoi(s);
  847.             if (i > 0)
  848.                 netarptime(i);
  849.             constate = 0;                    /* don't forget me! */
  850.             break;
  851.  
  852.         case CONBLOCK:                        /* blocking factor for text */
  853.             i = atoi(s);
  854.             if (i > 4096) i = 4096;
  855.             if (i > 0)
  856.                 Scon.textblock = i;
  857.             constate = 0;                    /* don't forget me! */
  858.             break;
  859.  
  860.         case CONDOMTO:                        /* DOMAIN timeout value */
  861.             i = atoi(s);
  862.             if (i > 1)
  863.                 Scon.domto = i;
  864.             constate = 0;
  865.             break;
  866.  
  867.         case CONNDOM:                        /* DOMAIN number of retries */
  868.             i = atoi(s);
  869.             if (i > 1)
  870.                 Scon.ndom = i;
  871.             constate = 0;
  872.             break;
  873.  
  874.         case CONHPF:                /* File name for HP dump */
  875.             Snewhpfile(s);
  876.             constate = 0;
  877.             break;
  878.  
  879.         case CONPSF:                /* File name for PS dump */
  880.             Snewpsfile(s);
  881.             constate = 0;
  882.             break;
  883.  
  884.         case CONTEKF:                /* File name for Tek dump */
  885.             Snewtekfile(s);
  886.             constate = 0;
  887.             break;
  888.  
  889.         default:
  890.             constate = 0;
  891.             break;
  892.     }
  893.  
  894.     return(0);
  895. }
  896.  
  897. /************************************************************************/
  898. /*  Scopyfrom
  899. *   Look at the Sflags array to determine which elements to copy from
  900. *   a previous machine's entries.  If a machine name as been given as
  901. *   "default", the state machine will fill in the fields from that
  902. *   machine's entries.
  903. *
  904. *   If the machine name to copyfrom is not present in the list, set the
  905. *   program default values for each field.
  906. */
  907. Scopyfrom(s)
  908.     char *s;
  909.     {
  910.     struct machinfo *m;
  911.     int i;
  912.  
  913.     m = Shostlook(s);            /* search list */
  914.  
  915.     for (i=3; i <= NUMSPECS-100; i++)         /* through list of parms */
  916.         if (!Sflags[i]) {
  917.             if (m)                             /* copy old value */
  918.             switch (100+i) {
  919.                 case CONHOST:
  920.                     Smptr->hname = m->hname;
  921.                     break;
  922.                 case CONIP:
  923.                     movebytes(Smptr->hostip,m->hostip,4);
  924.                     Smptr->mstat = m->mstat;
  925.                     break;
  926.                 case CONGATE:            /* gateways cannot be copied from */
  927.                     Smptr->gateway = 0;
  928.                     break;
  929.                 casecCONNS:                    /* can't copy nameservers either */
  930.                     Smptr->nameserv = 0;
  931.                     break;
  932.  
  933.                 case CONBKSP:
  934.                     Smptr->bksp = m->bksp;
  935.                     break;
  936.                 case CONBKSC:
  937.                     Smptr->bkscroll = m->bkscroll;
  938.                     break;
  939.                 case CONCLMODE:
  940.                     Smptr->clearsave = m->clearsave;
  941.                     break;
  942.                 case CONRETR:
  943.                     Smptr->retrans = m->retrans;
  944.                     break;
  945.                 case CONWIND:
  946.                     Smptr->window = m->window;
  947.                     break;
  948.                 case CONSEG:
  949.                     Smptr->maxseg = m->maxseg;
  950.                     break;
  951.                 case CONMTU:
  952.                     Smptr->mtu = m->mtu;
  953.                     break;
  954.  
  955.                 case CONTO:
  956.                     Smptr->conto = m->conto;
  957.                     break;
  958.                 case CONCRMAP:
  959.                     Smptr->crmap = m->crmap;
  960.                     break;
  961.                 case CONDUP:
  962.                     Smptr->halfdup = m->halfdup;
  963.                     break;
  964.                 case CONWRAP:
  965.                     Smptr->vtwrap = m->vtwrap;
  966.                     break;
  967.                 case CONWIDE:
  968.                     Smptr->vtwidth = m->vtwidth;
  969.                     break;
  970.                 case CONLINES:
  971.                     Smptr->nlines = m->nlines;
  972.                     break;
  973.  
  974.                 case CONNF:
  975.                     movebytes(Smptr->nfcolor,m->nfcolor,3*sizeof(int));
  976.                     break;
  977.                 case CONNB:
  978.                     movebytes(Smptr->nbcolor, m->nbcolor,3*sizeof(int));
  979.                     break;
  980.                 case CONBF:
  981.                     movebytes(Smptr->bfcolor,m->bfcolor,3*sizeof(int));
  982.                     break;
  983.                 case CONBB:
  984.                     movebytes(Smptr->bbcolor,m->bbcolor,3*sizeof(int));
  985.                     break;
  986.                 case CONUF:
  987.                     movebytes(Smptr->ufcolor,m->ufcolor,3*sizeof(int));
  988.                     break;
  989.                 case CONUB:
  990.                     movebytes(Smptr->ubcolor,m->ubcolor,3*sizeof(int));
  991.                     break;
  992.  
  993.                 case CONLKEYS:
  994.                     Smptr->ckey = m->ckey;
  995.                     Smptr->skey = m->skey;
  996.                     Smptr->qkey = m->qkey;
  997.                     break;
  998.  
  999.                 case CONFONT:
  1000.                     Smptr->font = m->font;
  1001.                     break;
  1002.                 case CONFSIZE:
  1003.                     Smptr->fsize = m->fsize;
  1004.                     break;
  1005.                 case CONPORT:
  1006.                     Smptr->port = m->port;
  1007.                     break;
  1008.  
  1009.                 default:
  1010.                     break;
  1011.             }
  1012.             else
  1013.             switch (100+i) {        /* m=NULL, install default values */
  1014.                 case CONHOST:
  1015.                     Smptr->hname = NULL;
  1016.                     break;
  1017.                 case CONIP:
  1018.                     Smptr->mstat = NOIP;
  1019.                     break;
  1020.                 case CONGATE:            /* gateways cannot be copied from */
  1021.                     Smptr->gateway = 0;
  1022.                     break;
  1023.                 case CONBKSP:
  1024.                     Smptr->bksp = 127;
  1025.                     break;
  1026.                 case CONBKSC:
  1027.                     Smptr->bkscroll = 0;
  1028.                     break;
  1029.                 case CONCLMODE:
  1030.                     Smptr->clearsave = 1;
  1031.                     break;
  1032.                 case CONRETR:
  1033.                     Smptr->retrans = SMINRTO;
  1034.                     break;
  1035.                 case CONWIND:
  1036. #ifdef MAC
  1037.                     Smptr->window = 512;
  1038. #else
  1039.                     Smptr->window = DEFWINDOW;
  1040. #endif
  1041.                     break;
  1042.                 case CONSEG:
  1043. #ifdef MAC
  1044.                     Smptr->maxseg = 512;
  1045. #else
  1046.                     Smptr->maxseg = DEFSEG;
  1047. #endif
  1048.                     break;
  1049.                 case CONMTU:
  1050. #ifdef MAC
  1051.                     Smptr->mtu = 512;
  1052. #else
  1053.                     Smptr->mtu = TSENDSIZE;
  1054. #endif
  1055.                     break;
  1056.  
  1057.                 case CONNS:                    /* can't copy nameservers either */
  1058.                     Smptr->nameserv = 0;
  1059.                     break;
  1060.         
  1061.                 case CONTO:
  1062.                     Smptr->conto = CONNWAITTIME;
  1063.                     break;
  1064.  
  1065.                 case CONCRMAP:
  1066.                     Smptr->crmap = 10;
  1067.                     break;
  1068.  
  1069.                 case CONDUP:
  1070.                     Smptr->halfdup = 0;
  1071.                     break;
  1072.                 case CONWRAP:
  1073.                     Smptr->vtwrap = 0;
  1074.                     break;
  1075.                 case CONWIDE:
  1076.                     Smptr->vtwidth = 80;
  1077.                     break;
  1078.                 case CONLINES:
  1079.                     Smptr->nlines = 24;        /* overall default to 24 lines */
  1080.                     break;
  1081.  
  1082.                 case CONNF:
  1083.                     movebytes(Smptr->nfcolor,Sxxnf,3*sizeof(int));
  1084.                     break;
  1085.                 case CONNB:
  1086.                     movebytes(Smptr->nbcolor,Sxxnb,3*sizeof(int));
  1087.                     break;
  1088.                 case CONBF:
  1089.                     movebytes(Smptr->bfcolor,Sxxbf,3*sizeof(int));
  1090.                     break;
  1091.                 case CONBB:
  1092.                     movebytes(Smptr->bbcolor,Sxxbb,3*sizeof(int));
  1093.                     break;
  1094.                 case CONUF:
  1095.                     movebytes(Smptr->ufcolor,Sxxuf,3*sizeof(int));
  1096.                     break;
  1097.                 case CONUB:
  1098.                     movebytes(Smptr->ubcolor,Sxxub,3*sizeof(int));
  1099.                     break;
  1100.  
  1101.                 case CONLKEYS:
  1102.                     Smptr->ckey = 3;            /* Ctrl-C */
  1103.                     Smptr->skey = 19;            /* Ctrl-S */
  1104.                     Smptr->qkey = 17;            /* Ctrl-Q */
  1105.                     break;
  1106.  
  1107.                 case CONFONT:
  1108.                     Smptr->font = "Monaco";
  1109.                     break;
  1110.                 case CONFSIZE:
  1111.                     Smptr->fsize = 9;
  1112.                     break;
  1113.                 case CONPORT:
  1114.                     Smptr->port = 23;            /* the telnet port */
  1115.                     break;
  1116.  
  1117.                 default:
  1118.                     break;
  1119.             }
  1120.         }
  1121.  
  1122.     Sflags[0] = 1;                    /* set that this machine was copied */
  1123.     return(0);
  1124. }
  1125.  
  1126. /************************************************************************/
  1127. /*  Smadd
  1128. *   Add a machine to the list. Increments machine number of machine.
  1129. *   Puts in parameters copied from the "default" entry.
  1130. *
  1131. */
  1132. struct machinfo 
  1133. *Smadd(mname)
  1134.     char *mname;
  1135.     {
  1136.     int i;
  1137.     struct machinfo *m;
  1138. /*
  1139. *  First, do we have the name already?
  1140. */
  1141.     m = Shostlook(mname);
  1142.     if (m)
  1143.         return(m);
  1144. /*
  1145. *   Don't have name, add another record
  1146. */
  1147.     Smptr = (struct machinfo *)NewPtr(sizeof(struct machinfo));
  1148.     if (Smptr == NULL)
  1149.         return(NULL);
  1150.  
  1151.     for (i=0; i < NUMSPECS-99; i++)
  1152.         Sflags[i] = 0;                    /* we have no parms */
  1153.     Scopyfrom("default");
  1154.  
  1155.     Smptr->sname = NULL;
  1156.     Smptr->hname = (char *)NewPtr(strlen(mname)+1);
  1157.     if (Smptr->hname)
  1158.         strcpy(Smptr->hname,mname);        /* copy in name of machine */
  1159.     Smptr->mno = ++mno;
  1160.     Smptr->mstat = NOIP;
  1161.  
  1162.     Smptr->next = Smachlist;            /* add to front of machlist */
  1163.     Smachlist = Smptr;
  1164.  
  1165.     return(Smptr);
  1166.  
  1167. }
  1168.  
  1169.  
  1170. /************************************************************************/
  1171. /* Shostfile
  1172. *   if the user wants to change the host file name from 'config.tel' to
  1173. *   something else.
  1174. */
  1175. Shostfile(ptr)
  1176.     char *ptr;
  1177.     {
  1178.     Smachfile = ptr;    
  1179. /*
  1180. *  note that the area with the file name must stay allocated for
  1181. *  later reference, typically it is in some argv[] parm.
  1182. */
  1183.  
  1184. }
  1185.  
  1186. /************************************************************************/
  1187. /*  get host by name
  1188. *   Given the name of a host machine, search our database to see if we
  1189. *   have that host ip number.  Search first the name field, and then the
  1190. *   hostname field.
  1191. *   Returns the pointer to the correct record, or pointer to the default
  1192. *   record if the number is not available
  1193. */
  1194. struct machinfo 
  1195. *Sgethost(machine)
  1196.     char *machine;
  1197.     {
  1198.     int i,j,k,l;
  1199.     unsigned char ipto[4],myipnum[4],xmask[4];
  1200.     unsigned long hnum;
  1201.     struct machinfo *m;
  1202.  
  1203.     m = NULL;
  1204. /*
  1205. *  First, check for the pound sign character which means we should use
  1206. *  the current netmask to build an IP number for the local network.
  1207. *  Take the host number, install it in the ipto[] array.  Then mask
  1208. *  in my IP number's network portion to build the final IP address.
  1209. */
  1210.  
  1211.     if ('#' == machine[0]) {        /* on my local network */
  1212.         netgetip(myipnum);
  1213.         netgetmask(xmask);            /* mask of network portion of IP # */
  1214.  
  1215.         sscanf(&machine[1],"%ld",&hnum);/* host number for local network */
  1216.         for (i=3; i >= 0; i--) {
  1217.             ipto[i] = hnum & 255L;    /* take off a byte */
  1218.             hnum >>= 8;                /* shift it over */
  1219.         }
  1220.  
  1221.         for (i=0; i < 4; i++) 
  1222.             ipto[i] |= (myipnum[i] & xmask[i]);        /* mask new one in */
  1223.  
  1224.     }
  1225. /*
  1226. *  next, is it an IP number?  We take it if the number is in four
  1227. *  parts, separated by periods.
  1228. */
  1229.     else 
  1230.     if (4 == sscanf(machine,"%d.%d.%d.%d",&i,&j,&k,&l)) {    /* given ip num */
  1231.         ipto[0] = i;
  1232.         ipto[1] = j;
  1233.         ipto[2] = k;
  1234.         ipto[3] = l;
  1235.     }
  1236. /*
  1237. *  lastly, it must be a name, first check the local host table
  1238. *  A first number of 127 means that it doesn't have an IP number, but
  1239. *  is in the table (strange occurrence)
  1240. */
  1241.     else {                                    /* look it up */
  1242.  
  1243.         m = Shostlook(machine);
  1244.         if (m == NULL) {
  1245.             netposterr(805);                /* informative */
  1246.             return(NULL);
  1247.         } 
  1248.         if (m->mstat < HAVEIP) {
  1249.             netposterr(806);                /* informative */
  1250.             return(NULL);
  1251.         }
  1252.     }
  1253.  
  1254.     if (!m) {
  1255.         m = Shostlook("default");
  1256.         movebytes(m->hostip,ipto,4);        /* copy in newest host # */
  1257.         m->mstat = HAVEIP;                    /* we have the IP # */
  1258.     }
  1259.  
  1260.     return(m);
  1261. }
  1262.  
  1263. struct machinfo 
  1264. *Shostlook(hname)
  1265.     char *hname;
  1266.     {
  1267.     struct machinfo *m;
  1268.     m = Smachlist;
  1269.     while (m != NULL) {
  1270.  
  1271.         if (m->sname && !ncstrcmp(hname,m->sname)) 
  1272.             return(m);
  1273.  
  1274.         m = m->next;
  1275.     }
  1276.  
  1277.     m = Smachlist;
  1278.     while (m != NULL) {
  1279.         if (m->hname && !ncstrcmp(hname,m->hname))
  1280.             return(m);
  1281.  
  1282.         m = m->next;
  1283.     }
  1284.  
  1285.     return(NULL);
  1286.  
  1287. }
  1288.  
  1289. /************************************************************************/
  1290. /*  Slooknum
  1291. *   get the host record by machine number, used primarily in DOMAIN name
  1292. *   lookup.
  1293. */
  1294. struct machinfo 
  1295. *Slooknum(num)
  1296.     int num;
  1297.     {
  1298.     struct machinfo *m;
  1299.  
  1300.     m = Smachlist;
  1301.     while (m) {
  1302.         if (m->mno == num)
  1303.             return(m);
  1304.         m = m->next;
  1305.     }
  1306.  
  1307.     return(NULL);
  1308.  
  1309. }
  1310.  
  1311. /**************************************************************************/
  1312. /*  Slookip
  1313. *   For FTP to look up the transfer options to use when running
  1314. *
  1315. */
  1316. struct machinfo 
  1317. *Slookip(ipnum)
  1318.     unsigned char *ipnum;
  1319.     {
  1320.     struct machinfo *m;
  1321.  
  1322.     m = Smachlist;
  1323.     while (m) {
  1324.         if (comparen(m->hostip,ipnum,4))
  1325.             return(m);
  1326.         m = m->next;
  1327.     }
  1328.  
  1329.     return(NULL);
  1330.  
  1331. }
  1332.  
  1333. /**************************************************************************/
  1334. /*  Sissep
  1335. *   is the character a valid separator for the hosts file?
  1336. *   separators are white space, special chars and :;=
  1337. *
  1338. */
  1339. Sissep(c)
  1340.     int c;
  1341.     {
  1342.     if (c < 33)
  1343.         return(1);
  1344.     if (c == ':' || c == ';' || c == '=')
  1345.         return(1);
  1346.     return(0);
  1347. }
  1348.  
  1349. /*********************************************************************/
  1350. /*  Snewns()
  1351. *   Rotate to the next nameserver
  1352. *   Chooses the next highest number from the nameserv field
  1353. */
  1354. Snewns()
  1355.     {
  1356.     struct machinfo *m,*low;
  1357.     int i;
  1358.  
  1359.     if (!Sns)                    /* safety, should never happen */
  1360.         Sns = Smachlist;
  1361.  
  1362.     low = Sns;
  1363.     i = Sns->nameserv;            /* what is value now? */
  1364.  
  1365.     m = Smachlist;
  1366.     while (m) {
  1367.         if (m->nameserv == i+1) {
  1368.             Sns = m;
  1369.             return(0);
  1370.         }
  1371.         if ((m->nameserv > 0) && (m->nameserv < low->nameserv))
  1372.             low = m;
  1373.         m = m->next;
  1374.     }
  1375.  
  1376.     if (Sns == low)
  1377.         return(1);                /* no alternate */
  1378.     else
  1379.         Sns = low;
  1380.  
  1381.     return(0);
  1382. }
  1383.  
  1384.  
  1385. Ssetns(ipn)
  1386.     unsigned char ipn[4];
  1387.     {
  1388.     struct machinfo *m;
  1389.     int i;
  1390.  
  1391.     i = 0;
  1392.     if (NULL == (m = Slookip(ipn))) {        /* have already? */
  1393.         m = Smadd("=nameserv=");
  1394.         movebytes(m->hostip,ipn,4);
  1395.         m->mstat = FROMKIP;
  1396.         i = 1;
  1397.     }
  1398.  
  1399.     m->nameserv = 1;
  1400.     Sns = m;
  1401.  
  1402.     return(i);
  1403. }
  1404.  
  1405. /************************************************************************/
  1406. /*  setgates
  1407. *   set up the gateway machines and the subnet mask after netinit()
  1408. *   and start up ftp and rcp for them.
  1409. */
  1410. Ssetgates()
  1411.     {
  1412.     struct machinfo *m;
  1413.     int level,again;
  1414.  
  1415.     if (Scon.havemask)                    /* leave default unless specified */
  1416.         netsetmask(Scon.netmask);
  1417. /*
  1418. *  Search the list of machines for gateway flags.
  1419. *  Invoke netsetgate in increasing order of gateway level #s.
  1420. *  Terminates when it gets through list without finding next higher number.
  1421. */
  1422.     level = 0;
  1423.     do {
  1424.         level++;
  1425.         again = 0;
  1426.         m = Smachlist;
  1427.         while (m != NULL) {
  1428.             if (m->gateway == level && m->mstat >= HAVEIP) 
  1429.                 netsetgate(m->hostip);
  1430.             if (m->gateway == level+1)
  1431.                 again=1;
  1432.             m = m->next;
  1433.         }
  1434.     } while (again);
  1435.  
  1436.     Sftpmode(Scon.ftp);
  1437. #ifdef PC
  1438.     Srcpmode(Scon.rcp);
  1439. #endif
  1440.     return(0);
  1441. }
  1442.