home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / pmush.c < prev    next >
C/C++ Source or Header  |  1992-10-30  |  7KB  |  291 lines

  1. /**************************************************************************
  2. NAME: Brian Buhrow
  3. DATE: September 17, 1991
  4. PURPOSE: This file contains the interface between the Mush program and the
  5.     POP post-office calls which put mail into the system mailbox.  Mail
  6.     will be placed in the user's mailbox when Mush is first fired up and
  7.     will be checked periodically as Mush is run.
  8.     Note that these routines will only be called if the pre-processor
  9.     variable POP3_SUPPORT is defined.
  10. **************************************************************************/
  11.  
  12. #ifdef POP3_SUPPORT
  13.  
  14. #include "config.h"
  15. #include "mush.h"
  16. #include "pop.h"
  17.  
  18. /*
  19.  * strstr - find first occurrence of wanted in s
  20.  */
  21.  
  22. char *                /* found string, or NULL if none */
  23. strstr(s, wanted)
  24. char *s;
  25. char *wanted;
  26. {
  27.     char *scan;
  28.     long len;
  29.     char firstc;
  30.  
  31.     /*
  32.      * The odd placement of the two tests is so "" is findable.
  33.      * Also, we inline the first char for speed.
  34.      * The ++ on scan has been moved down for optimization.
  35.      */
  36.     firstc = *wanted;
  37.     len = strlen(wanted);
  38.     for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
  39.     if (*scan++ == '\0')
  40.         return NULL;
  41.     return scan;
  42. }
  43.  
  44. /* This routine forms the header line for the From and Date functions below.
  45.  * It was written by John Kammens for use by UCSC's version of UCBmail running
  46.  * on the ATHENA system.
  47.  */
  48. static char *
  49. header(msg, tag)
  50. char *msg, *tag;
  51. {
  52.     char *val, *ptr, *eoh;
  53.  
  54.     val = malloc(strlen(tag) + 3);
  55.     if (!val)
  56.     return (0);
  57.  
  58.     sprintf(val, "\n%s:", tag);
  59.  
  60.     eoh = strstr(msg, "\n\n");
  61.     if (!eoh)
  62.     eoh = (char *) index(msg, '\0');
  63.  
  64.     ptr = strstr(msg, tag);
  65.  
  66.     if ((!ptr) || (ptr > eoh)) {
  67.     sprintf(val, "%s:", tag);
  68.     if (!strncmp(val, msg, strlen(val)))
  69.         ptr = msg;
  70.     else
  71.         ptr = 0;
  72.     }
  73.     if (!ptr) {
  74.     free(val);
  75.     return (0);
  76.     }
  77.     ptr += strlen(val);
  78.  
  79.     while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
  80.     ptr++;
  81.  
  82.     eoh = (char *) index(ptr, '\n');
  83.     if (!eoh)
  84.     eoh = (char *) index(ptr, '\0');
  85.  
  86.     val = realloc(val, (eoh - ptr) + 1);
  87.     strncpy(val, ptr, (eoh - ptr));
  88.     val[eoh - ptr] = '\0';
  89.  
  90.     return (val);
  91. }
  92.  
  93. /* This routine comes up with the Unix Date line to insert into the mail
  94.  * file.  It was written by John Kammens for use with UCSC's UCBMail on
  95.  * Athena.
  96.  *
  97.  * Modified to get rid of dependence on that hideous B-news yacc parser.
  98.  * Mush already has a perfectly good date parser, let's use it.  -- Bart
  99.  */
  100. static char *
  101. date(msg)
  102. char *msg;
  103. {
  104.     char *real = 0, *machine = 0;
  105.     long t;
  106.     int size;
  107.  
  108.     real = header(msg, "Date");
  109.  
  110.     if (real) {
  111.     machine = parse_date(real);
  112.     free(real);
  113.     if (machine) {
  114.         machine = date_to_ctime(machine);
  115.     }
  116.     }
  117.     if (!machine) {
  118.     t = time((long *)0);
  119.     machine = ctime(&t);
  120.     }
  121.     size = strlen(machine);
  122.     machine[size - 1] = '\0';    /* get rid of newline */
  123.     real = malloc(size);
  124.     if (!real)
  125.     return 0;
  126.     strcpy(real, machine);
  127.  
  128.     return real;
  129. }
  130.  
  131. /* This routine comes up with the Unix From line to insert into the mail
  132.  * file.  It was written by John Kammens for use with UCSC's UCBMail on
  133.  * Athena.
  134.  *
  135.  * Modified to use get_name_n_addr() so we don't depend on regexec()
  136.  * being available, which it usually isn't. -- Bart
  137.  */
  138. static char *
  139. from_line(msg)
  140. char *msg;
  141. {
  142.     char *real = header(msg, "From"), *real2;
  143.     char addr[256];
  144.  
  145.     if (real) {
  146.     addr[0] = 0;
  147.     (void) get_name_n_addr(real, NULL, addr);
  148.     if (addr[0]) {
  149.         (void) bang_form(real, addr);
  150.         return real;
  151.     }
  152.     }
  153.  
  154.     if (!real)
  155.     real = malloc(8);
  156.     if (!real)
  157.     return 0;
  158.     strcpy(real, "unknown");
  159.     return real;
  160. }
  161.  
  162. /* Retrieves mail from the system post office using the POP interface
  163.  * routines as put together by John Kammens for the UCBmail program under
  164.  * ATHENA.  This routine will be called both when Mush begins executing to
  165.  * check for new mail and when Mush is executing to see if new mail has
  166.  * arrived during the Mush session.
  167.  */
  168. static void 
  169. loadmail()
  170. {
  171.     PopServer postinfo;
  172.     int msgcount, msgsize, i, flags = 0;
  173.     char mailbox[MAXPATHLEN], *msgptr, *dateline, *fromline;
  174.     FILE *mfstream;
  175.     struct stat mfstat;
  176.     static char pass[64];
  177.  
  178.     *mailbox = (char) NULL;    /* Clear string */
  179.     strcat(mailbox, getenv("HOME"));
  180.     strcat(mailbox, "/");
  181.     strcat(mailbox, MAILFILE);
  182.     /* Get info about post drop */
  183.     if (pass[0])
  184.     flags = POP_NO_GETPASS;
  185.     if (!(postinfo = pop_open(NULL, login, pass, flags))) {
  186.     fprintf(stderr, "Error opening connection with post office: %s\n",
  187.         pop_error);
  188.     return;
  189.     }
  190.     if (pop_stat(postinfo, &msgcount, &msgsize)) {
  191.     fprintf(stderr, "Error collecting status from post office: %s\n",
  192.         pop_error);
  193.     pop_close(postinfo);
  194.     return;
  195.     }
  196.     if (!msgcount) {
  197.     pop_quit(postinfo);
  198.     return;
  199.     }
  200.     /* Begin loading mailbox */
  201.     if (stat(mailbox, &mfstat)) {
  202.     if (errno == ENOENT) {
  203.         close(open(mailbox, O_WRONLY | O_CREAT | O_EXCL, 0600));
  204.     }
  205.     }
  206.     if (!(mfstream = fopen(mailbox, "a"))) {
  207.     perror("Error opening mailbox in loadmail");
  208.     pop_close(postinfo);
  209.     return;
  210.     }
  211.     for (i = 1; i <= msgcount; i++) {    /* Load new messages */
  212.     msgptr = pop_retrieve(postinfo, i);
  213.     dateline = date(msgptr);
  214.     fromline = from_line(msgptr);
  215.     if (fprintf(mfstream, "\nFrom %s %s\n%s", fromline, dateline, msgptr)
  216.         < (strlen(fromline) + strlen(dateline) + strlen(msgptr))) {
  217.         fprintf(stderr, "Error writing mailbox file\n");
  218.         pop_close(postinfo);
  219.         cleanup(-1);
  220.     }
  221.     free(dateline);
  222.     free(fromline);
  223.     free(msgptr);
  224.     if (pop_delete(postinfo, i)) {
  225.         fprintf(stderr, "Error deleting message from post office: %s\n",
  226.             pop_error);
  227.     }
  228.     }
  229.     if (fclose(mfstream) == EOF) {
  230.     perror("Error closing mailbox file in loadmail");
  231.     pop_close(postinfo);
  232.     return;
  233.     }
  234.     if (pop_quit(postinfo)) {
  235.     fprintf(stderr, "Error closing post office: %s\n", pop_error);
  236.     }
  237.     return;
  238. }
  239.  
  240. /* This routine merely calls loadmail to get mail initially from the post
  241.  * office.  There is no forking, and it is intended to be used when Mush is
  242.  * first started.
  243.  */
  244. void
  245. popgetmail()
  246. {
  247.     loadmail();
  248. }
  249.  
  250. /* This function calls loadmail, after first forking, releasing stdin,
  251.  * stdout and stderr and ignoring any signals that might be generated.
  252.  * This function is invoked by the sigalrm signal.  The parent resets
  253.  * the alarm and returns.
  254.  */
  255. void 
  256. popchkmail()
  257. {
  258.     static int cpid = 0, numtries = 0;
  259.  
  260.     if (cpid > 0) {
  261.     if (!kill(cpid, 0)) {
  262.         numtries++;
  263.         if (numtries > 10) {
  264.         kill(cpid, SIGKILL);
  265.         }
  266.         return;
  267.     } else {
  268.         numtries = 0;
  269.     }
  270.     }
  271.     if (!(cpid = fork())) {
  272.     /* Ignore several signals for workability */
  273.     signal(SIGCONT, SIG_IGN);
  274.     signal(SIGQUIT, SIG_IGN);
  275.     signal(SIGTSTP, SIG_IGN);
  276.     signal(SIGSTOP, SIG_IGN);
  277.     signal(SIGTERM, SIG_IGN);
  278.     signal(SIGIO, SIG_IGN);
  279.     signal(SIGPIPE, SIG_IGN);
  280.     loadmail();
  281.     _exit(0);
  282.     } else {
  283.     if (cpid == -1) {
  284.         fprintf(stderr, "Unable to fork in popchkmail\n");
  285.     }
  286.     return;
  287.     }
  288. }
  289.  
  290. #endif    /* POP3_SUPPORT */
  291.