home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume3 / pcmail / part04 / rmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  6.0 KB  |  221 lines

  1. /*++
  2. /* NAME
  3. /*      rmail
  4. /* SUMMARY
  5. /*      extract originator from new mail received by cico
  6. /* PROJECT
  7. /*      pc-mail
  8. /* PACKAGE
  9. /*      rmail
  10. /* SYNOPSIS
  11. /*      rmail
  12. /* DESCRIPTION
  13. /*      rmail searches for new mail files received by cico and extracts
  14. /*    the originator's name, for later use by the mail visual shell.
  15. /*
  16. /*     Return address formats we understand (in order of preference):
  17. /* .nf
  18. /*
  19. /*    From: address (full_name)    (accept the full_name)
  20. /*    From: address            (accept the address)
  21. /*    >From address            (take address and keep scanning)
  22. /*    From address            (take address and keep scanning)
  23. /*
  24. /* .fi
  25. /*      To avoid tampering, new files will have read-only permission.
  26. /*
  27. /*      In order to avoid corruption, control-c interrupts are disabled.
  28. /* FILES
  29. /*      In the spool directory:
  30. /*    n<seqno>    received mail message
  31. /*    h<seqno>    extracted originator address
  32. /* SEE ALSO
  33. /*      path(5)         spool directory, file names
  34. /*      cico(1)         network process
  35. /*      mailsh(1)       visual mail shell
  36. /* DIAGNOSTICS
  37. /*      Exit status zero when no errors were detected, nonzero in case of file
  38. /*      access errors. See status(5) for error codes.
  39. /* BUGS
  40. /*    Note that the format "From: full_name <address>" is not 
  41. /*    recognized. The program will just pick up the first word from
  42. /*    full_name.
  43. /*
  44. /*      Does not really do a good job when parsing the mail headers.
  45. /*    At least, not good enough to extract a return path.
  46. /* AUTHOR(S)
  47. /*      W.Z. Venema
  48. /*      Eindhoven University of Technology
  49. /*      Department of Mathematics and Computer Science
  50. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  51. /* CREATION DATE
  52. /*      Tue Mar 31 20:14:11 GMT+1:00 1987
  53. /* LAST MODIFICATION
  54. /*    Wed Apr  6 00:21:54 MET 1988
  55. /* VERSION/RELEASE
  56. /*    1.4
  57. /*--*/
  58.  
  59. #include <setjmp.h>
  60. #include <signal.h>
  61. #include <time.h>
  62. #include <ctype.h>
  63. #include "defs.h"
  64. #include "dir.h"
  65. #include "path.h"
  66. #include "status.h"
  67.  
  68. extern struct tm *localtime();        /* system functions */
  69.  
  70. hidden void parse_args();        /* forward declarations */
  71. hidden void newmail();
  72. hidden void extract();
  73. hidden void usage();
  74.  
  75. #define HLEN            20        /* nbr of header lines scanned */
  76.  
  77. hidden int dflag = 0;            /* debugging option */
  78.  
  79. #define debug    if (dflag) printf
  80.  
  81. main(argc,argv)
  82. int argc;
  83. char **argv;
  84. {
  85.     signal(SIGINT,SIG_IGN);        /* disable ctrl-c */
  86.     parse_args(argc,argv);        /* parse command args */
  87.     pathinit();                /* get path info */
  88.     umask(0222);            /* make files read-only */
  89.     newmail();                /* get headers from new mail */
  90.     exit(0);
  91.     /* NOTREACHED */
  92. }
  93.  
  94. /* parse_args - process command-line arguments */
  95.  
  96. hidden void parse_args(argc,argv)
  97. int argc;
  98. char **argv;
  99. {
  100.     while (--argc && *++argv && **argv == '-') {    /* process options */
  101.     switch (*++*argv) {
  102.     case 'd':                    /* turn debugging on */
  103.         if (--argc == 0)
  104.         usage("missing debugging level argument");
  105.         sscanf(*++argv,"%d",&dflag);
  106.         if (dflag < 0 || dflag > 9)
  107.         dflag = 0;
  108.         break;
  109.     default:                    /* unknown option */
  110.         usage(strcons("invalid option: -%c",**argv));
  111.         break;
  112.     }
  113.     }
  114.  
  115.     /* check for extraneous arguments */
  116.  
  117.     if (argc > 0)
  118.     usage(strcons("unexpected argument: %s",*argv));
  119. }
  120.  
  121. /* scan for new mail that hasn't gotten yet a metafile */
  122.  
  123. hidden void newmail()
  124. {
  125.     register int dd;
  126.     int pfxlen = sizeof(NEWPFX)-1;
  127.     char *f;
  128.  
  129.     debug("directory: \"%s\"\n",maildir);        /* verify */
  130.  
  131.     /*
  132.     * Scan the spool directory for newly-arrived mail.
  133.     *
  134.     * Incoming mail message files have a name of "n<seqno>". 
  135.     * The originator name is normally present in files with names
  136.     * "h<seqno>" or "o<seqno>".
  137.     * The presence of an "o" file implies that the file "n<seqno>"
  138.     * has been read by the user. An "h" file means that the user
  139.     * has not yet read the message file.
  140.     *
  141.     * If a message file has no corresponding "h" or "o" file we
  142.     * assume it is a new mail message and create an "h" file with 
  143.     * the name of the originator.
  144.     */
  145.  
  146.     for (dd = opendir(maildir); f = readdir(dd); /* void */) {
  147.     int seqno;
  148.     debug("rmail: file \"%s\"\n",f);
  149.     if (strncmp(f,NEWPFX,pfxlen) == 0 && sscanf(f+pfxlen,"%d",&seqno)) {
  150.         if (access(in_meta(seqno),4) == 0) {    /* message already */
  151.         /* void */ ;                /* marked as read */
  152.         } else if (access(new_meta(seqno),4) == 0) {/* message already */
  153.         /* void */ ;                /* marked as unread */
  154.         } else {                    /* create meta file */
  155.         extract(new_mesg(seqno),new_meta(seqno));
  156.         }
  157.     }
  158.     }
  159.     closedir(dd);
  160. }
  161.  
  162. /* extract - extract originator info from mail file to meta file */
  163.  
  164. hidden void extract(mail,meta)
  165. char *mail;
  166. char *meta;
  167. {
  168.     FILE *mesgfp,*metafp;
  169.     char line[BUFSIZ];
  170.     char from[BUFSIZ];
  171.     int n;
  172.  
  173.     debug("-- \"%s\" -> \"%s\"\n",mail,meta);
  174.  
  175.     if ((mesgfp = fopen(mail,"r")) == NULL)    /* cannot open existing file */
  176.     exit(E_SYSFAIL);
  177.  
  178.     strcpy(from,"Somewhere");            /* default originator */
  179.  
  180.     /*
  181.     * Some mailers generate real headers, separated from the message
  182.     * body by an empty line. So we stop when we find an empty line.
  183.     * Other mailers have no headers, so we stop after HLEN lines.
  184.     * The following algorithm tries to extract the real user name
  185.     * if possible, otherwise it takes whatever it can get.
  186.     */
  187.  
  188.     for (n = 0; n < HLEN && fgets(line,BUFSIZ,mesgfp) && *line != '\n'; n++) {
  189.     if (sscanf(line,"From: %*s ( %[^)] )",from) == 1)
  190.         break;
  191.     if (sscanf(line,"From: %s",from) == 1)
  192.         break;
  193.     sscanf(line,"%*[>] From %s",from) || sscanf(line,"From %s",from);
  194.     }
  195.  
  196.     /* carefully check all went well */
  197.  
  198.     if (ferror(mesgfp))                /* sorry, read problem */
  199.     exit(E_READERR);
  200.     if ((metafp = fopen(meta,"w")) == NULL)    /* cannot create metafile */
  201.     exit(E_WRITERR);
  202.     fprintf(metafp,"%s\n",from);        /* write originator */
  203.     if (ferror(metafp)) {
  204.     fclose(metafp);                /* ms-dog needs this! */
  205.     chmod(meta,0666);            /* sorry, write problem */
  206.     unlink(meta);                /* delete metafile */
  207.     exit(E_WRITERR);
  208.     }
  209.     fclose(mesgfp);
  210.     fclose(metafp);
  211. }
  212.  
  213. /* usage - explain what is wrong */
  214.  
  215. hidden void usage(str)
  216. char *str;
  217. {
  218.     fprintf(stderr,"%s\nusage: rmail [-d debugging_level]\n",str);
  219.     exit(2);
  220. }
  221.