home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / contribu / byu_tel2.hqx / tcpip / confile.c < prev    next >
Text File  |  1989-11-09  |  32KB  |  1,459 lines

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