home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / uupc.lzh / uupc / mail.c < prev    next >
C/C++ Source or Header  |  1990-01-16  |  12KB  |  599 lines

  1. /*
  2.  *    mail
  3.  *
  4.  *    Amiga system mailer
  5.  *    This is the user interface for mail.  It supports a limited command
  6.  *    list and can display a list of messages waiting in the mailbox.
  7.  *
  8.  *    $Id: mail.c,v 1.2 90/01/16 10:26:32 crash Exp Locker: crash $
  9.  */
  10.  
  11. #ifndef lint
  12. static char RCSid[] = "$Id: mail.c,v 1.2 90/01/16 10:26:32 crash Exp Locker: crash $";
  13. #endif /* lint */
  14.  
  15. #define    EXIT    return
  16.  
  17. #include <stdio.h>
  18. #include "host.h"
  19.  
  20. extern char *index();
  21. extern char *rindex();
  22.  
  23. #ifdef MSDOS
  24. # define PC_FILENMS    1
  25. #endif
  26.  
  27. #ifdef AMIGA
  28. # define PC_FILENMS    1
  29. #endif
  30.  
  31. FILE *FOPEN();
  32. FILE *freopen();
  33.  
  34. int    debuglevel = 1;
  35.  
  36. #define OUT(x)        fprintf(stderr, x)
  37. #define LSIZE       256
  38.  
  39. #ifndef MAXNAMLEN
  40. # define MAXNAMLEN    255
  41. #endif
  42.  
  43. char    line[LSIZE];
  44. char    resp[LSIZE];
  45. char    mfilename[MAXNAMLEN+1];
  46.  
  47. struct ldesc {
  48.     int           delete;        /* status of this message */
  49.     long        adr;        /* address of From line */
  50.     long        date;        /* address of Date: line */
  51.     long        subject;    /* address of Subject: line */
  52.     long        from;        /* address of From: line */
  53.     long        size;        /* number of lines */
  54. };
  55.  
  56. #define MAXMSGS    300                    /* Maxmimum number of letters */
  57.  
  58. struct    ldesc letters[MAXMSGS];
  59. int       letternum   = 0;
  60. char       thefilename[MAXNAMLEN+1];
  61.  
  62. char       tmailbox[MAXNAMLEN+1];
  63. char     tmailbag[MAXNAMLEN+1];
  64.  
  65. FILE       *fmailbox;
  66. FILE     *rmailbox;
  67. FILE    *fmailbag;
  68.  
  69. int    error = 0;
  70. int    modified;
  71. int    printonly;
  72. int    PageCount = 0;
  73.  
  74. mailmain(argc, argv)
  75. int argc;
  76. char **argv;
  77. {
  78. #if 0            /* This is done by l_host.c before calling mailmain() */
  79.     HOSTINIT;
  80.     loadenv();
  81. #endif
  82.  
  83.     mkfilename( tmailbox, tempdir, "mailbox");
  84.     mkfilename( tmailbag, tempdir, "mailbag");
  85.     unlink( tmailbox );
  86.     if ( mailbox == (char *)NULL )
  87.         mailbox = "???";
  88.  
  89.     if (argc == 1 || (argv[1][0] == '-') && (argv[1][1] != 's'))
  90.         showmail (argc, argv );
  91.     else
  92.         lmail (argc, argv );
  93.  
  94.     finis();
  95. }
  96.  
  97. finis()
  98. {
  99.     if (fmailbag != (FILE *)NULL) fclose( fmailbag );
  100.     if (fmailbox != (FILE *)NULL) fclose( fmailbox );
  101.     unlink( tmailbox );
  102.     unlink( tmailbag );
  103.     EXIT( error );
  104. }
  105.  
  106. /*
  107.  *    sendmail
  108.  *    send message n to "line"
  109.  */
  110.  
  111. sendmail(n, line)
  112. int n;
  113. char *line;
  114. {
  115. #ifdef PC_FILENMS
  116.     FILE    *tmpfp, *tmp2fp;
  117. #endif
  118.     char     *argv[50];
  119.     int     argc;
  120.     char    buf[BUFSIZ];
  121.     long     bytes;
  122.  
  123.     bytes = letters[ n+1 ].adr - letters[ n ].adr;
  124.  
  125.     /* open a temporary file */
  126.     fmailbag = FOPEN( tmailbag, "w", 'b' );
  127.  
  128.     /* copy nth message to mailbag file */
  129.     fseek( fmailbox, letters[ n ].adr, 0 );
  130.     while( bytes > 0 && fgets( buf, sizeof(buf), fmailbox) ) {
  131.         fputs( buf, fmailbag  );
  132.         bytes -= strlen( buf );
  133.     }
  134.     fclose( fmailbag );
  135.  
  136.     /* use mailbag as stdin to mail delivery */
  137.     FILEMODE( 'b' );
  138.     if ( freopen( tmailbag, "r", stdin ) != (FILE *)NULL ) {
  139.         argc = getargs( line, argv );
  140.         lmail( argc, argv );
  141.     }
  142. #ifdef AMIGA
  143.     freopen( "*", "r", stdin );
  144. #else
  145.     freopen( device, "r", stdin );
  146. #endif
  147.  
  148.     /* get rid of mailbag */
  149.     unlink( tmailbag );
  150. }
  151.  
  152. invert( i )
  153. {
  154.     return( letternum-i-1 );
  155. }
  156.  
  157. showmail(argc, argv)
  158. int argc;
  159. char **argv;
  160. {
  161.     int flg, i, j, k, print;
  162.     char *p, *cp, *getnext();
  163.     long nextadr;
  164.     struct ldesc *letter;
  165.  
  166.     /* get mailbox file name */
  167.     mkfilename( mfilename, maildir, mailbox );
  168.  
  169.     /* parse arg's */
  170.     for (; argc > 1; argv++, argc--) {
  171.         if ( argv[1][0] == '-' ) {
  172.             switch (argv[1][1]) {
  173.             case 'f' :
  174.                 if (argc > 2) {
  175.                     if (argv[2][0] == '~')
  176.                         mkfilename( mfilename, maildir, argv[2]+1 );
  177.                     else
  178.                         strcpy( mfilename, argv[2] );
  179.                     argv++;
  180.                     argc--;
  181.                 }
  182.                 break;
  183.             case 'p' :
  184.                 printonly = TRUE;
  185.                 break;
  186.             default :
  187.                 fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
  188.                 finis();
  189.             }
  190.         } else
  191.             break;
  192.     }
  193.     /* open real mailbox file */
  194.     if (( rmailbox = FOPEN( mfilename, "r", 'b' ))  == (FILE *)NULL) {
  195.         fprintf( stdout, "No mail in %s.\n", mfilename );
  196.         return;
  197.     }
  198.     /* open up tmp mailbox file */
  199.     if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) {
  200.         fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox );
  201.         finis();
  202.     }
  203.     /*
  204.      *    Copy real mailbox file to tmp mailbox file.
  205.      *
  206.      *    During the copy, record the header information so it can
  207.      *    be displayed later.
  208.      */
  209.     letternum = 0;
  210.     nextadr = 0;
  211.     while (fgets(line, LSIZE, rmailbox)) {
  212.         fputs(line, fmailbox);
  213.         if ( strncmp( line, "From ", 5 ) == SAME ) {
  214.             letter          = &letters[letternum++];
  215.             letter->from    = -1L;
  216.             letter->subject = -1L;
  217.             letter->date    = -1L;
  218.             letter->adr     = nextadr;
  219.             letter->delete  = FALSE;
  220.             letter->size    = 0L;
  221.         } else if ( strncmp( line, "Date: ", 6 ) == SAME )
  222.             letter->date    = nextadr;
  223.         else if ( strncmp( line, "From: ", 6 ) == SAME )
  224.             letter->from    = nextadr;
  225.         else if ( strncmp( line, "Subject: ", 9 ) == SAME )
  226.             letter->subject = nextadr;
  227.         letter->size++;                    /* Count number of lines */
  228.         nextadr += strlen( line );        /* Keep track of seek position */
  229.     }
  230.     letters[letternum].adr = nextadr;    /* last plus 1 */
  231.  
  232.     /* close mailbox files */
  233.     fclose( rmailbox );
  234.     fclose( fmailbox );
  235.  
  236.     fmailbox = FOPEN( tmailbox, "r", 'b' );
  237.     modified = 0;
  238.     if (printonly) {
  239.         j = letternum;
  240.         while (j > 0)
  241.             pager(j--);
  242.         return;
  243.     }
  244.     printsub(-1);            /* Print the subject list */
  245.  
  246.     i = letternum-1;
  247.     while (TRUE) {
  248.         register char *inp = resp;
  249.  
  250.         if (i < 0) i = 0;
  251.         if (i >= letternum) i = letternum-1;
  252.         j = invert(i);
  253.  
  254.         fprintf(stdout, "%d ? ", j);
  255.         if (!fgets( inp, LSIZE, stdin)) break;
  256.         switch (*inp) {
  257.         default:
  258.             fprintf(stderr, "Usage\n");
  259.         case '?':
  260.             print = 0;
  261.             OUT("q\tquit\n");
  262.             OUT("x\texit\tmailbox restored\n");
  263.             OUT("p\tprint current message; also `RETURN'\n");
  264.             OUT("+\tprint next message; also `n'\n");
  265.             OUT("-\tprint last message; also `^'\n");
  266.             OUT("h\tprint subject header list; also `H'\n");
  267.             OUT("s[file]\tsave message to a file (default mbox)\n");
  268.             OUT("w[file]\t(same as `s' but without headers\n");
  269.             OUT("\t`file' may be absolute path or use ~ for $MAILDIR\n");
  270.             OUT("d\tdelete current message\n");
  271.             OUT("f user\tforward current message to `user'\n");
  272.             OUT("m user\tmail a message to `user'\n");
  273.             OUT("g num\tset current message; also `num'\n");
  274.             break;
  275.         case '+':
  276.         case 'n':
  277.             i-- ;
  278.             break;
  279.         case 'g':
  280.             i = invert(atoi(inp+1));
  281.             break;
  282.         case '0':
  283.         case '1':
  284.         case '2':
  285.         case '3':
  286.         case '4':
  287.         case '5':
  288.         case '6':
  289.         case '7':
  290.         case '8':
  291.         case '9':
  292.             i = invert(atoi(inp));
  293.             break;
  294.  
  295.         case 'x':
  296.             modified = 0;
  297.         case 'q':
  298.             goto donep;
  299.         case '\n':
  300.         case 'p':
  301.             pager( j );
  302.             break;
  303.         case '^':
  304.         case '-':
  305.             i++;
  306.             break;
  307.         case 'y':
  308.         case 'w':
  309.         case 's':
  310.             flg = 0;
  311.             k = *inp;
  312. #ifdef FJE
  313.             inp++;
  314.             while (isspace(*inp))
  315.                 inp++;
  316. #else
  317.             if (inp[1] != '\n' && inp[1] != ' ') {
  318.                 printf("illegal\n");
  319.                 flg++;
  320.                 print = 0;
  321.                 continue;
  322.             }
  323. #endif /* !FJE */
  324.             if (strlen(inp) < 2)
  325.                 strcat(inp, "~mbox");
  326.             for (p = inp; p = getnext(&cp, p); ) {
  327.                 if (*cp == '~')
  328.                     mkfilename(thefilename, maildir, ++cp);
  329.                 else
  330.                     strcpy(thefilename, cp);
  331.                 fprintf(stderr, "%s to %s\n",
  332.                     (k == 's') ? "Saving" : "Writing", thefilename);
  333.                 if ( !(fmailbag = FOPEN(thefilename, "a", 't')) ) {
  334.                     fprintf(stderr, "mail: cannot open %s\n", thefilename);
  335.                     flg++;
  336.                     continue;
  337.                 }
  338.                 copymsg(j, fmailbag, k == 'w');
  339.                 fclose( fmailbag );
  340.             }
  341.             if (flg)
  342.                 print = 0;
  343.             else {
  344.                 letters[j].delete = TRUE;
  345.                 modified++;
  346.                 i--;
  347.             }
  348.             break;
  349.         case 'm':
  350.             OUT("mail command not implemented yet!\n");
  351.             break;
  352.         case 'f':
  353.             flg = 0;
  354.             while (isspace(*inp))
  355.                 inp++;
  356.             if (!*inp) {
  357.                 printf("No user id to forward to!?\n");
  358.                 i++;
  359.                 continue;
  360.             }
  361.             sendmail(j, p);
  362.             if (flg)
  363.                 print = 0;
  364.             else {
  365.                 letters[j].delete = TRUE;
  366.                 modified++;
  367.                 i++;
  368.             }
  369.             break;
  370.  
  371.         case 'd':
  372.             letters[j].delete = TRUE;
  373.             modified++;
  374.             i--;
  375.             if (inp[1] == 'q')
  376.                 goto donep;
  377.             break;
  378.  
  379.         case 'h':
  380.             printsub( -1 );
  381.             break;
  382.  
  383.         case 'H':
  384.             printsub( i );
  385.             break;
  386.         }
  387.     }
  388. donep:
  389.     if (modified) copyback();
  390. }
  391.  
  392. readaline(adr, line)
  393. long adr;
  394. char *line;
  395. {
  396.     char     buf[132];
  397.     register char    *cp = buf;
  398.  
  399.     *line = '\0';
  400.     if (adr != -1L && !fseek(fmailbox, adr, 0) && fgets(cp, 132, fmailbox))
  401.         strcpy(line, cp);
  402.     if (cp = index(line, '\n'))
  403.         *cp = '\0';
  404. }
  405.  
  406. #if 0
  407. returnaddress()
  408. {
  409.     readaline( lp->from, line );
  410.     if (i = index(line, '<') && k = index(line, '>') && k > i) {
  411.         strncpy(from, line[i], k-i);
  412.         from[k] = '\0';
  413.     }
  414. }
  415. #endif
  416.  
  417. printsub( K )
  418. int K;
  419. {
  420.     static char from[132], subject[132], date[132], line[132];
  421.     register char    *sp, *dp, *lp, *tp;
  422.  
  423.     struct ldesc *ld;
  424.     int k, mink, maxk, j;
  425.  
  426.     pagereset();
  427.     if ( K == -1 ) {
  428.         maxk = letternum-1;
  429.         mink = 0;
  430.     } else
  431.         maxk = mink = K;
  432.  
  433.     sprintf(line, "%3s %6s %-20s %-35s Lines\n",
  434.                 "# ", "Date ", "From", "Subject");
  435.     pageline( line );
  436.     for (k = maxk; k >= mink; k--) {
  437.         j = invert(k);
  438.         ld = letters+j;
  439.  
  440.         (void) strcpy(from, "unknown");        /* default to "unknown" */
  441.         readaline(ld->from, line);
  442.         if (strlen(line)) {
  443.             /*
  444.              *    get first usable stuff after From:
  445.              */
  446.             sp = index(line, ':')+1;
  447.             /*
  448.              *    Is it "From: mailbox@site.domain (Proper Name)"?
  449.              */
  450.             if ( (tp = index(line, '(')) && (lp = index(tp, ')')) )
  451.                 sp = ++tp;
  452.             else
  453.                 /*
  454.                  *    or "From: Proper Name <mailbox@site.domain>"
  455.                  */
  456.                 lp = index( line, '<');
  457.  
  458.             if ( *lp == '<' || *lp == ')' )
  459.                 --lp;
  460.  
  461.             /* if we didn't get either of the last two, just grab line */
  462.             if (lp < sp || !lp)
  463.                 lp = line+strlen(line)-1;
  464.  
  465.             while (isspace(*sp)) sp++;
  466.             while (isspace(*lp)) lp--;
  467.             dp = from;
  468.             while (sp <= lp) *dp++ = *sp++;
  469.             *dp = '\0';
  470.         }
  471.         /*
  472.          *    Date formats:
  473.          *        Date: Wed May 13 23:59:53 1987
  474.          */
  475.         *date = '\0';
  476.         readaline(ld->date, date);
  477.         if (strlen(date)) {
  478.             sscanf(date, "%*s %*s %s %s", line, subject);
  479.             sprintf(date, "%s %s", line, subject);
  480.         }
  481.         strcpy(subject, "--- no subject ---");
  482.         readaline(ld->subject, line);
  483.         if (strlen(line)) {
  484.             sp = line;
  485.             while (!isspace(*sp)) sp++;
  486.             while ( isspace(*sp)) sp++;
  487.             strcpy(subject, sp);
  488.         }
  489.         sprintf(line, "%3.3d %6.6s %-20.20s %-35.35s (%ld)\n",
  490.                         j,   date,   from,  subject, ld->size);
  491.         if (pageline(line))
  492.             break;
  493.     }
  494. }
  495.  
  496. copyback()
  497. {
  498.     register i, n, c;
  499.     int new = 0;
  500.  
  501.     if ( !(fmailbag = FOPEN(mfilename, "w", 'b')) ) {
  502.         fprintf(stderr, "mail: can't rewrite %s\n", mfilename);
  503.         finis();
  504.     }
  505.     n = 0;
  506.     for (i = 0; i < letternum; i++)
  507.         if (letters[i].delete == FALSE) {
  508.             copymsg(i, fmailbag, FALSE);
  509.             n++;
  510.         }
  511.     fclose(fmailbag);
  512. }
  513.  
  514. /*
  515.  *    copy a message
  516.  *    if noheaders is TRUE, don't copy header lines
  517.  */
  518.  
  519. copymsg(n, f, noheaders)
  520. int n;
  521. FILE *f;
  522. int noheaders;
  523. {
  524.     long     bytes;
  525.     char    buf[BUFSIZ];
  526.  
  527.     fseek(fmailbox, letters[n].adr, 0);
  528.     bytes = letters[n+1].adr - letters[n].adr;
  529.  
  530.     while (bytes > 0 && fgets(buf, sizeof(buf), fmailbox)) {
  531.         bytes -= strlen(buf);
  532.         if (!noheaders) fputs(buf, f);
  533.         if (noheaders && buf[0] == '\n' && !buf[1]) noheaders = FALSE;
  534.     }
  535. }
  536.  
  537. pager(n)
  538. int n;
  539. {
  540.     long bytes;
  541.     char buf[BUFSIZ];
  542.  
  543.     fseek(fmailbox, letters[n].adr, 0);
  544.     bytes = letters[n+1].adr - letters[n].adr;
  545.  
  546.     pagereset();
  547.     while (bytes > 0 && fgets(buf, sizeof(buf), fmailbox)) {
  548.         bytes -= strlen(buf);
  549.         if (pageline(buf))
  550.             break;
  551.     }
  552.     pageline("\n");
  553. }
  554.  
  555. pagereset()
  556. {
  557.     PageCount = 0;
  558. }
  559.  
  560. pageline(s)
  561. char *s;
  562. {
  563.     int c;
  564.  
  565.     fputs(s, stdout);
  566.     if (++PageCount > 18) {
  567.         PageCount = 0;
  568.         fputs("\033[7m`q' to quit, SPACE to continue:\033[0m", stdout);
  569.         c = get_one();
  570.         fputs("\r\033[K", stdout);
  571.         switch (c) {
  572.             case 'q':
  573.             case 'Q':
  574.             case 'x':
  575.             case 'X':
  576.             case '\003':    /* ^C */
  577.             case '\033':    /* ESC */
  578.                 return( TRUE );
  579.         }
  580.     }
  581.     return( FALSE );
  582. }
  583.  
  584. char *getnext(s, p)
  585. register char **s, *p;
  586. {
  587.     *s = NULL;
  588.     while (*p == ' ' || *p == '\t')
  589.         p++;
  590.     if (*p == '\n' || !*p)
  591.         return( NULL );
  592.     *s = p;
  593.     while (isspace(*p))
  594.         *p++;
  595.     if (*p)
  596.         *p++ = '\0';
  597.     return(p);
  598. }
  599.