home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / dmail / load_mail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-21  |  13.6 KB  |  659 lines

  1.  
  2. /*
  3.  *  LOAD_MAIL.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/dmail/RCS/load_mail.c,v 1.1 90/02/02 12:03:35 dillon Exp Locker: dillon $
  6.  *
  7.  *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
  8.  *
  9.  *  file-io routines to scan the mail file and load required information.
  10.  *
  11.  *
  12.  *  Global Routines:    HOLD_LOAD()         hold on loading mail after change
  13.  *            NOHOLD_LOAD()       hold off.. load if changes
  14.  *            LOAD_CHANGES()      reload mail if changed
  15.  *            LOAD_MAIL()         load/reload mail
  16.  *            SAVE_FILE()         save mail items back to spool
  17.  *            CHECK_NEW_MAIL()    check for new mail
  18.  *            WRITE_FILE()        append mail items to a file
  19.  *            GET_EXTRA_OVR()     ret index of Field (create if not)
  20.  *            ADD_EXTRA()         add another field (reloads mail)
  21.  *            DELETE_EXTRA()      delete a field
  22.  *            GET_EXTRA()         ret index of Field, or error
  23.  *            M_SELECT()          select on current message list
  24.  *
  25.  *
  26.  *  Static Routines:    LOAD_HASH()         load hash table from fields list
  27.  *            FREE_ENTRY()        unload EVERYTHING
  28.  *            FREE_TABLE()        unload all Fields table
  29.  *            LOAD_FILE()         raw file loading/counting
  30.  *
  31.  *
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <sys/file.h>
  36. #include "dmail.h"
  37.  
  38. void do_flock();
  39. void free_table();
  40. void load_hash();
  41.  
  42. #define NOHOLD    0
  43. #define HOLD    1
  44.  
  45. #define NO_BASE     0
  46. #define NO_FIELDS   1
  47. #define ENTRY_OK    2
  48.  
  49. struct FIND Find[MAXTYPE + 1] = {
  50.     "From:"   , 5, 1, 0,
  51.     "To:"     , 3, 1, 0,
  52.     "Subject:", 8, 1, 0 };
  53.  
  54. static int  File_size;
  55. static int  changed, load_hold;
  56. static int  Hash[256];
  57.  
  58. static char *quo_quo = "";
  59.  
  60. void
  61. hold_load()
  62. {
  63.     load_hold = 1;
  64. }
  65.  
  66. void
  67. nohold_load()
  68. {
  69.     void load_changes();
  70.     load_hold = 0;
  71.     load_changes();
  72. }
  73.  
  74. void
  75. load_changes()
  76. {
  77.     if (changed  &&  !load_hold)
  78.     load_mail(Entries, 1);
  79. }
  80.  
  81. initial_load_mail()
  82. {
  83.     if (load_mail (0, 0) < 0)
  84.     return (-1);
  85.     return ((Entries) ? 1 : -1);
  86. }
  87.  
  88.  
  89. static
  90. load_mail(at, from0)
  91. {
  92.     FILE *fi;
  93.     int i, count, file_size;
  94.  
  95.     if (No_load_mail)
  96.     return (-1);
  97.     push_break();
  98.     load_hash();
  99.     if (from0)
  100.     free_table (0, HOLD);
  101.     else
  102.     free_table (at, NOHOLD);
  103.     fi = fopen (mail_file, "r+");
  104.     if (m_fi != NULL)
  105.     fclose (m_fi);
  106.     m_fi = fopen (mail_file, "r+");
  107.     if (fi == NULL  ||  m_fi == NULL) {
  108.     pop_break();
  109.     return (-1);
  110.     }
  111.     do_flock (fileno(m_fi), LOCK_EX);
  112.     if (at)
  113.     fseek (fi, Entry[at].fpos, 0);
  114.     else
  115.     fseek (fi, 0, 0);
  116.     count = Entries;
  117.     while (search_from(fi))
  118.     ++count;
  119.     if (Entries != count) {
  120.     if (!lmessage_overide)
  121.         printf ("%d Other Items loaded\n", count - Entries);
  122.     lmessage_overide = 0;
  123.     Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1));
  124.     bzero (&Entry[Entries], sizeof(*Entry) * (count + 1 - Entries));
  125.     }
  126.     Entries = count;
  127.     for (i = at; i < Entries; ++i) {
  128.     Entry[i].no  = 0;
  129.     Entry[i].status = 0;
  130.     }
  131.     Entry[i].fpos = File_size = file_size = ftell (fi);
  132.     fclose (fi);
  133.     load_file ((from0) ? 0 : at);
  134.     if (file_size != File_size) {       /* Last entry incomplete?       */
  135.     free_table (Entries - 1, NOHOLD);
  136.     }
  137.     changed = 0;
  138.     if (SelAll)
  139.     m_select (Nulav, 0);
  140.     flock (fileno(m_fi), LOCK_UN);
  141.     pop_break();
  142.     return (1);
  143. }
  144.  
  145. void
  146. do_flock(fd, stat)
  147. {
  148.     if (flock(fd, stat | LOCK_NB) < 0) {
  149.     puts ("File in use, Waiting for lock");
  150.     flock (fd, stat);
  151.     puts ("Have lock");
  152.     }
  153. }
  154.  
  155. static
  156. load_file(at)
  157. int at;
  158. {
  159.     FILE *fi;
  160.     char *next, *ptr;
  161.     int i, bit, maxbit, len, count, havefrom;
  162.  
  163.     maxbit = 0;
  164.     for (i = 0; Find[i].search != NULL; ++i)
  165.     maxbit = (maxbit << 1) | 1;
  166.     fi = fopen (mail_file, "r");
  167.     count = -1;
  168.     havefrom = 0;
  169.     while (havefrom  ||  search_from (fi)) {
  170.     havefrom = 0;
  171.     if (++count >= Entries)
  172.         break;
  173.     len = strlen(Buf) - 1;
  174.     Buf[len] = '\0';
  175.     next = next_word(Buf);
  176.     len -= next - Buf;
  177.     Entry[count].fpos = ftell (fi);
  178.     Entry[count].from = malloc (len + 1);
  179.     bcopy (next, Entry[count].from, len + 1);
  180.  
  181.     /* SEARCH FIELD LIST */
  182.  
  183.     bit = 0;
  184.     if (XDebug)
  185.         printf ("No %d  ---------------------\n", count + 1);
  186.     while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
  187.         if (Buf[0] == '\n')
  188.         break;
  189.         if (isfrom(Buf)) {
  190.         havefrom = 1;
  191.         break;
  192.         }
  193.         len = strlen(Buf) - 1;
  194.         Buf[len] = '\0';
  195.         if (XDebug)
  196.         printf ("CHECK: %s\n", Buf);
  197.         next = next_word(Buf);
  198.         len -= next - Buf;
  199.         if (Hash[*Buf] == 0)
  200.         continue;
  201.         if (Hash[*Buf] > 0) {
  202.         i = Hash[*Buf] & 0xff;
  203.         if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
  204.             goto found;
  205.         continue;
  206.         }
  207.         for (i = -Hash[*Buf] & 0xff; Find[i].search; ++i) {
  208.         if (*Find[i].search != *Buf)
  209.             break;
  210.         if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
  211.             goto found;
  212.         }
  213.         continue;
  214. found:
  215.         if (XDebug)
  216.         printf ("Found: %d %s\n", i, Buf);
  217.         if (Find[i].notnew == 0) {
  218.         Find[i].notnew = 1;
  219.         ptr = Buf;
  220.         while (*ptr  &&  *ptr != ':')
  221.             ++ptr;
  222.         ++ptr;
  223.         Find[i].search =
  224.             realloc (Find[i].search, ptr - Buf + 1);
  225.         strncpy (Find[i].search, Buf, ptr - Buf);
  226.         *(Find[i].search + (ptr - Buf)) = '\0';
  227.         Find[i].len = strlen(Find[i].search);
  228.         }
  229.         compile_field (Buf, fi);
  230.         Entry[count].fields[i] =
  231.             malloc (strlen(next) + 1);
  232.         strcpy (Entry[count].fields[i], next);
  233.         if ((bit |= (1 << i)) == maxbit)
  234.         break;
  235.     }
  236.     if (bit != maxbit) {
  237.         for (i = 0; Find[i].search != NULL; ++i) {
  238.         if (((1 << i) & bit) == 0) {
  239.             Entry[count].fields[i] = quo_quo;
  240.         }
  241.         }
  242.     }
  243.     }
  244.     File_size = ftell (fi);
  245.     fclose (fi);
  246.     return (1);
  247. }
  248.  
  249.  
  250. static void
  251. load_hash()
  252. {
  253.     register int i, c;
  254.  
  255.     bzero (Hash, sizeof(Hash));
  256.     for (i = 0; Find[i].search; ++i) {
  257.     c = *Find[i].search;
  258.     if (Hash[c] > 0)
  259.         Hash[c] = -Hash[c];
  260.     if (Hash[c] == 0)
  261.         Hash[c] = i | 0x100;
  262.     }
  263. }
  264.  
  265.  
  266. void
  267. free_entry()
  268. {
  269.     free_table(0, NOHOLD);
  270.     Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry));
  271.     bzero (Entry[0].fields, sizeof(Entry[0].fields));
  272.     File_size = Entries = 0;
  273.     Entry->status = Entry->no = Entry->fpos = Current = 0;
  274.     Listsize = 3;
  275.     if (m_fi) {
  276.     fclose (m_fi);
  277.     m_fi = NULL;
  278.     }
  279. }
  280.  
  281.  
  282. static void
  283. free_table(at, hold)
  284. {
  285.     int i, j;
  286.  
  287.     for (i = at; i < Entries; ++i) {
  288.     xfree (Entry[i].from);
  289.     for (j = 0; Find[j].search != NULL; ++j) {
  290.         if (Entry[i].fields[j] != quo_quo)
  291.         xfree (Entry[i].fields[j]);
  292.     }
  293.     }
  294.     Entries = (hold == HOLD) ? Entries : at;
  295.     File_size = (at) ? Entry[Entries].fpos : 0;
  296. }
  297.  
  298. static
  299. search_from(fi)
  300. FILE *fi;
  301. {
  302.     while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
  303.     if (isfrom (Buf))
  304.         return (1);
  305.     }
  306.     return (0);
  307. }
  308.  
  309.  
  310. save_file(reload, mark, notmark)
  311. {
  312.     FILE *fiscr;
  313.     int fdscr;
  314.     int i, count;
  315.     char scratch[64];
  316.  
  317.     for (i = 0; i < Entries; ++i) {
  318.     if ((Entry[i].status & mark) != mark  ||
  319.         (~Entry[i].status & notmark) != notmark)
  320.         break;
  321.     }
  322.     if (i == Entries) {
  323.     m_select (Nulav, M_RESET);
  324.     puts ("No Changes Made");
  325.     return (Entries);
  326.     }
  327.     if (m_fi == NULL)
  328.     return (-1);
  329.     count = 0;
  330.     sprintf(scratch, "t:dmail%d", getpid());
  331.     do_flock (fileno(m_fi), LOCK_EX);
  332.     fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE);
  333. #ifdef AMIGA        /*    fix bug in Lattice C fdopen */
  334.     fiscr = fopen("nil:", "w");
  335.     fclose(fiscr);
  336. #endif
  337.     fiscr = fdopen (fdscr, "a+");
  338.     for (i = 0; i < Entries; ++i) {
  339.     if ((Entry[i].status & mark) == mark  &&
  340.         (~Entry[i].status & notmark) == notmark) {
  341.         ++count;
  342.         fputs ("From ", fiscr);
  343.         fputs (Entry[i].from, fiscr);
  344.         putc ('\n', fiscr);
  345.         fseek (m_fi, Entry[i].fpos, 0);
  346.         while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
  347.         if (isfrom(Buf))
  348.             break;
  349.         fputs (Buf, fiscr);
  350.         }
  351.     }
  352.     }
  353.  
  354.     /*
  355.      *    If new mail has come in, append to the scratch file as well.
  356.      *    NOTE: for some machines like the Amiga an already open descriptor
  357.      *          does not know about any new data, thus we cannot simply
  358.      *          use m_fi .
  359.      */
  360.  
  361.     {
  362.     FILE *fi;
  363.  
  364.     if (fi = fopen(mail_file, "r")) {
  365.         fseek(fi, File_size, 0);
  366.         while (fgets(Buf, MAXFIELDSIZE, fi))
  367.         fputs(Buf, fiscr);
  368.         fclose(fi);
  369.     }
  370.     }
  371.  
  372.     /* Write scratch file back to mail file, or try to */
  373.  
  374.     fflush (fiscr);
  375.     fflush (m_fi);
  376.  
  377.     lseek (fdscr, 0 ,0);
  378. #ifdef UNIX
  379.     lseek (fileno(m_fi), 0, 0);
  380.     while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
  381.     write (fileno(m_fi), Buf, i);
  382.     ftruncate (fileno(m_fi), lseek (fileno(m_fi), 0, 1));
  383. #else
  384.     fclose(m_fi);
  385.     if (m_fi = fopen (mail_file, "w")) {
  386.     while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
  387.         write (fileno(m_fi), Buf, i);
  388.     fclose(m_fi);
  389.     m_fi = fopen (mail_file, "r+");
  390.     }
  391.     if (m_fi == NULL) {
  392.     printf("Unable to re-open %s !\n", mail_file);
  393.     return(-1);
  394.     }
  395. #endif
  396.     if (lseek (fileno(m_fi), 0, 2) == 0  &&  !reload) {
  397.     if (Did_cd == 0) {
  398.         fclose(m_fi);
  399.         m_fi = NULL;
  400.         if (unlink (mail_file) == 0)
  401.         printf ("%s  Removed\n", mail_file);
  402.         else
  403.         printf ("0 messages left in %s\n", mail_file);
  404.     }
  405.     }
  406.     fclose (fiscr);
  407.     if (m_fi)
  408.     fclose (m_fi);          /* Effectively unlocks the descriptor */
  409.     m_fi = NULL;
  410.     unlink (scratch);
  411.     if (reload) {
  412.     free_entry();
  413.     load_mail(0, 0);
  414.     }
  415.     m_select (Nulav, M_RESET);
  416.     return (count);
  417. }
  418.  
  419. void
  420. check_new_mail()
  421. {
  422.     FILE *fi;
  423.  
  424.     push_break();
  425.     if (m_fi == NULL) {
  426.     m_fi = fopen (mail_file, "r+");
  427.     if (m_fi == NULL) {
  428.         pop_break();
  429.         return;
  430.     }
  431.     }
  432.     if (fi = fopen(mail_file, "r")) {
  433.     if (fseek(fi, 0, 2) < 0 || ftell(fi) != File_size)
  434.         load_mail(Entries, 1);
  435.     fclose(fi);
  436.     }
  437.     pop_break();
  438. }
  439.  
  440.  
  441. write_file(file, modes, mark, notmark)
  442. char *file;
  443. {
  444.     int i, fd = 1, notopen = 1;
  445.     FILE *fi = NULL;
  446.  
  447.     for (i = 0; i < Entries; ++i) {
  448.     if ((Entry[i].status & mark) == mark  &&
  449.         (~Entry[i].status & notmark) == notmark) {
  450.         if (notopen) {
  451.         notopen = 0;
  452.         fd = open (file, O_APPEND | O_WRONLY | modes, MAILMODE);
  453.         if (fd < 0)
  454.             return (-1);
  455.         do_flock (fd, LOCK_EX);
  456. #ifdef AMIGA        /*    fix bug in Lattice C fdopen */
  457.         fi = fopen("nil:", "w");
  458.         fclose(fi);
  459. #endif
  460.         fi = fdopen (fd, "a");
  461.  
  462. #ifdef NOTDEF
  463.         if (fi) {
  464.             printf("ptr     %08lx\n", fi->_ptr);
  465.             printf("rcnt    %08lx\n", fi->_rcnt);
  466.             printf("wcnt    %08lx\n", fi->_wcnt);
  467.             printf("base    %08lx\n", fi->_base);
  468.             printf("size    %08lx\n", fi->_size);
  469.             printf("flag    %08lx\n", fi->_flag);
  470.             printf("file    %08lx\n", fi->_file);
  471.             return(-1);
  472.         }
  473. #endif
  474.         }
  475.         fputs ("From ", fi);
  476.         fputs (Entry[i].from, fi);
  477.         putc ('\n', fi);
  478.         if (m_fi) {
  479.         fseek (m_fi, Entry[i].fpos, 0);
  480.         while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
  481.             if (isfrom(Buf))
  482.             break;
  483.             fputs (Buf, fi);
  484.         }
  485.         }
  486.     }
  487.     }
  488.     if (!notopen)
  489.     fclose (fi);
  490.     return (1);
  491. }
  492.  
  493. /*
  494.  * Basic scheme: Each entry has a fields list.    Each entry in the fields list
  495.  * is guarenteed to be a valid malloc'd pointer (except some may be set to
  496.  * quo_quo).
  497.  *
  498.  * The find[] struct array holds the field name and length, the index
  499.  * corresponding to the index into the field[] in an Entry.
  500.  *
  501.  * The header and width arrays hold the list format.
  502.  */
  503.  
  504. get_extra_ovr(str)
  505. char *str;
  506. {
  507.     register int i;
  508.  
  509.     i = get_extra (str);
  510.     if (i < 0) {
  511.     i = add_extra (str);
  512.     load_changes();
  513.     }
  514.     return (i);
  515. }
  516.  
  517.  
  518. /*
  519.  * If there's room to add it, append to end.
  520.  * Else Find oldest field which doesn't exist in the setlist and replace it
  521.  *  with the new one.
  522.  */
  523.  
  524. add_extra(str)
  525. char *str;
  526. {
  527.     register int i, j, j_age, k;
  528.  
  529.     for (i = EXSTART; i < MAXTYPE; ++i) {
  530.     if (Find[i].search == NULL)
  531.         break;
  532.     ++Find[i].age;
  533.     }
  534.     if (i == MAXTYPE) {                 /* No room to add onto end */
  535.     j = j_age = -1;
  536.     for (i = EXSTART; i < MAXTYPE; ++i) {
  537.         for (k = 0; k < Listsize; ++k) {
  538.         if (i == header[k])
  539.             break;
  540.         }
  541.         if (k == Listsize  &&  Find[i].age > j_age) {
  542.         j = i;
  543.         j_age = Find[i].age;
  544.         }
  545.     }
  546.     i = j;
  547.     }
  548.     if (i < 0)
  549.     return (-1);
  550.     push_break();
  551.     if (Find[i].search != NULL)
  552.     xfree (Find[i].search);
  553.     Find[i].len = strlen(str);
  554.     Find[i].search = malloc (Find[i].len + 1);
  555.     Find[i].notnew = Find[i].age = 0;
  556.     strcpy (Find[i].search, str);
  557.     changed = 1;
  558.     for (j = 0; j < Entries; ++j) {
  559.     if (Entry[j].fields[i] && Entry[j].fields[i] != quo_quo)
  560.         xfree (Entry[j].fields[i]);
  561.     Entry[j].fields[i] = quo_quo;
  562.     }
  563.     pop_break();
  564.     return (i);
  565. }
  566.  
  567.  
  568. get_extra(str)
  569. char *str;
  570. {
  571.     int i;
  572.  
  573.     for (i = 0; Find[i].search; ++i) {
  574.     if (strncmp (str, Find[i].search, strlen(str)) == 0) {
  575.         Find[i].age = 0;
  576.         return (i);
  577.     }
  578.     }
  579.     return (-1);
  580. }
  581.  
  582.  
  583. m_select(sav, mode)
  584. register char *sav[];
  585. {
  586.     char *ptr, *dest;
  587.     char l_map[256];
  588.     int idx[MAXLIST], ix = 0;
  589.     int ok, not, len, scr;
  590.     register int i, j, avi;
  591.  
  592.     for (i = 0;i < 256; ++i)
  593.     l_map[i] = i;
  594.     for (i = 'A'; i <= 'Z'; ++i)
  595.     l_map[i] += 'a' - 'A';
  596.     hold_load();
  597.     i = 0;
  598.     idx[ix++] = get_extra_ovr (sav[i++]);
  599.     for (; sav[i]; ++i) {
  600.     if (strcmp (sav[i], ",") == 0  &&  sav[i + 1])
  601.         idx[ix++] = get_extra_ovr (sav[++i]);
  602.     }
  603.     idx[ix] = -1;
  604.     nohold_load();
  605.     j = 1;
  606.     push_break();
  607.     for (i = 0; i < Entries; ++i) {
  608.     if (mode == M_CONT  &&  Entry[i].no == 0)
  609.         continue;
  610.     ix = ok = 0;
  611.     avi = 1;
  612.     while ((ptr = sav[avi]) != NULL) {
  613.         if (ptr[0] == ','  &&  ptr[1] == '\0' && sav[avi+1]) {
  614.         ++ix;
  615.         avi += 2;
  616.         continue;
  617.         }
  618.         if (not = (*ptr == '!'))
  619.         ++ptr;
  620.         len = strlen (ptr);
  621.         dest = Entry[i].fields[idx[ix]];
  622.         if (*ptr == '\0') {
  623.         ok = 1;
  624.         goto gotit;
  625.         }
  626.         while (*dest) {
  627.         scr = 0;
  628.         while (l_map[dest[scr]] == l_map[ptr[scr]] && ptr[scr])
  629.             ++scr;
  630.         if (ptr[scr] == '\0') {
  631.             ok = 1;
  632.             goto gotit;
  633.         }
  634.         ++dest;
  635.         }
  636.         ++avi;
  637.     }
  638. gotit:
  639.     Entry[i].no = (ok ^ not) ? j++ : 0;
  640.     }
  641.     pop_break();
  642.     if (Current < 0)
  643.     Current = 0;
  644.     if (Entries) {
  645.     if (Entry[Current].no == 0) {
  646.         Current = indexof (1);
  647.         if (Current < 0) {
  648.          Current = 0;
  649.          return (-1);
  650.         }
  651.     }
  652.     } else {
  653.     Current = -1;
  654.     }
  655.     return (1);
  656. }
  657.  
  658.  
  659.