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

  1. /*--------------------------------------------------------------------*/
  2. /*    m a i l l i b . c                                               */
  3. /*                                                                    */
  4. /*    Mail user agent subroutine library 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: maillib.c 1.9 1993/11/13 17:43:26 ahd Exp $
  21.  *
  22.  *    $Log: maillib.c $
  23.  * Revision 1.9  1993/11/13  17:43:26  ahd
  24.  * Noramalize external command processing
  25.  *
  26.  * Revision 1.8  1993/10/12  01:30:23  ahd
  27.  * Normalize comments to PL/I style
  28.  *
  29.  * Revision 1.7  1993/10/09  20:16:12  rhg
  30.  * ANSIfy the source
  31.  *
  32.  * Revision 1.6  1993/09/20  04:41:54  ahd
  33.  * OS/2 2.x support
  34.  *
  35.  * Revision 1.5  1993/07/31  16:26:01  ahd
  36.  * Changes in support of Robert Denny's Windows support
  37.  *
  38.  * Revision 1.4  1993/06/13  14:06:00  ahd
  39.  * Add precedence to the standard ignore list
  40.  *
  41.  * Revision 1.3  1993/04/11  00:33:05  ahd
  42.  * Global edits for year, TEXT, etc.
  43.  *
  44.  * Revision 1.2  1992/11/27  14:36:10  ahd
  45.  * Use scrsize() for screen size
  46.  *
  47.  *       3 May 90 Create from mail.c
  48.  *       16 Jun 90:  Added support for mail (~) subcommands      pdm
  49.  *                   chgd calling seq of Collect_Mail to support
  50.  *                         above
  51.  *                   chges to CopyMsg to support ~i subcmd
  52.  *                   mods to SendMail to support autosign option
  53.  *                   broke out signature append code to seperate fn
  54.  *                   added support for alternate signature file
  55.  */
  56.  
  57. /*--------------------------------------------------------------------*/
  58. /*                        System include files                        */
  59. /*--------------------------------------------------------------------*/
  60.  
  61. #include <ctype.h>
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65.  
  66. /*--------------------------------------------------------------------*/
  67. /*                    UUPC/extended include files                     */
  68. /*--------------------------------------------------------------------*/
  69.  
  70. #include "lib.h"
  71. #include "address.h"
  72. #include "hlib.h"
  73. #include "mlib.h"
  74. #include "alias.h"
  75. #include "mail.h"
  76. #include "maillib.h"
  77. #include "scrsize.h"
  78.  
  79. #define  INDENT "> "
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*       Local variables                                              */
  83. /*--------------------------------------------------------------------*/
  84.  
  85. static int PageCount = 0;
  86.  
  87. static char *ignorelist[] =  { "Message-ID:",
  88.                         "Received:",
  89.                         "Status: ",
  90.                         "X-Mailer: ",
  91.                         "From " ,
  92.                         "Precedence: " ,
  93.                         "Path: ",
  94.                         "Lines: ",
  95.                         "References: ",
  96.                         "" };
  97.  
  98. currentfile();                /* Define current file for panic()     */
  99.  
  100. /*--------------------------------------------------------------------*/
  101. /*    P a g e r                                                       */
  102. /*                                                                    */
  103. /*    Page through a message                                          */
  104. /*                                                                    */
  105. /*    There are hooks here to let the user use his/her own pager,     */
  106. /*    like LIST, MORE, or LESS.  We just write the message out to     */
  107. /*    a temporary file and invoke the appropriate external program    */
  108. /*    to do the browsing.                                             */
  109. /*--------------------------------------------------------------------*/
  110.  
  111. boolean Pager(const int msgnum,
  112.               boolean external,
  113.               copyopt received,
  114.               const boolean reset)
  115. {
  116.    long nextloc;
  117.    char *browse   = NULL;
  118.    char buf[BUFSIZ];
  119.    boolean exit  = FALSE;        /* Flag for PRE-MATURE exit   ahd   */
  120.    FILE *fmailbag;
  121.  
  122.    if (msgnum == -1)
  123.       return FALSE;
  124.  
  125.    if (bflag[F_PAGER])           /* User want pager option inverted? */
  126.       external = ! external;     /* Yes --> Do the inversion         */
  127.  
  128.    if (letters[msgnum].status < M_READ)
  129.       letters[msgnum].status = M_READ;
  130.  
  131.    if (external && (E_pager != nil(char)))
  132.    {
  133.       browse = mktempname( NULL,"TMP" );/* Get a temporary file name */
  134.  
  135.       if ((fmailbag = FOPEN(browse, "w",TEXT_MODE)) == nil(FILE))
  136.       {
  137.          printerr(browse);
  138.          printmsg(0,"Cannot open browse file %s",browse);
  139.          return FALSE;
  140.       } /* if */
  141.       CopyMsg(msgnum, fmailbag, received, FALSE);
  142.       fclose(fmailbag);
  143.  
  144.       Invoke(E_pager, browse, bflag[F_NEWPAGERSESSION]);
  145.       remove(browse);
  146.       free(browse);
  147.  
  148.    } /* if */
  149.    else {
  150.       fseek(fmailbox, letters[msgnum].adr , SEEK_SET);
  151.       nextloc = letters[msgnum + 1].adr;
  152.  
  153.       if ( reset )
  154.          ClearScreen();
  155.       else
  156.          PageLine("\n");
  157.  
  158.       sprintf(buf,"Mailbox item %d:\n",msgnum + 1);
  159.       PageLine(buf);
  160.       while (ftell(fmailbox) < nextloc && (!exit) &&
  161.          fgets(buf, BUFSIZ, fmailbox) != nil(char))
  162.       {
  163.          boolean print = TRUE;
  164.  
  165.          switch(received)
  166.          {
  167.             case nocontinue:
  168.                if ((*buf != '\n') && !isgraph(*buf)) {
  169.                   print = FALSE;
  170.                   break;
  171.                }
  172.                else
  173.                   received = noreceived;
  174.             case noreceived:
  175.             {
  176.                char entry = 0;
  177.                while ( strlen(ignorelist[entry]) && print )
  178.                {
  179.                   if (equalni(ignorelist[entry],
  180.                         buf,strlen(ignorelist[entry])))
  181.                   {
  182.                      print = FALSE;
  183.                      received = nocontinue;
  184.                   }
  185.                   else
  186.                      entry++;
  187.                } /* while */
  188.             } /* case noreceived */
  189.          } /* switch */
  190.          if (received != seperators)
  191.             if (equal(buf,"\n"))
  192.                received = seperators;
  193.  
  194.          if (print)
  195.             if (PageLine(buf))         /* Exit if the user hits Q    */
  196.                exit = TRUE;
  197.       } /* while */
  198.  
  199.       if (equal(buf,"\n") && (!exit))                 /* ahd   */
  200.          putchar('\n');                               /* ahd   */
  201.    } /* else */
  202.  
  203.    return ! exit;
  204. } /*Pager*/
  205.  
  206.  
  207. /*--------------------------------------------------------------------*/
  208. /*    S u b _ P a g e r                                               */
  209. /*       pager for the ~p mail subcommand                             */
  210. /*       page through a mail message currently being entered          */
  211. /*                                                                    */
  212. /*    Clone of the Pager function                                     */
  213. /*--------------------------------------------------------------------*/
  214.  
  215. void Sub_Pager(const char *tinput,
  216.                      boolean external )
  217. {
  218.    boolean exit  = FALSE;        /* Flag for PRE-MATURE exit   ahd   */
  219.  
  220.    if (bflag[ F_PAGER ])
  221.       external = ! external;
  222.  
  223.    if ( external && (E_pager != nil(char)) )
  224.       Invoke(E_pager, tinput, bflag[F_NEWPAGERSESSION]);
  225.    else {
  226.       FILE *finput;
  227.       char buf[BUFSIZ];
  228.       finput = FOPEN(tinput, "r",TEXT_MODE);
  229.       if (finput == NULL) {
  230.          printmsg(0,"Cannot open file %s for display",tinput);
  231.          printerr(tinput);
  232.          return;
  233.       }
  234.       PageReset();
  235.       ClearScreen();
  236.       while ( (!exit) && fgets(buf, BUFSIZ, finput) != nil(char))
  237.       {
  238.         if (PageLine(buf))         /* Exit if the user hits Q  */
  239.            exit = TRUE;
  240.       }
  241.       fclose(finput);
  242.    }
  243.  
  244. } /*Sub_Pager*/
  245.  
  246. /*--------------------------------------------------------------------*/
  247. /*    P a g e R e s e t                                               */
  248. /*                                                                    */
  249. /*    Reset page function to top of page                              */
  250. /*--------------------------------------------------------------------*/
  251.  
  252. void PageReset()
  253. {
  254.    PageCount = 0;
  255. } /*PageReset*/
  256.  
  257. /*--------------------------------------------------------------------*/
  258. /*    P a g e L i n e                                                 */
  259. /*                                                                    */
  260. /*    Print one line when paging through a file                       */
  261. /*--------------------------------------------------------------------*/
  262.  
  263. boolean PageLine(char *line)
  264. {
  265.  
  266.    int pagesize = scrsize() - 3;
  267.  
  268.    fputs(line, stdout);
  269.  
  270.    PageCount = PageCount + 1 + strlen(line) / 81; /* Handle long lines */
  271.  
  272.    if (PageCount > pagesize)
  273.    {
  274.       int c;
  275.       fputs("More?", stdout);
  276.       c = Get_One();
  277.  
  278.       switch (tolower(c))
  279.       {
  280.          case 'q':
  281.          case '\003':
  282.          case 'n':                        /* Because that's what I
  283.                                              keep Pressing           */
  284.          case 'x':
  285.             fputs("\rAborted.\n", stdout);
  286.             return TRUE;
  287.  
  288.          case 'd':
  289.             PageCount = pagesize / 2;     /* Half a Page More */
  290.             break;
  291.  
  292.          case '\r':
  293.             PageCount = pagesize;         /* Only print one line  */
  294.             break;
  295.  
  296.          default:
  297.             PageCount = 0;                /* Print full screen    */
  298.       }
  299.       fputs("\r      \r",stdout);
  300.    }
  301.  
  302.    return FALSE;
  303.  
  304. } /*PageLine*/
  305.  
  306. /*--------------------------------------------------------------------*/
  307. /*    C o p y M s g                                                   */
  308. /*                                                                    */
  309. /*    Copy a message                                                  */
  310. /*                                                                    */
  311. /*    Allows copying message with one or more of the options          */
  312. /*    specified in the copyopt data type.                             */
  313. /*--------------------------------------------------------------------*/
  314.  
  315. boolean CopyMsg(int msgnum, FILE *f, copyopt headers, boolean indent)
  316. {
  317.    long nextloc;
  318.    boolean print;
  319.    char buf[BUFSIZ];
  320.  
  321. /*--------------------------------------------------------------------*/
  322. /*                 Write a separator line, if needed                  */
  323. /*--------------------------------------------------------------------*/
  324.  
  325.    if (headers == seperators)
  326.    {
  327.       if (fputs(MESSAGESEP,f) == EOF)     /* Write out separator line  */
  328.       {
  329.          printerr("CopyMsg");
  330.          panic();
  331.       } /* if (fputs(MESSAGESEP,f) == EOF) */
  332.    } /* if (headers == seperators) */
  333.  
  334. /*--------------------------------------------------------------------*/
  335. /*             else add a one line from line, if desired              */
  336. /*--------------------------------------------------------------------*/
  337.  
  338.    else if (headers == fromheader )
  339.    {
  340.       register char *sp = buf;
  341.       headers = noheader;                 /* Do not print full header */
  342.       if (RetrieveLine(letters[msgnum].date, buf, LSIZE))
  343.       {
  344.          register char  *sp = buf;
  345.          while (!isspace(*sp))
  346.             sp++;
  347.          while (isspace(*sp))
  348.             sp++;
  349.          fprintf(f,"On %s,", sp );
  350.       } /* if */
  351.  
  352.       if (RetrieveLine(letters[msgnum].from, buf, BUFSIZ))
  353.       {
  354.          while (!isspace(*sp) && (*sp != '\0'))
  355.             sp++;
  356.          BuildAddress( buf, sp );
  357.       } /* if */
  358.       else
  359.          strcpy(buf,"you");   /* Wimp out without admitting it       */
  360.  
  361.       fprintf(f, " %s wrote:\n", buf) ;
  362.    } /* if (headers == fromheader ) */
  363.  
  364. /*--------------------------------------------------------------------*/
  365. /*              Now position to the front of the letter               */
  366. /*--------------------------------------------------------------------*/
  367.  
  368.    fseek(fmailbox, letters[msgnum].adr , SEEK_SET);
  369.    nextloc = letters[msgnum + 1].adr;
  370.  
  371.    while (ftell(fmailbox) < nextloc &&
  372.       fgets(buf, BUFSIZ, fmailbox) != nil(char)) {
  373.  
  374. /*--------------------------------------------------------------------*/
  375. /*               Determine if we should write the line                */
  376. /*--------------------------------------------------------------------*/
  377.  
  378.       print = TRUE;
  379.  
  380.       switch (headers)
  381.       {
  382.          case noheader:
  383.             print = FALSE;
  384.             break;
  385.  
  386.          case nocontinue:
  387.             if ((*buf != '\n') && !isgraph(*buf)) {
  388.                print = FALSE;
  389.                break;
  390.             }
  391.             else
  392.                headers = noreceived;
  393.                /* Fall through ... */
  394.          case noreceived:
  395.          {
  396.             char entry = 0;
  397.             while ( strlen(ignorelist[entry]) && print )
  398.             {
  399.                if (equalni(ignorelist[entry],buf,strlen(ignorelist[entry])))
  400.                {
  401.                   print = FALSE;
  402.                   headers = nocontinue;
  403.                }
  404.                else
  405.                   entry++;
  406.             }
  407.          } /* case noreceived */
  408.                /* Fall through */
  409.          case noseperator:
  410.          case seperators:
  411.             break;
  412.  
  413.          default:
  414.             printmsg(0,"CopyMsg: Bad header copy state of %d",headers);
  415.             panic();
  416.       } /* switch */
  417.  
  418. /*--------------------------------------------------------------------*/
  419. /*                 If we should print the line, do so                 */
  420. /*--------------------------------------------------------------------*/
  421.  
  422.       if (print)
  423.       {
  424.          if (indent)
  425.          {
  426.             if ( fputs(INDENT , f ) == EOF )
  427.             {
  428.                printerr( "CopyMsg" );
  429.                panic();
  430.             } /* if ( fputs(INDENT , f ) == EOF ) */
  431.          } /* if (indent) */
  432.  
  433.          if ( fputs(buf , f ) == EOF )
  434.          {
  435.             printerr( "CopyMsg" );
  436.             panic();
  437.          } /* if ( fputs(buf , f ) == EOF ) */
  438.  
  439.       } /* if (print) */
  440.  
  441. /*--------------------------------------------------------------------*/
  442. /*  If end of the header, print all data until the end of the input   */
  443. /*--------------------------------------------------------------------*/
  444.  
  445.       if ( (headers != seperators) && equal(buf, "\n") )
  446.          headers = seperators;
  447.  
  448.    } /*while*/
  449.  
  450.    return TRUE;
  451. } /*CopyMsg*/
  452.  
  453. /*--------------------------------------------------------------------*/
  454. /*    N u m e r i c                                                   */
  455. /*                                                                    */
  456. /*    Determine if a string is numeric.  Returns TRUE if string is    */
  457. /*    numeric, else FALSE.                                            */
  458. /*--------------------------------------------------------------------*/
  459.  
  460.  boolean Numeric( const char *number)
  461.  {
  462.    char *column = (char *) number;
  463.  
  464.    if (*column == '\0')
  465.       return FALSE;
  466.  
  467.    while( isdigit(*column) )  /* Scan to string end or 1st non-digit */
  468.       column++;
  469.  
  470.    return *column == '\0';    /* Success if whole string was made of
  471.                                  digits                              */
  472.  } /* Numeric */
  473.  
  474. /*--------------------------------------------------------------------*/
  475. /*    R e t r i e v e L i n e                                         */
  476. /*                                                                    */
  477. /*    Read a line from a mail header, if available                    */
  478. /*--------------------------------------------------------------------*/
  479.  
  480. boolean RetrieveLine(long adr, char *line, const size_t len)
  481. {
  482.    char *cp = line;
  483.    size_t count;
  484.  
  485.    *line = '\0';              /* Insure nothing to find              */
  486.    if (adr == MISSING)        /* No information to read?             */
  487.       return FALSE;           /* Report this to caller               */
  488.  
  489.    if (fseek(fmailbox, adr, SEEK_SET)) /* Position to data           */
  490.    {                          /* Have a problem?                     */
  491.       printerr("mailbox");    /* Yes --> Report and return           */
  492.       return FALSE;
  493.    }
  494.  
  495. /*--------------------------------------------------------------------*/
  496. /*                     Actually read the data in                      */
  497. /*--------------------------------------------------------------------*/
  498.  
  499.    count = fread(line, sizeof *line, len-1, fmailbox);
  500.  
  501.    if ((count < (len-1)) && ferror( fmailbox ))
  502.    {
  503.       printerr( "RetrieveLine");
  504.       return FALSE;
  505.    }
  506.  
  507.    line[count] = '\0';        /* Terminate the string read           */
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*    A field continues until a new field begins in column of the     */
  511. /*    next line or the header ends (an empty line); find the end      */
  512. /*    of the field, trimming extra white space from the beginning     */
  513. /*    of each line as we go                                           */
  514. /*--------------------------------------------------------------------*/
  515.  
  516.    while( (cp = strchr(cp , '\n')) != NULL )
  517.    {
  518.       if ((cp[1] == '\n') || !isspace(cp[1]))   /* End of field?     */
  519.          *cp = '\0';          /* Yes --> Terminate string            */
  520.       else {
  521.          char *next;
  522.  
  523.          *cp++ = ' ';         /* Convert line break to whitespace    */
  524.          next = ++cp;         /* Get first position of new line      */
  525.          while( isspace( *next ) )  /* Ignore leading white space    */
  526.             next++;
  527.  
  528.          memmove( cp , next , strlen(next) + 1 );
  529.                               /* Trim leading white space            */
  530.       } /* else */
  531.    } /* while */
  532.  
  533.    return TRUE;
  534.  
  535. } /*RetrieveLine*/
  536.  
  537. /*--------------------------------------------------------------------*/
  538. /*    R e t u r n A d d r e s s                                       */
  539. /*                                                                    */
  540. /*    Returns the user name (if available and requested) or           */
  541. /*    E-mail address of the user                                      */
  542. /*                                                                    */
  543. /*    Written by ahd 15 July 1989                                     */
  544. /*--------------------------------------------------------------------*/
  545.  
  546. void ReturnAddress(char *line, struct ldesc *ld)
  547. {
  548.    char buffer[BUFSIZ];
  549.  
  550.    if (!RetrieveLine(ld->from, buffer, BUFSIZ))
  551.                                           /* From: line available?   */
  552.       strcpy(line,"-- Unknown --");       /* No --> Return error     */
  553.    else {
  554.       char *begin = buffer;
  555.       while (!isspace(*begin) && (*begin != '\0'))
  556.          begin++;
  557.       if (strlen(begin))
  558.          ExtractName(line,begin);         /* Yes --> Return name     */
  559.       else
  560.          strcpy(line,"-- Invalid From: line --");
  561.    }
  562.  
  563.    return;
  564.  
  565. } /*ReturnAddress*/
  566.  
  567. /*--------------------------------------------------------------------*/
  568. /*    s a y o p t i o n s                                             */
  569. /*                                                                    */
  570. /*    Announce user options in effect                                 */
  571. /*--------------------------------------------------------------------*/
  572.  
  573. void sayoptions( FLAGTABLE *flags)
  574. {
  575.  
  576.    size_t subscript;
  577.    size_t used = 0;
  578.  
  579.    printf("\nThe following options are set:\n");
  580.  
  581.    for (subscript = 0; flags[subscript].sym != NULL; subscript++)
  582.    {
  583.          size_t width;
  584.  
  585.          if (flags[subscript].bits & B_GLOBAL)
  586.             continue;               /* Don't print system options */
  587.  
  588.          width = 1 + strlen( flags[subscript].sym ) +
  589.                  ( bflag[ flags[subscript].position ] ? 0 : 2 );
  590.  
  591.          used += width;
  592.          if ( subscript > 0 )
  593.          {
  594.             if ( used > 79 )
  595.             {
  596.                putchar('\n');
  597.                used = width;
  598.             } /* if ( used > 79 ) */
  599.             else
  600.                putchar(' ');
  601.          } /* if ( subscript > 0 ) */
  602.  
  603.          printf("%s%s",
  604.                bflag[ flags[subscript].position ] ? "" : "no" ,
  605.                flags[subscript].sym );
  606.  
  607.    } /* for */
  608.  
  609.    putchar('\n');
  610.  
  611. } /* sayoptions */
  612.