home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC15B21.ZIP / NEWS.C < prev    next >
C/C++ Source or Header  |  1997-03-28  |  42KB  |  1,487 lines

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #include <ctype.h>
  4. #include <process.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <conio.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include <io.h>
  12. #include <dos.h>
  13. #include <share.h>
  14. #include <dir.h>
  15. #include <alloc.h>
  16. #include <sys\stat.h>
  17. #include <math.h>
  18. #include "tcp.h"
  19. #include "pop.h"
  20. #include "net.h"
  21. #include "vardec.h"
  22. #include "version.h"
  23.  
  24. extern unsigned _stklen = 16384;
  25.  
  26. #define NGROUPS 100
  27. #define BIGSTR 4096
  28. #define STRING 512
  29. #define STR 129
  30. #define WAIT_TIME 10
  31. #define TRIES 100
  32. #define NUL '\0'
  33. #define LAST(s) s[strlen(s)-1]
  34. #define NNTP_PORT 119
  35. #define free_Mail_Socket(SOCK) if (SOCK!=NULL) {     \
  36.   farfree(SOCK->sock); farfree(SOCK); SOCK=NULL; }
  37.  
  38. tcp_Socket nntpsock;
  39. configrec syscfg;
  40. subboardrec *subboards;
  41.  
  42. static int NNTP_stat;
  43.  
  44. unsigned short reply;
  45. unsigned long reparticle;
  46.  
  47. char serverhost[81], newsrc[81], fromline[121], smtppath[81];
  48. char maindir[181], tmpdir[201], net_data[181];
  49. char *version = "Freeware PPP News Retrieval " VERSION;
  50.  
  51. char cur_gname[STRING], tpktname[121];
  52. char msgto[STRING], msgarea[STRING];
  53. unsigned long cur_numa, cur_first, cur_last;
  54.  
  55. unsigned long cur_article;
  56. char cur_articleid[STRING];
  57. char cur_path[STRING], cur_from[STRING], cur_subject[STRING], cur_replyto[STRING];
  58. char cur_newsgroups[STRING], cur_message_ID[STRING], cur_organization[STRING], cur_references[STRING], cur_lines[STR], cur_date[STRING];
  59. unsigned short sy;
  60. int instance, SOCK_DELAY;
  61.  
  62. typedef struct {
  63.   char groupname[60];
  64.   unsigned long lastread;
  65.   unsigned short subtype;
  66. } GROUPFILEREC;
  67.  
  68. GROUPFILEREC *grouprec;
  69. int ngroups;
  70.  
  71. int bogus = 0;
  72.  
  73. #define SOCK_READ_ERR(SOCK) sock_err:                                   \
  74.   switch (NNTP_stat) {                                                  \
  75.     case 1 :                                                            \
  76.       write_groups(1);                                                  \
  77.       log_it("\n ! Connection closed : %s", sockerr(NNTP_sock->sock));  \
  78.       if (SOCK != NULL)                                                 \
  79.         free_Mail_Socket(SOCK);                                         \
  80.       fcloseall();                                                      \
  81.       cursor('R');                                                      \
  82.       exit(EXIT_FAILURE);                                               \
  83.     case -1:                                                            \
  84.       write_groups(1);                                                  \
  85.       log_it("\n ! Session error: %s", sockerr(NNTP_sock->sock));       \
  86.       if (SOCK != NULL)                                                 \
  87.         free_Mail_Socket(SOCK);                                         \
  88.       fcloseall();                                                      \
  89.       cursor('R');                                                      \
  90.       exit(EXIT_FAILURE);                                               \
  91.   }                                                                     \
  92.  
  93. char *texth[] = {"th", "st", "nd", "rd"};
  94.  
  95. char *ordinal_text(int number)
  96. {
  97.   if (((number %= 100) > 9 && number < 20) || (number %= 10) > 3)
  98.     number = 0;
  99.   return texth[number];
  100. }
  101.  
  102. static unsigned cursize;
  103.  
  104. void cursor(int tmp)
  105. {
  106.   union REGS inregs, outregs;
  107.  
  108.   switch (toupper(tmp)) {
  109.     case 'S':                               /* Save */
  110.       inregs.h.ah = 3;
  111.       inregs.h.bh = 0;
  112.       int86(0x10, &inregs, &outregs);
  113.       cursize = outregs.x.cx;
  114.       break;
  115.     case 'R':                               /* Restore */
  116.       inregs.h.ah = 1;
  117.       inregs.x.cx = cursize;
  118.       int86(0x10, &inregs, &outregs);
  119.       break;
  120.     case 'H':                               /* Hide */
  121.       inregs.h.ah = 1;
  122.       inregs.h.ch = 0x20;
  123.       int86(0x10, &inregs, &outregs);
  124.       break;
  125.     case 'N':                               /* Normal */
  126.       inregs.h.ah = 1;
  127.       inregs.h.ch = 6;
  128.       inregs.h.cl = 7;
  129.       int86(0x10, &inregs, &outregs);
  130.       break;
  131.   }
  132. }
  133.  
  134. void backline(void)
  135. {
  136.   int i;
  137.  
  138.   fprintf(stderr, " ");
  139.   for (i = wherex(); i > 0; i--)
  140.     fprintf(stderr, "\b \b");
  141. }
  142.  
  143. void cd_to(char *s)
  144. {
  145.   char *s1;
  146.   int i, db;
  147.  
  148.   s1 = s;
  149.   i = strlen(s1) - 1;
  150.   db = (s1[i] == '\\');
  151.   if (i == 0)
  152.     db = 0;
  153.   if ((i == 2) && (s1[1] == ':'))
  154.     db = 0;
  155.   if (db)
  156.     s1[i] = 0;
  157.   chdir(s1);
  158.   if (s[1] == ':')
  159.     setdisk(s[0] - 'A');
  160. }
  161.  
  162. void get_dir(char *s, int be)
  163. {
  164.   strcpy(s, "X:\\");
  165.   s[0] = 'A' + getdisk();
  166.   getcurdir(0, s + 3);
  167.   if (be) {
  168.     if (s[strlen(s) - 1] != '\\')
  169.       strcat(s, "\\");
  170.   }
  171. }
  172.  
  173. int sh_open(char *path, int file_access, unsigned mode)
  174. {
  175.   int handle, count, share;
  176.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  177.  
  178.   if ((file_access & O_RDWR) || (file_access & O_WRONLY) || (mode & S_IWRITE))
  179.     share = SH_DENYRW;
  180.   else
  181.     share = SH_DENYWR;
  182.   handle = open(path, file_access | share, mode);
  183.   if (handle < 0) {
  184.     count = 1;
  185.     fnsplit(path, drive, dir, file, ext);
  186.     if (access(path, 0) != -1) {
  187.       delay(WAIT_TIME);
  188.       handle = open(path, file_access | share, mode);
  189.       while (((handle < 0) && (errno == EACCES)) && (count < TRIES)) {
  190.         delay(WAIT_TIME);
  191.         count++;
  192.         handle = open(path, file_access | share, mode);
  193.       }
  194.     }
  195.   }
  196.   return (handle);
  197. }
  198.  
  199. int sh_open1(char *path, int access)
  200. {
  201.   unsigned fmode;
  202.  
  203.   fmode = 0;
  204.   if ((access & O_RDWR) || (access & O_WRONLY))
  205.     fmode |= S_IWRITE;
  206.   if ((access & O_RDWR) || (access & O_RDONLY))
  207.     fmode |= S_IREAD;
  208.   return (sh_open(path, access, fmode));
  209. }
  210.  
  211. long sh_lseek(int handle, long offset, int fromwhere)
  212. {
  213.   if (handle == -1) {
  214.     return (-1L);
  215.   }
  216.   return (lseek(handle, offset, fromwhere));
  217. }
  218.  
  219. FILE *fsh_open(char *path, char *fmode)
  220. {
  221.   FILE *f;
  222.   int count, share, md, fd;
  223.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  224.  
  225.   share = SH_DENYWR;
  226.   md = 0;
  227.   if (((char *) _fstrchr(fmode, 'w')) != NULL) {
  228.     share = SH_DENYRD;
  229.     md = O_RDWR | O_CREAT | O_TRUNC;
  230.   } else
  231.     if (((char *) _fstrchr(fmode, 'a')) != NULL) {
  232.     share = SH_DENYRD;
  233.     md = O_RDWR | O_CREAT;
  234.     }
  235.   else {
  236.     md = O_RDONLY;
  237.   }
  238.   if (((char *) _fstrchr(fmode, 'b')) != NULL) {
  239.     md |= O_BINARY;
  240.   }
  241.   if (((char *) _fstrchr(fmode, '+')) != NULL) {
  242.     md &= ~O_RDONLY;
  243.     md |= O_RDWR;
  244.     share = SH_DENYRD;
  245.   }
  246.   fd = open(path, md | share, S_IREAD | S_IWRITE);
  247.   if (fd < 0) {
  248.     count = 1;
  249.     fnsplit(path, drive, dir, file, ext);
  250.     if ((access(path, 0)) != -1) {
  251.       delay(WAIT_TIME);
  252.       fd = open(path, md | share, S_IREAD | S_IWRITE);
  253.       while (((fd < 0) && (errno == EACCES)) && (count < TRIES)) {
  254.         delay(WAIT_TIME);
  255.         count++;
  256.         fd = open(path, md | share, S_IREAD | S_IWRITE);
  257.       }
  258.     }
  259.   }
  260.   if (fd > 0) {
  261.     if (((char *) _fstrchr(fmode, 'a')) != NULL)
  262.       sh_lseek(fd, 0L, SEEK_END);
  263.     f = fdopen(fd, fmode);
  264.     if (!f) {
  265.       close(fd);
  266.     }
  267.   } else
  268.     f = 0;
  269.   return (f);
  270. }
  271.  
  272. int sh_close(int f)
  273. {
  274.   if (f != -1)
  275.     close(f);
  276.   return (-1);
  277. }
  278.  
  279. int sh_read(int handle, void *buf, unsigned len)
  280. {
  281.   if (handle == -1) {
  282.     return (-1);
  283.   }
  284.   return (read(handle, buf, len));
  285. }
  286.  
  287. int log_it(char *fmt,...)
  288. {
  289.   va_list v;
  290.   char fn[201];
  291.   FILE *fp;
  292.  
  293.   sprintf(fn, "%s\\NEWS.LOG", net_data);
  294.   if ((fp = fsh_open(fn, "at")) == NULL)
  295.     return 1;
  296.   va_start(v, fmt);
  297.   vfprintf(fp, fmt, v);
  298.   vfprintf(stderr, fmt, v);
  299.   va_end(v);
  300.   fclose(fp);
  301.   return 0;
  302. }
  303.  
  304.  
  305. long count_lines(char *s)
  306. {
  307.   FILE *fp;
  308.   char fn[201];
  309.   long int nl = 0;
  310.   const int NEWLINE = '\n';
  311.   int c;
  312.  
  313.   strcpy(fn, s);
  314.   fp = fsh_open(fn, "rt");
  315.   if (fp == NULL) {
  316.     printf("\n ■ Cannot open %s", fn);
  317.     return 0;
  318.   }
  319.   while ((c = getc(fp)) != EOF) {
  320.     if (c == NEWLINE)
  321.       ++nl;
  322.   }
  323.   fclose(fp);
  324.   return nl;
  325. }
  326.  
  327. static unsigned char *trimstr1(unsigned char *s)
  328. {
  329.   int i;
  330.   static char *whitespace = " \r\n\t";
  331.  
  332.   i = strlen(s);
  333.   while ((i > 0) && (_fstrchr(whitespace, s[i - 1])))
  334.     --i;
  335.   while ((i > 0) && (_fstrchr(whitespace, *s))) {
  336.     memmove(s, s + 1, --i);
  337.   }
  338.   s[i] = 0;
  339.   return (s);
  340. }
  341.  
  342. void usleep(void)
  343. {
  344.   tcp_tick(NULL);                           /* occasionally process something */
  345. }
  346.  
  347. int exist(char *s)
  348. {
  349.   int i;
  350.   struct ffblk ff;
  351.  
  352.   i = findfirst(s, &ff, 0);
  353.   if (i)
  354.     return (0);
  355.   else
  356.     return (1);
  357. }
  358.  
  359. void rename_pend(char *dir, char *file)
  360. {
  361.   char s[181], s1[181];
  362.   int i, ok;
  363.  
  364.   sprintf(s, "%s\\%s", dir, file);
  365.   ok = 0;
  366.   for (i = 0; i < 1000 && !ok; i++) {
  367.     sprintf(s1, "%s\\P0-%u.NET", dir, i);
  368.     if (!exist(s1)) {
  369.       rename(s, s1);
  370.       ok = 1;
  371.     }
  372.   }
  373. }
  374.  
  375. void check_packets(void)
  376. {
  377.   char s[181];
  378.   int f1;
  379.   struct ffblk ff;
  380.  
  381.   sprintf(s, "%s\\P0-*.%3.3d", net_data, instance);
  382.   f1 = findfirst(s, &ff, 0);
  383.   while (f1 == 0) {
  384.     rename_pend(net_data, ff.ff_name);
  385.     f1 = findnext(&ff);
  386.   }
  387. }
  388.  
  389.  
  390. void err_exit(int exitlevel, char *fmt,...)
  391. {
  392.   va_list v;
  393.  
  394.   va_start(v, fmt);
  395.   vfprintf(stderr, fmt, v);
  396.   va_end(v);
  397.   check_packets();
  398.   cursor('R');
  399.   exit(exitlevel);
  400. }
  401.  
  402. void write_groups(int display)
  403. {
  404.   int i;
  405.   FILE *groupfp;
  406.  
  407.   groupfp = fsh_open(newsrc, "wt");
  408.   if (!groupfp) {
  409.     fprintf(stderr, "\n ■ Unable to open %s!", newsrc);
  410.     return;
  411.   } else {
  412.     if (display)
  413.       fprintf(stderr, "\n ■ Updating pointers in %s...", newsrc);
  414.   }
  415.   for (i = 0; i < ngroups; i++) {
  416.     if ((grouprec[i].groupname[0]) && (stricmp(grouprec[i].groupname, "newsrc") != 0)) {
  417.       fprintf(groupfp, "%s %ld %hu\n", grouprec[i].groupname,
  418.               grouprec[i].lastread, grouprec[i].subtype);
  419.     }
  420.   }
  421.   fclose(groupfp);
  422. }
  423.  
  424. void far *mallocx(unsigned long l)
  425. {
  426.   void *x;
  427.   char huge *xx;
  428.  
  429.   if (!l)
  430.     l = 1;
  431.   x = farmalloc(l);
  432.   if (!x) {
  433.     fprintf(stderr, "\n ■ Unable to allocate %lu bytes of memory", l);
  434.     cursor('R');
  435.     exit(EXIT_FAILURE);
  436.   }
  437.   xx = (char huge *) x;
  438.   while (l) {
  439.     if (l > 32768L) {
  440.       memset((void *) xx, 0, 32768L);
  441.       l -= 32768L;
  442.       xx += 32768L;
  443.     } else {
  444.       memset((void *) xx, 0, l);
  445.       break;
  446.     }
  447.   }
  448.   return (x);
  449. }
  450.  
  451.  
  452. void far *malloca(unsigned long nbytes)
  453. {
  454.   void *buf;
  455.  
  456.   buf = malloc(nbytes + 1);
  457.   if (buf == NULL)
  458.     fprintf(stderr, "\n ■ Unable to allocate sufficient memory (%ld bytes)", nbytes);
  459.   return (buf);
  460. }
  461.  
  462. void nntp_shutdown(Mail_Socket * NNTP_sock)
  463. {
  464.   sock_printf(NNTP_sock->sock, "QUIT");
  465.   sock_close(NNTP_sock->sock);
  466.   sock_wait_closed(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  467. sock_err:
  468.   return;
  469. }
  470.  
  471.  
  472. void read_groups(void)
  473. {
  474.   int i = 0, ok;
  475.   unsigned short sn;
  476.   char *ss, fn[101], tmp[101];
  477.   FILE *groupfp;
  478.  
  479.   if (grouprec)
  480.     free((void *) grouprec);
  481.   grouprec = NULL;
  482.   ngroups = count_lines(newsrc);
  483.   if (!ngroups)
  484.     return;
  485.   grouprec = (GROUPFILEREC *) mallocx((ngroups + 1) * sizeof(GROUPFILEREC));
  486.   if (!grouprec) {
  487.     ngroups = 0;
  488.     fprintf(stderr, "\n ■ Unable to allocate memory for reading NEWS.RC!");
  489.     return;
  490.   }
  491.   groupfp = fsh_open(newsrc, "rt");
  492.   if (!groupfp) {
  493.     free((void *) grouprec);
  494.     ngroups = 0;
  495.     return;
  496.   }
  497.   while (fgets(tmp, 120, groupfp)) {
  498.     if (tmp[0]) {
  499.       if (strncmpi(tmp, "newsrc", 6) == 0) {
  500.         strcpy(grouprec[i].groupname, "newsrc");
  501.         ++i;
  502.       } else {
  503.         ss = strtok(tmp, " ");
  504.         strcpy(grouprec[i].groupname, ss);
  505.         ss = strtok(NULL, " ");
  506.         if (ss != NULL) {
  507.           grouprec[i].lastread = atol(ss);
  508.           ss = strtok(NULL, " \n");
  509.           if (ss != NULL) {
  510.             grouprec[i].subtype = atoi(ss);
  511.             ++i;
  512.           }
  513.         }
  514.       }
  515.     }
  516.   }
  517.   ngroups = i;
  518.   fclose(groupfp);
  519.   for (i = 0; i < ngroups; i++) {
  520.     if (grouprec[i].subtype) {
  521.       sprintf(fn, "%s\\N%hu.NET", net_data, grouprec[i].subtype);
  522.       if (!exist(fn))
  523.         log_it("\n ■ N%u.NET does not exist in %s!", grouprec[i].subtype,
  524.                net_data);
  525.       else {
  526.         groupfp = fsh_open(fn, "rt");
  527.         ok = 0;
  528.         while ((fgets(tmp, 25, groupfp)) && !ok) {
  529.           sn = atoi(tmp);
  530.           if (sn == 32767)
  531.             ok = 1;
  532.         }
  533.         fclose(groupfp);
  534.         if (!ok)
  535.           log_it("\n ■ @32767 not list as a subscriber in N%d.NET!",
  536.                  grouprec[i].subtype);
  537.       }
  538.     }
  539.   }
  540. }
  541.  
  542. int cgroup(Mail_Socket * NNTP_sock, char *s)
  543. {
  544.   static char _temp_buffer[STRING];
  545.  
  546.   sock_printf(NNTP_sock->sock, "GROUP %s", s);
  547.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  548.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  549.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  550.   if (reply == 411)
  551.     return -1;
  552.   else
  553.     if (reply == 211) {
  554.     sscanf(_temp_buffer, "%hu %lu %lu %lu %s",
  555.            &reply, &cur_numa, &cur_first, &cur_last, &cur_gname);
  556.     return 0;
  557.     }
  558.   else
  559.     log_it("\n ■ Unknown cgroup response : %s", _temp_buffer);
  560.   SOCK_READ_ERR(NNTP_sock);
  561.   return -1;
  562. }
  563.  
  564. int cstat(Mail_Socket * NNTP_sock, unsigned long i)
  565. {
  566.   char *p, *q;
  567.   static char _temp_buffer[STRING];
  568.  
  569.   sock_printf(NNTP_sock->sock, "STAT %lu", i);
  570.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  571.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  572.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  573.   if (reply == 423)
  574.     return -1;
  575.   else
  576.     if (reply == 223) {
  577.     cur_article = reparticle;
  578.     p = _temp_buffer;
  579.     q = cur_articleid;
  580.     while ((p < _temp_buffer + STRING - 2) && (*p != '<'))
  581.       p++;
  582.     while ((p < _temp_buffer + STRING - 2) && (*p != '>'))
  583.       *q++ = *p++;
  584.     *q++ = '>';
  585.     *q++ = '\0';
  586.     return 0;
  587.     }
  588.   else
  589.     log_it("\n ■ Unknown cstat error : %s", _temp_buffer);
  590.   SOCK_READ_ERR(NNTP_sock);
  591.   return -1;
  592. }
  593.  
  594. int qexit(Mail_Socket * NNTP_sock, int n)
  595. {
  596.   static char _temp_buffer[STR];
  597.  
  598.   if (n >= 10)
  599.     log_it("\n ! Fatal NEWS error: check configuration!");
  600.   fflush(stdout);
  601.   sock_printf(NNTP_sock->sock, "QUIT");
  602.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  603.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  604.   if (*_temp_buffer != '2')
  605.     log_it("\n ■ Tried to quit host but failed");
  606.   cursor('R');
  607.   check_packets();
  608.   if (n) {
  609.     fcloseall();
  610.     free_Mail_Socket(NNTP_sock);
  611.     exit(n);
  612.   }
  613.   SOCK_READ_ERR(NNTP_sock);
  614.   return 0;
  615. }
  616.  
  617. void treat(char *str)
  618. {
  619.   char *obuf, *nbuf;
  620.  
  621.   if (*str) {
  622.     for (obuf = str, nbuf = str; *obuf && obuf; ++obuf) {
  623.       if (((*obuf >= 32) && (*obuf <= 126)) || (*obuf == 10)) {
  624.         *nbuf++ = *obuf;
  625.       }
  626.     }
  627.   }
  628. }
  629.  
  630. void name_packet(char *pktname)
  631. {
  632.   int ok;
  633.   struct stat info;
  634.   unsigned i;
  635.  
  636.   ok = 0;
  637.   for (i = 0; ((i < 1000) && (!ok)); i++) {
  638.     sprintf(pktname, "%s\\P0-%u.%3.3d", net_data, i, instance);
  639.     if (stat(pktname, &info) == -1)
  640.       ok = 1;
  641.   }
  642. }
  643.  
  644. int savebody(Mail_Socket * NNTP_sock, int cug, int *abort)
  645. {
  646.   char s1[21], s2[21], ch;
  647.   unsigned int curpos, count, part;
  648.   char spin[26];
  649.   int i, place, len;
  650.   unsigned long msgsize;
  651.   struct stat statbuf;
  652.   FILE *tpktfp = NULL;
  653.   static char _temp_buffer[BIGSTR];
  654.  
  655.   strcpy(spin, "||//--\\\\");
  656.   place = count = 0;
  657.   len = strlen(spin);
  658.  
  659.   part = 1;
  660.   if (grouprec[cug].subtype == 0)
  661.     sprintf(tpktname, "%s\\NEWS%d.UUE", tmpdir, cug);
  662.   else {
  663.     sprintf(tpktname, "%s\\INPUT%d.MSG", tmpdir, part++);
  664.     if (stat(tpktname, &statbuf) == 0)
  665.       unlink(tpktname);
  666.   }
  667.   sock_printf(NNTP_sock->sock, "BODY %lu", cur_article);
  668.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  669.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  670.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  671.   if (reply == 423)
  672.     return -1;
  673.   else {
  674.     if (reply == 222) {
  675.       if (grouprec[cug].subtype) {
  676.         if ((tpktfp = fsh_open(tpktname, "wt+")) == NULL) {
  677.           log_it("\n ■ Unable to create temporary packet %s", tpktname);
  678.           qexit(NNTP_sock, 1);
  679.         }
  680.       } else {
  681.         if (tpktfp)
  682.           fclose(tpktfp);
  683.         if ((tpktfp = fsh_open(tpktname, "at+")) == NULL) {
  684.           log_it("\n ■ Unable to create temporary packet %s", tpktname);
  685.           qexit(NNTP_sock, 1);
  686.         } else {
  687.           fputs("\n", tpktfp);
  688.           for (i = 0; i < 79; i++)
  689.             fputs("-", tpktfp);
  690.           fputs("\n", tpktfp);
  691.           sprintf(_temp_buffer, "Art  : %lu\n", cur_article);
  692.           fputs(_temp_buffer, tpktfp);
  693.           sprintf(_temp_buffer, "Date : %s\n", cur_date);
  694.           fputs(_temp_buffer, tpktfp);
  695.           sprintf(_temp_buffer, "From : %s\n", cur_replyto);
  696.           fputs(_temp_buffer, tpktfp);
  697.           sprintf(_temp_buffer, "Subj : %s\n\n", cur_subject);
  698.           fputs(_temp_buffer, tpktfp);
  699.         }
  700.       }
  701.       fnsplit(tpktname, NULL, NULL, s1, s2);
  702.       if (grouprec[cug].subtype)
  703.         fprintf(stderr, "\n ■ Receiving message - <Esc> aborts - <Space> skips group [-]");
  704.       else
  705.         fprintf(stderr, "\n ■ Appending to %s%s - <Esc> aborts - <Space> skips group [-]", s1, s2);
  706.       msgsize = 0L;
  707.       curpos = 0L;
  708.       while (1) {
  709.         if (kbhit()) {
  710.           ch = (getch());
  711.           switch (ch) {
  712.             case 27:
  713.               fprintf(stderr, "\r ■ Abort detected... please wait until message is completed [-]");
  714.               *abort = 1;
  715.               break;
  716.             case 32:
  717.               fprintf(stderr, "\r ■ Skipping group... please wait until message is completed [-]");
  718.               *abort = 2;
  719.               break;
  720.             default:
  721.               break;
  722.           }
  723.         }
  724.         sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  725.         sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  726.         if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0) {
  727.           break;
  728.         } else {
  729.           treat(_temp_buffer);
  730.           strcat(_temp_buffer, "\n");
  731.           curpos = strlen(_temp_buffer);
  732.           fputs(_temp_buffer, tpktfp);
  733.           msgsize += curpos;
  734.         }
  735.         if (count++ > 5) {
  736.           fprintf(stderr, "\b\b%c]", spin[place++]);
  737.           place %= len;
  738.           count = 0;
  739.         }
  740.         if ((msgsize > 30000L) && grouprec[cug].subtype) {
  741.           if (tpktfp)
  742.             fclose(tpktfp);
  743.           sprintf(tpktname, "%s\\INPUT%d.MSG", tmpdir, part++);
  744.           if (stat(tpktname, &statbuf) == 0)
  745.             unlink(tpktname);
  746.           if ((tpktfp = fsh_open(tpktname, "wt+")) == 0) {
  747.             log_it("\n ■ Unable to create temporary packet %s", tpktname);
  748.             qexit(NNTP_sock, 1);
  749.           }
  750.           backline();
  751.           fprintf(stderr, "\r ■ Breaking into %d%s part [ ]", (
  752.                                          part - 1), ordinal_text(part - 1));
  753.           msgsize = 0L;
  754.         }
  755.       }
  756.       if (tpktfp)
  757.         fclose(tpktfp);
  758.       fprintf(stderr, "\b\bX]");
  759.       return 1;
  760.     }
  761.   }
  762.   if (tpktfp)
  763.     fclose(tpktfp);
  764.   SOCK_READ_ERR(NNTP_sock);
  765.   return 0;
  766. }
  767.  
  768. int extract(char *to, char *key, char *from)
  769. {
  770.   if (!strnicmp(from, key, strlen(key))) {
  771.     from += strlen(key);
  772.     while (*from == ' ')
  773.       from++;
  774.     strcpy(to, from);
  775.     return 1;
  776.   } else
  777.     return 0;
  778. }
  779.  
  780.  
  781. int chead(Mail_Socket * NNTP_sock)
  782. {
  783.   static char _temp_buffer[BIGSTR];
  784.  
  785.   *cur_path = 0;
  786.   *cur_from = 0;
  787.   *cur_replyto = 0;
  788.   *cur_subject = 0;
  789.   *cur_newsgroups = 0;
  790.   *cur_message_ID = 0;
  791.   *cur_references = 0;
  792.   *cur_date = 0;
  793.  
  794.   sock_printf(NNTP_sock->sock, "HEAD %lu", cur_article);
  795.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  796.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  797.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  798.   if (reply == 423)
  799.     return 0;
  800.   else
  801.     if (reply == 221)
  802.     while (1) {
  803.       sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  804.       sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  805.       if (strlen(_temp_buffer) > 1024)
  806.         _temp_buffer[1024] = 0;
  807.       if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0) {
  808.         if (cur_replyto[0] == 0)
  809.           strcpy(cur_replyto, cur_from);
  810.         return 1;
  811.       }
  812.       extract(cur_path, "Path:", _temp_buffer) ||
  813.           extract(cur_from, "From:", _temp_buffer) ||
  814.           extract(cur_subject, "Subject:", _temp_buffer) ||
  815.           extract(cur_replyto, "Reply-To:", _temp_buffer) ||
  816.           extract(cur_newsgroups, "Newsgroups:", _temp_buffer) ||
  817.           extract(cur_organization, "Organization:", _temp_buffer) ||
  818.           extract(cur_message_ID, "Message-ID:", _temp_buffer) ||
  819.           extract(cur_references, "References:", _temp_buffer) ||
  820.           extract(cur_lines, "Lines:", _temp_buffer) ||
  821.           extract(cur_date, "Date:", _temp_buffer);
  822.     }
  823.   else {
  824.     log_it("\n ■ Unknown chead error : %s", _temp_buffer);
  825.   }
  826.   SOCK_READ_ERR(NNTP_sock);
  827.   return 0;
  828. }
  829.  
  830. Mail_Socket *netsocket(char *host)
  831. {
  832.   Mail_Socket *NNTP_sock = NULL;
  833.   longword h;
  834.   static char _temp_buffer[STR];
  835.  
  836.   if (!(h = resolve(host)))
  837.     err_exit(EXIT_FAILURE, "\n ■ Could not resolve %s... aborting", host);
  838.   if ((NNTP_sock = (Mail_Socket *) farmalloc(sizeof(Mail_Socket))) == NULL)
  839.     err_exit(EXIT_FAILURE, "\n ■ Insufficient memory for socket... aborting.");
  840.   if ((NNTP_sock->sock = (tcp_Socket *) farmalloc(sizeof(tcp_Socket))) == NULL) {
  841.     farfree(NNTP_sock);
  842.     err_exit(EXIT_FAILURE, "\n ■ Insufficient memory for socket... aborting.");
  843.   }
  844.   if (!tcp_open(NNTP_sock->sock, 0, h, NNTP_PORT, NULL)) {
  845.     free_Mail_Socket(NNTP_sock);
  846.     err_exit(EXIT_FAILURE, "\n ■ TCP socket open failed... aborting");
  847.   }
  848.   sock_mode(NNTP_sock->sock, TCP_MODE_ASCII);
  849.   sock_wait_established(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  850.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  851.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  852.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  853.   switch (reply) {
  854.     case 200:
  855.       log_it("\n ■ Connection to %s accepted...", host);
  856.       break;
  857.     case 502:
  858.       free_Mail_Socket(NNTP_sock);
  859.       err_exit(EXIT_FAILURE, "\n ■ Connection to %s refused... try again later.", host);
  860.       break;
  861.     case 503:
  862.       free_Mail_Socket(NNTP_sock);
  863.       err_exit(EXIT_FAILURE, "\n ■ NNTP service unavailable. Connection to %s refused.", host);
  864.       break;
  865.     default:
  866.       free_Mail_Socket(NNTP_sock);
  867.       err_exit(EXIT_FAILURE, "\n ■ Unknown NNTP error. Connection to %s failed.", host);
  868.       break;
  869.   }
  870.   SOCK_READ_ERR(NNTP_sock);
  871.   return (NNTP_sock);
  872. }
  873.  
  874. int cnext(Mail_Socket * NNTP_sock)
  875. {
  876.   char *p, *q;
  877.   static char _temp_buffer[STRING];
  878.  
  879.   sock_printf(NNTP_sock->sock, "NEXT");
  880.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  881.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  882.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  883.   if (reply == 421)
  884.     return -1;
  885.   else
  886.     if (reply == 223) {
  887.     cur_article = reparticle;
  888.     p = _temp_buffer;
  889.     q = cur_articleid;
  890.     while ((p < _temp_buffer + STRING - 2) && (*p != '<'))
  891.       p++;
  892.     while ((p < _temp_buffer + STRING - 2) && (*p != '>'))
  893.       *q++ = *p++;
  894.     *q++ = '>';
  895.     *q++ = '\0';
  896.     return 0;
  897.     }
  898.   else {
  899.     log_it("\n ■ Unknown cnext error : %s", _temp_buffer);
  900.   }
  901.   SOCK_READ_ERR(NNTP_sock);
  902.   return -1;
  903. }
  904.  
  905. int saveactive(Mail_Socket * NNTP_sock, char *fn)
  906. {
  907.   char s[181], group[256], act;
  908.   unsigned long to, from;
  909.   int count;
  910.   FILE *fp;
  911.   static char _temp_buffer[BIGSTR];
  912.  
  913.   if ((fp = fsh_open(fn, "w")) == NULL) {
  914.     perror(fn);
  915.     return -1;
  916.   }
  917.   sock_printf(NNTP_sock->sock, "LIST");
  918.   sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  919.   sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  920.   sscanf(_temp_buffer, "%hu %lu", &reply, &reparticle);
  921.   if (reply == 215) {
  922.     count = 0;
  923.     while (1) {
  924.       if (count++ % 25 == 0)
  925.         fprintf(stderr, "\b\b\b\b\b\b\b%-7d", count);
  926.       sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  927.       sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  928.       if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0)
  929.         break;
  930.       sscanf(_temp_buffer, "%s %lu %lu %c", group, &to, &from, &act);
  931.       sprintf(s, "%s %lu\n", group, to);
  932.       fprintf(fp, s);
  933.     }
  934.     log_it("\n ■ %d total newsgroups available on %s", count, serverhost);
  935.     fclose(fp);
  936.     return 0;
  937.   } else
  938.     log_it("\n ■ Unknown saveactive error : %s", _temp_buffer);
  939.   SOCK_READ_ERR(NNTP_sock);
  940.   fclose(fp);
  941.   return -1;
  942. }
  943.  
  944. int checkx(int cug)
  945. {
  946.   char *ptr, *ptr2, *ptr3, buf[256];
  947.   int i, max;
  948.  
  949.   if (cug == 0)
  950.     return 1;
  951.   ptr = strtok(cur_organization, "*");
  952.   trimstr1(ptr);
  953.   if (strcmpi(ptr, syscfg.systemname) == 0) {
  954.     log_it("\n ■ Skipping message - original post from %s.", syscfg.systemname);
  955.     return 0;
  956.   }
  957.   ptr = cur_newsgroups;
  958.   while (*ptr == ' ')
  959.     ptr++;
  960.   max = 0;
  961.   while (1) {
  962.     if (*ptr == 0)
  963.       break;
  964.     if (*ptr == ',') {
  965.       ptr++;
  966.       ++max;
  967.     }
  968.     while (*ptr == ' ')
  969.       ptr++;
  970.     ptr2 = ptr;
  971.     ptr3 = buf;
  972.     while (*ptr2 != 0 && *ptr2 != ',')
  973.       *ptr3++ = *ptr2++;
  974.     *ptr3 = 0;
  975.     while (*(--ptr3) == ' ')
  976.       *ptr3 = 0;
  977.     ptr = ptr2;
  978.     for (i = 0; i < cug; i++) {
  979.       if (strcmpi(buf, grouprec[i].groupname) == 0) {
  980.         fprintf(stderr, "\n ■ Skipping message - already posted in %s.",
  981.                 grouprec[i].groupname);
  982.         return 0;
  983.       }
  984.     }
  985.     if (max > 10) {
  986.       fprintf(stderr, "\n ■ Skipping message - crossposted to more than 10 newsgroups.");
  987.       return 0;
  988.     }
  989.   }
  990.   return 1;
  991. }
  992.  
  993. void good_name(char *name)
  994. {
  995.   char *ss;
  996.   int i;
  997.  
  998.   trimstr1(name);
  999.   if ((strcspn(name, " ") == strlen(name)) && (strcspn(name, "(") == strlen(name)))
  1000.     if (_fstrchr(name, '@') != NULL)
  1001.       return;
  1002.   if (strcspn(name, "<") != strlen(name)) {
  1003.     ss = strtok(name, "<");
  1004.     if (ss)
  1005.       ss = strtok(NULL, ">");
  1006.     strcpy(name, ss);
  1007.     if (name[0] == 0)
  1008.       strcpy(name, "Unknown");
  1009.     return;
  1010.   }
  1011.   if ((i = strcspn(name, "(")) != strlen(name)) {
  1012.     if (name[i - 1] == 32) {
  1013.       ss = strtok(name, " ");
  1014.       if (ss)
  1015.         strcpy(name, ss);
  1016.     } else {
  1017.       ss = strtok(name, "(");
  1018.       if (ss)
  1019.         strcpy(name, ss);
  1020.     }
  1021.     if (name[0] == 0)
  1022.       strcpy(name, "Unknown");
  1023.     return;
  1024.   }
  1025. }
  1026.  
  1027. int postnews(Mail_Socket * NNTP_sock, int cug)
  1028. {
  1029.   char s[181], s1[12], s2[5], fn[201], *ss;
  1030.   int f1, nlines, in_header, len, tlen;
  1031.   FILE *fp;
  1032.   static char _temp_buffer[STR];
  1033.   long clock;
  1034.   struct ffblk ff;
  1035.  
  1036.   sprintf(fn, "%s\\OUTBOUND\\%hu.*", net_data, grouprec[cug].subtype);
  1037.   f1 = findfirst(fn, &ff, 0);
  1038.   if (f1 != 0) {
  1039.     log_it("\n ■ No outbound news articles to post...");
  1040.     return 1;
  1041.   }
  1042.   while (f1 == 0) {
  1043.     sock_printf(NNTP_sock->sock, "POST");
  1044.     sock_wait_input(NNTP_sock->sock, SOCK_DELAY, NULL, &NNTP_stat);
  1045.     sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1046.     if (*_temp_buffer != '3') {
  1047.       if (atoi(_temp_buffer) == 440)
  1048.         log_it("\n ■ No posting allowed to %s!", grouprec[cug].groupname);
  1049.       else
  1050.         log_it("\n ■ Remote error: %s", _temp_buffer);
  1051.       return 0;
  1052.     }
  1053.     fprintf(stderr, "\n ■ Posting article to %s\n", grouprec[cug].groupname);
  1054.     sprintf(s, "%s\\OUTBOUND\\%s", net_data, ff.ff_name);
  1055.     fp = fsh_open(s, "rb");
  1056.     nlines = 0;
  1057.     while (fgets(_temp_buffer, 120, fp) != NULL) {
  1058.       if (_temp_buffer[0] == '.' && _temp_buffer[1] == 0) {
  1059.         _temp_buffer[1] = '.';
  1060.         _temp_buffer[2] = 0;
  1061.       }
  1062.       tlen = 0;
  1063.       len = strlen(_temp_buffer);
  1064.       while (tlen < len) {
  1065.         if (!tcp_tick(NNTP_sock->sock)) {
  1066.           fclose(fp);
  1067.           fprintf(stderr, "\n ■ Connection reset by host");
  1068.           return 1;
  1069.         }
  1070.         tlen += sock_fastwrite(NNTP_sock->sock, &_temp_buffer[tlen], len - tlen);
  1071.       }
  1072.       backline();
  1073.       fprintf(stderr, "\r ■ Lines sent : %d", ++nlines);
  1074.     }
  1075.     fclose(fp);
  1076.     sock_printf(NNTP_sock->sock, ".\n");
  1077.     fprintf(stderr, "\n ■ Awaiting acknowledgement - may take several minutes...");
  1078.     log_it("\n ■ Server response : ");
  1079.     sock_wait_input(NNTP_sock->sock, 180, NULL, &NNTP_stat);
  1080.     sock_gets(NNTP_sock->sock, _temp_buffer, sizeof(_temp_buffer));
  1081.     log_it("%s", _temp_buffer);
  1082.     if (*_temp_buffer != '2') {
  1083.       if (atoi(_temp_buffer) == 441) {
  1084.         ss = strtok(_temp_buffer, " ");
  1085.         ss = strtok(NULL, " ");
  1086.         if (atoi(ss) == 435)
  1087.           unlink(s);
  1088.         fnsplit(s, NULL, NULL, s1, s2);
  1089.         log_it("\n ■ %s%s not accepted by server - nothing posted", s1, s2);
  1090.       } else
  1091.         log_it("\n ■ Remote error: %s", _temp_buffer);
  1092.     } else {
  1093.       if (unlink(s) == 0)
  1094.         log_it("\n ■ Deleted sent message - %s", s);
  1095.     }
  1096.     f1 = findnext(&ff);
  1097.   }
  1098.   SOCK_READ_ERR(NNTP_sock);
  1099.   return 0;
  1100. }
  1101.  
  1102. int get_subtype(int sub)
  1103. {
  1104.   int ok;
  1105.   char fn[181], s[81], net_name[21], *ss;
  1106.   FILE *fp;
  1107.  
  1108.   sprintf(fn, "%sSUBS.XTR", syscfg.datadir);
  1109.   fp = fsh_open(fn, "r");
  1110.   if (!fp)
  1111.     return 0;
  1112.   ok = 0;
  1113.   while (fgets(s, 80, fp)) {
  1114.     if (s[0] == '!') {
  1115.       if (sub == atoi(&s[1]))
  1116.         ok = 1;
  1117.     }
  1118.     if (ok && (s[0] == '$')) {
  1119.       ss = strtok(s, " ");
  1120.       strcpy(net_name, &ss[1]);
  1121.       ss = strtok(NULL, " ");
  1122.       fclose(fp);
  1123.       if ((stricmp(net_name, "FILENET") == 0) && (isdigit(ss[0])))
  1124.         return atoi(ss);
  1125.       else
  1126.         return 0;
  1127.     }
  1128.   }
  1129.   fclose(fp);
  1130.   return 0;
  1131. }
  1132.  
  1133. int max_on_sub(int cug)
  1134. {
  1135.   int i, f, max_subs, num_subs, stype;
  1136.   char s[121];
  1137.  
  1138.   if (grouprec[cug].subtype == 0)
  1139.     return 0;
  1140.   max_subs = syscfg.max_subs;
  1141.   subboards = (subboardrec *) mallocx(max_subs * sizeof(subboardrec));
  1142.   sprintf(s, "%sSUBS.DAT", syscfg.datadir);
  1143.   f = sh_open1(s, O_RDONLY | O_BINARY);
  1144.   if (f < 0) {
  1145.     fprintf(stderr, "\n ■ %s NOT FOUND", s);
  1146.     return 0;
  1147.   }
  1148.   num_subs = (sh_read(f, subboards, (max_subs * sizeof(subboardrec)))) /
  1149.       sizeof(subboardrec);
  1150.   f = sh_close(f);
  1151.   for (i = 0; i < num_subs; i++) {
  1152.     fprintf(stderr, "\b\b\b\b%-4d", i);
  1153.     stype = get_subtype(i);
  1154.     if (stype && (grouprec[cug].subtype == stype)) {
  1155.       if (subboards)
  1156.         free(subboards);
  1157.       fprintf(stderr, "\b\b\b\b%hu messages.", subboards[i].maxmsgs);
  1158.       return subboards[i].maxmsgs;
  1159.     }
  1160.   }
  1161.   if (subboards)
  1162.     free(subboards);
  1163.   return 0;
  1164. }
  1165.  
  1166. int getnews(char *hostname)
  1167. {
  1168.   int f1, nup, nug, cug, abort, ok, done, firstrun, new_articles, max_articles, parts;
  1169.   char *p, fn[201], mailname[121], reline[121], s[21], s1[21], pktname[121];
  1170.   char orig_subj[STRING];
  1171.   unsigned int text_len;
  1172.   net_header_rec nh;
  1173.   struct date dt;
  1174.   struct time tm;
  1175.   struct ffblk ff;
  1176.   static FILE *fp;
  1177.   Mail_Socket *nntp_sock;
  1178.   static char _temp_buffer[STR];
  1179.  
  1180.   abort = cug = 0;
  1181.   sock_init();
  1182.   nntp_sock = netsocket(hostname);
  1183.  
  1184.   if (stricmp(grouprec[0].groupname, "newsrc") == 0) {
  1185.     grouprec[0].groupname[0] = 0;
  1186.     write_groups(0);
  1187.     if (grouprec)
  1188.       free(grouprec);
  1189.     sprintf(fn, "%s\\NEWSRC", net_data);
  1190.     log_it("\n ■ Creating newsgroup list : %s...         ", fn);
  1191.     saveactive(nntp_sock, fn);
  1192.     nntp_shutdown(nntp_sock);
  1193.     free_Mail_Socket(nntp_sock);
  1194.     return 0;
  1195.   }
  1196.   nug = nup = 1;
  1197.   while ((cug < ngroups) && (!abort)) {
  1198.     if (kbhit()) {
  1199.       if (getch() == 27) {
  1200.         log_it("\n ■ Aborting news retrieval session...");
  1201.         if (fp)
  1202.           fclose(fp);
  1203.         grouprec[cug].lastread = cur_article;
  1204.         write_groups(1);
  1205.         nntp_shutdown(nntp_sock);
  1206.         free_Mail_Socket(nntp_sock);
  1207.         return 1;
  1208.       }
  1209.     }
  1210.     if (nup) {
  1211.       nup = 0;
  1212.       if (grouprec[cug].subtype) {
  1213.         if (fp)
  1214.           fclose(fp);
  1215.         write_groups(0);
  1216.         name_packet(pktname);
  1217.         if ((fp = fsh_open(pktname, "wb")) == NULL) {
  1218.           log_it("\n ■ Unable to create %s!", pktname);
  1219.           qexit(nntp_sock, 1);
  1220.         } else {
  1221.           fnsplit(pktname, NULL, NULL, s, s1);
  1222.           fprintf(stderr, "\n ■ Creating new packet : %s%s", s, s1);
  1223.         }
  1224.       } else {
  1225.         if (fp) {
  1226.           fclose(fp);
  1227.         }
  1228.       }
  1229.     }
  1230.     if (nug) {
  1231.       cur_article = ++grouprec[cug].lastread;
  1232.       nug = 0;
  1233.       if (cgroup(nntp_sock, grouprec[cug].groupname)) {
  1234.         log_it("\n ■ %s is an invalid or deleted newsgroup...",
  1235.                grouprec[cug].groupname);
  1236.         grouprec[cug].groupname[0] = 0;
  1237.         if (++bogus >= 10) {
  1238.           log_it("\n ■ More than 10 invalid newsgroups... possible NEWS.RC error!");
  1239.           qexit(nntp_sock, 10);
  1240.         }
  1241.         nug = 1;
  1242.         continue;
  1243.       }
  1244.       log_it("\n ■ Requesting %s... ", grouprec[cug].groupname);
  1245.       if (grouprec[cug].lastread < cur_first)
  1246.         grouprec[cug].lastread = cur_first;
  1247.       if (grouprec[cug].lastread > cur_last) {
  1248.         grouprec[cug].lastread = cur_last;
  1249.         log_it("no new articles.");
  1250.         nug = 1;
  1251.       } else {
  1252.         new_articles = cur_last - grouprec[cug].lastread + 1;
  1253.         log_it("%lu new article%s.        ",
  1254.                cur_last - grouprec[cug].lastread + 1,
  1255.                new_articles == 1 ? "" : "s");
  1256.         if (new_articles > 250) {
  1257.           fprintf(stderr, "\n ■ Checking maximum articles allowed on sub :     ");
  1258.           max_articles = max_on_sub(cug);
  1259.           if (max_articles && (new_articles > max_articles)) {
  1260.             log_it("\n ■ Requesting most recent %d articles", max_articles);
  1261.             grouprec[cug].lastread = (cur_last - max_articles);
  1262.           }
  1263.         }
  1264.       }
  1265.       postnews(nntp_sock, cug);
  1266.       if (!nug) {
  1267.         if (cur_numa == 0) {
  1268.           log_it("\n ■ No articles available in %s...",
  1269.                  grouprec[cug].groupname);
  1270.           nug = 1;
  1271.           continue;
  1272.         } else {
  1273.           if (cstat(nntp_sock, grouprec[cug].lastread) &&
  1274.               cstat(nntp_sock, cur_last))
  1275.             nug = 1;
  1276.         }
  1277.       }
  1278.     } else {
  1279.       if (cnext(nntp_sock)) {
  1280.         fprintf(stderr, "\n ■ End of new articles in %s",
  1281.                 grouprec[cug].groupname);
  1282.         nug = 1;
  1283.         write_groups(1);
  1284.       }
  1285.     }
  1286.     if (!nug) {
  1287.       // if ((!chead(nntp_sock)) || (!checkx(cug))) {
  1288.       if ((chead(nntp_sock)) && (checkx(cug))) {
  1289.         if (cur_subject[0]) {
  1290.           treat(cur_subject);
  1291.           if (strlen(cur_subject) > 65)
  1292.             cur_subject[65] = '\0';
  1293.         } else
  1294.           strcpy(cur_subject, "No subject");
  1295.         strcpy(orig_subj, cur_subject);
  1296.         if (cur_from[0]) {
  1297.           treat(cur_from);
  1298.           if (strlen(cur_from) > 45)
  1299.             cur_from[45] = 0;
  1300.         } else
  1301.           strcpy(cur_from, "Unknown");
  1302.         if (cur_replyto[0]) {
  1303.           /* treat(cur_replyto);     */
  1304.           /* good_name(cur_replyto); */
  1305.           if (strlen(cur_replyto) > 45)
  1306.             cur_replyto[45] = 0;
  1307.         }
  1308.         strncpy(_temp_buffer, orig_subj, 55);
  1309.         _temp_buffer[55] = '\0';
  1310.         fprintf(stderr, "\n ■ [%lu/%lu] : %s ", cur_article,
  1311.                 cur_last, _temp_buffer);
  1312.         ok = savebody(nntp_sock, cug, &abort);
  1313.         if (ok && grouprec[cug].subtype) {
  1314.           strcpy(msgarea, grouprec[cug].groupname);
  1315.           sprintf(msgto, "All");
  1316.           sprintf(fn, "%s\\INPUT*.MSG", tmpdir);
  1317.           done = 1;
  1318.           parts = 0;
  1319.           if (findfirst(fn, &ff, 0) == 0) {
  1320.             parts = 1;
  1321.             done = 0;
  1322.           }
  1323.           firstrun = 1;
  1324.           while (!done) {
  1325.             sprintf(fn, "%s\\%s", tmpdir, ff.ff_name);
  1326.             f1 = sh_open1(fn, O_RDONLY | O_BINARY);
  1327.             text_len = (unsigned int) filelength(f1);
  1328.             if (text_len > 32000L) {
  1329.               fprintf(stderr, "\n ■ Truncating %ld bytes from input file",
  1330.                       text_len - 32000L);
  1331.               text_len = 32000L;
  1332.             }
  1333.             p = (char *) malloca(32767);
  1334.             if (!p) {
  1335.               log_it("\n ■ Insufficient memory to read entire message");
  1336.               qexit(nntp_sock, 1);
  1337.             }
  1338.             sh_read(f1, (void *) p, text_len);
  1339.             sh_close(f1);
  1340.             nh.tosys = sy;
  1341.             nh.touser = 0;
  1342.             nh.fromsys = 32767L;
  1343.             nh.fromuser = 0;
  1344.             nh.main_type = main_type_pre_post;
  1345.             nh.minor_type = grouprec[cug].subtype;
  1346.             nh.list_len = 0;
  1347.             gettime(&tm);
  1348.             getdate(&dt);
  1349.             nh.daten = dostounix(&dt, &tm);
  1350.             nh.method = 0;
  1351.             if (parts > 1) {
  1352.               sprintf(_temp_buffer, "%d%s ", parts, ordinal_text(parts));
  1353.               strcat(_temp_buffer, orig_subj);
  1354.               strcpy(cur_subject, _temp_buffer);
  1355.               if (strlen(cur_subject) > 72)
  1356.                 cur_subject[72] = '\0';
  1357.               else
  1358.                 cur_subject[strlen(cur_subject)] = '\0';
  1359.             }
  1360.             nh.length = text_len + strlen(cur_subject) + 1;
  1361.             strncpy(mailname, cur_replyto, 46);
  1362.             strcat(mailname, "\r\n");
  1363.             nh.length += strlen(mailname);
  1364.             nh.length += 24 + 2;
  1365.             if (firstrun) {
  1366.               firstrun = 0;
  1367.               strncpy(reline, cur_articleid, 60);
  1368.               sprintf(cur_articleid, "RE: %s\r\n\r\n", reline);
  1369.             }
  1370.             nh.length += strlen(cur_articleid);
  1371.             fwrite(&nh, sizeof(net_header_rec), 1, fp);
  1372.             fwrite(cur_subject, sizeof(char), strlen(cur_subject) +1, fp);
  1373.             fwrite(mailname, sizeof(char), strlen(mailname), fp);
  1374.             strncpy(_temp_buffer, ctime(&(time_t) nh.daten), 24);
  1375.             _temp_buffer[24] = '\0';
  1376.             strcat(_temp_buffer, "\r\n");
  1377.             fwrite(_temp_buffer, sizeof(char), strlen(_temp_buffer), fp);
  1378.             sprintf(_temp_buffer, "%s\n\n", cur_articleid);
  1379.             fwrite(cur_articleid, sizeof(char), strlen(cur_articleid), fp);
  1380.             fwrite(p, sizeof(char), text_len, fp);
  1381.             if (p)
  1382.               free(p);
  1383.             unlink(fn);
  1384.             if (findnext(&ff) == 0) {
  1385.               done = 0;
  1386.               ++parts;
  1387.             } else
  1388.               done = 1;
  1389.           }
  1390.         }
  1391.         grouprec[cug].lastread = cur_article;
  1392.       } else
  1393.         grouprec[cug].lastread = cur_article + 1;
  1394.       if ((filelength(fileno(fp)) > 250000L) && grouprec[cug].subtype)
  1395.         nup = 1;
  1396.       if (abort == 2) {
  1397.         write_groups(1);
  1398.         nug = 1;
  1399.         abort = 0;
  1400.       }
  1401.     }
  1402.     if (nug) {
  1403.       ++cug;
  1404.       if ((grouprec[cug - 1].subtype == 0) && (grouprec[cug].subtype)) {
  1405.         nup = 1;
  1406.       } else {
  1407.         if ((grouprec[cug - 1].subtype) && (grouprec[cug].subtype == 0)) {
  1408.           if (fp) {
  1409.             fclose(fp);
  1410.           }
  1411.         }
  1412.       }
  1413.     }
  1414.   }
  1415.   if (fp)
  1416.     fclose(fp);
  1417.   if (abort)
  1418.     log_it("\n ■ Session aborted from keyboard");
  1419.   write_groups(1);
  1420.   nntp_shutdown(nntp_sock);
  1421.   free_Mail_Socket(nntp_sock);
  1422.   return 0;
  1423. }
  1424.  
  1425. void main(int argc, char *argv[])
  1426. {
  1427.   int f;
  1428.   char s[201], fn[201], *ss;
  1429.   FILE *fp;
  1430.   struct tm *time_now;
  1431.   time_t some;
  1432.  
  1433.   cursor('S');
  1434.   cursor('H');
  1435.   fprintf(stderr, "\n ■ %s", version);
  1436.   if (argc != 4)
  1437.     err_exit(EXIT_FAILURE, "\n ■ Invalid arguments for %s", argv[0]);
  1438.   ss = getenv("WWIV_INSTANCE");
  1439.   if (ss) {
  1440.     instance = atoi(ss);
  1441.     if ((instance <= 0) || (instance >= 1000)) {
  1442.       log_it("\n ■ WWIV_INSTANCE set to %d.  Can only be 1..999!", instance);
  1443.       instance = 1;
  1444.     }
  1445.   } else
  1446.     instance = 1;
  1447.   SOCK_DELAY = 120;
  1448.   get_dir(maindir, 0);
  1449.   strcpy(net_data, argv[1]);
  1450.   strcpy(serverhost, argv[2]);
  1451.   time(&some);
  1452.   time_now = localtime(&some);
  1453.   strftime(s, 80, "\n\nNEWS session beginning on %A, %B %d, %Y at %H:%M %p",
  1454.            time_now);
  1455.   sprintf(fn, "%s\\NEWS.LOG", net_data);
  1456.   if ((fp = fsh_open(fn, "at")) != NULL) {
  1457.     fprintf(fp, s);
  1458.     fclose(fp);
  1459.   }
  1460.   sprintf(tmpdir, "%s\\SPOOL", net_data);
  1461.   sy = atoi(argv[3]);
  1462.   sprintf(s, "%s\\CONFIG.DAT", maindir);
  1463.   f = sh_open1(s, O_RDONLY | O_BINARY);
  1464.   if (f < 0)
  1465.     err_exit(EXIT_FAILURE, "\n ■ %s NOT FOUND.", s);
  1466.   sh_read(f, (void *) (&syscfg), sizeof(configrec));
  1467.   sh_close(f);
  1468.   sprintf(newsrc, "%s\\NEWS.RC", net_data);
  1469.   read_groups();
  1470.   if (ngroups == 0)
  1471.     err_exit(EXIT_FAILURE, "\n ■ Unable to access newsgroup file: %s!", newsrc);
  1472.   if (stricmp(grouprec[0].groupname, "newsrc") == 0)
  1473.     log_it("\n ■ Retrieving current newsgroup listing from %s",
  1474.            serverhost);
  1475.   else
  1476.     log_it("\n ■ %d newsgroup%s defined in %s", ngroups,
  1477.            ngroups == 1 ? "" : "s", strlwr(newsrc));
  1478.   if (getnews(serverhost))
  1479.     err_exit(EXIT_FAILURE, "\n ■ Exiting program.");
  1480.   if (grouprec)
  1481.     free(grouprec);
  1482.   grouprec = NULL;
  1483.   cd_to(maindir);
  1484.   log_it("\n ■ NEWS succesfully completed processing %d newsgroups", ngroups);
  1485.   err_exit(EXIT_SUCCESS, "\n ■ Normal program termination");
  1486. }
  1487.