home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / hyprmail.zip / print.c < prev    next >
Text File  |  1997-03-16  |  25KB  |  921 lines

  1. /*
  2. ** Copyright (C) 1994, Enterprise Integration Technologies Corp.        
  3. ** All Rights Reserved.
  4. ** Kevin Hughes, kevinh@eit.com 
  5. ** 7/31/94
  6. */
  7.  
  8. #include "hypermail.h"
  9. #include "print.h"
  10.  
  11. /* Printing...the other main part of this program!
  12. ** This writes out the articles, beginning with the number startnum.
  13. */
  14.  
  15. void writearticles(dir, label, overwrite, startnum)
  16.      char *dir;
  17.      char *label;
  18.      int overwrite;
  19.      int startnum;
  20. {
  21.     int num, tmpnum, statusnum, skip, subjmatch, newfile;
  22.     char name[NAMESTRLEN], email[MAILSTRLEN], subject[SUBJSTRLEN],
  23.         inreply[REPYSTRLEN], date[DATESTRLEN], fromdate[DATESTRLEN],
  24.         msgid[MSGDSTRLEN];
  25.     char currentemail[MAILSTRLEN], currentid[MSGDSTRLEN],
  26.         currentsubject[SUBJSTRLEN];
  27.     char name2[NAMESTRLEN], email2[MAILSTRLEN], subject2[SUBJSTRLEN],
  28.         inreply2[REPYSTRLEN], date2[DATESTRLEN], fromdate2[DATESTRLEN],
  29.         msgid2[MSGDSTRLEN];
  30.     char filename[MAXFILELEN];
  31.     struct body *bp, *status;
  32.     struct reply *rp;
  33.     FILE *fp;
  34.  
  35.     num = startnum;
  36.     skip = 0;
  37.  
  38.     if (showprogress)
  39.         printf("Writing articles to \"%s\"...    ", dir);
  40.  
  41.     while ((bp = (struct body *) hashnumlookup(num, name, email,
  42.     subject, inreply, date, fromdate, msgid)) != NULL) {
  43.  
  44.         strcpy(currentemail, email);
  45.         strcpy(currentid, msgid);
  46.         strcpy(currentsubject, subject);
  47.  
  48.         sprintf(filename, "%s%s%.4d.html", dir,
  49.         (dir[strlen(dir) - 1] == '/') ? "" : "/", num);
  50.  
  51. /* Determine to overwrite files or not
  52. */
  53.         if (isfile(filename))
  54.             newfile = 0;
  55.         else
  56.             newfile = 1;
  57.  
  58.         if (!newfile && !overwrite) {
  59.             skip = 1;
  60.             num++;
  61.             continue;
  62.         }
  63.         else {
  64.             if ((fp = fopen(filename, "w")) == NULL) {
  65.                 sprintf(errmsg, "Couldn't write \"%s\".",
  66.                 filename);
  67.                 progerr(NULL);
  68.             }
  69.         }
  70.  
  71. /* Create the comment fields necessary for incremental updating
  72. */
  73.  
  74.         printcomment(fp, "received", fromdate);
  75.         printcomment(fp, "sent", date);
  76.         printcomment(fp, "name", name);
  77.         printcomment(fp, "email", email);
  78.         printcomment(fp, "subject", convchars(subject));
  79.         printcomment(fp, "id", msgid);
  80.         printcomment(fp, "inreplyto", convchars(inreply));
  81.  
  82.         fprintf(fp, "<title>%s: %s</title>\n", label,
  83.         convchars(subject));
  84.         fprintf(fp, "<h1>%s</h1>\n", convchars(subject));
  85.         if (!strcmp(name, email)) {
  86. #ifdef MAILCOMMAND
  87.             fprintf(fp, "<a href=\"%s\">",
  88.             makemailcommand(MAILCOMMAND, email, currentid,
  89.             currentsubject));
  90.             fprintf(fp, "<i>%s</i></a><br>\n", name);
  91. #else
  92.             fprintf(fp, "<i>%s</i><br>\n", name);
  93. #endif
  94.         }
  95.         else {
  96. #ifdef MAILCOMMAND
  97.             fprintf(fp, "<b>%s</b> (<a href=\"%s\">", name,
  98.             makemailcommand(MAILCOMMAND, email, currentid,
  99.             currentsubject));
  100.             fprintf(fp, "<i>%s</i></a>)<br>\n", email);
  101. #else
  102.             fprintf(fp, "%s (<i>%s</i>)<br>\n", name, email);
  103. #endif
  104.         }
  105.         fprintf(fp, "<i>%s</i>\n<p>\n", date);
  106.  
  107.         fprintf(fp, "<ul>\n");
  108.  
  109.         fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  110.         fprintf(fp, "<a href=\"%s#%d\">[ date ]</a>", datename, num);
  111.         fprintf(fp, "<a href=\"%s#%d\">[ thread ]</a>", thrdname, num);
  112.         fprintf(fp, "<a href=\"%s#%d\">[ subject ]</a>", subjname, num);
  113.         fprintf(fp, "<a href=\"%s#%d\">[ author ]</a>\n", authname,
  114.         num);
  115.  
  116.         printcomment(fp, "next", "start");
  117.  
  118. /* Is there a next message?
  119. */
  120.  
  121.         status = (struct body *) hashnumlookup(num + 1, name2,
  122.         email2, subject2, inreply2, date2, fromdate2, msgid2);
  123.         if (status != NULL) {
  124.             fprintf(fp, "<li> <b>Next message:</b> ");
  125.             fprintf(fp, "<a href=\"%.4d.html\">%s: \"%s\"</a>\n",
  126.             num + 1, name2, convchars(subject2));
  127.         }
  128.  
  129. /* Is there a previous message?
  130. */
  131.  
  132.         status = (struct body *) hashnumlookup(num - 1, name2,
  133.         email2, subject2, inreply2, date2, fromdate2, msgid2);
  134.         if (status != NULL) {
  135.             fprintf(fp, "<li> <b>Previous message:</b> ");
  136.             fprintf(fp, "<a href=\"%.4d.html\">%s: \"%s\"</a>\n",
  137.             num - 1, name2, convchars(subject2));
  138.         }
  139.  
  140. /* Is this message a reply to another?
  141. */
  142.  
  143.         if (inreply[0] != '\0') {
  144.             statusnum = hashreplylookup(inreply, name, subject,
  145.             &subjmatch);
  146.             if (statusnum != -1) {
  147.                 if (subjmatch)
  148.                     fprintf(fp,
  149.                     "<li> <b>Maybe in reply to:</b>");
  150.                 else
  151.                     fprintf(fp,
  152.                     "<li> <b>In reply to:</b>");
  153.                 fprintf(fp, " <a href=\"%.4d.html\">",
  154.                 statusnum);
  155.                 fprintf(fp, "%s: \"%s\"</a>\n",
  156.                 name, convchars(subject));
  157.             }
  158.         }
  159.  
  160. /* Is there a message next in the thread?
  161. */
  162.  
  163.         printcomment(fp, "nextthread", "start");
  164.  
  165.         for (rp = threadlist; rp != NULL; rp = rp->next)
  166.             if (rp->msgnum == num && rp->next != NULL &&
  167.             rp->next->msgnum != -1) {
  168.                 fprintf(fp, "<li> <b>Next in thread:</b> ");
  169.                 fprintf(fp, "<a href=\"%.4d.html\">",
  170.                 rp->next->msgnum);
  171.                 fprintf(fp, "%s: \"%s\"</a>\n",
  172.                 rp->next->name, convchars(rp->next->subject));
  173.             }
  174.  
  175. /* Does this message have replies? If so, print them all!
  176. */
  177.  
  178. #ifdef SHOWREPLIES
  179.         for (rp = replylist; rp != NULL; rp = rp->next)
  180.             if (rp->msgnum == num) {
  181.                 if (rp->maybereply)
  182.                     fprintf(fp, "<li> <b>Maybe reply:</b>");
  183.                 else
  184.                     fprintf(fp, "<li> <b>Reply:</b>");
  185.                 fprintf(fp, " <a href=\"%.4d.html\">",
  186.                 rp->frommsgnum);
  187.                 fprintf(fp, "%s: \"%s\"</a>\n",
  188.                 rp->name, convchars(rp->subject));
  189.             }
  190.         printcomment(fp, "reply", "end");
  191. #endif
  192.  
  193.         fprintf(fp, "</ul>\n");
  194.  
  195. /* Finally...print the body!
  196. */
  197.         printbody(fp, bp, currentid, currentsubject);
  198.  
  199.         fprintf(fp, "<p>\n<ul>\n");
  200.  
  201.         printcomment(fp, "next", "start");
  202.  
  203.         status = (struct body *) hashnumlookup(num + 1, name2,
  204.         email2, subject2, inreply2, date2, fromdate2, msgid2);
  205.         if (status != NULL) {
  206.             fprintf(fp, "<li> <b>Next message:</b> ");
  207.             fprintf(fp, "<a href=\"%.4d.html\">%s: \"%s\"</a>\n",
  208.             num + 1, name2, convchars(subject2));
  209.         }
  210.  
  211.         status = (struct body *) hashnumlookup(num - 1, name2,
  212.         email2, subject2, inreply2, date2, fromdate2, msgid2);
  213.         if (status != NULL) {
  214.             fprintf(fp, "<li> <b>Previous message:</b> ");
  215.             fprintf(fp, "<a href=\"%.4d.html\">%s: \"%s\"</a>\n",
  216.             num - 1, name2, convchars(subject2));
  217.         }
  218.  
  219.         if (inreply[0] != '\0') {
  220.             statusnum = hashreplylookup(inreply, name, subject,
  221.             &subjmatch);
  222.             if (statusnum != -1) {
  223.                 if (subjmatch)
  224.                     fprintf(fp,
  225.                     "<li> <b>Maybe in reply to:</b>");
  226.                 else
  227.                     fprintf(fp,
  228.                     "<li> <b>In reply to:</b>");
  229.                 fprintf(fp, " <a href=\"%.4d.html\">",
  230.                 statusnum);
  231.                 fprintf(fp, "%s: \"%s\"</a>\n",
  232.                 name, convchars(subject));
  233.             }
  234.         }
  235.  
  236.         printcomment(fp, "nextthread", "start");
  237.  
  238.         for (rp = threadlist; rp != NULL; rp = rp->next)
  239.             if (rp->msgnum == num && rp->next != NULL &&
  240.             rp->next->msgnum != -1) {
  241.                 fprintf(fp, "<li> <b>Next in thread:</b> ");
  242.                 fprintf(fp, "<a href=\"%.4d.html\">",
  243.                 rp->next->msgnum);
  244.                 fprintf(fp, "%s: \"%s\"</a>\n",
  245.                 rp->next->name, convchars(rp->next->subject));
  246.             }
  247.  
  248. #ifdef SHOWREPLIES
  249.         for (rp = replylist; rp != NULL; rp = rp->next)
  250.             if (rp->msgnum == num) {
  251.                 if (rp->maybereply)
  252.                     fprintf(fp, "<li> <b>Maybe reply:</b>");
  253.                 else
  254.                     fprintf(fp, "<li> <b>Reply:</b>");
  255.                 fprintf(fp, " <a href=\"%.4d.html\">",
  256.                 rp->frommsgnum);
  257.                 fprintf(fp, "%s: \"%s\"</a>\n",
  258.                 rp->name, convchars(rp->subject));
  259.             }
  260.         printcomment(fp, "reply", "end");
  261. #endif
  262.  
  263.         fprintf(fp, "</ul>\n");
  264.  
  265.         fclose(fp);
  266.  
  267.         if (newfile && chmod(filename, filemode) == -1) {
  268.             sprintf(errmsg, "Couldn't chmod \"%s\" to %o.",
  269.             filename, filemode);
  270.             progerr(NULL);
  271.         }
  272.  
  273.         if (!(num % 5) && showprogress && !skip) {
  274.             printf("\b\b\b\b%3.0f%c", ((float) num / (float) bignum)
  275.             * 100, '%');
  276.             fflush(stdout);
  277.         }
  278.  
  279.         num++;
  280.     }
  281.     if (showprogress)
  282.         printf("\b\b\b\b    \n");
  283.     if (!overwrite)
  284.         bignum = num - 1;
  285. }
  286.  
  287. void printbody(fp, bp, id, subject)
  288.      FILE *fp;
  289.      struct body *bp;
  290.      char *id;
  291.      char *subject;
  292. {
  293.  
  294.     int inheader, insig, inblank, inhtml;
  295.  
  296. #ifdef SHOWHR
  297.     fprintf(fp, "<hr>\n");
  298. #endif
  299.     printcomment(fp, "body", "start");
  300.  
  301.     if (!showhtml || (showhtml && showheaders))
  302.         fprintf(fp, "<pre>\n");
  303.  
  304.     inheader = 1;
  305.     inblank = 1;
  306.     inhtml = 0;
  307.     insig = 0;
  308.  
  309.     while (bp != NULL) {
  310.  
  311.         if ((bp->line)[0] == '\n') {
  312.             if (inheader && showhtml && showheaders)
  313.                 fprintf(fp, "</pre>\n");
  314.             inheader = 0;
  315.         }
  316.         else if (inheader && !showheaders) {
  317.             bp = bp->next;
  318.             continue;
  319.         }
  320.  
  321.         if ((bp->line)[0] == '\n' && inblank) {
  322.             bp = bp->next;
  323.             continue;
  324.         }
  325.         else
  326.             inblank = 0;
  327.  
  328.         if (!strncmp(bp->line, "<html>", 6) ||
  329.         !strncmp(bp->line, "<HTML>", 6)) {
  330.             inhtml = 1;
  331.             if (!showhtml)
  332.                 fprintf(fp, "</pre>\n");
  333.         }
  334.         else if (!strncmp(bp->line, "</html>", 7) ||
  335.         !strncmp(bp->line, "</HTML>", 7)) {
  336.             inhtml = 0;
  337.             fprintf(fp, "%s", bp->line);
  338.             if (!showhtml)
  339.                 fprintf(fp, "<pre>\n");
  340.             bp = bp->next;
  341.             continue;
  342.         }
  343.  
  344.         if (inhtml) {
  345.             fprintf(fp, "%s", bp->line);
  346.             bp = bp->next;
  347.             continue;
  348.         }
  349.  
  350.         if (showhtml) {
  351.             if (!strcmp(bp->line, "--\n") ||
  352.             !strcmp(bp->line, "-- \n") ||
  353.             !strcmp(bp->line, "---\n")) {
  354.                 insig = 1;
  355.                 fprintf(fp, "<pre>\n");
  356.             }
  357.  
  358.             if ((bp->line)[0] == '\n')
  359.                 fprintf(fp, "<p>\n");
  360.             else {
  361.                 if (insig)
  362.                     fprintf(fp, "%s",
  363.                     (char *) convurls(bp->line,
  364.                     id, subject));
  365.                 else if (isquote(bp->line))
  366. #ifdef IQUOTES
  367.                     fprintf(fp, "<i>%s</i><br>\n",
  368.                     (char *) convurls(rmcr(bp->line),
  369.                     id, subject));
  370. #else
  371.                     fprintf(fp, "%s<br>\n",
  372.                     (char *) convurls(rmcr(bp->line),
  373.                     id, subject));
  374. #endif
  375.                 else if ((bp->line)[0] != '\0')
  376. #ifdef SHOWBR
  377.                     fprintf(fp, "%s<br>\n",
  378.                     (char *) convurls(rmcr(bp->line),
  379.                     id, subject));
  380. #else
  381.                     fprintf(fp, "%s\n",
  382.                     (char *) convurls(rmcr(bp->line),
  383.                     id, subject));
  384. #endif
  385.             }
  386.         }
  387.         else if ((bp->line)[0] != '\0')
  388.             fprintf(fp, "%s", (char *) convurls(bp->line,
  389.             id, subject));
  390.  
  391.         bp = bp->next;
  392.  
  393.     }
  394.  
  395.     if (!showhtml)
  396.         fprintf(fp, "</pre>\n");
  397.     else {
  398.         if (insig)
  399.             fprintf(fp, "</pre>\n");
  400.     }
  401.  
  402.     printcomment(fp, "body", "end");
  403. #ifdef SHOWHR
  404.     fprintf(fp, "<hr>\n");
  405. #endif
  406. }
  407.  
  408. /* Write the date index...
  409. */
  410.  
  411. void writedates(dir, label, archives, about)
  412.      char *dir;
  413.      char *label;
  414.      char *archives;
  415.      char *about;
  416. {
  417.     int num, newfile;
  418.     char name[NAMESTRLEN], email[MAILSTRLEN], subject[SUBJSTRLEN],
  419.         inreply[REPYSTRLEN];
  420.     char filename[MAXFILELEN];
  421.     struct body *bp, *status;
  422.     FILE *fp;
  423.  
  424.     sprintf(filename, "%s%s%s", dir,
  425.     (dir[strlen(dir) - 1] == '/') ? "" : "/", datename);
  426.     if (isfile(filename))
  427.         newfile = 0;
  428.     else
  429.         newfile = 1;
  430.     if ((fp = fopen(filename, "w")) == NULL) {
  431.         sprintf(errmsg, "Couldn't write \"%s\".", filename);
  432.         progerr(NULL);
  433.     }
  434.  
  435.     if (showprogress)
  436.         printf("Writing date index to \"%s\"...", filename);
  437.  
  438.     fprintf(fp, "<title>%s by date</title>\n", label);
  439.     fprintf(fp, "<a name=\"start\"><h1>%s by date</h1></a>\n", label);
  440.     fprintf(fp, "<ul>\n");
  441.     if (strcmp(about, "NONE")) {
  442.         fprintf(fp, "<li> <b><a href=\"%s\">About this ", about);
  443.         fprintf(fp, "archive</a></b>\n");
  444.     }
  445.     if (!reverse)
  446.         fprintf(fp,
  447.         "<li> <b><a href=\"#end\">Most recent messages</a></b>\n");
  448.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  449.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  450.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>", subjname);
  451.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  452.     if (strcmp(archives, "NONE")) {
  453.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  454.         fprintf(fp, "archives</a></b>\n");
  455.     }
  456.     fprintf(fp, "</b>\n</ul>\n<p>\n");
  457.     fprintf(fp, "<b>Starting:</b> <i>%s</i><br>\n",
  458.     getdatestr(firstdatenum));
  459.     fprintf(fp, "<b>Ending:</b> <i>%s</i><br>\n", getdatestr(lastdatenum));
  460.     fprintf(fp, "<b>Messages:</b> %d\n<p>\n", bignum + 1);
  461.     fprintf(fp, "<ul>\n");
  462.  
  463.     printdates(fp, datelist);
  464.  
  465.     fprintf(fp, "</ul>\n<p>\n");
  466.     fprintf(fp, "<a name=\"end\"><b>Last message date:</b></a> ");
  467.     fprintf(fp, "<i>%s</i><br>\n", getdatestr(lastdatenum));
  468.     fprintf(fp, "<b>Archived on:</b> <i>%s</i><p>\n", getlocaltime());
  469.     fprintf(fp, "<ul>\n");
  470.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  471.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  472.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>", subjname);
  473.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  474.     if (strcmp(archives, "NONE")) {
  475.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  476.         fprintf(fp, "archives</a></b>\n");
  477.     }
  478.     fprintf(fp, "</a></b>\n</ul>\n<p>\n");
  479.     printfooter(fp);
  480.     fclose(fp);
  481.  
  482.     if (newfile && chmod(filename, filemode) == -1) {
  483.         sprintf(errmsg, "Couldn't chmod \"%s\" to %o.", filename,
  484.         filemode);
  485.         progerr(NULL);
  486.     }
  487.  
  488.     if (showprogress)
  489.         putchar('\n');
  490. }
  491.  
  492. /* Write the thread index...
  493. */
  494.  
  495. void writethreads(dir, label, archives, about)
  496.      char *dir;
  497.      char *label;
  498.      char *archives;
  499.      char *about;
  500. {
  501.     int newfile;
  502.     char filename[MAXFILELEN];
  503.     FILE *fp;
  504.  
  505.     printedlist = NULL;
  506.  
  507.     sprintf(filename, "%s%s%s", dir,
  508.     (dir[strlen(dir) - 1] == '/') ? "" : "/", thrdname);
  509.     if (isfile(filename))
  510.         newfile = 0;
  511.     else
  512.         newfile = 1;
  513.     if ((fp = fopen(filename, "w")) == NULL) {
  514.         sprintf(errmsg, "Couldn't write \"%s\".", filename);
  515.         progerr(NULL);
  516.     }
  517.  
  518.     if (showprogress)
  519.         printf("Writing thread index to \"%s\"...", filename);
  520.  
  521.     fprintf(fp, "<title>%s by thread</title>\n", label);
  522.     fprintf(fp, "<a name=\"start\"><h1>%s by thread</h1></a>\n", label);
  523.     fprintf(fp, "<ul>\n");
  524.     if (strcmp(about, "NONE")) {
  525.         fprintf(fp, "<li> <b><a href=\"%s\">About this ", about);
  526.         fprintf(fp, "archive</a></b>\n");
  527.     }
  528.     if (!reverse)
  529.         fprintf(fp,
  530.         "<li> <b><a href=\"#end\">Most recent messages</a></b>\n");
  531.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  532.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  533.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>", subjname);
  534.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  535.     if (strcmp(archives, "NONE")) {
  536.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  537.         fprintf(fp, "archives</a></b>\n");
  538.     }
  539.     fprintf(fp, "</ul>\n<p>\n");
  540.     fprintf(fp, "<b>Starting:</b> <i>%s</i><br>\n",
  541.     getdatestr(firstdatenum));
  542.     fprintf(fp, "<b>Ending:</b> <i>%s</i><br>\n", getdatestr(lastdatenum));
  543.     fprintf(fp, "<b>Messages:</b> %d\n<p>\n", bignum + 1);
  544.     fprintf(fp, "<ul>\n");
  545.  
  546.     printthreads(fp, datelist);
  547.  
  548.     fprintf(fp, "</ul>\n<p>\n");
  549.     fprintf(fp, "<a name=\"end\"><b>Last message date:</b></a> ");
  550.     fprintf(fp, "<i>%s</i><br>\n", getdatestr(lastdatenum));
  551.     fprintf(fp, "<b>Archived on:</b> <i>%s</i><p>\n", getlocaltime());
  552.     fprintf(fp, "<ul>\n");
  553.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  554.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  555.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>", subjname);
  556.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  557.     if (strcmp(archives, "NONE")) {
  558.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  559.         fprintf(fp, "archives</a></b>\n");
  560.     }
  561.     fprintf(fp, "</ul>\n<p>\n");
  562.     printfooter(fp);
  563.     fclose(fp);
  564.  
  565.     if (newfile && chmod(filename, filemode) == -1) {
  566.         sprintf(errmsg, "Couldn't chmod \"%s\" to %o.", filename,
  567.         filemode);
  568.         progerr(NULL);
  569.     }
  570.  
  571.     if (showprogress)
  572.         putchar('\n');
  573. }
  574.  
  575. /* Prints the article pointers in the thread index by date.
  576. */
  577.  
  578. void printthreads(fp, hp)
  579.      FILE *fp;
  580.      struct header *hp;
  581. {
  582.     int hasreply;
  583.     struct reply *rp;
  584.  
  585.     if (hp != NULL) {
  586.         printthreads(fp, hp->left);
  587.  
  588.         for (hasreply = 0, rp = replylist; rp != NULL; rp = rp->next)
  589.             if (rp->frommsgnum == hp->msgnum) {
  590.                 hasreply = 1;
  591.                 break;
  592.             }
  593.  
  594.         if (!hasreply && !wasprinted(printedlist, hp->msgnum)) {
  595.             fprintf(fp, "<li> <a href=\"%.4d.html\"><b>%s</b></a> ",
  596.             hp->msgnum, convchars(hp->subject));
  597.             fprintf(fp, "<a name=\"%d\"><i>%s</i></a>\n",
  598.             hp->msgnum, hp->name);
  599.             printedlist = (struct printed *)
  600.             markasprinted(printedlist, hp->msgnum);
  601.  
  602.             checkreplies(fp, hp->msgnum, 1);
  603.         }
  604.  
  605.         printthreads(fp, hp->right);
  606.     }
  607. }
  608.  
  609. /* Prints the subject index.
  610. */
  611.  
  612. void writesubjects(dir, label, archives, about)
  613.      char *dir;
  614.      char *label;
  615.      char *archives;
  616.      char *about;
  617. {
  618.     int newfile;
  619.     char filename[MAXFILELEN];
  620.     FILE *fp;
  621.  
  622.     sprintf(filename, "%s%s%s", dir,
  623.     (dir[strlen(dir) - 1] == '/') ? "" : "/", subjname);
  624.     if (isfile(filename))
  625.         newfile = 0;
  626.     else
  627.         newfile = 1;
  628.     if ((fp = fopen(filename, "w")) == NULL) {
  629.         sprintf(errmsg, "Couldn't write \"%s\".", filename);
  630.         progerr(NULL);
  631.     }
  632.  
  633.     if (showprogress)
  634.         printf("Writing subject index to \"%s\"...", filename);
  635.  
  636.     fprintf(fp, "<title>%s by subject</title>\n", label);
  637.     fprintf(fp, "<a name=\"start\"><h1>%s by subject</h1></a>\n", label);
  638.     fprintf(fp, "<ul>\n");
  639.     if (strcmp(about, "NONE")) {
  640.         fprintf(fp, "<li> <b><a href=\"%s\">About this ", about);
  641.         fprintf(fp, "archive</a></b>\n");
  642.     }
  643.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  644.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  645.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  646.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  647.     if (strcmp(archives, "NONE")) {
  648.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  649.         fprintf(fp, "archives</a></b>\n");
  650.     }
  651.     fprintf(fp, "</ul>\n<p>\n");
  652.     fprintf(fp, "<b>Starting:</b> <i>%s</i><br>\n",
  653.     getdatestr(firstdatenum));
  654.     fprintf(fp, "<b>Ending:</b> <i>%s</i><br>\n", getdatestr(lastdatenum));
  655.     fprintf(fp, "<b>Messages:</b> %d\n<p>\n", bignum + 1);
  656.     fprintf(fp, "<ul>\n");
  657.  
  658.     printsubjects(fp, subjectlist);
  659.  
  660.     fprintf(fp, "</ul>\n<p>\n");
  661.     fprintf(fp, "<b>Last message date:</b> <i>%s</i><br>\n",
  662.     getdatestr(lastdatenum));
  663.     fprintf(fp, "<b>Archived on:</b> <i>%s</i><p>\n", getlocaltime());
  664.     fprintf(fp, "<ul>\n");
  665.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  666.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  667.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  668.     fprintf(fp, "<a href=\"%s#start\">[ author ]</a>\n", authname);
  669.     if (strcmp(archives, "NONE")) {
  670.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  671.         fprintf(fp, "archives</a></b>\n");
  672.     }
  673.     fprintf(fp, "</ul>\n<p>\n");
  674.     printfooter(fp);
  675.     fclose(fp);
  676.  
  677.     if (newfile && chmod(filename, filemode) == -1) {
  678.         sprintf(errmsg, "Couldn't chmod \"%s\" to %o.", filename,
  679.         filemode);
  680.         progerr(NULL);
  681.     }
  682.  
  683.     if (showprogress)
  684.         putchar('\n');
  685. }
  686.  
  687. /* Pretty-prints the dates in the index files.
  688. */
  689.  
  690. void printdates(fp, hp)
  691.      FILE *fp;
  692.      struct header *hp;
  693. {
  694.     if (hp != NULL) {
  695.         printdates(fp, hp->left);
  696.         fprintf(fp, "<li> <a href=\"%.4d.html\"><b>%s</b></a> ",
  697.         hp->msgnum, convchars(hp->subject));
  698.         fprintf(fp, "<a name=\"%d\"><i>%s</i></a>\n", hp->msgnum,
  699.         hp->name);
  700.         printdates(fp, hp->right);
  701.     }
  702. }
  703.  
  704. /* Print the subject index pointers alphabetically.
  705. */
  706.  
  707. void printsubjects(fp, hp)
  708.      FILE *fp;
  709.      struct header *hp;
  710. {
  711.     static char oldsubject[SUBJSTRLEN];
  712.  
  713.     if (hp != NULL) {
  714.         printsubjects(fp, hp->left);
  715.         if (stricmp(hp->subject, oldsubject))
  716.             fprintf(fp, "<li> <b>%s</b>\n",
  717.             convchars(hp->subject));
  718.         fprintf(fp, "<ul>\n");
  719.         fprintf(fp, "<li> <a href=\"%.4d.html\">%s</a> ",
  720.         hp->msgnum, hp->name);
  721.         fprintf(fp, "<a name=\"%d\"><i>%s</i></a>\n", hp->msgnum,
  722.         hp->datestr);
  723.         fprintf(fp, "</ul>\n");
  724.         strcpy(oldsubject, hp->subject);
  725.         printsubjects(fp, hp->right);
  726.     }
  727. }
  728.  
  729. /* Prints the author index file.
  730. */
  731.  
  732. void writeauthors(dir, label, archives, about)
  733.      char *dir;
  734.      char *label;
  735.      char *archives;
  736.      char *about;
  737. {
  738.     int newfile;
  739.     char filename[MAXFILELEN];
  740.     FILE *fp;
  741.  
  742.     sprintf(filename, "%s%s%s", dir,
  743.     (dir[strlen(dir) - 1] == '/') ? "" : "/", authname);
  744.     if (isfile(filename))
  745.         newfile = 0;
  746.     else
  747.         newfile = 1;
  748.     if ((fp = fopen(filename, "w")) == NULL) {
  749.         sprintf(errmsg, "Couldn't write \"%s\".", filename);
  750.         progerr(NULL);
  751.     }
  752.  
  753.     if (showprogress)
  754.         printf("Writing author index to \"%s\"...", filename);
  755.  
  756.     fprintf(fp, "<title>%s by author</title>\n", label);
  757.     fprintf(fp, "<a name=\"start\"><h1>%s by author</h1></a>\n", label);
  758.     fprintf(fp, "<ul>\n");
  759.     if (strcmp(about, "NONE")) {
  760.         fprintf(fp, "<li> <b><a href=\"%s\">About this ", about);
  761.         fprintf(fp, "archive</a></b>\n");
  762.     }
  763.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  764.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  765.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  766.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>\n", subjname);
  767.     if (strcmp(archives, "NONE")) {
  768.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  769.         fprintf(fp, "archives</a></b>\n");
  770.     }
  771.     fprintf(fp, "</ul>\n<p>\n");
  772.     fprintf(fp, "<b>Starting:</b> <i>%s</i><br>\n",
  773.     getdatestr(firstdatenum));
  774.     fprintf(fp, "<b>Ending:</b> <i>%s</i><br>\n", getdatestr(lastdatenum));
  775.     fprintf(fp, "<b>Messages:</b> %d\n<p>\n", bignum + 1);
  776.     fprintf(fp, "<ul>\n");
  777.  
  778.     printauthors(fp, authorlist);
  779.  
  780.     fprintf(fp, "</ul>\n<p>\n");
  781.     fprintf(fp, "<b>Last message date:</b> <i>%s</i><br>\n",
  782.     getdatestr(lastdatenum));
  783.     fprintf(fp, "<b>Archived on:</b> <i>%s</i><p>\n", getlocaltime());
  784.     fprintf(fp, "<ul>\n");
  785.     fprintf(fp, "<li> <b>Messages sorted by:</b> ");
  786.     fprintf(fp, "<a href=\"%s#start\">[ date ]</a>", datename);
  787.     fprintf(fp, "<a href=\"%s#start\">[ thread ]</a>", thrdname);
  788.     fprintf(fp, "<a href=\"%s#start\">[ subject ]</a>\n", subjname);
  789.     if (strcmp(archives, "NONE")) {
  790.         fprintf(fp, "<li> <b><a href=\"%s\">Other mail ", archives);
  791.         fprintf(fp, "archives</a></b>\n");
  792.     }
  793.     fprintf(fp, "</ul>\n<p>\n");
  794.     printfooter(fp);
  795.     fclose(fp);
  796.  
  797.     if (newfile && chmod(filename, filemode) == -1) {
  798.         sprintf(errmsg, "Couldn't chmod \"%s\" to %o.", filename,
  799.         filemode);
  800.         progerr(NULL);
  801.     }
  802.  
  803.     if (showprogress)
  804.         putchar('\n');
  805. }
  806.  
  807. /* Prints the author index links sorted alphabetically.
  808. */
  809.  
  810. void printauthors(fp, hp)
  811.      FILE *fp;
  812.      struct header *hp;
  813. {
  814.     static char oldname[SUBJSTRLEN];
  815.  
  816.     if (hp != NULL) {
  817.         printauthors(fp, hp->left);
  818.         if (stricmp(hp->name, oldname))
  819.             fprintf(fp, "<li> <b>%s</b>\n", hp->name);
  820.         fprintf(fp, "<ul>\n");
  821.         fprintf(fp, "<li> <a href=\"%.4d.html\">%s</a> ",
  822.         hp->msgnum, convchars(hp->subject));
  823.         fprintf(fp, "<a name=\"%d\"><i>%s</i></a>\n", hp->msgnum,
  824.         hp->datestr);
  825.         fprintf(fp, "</ul>\n");
  826.         strcpy(oldname, hp->name);
  827.         printauthors(fp, hp->right);
  828.     }
  829. }
  830.  
  831. /* While printing the thread index, prints any replies to replies.
  832. */
  833.  
  834. void checkreplies(fp, num, level)
  835.      FILE *fp;
  836.      int num;
  837.      int level;
  838. {
  839.     struct reply *rp;
  840.  
  841.     for (rp = replylist; rp != NULL; rp = rp->next)
  842.         if (rp->msgnum == num) {
  843.             if (level < thrdlevels)
  844.                 fprintf(fp, "<ul>\n");
  845.             fprintf(fp, "<li> <a href=\"%.4d.html\">",
  846.             rp->frommsgnum);
  847.             printedlist = (struct printed *)
  848.             markasprinted(printedlist, rp->frommsgnum);
  849.             fprintf(fp, "<b>%s </b></a> ",
  850.             convchars(rp->subject));
  851.             fprintf(fp, "<a name=\"%d\"><i>%s</i></a>\n",
  852.             rp->frommsgnum, rp->name);
  853.             checkreplies(fp, rp->frommsgnum, level + 1);
  854.             if (level < thrdlevels)
  855.                 fprintf(fp, "</ul>\n");
  856.         }
  857. }
  858.  
  859. /* Prints a comment in the file.
  860. */
  861.  
  862. void printcomment(fp, label, value)
  863.      FILE *fp;
  864.      char *label;
  865.      char *value;
  866. {
  867.     fprintf(fp, "<!-- %s=\"%s\" -->\n", label, value);
  868. }
  869.  
  870. /* Prints the footer and pointer to the docs in the index files.
  871. */
  872.  
  873. void printfooter(fp)
  874.      FILE *fp;
  875. {
  876.     fprintf(fp, "<hr>\n<i>This archive was generated by ");
  877.     fprintf(fp, "<a href=\"%s\">%s %s</a>.</i>\n",
  878.     HMURL, PROGNAME, VERSION);
  879. }
  880.  
  881. /* Prints a program error string and stops. If errorstr is NULL,
  882. ** this prints whatever happens to be in errstr[] at the time.
  883. */
  884.  
  885. void progerr(errorstr)
  886.      char *errorstr;
  887. {
  888.     if (errorstr != NULL)
  889.             fprintf(stderr, "%s: %s\n", PROGNAME, errorstr);
  890.     else
  891.             fprintf(stderr, "%s: %s\n", PROGNAME, errmsg);
  892.         fprintf(stderr, "%s: type \"%s -z\" for options.\n", PROGNAME,
  893.         PROGNAME);
  894.         exit(-1);
  895. }
  896.  
  897. /* Prints the usage.
  898. */
  899.  
  900. void usage()
  901. {
  902.     printf("  usage: %s -upix [-m \"mbox\"] [-l \"label\"] ",
  903.     PROGNAME);
  904.     printf("[-d \"dir\"]\n");
  905.     printf("         [-a \"URL\"] [-b \"URL\"] [-c \"file\"]\n\n");
  906.     printf("options: -u : Update archive by one article\n");
  907.     printf("         -p : Show progress\n");
  908.     printf("         -i : Read messages from standard input\n");
  909.     printf("         -x : Overwrite previous messages\n");
  910.     printf("         -m : Mail archive to read in\n");
  911.     printf("         -l : What to name the output archive\n");
  912.     printf("         -d : The directory to save HTML files in\n");
  913.     printf("         -a : URL to other archives\n");
  914.     printf("         -b : URL to archive information\n");
  915.     printf("         -c : Configuration file to read in\n\n");
  916.     printf("version: %s\n", VERSION);
  917.     printf("   docs: %s\n", HMURL);
  918.  
  919.     exit(1);
  920. }
  921.