home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / sendcmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  22.4 KB  |  893 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/sendcmds.c,v 2.2 90/10/04 18:26:23 melissa Exp $";
  10. #endif
  11.  
  12. #include "mm.h"
  13. #include "cmds.h"
  14. #include "message.h"
  15. #include "parse.h"
  16.  
  17. #define FORWLINE "                ---------------\n\n"
  18.  
  19. static mail_msg outgoing, *msg;        /* outgoing message */
  20. mail_msg *parse_msg();
  21. headers *new_header();
  22. char *safe_strncat();
  23. extern mail_msg *current;
  24. int getmsg();
  25.  
  26. int
  27. cmd_send (n)
  28. int n;
  29. {
  30.     static fdb txtfdb = { _CMTXT };
  31.     static fdb cfmfdb = { _CMCFM , CM_SDH};
  32.     volatile int ret;                /* return value */
  33.     volatile int aa;
  34.     static addresslist temp= { nil, nil };
  35.     extern int prompt_rcpt_always, prompt_for_cc, prompt_for_fcc;
  36.     extern int prompt_for_bcc;
  37.  
  38.     if (mode & MM_SEND) {
  39.     confirm();
  40.     return(deliver());        /* deliver it now */
  41.     }
  42.  
  43.     cm_set_ind(false);            /* no indirections here */
  44.  
  45.     noise("message to");
  46.     free_addresslist(&temp);
  47.     parse_addresses(&temp);
  48.     free_msg(&outgoing);
  49.     set_send_defaults(&outgoing);
  50.     if (outgoing.to == NULL)
  51.     outgoing.to = new_header(TO, "To", HEAD_KNOWN, &outgoing);
  52.     if (outgoing.to->address == NULL) {
  53.     outgoing.to->address = (addresslist *)malloc(sizeof(addresslist));
  54.     outgoing.to->address->first = nil;
  55.     outgoing.to->address->last = nil;
  56.     }
  57.     send_mode(&outgoing);
  58.     if (temp.first) {
  59.     merge_addresses(outgoing.to->address, &temp);
  60.     }
  61.     else {
  62.     prompt_address(" To: ", outgoing.to->address);
  63.     files_to_fcc(outgoing.to->address, &outgoing);
  64.  
  65.     }
  66.     if (!temp.first || prompt_rcpt_always) {
  67.     if (temp.first)
  68.         free_addresslist(&temp);
  69.     if (prompt_for_cc) {
  70.         if (outgoing.cc->address == NULL) {
  71.         outgoing.cc->address =
  72.             (addresslist *)malloc(sizeof(addresslist));
  73.         outgoing.cc->address->first = NULL;
  74.         outgoing.cc->address->last = NULL;
  75.         }
  76.         prompt_address(" cc: ", outgoing.cc->address);
  77.         files_to_fcc(outgoing.cc->address, &outgoing);
  78.     }
  79.  
  80.     if (prompt_for_bcc) {
  81.         if (outgoing.bcc == NULL) {
  82.         outgoing.bcc = new_header(BCC, "Bcc", HEAD_KNOWN,&outgoing);
  83.         outgoing.bcc->address = NULL;
  84.         }
  85.         if (outgoing.bcc->address == NULL) {
  86.         outgoing.bcc->address =
  87.             (addresslist *)malloc(sizeof(addresslist));
  88.         outgoing.bcc->address->first = NULL;
  89.         outgoing.bcc->address->last = NULL;
  90.         }
  91.         prompt_address(" Bcc: ", outgoing.bcc->address);
  92.         files_to_fcc(outgoing.bcc->address, &outgoing);
  93.     }
  94.     if (prompt_for_fcc) {
  95.         if (outgoing.bcc == NULL) {
  96.         outgoing.bcc = new_header(BCC, "Fcc", HEAD_KNOWN,&outgoing);
  97.         outgoing.bcc->address = NULL;
  98.         }
  99.         prompt_fcc(" Fcc: ", outgoing.fcc->address);
  100.     }
  101.     }
  102.     if (outgoing.to)
  103.     files_to_fcc(outgoing.to->address, &outgoing);
  104.     if (outgoing.cc)
  105.     files_to_fcc(outgoing.cc->address, &outgoing);
  106.     if (outgoing.bcc)
  107.     files_to_fcc(outgoing.bcc->address, &outgoing);
  108.     cm_set_ind(true);
  109.     mode |= MM_SEND;
  110.     aa = allow_aborts;
  111.     cmseteof();
  112.     cmseter();
  113.     prompt(" Subject: ");
  114.     cmsetrp();
  115.     allow_aborts = true;
  116.     parse(fdbchn(&txtfdb, &cfmfdb, nil), &pv, &used);
  117.     if (used == &txtfdb) {
  118.     outgoing.subject = new_header(SUBJECT, "Subject", HEAD_KNOWN,
  119.                       &outgoing);
  120.     outgoing.subject->string =
  121.         malloc(strlen(atmbuf)+1);
  122.     strcpy(outgoing.subject->string, atmbuf);
  123.     }
  124.     allow_aborts = aa;
  125.     outgoing.body = NULL;
  126.     ret = getmsg(&outgoing);
  127.     if ((escape_automatic_send && (ret == GET_ESC)) ||
  128.     (control_d_automatic_send && (ret == GET_CTRLD))) { /* send! */
  129.     deliver();
  130.     }
  131. }
  132.  
  133.  
  134. cmd_reply(n)
  135. int n;
  136. {
  137.     pval pv; 
  138.     fdb *used;
  139.     int towhom = CMD_ALL;
  140.     int do_reply_many();
  141.  
  142.     if (mode & MM_READ) {        /* in read mode? */
  143.     /* set default based on reply_to mm var */
  144.     do_reply_one(cf->current,allow_aborts);
  145.     mode &= ~MM_REPLY;
  146.     }
  147.     else {
  148.     free_msg(&outgoing);
  149.     if (!check_cf(O_RDONLY))
  150.         return;
  151.     parse_sequence ("current",NULL,NULL);
  152.     mode |= MM_REPLY;
  153.     copy_sequence (cf->read_sequence, cf->sequence);
  154.     if (sequence_start(cf->read_sequence)) {
  155.         do_reply_many();
  156.     }
  157.     }
  158. }
  159.  
  160. do_reply_many()
  161. {
  162.     char buf[100];
  163.     int ok = false;
  164.     extern int allow_aborts;
  165.     int aa = allow_aborts;
  166.     volatile int doprev = false;
  167.  
  168.     sprintf(buf," Send reply for message %d to: ", cf->current);
  169.     cmseteof();
  170.     if (cmseter ()) {            /* errors return here */
  171.     if (cmcsb._cmerr == CMxEOF) {
  172.         return CMxEOF;
  173.     }
  174.     else
  175.         doprev = true;
  176.     }
  177.     
  178.     prompt(buf);
  179.     if (doprev) {
  180.     doprev = false;
  181.     prevcmd();
  182.     }
  183.     
  184.     allow_aborts = true;
  185.     cmsetrp();
  186.     if (!ignore (cf->current))
  187.     do_reply_one (cf->current,aa);
  188.     if (!sequence_next(cf->read_sequence))
  189.     mode &= ~MM_REPLY;
  190. }
  191.  
  192. /*
  193.  * handle_reply_to
  194.  * take care of parse for reply_to_fdb
  195.  * return FALSE if reply session aborted
  196.  */
  197. handle_reply_to (key, allp, aborts)
  198. int key, *allp;
  199. int aborts;
  200. {
  201.     switch(key) {
  202.     case CMD_ALL:
  203.     *allp = true;
  204.     break;
  205.     case CMD_SENDER:
  206.     *allp = false;
  207.     break;
  208.     case CMD_QUIT:
  209.     confirm();
  210.     allow_aborts = aborts;
  211.     if (cf->current < sequence_last (cf->read_sequence))
  212.         if (!yesno (" Continue replying to remaining messages? ", nil))
  213.         mode &= ~MM_REPLY;
  214.     return (FALSE);            /* skip this message */
  215.     }
  216.     return (TRUE);            /* do this message */
  217. }
  218.  
  219. /*
  220.  * handle_include:
  221.  * handle the include_fdb result
  222.  */
  223. handle_include (key, inclp)
  224. int key, *inclp;
  225. {
  226.     switch(key) {
  227.     case CMD_INCLUDE:
  228.     *inclp = true;
  229.     break;
  230.     case CMD_NOINCLUDE:
  231.     *inclp = false;
  232.     break;
  233.     }
  234. }
  235.  
  236. /*
  237.  * reply to the current message
  238.  */
  239. do_reply_one(n, aborts)
  240. {
  241.     int all, include;
  242.  
  243.     reply_to_fdb._cmdef = reply_all ? "all" : "sender";
  244.     include_fdb._cmdef = reply_insert ? "including" : "not-including";
  245.  
  246.     parse(fdbchn (&reply_to_fdb, &include_fdb, NULL), &pv, &used);
  247.     if (used == &reply_to_fdb) {
  248.     if (!handle_reply_to (pv._pvkey, &all, aborts)) /* aborted? */
  249.         return;
  250.     parse(fdbchn (&include_fdb, NULL), &pv, &used);
  251.     handle_include (pv._pvkey, &include);
  252.     }
  253.     else {                /* used == &include_fdb */
  254.     handle_include (pv._pvkey, &include);
  255.     parse (fdbchn (&reply_to_fdb, NULL), &pv, &used);
  256.     if (!handle_reply_to (pv._pvkey, &all))
  257.         return;
  258.     }
  259.     confirm();
  260.     allow_aborts = aborts;
  261.     do_reply(n, all, include);
  262. }
  263.  
  264.  
  265. do_reply(msgno, all, include) 
  266. {
  267.     int ret;
  268.     int gotfrom = false;
  269.     char *name;
  270.     char *do_reply_indent();
  271.     char *safe_strcpy(), *safe_strcat();
  272.     keylist keylist_copy();
  273.  
  274.     msg = parse_msg(&(cf->msgs[msgno]));
  275.     free_msg(&outgoing);
  276.     set_send_defaults(&outgoing);
  277.     if (outgoing.to == NULL) {
  278.     new_header(TO,"To", HEAD_KNOWN, &outgoing);
  279.     outgoing.to->address = NULL;
  280.     }
  281.     if (outgoing.to->address == NULL) {
  282.     outgoing.to->address = (addresslist *) malloc(sizeof(addresslist));
  283.     outgoing.to->address->first = outgoing.to->address->last = NULL;
  284.     }
  285.     
  286. #ifdef notdef
  287.     if (reply_include_me) {
  288.     if (outgoing.cc == NULL) {
  289.         new_header(CC,"cc", HEAD_KNOWN, &outgoing);
  290.         outgoing.cc->address = NULL;
  291.     }
  292.     if (outgoing.cc->address == NULL) {
  293.         outgoing.cc->address = (addresslist *) malloc(sizeof(addresslist));
  294.         outgoing.cc->address->first = outgoing.cc->address->last = NULL;
  295.     }
  296.     add_addresslist(outgoing.cc->address, user_name, ADR_ADDRESS);
  297.     }
  298. #endif
  299.     if (!gotfrom && msg->reply_to) {
  300.     name = msg->reply_to->string;
  301.     match_addresses(outgoing.to->address, &name, strlen(name));
  302.     gotfrom = true;
  303.  
  304.     }
  305.     if (!gotfrom && msg->from) {
  306.     name = msg->from->string;
  307.     match_addresses(outgoing.to->address, &name, strlen(name));
  308.     gotfrom = true;
  309.     }
  310.     if (msg->resent_from) {
  311.     name = msg->resent_from->string;
  312.     if (outgoing.cc == NULL) {
  313.         new_header(CC,"cc", HEAD_KNOWN, &outgoing);
  314.         outgoing.cc->address = NULL;
  315.     }
  316.     if (outgoing.cc->address == NULL) {
  317.         outgoing.cc->address = (addresslist *) malloc(sizeof(addresslist));
  318.         outgoing.cc->address->first = outgoing.cc->address->last = NULL;
  319.     }
  320.     match_addresses(outgoing.cc->address, &name, strlen(name));
  321.     }
  322.     if (all) {
  323.     if (msg->to || msg->cc) {
  324.         if (outgoing.cc == NULL) {
  325.         new_header(CC,"cc", HEAD_KNOWN, &outgoing);
  326.         outgoing.cc->address = NULL;
  327.         }
  328.         if (outgoing.cc->address == NULL) {
  329.         outgoing.cc->address =
  330.             (addresslist *) malloc(sizeof(addresslist));
  331.         outgoing.cc->address->first = outgoing.cc->address->last =
  332.             NULL;
  333.         }
  334.         if (msg->to)
  335.         merge_addresses(outgoing.cc->address, msg->to->address);
  336.         if (msg->cc)
  337.         merge_addresses(outgoing.cc->address, msg->cc->address);
  338.     }
  339.     }
  340.  
  341.     if (!reply_include_me)
  342.     remove_me (&outgoing);
  343.  
  344.     if (outgoing.to)
  345.     files_to_fcc(outgoing.to->address, &outgoing);
  346.     if (outgoing.cc)
  347.     files_to_fcc(outgoing.cc->address, &outgoing);
  348.     if (outgoing.bcc)
  349.     files_to_fcc(outgoing.bcc->address, &outgoing);
  350.  
  351.     if (include) {
  352.     outgoing.body = do_reply_indent(msg->body);
  353.     }
  354.     if (msg->subject) {
  355.     new_header(SUBJECT,"Subject", HEAD_KNOWN, &outgoing); 
  356.     if (ustrncmp(msg->subject->string, "Re:", 3) != 0) {
  357.         outgoing.subject->string = safe_strcpy("Re: ");
  358.     }
  359.     outgoing.subject->string =
  360.         safe_strcat(outgoing.subject->string, msg->subject->string, false);
  361.     }
  362.     new_header(IN_REPLY_TO, "In-Reply-To", HEAD_KNOWN, &outgoing);
  363. #ifdef undef                /* XXX */
  364.     if (msg->keywords) {
  365.     new_header(KEYWORDS, "Keywords", HEAD_KNOWN, &outgoing);
  366.     outgoing.keywords->keys = keylist_copy (msg->keywords->keys);
  367.     }
  368. #endif /* undef */
  369.     if (msg->date) {
  370.     outgoing.in_reply_to->string = safe_strcpy("Your message of ");
  371.     outgoing.in_reply_to->string =
  372.         safe_strcat(outgoing.in_reply_to->string,msg->date->string,false);
  373.     }
  374.     else if (msg->message_id) {
  375.     outgoing.in_reply_to->string =
  376.         safe_strcat(outgoing.in_reply_to->string,msg->message_id->string,
  377.             false);
  378.     }
  379.     free_msg(msg);
  380.  
  381.     if (reply_initial_display) {
  382.     if (cmcsb._cmoj == NULL)
  383.         display_header (stdout, &outgoing, FALSE, FALSE);
  384.     else
  385.         display_header (cmcsb._cmoj, &outgoing, FALSE, FALSE);
  386.     }
  387.  
  388.     send_mode(&outgoing);
  389.     mode |= MM_ANSWER;            /* to set ANSWER when appropriate */
  390.     ret = getmsg(&outgoing);
  391.     if ((escape_automatic_send && (ret == GET_ESC)) ||
  392.     (control_d_automatic_send && (ret == GET_CTRLD))) { /* send! */
  393.     deliver();
  394.     }
  395. }
  396.  
  397. char *
  398. do_reply_indent (msg)
  399. char *msg;
  400. {
  401.     char *p, *cp;
  402.     int lines,i;
  403.     
  404.     if (reply_indent == NULL || strlen(reply_indent) == 0) {
  405.     return(safe_strcpy (msg));
  406.     }
  407.     
  408.     p = msg;
  409.     lines = 0;
  410.     while(p = index(p,'\n'))
  411.     lines++, p++;
  412.     p = malloc(strlen(msg) + lines * strlen(reply_indent) + 2);
  413.  
  414.     cp = p;
  415.     for(i = 0; i < strlen(reply_indent); i++) /* start off with indent */
  416.         *(cp++) = reply_indent[i];
  417.     for(; *msg != '\0'; cp++, msg++) {
  418.     *cp = *msg;
  419.     if (*msg == '\n' && *(msg+1) != '\0') {
  420.         for(i = 0; i < strlen(reply_indent); i++)
  421.         *(++cp) = reply_indent[i];
  422.     }
  423.     }
  424.     *cp++ = '\n';
  425.     *cp = '\0';
  426.     return(p);
  427. }
  428.  
  429. cmd_forward(n)
  430. int n;
  431. {
  432.     pval pv; 
  433.     fdb *used;
  434.     int towhom = CMD_ALL;
  435.  
  436.     if (mode & MM_SEND) {
  437.     printf ("\
  438. The forward command can not be called while you are currently working on an\n\
  439. outgoing message.\n");
  440.     return;
  441.     }
  442.  
  443.     if (!check_cf(O_RDONLY))
  444.     return;
  445.     if (mode & MM_READ) {        /* in read mode? */
  446.     /* set default based on reply_to mm var */
  447.     noise("message to");
  448.     do_forward_one(cf->current);
  449.     }
  450.     else {
  451.     parse_sequence ("current",NULL,NULL);
  452.     if (sequence_start(cf->sequence))
  453.         do_forward_many();
  454.     }
  455. }
  456.  
  457. do_forward_one(which) {
  458.     int len;
  459.     int ret;
  460.     static addresslist temp = { NULL, NULL };
  461.  
  462.     parse_addresses(&temp);
  463.     free_msg(&outgoing);
  464.     set_send_defaults(&outgoing);
  465.     if (outgoing.to == NULL) {
  466.     new_header(TO, "To", HEAD_KNOWN, &outgoing);
  467.     outgoing.to->address = NULL;
  468.     }
  469.     if (outgoing.to->address == NULL) {
  470.     outgoing.to->address = (addresslist *)malloc(sizeof(addresslist));
  471.     outgoing.to->address->last = outgoing.to->address->first = NULL;
  472.     }
  473.     merge_addresses(outgoing.to->address, &temp);
  474.     if (outgoing.to)
  475.     files_to_fcc(outgoing.to->address, &outgoing);
  476.     if (outgoing.cc)
  477.     files_to_fcc(outgoing.cc->address, &outgoing);
  478.     if (outgoing.bcc)
  479.     files_to_fcc(outgoing.bcc->address, &outgoing);
  480.  
  481.     if (msg = parse_msg (&(cf->msgs[which])))
  482.     set_forward_subject ();
  483.  
  484.     ret = getmsg(&outgoing);
  485.     send_mode(&outgoing);
  486.     if (outgoing.body) {
  487.     if (*outgoing.body) {        /* did user type anything? */
  488.         if (outgoing.body[strlen(outgoing.body)-1] != '\n')
  489.         outgoing.body = safe_strcat(outgoing.body, "\n", false);
  490.         outgoing.body = safe_strcat(outgoing.body, FORWLINE, false);
  491.     }
  492.     outgoing.body = safe_strncat(outgoing.body, cf->msgs[which].text,
  493.                      cf->msgs[which].size);
  494.     if ((escape_automatic_send && (ret == GET_ESC)) ||
  495.         (control_d_automatic_send && (ret == GET_CTRLD))) { /* send! */
  496.         deliver();
  497.     }
  498.     /* XXX shouldn't set this if sendmail() failed */
  499.     if (!(cf->msgs[which].flags & M_FORWARDED) &&
  500.         !(cf->flags & MF_RDONLY)) {
  501.         cf->msgs[which].flags |= (M_FORWARDED|M_MODIFIED);
  502.         cf->flags |= MF_MODIFIED;    /* we'll have to save that flag */
  503.     }
  504.     }
  505.     else {
  506.     printf("Aborted.\n");
  507.     mode &= ~MM_SEND;
  508.     free_msg(&outgoing);
  509.     }
  510. }
  511.     
  512. /*
  513.  * set the subject string for a forwarded message
  514.  */
  515.  
  516. set_forward_subject()
  517. {
  518.     char *s, *f, *cp;
  519.     int fl, sl, len = 0;
  520.  
  521.     if (!(msg->from && msg->subject))
  522.     return;
  523.  
  524.     f = msg->from->string;
  525.     fl = strlen (f);
  526.  
  527.     s = msg->subject->string;
  528.     sl = strlen (s);
  529.  
  530.     new_header (SUBJECT, "Subject", HEAD_KNOWN, &outgoing);
  531.  
  532.     outgoing.subject->string = malloc (sl + fl + 4 + 4);
  533.     sprintf (outgoing.subject->string, "[%.*s: %.*s]", fl, f, sl, s);
  534. }
  535.  
  536. do_forward_many() 
  537. {
  538.     char *forwardees = NULL;
  539.     char *head = NULL;
  540.     char *forward_header(), *forward_banner();
  541.     int ret;
  542.  
  543.     free_msg(&outgoing);
  544.     set_send_defaults(&outgoing);
  545.     if (outgoing.to == NULL) {
  546.     outgoing.to = new_header(TO, "To", HEAD_KNOWN, &outgoing);
  547.     outgoing.to->address = NULL;
  548.     }
  549.     if (outgoing.to->address == NULL) {
  550.     outgoing.to->address = (addresslist *)malloc(sizeof(addresslist));
  551.     outgoing.to->address->first = NULL;
  552.     outgoing.to->address->last = NULL;
  553.     }
  554.     send_mode(&outgoing);
  555.     prompt_address(" To: ", outgoing.to->address);
  556.     files_to_fcc(outgoing.to->address, &outgoing);
  557.  
  558.     ret = getmsg(&outgoing);
  559.  
  560.     if (msg = parse_msg (&cf->msgs[cf->current]))
  561.     set_forward_subject ();
  562.  
  563.     /*
  564.      * If there's only one message to forward, we don't include a
  565.      * summary of the forwarded messages.
  566.      */
  567.     if (sequence_first(cf->sequence) == sequence_last(cf->sequence)) {
  568.     message *m = &cf->msgs[cf->current];
  569.  
  570.     if (*outgoing.body) {
  571.         if (outgoing.body[strlen(outgoing.body)-1] != '\n')
  572.         outgoing.body = safe_strcat(outgoing.body, "\n", false);
  573.         outgoing.body = safe_strcat(outgoing.body, FORWLINE, false);
  574.     }
  575.     outgoing.body = safe_strncat(outgoing.body, m->text, m->size);
  576.     }
  577.     else {                /* more than one message */
  578.     int i = 1;
  579.     do {
  580.         message *m = &cf->msgs[cf->current];
  581.         head = safe_strcat(head, forward_header (m, i), false);
  582.         head = safe_strcat(head, "\n", false);
  583.         if (forwardees && forwardees[strlen(forwardees)-1] !='\n')
  584.         forwardees = safe_strcat(forwardees,"\n", false);
  585.         forwardees = safe_strcat(forwardees, forward_banner(i), false);
  586.         forwardees = safe_strncat(forwardees, m->text, m->size);
  587.         ++i;
  588.     } while (sequence_next (cf->sequence));
  589.     head = safe_strcat(head, forwardees, false);
  590.     if (outgoing.body) {
  591.         if (outgoing.body[strlen(outgoing.body)-1] != '\n')
  592.         outgoing.body = safe_strcat(outgoing.body, "\n", false);
  593.         outgoing.body = safe_strcat(outgoing.body, FORWLINE, false);
  594.     }
  595.     outgoing.body = safe_strcat(outgoing.body, head, false);
  596.     free(forwardees);
  597.     free(head);
  598.     if ((escape_automatic_send && (ret == GET_ESC)) ||
  599.         (control_d_automatic_send && (ret == GET_CTRLD))) { /* send! */
  600.         deliver ();
  601.     }
  602.     }
  603. }
  604.  
  605.  
  606. char *
  607. forward_banner(n) {
  608.     static char buf[50];
  609.     sprintf(buf,"\nMessage %d -- *********************\n",n);
  610.     return(buf);
  611. }
  612.  
  613. char *
  614. forward_header(m, n)
  615. message *m;                /* which message */
  616. int n;                    /* position in forwarded message */
  617. {
  618.     static buffer line;
  619.     char *cp = line;
  620.     char *p;
  621.  
  622.     (void) sprintf (cp, "%4d) %s ", n, hdate (m->date));
  623.     cp += strlen (cp);
  624.     sprintf (cp, "%-12.12s ", htext ("from", m->text));
  625.     cp += strlen (cp);
  626.     sprintf (cp, "%-.32s (%ld chars)", htext ("subject", m->text), m->size);
  627.     cp += strlen (cp);
  628.     return(line);
  629. }
  630.  
  631. cmd_remail(n)
  632. int n;
  633. {
  634.     pval pv; 
  635.     fdb *used;
  636.     int towhom = CMD_ALL;
  637.     addresslist to;
  638.  
  639.     if (mode & MM_SEND) {
  640.     printf ("\
  641. The remail command can not be called while you are currently working on an\n\
  642. outgoing message.\n");
  643.     return;
  644.     }
  645.     to.last = to.first = NULL;
  646.  
  647.     if (mode & MM_READ) {        /* in read mode? */
  648.     /* set default base on reply_to mm var */
  649.     noise("message to");
  650.     parse_addresses(&to);
  651.     while (to.first == NULL)    /* have to have one */
  652.         prompt_address(" To: ", &to);
  653.     do_remail_one(cf->current, &to);
  654.     free_addresslist(&to);
  655.     }
  656.     else {
  657.     if (!check_cf(O_RDONLY))
  658.         return;
  659.     parse_sequence ("current",NULL,NULL);
  660.     if (sequence_start(cf->sequence)) {
  661.         do_remail_many();
  662.     }
  663.     }
  664. }
  665.  
  666. do_remail_one(which, to) 
  667. int which;
  668. addresslist *to;
  669. {
  670.     int len;
  671.     static addresslist temp = { NULL, NULL };
  672.  
  673.     /* not a memory leak unless parse_msg starts to malloc */
  674.     msg = parse_msg(&(cf->msgs[which]));
  675.     if (msg->resent_to) {
  676.     free_header(msg, RESENT_TO);
  677.     }
  678.     new_header(RESENT_TO, "Resent-To", HEAD_KNOWN, msg);
  679.     msg->resent_to->address = (addresslist *) malloc(sizeof(addresslist));
  680.     msg->resent_to->address->last = msg->resent_to->address->first =  NULL;
  681.     merge_addresses(msg->resent_to->address, to);
  682.     if (msg->resent_date) 
  683.     free_header(msg, RESENT_DATE);
  684.     new_header(RESENT_DATE, "Resent-Date", HEAD_KNOWN, msg);
  685.     msg->resent_date->string = safe_strcpy(rfctime(time(0)));
  686.     if (msg->resent_from) 
  687.     free_header(msg, RESENT_FROM);
  688.     new_header(RESENT_FROM, "Resent-From", HEAD_KNOWN, msg);
  689.                     /* check from variable. */
  690.     msg->resent_from->string = safe_strcpy(create_sender());
  691.     len = 0;
  692.     if (msg->to)
  693.         files_to_fcc(msg->to->address, msg);
  694.     sendmail(msg);
  695. }
  696.     
  697. do_remail_many() 
  698. {
  699.     addresslist to;
  700.     
  701.     to.last = to.first = NULL;
  702.     prompt_address(" To: ", &to);
  703.     do {
  704.     if (!ignore(cf->current))
  705.         do_remail_one(cf->current, &to);
  706.     } while (sequence_next (cf->sequence));
  707. }
  708.  
  709.  
  710. int
  711. cmd_bug (n)
  712. int n;
  713. {
  714.     static fdb txtfdb = { _CMTXT };
  715.     static fdb cfmfdb = { _CMCFM , CM_SDH};
  716.     char *name;
  717.     int ret;
  718.     addresslist tmp;
  719.     headers *h;
  720.     int aa;
  721.     volatile int doprev = false;
  722.  
  723.     cm_set_ind(false);            /* no indirections here */
  724.  
  725.     tmp.first = tmp.last = NULL;
  726.     free_msg(&outgoing);
  727.     set_send_defaults(&outgoing);
  728.     confirm();
  729.     send_mode(&outgoing);
  730.     cm_set_ind(false);
  731.     name = BUGSTO;
  732.     match_addresses(outgoing.to->address, &name, strlen(name));
  733.     merge_addresses(outgoing.to,&tmp);
  734.     aa = allow_aborts;
  735.     cmseteof();
  736.     if (cmseter ()) {            /* errors return here */
  737.     if (cmcsb._cmerr == CMxEOF) {
  738.         return CMxEOF;
  739.     }
  740.     else
  741.         doprev = true;
  742.     }
  743.     
  744.     prompt(" Subject: ");
  745.     if (doprev) {
  746.     doprev = false;
  747.     prevcmd();
  748.     }
  749.     cmsetrp();
  750.     allow_aborts = true;
  751.     parse(fdbchn(&txtfdb, &cfmfdb, nil), &pv, &used);
  752.     if (used == &txtfdb) {
  753.     outgoing.subject = new_header(SUBJECT, "Subject", HEAD_KNOWN,
  754.                       &outgoing);
  755.     outgoing.subject->string =
  756.         malloc(strlen(atmbuf)+1);
  757.     strcpy(outgoing.subject->string, atmbuf);
  758.     }
  759.     allow_aborts = aa;
  760.     h = new_header(USER_HEADERS, "Bug-Report", HEAD_UNKNOWN, &outgoing);
  761.     h->string = malloc(strlen("Bug in ")+strlen(mm_version)+
  762.                strlen(OStype)+3+1);
  763.     sprintf(h->string,"Bug in %s (%s)", mm_version, OStype);
  764.     
  765.     outgoing.body = NULL;
  766.     ret = getmsg(&outgoing);
  767.     if ((escape_automatic_send && (ret == GET_ESC)) ||
  768.     (control_d_automatic_send && (ret == GET_CTRLD))) { /* send! */
  769.     deliver ();
  770.     }
  771. }
  772.  
  773.  
  774. cmd_insert (n)
  775. int n;
  776. {
  777.   char *fname, *parse_input_file();
  778.   char *text, *read_from_temp();
  779.  
  780.   if (!(mode & MM_SEND)) {
  781.     fprintf (stderr, "\nNot in send mode.  Cannot insert file.\n");
  782.     return;
  783.   }
  784.   noise ("from file");
  785.   fname = parse_input_file (NULL, NULL, false);
  786.   confirm();
  787.   if ((text = read_from_temp(fname)) == NULL) {
  788.     free (fname);
  789.     return;
  790.   }
  791.   free (fname);
  792.   if (outgoing.body == NULL) {
  793.     outgoing.body = (char *) malloc (strlen(text)+1);
  794.     outgoing.body[0] = '\0';
  795.   }
  796.   else
  797.     outgoing.body = (char *) safe_realloc (outgoing.body, 
  798.                      strlen(outgoing.body)+strlen(text)+1);
  799.   strcat (outgoing.body, text);
  800.   free (text);
  801. }
  802.  
  803.  
  804.  
  805. mail_msg *
  806. get_outgoing() {
  807.   return (&outgoing);
  808. }
  809.  
  810.  
  811. set_outgoing (m) mail_msg *m; {
  812.   free_msg (&outgoing);
  813.   bcopy ((char *) m, (char *) &outgoing, sizeof(mail_msg));
  814. }
  815.  
  816. /*
  817.  * remove self from recipient headers.
  818.  * invoked by "reply" command if reply-include-me is false.
  819.  */
  820.  
  821. remove_me (msg)
  822. mail_msg *msg;
  823. {
  824.     addr_unit au;
  825.     addresslist al;
  826.  
  827.     /*
  828.      * construct a trivial addr_unit consisting of our username.
  829.      * we should really use a user-specifiable pattern instead.
  830.      */
  831.     au.type = ADR_ADDRESS;
  832.     au.data = user_name;
  833.     au.next = au.prev = nil;
  834.  
  835.     /*
  836.      * build a trivial address list
  837.      */
  838.     al.first = al.last = &au;
  839.  
  840.     /*
  841.      * remove ourself from the To: and cc: headers.
  842.      */
  843.     if (msg->to)
  844.     remove_addr (msg->to->address, &al);
  845.     if (msg->cc)
  846.     remove_addr (msg->cc->address, &al);
  847. }
  848.  
  849. int
  850. cmd_smail (n)
  851. int n;
  852. {
  853.     static fdb txtfdb = { _CMTXT };
  854.     static fdb cfmfdb = { _CMCFM , CM_SDH};
  855.     int ret;                /* return value */
  856.     int aa;
  857.     static addresslist temp= { nil, nil };
  858.     extern int prompt_rcpt_always, prompt_for_cc, prompt_for_fcc;
  859.     extern int prompt_for_bcc;
  860.  
  861.     cm_set_ind(false);            /* no indirections here */
  862.  
  863.     noise("message to");
  864.     free_addresslist(&temp);
  865.     parse_addresses(&temp);
  866.     free_msg(&outgoing);
  867.     set_send_defaults(&outgoing);
  868.     if (outgoing.to == NULL)
  869.     outgoing.to = new_header(TO, "To", HEAD_KNOWN, &outgoing);
  870.     if (outgoing.to->address == NULL) {
  871.     outgoing.to->address = (addresslist *)malloc(sizeof(addresslist));
  872.     outgoing.to->address->first = nil;
  873.     outgoing.to->address->last = nil;
  874.     }
  875.     send_mode(&outgoing);
  876.     if (temp.first) {
  877.     merge_addresses(outgoing.to->address, &temp);
  878.     }
  879.     if (outgoing.to)
  880.     files_to_fcc(outgoing.to->address, &outgoing);
  881.     if (outgoing.cc)
  882.     files_to_fcc(outgoing.cc->address, &outgoing);
  883.     if (outgoing.bcc)
  884.     files_to_fcc(outgoing.bcc->address, &outgoing);
  885.     cm_set_ind(true);
  886.     mode |= MM_SEND;
  887.     outgoing.body = NULL;
  888.     ret = getmsg(&outgoing);
  889.     deliver();
  890. }
  891.  
  892.  
  893.