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