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