home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / DWNSRS56.ZIP / DOWNRPT2.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-10  |  20.3 KB  |  509 lines

  1. /* ================================================================ */
  2. /*  Rob Hamerling's MAXIMUS download file scan and sort utility     */
  3. /*  -> DOWNRPT2.C                                                   */
  4. /*  -> Make all types of IPF-lists.                                 */
  5. /* ================================================================ */
  6.  
  7. #define INCL_BASE
  8. #include <os2.h>
  9.  
  10. #include <conio.h>
  11. #include <malloc.h>
  12. #include <memory.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16.  
  17. #include "..\max\mstruct.h"
  18. #include "downsort.h"
  19. #include "downfpro.h"
  20.  
  21. /* IPF-tags */
  22. static char  AW[]   = ":artwork align=center name='DOWNSORT.BMP'.";
  23. static char  CD[]   = ":color fc=default.";
  24. static char  CG[]   = ":cgraphic.";
  25. static char  CR[]   = ":color fc=red.";
  26. static char  CY[]   = ":color fc=yellow.";
  27. static char  DP[]   = ":docprof toc='*3'.";
  28. static char  ED[]   = ":euserdoc.\n";
  29. static char  EG[]   = ":ecgraphic.";
  30. static char  EL[]   = ":elines.\n";
  31. static char  ET[]   = ":etable.\n";
  32. static char  H1[]   = ":h1.";
  33. static char  H2[]   = ":h2";
  34. static char  H3[]   = ":h3";
  35. static char  OV[]   = "Overview";
  36. static char  LI[]   = ":lines align=center.";
  37. static char  LL[]   = ":lines align=left.";
  38. static char  LP[]   = ":lp.";
  39. static char  TB[]   = ":table cols='12 15 38' frame=box rules=both.\n";
  40. static char  TI[]   = ":title.";
  41. static char  UD[]   = ":userdoc.";
  42.  
  43. /* prototypes of local functions */
  44.  
  45. void ipf_list_head(FILE *, struct  _filechain **,
  46.                    struct  _downpath huge *, unsigned int, unsigned int);
  47. void ipf_area_oview(FILE *,
  48.                    struct  _downpath huge *, unsigned int, unsigned int);
  49. void ipf_area_head(FILE *, struct  _filechain **,
  50.                    unsigned int, unsigned int);
  51. int  ipf_file_entry(FILE *, struct  _filechain **,
  52.                     unsigned int, unsigned int);
  53. int  ip2_file_entry(FILE *, struct  _filechain **,
  54.                     unsigned int, unsigned int);
  55.  
  56.  
  57. /* ------------------------------------------------------- */
  58. /* Produce the file-request format of IPFfiles  (IPF-list) */
  59. /* ------------------------------------------------------- */
  60. void make_ipf(struct  _filechain **dm,
  61.               struct  _downpath huge *area,
  62.               unsigned int  x)
  63. {
  64.   FILE   *pf;                           // file handle
  65.   char   outfile[MAXFN];                // file names
  66.   char   ac[40];                        // area name
  67.   unsigned int i,l,pcnt,n,pmax;         // counters
  68.  
  69.   sprintf(outfile,"%s.%s%c",
  70.           lp[P_IPF].name,
  71.           lp[P_IPF].ext,
  72.           priv_name[lp[P_IPF].priv[x]-TWIT][0]);
  73.   pf = fopen(outfile,WRITE);              // output file
  74.   if (pf != NULL) {
  75.     if (oper_mode == VERBOSE)
  76.       printf(MSG_SRT,file_total_count,area_total_count,outfile);
  77.     ipf_list_head(pf, dm, area, P_IPF, x); // sort + list header
  78.     if (oper_mode!=QUIET)
  79.       printf(MSG_REP, outfile);
  80.     ipf_area_oview(pf, area, P_IPF, x); // create area overview
  81.     if (oper_mode==VERBOSE)             // keep operator awake
  82.       printf(MSG_REC,outfile);
  83.  
  84.     fprintf(pf,"%s%s\n",H1,"File List per Area");
  85.     fprintf(pf,"%s\n%s :hp8.%c:ehp8.%s, :hp8.%c:ehp8.%s\n%s\n",
  86.                LI, DF, DAYS_7, WK, DAYS_30, MO, EL);
  87.     ac[0] = '\0';                       // null area name
  88.     l=n=0;                              // init file counters
  89.     for (i=0; i<file_total_count; i++) {    // all files
  90.       if (strcmp(ac, dm[i]->parea->name)) { // new area collection
  91.         strcpy(ac, dm[i]->parea->name);   // set new
  92.         if (dm[i]->parea->file_count > 0) { // any files in this area
  93.           if (l>0)                      // have to close open list?
  94.             fprintf(pf,":edl.\n");      // close previous area-list
  95.           ipf_area_head(pf, dm, P_IPF, i); // create area header
  96.           pcnt = l = 0;                 // sub-counters this area
  97.           }
  98.         }
  99.       if (dm[i]->priv <= lp[P_IPF].priv[x]) {   // only upto max priv_level
  100.         pmax = 1 + dm[i]->parea->file_count/lp[P_IPF].max_fil;
  101.         if ((l % lp[P_IPF].max_fil) == 0) {   // 'page' separations
  102.           if (l == 0) {                 // only for first entry
  103.             if (dm[i]->parea->file_count > lp[P_IPF].max_fil)  // split
  104.               fprintf(pf,":p.(part %d of %d)\n", ++pcnt, pmax);
  105.             }
  106.           else {                        // only part 2 and up
  107.             fprintf(pf,":edl.\n");      // end of previous part
  108.             ++pcnt;                     // increment part counter
  109.             fprintf(pf,":p.Jump to: :link reftype=hd refid=%.8sP%d.\n"
  110.                        "part %d of %d:elink.",
  111.                        dm[i]->parea->name, pcnt, pcnt, pmax);
  112.             fprintf(pf,"\n%s id=%.8sP%d.%s - (part %d of %d)\n",
  113.                        H3, dm[i]->parea->name, pcnt, ac, pcnt, pmax);
  114.             fprintf(pf,":p.%s (part %d of %d)\n",
  115.                        stripf(dm[i]->parea->adesc), pcnt, pmax);
  116.             }
  117.           fprintf(pf,":dl tsize=20 compact.\n");
  118.           fprintf(pf,":hp6.:dthd.%s:ddhd.%s:ehp6.\n",FN,DS);
  119.           }
  120.         ++l;                            // listed lines (incl comments)
  121.         n += ipf_file_entry(pf, dm, P_IPF, i); // print entry
  122.         if (dm[i]->fname[0] != '\0')    // filename present
  123.           if (oper_mode==VERBOSE && (n%25)==0)
  124.             cprintf("\r %5u",n);        // report progress
  125.         }
  126.       }
  127.     fprintf(pf,":edl.\n");              // end of file-list last area
  128.     if (oper_mode==VERBOSE)             // last value
  129.       printf("\r %5u",n);
  130.     fprintf(pf,"%s%s\n%s\n\n",H1,"Epilog",LI);
  131.     signature(pf,stripf(today));        // leave fingerprint
  132.     insert_title(pf, bot_lines, 1);
  133.     fprintf(pf,"%s%s",EL,ED);
  134.     stripf(NULL);                       // let stripf free memory
  135.     fclose(pf);                         // finished with .IPF file
  136.     }
  137.   else {
  138.     if (oper_mode!=QUIET)
  139.       printf(OPEN_FAIL, outfile, 0);    // open failed
  140.     }
  141.   }
  142.  
  143. /* ------------------------------------------------------- */
  144. /* Produce the file-request format of IP2-files (IPF-list) */
  145. /* ------------------------------------------------------- */
  146. void make_ip2(struct  _filechain **dm,
  147.               struct  _downpath huge *area,
  148.               unsigned int  x)
  149. {
  150.   FILE   *pf;                           // file handle
  151.   char   outfile[MAXFN];                // file names
  152.   char   ac[40];                        // area name
  153.   unsigned int i,l,pcnt,n,pmax;         // counters
  154.  
  155.   sprintf(outfile,"%s.%s%c",
  156.           lp[P_IP2].name,
  157.           lp[P_IP2].ext,
  158.           priv_name[lp[P_IP2].priv[x]-TWIT][0]);
  159.   pf = fopen(outfile,WRITE);              // output file
  160.   if (pf != NULL) {
  161.     if (oper_mode == VERBOSE)
  162.       printf(MSG_SRT,file_total_count,area_total_count,outfile);
  163.     ipf_list_head(pf, dm, area, P_IP2, x); // sort + list header
  164.     if (oper_mode!=QUIET)
  165.       printf(MSG_REP, outfile);
  166.     ipf_area_oview(pf, area, P_IP2, x); // create area overview
  167.     if (oper_mode==VERBOSE)             // keep operator awake
  168.       printf(MSG_REC,outfile);
  169.  
  170.     fprintf(pf,"%s%s\n",H1,"File List per Area");
  171.     fprintf(pf,"%s\n%s :hp8.%c:ehp8.%s, :hp8.%c:ehp8.%s\n%s\n",
  172.                LI, DF, DAYS_7, WK, DAYS_30, MO, EL);
  173.     ac[0] = '\0';                       // null area name
  174.     l=n=0;                              // init file counters
  175.     for (i=0; i<file_total_count; i++) {    // all files
  176.       if (strcmp(ac, dm[i]->parea->name)) { // new area collection
  177.         strcpy(ac, dm[i]->parea->name);   // set new
  178.         if (dm[i]->parea->file_count > 0) { // any files in this area
  179.           if (l>0)                      // have to close open list?
  180.             fprintf(pf,ET);             // close previous table
  181.           ipf_area_head(pf, dm, P_IP2, i); // create area header
  182.           pcnt = l = 0;                 // sub-counters this area
  183.           }
  184.         }
  185.       if (dm[i]->priv <= lp[P_IP2].priv[x]) {   // only upto max priv_level
  186.         pmax = 1 + dm[i]->parea->file_count/lp[P_IP2].max_fil;
  187.         if ((l % lp[P_IP2].max_fil) == 0) {   // 'page' separations
  188.           if (l == 0) {                 // only for first entry
  189.             if (dm[i]->parea->file_count > lp[P_IP2].max_fil)  // split
  190.               fprintf(pf,":p.(part %d of %d)\n", ++pcnt, pmax);
  191.             }
  192.           else {                        // only part 2 and up
  193.             fprintf(pf,ET);             // end of previous table
  194.             ++pcnt;                     // increment part counter
  195.             fprintf(pf,":p.Jump to: :link reftype=hd refid=%.8sP%d.\n"
  196.                        "part %d of %d:elink.",
  197.                        dm[i]->parea->name, pcnt, pcnt, pmax);
  198.             fprintf(pf,"\n%s id=%.8sP%d.%s - (part %d of %d)\n",
  199.                        H3, dm[i]->parea->name, pcnt, ac, pcnt, pmax);
  200.             fprintf(pf,":p.%s (part %d of %d)\n",
  201.                        stripf(dm[i]->parea->adesc), pcnt, pmax);
  202.             }
  203. //        fprintf(pf,":font facename=Helv size=10x8.\n");
  204.           fprintf(pf,TB);
  205.           }
  206.         ++l;                            // listed lines (incl comments)
  207.         n += ip2_file_entry(pf, dm, P_IP2, i); // print entry
  208.         if (dm[i]->fname[0] != '\0')    // filename present
  209.           if (oper_mode==VERBOSE && (n%25)==0)
  210.             cprintf("\r %5u",n);        // report progress
  211.         }
  212.       }
  213.     fprintf(pf,ET);                     // end of table this area
  214.     if (oper_mode==VERBOSE)             // last value
  215.       printf("\r %5u",n);
  216.     fprintf(pf,"%s%s\n%s\n\n",H1,"Epilog",LI);
  217.     signature(pf,stripf(today));        // leave fingerprint
  218.     insert_title(pf, bot_lines, 1);
  219.     fprintf(pf,"%s%s",EL,ED);
  220.     stripf(NULL);                       // let stripf free memory
  221.     fclose(pf);                         // finished with .IPF file
  222.     }
  223.   else {
  224.     if (oper_mode!=QUIET)
  225.       printf(OPEN_FAIL, outfile, 0);    // open failed
  226.     }
  227.   }
  228.  
  229. /* ------------------------ */
  230. /* generate IPF list header */
  231. /* ------------------------ */
  232. void ipf_list_head(FILE *pf,
  233.                    struct _filechain **dm,
  234.                    struct _downpath huge *area,
  235.                    unsigned int P_ppp,
  236.                    unsigned int x)
  237. {
  238.   char   s[MAXDESC];                    // work buffer
  239.  
  240.   switch(lp[P_ppp].sortflag) {
  241.     case ALPHA:     psort(dm,0,file_total_count-1,sort_all); break;
  242.     case TIMESTAMP: psort(dm,0,file_total_count-1,sort_al2); break;
  243.     case KEEPSEQ:   psort(dm,0,file_total_count-1,sort_akp); break;
  244.     default: break;
  245.     }
  246.   preproc_area(area, dm, lp[P_ppp].priv[x]);
  247.   fprintf(pf,"%s\n%s%s\n%s\n",UD,TI,stripf(list_title),DP);
  248.   fprintf(pf,"%s%s\n%s\n",H1,stripf(list_title),LI);
  249.   insert_title(pf, pre_title, 1);
  250.   fprintf(pf,"%s%s\n%s\n",EL,CG,CR);
  251.   block_title(pf, 20, list_title, P_ppp),
  252.   fprintf(pf,"%s\n%s\n",CD,EG);
  253.   file_incl(pf, P_ppp);             // insert user-'logo'
  254.   fprintf(pf,"%s\n",LI);
  255.   insert_title(pf, sub_title, 1);
  256.   fprintf(pf,"%s%s%s%s%s\n",EL,H1,"About ",PROGNAME," program");
  257.   fprintf(pf,"\n%s\n",AW);
  258.   fprintf(pf,"\n%s\n%s  Version %c.%c%c\n",
  259.                    LI,PROGNAME,VERSION,SUBVERS,SUFFIX);
  260.   fprintf(pf,"\nby %s\n\n%s\n",AUTHOR, CITY);
  261.   sprintf(s,"\n%s\n%s\n",PHONE,FIDO);
  262.   fprintf(pf,"%s\n",stripf(s));
  263.   fprintf(pf,"%s",EL);
  264.   }
  265.  
  266. /* ------------------------------- */
  267. /* generate IPF list area overview */
  268. /* ------------------------------- */
  269. void ipf_area_oview(FILE *pf,
  270.                    struct  _downpath huge *area,
  271.                    unsigned int  P_ppp,
  272.                    unsigned int  x)
  273. {
  274.   char   s[MAXDESC];                    // pointer to line buffer
  275.   unsigned int j;                       // counter
  276.   struct _downpath huge *area2;         // copy of area-array for sort
  277.  
  278.   if (oper_mode==VERBOSE)
  279.     printf(MSG_REP, OV);
  280. #ifndef __32BIT__
  281.   area2 = (struct _downpath *)halloc(area_total_count,
  282.                                      sizeof(struct _downpath));
  283. #else
  284.   area2 = (struct _downpath *)malloc(area_total_count *
  285.                                      sizeof(struct _downpath));
  286. #endif
  287.                                         // dup area-array for sorting!
  288.   if (area2 == NULL) {                  // memory not obtained?
  289.     if (oper_mode!=QUIET)
  290.       printf("\nNot enough memory for summary report, skipped.");
  291.     }
  292.   else {
  293.     memmove(area2,area,area_total_count*sizeof(struct _downpath));
  294.     qsort(area2,area_total_count,sizeof(struct _downpath),sort_summ);
  295.     fprintf(pf,"%s%s\n",H1,OV);
  296.     fprintf(pf,"%s\n%s\n",CG,CR);
  297.     block_title(pf, 8, OV, P_ppp);
  298.     fprintf(pf,"%s\n%s\n",CD,EG);
  299.     fprintf(pf,"%s\nlist creation date: %s\n",
  300.                 LI,stripf(sys_date(today)));
  301.     if (lp[P_ppp].exclflag != EXCLPRIV)
  302.       fprintf(pf,"%s%s\n", MP, priv_name[lp[P_ppp].priv[x]-TWIT]);
  303.     fprintf(pf,"%s%s\n:hp2.\n%s %-39s %5s %8s\n",EL,CG,AC,DS,FS,BY);
  304.     sep_line(pf, '─', 44, 5, 9, 0);
  305.     for (j=0; j<area_total_count; j++) {
  306.       if (area2[j].file_count) {
  307.         fprintf(pf,":link reftype=hd refid=A$%.8s.%-8.8s:elink.",
  308.                    area2[j].name,
  309.                    area2[j].name);
  310.         sprintf(s," %-35.35s %5u %8luK",
  311.                    area2[j].adesc,
  312.                    area2[j].file_count,
  313.                    (area2[j].byte_count+512)/1024);
  314.         fprintf(pf,"%s\n",stripf(s));
  315.         }
  316.       }
  317.     sep_line(pf, '─', 44, 5, 9, 0);
  318.     fprintf(pf,"%44s %5u %8luK\n:ehp2.\n%s\n",
  319.                "Total:",
  320.                count_files(area2),
  321.                (count_bytes(area2)+512)/1024,
  322.                EG);
  323. #ifndef __32BIT__
  324.     hfree(area2);                       // free copy of area array
  325. #else
  326.     free(area2);                        // free copy of area array
  327. #endif
  328.     }
  329.   }
  330.  
  331.  
  332. /* ------------------------- */
  333. /* generate IPF area heading */
  334. /* ------------------------- */
  335. void ipf_area_head(FILE *pf,
  336.                    struct  _filechain **dm,
  337.                    unsigned int  P_ppp,
  338.                    unsigned int  i)
  339. {
  340.   fprintf(pf,":p.Continue with filearea"
  341.           ":link reftype=hd refid=A$%.8s. %s :elink.&colon. ",
  342.            dm[i]->parea->name,
  343.            dm[i]->parea->name);
  344.   fprintf(pf,"%-45.45s\n", stripf(dm[i]->parea->adesc));
  345.   fprintf(pf,"%s id=A$%.8s.%s - %s\n%s\n",
  346.           H2,
  347.           dm[i]->parea->name,
  348.           dm[i]->parea->name,
  349.           stripf(dm[i]->parea->adesc),CG);
  350.   if (max_aname <= 3) {                 /* short areanames */
  351.     fprintf(pf,"%s%s%s ║ :hp2.%s:ehp2.\n",
  352.             CR,
  353.             strnblk(dm[i]->parea->name,3,FONT3,LINE1),
  354.             CD,
  355.             stripf(dm[i]->parea->adesc));
  356.     fprintf(pf,"%s%s%s ║ :hp2.Available: "
  357.             "%u files (%lu.%lu MB):ehp2.\n",
  358.              CR, strnblk(dm[i]->parea->name,3,FONT3,LINE2), CD,
  359.              dm[i]->parea->file_count,
  360.              (dm[i]->parea->byte_count+52428L)/1048576L,  // round
  361.              ((dm[i]->parea->byte_count+52429L)/104857L)%10); // fract
  362.     fprintf(pf,"%s%s%s ║",CR,strnblk(dm[i]->parea->name,3,FONT3,LINE3),CD);
  363.     if (lp[P_ppp].exclflag != EXCLPRIV)
  364.       fprintf(pf," :hp2.Privilege: %-.9s:ehp2.\n",
  365.                   priv_name[dm[i]->parea->priv-TWIT]);  // area priv
  366.     else
  367.       fprintf(pf,"\n");
  368.     fprintf(pf,"%s%s%s ║",CR,strnblk(dm[i]->parea->name,3,FONT3,LINE4),CD);
  369.     }
  370.   else {                                /* long areanames */
  371.     fprintf(pf,"%s\n", CR);
  372.     fprintf(pf,"%s\n", strnblk(dm[i]->parea->name,8,FONT3,LINE1));
  373.     fprintf(pf,"%s\n", strnblk(dm[i]->parea->name,8,FONT3,LINE2));
  374.     fprintf(pf,"%s\n", strnblk(dm[i]->parea->name,8,FONT3,LINE3));
  375.     fprintf(pf,"%s\n", strnblk(dm[i]->parea->name,8,FONT3,LINE4));
  376.     fprintf(pf,"%s\n\n", CD);
  377.     fprintf(pf," :hp2.%s:ehp2.\n", stripf(dm[i]->parea->adesc));
  378.     fprintf(pf," :hp2.Available: %u files (%lu.%lu MB):ehp2.\n",
  379.              dm[i]->parea->file_count,
  380.              (dm[i]->parea->byte_count+52428L)/1048576L,      // MB
  381.              ((dm[i]->parea->byte_count+52429L)/104857L)%10); // fract
  382.     if (lp[P_ppp].exclflag != EXCLPRIV)
  383.       fprintf(pf," :hp2.Privilege: %-.9s:ehp2.\n",
  384.                   priv_name[dm[i]->parea->priv-TWIT]);  // area priv
  385.     }
  386.   if (dm[i]->parea->newest != NULL) {   // newest file
  387.     fprintf(pf," :hp2.Newest:");
  388.     fprintf(pf," %s",stripf(dm[i]->parea->newest->fname));
  389.     fprintf(pf," %s",stripf(f_date(dm[i]->parea->newest->wdate)));
  390.     fprintf(pf," (avail: %s):ehp2.\n",
  391.                 stripf(f_date(dm[i]->parea->newest->cdate)));
  392.     }
  393.   fprintf(pf,"%s\n",EG);
  394.   }
  395.  
  396. /* ----------------------- */
  397. /* generate IPF file entry */
  398. /* ----------------------- */
  399. int  ipf_file_entry(FILE *pf,
  400.                    struct  _filechain **dm,
  401.                    unsigned int  P_ppp,
  402.                    unsigned int  i)
  403. {
  404.   int rc;
  405.   char ageflag, *strptr;
  406.   unsigned int k;                       // counter
  407.  
  408.   rc = 0;
  409.   if (dm[i]->fname[0] != '\0') {        // filename present
  410.     fprintf(pf,":dt.:link refid=F$%u reftype=fn.%-s:elink.",
  411.                i, stripf(dm[i]->fname));        // filename
  412.     ageflag = file_age_ind(dm[i]->cdate,dm[i]->ctime); // file age flag
  413.     if (ageflag!=' ')
  414.       fprintf(pf,":hp8.%c:ehp8.", ageflag);
  415.     fprintf(pf,"\n:dd.");
  416.     k = strsubw(dm[i]->fdesc,&strptr,240);
  417.     if (k>0)
  418.       fprintf(pf, (dm[i]->size) ? "%s\n" : ":hp1.%s:ehp1.\n",
  419.            stripf(strptr));             // description
  420.     fprintf(pf,":fn id=F$%u.%s:efn.\n",
  421.            i,                           // file number
  422.            f_size_date(dm[i]->size,
  423.            dm[i]->wdate,
  424.            dm[i]->cdate,
  425.            dm[i]->ctime));
  426.     rc = 1;                             // file entry printed
  427.     }
  428.   else if(lp[P_ppp].sortflag == KEEPSEQ)  // '/K' specified
  429.     fprintf(pf,"%s%s%-s%s%s",
  430.             LL, CY,
  431.             (strip_ava == 'Y') ? strava(dm[i]->fdesc) : dm[i]->fdesc,
  432.             CD, EL);
  433.   return(rc);                           // report result
  434.   }
  435.  
  436.  
  437. /* ----------------------- */
  438. /* generate IPF file entry */
  439. /* ----------------------- */
  440. int  ip2_file_entry(FILE *pf,
  441.                    struct  _filechain **dm,
  442.                    unsigned int  P_ppp,
  443.                    unsigned int  i)
  444. {
  445.   int rc;
  446.  
  447.   rc = 0;
  448.   if (dm[i]->fname[0] != '\0') {        // filename present
  449.     fprintf(pf,":row.:c.%s:c.%s",
  450.            stripf(dm[i]->fname),        // filename
  451.            f_size_date(dm[i]->size, dm[i]->wdate,
  452.                        dm[i]->cdate, dm[i]->ctime));
  453.     fprintf(pf, (dm[i]->size) ? ":c.%s\n" : ":c.:hp1.%s:ehp1.\n",
  454.            stripf(dm[i]->fdesc));       // description
  455.     rc = 1;                             // file entry printed
  456.     }
  457.   else if(lp[P_ppp].sortflag == KEEPSEQ)  // '/K' specified
  458.     fprintf(pf,"%s%s%-s%s%s",
  459.             LL, CY,
  460.             (strip_ava == 'Y') ? strava(dm[i]->fdesc) : dm[i]->fdesc,
  461.             CD, EL);
  462.   return(rc);                           // report result
  463.   }
  464.  
  465. /* ---------------------------------------------------- */
  466. /* function to 'neutralise' IPFC conflicting characters */
  467. /* ---------------------------------------------------- */
  468. char *stripf(char *s)
  469. {
  470.   int i,j,k;
  471.  
  472.   static char colon[] = "&colon.";
  473.   static char amp[]   = "&.";
  474.   static char grave[] = "&rbl.";        // translated to required BLANK
  475.   static int  maxline = MAXDESC;        // length of work-buffer
  476.   static char *t = NULL;                // pointer to work-buffer
  477.  
  478.   if (s == NULL && t != NULL) {         // no input-string
  479.     free(t);                            // free-up memory
  480.     t = NULL;                           // for next time use
  481.     return(s);
  482.     }
  483.  
  484.   if (t == NULL)                        // no memory yet
  485.     t = malloc(maxline);                // get it now
  486.  
  487.   if (t != NULL) {
  488.     for (i=j=0; s[i] && j<maxline-10; ++i) { // keep some slack
  489.       switch(s[i]) {
  490.         case ':': for (k=0;  colon[k]; )
  491.                     t[j++] = colon[k++];
  492.                   break;
  493.         case '`': for (k=0;  grave[k]; )
  494.                     t[j++] = grave[k++];
  495.                   break;
  496.         case '&': for (k=0;  amp[k]; )
  497.                     t[j++] = amp[k++];
  498.                   break;
  499.         default:  t[j++] = s[i];
  500.                   break;
  501.         }
  502.       }
  503.     t[j] = '\0';                        // end of string
  504.     return(t);                          // pointer to converted line
  505.     }
  506.   else
  507.     return(s);                          // no conversion done
  508.   }
  509.