home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYMail.c < prev    next >
C/C++ Source or Header  |  1998-05-10  |  47KB  |  1,978 lines

  1. /*
  2.  * This file checked for sprintf() buffer overruns on 1998/05/06 by Bela
  3.  * Lubkin <filbo@armory.com>.  Please don't introduce any new ones...
  4.  *
  5.  * See comments marked "- BL" for two still-possible overruns in the VMS
  6.  * code.
  7.  *
  8.  * Not yet checked for any other sort of buffer overrun.
  9.  */
  10.  
  11. #include <HTUtils.h>
  12. #include <tcp.h>
  13. #include <HTParse.h>
  14. #include <LYGlobalDefs.h>
  15. #include <HTAlert.h>
  16. #include <LYCurses.h>
  17. #include <LYSignal.h>
  18. #include <LYUtils.h>
  19. #include <LYClean.h>
  20. #include <LYStrings.h>
  21. #include <GridText.h>
  22. #include <LYSystem.h>
  23. #include <LYMail.h>
  24. #include <LYCharSets.h>  /* to get current charset for mail header */
  25.  
  26. #include <LYLeaks.h>
  27.  
  28. #define FREE(x) if (x) {free(x); x = NULL;}
  29.  
  30. BOOLEAN term_letter;    /* Global variable for async i/o. */
  31. PRIVATE void terminate_letter  PARAMS((int sig));
  32. PRIVATE void remove_tildes PARAMS((char *string));
  33.  
  34. /*
  35. **  mailform() sends form content to the mailto address(es). - FM
  36. */
  37. PUBLIC void mailform ARGS4(
  38.     char *,     mailto_address,
  39.     char *,     mailto_subject,
  40.     char *,     mailto_content,
  41.     char *,     mailto_type)
  42. {
  43.     FILE *fd;
  44.     char *address = NULL;
  45.     char *ccaddr = NULL;
  46.     char *keywords = NULL;
  47.     char *searchpart = NULL;
  48.     char *cp = NULL, *cp0 = NULL, *cp1 = NULL;
  49.     char subject[80];
  50.     char self[80];
  51.     char cmd[512];
  52.     int len, i, ch;
  53. #if defined(VMS) || defined(DOSPATH)
  54.     char my_tmpfile[256];
  55.     char *address_ptr1, *address_ptr2;
  56.     char *command = NULL;
  57.     BOOLEAN first = TRUE;
  58.     BOOLEAN isPMDF = FALSE;
  59.     char hdrfile[256];
  60.     FILE *hfd;
  61.  
  62.     if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
  63.     isPMDF = TRUE;
  64.     }
  65. #endif /* VMS */
  66.  
  67.     if (!mailto_address || !mailto_content) {
  68.     HTAlert(BAD_FORM_MAILTO);
  69.     return;
  70.     }
  71.     subject[0] = '\0';
  72.     self[0] = '\0';
  73.  
  74.     if ((cp = (char *)strchr(mailto_address,'\n')) != NULL)
  75.     *cp = '\0';
  76.     StrAllocCopy(address, mailto_address);
  77.  
  78.     /*
  79.      *    Check for a ?searchpart. - FM
  80.      */
  81.     if ((cp = strchr(address, '?')) != NULL) {
  82.     StrAllocCopy(searchpart, cp);
  83.     *cp = '\0';
  84.     cp = (searchpart + 1);
  85.     if (*cp != '\0') {
  86.         /*
  87.          *    Seek and handle a subject=foo. - FM
  88.          */
  89.         while (*cp != '\0') {
  90.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  91.             !strncasecomp(cp, "subject=", 8))
  92.             break;
  93.         cp++;
  94.         }
  95.         if (*cp) {
  96.         cp += 8;
  97.         if ((cp1 = strchr(cp, '&')) != NULL) {
  98.             *cp1 = '\0';
  99.         }
  100.         if (*cp) {
  101.             HTUnEscape(subject);
  102.             LYstrncpy(subject, cp, 70);
  103.         }
  104.         if (cp1) {
  105.             *cp1 = '&';
  106.             cp1 = NULL;
  107.         }
  108.         }
  109.  
  110.         /*
  111.          *    Seek and handle to=address(es) fields.
  112.          *    Appends to address. - FM
  113.          */
  114.         cp = (searchpart + 1);
  115.         while (*cp != '\0') {
  116.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  117.             !strncasecomp(cp, "to=", 3)) {
  118.             cp += 3;
  119.             if ((cp1 = strchr(cp, '&')) != NULL) {
  120.             *cp1 = '\0';
  121.             }
  122.             while (*cp == ',' || isspace((unsigned char)*cp))
  123.             cp++;
  124.             if (*cp) {
  125.             if (*address) {
  126.                 StrAllocCat(address, ",");
  127.             }
  128.             StrAllocCat(address, cp);
  129.             }
  130.             if (cp1) {
  131.             *cp1 = '&';
  132.             cp = cp1;
  133.             cp1 = NULL;
  134.             } else {
  135.             break;
  136.             }
  137.         }
  138.         cp++;
  139.         }
  140.  
  141.         /*
  142.          *    Seek and handle cc=address(es) fields.    Excludes
  143.          *    Bcc=address(es) as unsafe.  We may append our own
  144.          *    cc (below) as a list for the actual mailing. - FM
  145.          */
  146.         cp = (searchpart + 1);
  147.         while (*cp != '\0') {
  148.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  149.             !strncasecomp(cp, "cc=", 3)) {
  150.             cp += 3;
  151.             if ((cp1 = strchr(cp, '&')) != NULL) {
  152.             *cp1 = '\0';
  153.             }
  154.             while (*cp == ',' || isspace((unsigned char)*cp))
  155.             cp++;
  156.             if (*cp) {
  157.             if (ccaddr == NULL) {
  158.                 StrAllocCopy(ccaddr, cp);
  159.             } else {
  160.                 StrAllocCat(ccaddr, ",");
  161.                 StrAllocCat(ccaddr, cp);
  162.             }
  163.             }
  164.             if (cp1) {
  165.             *cp1 = '&';
  166.             cp = cp1;
  167.             cp1 = NULL;
  168.             } else {
  169.             break;
  170.             }
  171.         }
  172.         cp++;
  173.         }
  174.  
  175.         /*
  176.          *    Seek and handle keywords=term(s) fields. - FM
  177.          */
  178.         cp = (searchpart + 1);
  179.         while (*cp != '\0') {
  180.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  181.             !strncasecomp(cp, "keywords=", 9)) {
  182.             cp += 9;
  183.             if ((cp1 = strchr(cp, '&')) != NULL) {
  184.             *cp1 = '\0';
  185.             }
  186.             while (*cp == ',' || isspace((unsigned char)*cp))
  187.             cp++;
  188.             if (*cp) {
  189.             if (keywords == NULL) {
  190.                 StrAllocCopy(keywords, cp);
  191.             } else {
  192.                 StrAllocCat(keywords, cp);
  193.                 StrAllocCat(keywords, ", ");
  194.             }
  195.             }
  196.             if (cp1) {
  197.             *cp1 = '&';
  198.             cp = cp1;
  199.             cp1 = NULL;
  200.             } else {
  201.             break;
  202.             }
  203.         }
  204.         cp++;
  205.         }
  206.         if (keywords != NULL) {
  207.         if (*keywords != '\0') {
  208.             HTUnEscape(keywords);
  209.         } else {
  210.             FREE(keywords);
  211.         }
  212.         }
  213.  
  214.         FREE(searchpart);
  215.     }
  216.     }
  217.  
  218.     /*
  219.      * Convert any Explorer semi-colon Internet address
  220.      * separators to commas. - FM
  221.      */
  222.     cp = address;
  223.     while ((cp1 = strchr(cp, '@')) != NULL) {
  224.     cp1++;
  225.     if ((cp0 = strchr(cp1, ';')) != NULL) {
  226.         *cp0 = ',';
  227.         cp1 = cp0 + 1;
  228.     }
  229.     cp = cp1;
  230.     }
  231.     if (address[(strlen(address) - 1)] == ',')
  232.     address[(strlen(address) - 1)] = '\0';
  233.     if (*address == '\0') {
  234.     FREE(address);
  235.     FREE(ccaddr);
  236.     FREE(keywords);
  237.     HTAlert(BAD_FORM_MAILTO);
  238.     return;
  239.     }
  240.     if (ccaddr != NULL) {
  241.     cp = ccaddr;
  242.     while ((cp1 = strchr(cp, '@')) != NULL) {
  243.         cp1++;
  244.         if ((cp0 = strchr(cp1, ';')) != NULL) {
  245.         *cp0 = ',';
  246.         cp1 = cp0 + 1;
  247.         }
  248.         cp = cp1;
  249.     }
  250.     if (ccaddr[(strlen(ccaddr) - 1)] == ',') {
  251.         ccaddr[(strlen(ccaddr) - 1)] = '\0';
  252.     }
  253.     if (*ccaddr == '\0') {
  254.         FREE(ccaddr);
  255.     }
  256.     }
  257.  
  258.     /*
  259.      *    Unescape the address and ccaddr fields. - FM
  260.      */
  261.     HTUnEscape(address);
  262.     if (ccaddr != NULL) {
  263.     HTUnEscape(ccaddr);
  264.     }
  265.  
  266.     /*
  267.      *    Allow user to edit the default Subject - FM
  268.      */
  269.     if (subject[0] == '\0') {
  270.     if (mailto_subject && *mailto_subject) {
  271.         LYstrncpy(subject, mailto_subject, 70);
  272.     } else {
  273.         strcpy(subject, "mailto:");
  274.         LYstrncpy((char*)&subject[7], address, 63);
  275.     }
  276.     }
  277.     _statusline(SUBJECT_PROMPT);
  278.     if ((ch = LYgetstr(subject, VISIBLE, 71, NORECALL)) < 0) {
  279.     /*
  280.      * User cancelled via ^G. - FM
  281.      */
  282.     _statusline(FORM_MAILTO_CANCELLED);
  283.     sleep(InfoSecs);
  284.     FREE(address);
  285.     FREE(ccaddr);
  286.     FREE(keywords);
  287.     return;
  288.     }
  289.  
  290.     /*
  291.      *    Allow user to specify a self copy via a CC:
  292.      *    entry, if permitted. - FM
  293.      */
  294.     if (!LYNoCc) {
  295.     sprintf(self, "%.79s", (personal_mail_address ?
  296.                 personal_mail_address : ""));
  297.     self[79] = '\0';
  298.     _statusline("Cc: ");
  299.     if ((ch = LYgetstr(self, VISIBLE, sizeof(self), NORECALL)) < 0) {
  300.         /*
  301.          * User cancelled via ^G. - FM
  302.          */
  303.         _statusline(FORM_MAILTO_CANCELLED);
  304.         sleep(InfoSecs);
  305.         FREE(address);
  306.         FREE(ccaddr);
  307.         FREE(keywords);
  308.         return;
  309.     }
  310.     remove_tildes(self);
  311.     if (ccaddr == NULL) {
  312.         StrAllocCopy(ccaddr, self);
  313.     } else {
  314.         StrAllocCat(ccaddr, ",");
  315.         StrAllocCat(ccaddr, self);
  316.     }
  317.     }
  318.  
  319. #if defined(VMS) || defined(DOSPATH)
  320.     tempname(my_tmpfile, NEW_FILE);
  321.     if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
  322.     NULL == strchr(cp, ']') &&
  323.     NULL == strchr(cp, '/')) {
  324.     *cp = '\0';
  325.     strcat(my_tmpfile, ".txt");
  326.     }
  327.     if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
  328.     HTAlert(FORM_MAILTO_FAILED);
  329.     FREE(address);
  330.     FREE(ccaddr);
  331.     FREE(keywords);
  332.     return;
  333.     }
  334.     if (isPMDF) {
  335.     tempname(hdrfile, NEW_FILE);
  336.     if (((cp = strrchr(hdrfile, '.')) != NULL) &&
  337.         NULL == strchr(cp, ']') &&
  338.         NULL == strchr(cp, '/')) {
  339.         *cp = '\0';
  340.         strcat(hdrfile, ".txt");
  341.     }
  342.     if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
  343.         HTAlert(FORM_MAILTO_FAILED);
  344.         FREE(address);
  345.         FREE(ccaddr);
  346.         FREE(keywords);
  347.         return;
  348.     }
  349.     }
  350. #ifdef VMS
  351.     if (isPMDF) {
  352.     if (mailto_type && *mailto_type) {
  353.         fprintf(hfd, "Mime-Version: 1.0\n");
  354.         fprintf(hfd, "Content-Type: %s\n", mailto_type);
  355.         if (personal_mail_address && *personal_mail_address)
  356.         fprintf(hfd, "From: %s\n", personal_mail_address);
  357.         }
  358.     } else if (mailto_type &&
  359.            !strncasecomp(mailto_type, "multipart/form-data", 19)) {
  360.     /*
  361.      *  Ugh!  There's no good way to include headers while
  362.      *  we're still using "generic" VMS MAIL, so we'll put
  363.      *  this in the body of the message. - FM
  364.      */
  365.     fprintf(fd, "X-Content-Type: %s\n\n", mailto_type);
  366.     }
  367. #else
  368.     if (mailto_type && *mailto_type) {
  369.     fprintf(fd, "Mime-Version: 1.0\n");
  370.     fprintf(fd, "Content-Type: %s\n", mailto_type);
  371.     }
  372.     fprintf(fd,"To: %s\n", address);
  373.     if (personal_mail_address && *personal_mail_address)
  374.     fprintf(fd,"From: %s\n", personal_mail_address);
  375.     remove_tildes(self);
  376.     fprintf(fd,"Subject: %.70s\n\n", subject);
  377. #endif
  378.  
  379. #else
  380.     sprintf(cmd, "%s %s", system_mail, system_mail_flags);
  381.     if ((fd = popen(cmd, "w")) == NULL) {
  382.     HTAlert(FORM_MAILTO_FAILED);
  383.     FREE(address);
  384.     FREE(ccaddr);
  385.     FREE(keywords);
  386.     return;
  387.     }
  388.  
  389.     if (mailto_type && *mailto_type) {
  390.     fprintf(fd, "Mime-Version: 1.0\n");
  391.     fprintf(fd, "Content-Type: %s\n", mailto_type);
  392.     }
  393.     fprintf(fd, "To: %s\n", address);
  394.     if (personal_mail_address && *personal_mail_address)
  395.     fprintf(fd, "From: %s\n", personal_mail_address);
  396.     if (ccaddr != NULL && *ccaddr != '\0')
  397.     fprintf(fd, "Cc: %s\n", ccaddr);
  398.     fprintf(fd, "Subject: %s\n\n", subject);
  399.     if (keywords != NULL && *keywords != '\0')
  400.     fprintf(fd, "Keywords: %s\n", keywords);
  401.     _statusline(SENDING_FORM_CONTENT);
  402. #endif /* VMS */
  403.  
  404.     /*
  405.      *    Break up the content into lines with a maximum length of 78.
  406.      *    If the ENCTYPE was text/plain, we have physical newlines and
  407.      *    should take them into account.    Otherwise, the actual newline
  408.      *    characters in the content are hex escaped. - FM
  409.      */
  410.     while((cp = strchr(mailto_content, '\n')) != NULL) {
  411.     *cp = '\0';
  412.     i = 0;
  413.     len = strlen(mailto_content);
  414.     while (len > 78) {
  415.         strncpy(cmd, (char *)&mailto_content[i], 78);
  416.         cmd[78] = '\0';
  417.         fprintf(fd, "%s\n", cmd);
  418.         i += 78;
  419.         len = strlen((char *)&mailto_content[i]);
  420.     }
  421.     fprintf(fd, "%s\n", (char *)&mailto_content[i]);
  422.     mailto_content = (cp+1);
  423.     }
  424.     i = 0;
  425.     len = strlen(mailto_content);
  426.     while (len > 78) {
  427.     strncpy(cmd, (char *)&mailto_content[i], 78);
  428.     cmd[78] = '\0';
  429.     fprintf(fd, "%s\n", cmd);
  430.     i += 78;
  431.     len = strlen((char *)&mailto_content[i]);
  432.     }
  433.     if (len)
  434.     fprintf(fd, "%s\n", (char *)&mailto_content[i]);
  435.  
  436. #ifdef UNIX
  437.     pclose(fd);
  438.     sleep(MessageSecs);
  439. #endif /* UNIX */
  440. #if defined(VMS) || defined(DOSPATH)
  441.     fclose(fd);
  442. #ifdef VMS
  443.     /*
  444.      *    Set the mail command. - FM
  445.      */
  446.     if (isPMDF) {
  447.     /*
  448.      *  For PMDF, put any keywords and the subject
  449.      *  in the header file and close it. - FM
  450.      */
  451.     if (keywords != NULL && *keywords != '\0') {
  452.         fprintf(hfd, "Keywords: %s\n", keywords);
  453.     }
  454.     fprintf(hfd, "Subject: %s\n\n", subject);
  455.     fclose(hfd);
  456.     /*
  457.      *  Now set up the command. - FM
  458.      */
  459.     sprintf(cmd,
  460.         "%s %s %s,%s ",
  461.         system_mail,
  462.         system_mail_flags,
  463.         hdrfile,
  464.         my_tmpfile);
  465.     } else {
  466.     /*
  467.      *  For "generic" VMS MAIL, include the subject in the
  468.      *  command, and ignore any keywords to minimize risk
  469.      *  of them making the line too long or having problem
  470.      *  characters. - FM
  471.      *
  472.      *  Possibly still a problem if user supplies long subject. - BL
  473.      */
  474.     sprintf(cmd,
  475.         "%s %s%s/subject=\"%s\" %s ",
  476.         system_mail,
  477.         system_mail_flags,
  478.         (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"),
  479.         subject,
  480.         my_tmpfile);
  481.     }
  482.     StrAllocCopy(command, cmd);
  483.  
  484.     /*
  485.      *    Now add all the people in the address field. - FM
  486.      */
  487.     address_ptr1 = address;
  488.     do {
  489.     if ((cp = strchr(address_ptr1, ',')) != NULL) {
  490.         address_ptr2 = (cp+1);
  491.         *cp = '\0';
  492.     } else {
  493.         address_ptr2 = NULL;
  494.     }
  495.  
  496.     /*
  497.      *  4 letters is arbitrarily the smallest possible mail
  498.      *  address, at least for lynx.  That way extra spaces
  499.      *  won't confuse the mailer and give a blank address.
  500.      *
  501.      *  ignore addresses so long that they would overflow the
  502.      *  temporary buffer (i.e. about 500 chars). - BL
  503.      */
  504.     if (strlen(address_ptr1) > 3 &&
  505.             strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
  506.         if (!first) {
  507.         StrAllocCat(command, ",");
  508.         }
  509.         sprintf(cmd, mail_adrs, address_ptr1);
  510.         StrAllocCat(command, cmd);
  511.         first = FALSE;
  512.     }
  513.     address_ptr1 = address_ptr2;
  514.     } while (address_ptr1 != NULL);
  515.  
  516.     /*
  517.      *    Now add all the people in the CC field. - FM
  518.      */
  519.     if (ccaddr != NULL && *ccaddr != '\0') {
  520.     address_ptr1 = ccaddr;
  521.     do {
  522.         if ((cp = strchr(address_ptr1, ',')) != NULL) {
  523.         address_ptr2 = (cp+1);
  524.         *cp = '\0';
  525.         } else {
  526.         address_ptr2 = NULL;
  527.         }
  528.  
  529.         /*
  530.          *    4 letters is arbitrarily the smallest possible mail
  531.          *    address, at least for lynx.  That way extra spaces
  532.          *    won't confuse the mailer and give a blank address.
  533.          *
  534.          *  ignore addresses so long that they would overflow the
  535.          *  temporary buffer (i.e. about 500 chars). - BL
  536.          */
  537.         if (strlen(address_ptr1) > 3 &&
  538.                 strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
  539.         StrAllocCat(command, ",");
  540.         sprintf(cmd, mail_adrs, address_ptr1);
  541.         if (isPMDF) {
  542.             strcat(cmd, "/CC");
  543.         }
  544.         StrAllocCat(command, cmd);
  545.         }
  546.         address_ptr1 = address_ptr2;
  547.     } while (address_ptr1 != NULL);
  548.     }
  549.  
  550.     stop_curses();
  551.     printf("Sending form content:\n\n$ %s\n\nPlease wait...", command);
  552.     system(command);
  553.     FREE(command);
  554.     sleep(AlertSecs);
  555.     start_curses();
  556.     remove(my_tmpfile);
  557.     remove(hdrfile);
  558. #else /* DOSPATH */
  559.     StrAllocCopy(command, system_mail);
  560.     StrAllocCat(command, " -t \"");
  561.     StrAllocCat(command, address);
  562.     StrAllocCat(command, "\" -F ");
  563.     StrAllocCat(command, my_tmpfile);
  564.     stop_curses();
  565.     printf("Sending form content:\n\n$ %s\n\nPlease wait...", command);
  566.     system(command);
  567.     FREE(command);
  568.     sleep(MessageSecs);
  569.     start_curses();
  570.     remove(my_tmpfile);
  571. #endif
  572. #endif /* VMS */
  573.  
  574.     FREE(address);
  575.     FREE(ccaddr);
  576.     FREE(keywords);
  577.     return;
  578. }
  579.  
  580. /*
  581. **  mailmsg() sends a message to the owner of the file, if one is defined,
  582. **  telling of errors (i.e., link not available).
  583. */
  584. PUBLIC void mailmsg ARGS4(
  585.     int,        cur,
  586.     char *,     owner_address,
  587.     char *,     filename,
  588.     char *,     linkname)
  589. {
  590.     FILE *fd, *fp;
  591.     char *address = NULL;
  592.     char *searchpart = NULL;
  593.     char cmd[512], *cp, *cp0, *cp1;
  594. #if defined(VMS) || defined(DOSPATH)
  595.     char my_tmpfile[256];
  596.     char *address_ptr1, *address_ptr2;
  597.     char *command = NULL;
  598.     BOOLEAN first = TRUE;
  599.     BOOLEAN isPMDF = FALSE;
  600.     char hdrfile[256];
  601.     FILE *hfd;
  602.  
  603.     CTRACE(tfp, "mailmsg(%d, \"%s\", \"%s\", \"%s\")\n",cur,
  604.     cur, owner_address?owner_address:"<nil>",
  605.     filename?filename:"<nil>",
  606.     linkname?linkname:"<nil>");
  607.  
  608.     if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
  609.     isPMDF = TRUE;
  610.     }
  611. #endif /* VMS */
  612.  
  613.     if (owner_address == NULL || *owner_address == '\0') {
  614.     return;
  615.     }
  616.     if ((cp = (char *)strchr(owner_address,'\n')) != NULL)
  617.     *cp = '\0';
  618.     StrAllocCopy(address, owner_address);
  619.  
  620.     /*
  621.      *    Check for a ?searchpart. - FM
  622.      */
  623.     if ((cp = strchr(address, '?')) != NULL) {
  624.     StrAllocCopy(searchpart, cp);
  625.     *cp = '\0';
  626.     cp = (searchpart + 1);
  627.     if (*cp != '\0') {
  628.         /*
  629.          *    Seek and handle to=address(es) fields.
  630.          *    Appends to address.  We ignore any other
  631.          *    headers in the ?searchpart. - FM
  632.          */
  633.         cp = (searchpart + 1);
  634.         while (*cp != '\0') {
  635.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  636.             !strncasecomp(cp, "to=", 3)) {
  637.             cp += 3;
  638.             if ((cp1 = strchr(cp, '&')) != NULL) {
  639.             *cp1 = '\0';
  640.             }
  641.             while (*cp == ',' || isspace((unsigned char)*cp))
  642.             cp++;
  643.             if (*cp) {
  644.             if (*address) {
  645.                 StrAllocCat(address, ",");
  646.             }
  647.             StrAllocCat(address, cp);
  648.             }
  649.             if (cp1) {
  650.             *cp1 = '&';
  651.             cp = cp1;
  652.             cp1 = NULL;
  653.             } else {
  654.             break;
  655.             }
  656.         }
  657.         cp++;
  658.         }
  659.     }
  660.     }
  661.  
  662.     /*
  663.      *    Convert any Explorer semi-colon Internet address
  664.      *    separators to commas. - FM
  665.      */
  666.     cp = address;
  667.     while ((cp1 = strchr(cp, '@')) != NULL) {
  668.     cp1++;
  669.     if ((cp0 = strchr(cp1, ';')) != NULL) {
  670.         *cp0 = ',';
  671.         cp1 = cp0 + 1;
  672.     }
  673.     cp = cp1;
  674.     }
  675.  
  676.     /*
  677.      *    Unescape the address field. - FM
  678.      */
  679.     HTUnEscape(address);
  680.     if (address[(strlen(address) - 1)] == ',')
  681.     address[(strlen(address) - 1)] = '\0';
  682.     if (*address == '\0') {
  683.     FREE(address);
  684.     CTRACE(tfp, "mailmsg: No address in '%s'.\n",
  685.             owner_address);
  686.     return;
  687.     }
  688.  
  689. #ifdef UNIX
  690.     sprintf(cmd, "%s %s", system_mail, system_mail_flags);
  691.     if ((fd = popen(cmd, "w")) == NULL) {
  692.     FREE(address);
  693.     CTRACE(tfp, "mailmsg: '%s' failed.\n",
  694.             cmd);
  695.     return;
  696.     }
  697.  
  698.     fprintf(fd, "To: %s\n", address);
  699.     fprintf(fd, "Subject: Lynx Error in %s\n", filename);
  700.     if (personal_mail_address != NULL && *personal_mail_address != '\0') {
  701.     fprintf(fd, "Cc: %s\n", personal_mail_address);
  702.     }
  703.     fprintf(fd, "X-URL: %s\n", filename);
  704.     fprintf(fd, "X-Mailer: Lynx, Version %s\n\n", LYNX_VERSION);
  705. #endif /* UNIX */
  706. #if defined(VMS) || defined(DOSPATH)
  707.     tempname(my_tmpfile, NEW_FILE);
  708.     if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
  709.     NULL == strchr(cp, ']') &&
  710.     NULL == strchr(cp, '/')) {
  711.     *cp = '\0';
  712.     strcat(my_tmpfile, ".txt");
  713.     }
  714.     if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
  715.     CTRACE(tfp, "mailmsg: Could not fopen '%s'.\n",
  716.             my_tmpfile);
  717.     FREE(address);
  718.     return;
  719.     }
  720.     if (isPMDF) {
  721.     tempname(hdrfile, NEW_FILE);
  722.     if (((cp = strrchr(hdrfile, '.')) != NULL) &&
  723.         NULL == strchr(cp, ']') &&
  724.         NULL == strchr(cp, '/')) {
  725.         *cp = '\0';
  726.         strcat(hdrfile, ".txt");
  727.     }
  728.     if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
  729.         CTRACE(tfp, "mailmsg: Could not fopen '%s'.\n",
  730.             hdrfile);
  731.         FREE(address);
  732.         return;
  733.     }
  734.  
  735.     if (personal_mail_address != NULL && *personal_mail_address != '\0') {
  736.         fprintf(fd, "Cc: %s\n", personal_mail_address);
  737.     }
  738.     fprintf(fd, "X-URL: %s\n", filename);
  739.     fprintf(fd, "X-Mailer: Lynx, Version %s\n\n", LYNX_VERSION);
  740.     }
  741. #endif /* VMS */
  742.  
  743.     fprintf(fd, "The link   %s :?: %s \n",
  744.         links[cur].lname, links[cur].target);
  745.     fprintf(fd, "called \"%s\"\n", links[cur].hightext);
  746.     fprintf(fd, "in the file \"%s\" called \"%s\"", filename, linkname);
  747.  
  748.     fputs("\nwas requested but was not available.", fd);
  749.     fputs("\n\nThought you might want to know.", fd);
  750.  
  751.     fputs("\n\nThis message was automatically generated by\n", fd);
  752.     fprintf(fd, "Lynx ver. %s", LYNX_VERSION);
  753.     if ((LynxSigFile != NULL) &&
  754.     (fp = fopen(LynxSigFile, "r")) != NULL) {
  755.     fputs("-- \n", fd);
  756.     while (fgets(cmd, sizeof(cmd), fp) != NULL)
  757.         fputs(cmd, fd);
  758.     fclose(fp);
  759.     }
  760. #ifdef UNIX
  761.     pclose(fd);
  762. #endif /* UNIX */
  763. #if defined(VMS) || defined(DOSPATH)
  764.     fclose(fd);
  765. #ifdef VMS
  766.     if (isPMDF) {
  767.     /*
  768.      *  For PMDF, put the subject in the
  769.      *  header file and close it. - FM
  770.      */
  771.     fprintf(hfd, "Subject: Lynx Error in %.56s\n\n", filename);
  772.     fclose(hfd);
  773.     /*
  774.      *  Now set up the command. - FM
  775.      */
  776.     sprintf(cmd,
  777.         "%s %s %s,%s ",
  778.         system_mail,
  779.         system_mail_flags,
  780.         hdrfile,
  781.         my_tmpfile);
  782.     } else {
  783.     /*
  784.      *  For "generic" VMS MAIL, include the
  785.      *  subject in the command. - FM
  786.      */
  787.     sprintf(cmd,
  788.         "%s %s/self/subject=\"Lynx Error in %.56s\" %s ",
  789.         system_mail,
  790.         system_mail_flags,
  791.         filename,
  792.         my_tmpfile);
  793.     }
  794.     StrAllocCopy(command, cmd);
  795.     address_ptr1 = address;
  796.     do {
  797.     if ((cp = strchr(address_ptr1, ',')) != NULL) {
  798.         address_ptr2 = (cp+1);
  799.         *cp = '\0';
  800.     } else
  801.         address_ptr2 = NULL;
  802.  
  803.     /*
  804.      *  4 letters is arbitrarily the smallest possible mail
  805.      *  address, at least for lynx.  That way extra spaces
  806.      *  won't confuse the mailer and give a blank address.
  807.      *
  808.      *  ignore addresses so long that they would overflow the
  809.      *  temporary buffer (i.e. about 500 chars). - BL
  810.      */
  811.     if (strlen(address) > 3 &&
  812.             strlen(address) + strlen(mail_adrs) < sizeof(cmd)) {
  813.         if (!first) {
  814.         StrAllocCat(command, ",");
  815.         }
  816.         sprintf(cmd, mail_adrs, address_ptr1);
  817.         StrAllocCat(command, cmd);
  818.         first = FALSE;
  819.     }
  820.     address_ptr1 = address_ptr2;
  821.     } while (address_ptr1 != NULL);
  822.  
  823.     system(command);
  824.     FREE(command);
  825.     remove(my_tmpfile);
  826.     if (isPMDF) {
  827.     remove(hdrfile);
  828.     }
  829. #else /* DOSPATH */
  830.     StrAllocCopy(command, system_mail);
  831.     StrAllocCat(command, " -t \"");
  832.     StrAllocCat(command, address);
  833.     StrAllocCat(command, "\" -F ");
  834.     StrAllocCat(command, my_tmpfile);
  835.     system(command);
  836.     FREE(command);
  837.     remove(my_tmpfile);
  838. #endif
  839. #endif /* VMS */
  840.  
  841.     if (traversal) {
  842.     FILE *ofp;
  843.  
  844.     if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
  845.         if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
  846.         perror(NOOPEN_TRAV_ERR_FILE);
  847. #ifndef NOSIGHUP
  848.         (void) signal(SIGHUP, SIG_DFL);
  849. #endif /* NOSIGHUP */
  850.         (void) signal(SIGTERM, SIG_DFL);
  851. #ifndef VMS
  852.         (void) signal(SIGINT, SIG_DFL);
  853. #endif /* !VMS */
  854. #ifdef SIGTSTP
  855.         if (no_suspend)
  856.             (void) signal(SIGTSTP,SIG_DFL);
  857. #endif /* SIGTSTP */
  858.         exit(-1);
  859.         }
  860.     }
  861.  
  862.     fprintf(ofp, "%s\t%s \tin %s\n",
  863.              links[cur].lname, links[cur].target, filename);
  864.     fclose(ofp);
  865.     }
  866.  
  867.     FREE(address);
  868.     return;
  869. }
  870.  
  871. /*
  872. **  reply_by_mail() invokes sendmail on Unix or mail on VMS to send
  873. **  a comment  from the users to the owner
  874. */
  875. PUBLIC void reply_by_mail ARGS3(
  876.     char *,     mail_address,
  877.     char *,     filename,
  878.     CONST char *,    title)
  879. {
  880.     char user_input[1000];
  881.     FILE *fd, *fp;
  882.     char *address = NULL;
  883.     char *ccaddr = NULL;
  884.     char *keywords = NULL;
  885.     char *searchpart = NULL;
  886.     char *body = NULL;
  887.     char *cp = NULL, *cp0 = NULL, *cp1 = NULL;
  888.     char *temp = NULL;
  889.     int i, len;
  890.     int c = 0;    /* user input */
  891.     char my_tmpfile[256], cmd[512];
  892. #ifdef DOSPATH
  893.     char tmpfile2[256];
  894. #endif
  895. #if defined(DOSPATH) || defined(VMS)
  896.     char *command = NULL;
  897. #endif
  898.     static char *personal_name = NULL;
  899.     char subject[80];
  900. #ifdef VMS
  901.     char *address_ptr1 = NULL, *address_ptr2 = NULL;
  902.     BOOLEAN first = TRUE;
  903.     BOOLEAN isPMDF = FALSE;
  904.     char hdrfile[256];
  905.     FILE *hfd;
  906.  
  907.     CTRACE(tfp, "reply_by_mail(\"%s\", \"%s\", \"%s\")\n",
  908.     mail_address?mail_address:"<nil>",
  909.     filename?filename:"<nil>",
  910.     title?tilde:"<nil>");
  911.  
  912.     if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
  913.     isPMDF = TRUE;
  914.     }
  915. #else
  916.     char buf[512];
  917.     char *header = NULL;
  918.     int n;
  919. #endif /* VMS */
  920.  
  921.     term_letter = FALSE;
  922.  
  923.     if (mail_address && *mail_address) {
  924.     StrAllocCopy(address, mail_address);
  925.     } else {
  926.     HTAlert(NO_ADDRESS_IN_MAILTO_URL);
  927.     return;
  928.     }
  929.  
  930.     tempname(my_tmpfile, NEW_FILE);
  931.     if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
  932. #ifdef VMS
  933.     NULL == strchr(cp, ']') &&
  934. #endif /* VMS */
  935.     NULL == strchr(cp, '/')) {
  936.     *cp = '\0';
  937.     strcat(my_tmpfile, ".txt");
  938.     }
  939.     if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
  940.     HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
  941.     return;
  942.     }
  943. #ifdef VMS
  944.     if (isPMDF) {
  945.     tempname(hdrfile, NEW_FILE);
  946.     if (((cp = strrchr(hdrfile, '.')) != NULL) &&
  947.         NULL == strchr(cp, ']') &&
  948.         NULL == strchr(cp, '/')) {
  949.         *cp = '\0';
  950.         strcat(hdrfile, ".txt");
  951.     }
  952.     if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
  953.         HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
  954.         return;
  955.     }
  956.     }
  957. #endif /* VMS */
  958.     subject[0] = '\0';
  959.  
  960.     /*
  961.      *    Check for a ?searchpart. - FM
  962.      */
  963.     if ((cp = strchr(address, '?')) != NULL) {
  964.     StrAllocCopy(searchpart, cp);
  965.     *cp = '\0';
  966.     cp = (searchpart + 1);
  967.     if (*cp != '\0') {
  968.         /*
  969.          *    Seek and handle a subject=foo. - FM
  970.          */
  971.         while (*cp != '\0') {
  972.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  973.             !strncasecomp(cp, "subject=", 8))
  974.             break;
  975.         cp++;
  976.         }
  977.         if (*cp) {
  978.         cp += 8;
  979.         if ((cp1 = strchr(cp, '&')) != NULL) {
  980.             *cp1 = '\0';
  981.         }
  982.         if (*cp) {
  983.             strncpy(subject, cp, 70);
  984.             subject[70] = '\0';
  985.             HTUnEscape(subject);
  986.         }
  987.         if (cp1) {
  988.             *cp1 = '&';
  989.             cp1 = NULL;
  990.         }
  991.         }
  992.  
  993.         /*
  994.          *    Seek and handle to=address(es) fields.
  995.          *    Appends to address. - FM
  996.          */
  997.         cp = (searchpart + 1);
  998.         while (*cp != '\0') {
  999.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  1000.             !strncasecomp(cp, "to=", 3)) {
  1001.             cp += 3;
  1002.             if ((cp1 = strchr(cp, '&')) != NULL) {
  1003.             *cp1 = '\0';
  1004.             }
  1005.             while (*cp == ',' || isspace((unsigned char)*cp))
  1006.             cp++;
  1007.             if (*cp) {
  1008.             if (*address) {
  1009.                 StrAllocCat(address, ",");
  1010.             }
  1011.             StrAllocCat(address, cp);
  1012.             }
  1013.             if (cp1) {
  1014.             *cp1 = '&';
  1015.             cp = cp1;
  1016.             cp1 = NULL;
  1017.             } else {
  1018.             break;
  1019.             }
  1020.         }
  1021.         cp++;
  1022.         }
  1023.  
  1024.         /*
  1025.          *    Seek and handle cc=address(es) fields.    Excludes
  1026.          *    Bcc=address(es) as unsafe.  We may append our own
  1027.          *    cc (below) as a list for the actual mailing. - FM
  1028.          */
  1029.         cp = (searchpart + 1);
  1030.         while (*cp != '\0') {
  1031.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  1032.             !strncasecomp(cp, "cc=", 3)) {
  1033.             cp += 3;
  1034.             if ((cp1 = strchr(cp, '&')) != NULL) {
  1035.             *cp1 = '\0';
  1036.             }
  1037.             while (*cp == ',' || isspace((unsigned char)*cp))
  1038.             cp++;
  1039.             if (*cp) {
  1040.             if (ccaddr == NULL) {
  1041.                 StrAllocCopy(ccaddr, cp);
  1042.             } else {
  1043.                 StrAllocCat(ccaddr, ",");
  1044.                 StrAllocCat(ccaddr, cp);
  1045.             }
  1046.             }
  1047.             if (cp1) {
  1048.             *cp1 = '&';
  1049.             cp = cp1;
  1050.             cp1 = NULL;
  1051.             } else {
  1052.             break;
  1053.             }
  1054.         }
  1055.         cp++;
  1056.         }
  1057.  
  1058.         /*
  1059.          *    Seek and handle keywords=term(s) fields. - FM
  1060.          */
  1061.         cp = (searchpart + 1);
  1062.         while (*cp != '\0') {
  1063.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  1064.             !strncasecomp(cp, "keywords=", 9)) {
  1065.             cp += 9;
  1066.             if ((cp1 = strchr(cp, '&')) != NULL) {
  1067.             *cp1 = '\0';
  1068.             }
  1069.             while (*cp == ',' || isspace((unsigned char)*cp))
  1070.             cp++;
  1071.             if (*cp) {
  1072.             if (keywords == NULL) {
  1073.                 StrAllocCopy(keywords, cp);
  1074.             } else {
  1075.                 StrAllocCat(keywords, cp);
  1076.                 StrAllocCat(keywords, ", ");
  1077.             }
  1078.             StrAllocCat(keywords, cp);
  1079.             }
  1080.             if (cp1) {
  1081.             *cp1 = '&';
  1082.             cp = cp1;
  1083.             cp1 = NULL;
  1084.             } else {
  1085.             break;
  1086.             }
  1087.         }
  1088.         cp++;
  1089.         }
  1090.         if (keywords != NULL) {
  1091.         if (*keywords != '\0') {
  1092.             HTUnEscape(keywords);
  1093.         } else {
  1094.             FREE(keywords);
  1095.         }
  1096.         }
  1097.  
  1098.         /*
  1099.          *    Seek and handle body=foo fields. - FM
  1100.          */
  1101.         cp = (searchpart + 1);
  1102.         while (*cp != '\0') {
  1103.         if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
  1104.             !strncasecomp(cp, "body=", 5)) {
  1105.             cp += 5;
  1106.             if ((cp1 = strchr(cp, '&')) != NULL) {
  1107.             *cp1 = '\0';
  1108.             }
  1109.             if (*cp) {
  1110.             /*
  1111.              *  Break up the value into lines with
  1112.              *  a maximum length of 78. - FM
  1113.              */
  1114.             StrAllocCopy(temp, cp);
  1115.             HTUnEscape(temp);
  1116.             cp0 = temp;
  1117.             while((cp = strchr(cp0, '\n')) != NULL) {
  1118.                 *cp = '\0';
  1119.                 if (cp > cp0) {
  1120.                 if (*(cp - 1) == '\r') {
  1121.                     *(cp - 1) = '\0';
  1122.                 }
  1123.                 }
  1124.                 i = 0;
  1125.                 len = strlen(cp0);
  1126.                 while (len > 78) {
  1127.                 strncpy(cmd, (char *)&cp0[i], 78);
  1128.                 cmd[78] = '\0';
  1129.                 strcat(cmd, "\n");
  1130.                 StrAllocCat(body, cmd);
  1131.                 i += 78;
  1132.                 len = strlen((char *)&cp0[i]);
  1133.                 }
  1134.                 sprintf(cmd, "%s\n", (char *)&cp0[i]);
  1135.                 StrAllocCat(body, cmd);
  1136.                 cp0 = (cp + 1);
  1137.             }
  1138.             i = 0;
  1139.             len = strlen(cp0);
  1140.             while (len > 78) {
  1141.                 strncpy(cmd, (char *)&cp0[i], 78);
  1142.                 cmd[78] = '\0';
  1143.                 strcat(cmd, "\n");
  1144.                 StrAllocCat(body, cmd);
  1145.                 i += 78;
  1146.                 len = strlen((char *)&cp0[i]);
  1147.             }
  1148.             if (len) {
  1149.                 sprintf(cmd, "%s\n", (char *)&cp0[i]);
  1150.                 StrAllocCat(body, cmd);
  1151.             }
  1152.             FREE(temp);
  1153.             }
  1154.             if (cp1) {
  1155.             *cp1 = '&';
  1156.             cp = cp1;
  1157.             cp1 = NULL;
  1158.             } else {
  1159.             break;
  1160.             }
  1161.         }
  1162.         cp++;
  1163.         }
  1164.  
  1165.         FREE(searchpart);
  1166.     }
  1167.     }
  1168.  
  1169.     /*
  1170.      *    Convert any Explorer semi-colon Internet address
  1171.      *    separators to commas. - FM
  1172.      */
  1173.     cp = address;
  1174.     while ((cp1 = strchr(cp, '@')) != NULL) {
  1175.     cp1++;
  1176.     if ((cp0 = strchr(cp1, ';')) != NULL) {
  1177.         *cp0 = ',';
  1178.         cp1 = cp0 + 1;
  1179.     }
  1180.     cp = cp1;
  1181.     }
  1182.     if (address[(strlen(address) - 1)] == ',')
  1183.     address[(strlen(address) - 1)] = '\0';
  1184.     if (*address == '\0') {
  1185.     FREE(address);
  1186.     FREE(ccaddr);
  1187.     FREE(keywords);
  1188.     FREE(body);
  1189.     fclose(fd);        /* Close the tmpfile.  */
  1190.     remove(my_tmpfile);    /* Delete the tmpfile. */
  1191.     HTAlert(NO_ADDRESS_IN_MAILTO_URL);
  1192.     return;
  1193.     }
  1194.     if (ccaddr != NULL) {
  1195.     cp = ccaddr;
  1196.     while ((cp1 = strchr(cp, '@')) != NULL) {
  1197.         cp1++;
  1198.         if ((cp0 = strchr(cp1, ';')) != NULL) {
  1199.         *cp0 = ',';
  1200.         cp1 = cp0 + 1;
  1201.         }
  1202.         cp = cp1;
  1203.     }
  1204.     if (ccaddr[(strlen(ccaddr) - 1)] == ',') {
  1205.         ccaddr[(strlen(ccaddr) - 1)] = '\0';
  1206.     }
  1207.     if (*ccaddr == '\0') {
  1208.         FREE(ccaddr);
  1209.     }
  1210.     }
  1211.  
  1212.     /*
  1213.      *    Unescape the address and ccaddr fields. - FM
  1214.      */
  1215.     HTUnEscape(address);
  1216.     if (ccaddr != NULL) {
  1217.     HTUnEscape(ccaddr);
  1218.     }
  1219.  
  1220.     /*
  1221.      *    Set the default subject. - FM
  1222.      */
  1223.     if (subject[0] == '\0' && title && *title) {
  1224.     strncpy(subject, title, 70);
  1225.     subject[70] = '\0';
  1226.     }
  1227.  
  1228.     /*
  1229.      *    Use ^G to cancel mailing of comment
  1230.      *    and don't let SIGINTs exit lynx.
  1231.      */
  1232.     signal(SIGINT, terminate_letter);
  1233.  
  1234.  
  1235. #ifdef VMS
  1236.     if (isPMDF || !body) {
  1237.     /*
  1238.      *  Put the X-URL and X-Mailer lines in the hdrfile
  1239.      *  for PMDF or my_tmpfile for VMS MAIL. - FM
  1240.      */
  1241.     fprintf((isPMDF ? hfd : fd),
  1242.         "X-URL: %s%s\n",
  1243.         (filename && *filename) ? filename : "mailto:",
  1244.         (filename && *filename) ? "" : address);
  1245.     fprintf((isPMDF ? hfd : fd),
  1246.         "X-Mailer: Lynx, Version %s\n",LYNX_VERSION);
  1247. #ifdef NO_ANONYMOUS_MAIL
  1248.     if (!isPMDF) {
  1249.         fprintf(fd, "\n");
  1250.     }
  1251. #endif /* NO_ANONYMOUS_MAIL */
  1252.     }
  1253. #else /* Unix: */
  1254.     /*
  1255.      *    Put the To: line in the header.
  1256.      */
  1257. #ifndef DOSPATH
  1258.     StrAllocCopy(header, "To: ");
  1259.     StrAllocCat(header, address);
  1260.     StrAllocCat(header, "\n");
  1261. #endif
  1262.  
  1263.     /*
  1264.      *    Put the Mime-Version, Content-Type and
  1265.      *    Content-Transfer-Encoding in the header.
  1266.      *    This assumes that the same character set is used
  1267.      *    for composing the mail which is currently selected
  1268.      *    as display character set...
  1269.      *    Don't send a charset if we have a CJK character set
  1270.      *    selected, since it may not be appropriate for mail...
  1271.      *    Also don't use an unofficial "x-" charset.
  1272.      *    Also if the charset would be "us-ascii" (7-bit replacements
  1273.      *    selected, don't send any MIME headers. - kw
  1274.      */
  1275.     if (strncasecomp(LYCharSet_UC[current_char_set].MIMEname,
  1276.              "us-ascii", 8) != 0) {
  1277.     StrAllocCat(header, "Mime-Version: 1.0\n");
  1278.     if (!LYHaveCJKCharacterSet &&
  1279.         strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "x-", 2)
  1280.         != 0) {
  1281.         sprintf(buf,"Content-Type: text/plain; charset=%s\n",
  1282.             LYCharSet_UC[current_char_set].MIMEname);
  1283.         StrAllocCat(header, buf);
  1284.     }
  1285.     StrAllocCat(header, "Content-Transfer-Encoding: 8bit\n");
  1286.     }
  1287.     /*
  1288.      *    Put the X-URL and X-Mailer lines in the header.
  1289.      */
  1290.     StrAllocCat(header, "X-URL: ");
  1291.     if (filename && *filename) {
  1292.         StrAllocCat(header, filename);
  1293.     }
  1294.     else {
  1295.         StrAllocCat(header, "mailto:");
  1296.         StrAllocCat(header, address);
  1297.     }
  1298.     StrAllocCat(header, buf);
  1299.     sprintf(buf, "X-Mailer: Lynx, Version %s\n", LYNX_VERSION);
  1300.     StrAllocCat(header, buf);
  1301. #endif /* VMS */
  1302.  
  1303.     /*
  1304.      *    Clear the screen and inform the user.
  1305.      */
  1306.     clear();
  1307.     move(2,0);
  1308.     scrollok(stdscr, TRUE);    /* Enable scrolling. */
  1309.     if (body)
  1310.     addstr(SENDING_MESSAGE_WITH_BODY_TO);
  1311.     else
  1312.     addstr(SENDING_COMMENT_TO);
  1313.     cp = address;
  1314.     while ((cp1 = strchr(cp, ',')) != NULL) {
  1315.     *cp1 = '\0';
  1316.     while (*cp == ' ')
  1317.         cp++;
  1318.     if (*cp) {
  1319.         addstr(cp);
  1320.         addstr(",\n  ");
  1321.     }
  1322.     *cp1 = ',';
  1323.     cp = (cp1 + 1);
  1324.     }
  1325.     if (*cp) {
  1326.     addstr(cp);
  1327.     }
  1328. #ifdef VMS
  1329.     if ((isPMDF == TRUE) &&
  1330.     (cp = ccaddr) != NULL)
  1331. #else
  1332.     if ((cp = ccaddr) != NULL)
  1333. #endif /* VMS */
  1334.     {
  1335.     if (strchr(cp, ',') != NULL) {
  1336.         addstr(WITH_COPIES_TO);
  1337.     } else {
  1338.         addstr(WITH_COPY_TO);
  1339.     }
  1340.     while ((cp1 = strchr(cp, ',')) != NULL) {
  1341.         *cp1 = '\0';
  1342.         while (*cp == ' ')
  1343.         cp++;
  1344.         if (*cp) {
  1345.         addstr(cp);
  1346.         addstr(",\n  ");
  1347.         }
  1348.         *cp1 = ',';
  1349.         cp = (cp1 + 1);
  1350.     }
  1351.     if (*cp) {
  1352.         addstr(cp);
  1353.     }
  1354.     }
  1355.     addstr(CTRL_G_TO_CANCEL_SEND);
  1356.  
  1357. #ifdef VMS
  1358.     if (isPMDF || !body) {
  1359. #endif /* VMS */
  1360. #ifndef NO_ANONYMOUS_EMAIL
  1361.     /*
  1362.      *    Get the user's personal name.
  1363.      */
  1364.     addstr(ENTER_NAME_OR_BLANK);
  1365.     if (personal_name == NULL)
  1366.     *user_input = '\0';
  1367.     else {
  1368.     addstr(CTRL_U_TO_ERASE);
  1369.     strcpy(user_input, personal_name);
  1370.     }
  1371. #ifdef VMS
  1372.     if (isPMDF) {
  1373.     addstr("Personal_name: ");
  1374.     } else {
  1375.     addstr("X_Personal_name: ");
  1376.     }
  1377. #else
  1378.     addstr("Personal Name: ");
  1379. #endif /* VMS */
  1380.     if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
  1381.     term_letter) {
  1382.     addstr("\n");
  1383.     _statusline(COMMENT_REQUEST_CANCELLED);
  1384.     sleep(InfoSecs);
  1385.     fclose(fd);        /* Close the tmpfile. */
  1386.     scrollok(stdscr,FALSE); /* Stop scrolling.    */
  1387.     goto cleanup;
  1388.     }
  1389.     addstr("\n");
  1390.     remove_tildes(user_input);
  1391.     StrAllocCopy(personal_name, user_input);
  1392.     term_letter = FALSE;
  1393.     if (*user_input) {
  1394. #ifdef VMS
  1395.     fprintf((isPMDF ? hfd : fd),
  1396.         "X-Personal_name: %s\n",user_input);
  1397. #else
  1398.     StrAllocCat(header, "X-Personal_name: ");
  1399.     StrAllocCat(header, user_input);
  1400.     StrAllocCat(header, "\n");
  1401. #endif /* VMS */
  1402.     }
  1403.  
  1404.     /*
  1405.      *    Get the user's return address.
  1406.      */
  1407.     addstr(ENTER_MAIL_ADDRESS_OR_OTHER);
  1408.     addstr(MEANS_TO_CONTACT_FOR_RESPONSE);
  1409.     if (personal_mail_address)
  1410.     addstr(CTRL_U_TO_ERASE);
  1411. #ifdef VMS
  1412.     if (isPMDF) {
  1413.     addstr("From: ");
  1414.     } else {
  1415.     addstr("X-From: ");
  1416.     }
  1417. #else
  1418.     addstr("From: ");
  1419. #endif /* VMS */
  1420.     /* Add the personal mail address if there is one. */
  1421.     sprintf(user_input, "%s", (personal_mail_address ?
  1422.                    personal_mail_address : ""));
  1423.     if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
  1424.     term_letter) {
  1425.     addstr("\n");
  1426.     _statusline(COMMENT_REQUEST_CANCELLED);
  1427.     sleep(InfoSecs);
  1428.     fclose(fd);        /* Close the tmpfile. */
  1429.     scrollok(stdscr,FALSE); /* Stop scrolling.    */
  1430.     goto cleanup;
  1431.     }
  1432.     addstr("\n");
  1433.     remove_tildes(user_input);
  1434. #ifdef VMS
  1435.     if (*user_input) {
  1436.     if (isPMDF) {
  1437.         fprintf(hfd, "From: %s\n", user_input);
  1438.     } else {
  1439.         fprintf(fd, "X-From: %s\n\n", user_input);
  1440.     }
  1441.     } else if (!isPMDF) {
  1442.     fprintf(fd, "\n");
  1443.     }
  1444. #else
  1445.     StrAllocCat(header, "From: ");
  1446.     StrAllocCat(header, user_input);
  1447.     StrAllocCat(header, "\n");
  1448. #endif /* VMS */
  1449. #endif /* !NO_ANONYMOUS_EMAIL */
  1450. #ifdef VMS
  1451.     }
  1452. #endif /* VMS */
  1453.  
  1454.     /*
  1455.      *    Get the subject line.
  1456.      */
  1457.     addstr(ENTER_SUBJECT_LINE);
  1458.     addstr(CTRL_U_TO_ERASE);
  1459.     addstr("Subject: ");
  1460.     /* Add the default subject. */
  1461.     sprintf(user_input, "%.70s%.63s",
  1462.             (subject[0] != '\0') ?
  1463.                      subject :
  1464.             ((filename && *filename) ?
  1465.                     filename : "mailto:"),
  1466.             (subject[0] != '\0') ?
  1467.                       "" :
  1468.             ((filename && *filename) ?
  1469.                       "" : address));
  1470.     if (LYgetstr(user_input, VISIBLE, 71, NORECALL) < 0 ||
  1471.     term_letter) {
  1472.     addstr("\n");
  1473.     _statusline(COMMENT_REQUEST_CANCELLED);
  1474.     sleep(InfoSecs);
  1475.     fclose(fd);        /* Close the tmpfile. */
  1476.     scrollok(stdscr,FALSE); /* Stop scrolling.    */
  1477.     goto cleanup;
  1478.     }
  1479.     addstr("\n");
  1480.     remove_tildes(user_input);
  1481. #ifdef VMS
  1482.     sprintf(subject, "%.70s", user_input);
  1483. #else
  1484.     StrAllocCat(header, "Subject: ");
  1485.     StrAllocCat(header, user_input);
  1486.     StrAllocCat(header, "\n");
  1487. #endif /* VMS */
  1488.  
  1489.     /*
  1490.      *    Offer a CC line, if permitted. - FM
  1491.      */
  1492.     user_input[0] = '\0';
  1493.     if (!LYNoCc) {
  1494.     addstr(ENTER_ADDRESS_FOR_CC);
  1495.     if (personal_mail_address)
  1496.         addstr(CTRL_U_TO_ERASE);
  1497.     addstr(BLANK_FOR_NO_COPY);
  1498.     addstr("Cc: ");
  1499.     /*
  1500.      *  Add the mail address if there is one.
  1501.      */
  1502.     sprintf(user_input, "%s", (personal_mail_address ?
  1503.                    personal_mail_address : ""));
  1504.     if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
  1505.         term_letter) {
  1506.         addstr("\n");
  1507.         _statusline(COMMENT_REQUEST_CANCELLED);
  1508.         sleep(InfoSecs);
  1509.         fclose(fd);         /* Close the tmpfile. */
  1510.         scrollok(stdscr, FALSE);    /* Stop scrolling.    */
  1511.         goto cleanup;
  1512.     }
  1513.     addstr("\n");
  1514.     }
  1515.     remove_tildes(user_input);
  1516.  
  1517.     if (*user_input) {
  1518.     cp = user_input;
  1519.     while (*cp == ',' || isspace((unsigned char)*cp))
  1520.         cp++;
  1521.     if (*cp) {
  1522.         if (ccaddr == NULL) {
  1523.         StrAllocCopy(ccaddr, cp);
  1524.         } else {
  1525.         StrAllocCat(ccaddr, ",");
  1526.         StrAllocCat(ccaddr, cp);
  1527.         }
  1528.     }
  1529.     }
  1530.  
  1531. #ifdef DOSPATH
  1532.     if (*address) {
  1533.         StrAllocCat(header, "To: ");
  1534.         StrAllocCat(header, address);
  1535.         StrAllocCat(header, "\n");
  1536.     }
  1537. #endif
  1538.  
  1539. #ifndef VMS
  1540.     /*
  1541.     **    Add the Cc: header. - FM
  1542.     */
  1543.     if (ccaddr != NULL && *ccaddr != '\0') {
  1544.     StrAllocCat(header, "Cc: ");
  1545.     StrAllocCat(header, ccaddr);
  1546.     StrAllocCat(header, "\n");
  1547.     }
  1548.  
  1549.     /*
  1550.     **    Add the Keywords: header. - FM
  1551.     */
  1552.     if (keywords != NULL && *keywords != '\0') {
  1553.     StrAllocCat(header, "Keywords: ");
  1554.     StrAllocCat(header, keywords);
  1555.     StrAllocCat(header, "\n");
  1556.     }
  1557.  
  1558.     /*
  1559.      *    Terminate the header.
  1560.      */
  1561.     sprintf(buf, "\n");
  1562.     StrAllocCat(header, buf);
  1563. #endif /* !VMS */
  1564.  
  1565.     CTRACE(tfp,"**header==\n%s",header);
  1566.     if (!no_editor && editor && *editor != '\0') {
  1567.     /*
  1568.      *  Use an external editor for the message.
  1569.      */
  1570.     char *editor_arg = "";
  1571.  
  1572.     if (body) {
  1573.         cp1 = body;
  1574.         while((cp = strchr(cp1, '\n')) != NULL) {
  1575.         *cp++ = '\0';
  1576.         fprintf(fd, "%s\n", cp1);
  1577.         cp1 = cp;
  1578.         }
  1579.     } else if (strcmp(HTLoadedDocumentURL(), "")) {
  1580.         /*
  1581.          *    Ask if the user wants to include the original message.
  1582.          */
  1583.         BOOLEAN is_preparsed = (LYPreparsedSource &&
  1584.                     HTisDocumentSource());
  1585.         if (is_preparsed)
  1586.         _statusline(INC_PREPARSED_MSG_PROMPT);
  1587.         else
  1588.         _statusline(INC_ORIG_MSG_PROMPT);
  1589.         c = 0;
  1590.         while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
  1591.            !term_letter && c != 7   && c != 3)
  1592.         c = LYgetch();
  1593.         if (TOUPPER(c) == 'Y') {
  1594.         /*
  1595.          *  The 1 will add the reply "> " in front of every line.
  1596.          */
  1597.         if (is_preparsed)
  1598.             print_wwwfile_to_fd(fd, 0);
  1599.         else
  1600.             print_wwwfile_to_fd(fd, 1);
  1601.         }
  1602.     }
  1603.     fclose(fd);        /* Close the tmpfile. */
  1604.     scrollok(stdscr,FALSE); /* Stop scrolling.    */
  1605.  
  1606.     if (term_letter || c == 7 || c == 3)
  1607.         goto cleanup;
  1608.  
  1609.     /*
  1610.      *  Spawn the users editor on the mail file
  1611.      */
  1612.     if (strstr(editor, "pico")) {
  1613.         editor_arg = " -t"; /* No prompt for filename to use */
  1614.     }
  1615.     sprintf(user_input, "%s%s %s", editor, editor_arg, my_tmpfile);
  1616.     _statusline(SPAWNING_EDITOR_FOR_MAIL);
  1617.     stop_curses();
  1618.     if (system(user_input)) {
  1619.         start_curses();
  1620.         _statusline(ERROR_SPAWNING_EDITOR);
  1621.         sleep(AlertSecs);
  1622.     } else {
  1623.         start_curses();
  1624.     }
  1625.  
  1626.     } else if (body) {
  1627.     /*
  1628.      *  Let user review the body. - FM
  1629.      */
  1630.     clear();
  1631.     move(0,0);
  1632.     addstr(REVIEW_MESSAGE_BODY);
  1633.     refresh();
  1634.     cp1 = body;
  1635.     i = (LYlines - 5);
  1636.     while((cp = strchr(cp1, '\n')) != NULL) {
  1637.         if (i <= 0) {
  1638.         addstr(RETURN_TO_CONTINUE);
  1639.         refresh();
  1640.         c = LYgetch();
  1641.         addstr("\n");
  1642.         if (term_letter || c == 7 || c == 3) {
  1643.             addstr(CANCELLED);
  1644.             sleep(InfoSecs);
  1645.             fclose(fd);         /* Close the tmpfile. */
  1646.             scrollok(stdscr, FALSE);    /* Stop scrolling.    */
  1647.             goto cleanup;
  1648.         }
  1649.         i = (LYlines - 2);
  1650.         }
  1651.         *cp++ = '\0';
  1652.         fprintf(fd, "%s\n", cp1);
  1653.         addstr(cp1);
  1654.         addstr("\n");
  1655.         cp1 = cp;
  1656.         i--;
  1657.     }
  1658.     while (i >= 0) {
  1659.         addstr("\n");
  1660.         i--;
  1661.     }
  1662.     refresh();
  1663.     fclose(fd);        /* Close the tmpfile.      */
  1664.     scrollok(stdscr,FALSE); /* Stop scrolling.      */
  1665.  
  1666.     } else {
  1667.     /*
  1668.      *  Use the internal line editor for the message.
  1669.      */
  1670.     addstr(ENTER_MESSAGE_BELOW);
  1671.     addstr(ENTER_PERIOD_WHEN_DONE_A);
  1672.     addstr(ENTER_PERIOD_WHEN_DONE_B);
  1673.     addstr("\n\n");
  1674.     refresh();
  1675.     *user_input = '\0';
  1676.     if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
  1677.         term_letter || STREQ(user_input, ".")) {
  1678.         _statusline(COMMENT_REQUEST_CANCELLED);
  1679.         sleep(InfoSecs);
  1680.         fclose(fd);         /* Close the tmpfile. */
  1681.         scrollok(stdscr,FALSE);    /* Stop scrolling.    */
  1682.         goto cleanup;
  1683.     }
  1684.  
  1685.     while (!STREQ(user_input, ".") && !term_letter) {
  1686.         addstr("\n");
  1687.         remove_tildes(user_input);
  1688.         fprintf(fd, "%s\n", user_input);
  1689.         *user_input = '\0';
  1690.         if (LYgetstr(user_input, VISIBLE,
  1691.              sizeof(user_input), NORECALL) < 0) {
  1692.         _statusline(COMMENT_REQUEST_CANCELLED);
  1693.         sleep(InfoSecs);
  1694.         fclose(fd);        /* Close the tmpfile. */
  1695.         scrollok(stdscr,FALSE); /* Stop scrolling.    */
  1696.         goto cleanup;
  1697.         }
  1698.     }
  1699.  
  1700.     fprintf(fd, "\n");    /* Terminate the message. */
  1701.     fclose(fd);        /* Close the tmpfile.      */
  1702.     scrollok(stdscr,FALSE); /* Stop scrolling.      */
  1703.     }
  1704.  
  1705. #ifndef VMS
  1706.     /*
  1707.      *    Ignore CTRL-C on this last question.
  1708.      */
  1709.     signal(SIGINT, SIG_IGN);
  1710. #endif /* !VMS */
  1711.     LYStatusLine = (LYlines - 1);
  1712.     if (body)
  1713.     _statusline(SEND_MESSAGE_PROMPT);
  1714.     else
  1715.     _statusline(SEND_COMMENT_PROMPT);
  1716.     LYStatusLine = -1;
  1717.     c = 0;
  1718.     while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
  1719.        !term_letter && c != 7   && c != 3)
  1720.     c = LYgetch();
  1721.     if (TOUPPER(c) != 'Y') {
  1722.     clear();  /* clear the screen */
  1723.     goto cleanup;
  1724.     }
  1725.     if ((body == NULL && LynxSigFile != NULL) &&
  1726.     (fp = fopen(LynxSigFile, "r")) != NULL) {
  1727.     LYStatusLine = (LYlines - 1);
  1728.     _user_message(APPEND_SIG_FILE, LynxSigFile);
  1729.     c = 0;
  1730.     LYStatusLine = -1;
  1731.     while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
  1732.            !term_letter && c != 7    && c != 3)
  1733.         c = LYgetch();
  1734.     if (TOUPPER(c) == 'Y') {
  1735.         if ((fd = fopen(my_tmpfile, "a")) != NULL) {
  1736.         fputs("-- \n", fd);
  1737.         while (fgets(user_input, sizeof(user_input), fp) != NULL) {
  1738.             fputs(user_input, fd);
  1739.         }
  1740.         fclose(fd);
  1741.         }
  1742.     }
  1743.     fclose(fp);
  1744.     }
  1745.     clear();  /* Clear the screen. */
  1746.  
  1747.     /*
  1748.      *    Send the message.
  1749.      */
  1750. #ifdef VMS
  1751.     /*
  1752.      *    Set the mail command. - FM
  1753.      */
  1754.     if (isPMDF) {
  1755.     /*
  1756.      *  For PMDF, put any keywords and the subject
  1757.      *  in the header file and close it. - FM
  1758.      */
  1759.     if (keywords != NULL && *keywords != '\0') {
  1760.         fprintf(hfd, "Keywords: %s\n", keywords);
  1761.     }
  1762.     fprintf(hfd, "Subject: %s\n\n", subject);
  1763.     fclose(hfd);
  1764.     /*
  1765.      *  Now set up the command. - FM
  1766.      */
  1767.     sprintf(cmd,
  1768.         "%s %s %s,%s ",
  1769.         system_mail,
  1770.         system_mail_flags,
  1771.         hdrfile,
  1772.         my_tmpfile);
  1773.     } else {
  1774.     /*
  1775.      *  For "generic" VMS MAIL, include the subject in the
  1776.      *  command, and ignore any keywords to minimize risk
  1777.      *  of them making the line too long or having problem
  1778.      *  characters. - FM
  1779.      *
  1780.      *  Possibly still a problem if user supplies long subject. - BL
  1781.      */
  1782.     sprintf(cmd,
  1783.         "%s %s%s/subject=\"%s\" %s ",
  1784.         system_mail,
  1785.         system_mail_flags,
  1786.         (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"),
  1787.         subject,
  1788.         my_tmpfile);
  1789.     }
  1790.     StrAllocCopy(command, cmd);
  1791.  
  1792.     /*
  1793.      *    Now add all the people in the address field. - FM
  1794.      */
  1795.     address_ptr1 = address;
  1796.     do {
  1797.     if ((cp = strchr(address_ptr1, ',')) != NULL) {
  1798.         address_ptr2 = (cp+1);
  1799.         *cp = '\0';
  1800.     } else {
  1801.         address_ptr2 = NULL;
  1802.     }
  1803.  
  1804.     /*
  1805.      *  4 letters is arbitrarily the smallest possible mail
  1806.      *  address, at least for lynx.  That way extra spaces
  1807.      *  won't confuse the mailer and give a blank address.
  1808.      *
  1809.      *  ignore addresses so long that they would overflow the
  1810.      *  temporary buffer (i.e. about 500 chars). - BL
  1811.      */
  1812.     if (strlen(address_ptr1) > 3 &&
  1813.             strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
  1814.         if (!first) {
  1815.         StrAllocCat(command, ",");
  1816.         }
  1817.         sprintf(cmd, mail_adrs, address_ptr1);
  1818.         StrAllocCat(command, cmd);
  1819.         first = FALSE;
  1820.     }
  1821.     address_ptr1 = address_ptr2;
  1822.     } while (address_ptr1 != NULL);
  1823.  
  1824.     /*
  1825.      *    Now add all the people in the CC field. - FM
  1826.      */
  1827.     if (ccaddr != NULL && *ccaddr != '\0') {
  1828.     address_ptr1 = ccaddr;
  1829.     do {
  1830.         if ((cp = strchr(address_ptr1, ',')) != NULL) {
  1831.         address_ptr2 = (cp+1);
  1832.         *cp = '\0';
  1833.         } else {
  1834.         address_ptr2 = NULL;
  1835.         }
  1836.  
  1837.         /*
  1838.          *    4 letters is arbitrarily the smallest possible mail
  1839.          *    address, at least for lynx.  That way extra spaces
  1840.          *    won't confuse the mailer and give a blank address.
  1841.          *
  1842.          *  ignore addresses so long that they would overflow the
  1843.          *  temporary buffer (i.e. about 500 chars). - BL
  1844.          */
  1845.         if (strlen(address_ptr1) > 3 &&
  1846.                 strlen(address_ptr1) + strlen(mail_adrs) < sizeof(cmd)) {
  1847.         StrAllocCat(command, ",");
  1848.         sprintf(cmd, mail_adrs, address_ptr1);
  1849.         if (isPMDF) {
  1850.             strcat(cmd, "/CC");
  1851.         }
  1852.         StrAllocCat(command, cmd);
  1853.         }
  1854.         address_ptr1 = address_ptr2;
  1855.     } while (address_ptr1 != NULL);
  1856.     }
  1857.  
  1858.     stop_curses();
  1859.     printf("Sending your comment:\n\n$ %s\n\nPlease wait...", command);
  1860.     system(command);
  1861.     FREE(command);
  1862.     sleep(AlertSecs);
  1863.     start_curses();
  1864.     goto cleandown;
  1865. #else /* Unix: */
  1866.     /*
  1867.      *    Send the tmpfile into sendmail.
  1868.      */
  1869.     _statusline(SENDING_YOUR_MSG);
  1870.     sprintf(cmd, "%s %s", system_mail, system_mail_flags);
  1871. #ifdef DOSPATH
  1872.     tempname(tmpfile2, NEW_FILE);
  1873.     if (((cp = strrchr(tmpfile2, '.')) != NULL) &&
  1874.     NULL == strchr(cp, '/')) {
  1875.     *cp = '\0';
  1876.     strcat(tmpfile2, ".txt");
  1877.     }
  1878.     if ((fp = LYNewTxtFile(tmpfile2)) == NULL) {
  1879.     HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
  1880.     return;
  1881.     }
  1882. #else
  1883.     signal(SIGINT, SIG_IGN);
  1884.     fp = popen(cmd, "w");
  1885.     if (fp == NULL) {
  1886.     _statusline(COMMENT_REQUEST_CANCELLED);
  1887.     sleep(InfoSecs);
  1888.     goto cleanup;
  1889.     }
  1890. #endif /* DOSPATH */
  1891.     fd = fopen(my_tmpfile, "r");
  1892.     if (fd == NULL) {
  1893.     _statusline(COMMENT_REQUEST_CANCELLED);
  1894.     sleep(InfoSecs);
  1895.     pclose(fp);
  1896.     goto cleanup;
  1897.     }
  1898.     fputs(header, fp);
  1899.     while ((n = fread(buf, 1, sizeof(buf), fd)) != 0)
  1900.     fwrite(buf, 1, n, fp);
  1901. #ifdef DOSPATH
  1902.     StrAllocCopy(command, system_mail);
  1903.     StrAllocCat(command, " -t \"");
  1904.     StrAllocCat(command, address);
  1905.     StrAllocCat(command, "\" -F ");
  1906.     StrAllocCat(command, tmpfile2);
  1907.     fclose(fp);        /* Close the tmpfile. */
  1908.     stop_curses();
  1909.     printf("Sending your comment:\n\n$ %s\n\nPlease wait...", command);
  1910.     system(command);
  1911.     FREE(command);
  1912.     sleep(MessageSecs);
  1913.     start_curses();
  1914.     remove(tmpfile2);    /* Delete the tmpfile. */
  1915. #else
  1916.     pclose(fp);
  1917. #endif
  1918.     fclose(fd); /* Close the tmpfile. */
  1919.  
  1920.     CTRACE(tfp, "%s\n", cmd);
  1921. #endif /* VMS */
  1922.  
  1923.     /*
  1924.      *    Come here to cleanup and exit.
  1925.      */
  1926. cleanup:
  1927.     signal(SIGINT, cleanup_sig);
  1928. #if !defined(VMS) && !defined(DOSPATH)
  1929.     FREE(header);
  1930. #endif /* !VMS */
  1931.  
  1932. #if defined(VMS) || defined(DOSPATH)
  1933. cleandown:
  1934. #endif /* VMS */
  1935.     term_letter = FALSE;
  1936. #ifdef VMS
  1937.     FREE(command);
  1938.     while (remove(my_tmpfile) == 0)
  1939.     ;         /* Delete the tmpfile(s). */
  1940.     if (isPMDF) {
  1941.     remove(hdrfile); /* Delete the hdrfile. */
  1942.     }
  1943. #else
  1944.     remove(my_tmpfile);  /* Delete the tmpfile. */
  1945. #endif /* VMS */
  1946.     FREE(address);
  1947.     FREE(ccaddr);
  1948.     FREE(keywords);
  1949.     FREE(body);
  1950.     return;
  1951. }
  1952.  
  1953. PRIVATE void terminate_letter ARGS1(int,sig GCC_UNUSED)
  1954. {
  1955.     term_letter = TRUE;
  1956.     /* Reassert the AST */
  1957.     signal(SIGINT, terminate_letter);
  1958. #if defined(VMS) || defined(DOSPATH)
  1959.     /*
  1960.      *    Refresh the screen to get rid of the "interrupt" message.
  1961.      */
  1962.     if (!dump_output_immediately) {
  1963.     lynx_force_repaint();
  1964.     refresh();
  1965.     }
  1966. #endif /* VMS */
  1967. }
  1968.  
  1969. PRIVATE void remove_tildes ARGS1(char *,string)
  1970. {
  1971.    /*
  1972.     *  Change the first character to
  1973.     *  a space if it is a '~'.
  1974.     */
  1975.     if (*string == '~')
  1976.     *string = ' ';
  1977. }
  1978.