home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / thread / pmnews1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-12  |  28.5 KB  |  1,084 lines

  1.  
  2. /*
  3.     PMNEWS 1.0
  4.  
  5.     Service functions for the PMNEWS news reader
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License, version 1, as
  9.     published by the Free Software Foundation.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     See the file COPYING, which contains a copy of the GNU General
  17.     Public License.
  18.  
  19.  */
  20. #include  <ctype.h>
  21. #define   INCL_DOSSEMAPHORES
  22. #define   INCL_DOSPROCESS
  23. #define   INCL_DOSSESMGR
  24. #define   INCL_DOSQUEUES
  25. #include  <os2.h>
  26. #include "defs.h"
  27. #include "pmnews.h"
  28. #include "pmnthrd.h"
  29.  
  30.  
  31. static unsigned char   SysTermQ[] = "\\QUEUES\\PMNEWS\\EDITART.QUE";
  32. HQUEUE SysTermH;  /* must be static, since it needs to be open
  33.                      for the life of our thread */
  34. /*--------------------------- new_session --------------------------------*/
  35. /* start a new session (text-windowed, foreground, child )
  36.    the boys who thought this up were some very sick puppies */
  37. int  new_session( PSZ  cmd, PBYTE opt, PSZ title )
  38. {
  39.  
  40.   STARTDATA  sd;
  41.   ULONG sessnum = 0;
  42.   PID   pid = 0;
  43.   APIRET rc;
  44.   REQUESTDATA rq;
  45.   PVOID  dbuf;
  46.   ULONG  dlen;
  47.   BYTE   pri;
  48.  
  49.   if ( SysTermH == (HQUEUE)NULL )
  50.   rc = DosCreateQueue( &SysTermH, 0L, &SysTermQ[0] );
  51.  
  52.   memset( &sd, 0, sizeof(STARTDATA) );
  53.   sd.Length = sizeof(STARTDATA);
  54.   sd.Related = SSF_RELATED_CHILD;
  55.   sd.FgBg = SSF_FGBG_FORE;
  56.   sd.TraceOpt = SSF_TRACEOPT_NONE;
  57.   sd.PgmTitle = title;
  58.   sd.PgmName  = cmd;
  59.   sd.PgmInputs = opt;
  60.   sd.TermQ = &SysTermQ[0];
  61.   sd.Environment = NULL;
  62.   sd.InheritOpt = SSF_INHERTOPT_PARENT;
  63.   sd.SessionType = SSF_TYPE_DEFAULT;
  64.   sd.IconFile = NULL;
  65.   sd.PgmHandle = 0;
  66.  
  67.   rc = DosStartSession( &sd, &sessnum, &pid );
  68.   if ( rc ) fprintf( errf, "startsess: %ld  num: %ld %x\n", rc, sessnum, pid );
  69.   else
  70.      do {
  71.         rc = DosReadQueue( SysTermH, &rq, &dlen, &dbuf, 0L, DCWW_WAIT, &pri, (HEV)0L );
  72.         DosFreeMem( dbuf );
  73.         }  while ( rq.ulData != 0 && rc == 0 );
  74.  
  75.   return 0;
  76. }
  77.  
  78. /*--------------------------- expand the tabs ----------------------------*/
  79. void expand_tabs(char *buf, int max_len)
  80. {
  81.     int  l, k;
  82.     char tmp[256], *p, *t;
  83.  
  84.     p = buf;
  85.     t = &tmp[0];
  86.     l = 0;
  87.  
  88.     while ((*p != '\x00') && (l < max_len - 1)) {
  89.         if (*p != '\x09') {
  90.             *t = *p;
  91.             t++;
  92.             p++;
  93.             l++;
  94.         } else {
  95.             p++;
  96.             k = ((l / 8) + 1) * 8;
  97.             for ( ; l < k ; l++) {
  98.                 *t = ' ';
  99.                 t++;
  100.                 if (l >= max_len - 1) break;
  101.             }
  102.         }
  103.     }
  104.  
  105.     *t = '\x00';
  106.     strcpy(buf, tmp);
  107. }
  108.  
  109.  
  110. /*------------------- count unread articles in a group --------------------*/
  111. int count_unread_in_group(ACTIVE *gp)
  112. {
  113.     /*
  114.      *  Take the thread 'a' for the given group 'gp' and return the number
  115.      *  of unread articles
  116.      */
  117.  
  118.     int articles, ct, i;
  119.  
  120.     ct = 0;
  121.     articles = (int)(gp->hi_num - gp->lo_num);
  122.  
  123.     for (i = 0; i < articles; i++) {
  124.         if ( (gp->read_list) && (*((gp->read_list)+i) == FALSE) )
  125.             ct++;
  126.     }
  127.  
  128.     return(ct);
  129. }
  130.  
  131.  
  132. /*------------------- count unread articles in a thread --------------------*/
  133. int count_unread_in_thread(ACTIVE *gp, ARTICLE *a)
  134. {
  135.     /*
  136.      *  Take the thread 'a' for the given group 'gp' and return the number
  137.      *  of unread articles
  138.      */
  139.  
  140.     ART_ID *id;
  141.     int    ct, idx;
  142.  
  143.     ct = 0;
  144.     id = a->art_num;
  145.  
  146.     while (id != NULL) {
  147.         idx = (int)(id->id - gp->lo_num - 1);
  148.         if (*((gp->read_list)+idx) == FALSE)
  149.             ct++;
  150.         id = id->next_art;
  151.     }
  152.  
  153.     return(ct);
  154. }
  155.  
  156. /********************************************************/
  157. void mark_group_as_read(ACTIVE *gp)
  158. {
  159.  
  160.     int articles, i;
  161.  
  162.  
  163.     articles = (int)(gp->hi_num - gp->lo_num);
  164.  
  165.     for (i = 0; i < articles; i++)
  166.         *((gp->read_list)+i) = TRUE;
  167.  
  168.  
  169. }
  170.  
  171.  
  172. /*------------------- mark articles read in a thread --------------------*/
  173. void mark_read_in_thread(ACTIVE *gp, ARTICLE *a)
  174. {
  175.     /*
  176.      *  Take the thread 'a' for the given group 'gp' and mark the articles
  177.      *  as read.
  178.      */
  179.  
  180.     ART_ID *id;
  181.     int     idx;
  182.  
  183.     id = a->art_num;
  184.  
  185.     while (id != NULL) {
  186.         idx = (int)(id->id - gp->lo_num - 1);
  187.         *((gp->read_list)+idx) = TRUE;
  188.         id = id->next_art;
  189.     }
  190.  
  191.     return;
  192. }
  193.  
  194.  
  195.  
  196.  
  197. /*-------------------- release the subject structures ---------------------*/
  198. void free_header(ARTICLE *start)
  199. {
  200.     /*
  201.      *  Work our way through the subject structure releasing all the
  202.      *  memory
  203.      */
  204.  
  205.     ARTICLE *a, *t;
  206.     ART_ID  *u, *v;
  207.  
  208.     a = start;
  209.  
  210.     while (a != NULL) {
  211.  
  212.         u = a->art_num;
  213.         while (u != NULL) {
  214.             v = u->next_art;
  215.             free(u);
  216.             u = v;
  217.         }
  218.  
  219.         t = a->next;
  220.         free(a->header);
  221.         free(a);
  222.         a = t;
  223.     }
  224. }
  225.  
  226. static char  noauth[] = "** no one **";
  227. static char  noname[] = "** unknown **";
  228.  
  229. /*---------------------- deallocate article memory ------------------------*/
  230. void free_article(TEXT *t)
  231. {
  232.  
  233.     aLINE *l, *k;
  234.  
  235.     l = t->top;
  236.     while (l != NULL) {
  237.         k = l;
  238.         l = l->next;
  239.         free(k);
  240.     }
  241.  
  242.     if ( t->author != noauth ) free( t->author );
  243.     if ( t->rname != noname ) free( t->rname );
  244.     free(t);
  245. }
  246.  
  247.  
  248. /*------------------------ clean up subject line ----------------------------*/
  249. void eat_gunk(char *buf)
  250. {
  251.     /*
  252.      *  This routine takes the header line, and strips the
  253.      *  word header word, 'Re:', and any extra blanks, trim to 59 chars
  254.      */
  255.  
  256.     char *p, tmp[256];
  257.  
  258.     buf[58] = 0;
  259.  
  260.  
  261.     /* strip the Subject: etc off the front */
  262.     while ((strstr(buf, "Re:") != NULL) ||
  263.         (strnicmp(buf, "From:", 5) == 0) ||
  264.         (strnicmp(buf, "Path:", 5) == 0) ||
  265.         (strnicmp(buf, "Subject:", 8) == 0) ||
  266.         (strnicmp(buf, "Organization:", 13) == 0) ||
  267.         (strnicmp(buf, "Organisation:", 13) == 0) ||
  268.         (strnicmp(buf, "Followup-To:", 12) == 0)) {
  269.         p = strstr(buf, ":");
  270.         strcpy(buf, p+1);
  271.     }
  272.  
  273.     strcpy(tmp, buf);
  274.     *buf = '\x00';
  275.     p = strtok(tmp, " \n\r");
  276.  
  277.     while (p != NULL) {
  278.  
  279.         if (stricmp(p, "Re:") != 0) {
  280.             strcat(buf, p);
  281.             strcat(buf, " ");
  282.         }
  283.         p = strtok(NULL, " \n\r");
  284.     }
  285.  
  286.     if (strlen(buf) <= 1)
  287.         strcpy(buf, "** no subject **");
  288. }
  289.  
  290.  
  291.  
  292. /*----------------------- get stuf off article header --------------------*/
  293. void get_his_stuff(TEXT *txs, char *author, char *msg_id)
  294. {
  295.     /*
  296.      *  Retrieve the author and msg_id from the article
  297.      */
  298.  
  299.     aLINE *ln;
  300.     char *p;
  301.     char buf[100];
  302.     char *null_name = {" ** none ** "};
  303.  
  304.     strcpy(author, null_name);
  305.     strcpy(msg_id, " <none> ");
  306.  
  307.     ln = txs->top;
  308.     while (ln != NULL) {
  309.         strcpy(buf, ln->data);
  310.         p = strtok(buf, " :\n\r");
  311.         p = strtok(NULL, " :\n\r");
  312.         if (strnicmp(ln->data, "Message-ID:", 11) == 0) {
  313.             strcpy(msg_id, p);
  314.         }
  315.  
  316.         if ((strnicmp(ln->data, "From:", 5) == 0) &&
  317.           (strcmp(author, null_name) == 0)) {
  318.             strcpy(author, p);
  319.         }
  320.  
  321.         if (strnicmp(ln->data, "Reply-To:", 5) == 0) {
  322.             strcpy(author, p);
  323.         }
  324.  
  325.         if (strlen(ln->data) < 2) break;
  326.         ln = ln->next;
  327.     }
  328. }
  329.  
  330. /*------------------------- read the headers --------------------------*/
  331. ARTICLE *get_headers(ACTIVE *gp)
  332. {
  333.     /*
  334.      *  Read the files and get the headers
  335.      */
  336.  
  337.     char *fn;
  338.     char buf[256], fnx[256], *buf_p;
  339.     long g;
  340.     FILE *tmp_file;
  341.  
  342.     ARTICLE *start, *that, *tmp;
  343.     ART_ID  *art_this, *new;
  344.     int     ct_art;
  345.     void    *user;
  346.  
  347.     ct_art = 0;
  348.     start  = NULL;
  349.  
  350.     user  = thread_init();
  351.  
  352.     fn = make_news_group_name(gp->group);
  353.     sprintf(fnx, "%s.IDX", fn);
  354.  
  355.     if ((tmp_file = fopen(fnx, "rb")) != NULL) {
  356.  
  357.         for (g = gp->lo_num+1; g <= gp->hi_num; g++) {
  358.  
  359.  
  360.             /*
  361.              *  Read the index
  362.              *  Search the linked list for the subject
  363.              *    - allocate a new subject if necessary
  364.              *    - add to the existing list
  365.              */
  366.  
  367.             if (fgets(buf, 255, tmp_file) == NULL) {
  368.                 message( "Index file is corrupt", "PMNews error", MB_CANCEL );
  369.                 exit(1);
  370.             }
  371.  
  372.             /* check all is in sync */
  373.             if (g != atol(buf+9)) {
  374.                 sprintf( fnx, "Article %ld found when %ld expected",
  375.                                atol(buf+9), g );
  376.                 message( fnx, "PMNews error", MB_CANCEL );
  377.                 exit(1);
  378.             }
  379.  
  380.             /* skip the two eight digit numbers and the 9 and the spaces */
  381.             buf_p = buf+28;
  382.  
  383.             eat_gunk(buf_p);
  384.  
  385.             if ( thread_compare( buf_p, user, &tmp ) )
  386.                {
  387.                     /* found this subject */
  388.                     tmp->num_articles++;
  389.  
  390.                     /* allocate new article number */
  391.                     new = xmalloc(sizeof (ART_ID));
  392.                     new->id = g;
  393.                     new->art_off = atol(buf);
  394.  
  395.                     /* place it at the end */
  396.                     art_this = tmp->art_num;
  397.                     while (art_this->next_art != NULL) {
  398.                         art_this = art_this->next_art;
  399.                     }
  400.                     art_this->next_art = new;
  401.  
  402.                     new->last_art = art_this;
  403.                     new->next_art = NULL;
  404.  
  405.                }
  406.  
  407.             else
  408.                {
  409.                /* not found - allocate new thread */
  410.  
  411.                 if (start == NULL) {
  412.                     start = tmp;  /* side-effect of thread_compare */
  413.                     that = start;
  414.                     that->last = NULL;
  415.                 } else {
  416.                     ct_art++;
  417.                     that->next = tmp; /* side-effect of thread_compare */
  418.                     that->next->last = that;
  419.                     that = that->next;
  420.                 }
  421.  
  422.                 that->next = NULL;
  423.                 that->index = ct_art;
  424.                 /* that->left and that->right may be modified
  425.                    by thread_compare */
  426.  
  427.                 /* store article data */
  428.                 that->header = xmalloc(strlen(buf_p) + 1);
  429.                 strcpy(that->header, buf_p);
  430.                 that->num_articles = 1;
  431.  
  432.                 that->art_num = xmalloc(sizeof (ART_ID));
  433.                 that->art_num->last_art = NULL;
  434.                 that->art_num->next_art = NULL;
  435.                 that->art_num->id = g;
  436.                 that->art_num->art_off = atol(buf);
  437.  
  438.             }
  439.         }
  440.  
  441.         thread_end( user );
  442.         fclose(tmp_file);
  443.  
  444.     } else {
  445.         sprintf( buf, "Can't open index file %s", fnx );
  446.         message( buf, "PMNews error", MB_CANCEL );
  447.         exit(1);
  448.     }
  449.  
  450.     return(start);
  451.  
  452. }
  453.  
  454.  
  455. /*------------------------- read in an article -----------------------------*/
  456. TEXT *load_article(char *fnx, long offset)
  457. {
  458.     /*
  459.      *  Open the file and read it.  Save the author and organisation
  460.      *  fill in the structures
  461.      */
  462.  
  463.     FILE *tmp_file;
  464.     char buf[256], lnbuf[256], *p, *rp;
  465.     TEXT *txn;
  466.     aLINE *ln, *lz;
  467.     int  ct, i;
  468.  
  469.     txn = NULL;
  470.     ct = 0;
  471.  
  472.     if ((tmp_file = fopen(fnx, "rb")) != NULL) {
  473.  
  474.         fseek(tmp_file, offset, SEEK_SET);
  475.  
  476.         txn = xmalloc(sizeof(TEXT));
  477.         txn->top = NULL;
  478.         txn->start = NULL;
  479.  
  480.  
  481.         strcpy(txn->follow_up, "");
  482.         txn->author =  &noauth[0];
  483.         txn->rname  =  &noname[0];
  484.  
  485.         strcpy(txn->organisation, " ** none ** ");
  486.  
  487.         while (fgets(buf, 255, tmp_file) != NULL) {
  488.  
  489.             if (strncmp(buf, "@@@@END", 7) == 0) break;
  490.  
  491.             expand_tabs(buf, 255);
  492.  
  493.             /*
  494.              *  We now have a line of input.  If the line is two long
  495.              *  it is wrapped at spaces or '!'.  The lines of text are
  496.              *  stored in LINE structures
  497.              */
  498.             p = &buf[0];
  499.             while (strlen(p) > 0) {
  500.  
  501.                 strcpy(lnbuf, p);
  502.                 if (strlen(p) <= 80) {
  503.                     strcpy(lnbuf, p);
  504.                     *p = '\x00';
  505.                 } else {
  506.                     p += 79;
  507.                     for (i = 79; i > 50; i--) {
  508.                         if ((lnbuf[i] == ' ') || (lnbuf[i] == '!'))
  509.                             break;
  510.                         p--;
  511.                     }
  512.                     lnbuf[i] = '\x00';
  513.                 }
  514.  
  515.                 /* is it the first line - if so int the TEXT structure */
  516.                 if (ct == 0) {
  517.                     ln = xmalloc(sizeof(aLINE));
  518.                     ln->last = NULL;
  519.                     txn->top = ln;
  520.                 } else {
  521.                     lz = ln;
  522.                     ln->next = xmalloc(sizeof(aLINE));
  523.                     ln = ln->next;
  524.                     ln->last = lz;
  525.                 }
  526.  
  527.                 lnbuf[79] = '\x00';
  528.                 ln->index = ct;
  529.                 strcpy(ln->data, lnbuf);
  530.  
  531.                 if ((strlen(lnbuf) == 1) && (txn->start == NULL))
  532.                     txn->start = ln;
  533.  
  534.                 ct++;
  535.  
  536.                 /* save the header info */
  537.                 if ((txn->start == NULL) && (strncmp("From:", lnbuf, 5) == 0)) {
  538.                     eat_gunk(lnbuf);
  539.                     rp = strchr(lnbuf, '(');
  540.                     txn->rname = NULL;
  541.                     if ( rp )
  542.                        {
  543.                        rp++;
  544.                        txn->rname = xmalloc( strlen( rp ) + 1 );
  545.                        strcpy( txn->rname, rp );
  546.                        if ( ( rp = strchr( txn->rname, ')' ) ) != NULL )
  547.                           *rp = '\0';
  548.                        }
  549.  
  550.                     txn->author = xmalloc(strlen(lnbuf) + 1);
  551.                     lnbuf[WHO_LENGTH-1] = '\x00';
  552.                     strcpy(txn->author, lnbuf);
  553.                 }
  554.                 if ((txn->start == NULL) &&
  555.                   ((strncmp("Organisation:", lnbuf, 13) == 0) ||
  556.                   (strncmp("Organization:", lnbuf, 13) == 0))) {
  557.                     eat_gunk(lnbuf);
  558.                     lnbuf[WHO_LENGTH-1] = '\x00';
  559.                     strcpy(txn->organisation, lnbuf);
  560.                 }
  561.  
  562.                 if ((txn->start == NULL) && (strncmp("Followup-To:", lnbuf, 12) == 0)) {
  563.                     eat_gunk(lnbuf);
  564.                     lnbuf[79] = '\x00';
  565.                     strcpy(txn->follow_up, lnbuf);
  566.                 }
  567.             }
  568.  
  569.         }
  570.  
  571.         ln->next = NULL;
  572.         txn->lines = ct;
  573.  
  574.         fclose(tmp_file);
  575.     }
  576.  
  577.     return(txn);
  578. }
  579.  
  580. static char *addressee;
  581.  
  582. /********************* mail current article ************************/
  583. void mail_to_someone(TEXT *tx, char * who )
  584. {
  585.     /*
  586.      *  Mail this article to someone
  587.      */
  588.  
  589.     ULONG  pcnt;
  590.     FILE  *tmp;
  591.     aLINE *ln;
  592.     char fn[80];
  593.     char buf[256];
  594.     char author[80], msg_id[80];
  595.  
  596.     strcpy(fn, "reply.tmp");
  597.  
  598.     if ((tmp= fopen(fn, "w")) != NULL) {
  599.  
  600.         get_his_stuff(tx, author, msg_id);
  601.  
  602.         /* add the quoted message */
  603.  
  604.         fprintf(tmp, "\nThis article was forwarded to you by %s@%s (%s):\n\n",
  605.             my_stuff.user, my_stuff.my_domain, my_stuff.my_name);
  606.         fprintf(tmp,"--------------------------------- cut here -----------------------------\n\n");
  607.         ln = tx->top;
  608.         while (ln != NULL) {
  609.             fprintf(tmp, "%s", ln->data);
  610.             ln = ln->next;
  611.         }
  612.  
  613.         fprintf(tmp,"--------------------------------- cut here -----------------------------\n\n");
  614.  
  615.         fclose(tmp);
  616.  
  617.         pcnt = 0;
  618.  
  619.         addressee = who;
  620.  
  621.         WinPostMsg( hwndArt, WM_USER, MPFROMLONG(MAIL_VERIFY),
  622.                      MPFROMP(addressee) );
  623.  
  624.  
  625.         DosWaitEventSem( work_to_do, -1L );
  626.         DosResetEventSem( work_to_do, &pcnt );
  627.  
  628.         if ( queryans == MBID_YES )
  629.             {
  630.             sprintf(buf, "mail %s <%s", who, fn);
  631.             system(buf);
  632.             }
  633.         remove(fn);
  634.  
  635.     } else {
  636.         WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  637.     }
  638.  
  639. }
  640.  
  641.  
  642.  
  643. /*-------------------------- reply to article ---------------------------*/
  644. void reply_to_article(TEXT *tx)
  645. {
  646.     /*
  647.      *  Mail reply to article
  648.      */
  649.  
  650.     FILE *sig;
  651.     char sig_fn[80];
  652.  
  653.     FILE *tmp;
  654.     aLINE *ln;
  655.     ULONG  pcnt;
  656.     char fn[80];
  657.     char buf[256];
  658.     char author[80], msg_id[80];
  659.     char *cp;
  660.  
  661.     strcpy(fn, "reply.tmp");
  662.  
  663.     if ((tmp = fopen(fn, "w")) != NULL)
  664.         {
  665.         get_his_stuff(tx, author, msg_id);
  666.  
  667.  
  668.         /* add the quoted message */
  669.  
  670.         WinPostMsg( hwndArt, WM_USER, (MPARAM) REPART_QUOTE, (MPARAM) 0L );
  671.         DosWaitEventSem( work_to_do, -1L );
  672.         DosResetEventSem( work_to_do, &pcnt );
  673.  
  674.         if ( queryans == MBID_YES )
  675.            {
  676.  
  677.             fprintf(tmp, "In article %s you write:\r\n", msg_id);
  678.             ln = tx->start;
  679.             while (ln != NULL) {
  680.                 fprintf(tmp, "> %s", ln->data);
  681.                 ln = ln->next;
  682.                 }
  683.            }
  684.  
  685.  
  686.         /* append the signature if there is one */
  687.         strcpy(sig_fn, my_stuff.home);
  688.         strcat(sig_fn, my_stuff.signature);
  689.         if ((sig= fopen(sig_fn, "r")) != NULL) {
  690.             fputs("\r\n--\r\n", tmp);
  691.             while (fgets(buf, 79, sig) != NULL)
  692.                 fputs(buf, tmp);
  693.             fclose(sig);
  694.             }
  695.  
  696.         fclose(tmp);
  697.  
  698.         /* trim the editor program name */
  699.         cp = my_stuff.editor;
  700.         while ( *cp <= ' ' ) cp++;
  701.         strcpy( buf, cp );
  702.         cp = buf;
  703.         while ( *cp > ' ' ) cp++;
  704.         *cp = '\0';
  705.         if ( strrchr( buf, '.' ) == NULL )
  706.            strcat( buf, ".exe" );
  707.         new_session( buf, fn, "Edit Reply" );
  708.  
  709.         WinPostMsg( hwndArt, WM_USER, MPFROMLONG( MAIL_VERIFY ),
  710.                              MPFROMP( author ) );
  711.         DosWaitEventSem( work_to_do, -1L );
  712.         DosResetEventSem( work_to_do, &pcnt );
  713.  
  714.         if ( queryans == MBID_YES )
  715.            {
  716.            strcpy(msg_id, artp->header);
  717.            eat_gunk(msg_id);
  718.            sprintf(buf, "mail -s \"Re: %s\" %s <%s 2>nul",
  719.                     msg_id, author, fn);
  720.            system(buf);
  721.            }
  722.         remove(fn);
  723.  
  724.     } else {
  725.         WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  726.         }
  727.  
  728. }
  729.  
  730.  
  731. /*--------------------------- post an article ---------------------------*/
  732. void post_it(FILE *article, char *newsgroups, char *subject, char *dist,
  733.                   char *msg_id)
  734. {
  735.     /*
  736.      *  Post an article.  The article is passed as an open file,
  737.      *  with the other header data.  The header is added to the file
  738.      *  and the article sent.
  739.      */
  740.  
  741.     FILE   *tmp, *local, *log;
  742.     char   buf[256], *p;
  743.     char   ng[256];
  744.     char   d_name[20], x_name[20];
  745.     char   short_d_name[20], short_x_name[20];
  746.     int    ct, seq;
  747.     time_t t;
  748.     struct tm *gmt;
  749.     long   where;
  750.     ACTIVE *gp;
  751.  
  752.     static char *dow[] = {
  753.         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  754.     };
  755.     static char *mth[] = {
  756.         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  757.         "Oct", "Nov", "Dec"
  758.     };
  759.  
  760.     ct = 0;
  761.  
  762.     seq = post_sequence();
  763.     sprintf(d_name, "D.%s%04x", my_stuff.my_site, seq);
  764.     sprintf(x_name, "X.%s%04x", my_stuff.my_site, seq);
  765.  
  766.     sprintf(short_d_name, "D.%.3s", my_stuff.my_site);
  767.     sprintf(short_x_name, "X.%.3s", my_stuff.my_site);
  768.  
  769.     /* count the lines */
  770.     rewind(article);
  771.     while (fgets(buf, 255, article) != NULL)
  772.         ct++;
  773.  
  774.  
  775.     /*
  776.      *  Make the final article file.  This posting stuff is a horrible
  777.      *  kludge (blush).  If you get a around to fixing this, please
  778.      *  post me a copy :)
  779.      */
  780.     if ((tmp = fopen(short_d_name, "w+b")) != NULL) {
  781.  
  782.         fprintf(tmp, "Path: %s!%s\n", my_stuff.my_site, my_stuff.user);
  783.         fprintf(tmp, "From: %s@%s (%s)\n", my_stuff.user, my_stuff.my_domain,
  784.             my_stuff.my_name);
  785.         fprintf(tmp, "Newsgroups: %s\n", newsgroups);
  786.         fprintf(tmp, "Subject: %s\n", subject);
  787.         fprintf(tmp, "Distribution: %s\n", dist);
  788.  
  789.         fprintf(tmp, "Message-ID: <%ldsnx@%s>\n", time(&t), my_stuff.my_domain);
  790.  
  791.         if (strlen(msg_id) > 0)
  792.             fprintf(tmp, "References: %s\n", msg_id);
  793.  
  794.         time(&t);
  795.         gmt = gmtime(&t);
  796.         fprintf(tmp, "Date: %s, %02d %s %02d %02d:%02d:%02d GMT\n",
  797.                 dow[gmt->tm_wday],
  798.                 gmt->tm_mday, mth[gmt->tm_mon], (gmt->tm_year % 100),
  799.                 gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
  800.  
  801.         fprintf(tmp, "Organization: %s\n", my_stuff.my_organisation);
  802.         fprintf(tmp, "Lines: %d\n\n", ct);
  803.  
  804.         /* copy the rest */
  805.         rewind(article);
  806.         while (fgets(buf, 255, article) != NULL) {
  807.             fputs(buf, tmp);
  808.         }
  809.  
  810.         /* ok, now post it locally */
  811.         strcpy(ng, newsgroups);
  812.         p = strtok(ng, " ,");
  813.         while (p != NULL) {
  814.  
  815.             if (fseek(tmp, 0L, SEEK_SET) != 0) {
  816.                 WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  817.                 return;
  818.             }
  819.  
  820.             local = open_out_file(p);
  821.             where = ftell(local);
  822.             while (fgets(buf, 255, tmp) != NULL)  {
  823.                 fputs(buf, local);
  824.             }
  825.             fprintf(local, "\n@@@@END\n");
  826.             fclose(local);
  827.  
  828.             /* save the data in the index file */
  829.             local = open_index_file(p);
  830.             gp = find_news_group(p);
  831.             fprintf(local,"%08ld %08ld %09ld %s\n", where, gp->hi_num, t,
  832.                 subject);
  833.             fclose(local);
  834.  
  835.             p = strtok(NULL, " ,");
  836.         }
  837.  
  838.  
  839.         /* finally log it */
  840.         strcpy(buf, my_stuff.news_dir);
  841.         strcat(buf, "post.log");
  842.         if ((log = fopen(buf, "at")) != NULL) {
  843.             fprintf(log, "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
  844.                          "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\n");
  845.  
  846.             fseek(tmp, 0L, SEEK_SET);
  847.             while (fgets(buf, 255, tmp) != NULL)  {
  848.                fputs(buf, log);
  849.             }
  850.  
  851.             fclose(log);
  852.         }
  853.  
  854.         fclose(tmp);
  855.  
  856.  
  857.         /* now the the X... file */
  858.         if ((tmp = fopen(short_x_name, "wb")) != NULL) {
  859.             fprintf(tmp, "U news %s\n", my_stuff.my_site);
  860.             fprintf(tmp, "Z\n");
  861.             fprintf(tmp, "F %s\n", d_name);
  862.             fprintf(tmp, "I %s\n", d_name);
  863.             fprintf(tmp, "C rnews\n");
  864.             fclose(tmp);
  865.  
  866.             sprintf(buf, "uucp -C %s %s!%s ", short_d_name, my_stuff.mail_server,
  867.                     d_name);
  868.             system(buf);
  869.             sprintf(buf, "uucp -C %s %s!%s ", short_x_name, my_stuff.mail_server,
  870.                     x_name);
  871.             system(buf);
  872.  
  873.         } else {
  874.  
  875.             WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  876.         }
  877.  
  878.         remove(short_d_name);
  879.         remove(short_x_name);
  880.  
  881.     } else {
  882.         WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  883.     }
  884. }
  885.  
  886.  
  887.  
  888. /* quote article to 'post.tmp' file if required, then schedule
  889.    edit of new article and wait for it.
  890.    Then return to mainline for posting query, waiting for answer,
  891.    the post if yes */
  892.  
  893. void post_art( USHORT doquote )
  894.  
  895. {
  896.     FILE *sig;
  897.     char sig_fn[80];
  898.  
  899.     FILE *article;
  900.     aLINE *ln;
  901.     ULONG  pcnt;
  902.     char fn[80];
  903.     char buf[256];
  904.     char subject[256];
  905.     char author[80], msg_id[80];
  906.     char *cp;
  907.  
  908.     strcpy(fn, "post.tmp");
  909.  
  910.     if ((article = fopen(fn, "w")) != NULL)
  911.         {
  912.         get_his_stuff(tx, author, msg_id);
  913.  
  914.         if ( strnicmp(nsubj, "Re: ", 4) != 0 )
  915.            sprintf(subject, "Re: %s", nsubj);
  916.         else
  917.            strcpy(subject, nsubj);
  918.  
  919.         /* add the quoted message if quotans = yes  */
  920.         if ( quotans == MBID_YES )
  921.            {
  922.            fprintf(article, "%s writes in article %s:\n", author, msg_id);
  923.            ln = tx->start;
  924.            while (ln != NULL)
  925.                  {
  926.                  fprintf(article, "> %s", ln->data);
  927.                  ln = ln->next;
  928.                  }
  929.            }
  930.  
  931.         /* append the signature if there is one */
  932.         strcpy(sig_fn, my_stuff.home);
  933.         strcat(sig_fn, my_stuff.signature);
  934.         if ((sig = fopen(sig_fn, "r")) != NULL)
  935.            {
  936.            fputs("\n--\n", article);
  937.            while (fgets(buf, 79, sig) != NULL)
  938.                  fputs(buf, article);
  939.            fclose(sig);
  940.            }
  941.  
  942.         fclose(article);
  943.  
  944.         /* trim the editor program name */
  945.         cp = my_stuff.editor;
  946.         while ( *cp <= ' ' ) cp++;
  947.         strcpy( buf, cp );
  948.         cp = buf;
  949.         while ( *cp > ' ' ) cp++;
  950.         *cp = '\0';
  951.         if ( strrchr( buf, '.' ) == NULL )
  952.            strcat( buf, ".exe" );
  953.  
  954.         new_session( buf, fn, "Edit Reply" );
  955.  
  956.         WinPostMsg( hwndArt, WM_USER, MPFROMLONG( POST_VERIFY ),
  957.                              MPFROMP( NULL ) );
  958.         DosWaitEventSem( work_to_do, -1L );
  959.         DosResetEventSem( work_to_do, &pcnt );
  960.  
  961.         if ( queryans == MBID_YES )
  962.            {
  963.            article = fopen("post.tmp", "r");
  964.            post_it( article, ngroup, subject, "world", msg_id );
  965.            fclose( article );
  966.            }
  967.  
  968.         remove(fn);
  969.  
  970.         }
  971.     else
  972.         WinPostMsg( hwndArt, WM_USER, (MPARAM) MAIL_FILERR, (MPARAM) 0L );
  973. }
  974.  
  975. /* search the given news group for the specified string.
  976.    Return an article header with a chain of ART_IDs
  977.    linked from it, if the string is found, else return
  978.    null */
  979.  
  980. ARTICLE *search_group( ACTIVE *gp, char *srcharg )
  981. {
  982. /* open the index and data files for the group */
  983. /* search each article for the requested string,
  984.    building a linked list of containing articles */
  985.  
  986.   ARTICLE *thrd, *head, *outp, *tmph, *lasth;
  987.   ART_ID  *tmpd, *tmpa, *lasta, *new;
  988.   BOOL     build_art;
  989.  
  990.   char    *fn;
  991.   TEXT    *tmpt;
  992.   aLINE   *lp;
  993.   int      ln, nart, topic;
  994.  
  995.   fn   = make_news_group_name( gp->group );
  996.   head = thrd = get_headers( gp );
  997.   tmpa = lasta = NULL;  /* list of articles where string found */
  998.   outp = lasth = NULL;          /* final article list */
  999.   nart = 0;
  1000.   topic = 0;
  1001.  
  1002.   while ( thrd != NULL )
  1003.      {
  1004.      build_art = FALSE;
  1005.      tmpd = thrd->art_num;
  1006.      while ( tmpd != NULL )
  1007.        {
  1008.        tmpt = load_article( fn, tmpd->art_off );
  1009.  
  1010.        /* search the loaded lines for arg string */
  1011.        lp = tmpt->start;
  1012.        ln = strlen( srcharg );
  1013.        while ( lp != NULL )
  1014.          {
  1015.          if ( strlen( lp->data ) >= ln )
  1016.             {
  1017.             if ( strstr( lp->data, srcharg ) != NULL )
  1018.                break;
  1019.             }
  1020.          lp = lp->next;
  1021.          }
  1022.  
  1023.        free_article( tmpt );
  1024.        if ( lp != NULL )
  1025.           {  /* put a copy ART_ID on our output list */
  1026.           new = xmalloc( sizeof(ART_ID) );
  1027.           new->id = tmpd->id;
  1028.           new->art_off = tmpd->art_off;
  1029.           build_art = TRUE;
  1030.           nart++;
  1031.           if ( tmpa == NULL )
  1032.              {
  1033.              tmpa = lasta = new;
  1034.              new->next_art = new->last_art = NULL;
  1035.              }
  1036.           else
  1037.              {
  1038.              lasta->next_art = new;
  1039.              new->last_art = lasta;
  1040.              new->next_art = NULL;
  1041.              lasta = new;
  1042.              }
  1043.           }
  1044.  
  1045.        tmpd = tmpd->next_art;
  1046.        }
  1047.  
  1048.      if ( build_art )
  1049.         {
  1050.         /* build an ARTICLE struct */
  1051.         tmph = xmalloc( sizeof(ARTICLE) );
  1052.         tmph->num_articles = nart;
  1053.         tmph->index = ++topic;
  1054.         tmph->art_num = tmpa;
  1055.         tmpa = lasta = NULL;  /* reset art_id list  */
  1056.         nart = 0;             /* and art_id count */
  1057.  
  1058.         /* copy the header (subject) */
  1059.         tmph->header = xmalloc( strlen( thrd->header ) + 1 );
  1060.         strcpy( tmph->header, thrd->header );
  1061.  
  1062.         if ( outp == NULL )
  1063.            {
  1064.            outp = lasth = tmph;
  1065.            tmph->next = tmph->last = NULL;
  1066.            }
  1067.         else
  1068.            {
  1069.            lasth->next = tmph;
  1070.            tmph->last = lasth;
  1071.            tmph->next = NULL;
  1072.            lasth = tmph;
  1073.            }
  1074.  
  1075.         }
  1076.  
  1077.      thrd = thrd->next;
  1078.      }
  1079.  
  1080.   free_header( head );
  1081.  
  1082.   return outp;
  1083. }
  1084.