home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / com / bbs / downsrt / source / downrpt2.c < prev    next >
C/C++ Source or Header  |  1991-06-19  |  24KB  |  517 lines

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