home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES3.ZIP / MAIL / mailsend.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  36.3 KB  |  1,039 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    m a i l s e n d . c                                             */
  3. /*                                                                    */
  4. /*    Subroutines for sending mail for UUPC/extended                  */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  9. /*       Wonderworks.                                                 */
  10. /*                                                                    */
  11. /*       All rights reserved except those explicitly granted by       */
  12. /*       the UUPC/extended license agreement.                         */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: mailsend.c 1.11 1993/11/20 14:48:53 ahd Exp $
  21.  *
  22.  *    Revision history:
  23.  *    $Log: mailsend.c $
  24.  * Revision 1.11  1993/11/20  14:48:53  ahd
  25.  * Correct execute() flag to use new editor window option, not pager window
  26.  *
  27.  * Revision 1.10  1993/11/13  17:43:26  ahd
  28.  * Normalize external command processing
  29.  *
  30.  * Revision 1.9  1993/10/31  19:04:03  ahd
  31.  * Trap no subject after subject (-s) flag when sending mail
  32.  *
  33.  * Revision 1.8  1993/10/12  01:32:08  ahd
  34.  * Normalize comments to PL/I style
  35.  *
  36.  * Revision 1.6  1993/10/04  03:57:20  ahd
  37.  * Clarify error message
  38.  *
  39.  * Revision 1.5  1993/08/02  03:24:59  ahd
  40.  * Further changes in support of Robert Denny's Windows 3.x support
  41.  *
  42.  * Revision 1.4  1993/07/31  16:26:01  ahd
  43.  * Changes in support of Robert Denny's Windows support
  44.  *
  45.  */
  46.  
  47. /*--------------------------------------------------------------------*/
  48. /*                        System include files                        */
  49. /*--------------------------------------------------------------------*/
  50.  
  51. #include <ctype.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57.  
  58. /*--------------------------------------------------------------------*/
  59. /*                    UUPC/extended include files                     */
  60. /*--------------------------------------------------------------------*/
  61.  
  62. #include "lib.h"
  63.  
  64. #include "arpadate.h"
  65. #include "expath.h"
  66. #include "execute.h"
  67. #include "hlib.h"
  68. #include "mlib.h"
  69. #include "alias.h"
  70. #include "mail.h"
  71. #include "maillib.h"
  72. #include "mailblib.h"
  73. #include "mailsend.h"
  74. #include "safeio.h"
  75. #include "address.h"
  76.  
  77. /*--------------------------------------------------------------------*/
  78. /*                     Local function prototypes                      */
  79. /*--------------------------------------------------------------------*/
  80.  
  81.  static char *ExplodeAlias(char *header ,
  82.                       const char *alias,
  83.                       FILE *stream,
  84.                       const boolean resent);
  85.  
  86.  
  87.  static void PutHead( const char *label,
  88.                       const char *operand,
  89.                       FILE *stream,
  90.                       const boolean resent);
  91.  
  92.  static boolean Append_Signature(FILE *mailbag,
  93.                      const boolean alternate);
  94.  
  95.  static void Prompt_Input( char *tmailbag,
  96.                           FILE *fmailbag,
  97.                            char *subject,
  98.                           const int current);
  99.  
  100.  static boolean Subcommand( char *buf,
  101.                            FILE *fmailbag,
  102.                            char *tmailbag,
  103.                            char *subject,
  104.                            const int current_msg);
  105.  
  106.  static void CopyOut( const char* input);
  107.  
  108.  static void filter( char *tmailbag, char *command);
  109.  
  110.  static char *GetString( char *input);
  111.  
  112. currentfile();                /* Define current file for panic()     */
  113.  
  114. /*--------------------------------------------------------------------*/
  115. /*    E x p l o d e A l i a s                                         */
  116. /*                                                                    */
  117. /*    Resolves an alias, exploding it into a list if needed.          */
  118. /*--------------------------------------------------------------------*/
  119.  
  120.  static char *ExplodeAlias(char *header ,
  121.                       const char *alias,
  122.                       FILE *stream,
  123.                       const boolean resent)
  124. {
  125.    char *fullname;
  126.    char buffer[LSIZE];
  127.  
  128.    if ((alias == NULL) || (strlen(alias) == 0))
  129.    {
  130.       printmsg(0,"ExplodeAlias: NULL or empty string for argument");
  131.       panic();
  132.    }
  133.  
  134.    fullname = AliasByNick(alias);
  135.  
  136.    printmsg(4,"Processing alias '%s', result '%s'", alias,
  137.       (fullname == NULL) ? alias : fullname);
  138.  
  139.    if (fullname == NULL)            /* No alias found for user?     */
  140.    {                                /* No --> Try node lookup       */
  141.       char user[MAXADDR];
  142.       char node[MAXADDR];
  143.       char path[MAXADDR];
  144.       char bucket[MAXADDR];
  145.  
  146.       ExtractAddress(bucket, (char *) alias, FALSE);
  147.       user_at_node(bucket, path, node, user);
  148.       fullname = AliasByAddr( node, user);
  149.  
  150.       if (fullname == NULL)         /* Did we come up empty?         */
  151.       {
  152.          char *hisuser, *hisnode;
  153.  
  154.          hisuser = strtok( bucket, "@");
  155.          hisnode = strtok( NULL, "@");
  156.          if ((*bucket != '@') &&
  157.              equal(hisuser, user ) && (hisnode != NULL) &&
  158.              equal(hisnode, node ) && (strchr( node, '.') == NULL))
  159.          {
  160.             if (equal(hisnode, E_nodename))
  161.                strcpy(node, E_fdomain);
  162.             else {
  163.                strcat(node,".");
  164.                strcat(node,E_localdomain);
  165.             }
  166.  
  167.             ExtractAddress(path, (char *) alias, TRUE);
  168.             if (strlen( path ) == 0)
  169.                sprintf(buffer,"%s@%s", hisuser, node );
  170.             else
  171.                sprintf(buffer,"\"%s\" <%s@%s>", path, hisuser, node);
  172.             fullname = buffer;
  173.          }
  174.          else
  175.             fullname = (char *) alias; /* Use original information     */
  176.       }
  177.    }
  178.    else {
  179.       ExtractAddress(buffer,fullname,TRUE);
  180.       if (strlen(buffer) == 0)      /* A list of users?              */
  181.       {                             /* Yes --> Do recursive call     */
  182.          char *current = buffer;    /* Current token being processed */
  183.          char *next = NULL;         /* Next token to process         */
  184.  
  185.          strcpy(buffer,fullname);
  186.  
  187.          do {
  188.             current = strtok(current,",\t "); /* Get next alias to process */
  189.             next    = strtok(NULL,"");    /* Also save rest of list    */
  190.             header  = ExplodeAlias( header , current, stream, resent);
  191.                                           /* Get alias, including sub-list */
  192.             current  = next;
  193.          } while ( next != NULL );        /* Until no more tokens exist */
  194.  
  195.          return header;                   /* Have written header, return  */
  196.  
  197.       } /* if */
  198.    } /* else */
  199.  
  200.    if (strpbrk(fullname,"!@") == nil(char))
  201.    {
  202.       sprintf(buffer,"%s@%s", fullname , E_fdomain);
  203.                               /* Local address                    */
  204.       fullname = buffer;      /* Write out the formatted address  */
  205.    }
  206.  
  207.    PutHead(header, fullname, stream, resent);
  208.                               /* Remote address                   */
  209.    return "";                 /* Make header empty string for
  210.                                  next caller                      */
  211. } /* ExplodeAlias */
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*    A p p e n d _ S i g n a t u r e                                 */
  215. /*                                                                    */
  216. /*    Append the signature file to the specified mailbag file         */
  217. /*                                                                    */
  218. /*    [Broke this code out from Send_Mail to support the ~a mail      */
  219. /*    subcommand]                                                     */
  220. /*                                                                    */
  221. /*    Returns:  0 on success, 1 if signature file not found           */
  222. /*--------------------------------------------------------------------*/
  223.  
  224. static boolean Append_Signature(FILE *mailbag_fp ,
  225.                      const boolean alternate)
  226. {
  227.    FILE *sigfp;
  228.    char *sig;
  229.    char sigfile[FILENAME_MAX];
  230.    char buf[BUFSIZ];
  231.  
  232.    sig = alternate ? E_altsignature : E_signature;
  233.  
  234.    if(sig != nil(char)) {
  235.       mkfilename(sigfile, E_homedir, sig);
  236.       printmsg(4, "Append_Signature: signature file %s", sigfile);
  237.       if ((sigfp = FOPEN(sigfile, "r",TEXT_MODE)) != nil(FILE)) {
  238.          fputs("-- \n", mailbag_fp);
  239.          while (fgets(buf, BUFSIZ, sigfp) != nil(char))
  240.             fputs(buf, mailbag_fp);
  241.          fclose(sigfp);
  242.          return(0);
  243.       }
  244.       else {
  245.          printmsg(0, "Signature file \"%s\" doesn't exist!\n", sigfile);
  246.          return(1);
  247.       }
  248.    }
  249.    return(0);
  250. }  /* Append_Signature */
  251.  
  252. /*--------------------------------------------------------------------*/
  253. /*    S e n d _ M a i l                                               */
  254. /*                                                                    */
  255. /*    Send text in a mailbag file to address(es) specified by line.   */
  256. /*--------------------------------------------------------------------*/
  257.  
  258. boolean Send_Mail(FILE *datain,
  259.                int argc,
  260.                char *argv[],
  261.                char *subject,
  262.                const boolean resent)
  263. {
  264.    int argx = 0;
  265.    char buf[LSIZE];
  266.    char *header    = "To:";
  267.    char *CcHeader  = "Cc:";
  268.    char *BccHeader = "Bcc:";
  269.    char *pipename  = mktempname(NULL, "TMP");
  270.    FILE *stream = FOPEN(pipename , "w",TEXT_MODE);
  271.    int status;
  272.  
  273. /*--------------------------------------------------------------------*/
  274. /*                     Verify our workfile opened                     */
  275. /*--------------------------------------------------------------------*/
  276.  
  277.    if ( stream == NULL )
  278.    {
  279.       printerr(pipename);
  280.       free(pipename);
  281.       return FALSE;
  282.    }
  283.  
  284. /*--------------------------------------------------------------------*/
  285. /*    Add the boilerplate the front:                                  */
  286. /*                                                                    */
  287. /*       Date, From, Organization, and Reply-To                       */
  288. /*--------------------------------------------------------------------*/
  289.  
  290.    PutHead("Date:", arpadate() , stream, resent);
  291.  
  292.    if (bflag[F_BANG])
  293.       sprintf(buf, "(%s) %s!%s", E_name, E_fdomain, E_mailbox );
  294.    else
  295.       sprintf(buf, "\"%s\" <%s@%s>", E_name, E_mailbox, E_fdomain );
  296.    PutHead("From:", buf, stream , resent);
  297.  
  298.    if (E_organization != NULL )
  299.       PutHead("Organization:", E_organization, stream, resent );
  300.  
  301.    if (E_replyto != NULL )
  302.    {
  303.       if (strpbrk(E_replyto,"!@") == nil(char))
  304.          sprintf(buf,"\"%s\" <%s@%s>", E_name, E_replyto , E_fdomain);
  305.       else
  306.          sprintf(buf,"\"%s\" <%s>", E_name, E_replyto);
  307.       PutHead("Reply-To:", buf, stream, resent );
  308.    }
  309.  
  310. /*--------------------------------------------------------------------*/
  311. /*                      Write the addressees out                      */
  312. /*--------------------------------------------------------------------*/
  313.  
  314.    for (argx = 0 ; argx < argc; argx++ )
  315.    {
  316.       if (equal(argv[argx],"-c"))
  317.       {
  318.          header = CcHeader;
  319.          CcHeader = "";
  320.       } /* if */
  321.       else if (equal(argv[argx],"-b"))
  322.       {
  323.          header = BccHeader;
  324.          CcHeader = BccHeader = "";
  325.       } /* if else */
  326.       else
  327.          header = ExplodeAlias( header , argv[argx], stream, resent);
  328.    } /* for */
  329.  
  330. /*--------------------------------------------------------------------*/
  331. /*                  Prompt for carbon copies, if any                  */
  332. /*--------------------------------------------------------------------*/
  333.  
  334.    if ( bflag[F_ASKCC] && Is_Console(stdin) &&
  335.         Console_fgets(buf,LSIZE,"Cc: "))
  336.    {
  337.       char *current = buf;
  338.       header = CcHeader;
  339.       CcHeader = "";
  340.       printmsg(4,"CC buffer: %s",current);
  341.  
  342.       while ((current != NULL) &&
  343.              (current = strtok(current,",\t\n ")) != NULL)
  344.       {
  345.          char *next  =  strtok(NULL,"");
  346.          if (equal(current,"-b"))
  347.          {
  348.             header = BccHeader;
  349.             CcHeader = BccHeader = "";
  350.          } /* if */
  351.          else
  352.             header = ExplodeAlias( header, current, stream, resent);
  353.          current = next;
  354.       } /* while */
  355.    }  /* If Console_fgets() */
  356.  
  357. /*--------------------------------------------------------------------*/
  358. /*                     Handle the subject, if any                     */
  359. /*--------------------------------------------------------------------*/
  360.  
  361.    if (subject != NULL)
  362.       PutHead("Subject:",subject, stream, resent);
  363.    PutHead(NULL, "", stream, resent);  /* Terminate the header file   */
  364.  
  365. /*--------------------------------------------------------------------*/
  366. /*                    Copy the body of the message                    */
  367. /*--------------------------------------------------------------------*/
  368.  
  369.    while (fgets(buf, LSIZE, datain) != nil(char))
  370.    {
  371.       int result = fputs(buf, stream );
  372.       if (result == EOF)
  373.       {
  374.          printerr( pipename );
  375.          panic();
  376.       } /* if */
  377.       if (buf[strlen(buf)-1] != '\n')
  378.             fputc('\n', stream);
  379.    } /* while */
  380.  
  381.    if (!feof(datain))
  382.    {
  383.       printerr("Send_Mail:");
  384.       panic();
  385.    } /* if */
  386.  
  387.    if (datain != stdin)
  388.       fclose(datain);
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*    Append user's primary signature file, if autosign option on     */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.    if ( bflag[F_AUTOSIGN] )
  395.       Append_Signature(stream, FALSE);
  396.  
  397.    fclose(stream);
  398.  
  399. /*--------------------------------------------------------------------*/
  400. /*                  Invoke the mail delivery program                  */
  401. /*--------------------------------------------------------------------*/
  402.  
  403.  
  404.    sprintf(buf, "-t -f %s", pipename);
  405.    status = execute(RMAIL, buf, NULL, NULL, TRUE, FALSE );
  406.  
  407.    if ( status < 0 )
  408.    {
  409.       printerr( RMAIL );
  410.       printmsg(0,"Unable to execute rmail; mail not delivered.");
  411.    }
  412.    else if ( status > 0 )
  413.       printmsg(0,
  414.          "rmail returned non-zero status; delivery may be incomplete.");
  415.  
  416. /*--------------------------------------------------------------------*/
  417. /*               Log a copy of the mail for the sender                */
  418. /*--------------------------------------------------------------------*/
  419.  
  420.    if (bflag[F_SAVERESENT] || ! resent)
  421.       CopyOut(pipename);
  422.  
  423. /*--------------------------------------------------------------------*/
  424. /*                   Clean up and return to caller                    */
  425. /*--------------------------------------------------------------------*/
  426.  
  427.    remove(pipename);
  428.    free(pipename);
  429.    return (status == 0 );
  430.  
  431. } /*Send_Mail*/
  432.  
  433. /*--------------------------------------------------------------------*/
  434. /*    C o p y O u t                                                   */
  435. /*                                                                    */
  436. /*    Save copy of outgoing mail, if desired                          */
  437. /*--------------------------------------------------------------------*/
  438.  
  439. static void CopyOut( const char* input)
  440. {
  441.    FILE *datain;
  442.    FILE *dataout;
  443.    char buf[BUFSIZ];
  444.    char outbox[FILENAME_MAX];
  445.  
  446.    if (E_filesent == NULL)
  447.       return;
  448.  
  449.    strcpy( outbox, E_filesent);
  450.    expand_path( outbox, E_homedir, E_homedir, E_mailext );
  451.  
  452.    datain = FOPEN( input, "r",TEXT_MODE);
  453.  
  454.    if (datain == NULL )
  455.    {
  456.       printerr(input);
  457.       panic();
  458.    } /* if */
  459.  
  460.    dataout = FOPEN( outbox, "a",TEXT_MODE);
  461.    if (dataout == NULL )
  462.    {
  463.       printerr( outbox );
  464.       panic();
  465.    } /* if */
  466.  
  467.    fputs(MESSAGESEP,dataout);
  468.  
  469.    while (fgets(buf, BUFSIZ, datain) != nil(char))
  470.    {
  471.       int result = fputs(buf, dataout);
  472.       if (result == EOF)
  473.       {
  474.          printerr( outbox );
  475.          panic();
  476.       } /* if */
  477.    } /* while */
  478.  
  479.    if (!feof(datain))
  480.    {
  481.       printerr(input);
  482.       panic();
  483.    } /* if */
  484.  
  485.    fclose(datain);
  486.    fclose(dataout);
  487. } /* CopyOut */
  488.  
  489. /*--------------------------------------------------------------------*/
  490. /* P u t H e a d                                                      */
  491. /*                                                                    */
  492. /* Write one line of an RFC-822 header                                */
  493. /*--------------------------------------------------------------------*/
  494.  
  495.  static void PutHead( const char *label,
  496.                       const char *operand,
  497.                       FILE *stream,
  498.                       const boolean resent)
  499.  {
  500.    static boolean terminate = TRUE;
  501.                               /* If previous line was terminated     */
  502.  
  503.    if (label == NULL )        /* Terminate call?                     */
  504.    {                          /* Yes --> Reset Flag and return       */
  505.       fputc('\n', stream);    /* Terminate the current line          */
  506.       if (!resent)
  507.          fputc('\n', stream); /* Terminate the header file           */
  508.       terminate = TRUE;
  509.       return;
  510.    } /* if */
  511.  
  512.    if (strlen(label))         /* First line of a header?             */
  513.    {
  514.       if (!terminate)         /* Terminate previous line?            */
  515.          fputc('\n', stream);
  516.       if (resent)
  517.          fprintf(stream,"Resent-%s %s",label, operand);
  518.       else
  519.          fprintf(stream,"%-10s %s",label, operand);
  520.       terminate = FALSE;          /* Flag that we did not end file   */
  521.    } /* if */
  522.    else                       /* Continuing line                     */
  523.       fprintf(stream,",\n%-10s %s",label, operand);
  524.  } /* PutHead */
  525.  
  526. /*--------------------------------------------------------------------*/
  527. /*    C o l l e c t _ M a i l                                         */
  528. /*                                                                    */
  529. /*    Create mailbox file for delivery                                */
  530. /*--------------------------------------------------------------------*/
  531.  
  532. boolean Collect_Mail(FILE *stream,
  533.                   int argc,
  534.                   char **argv,
  535.                   const int current_msg,
  536.                   const boolean reply)
  537. {
  538.    boolean editonly = FALSE;
  539.    char Subuffer[LSIZE];
  540.    char *subject = NULL;
  541.    char *tmailbag;
  542.    int  c;                    /* Really a 'char', but who cares?     */
  543.    boolean done = FALSE;
  544.    FILE  *fmailbag;
  545.  
  546.    if ( argc < (equal(argv[0], "-s" ) ? 3 : 1 ))
  547.    {
  548.       printmsg(0,"Cannot send mail, no addressees provided" );
  549.       return FALSE;           /* Actually doesn't mean anything      */
  550.    } /* if */
  551.  
  552. /*--------------------------------------------------------------------*/
  553. /*      Determine if we are running interactively; if not, just       */
  554. /*         pass the input stream to Send_Mail for processing          */
  555. /*--------------------------------------------------------------------*/
  556.  
  557.    if (!Is_Console(stream))
  558.    {
  559.       if ( equal(argv[0], "-s" ) )
  560.          return Send_Mail( stream, argc-2, argv+2, argv[1], FALSE);
  561.       else
  562.          return Send_Mail( stream , argc , argv, NULL , FALSE);
  563.    } /* if */
  564.  
  565. /*--------------------------------------------------------------------*/
  566. /*    We are running interactively; create a determine the name of    */
  567. /*                        our work file to be.                        */
  568. /*--------------------------------------------------------------------*/
  569.  
  570.    *Subuffer = '\0';          /* Assume no subject */
  571.    tmailbag = mktempname( NULL, "TXT");
  572.  
  573. /*--------------------------------------------------------------------*/
  574. /*         Determine if we should go straight into the editor         */
  575. /*--------------------------------------------------------------------*/
  576.  
  577.    editonly = bflag[F_AUTOEDIT] && (E_editor != NULL);
  578.  
  579.    if ( equal(argv[0],"-s"))     /* Any subject specified?           */
  580.    {
  581.       strcpy( Subuffer , argv[1] ); /* Save the subject for later    */
  582.       argv += 2;                 /* Skip over it in argument list    */
  583.       argc -= 2;                 /* Giving us fewer args left        */
  584.    }
  585.    else {                        /* No --> Prompt for one            */
  586.       if(Console_fgets(Subuffer,LSIZE,"Subject: "))
  587.       {
  588.          if (Subuffer[strlen(Subuffer) - 1 ] == '\n')
  589.             Subuffer[strlen(Subuffer)-1] = '\0';   /* End the subject */
  590.       }  /* If Console_fgets() */
  591.    } /* if ( equal(argv[0],"-s")) */
  592.  
  593. /*--------------------------------------------------------------------*/
  594. /*      Copy a message from the original input to temporary file      */
  595. /*--------------------------------------------------------------------*/
  596.  
  597.    fmailbag = FOPEN(tmailbag, "w",TEXT_MODE);
  598.    if (fmailbag == NULL )
  599.    {
  600.       printerr( tmailbag );
  601.       panic();
  602.    }
  603.  
  604. /*--------------------------------------------------------------------*/
  605. /*               Include incoming message if requested                */
  606. /*--------------------------------------------------------------------*/
  607.  
  608.    if ( bflag[F_AUTOINCLUDE] && reply)
  609.    {
  610.        CopyMsg(current_msg, fmailbag, fromheader , TRUE);
  611.        fprintf(stdout, "Message %d Included\n", current_msg+1);
  612.    } /* if ( bflag[F_AUTOINCLUDE] && reply) */
  613.  
  614. /*--------------------------------------------------------------------*/
  615. /*                     Edit the file if requested                     */
  616. /*--------------------------------------------------------------------*/
  617.  
  618.    if (editonly)              /* Enter editor immediately?     ahd   */
  619.    {                          /* Yes --> Go to it                    */
  620.       fclose(fmailbag);
  621.       Invoke(E_editor, tmailbag, bflag[F_NEWEDITORSESSION] );
  622.    } /* if */
  623.    else {                     /* No  --> prompt for data       ahd   */
  624.       Prompt_Input( tmailbag , fmailbag , Subuffer, current_msg );
  625.       fclose(fmailbag);
  626.    } /*else */
  627.  
  628.  
  629.    do {
  630.       fputs("\nAbort, Continue, Edit, List, or Send? ",stdout);
  631.       c     = Get_One();             /* adaptation for QuickC */  /* pdm */
  632.       switch (tolower( c ))
  633.       {
  634.          case 'c':
  635.             puts("Continue");
  636.             fmailbag = FOPEN(tmailbag, "a",TEXT_MODE);
  637.             Prompt_Input( tmailbag , fmailbag , Subuffer, current_msg );
  638.  
  639. #if defined(_Windows)
  640.  
  641. /*--------------------------------------------------------------------*/
  642. /*            Prompt_Input() comes back with EOF on stdin!            */
  643. /*--------------------------------------------------------------------*/
  644.  
  645.             rewind(stdin);
  646. #endif
  647.             fclose(fmailbag);
  648.             break;
  649.  
  650.          case 'l':
  651.             puts("List");
  652.             Sub_Pager(tmailbag, islower(c) );
  653.             break;
  654.  
  655.          case 's':
  656.             puts("Send");
  657.             fmailbag = FOPEN(tmailbag, "r",TEXT_MODE);
  658.             if (fmailbag == NULL )
  659.             {
  660.                printerr(tmailbag);
  661.                panic();
  662.             }
  663.             if ( strlen( Subuffer ))
  664.                subject = Subuffer;
  665.             Send_Mail(fmailbag, argc, argv, subject, FALSE);
  666.             done = TRUE;
  667.             break;
  668.  
  669.          case 'e':
  670.             puts("Edit");
  671.             Invoke(E_editor, tmailbag, bflag[F_NEWEDITORSESSION] );
  672.             break;
  673.  
  674.          case 'a':
  675.             fputs("Abort\nAre you sure? ", stdout);
  676.             safeflush();
  677.             c = Get_One();             /* for QuickC */          /* pdm */
  678.             switch (tolower(c)) {      /* unravel these two calls */
  679.             case 'y':
  680.                puts("Yes");
  681.                done = TRUE;
  682.                break;
  683.             default:
  684.                puts("No");
  685.             } /*switch*/
  686.             break;
  687.  
  688.          default:
  689.             puts("\n\aEnter A, C, E, L, or S.");
  690.             safeflush();
  691.             done = FALSE;
  692.       } /*switch*/
  693.    } while (!done);
  694.  
  695.    remove(tmailbag);
  696.    free(tmailbag);
  697.  
  698.    return TRUE;
  699. } /*Collect_Mail*/
  700.  
  701.  
  702. /*--------------------------------------------------------------------*/
  703. /*    P r o m p t _ I n p u t                                         */
  704. /*                                                                    */
  705. /*    Prompt for mail entry interactively.                            */
  706. /*--------------------------------------------------------------------*/
  707.  
  708. static void Prompt_Input( char *tmailbag,
  709.             FILE *fmailbag,
  710.             char *subject,
  711.             const int current_msg)
  712. {
  713.    char buf[LSIZE];
  714.  
  715.    printf("\nEnter message.  Enter ~? for help.  End input with %s\n",
  716.           bflag[ F_DOT ] ?  "a period (.)" :
  717.          "end-of-file (Control-Z)");
  718.    for ( ; ; )
  719.    {
  720.       if (Console_fgets(buf, LSIZE, "? "))
  721.       {
  722.          if (bflag[F_DOT] && equal(buf,".\n"))
  723.             break;
  724.          else if (Subcommand( buf, fmailbag, tmailbag, subject, current_msg) )
  725.             continue;      /*Don't write line out if subcommand   */
  726.       } /* if */
  727.       else
  728.          break;            /* Exit loop if end of file            */
  729.  
  730.       if (fputs(buf, fmailbag) == EOF )
  731.       {
  732.          printerr( tmailbag );
  733.          panic();
  734.       } /* if (fputs(buf, fmailbag) == EOF ) */
  735.  
  736.       if (buf[strlen(buf)-1] != '\n')
  737.          fputc('\n', fmailbag);
  738.    } /* for */
  739. } /* Prompt_Input */
  740.  
  741. /*--------------------------------------------------------------------*/
  742. /*    S u b c o m m a n d                                             */
  743. /*                                                                    */
  744. /*    Handle tilde (~) subcommands for Interactive mail               */
  745. /*--------------------------------------------------------------------*/
  746.  
  747. static boolean Subcommand( char *buf,
  748.                            FILE *fmailbag,
  749.                            char *tmailbag,
  750.                            char *subject,
  751.                            const int current_msg)
  752. {
  753.    int message;
  754.    char fname[FILENAME_MAX];
  755.    char *token;
  756.    FILE *stream;
  757.  
  758.    if(*buf == '~')        /* Handle mail subcommands  pdm */
  759.    {
  760.       switch(buf[1])
  761.       {
  762.  
  763. /*--------------------------------------------------------------------*/
  764. /*                     Treat as normal data line                      */
  765. /*--------------------------------------------------------------------*/
  766.  
  767.          case '~':
  768.             memmove( buf, buf + 1, strlen( buf + 1 ));
  769.             return FALSE;        /* Treat as normal line              */
  770.  
  771. /*--------------------------------------------------------------------*/
  772. /*              Put signature file into current message               */
  773. /*--------------------------------------------------------------------*/
  774.  
  775.          case 'a':
  776.          case 'A':
  777.             Append_Signature(fmailbag, isupper( buf[1] ));
  778.             fputs("(continue)\n", stdout);
  779.             break;
  780.  
  781. /*--------------------------------------------------------------------*/
  782. /*                       Edit outgoing message                        */
  783. /*--------------------------------------------------------------------*/
  784.  
  785.          case 'v':            /* UNIX allows 'v'isual editor         */
  786.          case 'e':
  787.             /* invoke editor with current msg */
  788.             fclose(fmailbag);
  789.             Invoke(E_editor, tmailbag, bflag[F_NEWEDITORSESSION] );
  790.             fmailbag = FOPEN(tmailbag, "a",TEXT_MODE);
  791.             fputs("(continue)\n", stdout);
  792.             break;
  793.  
  794. /*--------------------------------------------------------------------*/
  795. /*                 Include any letter in this message                 */
  796. /*--------------------------------------------------------------------*/
  797.  
  798.          case 'f':
  799.          case 'F':
  800.          case 'i':
  801.          case 'I':
  802.          case 'm':
  803.          case 'M':
  804.             if (fmailbox == NULL)
  805.                puts("Mailbox not accessible!");
  806.             else {
  807.                int *item_list;
  808.                int next_item = PushItemList( &item_list );
  809.                boolean first_pass = TRUE;
  810.  
  811.                token = GetString( &buf[2] );
  812.  
  813.                if (SelectItems( &token, current_msg, LETTER_OP ))
  814.                while( Get_Operand( &message, &token, LETTER_OP, first_pass))
  815.                {
  816.                   CopyMsg( message , fmailbag,
  817.                            islower(buf[1]) ? fromheader : noseperator ,
  818.                            tolower(buf[1]) != 'f');
  819.                   fprintf(stdout, "Message %d included\n", message + 1);
  820.                   first_pass = FALSE;
  821.                } /* while */
  822.  
  823.                PopItemList( item_list, next_item );
  824.             } /* else */
  825.             break;
  826.  
  827. /*--------------------------------------------------------------------*/
  828. /*                       Print current message                        */
  829. /*--------------------------------------------------------------------*/
  830.  
  831.          case 'p':
  832.          case 'P':
  833.             fclose(fmailbag);
  834.             Sub_Pager(tmailbag, islower(buf[1]) );
  835.             fmailbag = FOPEN(tmailbag, "a",TEXT_MODE);
  836.             fputs("(continue)\n", stdout);
  837.             break;
  838.  
  839. /*--------------------------------------------------------------------*/
  840. /*                           Include a file                           */
  841. /*--------------------------------------------------------------------*/
  842.  
  843.          case 'r':
  844.             token = strtok( &buf[2], " \t\n");
  845.             if ( token == NULL )
  846.             {
  847.                printf("Need a file name for this command!\n");
  848.                break;
  849.             }
  850.             strcpy( fname, token );
  851.             if ( expand_path( fname, NULL, E_homedir , NULL) == NULL )
  852.                break;
  853.             stream = FOPEN( fname, "r",TEXT_MODE);
  854.             if (stream == NULL )
  855.             {
  856.                printerr(fname);
  857.                break;
  858.             }
  859.             else while( fgets( buf, LSIZE, stream ))
  860.             {
  861.                fputs( buf, fmailbag);
  862.                if ferror( fmailbag )
  863.                {
  864.                   printerr( tmailbag);
  865.                   break;
  866.                } /* if */
  867.             } /* else while */
  868.             if (ferror( stream ) )
  869.             {
  870.                printerr( fname );
  871.                clearerr( stream );
  872.             } /* if */
  873.             fclose( stream );
  874.             fputs("(continue)\n", stdout);
  875.             break;
  876.  
  877.  
  878. /*--------------------------------------------------------------------*/
  879. /*                        Change mail subject                         */
  880. /*--------------------------------------------------------------------*/
  881.  
  882.          case 's':
  883.             token = GetString( &buf[2] );
  884.             if ( token != NULL )
  885.             {
  886.                strcpy( subject, token );
  887.             }
  888.             else
  889.                printf("No new subject, command ignored\n");
  890.             printf("Subject: %s\n",subject);
  891.             break;
  892.  
  893. /*--------------------------------------------------------------------*/
  894. /*                                Help                                */
  895. /*--------------------------------------------------------------------*/
  896.  
  897.          case '?':
  898.          {
  899.             mkfilename(fname, E_confdir, "tilde.hlp");
  900.             Sub_Pager( fname, TRUE );
  901.             break;
  902.          }
  903.  
  904. /*--------------------------------------------------------------------*/
  905. /*                             A subshell                             */
  906. /*--------------------------------------------------------------------*/
  907.  
  908.          case '!':
  909.             token = strtok( &buf[2], "\n");
  910.             subshell( token );
  911.             break;
  912.  
  913. /*--------------------------------------------------------------------*/
  914. /*                     Pipe mail through a filter                     */
  915. /*--------------------------------------------------------------------*/
  916.  
  917.          case '|':
  918.             fclose( fmailbag );
  919.             filter( tmailbag, &buf[2] );
  920.             fmailbag = FOPEN(tmailbag, "a",TEXT_MODE);
  921.             fputs("(continue)\n", stdout);
  922.             break;
  923.  
  924. /*--------------------------------------------------------------------*/
  925. /*                          Invalid command                           */
  926. /*--------------------------------------------------------------------*/
  927.  
  928.          default:
  929.             fputs("Unknown mail subcommand, ~? for help.\n",
  930.                   stdout);
  931.             break;
  932.       } /* switch */
  933.  
  934.       return TRUE;
  935.    } /* if */
  936.    else
  937.       return FALSE;           /* It wasn't a sub-command             */
  938.  
  939. } /*SubCommand*/
  940.  
  941. /*--------------------------------------------------------------------*/
  942. /*    f i l t e r                                                     */
  943. /*                                                                    */
  944. /*    Filter the next of an outgoing program into the output mail     */
  945. /*--------------------------------------------------------------------*/
  946.  
  947. static void filter( char *tmailbag, char *command)
  948. {
  949.  
  950.    char pipename[FILENAME_MAX];
  951.    struct stat statbuf;
  952.    int    result = 0;
  953.  
  954.    command = GetString( command );
  955.  
  956.    if ( command == NULL )
  957.    {
  958.       printf("No command given for filter");
  959.       return;
  960.    }
  961.  
  962. /*--------------------------------------------------------------------*/
  963. /*   Set up our standard input and standard output for the command    */
  964. /*--------------------------------------------------------------------*/
  965.  
  966.    mktempname(pipename, "TMP");
  967.  
  968. /*--------------------------------------------------------------------*/
  969. /*                          Run the command                           */
  970. /*--------------------------------------------------------------------*/
  971.  
  972.    result = executeCommand( command, tmailbag, pipename, TRUE, TRUE );
  973.  
  974.    if (result == -1)       /* Did spawn fail?            */
  975.          ;                 /* No operation               */
  976.    else if( stat( pipename, &statbuf) <0 )   /* Create output?    */
  977.    {
  978.       printf(0,"Cannot determine status of output %s",pipename);
  979.       printerr( pipename );
  980.    }
  981.    else if( statbuf.st_size == 0 )  /* Anything in the file?      */
  982.       printf("Output file %s is empty!\n", pipename);
  983.    else {                  /* Good output, replace input file     */
  984.       remove( tmailbag );
  985.       if (rename( pipename, tmailbag ))
  986.          printerr( pipename );
  987.    } /* else */
  988.  
  989. /*--------------------------------------------------------------------*/
  990. /*                   Clean up and return to caller                    */
  991. /*--------------------------------------------------------------------*/
  992.  
  993.    remove( pipename );
  994.  
  995. } /* filter */
  996.  
  997. /*--------------------------------------------------------------------*/
  998. /*    G e t S t r i n g                                               */
  999. /*                                                                    */
  1000. /*    Get non-whitespace in a string                                  */
  1001. /*--------------------------------------------------------------------*/
  1002.  
  1003. static char *GetString( char *input)
  1004. {
  1005.    char *end;
  1006.  
  1007. /*--------------------------------------------------------------------*/
  1008. /*                   Look for first data in string                    */
  1009. /*--------------------------------------------------------------------*/
  1010.  
  1011.    while( *input && !isgraph( *input ))
  1012.       input++ ;
  1013.  
  1014. /*--------------------------------------------------------------------*/
  1015. /*   If no input or all blanks, return NULL to denote empty string    */
  1016. /*--------------------------------------------------------------------*/
  1017.  
  1018.    if (*input == '\0')
  1019.       return NULL ;
  1020.  
  1021. /*--------------------------------------------------------------------*/
  1022. /*                Delete whitespace from end of string                */
  1023. /*--------------------------------------------------------------------*/
  1024.  
  1025.    end = input + strlen( input ) - 1;
  1026.  
  1027.    while (!isgraph(*end))
  1028.       end--;
  1029.  
  1030.    end[1] = '\0';
  1031.  
  1032. /*--------------------------------------------------------------------*/
  1033. /*                 Return beginning of string to caller               */
  1034. /*--------------------------------------------------------------------*/
  1035.  
  1036.    return input;
  1037.  
  1038. } /* GetString */
  1039.