home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC / SRC15B34.ZIP / NETWORK.C < prev    next >
Text File  |  1997-08-03  |  47KB  |  1,885 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include <dos.h>
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #include <ctype.h>
  9. #include <mem.h>
  10. #include <conio.h>
  11. #include <io.h>
  12. #include <share.h>
  13. #include <errno.h>
  14. #include <malloc.h>
  15. #include <dir.h>
  16. #include <time.h>
  17. #include <process.h>
  18. #include <direct.h>
  19. #include "vardec.h"
  20. #include "net.h"
  21. #include "version.h"
  22. #include "retcode.h"
  23.  
  24. #define NUL '\0'
  25. #define LAST(s) s[strlen(s)-1]
  26. #define MAX_PATH 79
  27.  
  28. #define SHARE_LEVEL 10
  29. #define WAIT_TIME 10
  30. #define TRIES 100
  31.  
  32. #define MT_DESQVIEW 0x01
  33. #define MT_WINDOWS  0x02
  34. #define MT_OS2      0x04
  35. #define MT_NB       0x40
  36.  
  37. #define VIDEO 0x10
  38.  
  39. #define INI_NETWORK   0x01
  40. #define INI_GENERAL   0x02
  41. #define INI_NEWS      0x04
  42.  
  43. char *version = "Freeware PPP Net Packet Engine " VERSION;
  44. char *author = "Contact Frank Reid at edare@abs.net or 1@8213.WWIVnet for support";
  45.  
  46. unsigned _stklen = 8000;
  47.  
  48. typedef struct {
  49.   unsigned int sysnum;
  50.   char address[60];
  51. } net_address_rec;
  52.  
  53. configrec syscfg;
  54. configoverrec syscfgovr;
  55. net_networks_rec netcfg;
  56. net_system_list_rec *netsys;
  57. net_address_rec *netaddr;
  58.  
  59. int multitasker = 0, ini_section = 0, num_addr;
  60. char wwiv_net_no[20], maindir[121];
  61. char net_name[16], net_data[121];
  62. unsigned short net_sysnum;
  63. int num_sys_list, net_num, net_num_max, netnum;
  64. static int lsl_loaded;
  65.  
  66. char SMTPHOST[60], POPHOST[60], NEWSHOST[60], POPNAME[60], POPPASS[25];
  67.  
  68. char IPADDR[21], NETMASK[21], FWDNAME[60], FWDDOM[60];
  69. char DNS[21], DOMAIN[60], GATEWAY[60], temp_dir[MAXPATH];
  70. unsigned int KEEPSENT = 0, ALLMAIL = 1, CLEANUP = 0, MOREINFO = 0, TIMEOUT = 60, SOCK_DELAY = 30, INACTIVE = 60;
  71. unsigned int ONECALL = 0, PURGE = 1;
  72. int instance;
  73.  
  74. char *xenviron[50];
  75.  
  76. void dv_pause(void)
  77. {
  78.   __emit__(0xb8, 0x1a, 0x10, 0xcd, 0x15);
  79.   __emit__(0xb8, 0x00, 0x10, 0xcd, 0x15);
  80.   __emit__(0xb8, 0x25, 0x10, 0xcd, 0x15);
  81. }
  82.  
  83. void win_pause(void)
  84. {
  85.   __emit__(0x55, 0xb8, 0x80, 0x16, 0xcd, 0x2f, 0x5d);
  86. }
  87.  
  88. int get_dos_version(void)
  89. {
  90.   _AX = 0x3000;
  91.   geninterrupt(0x21);
  92.   if (_AX % 256 >= 10) {
  93.     multitasker |= MT_OS2;
  94.   }
  95.   return (_AX);
  96. }
  97.  
  98. int get_dv_version(void)
  99. {
  100.   int v;
  101.  
  102.   if (multitasker & MT_OS2)
  103.     return 0;
  104.   _AX = 0x2b01;
  105.   _CX = 0x4445;
  106.   _DX = 0x5351;
  107.   geninterrupt(0x21);
  108.   if (_AL == 0xff) {
  109.     return 0;
  110.   } else {
  111.     v = _BX;
  112.     multitasker |= MT_DESQVIEW;
  113.     return v;
  114.   }
  115. }
  116.  
  117. int get_win_version(void)
  118. {
  119.   int v = 0;
  120.  
  121.   __emit__(0x55, 0x06, 0x53);
  122.   _AX = 0x352f;
  123.   geninterrupt(0x21);
  124.   _AX = _ES;
  125.   if (_AX | _BX) {
  126.     _AX = 0x1600;
  127.     geninterrupt(0x2f);
  128.     v = _AX;
  129.     if (v % 256 <= 1)
  130.       v = 0;
  131.   }
  132.   __emit__(0x5b, 0x07, 0x5d);
  133.   if (v != 0)
  134.     multitasker |= MT_WINDOWS;
  135.   return (v);
  136. }
  137.  
  138. int get_nb_version(void)
  139. {
  140.   _AX = 0;
  141.   geninterrupt(0x2A);
  142.   return (_AH);
  143. }
  144.  
  145. void detect_multitask(void)
  146. {
  147.   get_dos_version();
  148.   get_win_version();
  149.   get_dv_version();
  150.   if (multitasker < 2)
  151.     if (get_nb_version())
  152.       multitasker = MT_NB;
  153. }
  154.  
  155. void giveup_timeslice(void)
  156. {
  157.   if (multitasker) {
  158.     switch (multitasker) {
  159.  case 1:
  160.  case 3:
  161.         dv_pause();
  162.         break;
  163.       case 2:
  164.       case 4:
  165.       case 5:
  166.       case 6:
  167.       case 7:
  168.         win_pause();
  169.         break;
  170.       default:
  171.         break;
  172.     }
  173.   }
  174. }
  175.  
  176. char *stripspace(char *str)
  177. {
  178.   char *obuf, *nbuf;
  179.  
  180.   if (str) {
  181.     for (obuf = str, nbuf = str; *obuf; ++obuf) {
  182.       if (!isspace(*obuf))
  183.         *nbuf++ = *obuf;
  184.     }
  185.     *nbuf = NULL;
  186.   }
  187.   return (str);
  188. }
  189.  
  190. int sh_write(int handle, void *buffer, unsigned long len)
  191. {
  192.   if (handle == -1) {
  193.     return (-1);
  194.   }
  195.   return (write(handle, buffer, (unsigned) len));
  196. }
  197.  
  198. int sh_open(char *path, int file_access, unsigned fmode)
  199. {
  200.   int handle, count, share;
  201.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  202.  
  203.   if ((file_access & O_RDWR) || (file_access & O_WRONLY) || (fmode & S_IWRITE)) {
  204.     share = SH_DENYRW;
  205.   } else {
  206.     share = SH_DENYWR;
  207.   }
  208.   handle = open(path, file_access | share, fmode);
  209.   if (handle < 0) {
  210.     count = 1;
  211.     fnsplit(path, drive, dir, file, ext);
  212.     if (access(path, 0) != -1) {
  213.       delay(WAIT_TIME);
  214.       handle = open(path, file_access | share, fmode);
  215.       while (((handle < 0) && (errno == EACCES)) && (count < TRIES)) {
  216.         if (count % 2)
  217.           delay(WAIT_TIME);
  218.         else
  219.           giveup_timeslice();
  220.         count++;
  221.         handle = open(path, file_access | share, fmode);
  222.       }
  223.     }
  224.   }
  225.   return (handle);
  226. }
  227.  
  228. int sh_open1(char *path, int access)
  229. {
  230.   unsigned fmode;
  231.  
  232.   fmode = 0;
  233.   if ((access & O_RDWR) || (access & O_WRONLY))
  234.     fmode |= S_IWRITE;
  235.   if ((access & O_RDWR) || (access & O_RDONLY))
  236.     fmode |= S_IREAD;
  237.   return (sh_open(path, access, fmode));
  238. }
  239.  
  240. int sh_close(int f)
  241. {
  242.   if (f != -1)
  243.     close(f);
  244.   return (-1);
  245. }
  246.  
  247. int sh_read(int handle, void *buf, unsigned len)
  248. {
  249.   if (handle == -1) {
  250.     return (-1);
  251.   }
  252.   return (read(handle, buf, len));
  253. }
  254.  
  255. long sh_lseek(int handle, long offset, int fromwhere)
  256. {
  257.   if (handle == -1) {
  258.     return (-1L);
  259.   }
  260.   return (lseek(handle, offset, fromwhere));
  261. }
  262.  
  263. FILE *fsh_open(char *path, char *fmode)
  264. {
  265.   FILE *f;
  266.   int count, share, md, fd;
  267.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  268.  
  269.   share = SH_DENYWR;
  270.   md = 0;
  271.   if (((char *) _fstrchr(fmode, 'w')) != NULL) {
  272.     share = SH_DENYRD;
  273.     md = O_RDWR | O_CREAT | O_TRUNC;
  274.   } else
  275.     if (((char *) _fstrchr(fmode, 'a')) != NULL) {
  276.     share = SH_DENYRD;
  277.     md = O_RDWR | O_CREAT;
  278.   } else {
  279.     md = O_RDONLY;
  280.   }
  281.   if (((char *) _fstrchr(fmode, 'b')) != NULL) {
  282.     md |= O_BINARY;
  283.   }
  284.   if (((char *) _fstrchr(fmode, '+')) != NULL) {
  285.     md &= ~O_RDONLY;
  286.     md |= O_RDWR;
  287.     share = SH_DENYRD;
  288.   }
  289.   fd = open(path, md | share, S_IREAD | S_IWRITE);
  290.   if (fd < 0) {
  291.     count = 1;
  292.     fnsplit(path, drive, dir, file, ext);
  293.     if ((access(path, 0)) != -1) {
  294.       delay(WAIT_TIME);
  295.       fd = open(path, md | share, S_IREAD | S_IWRITE);
  296.       while (((fd < 0) && (errno == EACCES)) && (count < TRIES)) {
  297.         delay(WAIT_TIME);
  298.         count++;
  299.         fd = open(path, md | share, S_IREAD | S_IWRITE);
  300.       }
  301.     }
  302.   }
  303.   if (fd > 0) {
  304.     if (((char *) _fstrchr(fmode, 'a')) != NULL)
  305.       sh_lseek(fd, 0L, SEEK_END);
  306.     f = fdopen(fd, fmode);
  307.     if (!f) {
  308.       close(fd);
  309.     }
  310.   } else
  311.     f = NULL;
  312.   return (f);
  313. }
  314.  
  315. void output(char *fmt, ...)
  316. {
  317.   va_list v;
  318.   char s[255];
  319.  
  320.   va_start(v, fmt);
  321.   vsprintf(s, fmt, v);
  322.   va_end(v);
  323.   fputs(s, stderr);
  324. }
  325.  
  326.  
  327. void backline(void)
  328. {
  329.   int i;
  330.  
  331.   output(" ");
  332.   for (i = wherex(); i > 0; i--)
  333.     output("\b \b");
  334. }
  335.  
  336.  
  337. int do_spawn(char *cl)
  338. {
  339.   int i, i1, l;
  340.   char *s, *ss[50];
  341.  
  342.   s = strdup(cl);
  343.   ss[0] = s;
  344.   i = 1;
  345.   l = strlen(s);
  346.   for (i1 = 1; i1 < l; i1++)
  347.     if (s[i1] == 32) {
  348.       s[i1] = 0;
  349.       ss[i++] = &(s[i1 + 1]);
  350.     }
  351.   ss[i] = NULL;
  352.   if (MOREINFO)
  353.     output("\n");
  354.   i = (spawnvpe(P_WAIT, ss[0], ss, xenviron) & 0x00ff);
  355.   free(s);
  356.   return (i);
  357. }
  358.  
  359. void unload_klos(void)
  360. {
  361.   char s[101];
  362.  
  363.   sprintf(s, "%s\\IPSTUB U", maindir);
  364.   do_spawn(s);
  365.   sprintf(s, "%s\\PPP U", maindir);
  366.   do_spawn(s);
  367.   if (!lsl_loaded) {
  368.     sprintf(s, "%s\\LSL U", maindir);
  369.     do_spawn(s);
  370.   }
  371. }
  372.  
  373. void cd_to(char *s)
  374. {
  375.   char *s1;
  376.   int i, db;
  377.  
  378.   s1 = s;
  379.   i = strlen(s1) - 1;
  380.   db = (s1[i] == '\\');
  381.   if (i == 0)
  382.     db = 0;
  383.   if ((i == 2) && (s1[1] == ':'))
  384.     db = 0;
  385.   if (db)
  386.     s1[i] = 0;
  387.   chdir(s1);
  388.   if (s[1] == ':')
  389.     setdisk(s[0] - 'A');
  390. }
  391.  
  392. void get_dir(char *s, int be)
  393. {
  394.   strcpy(s, "X:\\");
  395.   s[0] = 'A' + getdisk();
  396.   getcurdir(0, s + 3);
  397.   if (be) {
  398.     if (s[strlen(s) - 1] != '\\')
  399.       strcat(s, "\\");
  400.   }
  401. }
  402.  
  403. unsigned char *trimstr1(unsigned char *s)
  404. {
  405.   int i;
  406.   static char *whitespace = " \r\n\t";
  407.  
  408.   i = (int) strlen(s);
  409.   while ((i > 0) && ((char *) _fstrchr(whitespace, s[i - 1]) != NULL))
  410.     --i;
  411.   while ((i > 0) && ((char *) _fstrchr(whitespace, *s) != NULL)) {
  412.     memmove(s, s + 1, --i);
  413.   }
  414.   s[i] = NUL;
  415.   return (s);
  416. }
  417.  
  418. char *make_abs_path(unsigned char *checkdir)
  419. {
  420.   char newdir[121];
  421.  
  422.   if ((strlen(checkdir) < 3) || (checkdir[1] != ':') || (checkdir[2] != '\\')) {
  423.     cd_to(maindir);
  424.     cd_to(checkdir);
  425.     if (LAST(checkdir) == '\\')
  426.       get_dir(newdir, 1);
  427.     else
  428.       get_dir(newdir, 0);
  429.     cd_to(maindir);
  430.     strcpy(checkdir, newdir);
  431.   }
  432.   return checkdir;
  433. }
  434.  
  435. int exist(char *s)
  436. {
  437.   int i;
  438.   struct ffblk ff;
  439.  
  440.   i = findfirst(s, &ff, 0);
  441.   if (i)
  442.     return (0);
  443.   else
  444.     return (1);
  445. }
  446.  
  447. void set_net_num(int n)
  448. {
  449.   char s[121];
  450.   int f;
  451.  
  452.   sprintf(s, "%sNETWORKS.DAT", syscfg.datadir);
  453.   f = sh_open1(s, O_RDONLY | O_BINARY);
  454.   if (f < 0)
  455.     return;
  456.   lseek(f, ((long) (n)) * sizeof(net_networks_rec), SEEK_SET);
  457.   sh_read(f, &netcfg, sizeof(net_networks_rec));
  458.   close(f);
  459.   net_num = n;
  460.   net_sysnum = netcfg.sysnum;
  461.   strcpy(net_name, netcfg.name);
  462.   strcpy(net_data, make_abs_path(netcfg.dir));
  463.   if (LAST(net_data) != '\\')
  464.     strcat(net_data, "\\");
  465.   sprintf(wwiv_net_no, "WWIV_NET=%d", net_num);
  466. }
  467.  
  468. int make_path(char *s)
  469. {
  470.   unsigned int i;
  471.   char drive, current_path[MAX_PATH], current_drive, *p, *flp;
  472.   union REGS r;
  473.  
  474.   p = flp = strdup(s);
  475.   _getdcwd(0, current_path, MAX_PATH);
  476.   current_drive = *current_path - '@';
  477.   if (LAST(s) == '\\')
  478.     LAST(s) = 0;
  479.   if (p[1] == ':') {
  480.     drive = toupper(p[0]) - 'A' + 1;
  481.     if ((_osmajor == 3 && _osminor >= 1) || (_osmajor > 3)) {
  482.       r.x.ax = 0x4409;
  483.       r.h.bl = drive;
  484.       int86(0x21, &r, &r);
  485.       if (r.x.cflag)
  486.         return -3;
  487.     }
  488.     if (_chdrive(drive)) {
  489.       chdir(current_path);
  490.       _dos_setdrive(current_drive, &i);
  491.       return -2;
  492.     }
  493.     p += 2;
  494.   }
  495.   if (*p == '\\') {
  496.     chdir("\\");
  497.     p++;
  498.   }
  499.   for (; (p = strtok(p, "\\")) != 0; p = 0) {
  500.     if (chdir(p)) {
  501.       if (mkdir(p)) {
  502.         chdir(current_path);
  503.         _dos_setdrive(current_drive, &i);
  504.         return -1;
  505.       }
  506.       chdir(p);
  507.     }
  508.   }
  509.   chdir(current_path);
  510.   if (flp)
  511.     free(flp);
  512.   return 0;
  513. }
  514.  
  515. void process_mail(void)
  516. {
  517.   char s[121];
  518.  
  519.   sprintf(s, "%s\\FLINK.EXE", maindir);
  520.   if (exist(s))
  521.     do_spawn(s);
  522.   sprintf(s, "%s\\LINKER.EXE", maindir);
  523.   if (exist(s))
  524.     do_spawn(s);
  525. }
  526.  
  527. int valid_system(unsigned int ts)
  528. {
  529.   int i;
  530.  
  531.   for (i = 0; i < num_sys_list; i++) {
  532.     if (netsys[i].sysnum == ts) {
  533.       if (netsys[i].numhops == 1)
  534.         return (1);
  535.       else
  536.         return (0);
  537.     }
  538.   }
  539.   return (0);
  540. }
  541.  
  542. int create_contact_ppp(void)
  543. {
  544.   char *ss, fn[101], s[81];
  545.   unsigned short node;
  546.   int curfile, i;
  547.   net_address_rec curaddr;
  548.   FILE *fp, *fc;
  549.  
  550.   sprintf(fn, "%sCONTACT.PPP", net_data);
  551.   if ((fc = fsh_open(fn, "wb+")) == NULL) {
  552.     output("\n ■ Unable to create %s!\n", fn);
  553.     return (1);
  554.   }
  555.   curfile = 1;
  556.   num_addr = 0;
  557.   do {
  558.     sprintf(fn, "%sADDRESS.%d", net_data, curfile);
  559.     if ((fp = fsh_open(fn, "rt")) == NULL)
  560.       curfile = -1;
  561.     while ((curfile > 0) && (fgets(s, 80, fp) != NULL)) {
  562.       if (s[0] != '@')
  563.         continue;
  564.       ss = strtok(s, " \t\r");
  565.       node = atoi(&ss[1]);
  566.       if (node) {
  567.         ss = strtok(NULL, " \t\r");
  568.         trimstr1(ss);
  569.         curaddr.sysnum = node;
  570.         strcpy(curaddr.address, ss);
  571.         fwrite(&curaddr, sizeof(net_address_rec), 1, fc);
  572.         ++num_addr;
  573.       }
  574.     }
  575.     if (fp != NULL)
  576.       fclose(fp);
  577.     ++curfile;
  578.   } while (curfile > 0);
  579.   if ((netaddr = (net_address_rec *) farmalloc((num_addr) *
  580.                                      sizeof(net_address_rec))) == NULL) {
  581.     output("\n ■ Insufficient memory to process CONTACT.PPP!\n");
  582.     return (1);
  583.   }
  584.   fseek(fc, 0L, SEEK_SET);
  585.   fread(netaddr, sizeof(net_address_rec), num_addr, fc);
  586.   sprintf(fn, "%sADDRESS.0", net_data);
  587.   if ((fp = fsh_open(fn, "rt")) == NULL) {
  588.     if (fc != NULL)
  589.       fclose(fc);
  590.     return(0);
  591.   }
  592.   while (fgets(s, 80, fp) != NULL) {
  593.     if (s[0] != '@')
  594.       continue;
  595.     ss = strtok(s, " \t\r");
  596.     node = atoi(&ss[1]);
  597.     do {
  598.       ss = strtok(NULL, " \t\r");
  599.       switch (ss[0]) {
  600.         case '-':
  601.           for (i = 0; i < num_addr; i++)
  602.             if (node == netaddr[i].sysnum)
  603.               netaddr[i].sysnum = 0;
  604.           break;
  605.       }
  606.     } while (ss);
  607.   }
  608.   if (fp != NULL)
  609.     fclose(fp);
  610.   fseek(fc, 0L, SEEK_SET);
  611.   fwrite(netaddr, sizeof(net_address_rec), num_addr, fc);
  612.   if (fc != NULL)
  613.     fclose(fc);
  614.   return (0);
  615. }
  616.  
  617. int read_contact_ppp(void)
  618. {
  619.   char fn[101];
  620.   FILE *fc;
  621.  
  622.   if (netaddr == NULL) {
  623.     sprintf(fn, "%sCONTACT.PPP", net_data);
  624.     if ((fc = fsh_open(fn, "rb")) == NULL) {
  625.       output("\n ■ Unable to open %s!", fn);
  626.       return (1);
  627.     }
  628.     if ((netaddr = (net_address_rec *) farmalloc((num_addr) *
  629.                                        sizeof(net_address_rec))) == NULL) {
  630.       output("\n ■ Insufficient memory to process CONTACT.PPP!");
  631.       fclose(fc);
  632.       return (1);
  633.     }
  634.     fseek(fc, 0L, SEEK_SET);
  635.     fread(netaddr, sizeof(net_address_rec), num_addr, fc);
  636.     if (fc != NULL)
  637.       fclose(fc);
  638.   }
  639.   return(0);
  640. }
  641.  
  642.  
  643. void good_addr(char *address, unsigned short sn)
  644. {
  645.   int i;
  646.  
  647.   address[0] = 0;
  648.   if (read_contact_ppp())
  649.     return;
  650.   for (i=0; ((i < num_addr) && (!address[0])); i++)
  651.     if (sn == netaddr[i].sysnum)
  652.       strcpy(address, netaddr[i].address);
  653. }
  654.  
  655. int copyfile(char *input, char *output)
  656. {
  657.   int f1, f2, i;
  658.   char *b;
  659.   struct ftime ft;
  660.  
  661.   if ((strcmp(input, output) != 0) && (exist(input)) && (!exist(output))) {
  662.     if ((b = (char *) malloc(16400)) == NULL)
  663.       return 0;
  664.     f1 = sh_open1(input, O_RDONLY | O_BINARY);
  665.     if (!f1) {
  666.       free(b);
  667.       b = NULL;
  668.       return 0;
  669.     }
  670.     getftime(f1, &ft);
  671.     f2 = sh_open(output, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  672.     if (!f2) {
  673.       free(b);
  674.       b = NULL;
  675.       sh_close(f1);
  676.       return 0;
  677.     }
  678.     i = read(f1, (void *) b, 16384);
  679.     while (i > 0) {
  680.       sh_write(f2, (void *) b, i);
  681.       i = read(f1, (void *) b, 16384);
  682.     }
  683.     f1 = sh_close(f1);
  684.     setftime(f2, &ft);
  685.     f2 = sh_close(f2);
  686.     free(b);
  687.     b = NULL;
  688.   }
  689.   return 1;
  690. }
  691.  
  692. void do_exit(int exitlevel)
  693. {
  694.   if (netaddr != NULL)
  695.     farfree(netaddr);
  696.  
  697.   delay(2000);
  698.   exit(exitlevel);
  699. }
  700.  
  701. int uu(char *fn, char *pktname, char *dest)
  702. {
  703.   int ok;
  704.   char s[121], s1[121], s2[81];
  705.   FILE *fp;
  706.  
  707.   sprintf(s, "%sMQUEUE\\%s.UUE", net_data, pktname);
  708.   if ((fp = fsh_open(s, "wt")) == NULL) {
  709.     output("\n ■ Unable to open %s for write operations!", s);
  710.     do_exit(EXIT_FAILURE);
  711.   } else {
  712.     sprintf(s2, "from: %s@%s\n", POPNAME, DOMAIN);
  713.     fprintf(fp, s2);
  714.     sprintf(s2, "to: %s\n", dest);
  715.     fprintf(fp, s2);
  716.     sprintf(s2, "subject: @%s NET PACKET : %s.UUE\n\n", net_name, pktname);
  717.     fprintf(fp, s2);
  718.   }
  719.   if (fp != NULL)
  720.     fclose(fp);
  721.   sprintf(s1, "%s\\UU -encode %s %s", maindir, fn, s);
  722.   ok = do_spawn(s1);
  723.   return ok;
  724. }
  725.  
  726. int update_contact(unsigned short sy, unsigned long sb, unsigned long rb)
  727. {
  728.   char s[101];
  729.   int i, i1, f;
  730.   long cur_time, l;
  731.  
  732.   sprintf(s, "%sCONTACT.NET", net_data);
  733.   f = sh_open1(s, O_RDONLY | O_BINARY);
  734.   if (f >= 0) {
  735.     l = filelength(f);
  736.     netcfg.num_ncn = (int) (l / sizeof(net_contact_rec));
  737.     if ((netcfg.ncn = (net_contact_rec *) malloc((netcfg.num_ncn + 2) *
  738.                                         sizeof(net_contact_rec))) == NULL) {
  739.       output("\n ■ Unable to allocate %d bytes of memory to update CONTACT.NET",
  740.               (int) (netcfg.num_ncn + 2) * sizeof(net_contact_rec));
  741.       sh_close(f);
  742.       return 1;
  743.     }
  744.     sh_lseek(f, 0L, SEEK_SET);
  745.     sh_read(f, (void *) netcfg.ncn, netcfg.num_ncn * sizeof(net_contact_rec));
  746.     sh_close(f);
  747.   }
  748.   for (i = 0; i < netcfg.num_ncn; i++)
  749.     if (netcfg.ncn[i].systemnumber == sy)
  750.       i1 = i;
  751.   time(&cur_time);
  752.   netcfg.ncn[i1].lasttry = cur_time;
  753.   ++netcfg.ncn[i1].numcontacts;
  754.   if (!netcfg.ncn[i1].firstcontact)
  755.     netcfg.ncn[i1].firstcontact = cur_time;
  756.   netcfg.ncn[i1].lastcontact = cur_time;
  757.   netcfg.ncn[i1].lastcontactsent = cur_time;
  758.   netcfg.ncn[i1].bytes_sent += sb;
  759.   if (rb)
  760.     netcfg.ncn[i1].bytes_received += rb;
  761.   netcfg.ncn[i1].bytes_waiting = 0L;
  762.   sprintf(s, "%sS%hd.net", net_data, sy);
  763.   if (!exist(s))
  764.     sprintf(s, "%sZ%hd.net", net_data, sy);
  765.   f = sh_open1(s, O_RDONLY | O_BINARY);
  766.   if (f > 0) {
  767.     netcfg.ncn[i1].bytes_waiting += filelength(f);
  768.     close(f);
  769.   }
  770.   sprintf(s, "%sCONTACT.NET", net_data);
  771.   f = sh_open1(s, O_RDWR | O_CREAT | O_BINARY);
  772.   if (f > 0) {
  773.     sh_lseek(f, 0L, SEEK_SET);
  774.     sh_write(f, (void *) netcfg.ncn, netcfg.num_ncn * sizeof(net_contact_rec));
  775.     sh_close(f);
  776.   }
  777.   if (netcfg.ncn)
  778.     free(netcfg.ncn);
  779.   return 0;
  780. }
  781.  
  782.  
  783. int update_contacts(unsigned short sy, unsigned long sb, unsigned long rb)
  784. {
  785.   int i,rc;
  786.  
  787.   rc = update_contact(sy, sb, rb);
  788.   if (read_contact_ppp())
  789.     return (rc);
  790.   for (i = 0; i < num_addr; i++)
  791.     if (netaddr[i].sysnum != sy)
  792.       update_contact(netaddr[i].sysnum, 0, 0);
  793.   return (rc);
  794. }
  795.  
  796. int uu_packets(void)
  797. {
  798.   char pktname[21], s[121], s1[121], s2[121], s3[121], destaddr[101], temp[121];
  799.   int found, sz, f, f1, i;
  800.   unsigned short node;
  801.   unsigned long sbytes, basename;
  802.  
  803.   num_sys_list = 0;
  804.   basename = time(NULL);
  805.   sprintf(s, "%sBBSDATA.NET", net_data);
  806.   f = sh_open1(s, O_RDONLY | O_BINARY);
  807.   if (f > 0) {
  808.     num_sys_list = (int) (filelength(f) / sizeof(net_system_list_rec));
  809.     if ((netsys = (net_system_list_rec *) malloc((num_sys_list + 2) *
  810.                                     sizeof(net_system_list_rec))) == NULL) {
  811.       output("\n ■ Unable to allocate %d bytes of memory for BBSDATA.NET",
  812.               (int) (num_sys_list + 2) * sizeof(net_system_list_rec));
  813.       sh_close(f);
  814.       return 0;
  815.     }
  816.     sh_lseek(f, 0L, SEEK_SET);
  817.     sh_read(f, (void *) netsys, num_sys_list * sizeof(net_system_list_rec));
  818.     sh_close(f);
  819.   } else
  820.     return 0;
  821.   for (i=0; i < num_addr; i++) {
  822.     node = netaddr[i].sysnum;
  823.     if ((valid_system(node)) && (node != 32767)) {
  824.       sprintf(s1, "%sS%hd.NET", net_data, node);
  825.       if (exist(s1))
  826.         sz = 0;
  827.       else {
  828.         sprintf(s1, "%sZ%hd.NET", net_data, node);
  829.         if (exist(s1))
  830.           sz = 1;
  831.         else
  832.           continue;
  833.       }
  834.       do {
  835.         sprintf(pktname, "%8.8lx", ++basename);
  836.         sprintf(temp, "%sMQUEUE\\%s.UUE", net_data, pktname);
  837.       } while (exist(temp));
  838.       good_addr(destaddr, node);
  839.       backline();
  840.       output("\r ■ Encoding %s%hd.NET as %s.UUE -",
  841.               sz ? "Z" : "S", node, strupr(pktname));
  842.       if ((uu(s1, pktname, destaddr)) == EXIT_FAILURE) {
  843.         output("\n ■ Error creating %sMQUEUE\\%s.UUE", net_data, pktname);
  844.         free(netsys);
  845.         do_exit(EXIT_FAILURE);
  846.       } else {
  847.         found = 1;
  848.         if (KEEPSENT) {
  849.           sprintf(s3, "%sMQUEUE\\%s.UUE", net_data, pktname);
  850.           sprintf(s2, "%sSENT\\%s.SNT", net_data, pktname);
  851.           f1 = sh_open1(s3, O_RDONLY | O_BINARY);
  852.           if (f1 > 0) {
  853.             sbytes = filelength(f1);
  854.             sh_close(f1);
  855.           }
  856.           if (!copyfile(s3, s2))
  857.             output("\n ■ Error moving %s%hd.NET", sz ? "Z" : "S", node);
  858.         }
  859.         unlink(s1);
  860.         update_contact(node, sbytes, 0);
  861.       }
  862.     }
  863.   }
  864.   if (netsys)
  865.     free(netsys);
  866.   return found;
  867. }
  868.  
  869. int purge_sent(void)
  870. {
  871.   char s[121];
  872.   int f1, howmany = 0;
  873.   long age;
  874.   struct ffblk ff;
  875.   struct stat fileinfo;
  876.  
  877.   sprintf(s, "%sSENT\\*.*", net_data);
  878.   f1 = findfirst(s, &ff, 0);
  879.   while (f1 == 0) {
  880.     sprintf(s, "%sSENT\\%s", net_data, ff.ff_name);
  881.     if (stat(s, &fileinfo) == 0) {
  882.       age = (time(NULL) - fileinfo.st_atime);
  883.       if (age > (86400L * KEEPSENT)) {
  884.         ++howmany;
  885.         unlink(s);
  886.       }
  887.     }
  888.     f1 = findnext(&ff);
  889.   }
  890.   return howmany;
  891. }
  892.  
  893. int parse_net_ini(void)
  894. {
  895.   char cursect;
  896.   char line[121], *ss;
  897.   FILE *fp;
  898.  
  899.   if ((fp = fsh_open("NET.INI", "rt")) == NULL)
  900.     return (0);
  901.   while (fgets(line, 80, fp)) {
  902.     stripspace(line);
  903.     ss = NULL;
  904.     ss = strtok(line, "=");
  905.     if (ss)
  906.       ss = strtok(NULL, "\n");
  907.     if ((line[0] == ';') || (line[0] == '\n') || (strlen(line) == 0))
  908.       continue;
  909.     if ((strnicmp(line, "[FILENET]", 9) == 0) ||
  910.         (strnicmp(line, "[PPPNET]", 8) == 0)) {
  911.       cursect = INI_NETWORK;
  912.       ini_section |= INI_NETWORK;
  913.       continue;
  914.     }
  915.     if (strnicmp(line, "[GENERAL]", 9) == 0) {
  916.       cursect = INI_GENERAL;
  917.       ini_section |= INI_GENERAL;
  918.       continue;
  919.     }
  920.     if (strnicmp(line, "[NEWS]", 6) == 0) {
  921.       cursect = INI_NEWS;
  922.       ini_section |= INI_NEWS;
  923.       continue;
  924.     }
  925.     if (cursect & INI_NETWORK) {
  926.       if (strnicmp(line, "SMTPHOST", 8) == 0) {
  927.         if (ss)
  928.           strcpy(SMTPHOST, ss);
  929.         continue;
  930.       }
  931.       if (strnicmp(line, "POPHOST", 7) == 0) {
  932.         if (ss)
  933.           strcpy(POPHOST, ss);
  934.         continue;
  935.       }
  936.       if (strnicmp(line, "POPNAME", 7) == 0) {
  937.         if (ss)
  938.           strcpy(POPNAME, ss);
  939.         continue;
  940.       }
  941.       if (strnicmp(line, "POPPASS", 7) == 0) {
  942.         if (ss)
  943.           strcpy(POPPASS, ss);
  944.         continue;
  945.       }
  946.     }
  947.     if (cursect & INI_GENERAL) {
  948.       if (strnicmp(line, "TIMEOUT", 7) == 0) {
  949.         if (atoi(ss))
  950.           TIMEOUT = atoi(ss);
  951.         continue;
  952.       }
  953.       if (strnicmp(line, "SOCK_DELAY", 10) == 0) {
  954.         if (atoi(ss))
  955.           SOCK_DELAY = atoi(ss);
  956.         continue;
  957.       }
  958.       if (strnicmp(line, "INACTIVE", 13) == 0) {
  959.         if (atoi(ss))
  960.           INACTIVE = atoi(ss);
  961.         continue;
  962.       }
  963.       if (strnicmp(line, "KEEPSENT", 8) == 0) {
  964.         if (atoi(ss))
  965.           KEEPSENT = atoi(ss);
  966.         continue;
  967.       }
  968.       if (strnicmp(line, "PURGE", 5) == 0) {
  969.         if (toupper(ss[0]) == 'N')
  970.           PURGE = 0;
  971.         continue;
  972.       }
  973.       if (strnicmp(line, "ALLMAIL", 7) == 0) {
  974.         if (toupper(ss[0]) == 'N')
  975.           ALLMAIL = 0;
  976.         continue;
  977.       }
  978.       if (strnicmp(line, "ONECALL", 7) == 0) {
  979.         if (toupper(ss[0]) == 'Y')
  980.           ONECALL = 1;
  981.         continue;
  982.       }
  983.       if (strnicmp(line, "MOREINFO", 8) == 0) {
  984.         if (toupper(ss[0]) == 'Y')
  985.           MOREINFO = 1;
  986.         continue;
  987.       }
  988.       if (strnicmp(line, "CLEANUP", 7) == 0) {
  989.         if (toupper(ss[0]) == 'Y')
  990.           CLEANUP = 1;
  991.         continue;
  992.       }
  993.       if (strnicmp(line, "IPADDR", 6) == 0) {
  994.         if ((ss) && (ss[0] != '0'))
  995.           strcpy(IPADDR, ss);
  996.         continue;
  997.       }
  998.       if (strnicmp(line, "NETMASK", 7) == 0) {
  999.         if (ss)
  1000.           strcpy(NETMASK, ss);
  1001.         continue;
  1002.       }
  1003.       if (strnicmp(line, "DNS", 3) == 0) {
  1004.         if (ss)
  1005.           strcpy(DNS, ss);
  1006.         continue;
  1007.       }
  1008.       if (strnicmp(line, "DOMAIN", 6) == 0) {
  1009.         if (ss)
  1010.           strcpy(DOMAIN, ss);
  1011.         continue;
  1012.       }
  1013.       if (strnicmp(line, "FWDNAME", 7) == 0) {
  1014.         if (ss)
  1015.           strcpy(FWDNAME, ss);
  1016.         continue;
  1017.       }
  1018.       if (strnicmp(line, "FWDDOM", 6) == 0) {
  1019.         if (ss)
  1020.           strcpy(FWDDOM, ss);
  1021.         continue;
  1022.       }
  1023.       if (strnicmp(line, "GATEWAY", 7) == 0) {
  1024.         if ((ss) && (ss[0] != '0'))
  1025.           strcpy(GATEWAY, ss);
  1026.         continue;
  1027.       }
  1028.     }
  1029.     if (cursect & INI_NEWS) {
  1030.       if (strnicmp(line, "NEWSHOST", 8) == 0) {
  1031.         if (ss)
  1032.           strcpy(NEWSHOST, ss);
  1033.         continue;
  1034.       }
  1035.     }
  1036.   }
  1037.   if (!FWDNAME[0])
  1038.     strcpy(FWDNAME, POPNAME);
  1039.   if (!FWDDOM[0])
  1040.     strcpy(FWDDOM, DOMAIN);
  1041.   if (fp != NULL)
  1042.     fclose(fp);
  1043.   return (1);
  1044. }
  1045.  
  1046.  
  1047. int count_lines(char *s)
  1048. {
  1049.   FILE *fp;
  1050.   char fn[121];
  1051.   unsigned int nl = 0;
  1052.   const int NEWLINE = '\n';
  1053.   int c;
  1054.  
  1055.   strcpy(fn, s);
  1056.   if ((fp = fsh_open(fn, "rt")) == NULL) {
  1057.     printf("\n ■ Cannot open %s", fn);
  1058.     return 0;
  1059.   }
  1060.   while ((c = getc(fp)) != EOF) {
  1061.     if (c == NEWLINE)
  1062.       ++nl;
  1063.   }
  1064.   if (fp != NULL)
  1065.     fclose(fp);
  1066.   return nl;
  1067. }
  1068.  
  1069. typedef struct {
  1070.   char line[81];
  1071. } nlines;
  1072.  
  1073. nlines *NETLOG;
  1074.  
  1075. int write_netlog(int sn, long sent, long recd, char *tmused)
  1076. {
  1077.   FILE *fp;
  1078.   int i = 0;
  1079.   unsigned int lines;
  1080.   char s[81], s1[81], s2[81], fn[121];
  1081.   struct tm *time_now;
  1082.   time_t some;
  1083.  
  1084.   sprintf(fn, "%sNET.LOG", syscfg.gfilesdir);
  1085.   lines = 0;
  1086.   lines = count_lines(fn);
  1087.   if ((NETLOG = ((nlines *) malloc((lines + 2) * 81))) == NULL) {
  1088.     output("\n ■ Unable to allocate %d bytes for NET.LOG entry",
  1089.             (lines + 2) * 81);
  1090.     return 1;
  1091.   }
  1092.   if ((fp = fsh_open(fn, "r")) == NULL)
  1093.     return 1;
  1094.   while (fgets(s, 80, fp)) {
  1095.     strtok(s, "\n");
  1096.     strcpy(NETLOG[i++].line, s);
  1097.   }
  1098.   if (fp != NULL)
  1099.     fclose(fp);
  1100.   time(&some);
  1101.   time_now = localtime(&some);
  1102.   strftime(s1, 35, "%m/%d/%y %H:%M:%S", time_now);
  1103.   if ((sent) || (recd)) {
  1104.     if ((recd) && (!sent))
  1105.       sprintf(s2, "       , R:%4ldk,", recd);
  1106.     else {
  1107.       if ((recd) && (sent))
  1108.         sprintf(s2, "S:%4ldk, R:%4ldk,", sent, recd);
  1109.       else
  1110.         sprintf(s2, "S:%4ldk,         ", sent);
  1111.     }
  1112.   } else
  1113.     strcpy(s2, "                 ");
  1114.   fp = fsh_open(fn, "wt+");
  1115.   fprintf(fp, "%s To %5d, %s          %4s min  %s\n", s1, sn, s2,
  1116.           tmused, net_name);
  1117.   for (i = 0; i < lines; i++)
  1118.     fprintf(fp, "%s\n", NETLOG[i].line);
  1119.   if (NETLOG)
  1120.     free(NETLOG);
  1121.   NETLOG = NULL;
  1122.   if (fp != NULL)
  1123.     fclose(fp);
  1124.   return 0;
  1125. }
  1126.  
  1127. void read_networks(void)
  1128. {
  1129.   int f;
  1130.   char s[121];
  1131.  
  1132.   sprintf(s, "%sNETWORKS.DAT", syscfg.datadir);
  1133.   f = sh_open1(s, O_RDONLY | O_BINARY);
  1134.   net_num_max = 0;
  1135.   if (f > 0) {
  1136.     net_num_max = (int) (filelength(f) / sizeof(net_networks_rec));
  1137.     sh_close(f);
  1138.   }
  1139. }
  1140.  
  1141. void init(void)
  1142. {
  1143.   char s[81], s1[81], *ss;
  1144.   int i, i1, dv, f;
  1145.   struct tm *time_now;
  1146.   time_t some;
  1147.  
  1148.   output("\n%s\n%s\n\n", version, author);
  1149.   get_dir(maindir, 0);
  1150.   ss = getenv("WWIV_INSTANCE");
  1151.   if (ss) {
  1152.     instance = atoi(ss);
  1153.     if ((instance <= 0) || (instance > 999)) {
  1154.       output("\n ■ WWIV_INSTANCE can only be 1..999!");
  1155.       instance = 1;
  1156.     }
  1157.   } else {
  1158.     instance = 1;
  1159.   }
  1160.  
  1161.   detect_multitask();
  1162.  
  1163.   switch (multitasker) {
  1164.     case 1:
  1165.       dv = get_dv_version();
  1166.       sprintf(s1, "DesqView %d.%02d", dv / 256, dv % 256);
  1167.       break;
  1168.     case 2:
  1169.       dv = get_win_version();
  1170.       if (dv == 4)
  1171.         strcpy(s1, "Windows 95");
  1172.       else
  1173.         sprintf(s1, "Windows %d.%02d", dv % 256, dv / 256);
  1174.       break;
  1175.     case 3:
  1176.       dv = get_dv_version();
  1177.       sprintf(s1, "Windows and DesqView %d.%02d", dv / 256, dv % 256);
  1178.       break;
  1179.     case 4:
  1180.     case 5:
  1181.     case 6:
  1182.     case 7:
  1183.       if ((_osmajor / 10 == 2) && (_osminor >= 30))
  1184.         strcpy(s1, "OS/2 Warp");
  1185.       else
  1186.         sprintf(s1, "OS/2 %d.%2.2d", _osmajor / 10, _osminor);
  1187.       break;
  1188.     case 8:
  1189.       sprintf(s1, "NETBIOS network");
  1190.       multitasker = 1;
  1191.       break;
  1192.     default:
  1193.       strcpy(s1, "DOS");
  1194.       break;
  1195.   }
  1196.   strcpy(s, "CONFIG.DAT");
  1197.   f = sh_open1(s, O_RDONLY | O_BINARY);
  1198.   if (f < 0) {
  1199.     output("\n ■ %s NOT FOUND.", s);
  1200.     return;
  1201.   }
  1202.   sh_read(f, (void *) (&syscfg), sizeof(configrec));
  1203.   sh_close(f);
  1204.   output(" ■ Running under %s on instance %d ", s1, instance);
  1205.   time(&some);
  1206.   time_now = localtime(&some);
  1207.   strftime(s, 80, "at %I:%M%p, %d %b %y", time_now);
  1208.   printf(s);
  1209.   strcpy(s, "CONFIG.OVR");
  1210.   f = sh_open1(s, O_RDONLY | O_BINARY);
  1211.   if (f < 0) {
  1212.     output("\n ■ %s NOT FOUND.", s);
  1213.     return;
  1214.   }
  1215.   sh_lseek(f, (instance - 1) * sizeof(configoverrec), SEEK_SET);
  1216.   read(f, &syscfgovr, sizeof(configoverrec));
  1217.   f = sh_close(f);
  1218.   sprintf(s, "%sINSTANCE.DAT", syscfg.datadir);
  1219.   if (!exist(s)) {
  1220.     output("\n ■ %s NOT FOUND.", s);
  1221.     return;
  1222.   }
  1223.   read_networks();
  1224.   i = i1 = 0;
  1225.   while (environ[i] != NULL) {
  1226.     xenviron[i1++] = environ[i];
  1227.     ++i;
  1228.   }
  1229.   xenviron[i1] = NULL;
  1230. }
  1231.  
  1232. long getfctime(char *s)
  1233. {
  1234.   struct stat statbuf;
  1235.  
  1236.   if (stat(s, &statbuf) < 0)
  1237.     return (0L);
  1238.   else
  1239.     return (statbuf.st_atime);
  1240. }
  1241.  
  1242. int process_bbsdata(void)
  1243. {
  1244.   char s[101];
  1245.   unsigned long bbslist_ctime, connect_ctime, callout_ctime, bbsdata_ctime;
  1246.   int tf, n, net3;
  1247.  
  1248.   net3 = 0;
  1249.   sprintf(s, "%sBBSLIST.NET", net_data);
  1250.   bbslist_ctime = getfctime(s);
  1251.   sprintf(s, "%sCONNECT.NET", net_data);
  1252.   connect_ctime = getfctime(s);
  1253.   sprintf(s, "%sCALLOUT.NET", net_data);
  1254.   callout_ctime = getfctime(s);
  1255.   sprintf(s, "%sBBSDATA.NET", net_data);
  1256.   bbsdata_ctime = getfctime(s);
  1257.   sprintf(s, "%sBBSLIST.UPD", net_data);
  1258.   bbslist_ctime = getfctime(s);
  1259.   sprintf(s, "%sCONNECT.UPD", net_data);
  1260.   connect_ctime = getfctime(s);
  1261.  
  1262.   n = 0;
  1263.   tf = ((bbslist_ctime > bbsdata_ctime) || (connect_ctime > bbsdata_ctime));
  1264.   if (tf)
  1265.     n = 1;
  1266.   tf = (tf || (callout_ctime > bbsdata_ctime));
  1267.   if (tf) {
  1268.     sprintf(s, "NETWORK3 .%d", netnum);
  1269.     if (n) {
  1270.       sprintf(s, "NETWORK3 .%d Y", netnum);
  1271.       net3 = 1;
  1272.     }
  1273.     do_spawn(s);
  1274.   }
  1275.   return (net3);
  1276. }
  1277.  
  1278. void do_it(char *cl)
  1279. {
  1280.   int i, i1, l;
  1281.   char *s, *ss[30];
  1282.  
  1283.   s = strdup(cl);
  1284.   ss[0] = s;
  1285.   i = 1;
  1286.   l = strlen(s);
  1287.   for (i1 = 1; i1 < l; i1++)
  1288.     if (s[i1] == 32) {
  1289.       s[i1] = 0;
  1290.       ss[i++] = &(s[i1 + 1]);
  1291.     }
  1292.   ss[i] = NULL;
  1293.   execvpe(ss[0], ss, xenviron);
  1294. }
  1295.  
  1296. int create_wattcp_cfg(void)
  1297. {
  1298.   char s[MAXPATH], s1[41];
  1299.   FILE *fp;
  1300.  
  1301.   sprintf(s, "%s\\WATTCP.CFG", maindir);
  1302.   if ((fp = fsh_open(s, "wt")) == NULL) {
  1303.     output("\n ■ Can't open %s for output!", s);
  1304.     return 1;
  1305.   }
  1306.   fseek(fp, 0L, SEEK_SET);
  1307.   sprintf(s, "my_ip=%s\n", IPADDR);
  1308.   fprintf(fp, s);
  1309.   fprintf(fp, "netmask=%s\n", NETMASK);
  1310.   fprintf(fp, "nameserver=%s\n", DNS);
  1311.   if (GATEWAY[0] == 0) {
  1312.     strcpy(s1, IPADDR);
  1313.     while (LAST(s1) != '.')
  1314.       LAST(s1) = 0;
  1315.     strcat(s1, "1");
  1316.     strcpy(GATEWAY, s1);
  1317.   }
  1318.   sprintf(s, "gateway=%s\n", GATEWAY);
  1319.   fprintf(fp, s);
  1320.   fprintf(fp, "domainslist=\"%s\"\n", DOMAIN);
  1321.   fprintf(fp, "hostname=\"%s\"\n", POPNAME);
  1322.   fprintf(fp, "sockdelay=%d\n", SOCK_DELAY);
  1323.   fprintf(fp, "inactive=%d\n", INACTIVE);
  1324.   if (fp != NULL)
  1325.     fclose(fp);
  1326.   return 0;
  1327. }
  1328.  
  1329. int check_for_lsl(void)
  1330. {
  1331.   union REGS r;
  1332.   struct SREGS s;
  1333.   char *intstr;
  1334.  
  1335.   for (r.h.ah = 0xc0; r.h.ah != 0; r.h.ah++) {
  1336.     r.h.al = 0;
  1337.     int86x(0x2f, &r, &r, &s);
  1338.     if (r.h.al == 0xff) {
  1339.       intstr = (char *) MK_FP(s.es, r.x.si);
  1340.       if (strncmp(intstr, "LINKSUP$", 8) == 0)
  1341.         return 1;
  1342.     }
  1343.   }
  1344.   return 0;
  1345. }
  1346.  
  1347. void klos_ppp(void)
  1348. {
  1349.   char s[121], *ss;
  1350.   int i;
  1351.   FILE *fp;
  1352.  
  1353.   lsl_loaded = check_for_lsl();
  1354.   if (!lsl_loaded) {
  1355.     sprintf(s, "%s\\LSL.COM", maindir);
  1356.     if (exist(s)) {
  1357.       output("\n ■ Loading Link Support Layer and ");
  1358.       do_spawn(s);
  1359.     } else {
  1360.       output("\n ■ LSL.COM not in BBS main directory!");
  1361.       do_exit(EXIT_FAILURE);
  1362.     }
  1363.   } else
  1364.     output("\n ■ LSL already in memory - loading ");
  1365.   sprintf(s, "%s\\PPP.EXE", maindir);
  1366.   if (exist(s)) {
  1367.     output("PPP packet driver.");
  1368.     do_spawn(s);
  1369.   } else {
  1370.     output("\n ■ %s\\PPP.EXE not found!", maindir);
  1371.     do_exit(EXIT_FAILURE);
  1372.   }
  1373.   while (kbhit())
  1374.     getch();
  1375.   sprintf(s, "%s\\PPPSTATE.EXE", maindir);
  1376.   if (exist(s)) {
  1377.     output("\n ■ Dialing %s and waiting %d seconds for connection... ", DOMAIN, TIMEOUT);
  1378.     sprintf(s, "%s\\PPPSTATE.EXE WAIT=%d IP", maindir, TIMEOUT);
  1379.     i = do_spawn(s);
  1380.     switch (i) {
  1381.       case 0:
  1382.         output(" connected!");
  1383.         break;
  1384.       case 1:
  1385.         output("\n ■ Unable to establish connection... aborting");
  1386.         sprintf(s, "%s\\PPP U", maindir);
  1387.         do_spawn(s);
  1388.         if (!lsl_loaded) {
  1389.           sprintf(s, "%s\\LSL U", maindir);
  1390.           do_spawn(s);
  1391.         }
  1392.         do_exit(EXIT_FAILURE);
  1393.       case 2:
  1394.         output("\n ■ Unable to find PPP layer... aborting");
  1395.         sprintf(s, "%s\\PPP U", maindir);
  1396.         do_spawn(s);
  1397.         if (!lsl_loaded) {
  1398.           sprintf(s, "%s\\LSL U", maindir);
  1399.           do_spawn(s);
  1400.         }
  1401.         do_exit(EXIT_FAILURE);
  1402.       default:
  1403.         output("\n ■ Unknown PPPState Error #%d... aborting", i);
  1404.         sprintf(s, "%s\\PPP U", maindir);
  1405.         do_spawn(s);
  1406.         if (!lsl_loaded) {
  1407.           sprintf(s, "%s\\LSL U", maindir);
  1408.           do_spawn(s);
  1409.         }
  1410.         do_exit(EXIT_FAILURE);
  1411.     }
  1412.   } else {
  1413.     output("\n ■ %s\\PPPSTATE.EXE not found!", maindir);
  1414.     do_exit(EXIT_FAILURE);
  1415.   }
  1416.   if (!IPADDR[0]) {
  1417.     sprintf(s, "%s\\PPPWAT.EXE", maindir);
  1418.     if (exist(s)) {
  1419.       do_spawn(s);
  1420.     } else {
  1421.       output("\n ■ %s\\PPPWAT.EXE not found!", maindir);
  1422.       unload_klos();
  1423.       do_exit(EXIT_FAILURE);
  1424.     }
  1425.     sprintf(s, "%s\\WATTCP.CFG", maindir);
  1426.     if ((fp = fsh_open(s, "rt")) != NULL) {
  1427.       while (fgets(s, 100, fp) != NULL) {
  1428.         if (strnicmp(s, "my_ip", 5) == 0) {
  1429.           ss = strtok(s, "=");
  1430.           ss = strtok(NULL, "\r");
  1431.           trimstr1(ss);
  1432.           strcpy(IPADDR, ss);
  1433.           break;
  1434.         }
  1435.       }
  1436.       if (fp != NULL)
  1437.         fclose(fp);
  1438.     } else {
  1439.       output("\n ■ Unable to read %s\\WATTCP.CFG... aborting!", maindir);
  1440.       unload_klos();
  1441.       do_exit(EXIT_FAILURE);
  1442.     }
  1443.   }
  1444.   if (IPADDR) {
  1445.     output("\n ■ Session IP address %s... ", IPADDR);
  1446.     if (create_wattcp_cfg()) {
  1447.       unload_klos();
  1448.       do_exit(EXIT_FAILURE);
  1449.     }
  1450.   } else {
  1451.     output("\n ■ Could not find IP Address... aborting!");
  1452.     unload_klos();
  1453.     do_exit(EXIT_FAILURE);
  1454.   }
  1455.   sprintf(s, "%s\\IPSTUB.EXE", maindir);
  1456.   if (exist(s)) {
  1457.     do_spawn(s);
  1458.   } else {
  1459.     output("\n ■ %s\\IPSTUB.EXE not found!", maindir);
  1460.     do_exit(EXIT_FAILURE);
  1461.   }
  1462.   output("establishing socket     ");
  1463.   for (i = 5; i >= 0; i--) {
  1464.     output("\b\b\b\b%d...", i);
  1465.     delay(1000);
  1466.   }
  1467.   output("\b\b\b\b\b... ready!");
  1468. }
  1469.  
  1470. double freek(int dr)
  1471. {
  1472.   float d;
  1473.   struct dfree df;
  1474.  
  1475.   getdfree(dr, &df);
  1476.   d = (float) df.df_avail;
  1477.   d *= ((float) df.df_bsec);
  1478.   d *= ((float) df.df_sclus);
  1479.   d /= 1024.0;
  1480.   if (df.df_sclus == 0xffff)
  1481.     d = -1.0;
  1482.   return (d);
  1483. }
  1484.  
  1485. int main(int argc, char *argv[])
  1486. {
  1487.   int i, ok, news, totf, send, f1;
  1488.   unsigned short sy;
  1489.   double dspace;
  1490.   char *ss, s[121], s1[MAXPATH], destaddr[121], temp[121];
  1491.   char ttotal[21];
  1492.   clock_t starttime, mailtime, newstime;
  1493.   unsigned long sentbytes, recdbytes, rnewsbytes, snewsbytes;
  1494.   FILE *fp;
  1495.   struct ffblk ff;
  1496.  
  1497.   init();
  1498.   news = 0;
  1499.   num_addr = 0;
  1500.   netaddr = NULL;
  1501.   ss = argv[argc - 1];
  1502.   ok = 0;
  1503.   if (_fstrstr((char *) ss, ".") != NULL) {
  1504.     if (atoi(&ss[1]) < net_num_max) {
  1505.       netnum = atoi(&ss[1]);
  1506.       ok = 1;
  1507.     }
  1508.   } else {
  1509.     ss = (getenv("WWIV_NET"));
  1510.     netnum = atoi(ss);
  1511.     if (netnum < net_num_max)
  1512.       ok = 1;
  1513.   }
  1514.   if (!ok) {
  1515.     strcpy(s, "WWIV_NET.DAT");
  1516.     if ((fp = fsh_open(s, "rb")) != NULL) {
  1517.       fgets(s, 3, fp);
  1518.       netnum = atoi(s);
  1519.       if (fp != NULL)
  1520.         fclose(fp);
  1521.       if (netnum < net_num_max)
  1522.         ok = 1;
  1523.     }
  1524.   }
  1525.   ss = argv[1];
  1526.   if (strncmpi(ss, "/N", 2))
  1527.     ok = 0;
  1528.   set_net_num(netnum);
  1529.   sprintf(s, "%sADDRESS.1", net_data);
  1530.   if (!exist(s))
  1531.     ok = 0;
  1532.   if (ok) {
  1533.     SMTPHOST[0] = 0;
  1534.     POPHOST[0] = 0;
  1535.     NEWSHOST[0] = 0;
  1536.     POPNAME[0] = 0;
  1537.     POPPASS[0] = 0;
  1538.     IPADDR[0] = 0;
  1539.     NETMASK[0] = 0;
  1540.     DNS[0] = 0;
  1541.     DOMAIN[0] = 0;
  1542.     GATEWAY[0] = 0;
  1543.     FWDNAME[0] = 0;
  1544.     FWDDOM[0] = 0;
  1545.     if (parse_net_ini()) {
  1546.       set_net_num(netnum);
  1547.       if (ini_section & INI_NETWORK) {
  1548.         if (!(ini_section & INI_GENERAL)) {
  1549.           output("\n ■ [GENERAL] tag missing from NET.INI!");
  1550.           ok = 0;
  1551.         }
  1552.       } else {
  1553.         ok = 0;
  1554.         output("\n ■ [FILENET] tag missing from NET.INI!");
  1555.       }
  1556.     } else {
  1557.       output("\n ■ Could not open file NET.INI!");
  1558.       ok = 0;
  1559.     }
  1560.   }
  1561.   if (ok)
  1562.     if (create_contact_ppp())
  1563.       ok = 0;
  1564.   if (ok) {
  1565.     output("\n ■ Available memory : %ld bytes...", coreleft());
  1566.     if (net_data[1] == ':')
  1567.       i = net_data[0];
  1568.     else
  1569.       i = maindir[0];
  1570.     i = toupper(i) - 'A' + 1;
  1571.     dspace = freek(i);
  1572.     if (dspace < 1024.0) {
  1573.       output("\n ■ Only %.1fK available on drive %c:... aborting!",
  1574.               dspace, i + '@');
  1575.       do_exit(EXIT_FAILURE);
  1576.     } else {
  1577.       output(" disk space ");
  1578.       if (dspace < 10000.0)
  1579.         output(": %c:%.1fK", i + '@', dspace);
  1580.       else
  1581.         output(": %c:%.1fM", i + '@', dspace / 1024.0);
  1582.     }
  1583.  
  1584.     set_net_num(netnum);
  1585.     ss = argv[1];
  1586.     sy = atoi(&ss[2]);
  1587.     destaddr[0] = 0;
  1588.     if (sy != 32767)
  1589.       good_addr(destaddr, sy);
  1590.  
  1591.     if ((destaddr[0] == 0) && (sy != 32767)) {
  1592.       output("\n ■ Using direct dial for @%hd.%s\n\n", sy, net_name);
  1593.       ok = 0;
  1594.     } else {
  1595.       ok = 1;
  1596.       if (sy == 32767) {
  1597.         if (ini_section & INI_NEWS) {
  1598.           output("\n ■ Initiating newsgroup retrieval session...");
  1599.           news = 1;
  1600.         } else {
  1601.           output("\n ■ [NEWS] tag missing from NET.INI!");
  1602.           do_exit(EXIT_FAILURE);
  1603.         }
  1604.       }
  1605.     }
  1606.   }
  1607.   if (ok) {
  1608.     if (!MOREINFO)
  1609.       freopen(NULL, "w", stdout);
  1610.     if (CLEANUP)
  1611.       process_mail();
  1612.     set_net_num(netnum);
  1613.     sprintf(s, "%sSPOOL", net_data);
  1614.     if ((make_path(s)) < 0) {
  1615.       output("\n ■ Unable to create \"%s\"", s);
  1616.       do_exit(EXIT_FAILURE);
  1617.     }
  1618.     sprintf(s, "%sMQUEUE", net_data);
  1619.     if ((make_path(s)) < 0) {
  1620.       output("\n ■ Unable to create \"%s\"", s);
  1621.       do_exit(EXIT_FAILURE);
  1622.     }
  1623.     sprintf(s, "%sOUTBOUND", net_data);
  1624.     if ((make_path(s)) < 0) {
  1625.       output("\n ■ Unable to create \"%s\"", s);
  1626.       do_exit(EXIT_FAILURE);
  1627.     }
  1628.     sprintf(s, "%sINBOUND", net_data);
  1629.     if ((make_path(s)) < 0) {
  1630.       output("\n ■ Unable to create \"%s\"", s);
  1631.       do_exit(EXIT_FAILURE);
  1632.     }
  1633.     sprintf(s, "%sSENT", net_data);
  1634.     if ((make_path(s)) < 0) {
  1635.       output("\n ■ Unable to create \"%s\"", s);
  1636.       do_exit(EXIT_FAILURE);
  1637.     }
  1638.     if (PURGE) {
  1639.       if ((KEEPSENT) && (sy != 32767)) {
  1640.         output("\n ■ Purging sent packets older than %d day%s...", KEEPSENT,
  1641.                 KEEPSENT == 1 ? "" : "s");
  1642.         i = purge_sent();
  1643.         output(" %d packet%s deleted.", i, i == 1 ? "" : "s");
  1644.       }
  1645.     }
  1646.     sprintf(s, "%sCHECKNET", net_data);
  1647.     if ((make_path(s)) < 0) {
  1648.       output("\n ■ Unable to create \"%s\"", s);
  1649.       do_exit(EXIT_FAILURE);
  1650.     }
  1651.     send = 1;
  1652.  
  1653.     cd_to(maindir);
  1654.     sprintf(s, "%s\\EXP.EXE", maindir);
  1655.     if (!exist(s)) {
  1656.       output("\n ■ Export module EXP.EXE not found!");
  1657.     } else {
  1658.       sprintf(s, "%sS32767.NET", net_data);
  1659.       sprintf(s1, "%sSPOOL\\UNK*.*", net_data);
  1660.       if ((exist(s)) || (exist(s1))) {
  1661.         sprintf(s, "EXP.EXE S32767.NET %s %hu %s %s %s",
  1662.                 net_data, net_sysnum, FWDNAME, FWDDOM, net_name);
  1663.         if (do_spawn(s))
  1664.           output("\n ■ Unknown error during export.");
  1665.       } else
  1666.         output("\n ■ No Internet mail or newsgroup posts to process.");
  1667.     }
  1668.  
  1669.     cd_to(maindir);
  1670.     if ((sy != 32767) || (ONECALL)) {
  1671.       output("\n ■ Preparing outbound mail for transmission...");
  1672.       if (!uu_packets()) {
  1673.         sprintf(s, "%sMQUEUE\\*.*", net_data);
  1674.         if (findfirst(s, &ff, 0) == 0) {
  1675.           output(" outbound packets in MQUEUE.");
  1676.         } else {
  1677.           output(" no mail or packets to send.");
  1678.           send = 0;
  1679.         }
  1680.       } else {
  1681.         backline();
  1682.         output("\r ■ All packets prepared for transmission.");
  1683.       }
  1684.     }
  1685.     sprintf(s, "%sNET%d.CFG", net_data, instance);
  1686.     if (exist(s)) {
  1687.       sprintf(s1, "%s\\NET.CFG", maindir);
  1688.       unlink(s1);
  1689.       if (!copyfile(s, s1))
  1690.         output("\n ■ Unable to copy %s to %s", s, s1);
  1691.     }
  1692.  
  1693.     starttime = clock();
  1694.     sentbytes = recdbytes = snewsbytes = rnewsbytes = 0L;
  1695.  
  1696.     cd_to(maindir);
  1697.  
  1698.     if (netaddr != NULL)
  1699.       farfree(netaddr);
  1700.     klos_ppp();
  1701.     netaddr = NULL;
  1702.  
  1703.     sprintf(temp_dir, "%sINBOUND\\", net_data);
  1704.  
  1705.     if ((send) && ((sy != 32767) || (ONECALL))) {
  1706.       totf = 0;
  1707.       sprintf(temp, "%sMQUEUE\\*.*", net_data);
  1708.       f1 = findfirst(temp, &ff, FA_ARCH);
  1709.       if (f1 == 0)
  1710.         output("\n");
  1711.       while (f1 == 0) {
  1712.         sprintf(s1, "%sMQUEUE\\%s", net_data, ff.ff_name);
  1713.         sprintf(s, "%s\\POP -send %s %s %s %d", maindir, SMTPHOST, DOMAIN, s1, MOREINFO);
  1714.         backline();
  1715.         output("\r ■ SND : %s ", ff.ff_name);
  1716.         if (do_spawn(s) == EXIT_SUCCESS) {
  1717.           unlink(s1);
  1718.           sentbytes += ff.ff_fsize;
  1719.           ++totf;
  1720.         } else
  1721.           output("\n ■ Unsuccessful!  %s remains in MQUEUE.", ff.ff_name);
  1722.         f1 = findnext(&ff);
  1723.       }
  1724.       sprintf(temp, "%sMQUEUE\\*.*", net_data);
  1725.       f1 = findfirst(temp, &ff, FA_ARCH);
  1726.       while (f1 == 0) {
  1727.         sprintf(s1, "%sMQUEUE\\%s", net_data, ff.ff_name);
  1728.         sprintf(s, "%s\\POP -send %s %s %s %d", maindir, SMTPHOST, DOMAIN, s1, MOREINFO);
  1729.         backline();
  1730.         output("\r ■ SND : %s ", ff.ff_name);
  1731.         if (do_spawn(s) == EXIT_SUCCESS) {
  1732.           unlink(s1);
  1733.           sentbytes += ff.ff_fsize;
  1734.           ++totf;
  1735.         } else
  1736.           output("\n ■ Unsuccessful!  %s remains in MQUEUE.", ff.ff_name);
  1737.         f1 = findnext(&ff);
  1738.       }
  1739.       backline();
  1740.       output("\r ■ Outbound mail transfer completed - %d file%s, %ldK bytes.",
  1741.               totf, totf == 1 ? "" : "s", ((sentbytes + 1023) / 1024));
  1742.       send = 0;
  1743.     }
  1744.     if ((sy != 32767) || (ONECALL)) {
  1745.       sprintf(s, "%s\\POP -receive %s %s %s %s %d %s %d", maindir, POPHOST, POPNAME, POPPASS,
  1746.               temp_dir, ALLMAIL, DOMAIN, MOREINFO);
  1747.       output("\n ■ Checking for inbound mail - ");
  1748.       sprintf(s1, "%s*.*", temp_dir);
  1749.       if ((do_spawn(s) == EXIT_SUCCESS) || (exist(s1))) {
  1750.         sprintf(temp, "%s*.*", temp_dir);
  1751.         f1 = findfirst(temp, &ff, FA_ARCH);
  1752.         i = 0;
  1753.         send = 0;
  1754.         while (f1 == 0) {
  1755.           if ((strncmp(ff.ff_name, "BAD", 3) != 0) && (ff.ff_fsize)) {
  1756.             recdbytes += ff.ff_fsize;
  1757.             sprintf(s1, "%s%s", temp_dir, ff.ff_name);
  1758.             sprintf(temp, "%s\\UU -decode %s %s %s", maindir, ff.ff_name,
  1759.                     temp_dir, net_data);
  1760.             if (!do_spawn(temp)) {
  1761.               send = 1;
  1762.               unlink(s1);
  1763.             }
  1764.           }
  1765.           f1 = findnext(&ff);
  1766.         }
  1767.       } else
  1768.         output("\n ■ No network packets to process");
  1769.  
  1770.       if ((send) && (CLEANUP)) {
  1771.         output("\n ■ Running FLINK/Linker on received packets... please wait.");
  1772.         process_mail();
  1773.         set_net_num(netnum);
  1774.         process_bbsdata();
  1775.       }
  1776.     }
  1777.     sprintf(s, "%sSPOOL\\UNK*.*", net_data);
  1778.     if (exist(s)) {
  1779.       sprintf(s, "EXP.EXE S32767.NET %s %hu %s %s %s",
  1780.               net_data, net_sysnum, FWDNAME, FWDDOM, net_name);
  1781.       if (do_spawn(s))
  1782.         output("\n ■ Unknown error during export");
  1783.     }
  1784.     mailtime = clock() - starttime;
  1785.     if ((sy == 32767) || (ONECALL)) {
  1786.       starttime = clock();
  1787.       set_net_num(netnum);
  1788.       sprintf(temp, "%sOUTBOUND\\*.*", net_data);
  1789.       f1 = findfirst(temp, &ff, FA_ARCH);
  1790.       while (f1 == 0) {
  1791.         snewsbytes += ff.ff_fsize;
  1792.         f1 = findnext(&ff);
  1793.       }
  1794.       cd_to(maindir);
  1795.       strcpy(s1, net_data);
  1796.       if (LAST(s1) == '\\')
  1797.         LAST(s1) = 0;
  1798.       sprintf(s, "%s\\NEWS.EXE %s %s %hu", maindir, s1, NEWSHOST, net_sysnum);
  1799.       ok = 1;
  1800.       if (do_spawn(s) != EXIT_SUCCESS)
  1801.         output("\n ■ Unsuccessful news retrieval session...");
  1802.       set_net_num(netnum);
  1803.       sprintf(temp, "%sP0*.*", net_data);
  1804.       f1 = findfirst(temp, &ff, 0);
  1805.       while (f1 == 0) {
  1806.         rnewsbytes += ff.ff_fsize;
  1807.         f1 = findnext(&ff);
  1808.       }
  1809.     }
  1810.   } else {
  1811.     output("\n");
  1812.     set_net_num(netnum);
  1813.     strcpy(s, "NETWORK0.EXE");
  1814.     for (i = 1; i < argc; i++) {
  1815.       strcat(s, " ");
  1816.       strcat(s, argv[i]);
  1817.     }
  1818.     s[strlen(s) + 1] = '\0';
  1819.     do_it(s);
  1820.     if (netaddr != NULL)
  1821.       farfree(netaddr);
  1822.     exit(EXIT_SUCCESS);
  1823.   }
  1824.  
  1825.   if (netaddr != NULL)
  1826.     farfree(netaddr);
  1827.   unload_klos();
  1828.   netaddr = NULL;
  1829.  
  1830.   newstime = clock() - starttime;
  1831.   output("\n ■ Updating network connection records...");
  1832.   if (ONECALL) {
  1833.     recdbytes = ((recdbytes + 1023) / 1024);
  1834.     sentbytes = ((sentbytes + 1023) / 1024);
  1835.     if (mailtime)
  1836.       sprintf(ttotal, "%2.1f", (mailtime / CLK_TCK / 60));
  1837.     else
  1838.       strcpy(ttotal, "0.1");
  1839.     if (update_contacts(sy, sentbytes, recdbytes))
  1840.       output("\n ■ Unable to access CONTACT.NET!");
  1841.     if (write_netlog(sy, sentbytes, recdbytes, ttotal))
  1842.       output("\n ■ Unable to access NET.LOG!");
  1843.     if (newstime)
  1844.       sprintf(ttotal, "%2.1f", (newstime / CLK_TCK / 60));
  1845.     else
  1846.       strcpy(ttotal, "0.1");
  1847.     rnewsbytes = ((rnewsbytes + 1023) / 1024);
  1848.     snewsbytes = ((snewsbytes + 1023) / 1024);
  1849.     if (update_contact(32767, snewsbytes, rnewsbytes))
  1850.       output("\n ■ Unable to access CONTACT.NET!");
  1851.     if (write_netlog(32767, snewsbytes, rnewsbytes, ttotal))
  1852.       output("\n ■ Unable to access NET.LOG!");
  1853.   } else {
  1854.     if (news) {
  1855.       if (newstime)
  1856.         sprintf(ttotal, "%2.1f", (newstime / CLK_TCK / 60));
  1857.       else
  1858.         strcpy(ttotal, "0.1");
  1859.       rnewsbytes = ((rnewsbytes + 1023) / 1024);
  1860.       snewsbytes = ((snewsbytes + 1023) / 1024);
  1861.       if (update_contact(32767, snewsbytes, rnewsbytes))
  1862.         output("\n ■ Unable to access CONTACT.NET!");
  1863.       if (write_netlog(32767, snewsbytes, rnewsbytes, ttotal))
  1864.         output("\n ■ Unable to access NET.LOG!");
  1865.     } else {
  1866.       recdbytes = ((recdbytes + 1023) / 1024);
  1867.       sentbytes = ((sentbytes + 1023) / 1024);
  1868.       if (mailtime)
  1869.         sprintf(ttotal, "%2.1f", (mailtime / CLK_TCK / 60));
  1870.       else
  1871.         strcpy(ttotal, "0.1");
  1872.       if (update_contacts(sy, sentbytes, recdbytes))
  1873.         output("\n ■ Unable to access CONTACT.NET!");
  1874.       if (write_netlog(sy, sentbytes, recdbytes, ttotal))
  1875.         output("\n ■ Unable to access NET.LOG!");
  1876.     }
  1877.   }
  1878.   cd_to(maindir);
  1879.   set_net_num(netnum);
  1880.   if (netaddr != NULL)
  1881.     farfree(netaddr);
  1882.   output("\n ■ %s completed!\n\n", version);
  1883.   return 0;
  1884. }
  1885.