home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * LOAD_MAIL.C
- *
- * $Header: Beta:src/uucp/src/dmail/RCS/load_mail.c,v 1.1 90/02/02 12:03:35 dillon Exp Locker: dillon $
- *
- * (C) Copyright 1985-1990 by Matthew Dillon, All Rights Reserved.
- *
- * file-io routines to scan the mail file and load required information.
- *
- *
- * Global Routines: HOLD_LOAD() hold on loading mail after change
- * NOHOLD_LOAD() hold off.. load if changes
- * LOAD_CHANGES() reload mail if changed
- * LOAD_MAIL() load/reload mail
- * SAVE_FILE() save mail items back to spool
- * CHECK_NEW_MAIL() check for new mail
- * WRITE_FILE() append mail items to a file
- * GET_EXTRA_OVR() ret index of Field (create if not)
- * ADD_EXTRA() add another field (reloads mail)
- * DELETE_EXTRA() delete a field
- * GET_EXTRA() ret index of Field, or error
- * M_SELECT() select on current message list
- *
- *
- * Static Routines: LOAD_HASH() load hash table from fields list
- * FREE_ENTRY() unload EVERYTHING
- * FREE_TABLE() unload all Fields table
- * LOAD_FILE() raw file loading/counting
- *
- *
- */
-
- #include <stdio.h>
- #include <sys/file.h>
- #include "dmail.h"
-
- void do_flock();
- void free_table();
- void load_hash();
-
- #define NOHOLD 0
- #define HOLD 1
-
- #define NO_BASE 0
- #define NO_FIELDS 1
- #define ENTRY_OK 2
-
- struct FIND Find[MAXTYPE + 1] = {
- "From:" , 5, 1, 0,
- "To:" , 3, 1, 0,
- "Subject:", 8, 1, 0 };
-
- static int File_size;
- static int changed, load_hold;
- static int Hash[256];
-
- static char *quo_quo = "";
-
- void
- hold_load()
- {
- load_hold = 1;
- }
-
- void
- nohold_load()
- {
- void load_changes();
- load_hold = 0;
- load_changes();
- }
-
- void
- load_changes()
- {
- if (changed && !load_hold)
- load_mail(Entries, 1);
- }
-
- initial_load_mail()
- {
- if (load_mail (0, 0) < 0)
- return (-1);
- return ((Entries) ? 1 : -1);
- }
-
-
- static
- load_mail(at, from0)
- {
- FILE *fi;
- int i, count, file_size;
-
- if (No_load_mail)
- return (-1);
- push_break();
- load_hash();
- if (from0)
- free_table (0, HOLD);
- else
- free_table (at, NOHOLD);
- fi = fopen (mail_file, "r+");
- if (m_fi != NULL)
- fclose (m_fi);
- m_fi = fopen (mail_file, "r+");
- if (fi == NULL || m_fi == NULL) {
- pop_break();
- return (-1);
- }
- do_flock (fileno(m_fi), LOCK_EX);
- if (at)
- fseek (fi, Entry[at].fpos, 0);
- else
- fseek (fi, 0, 0);
- count = Entries;
- while (search_from(fi))
- ++count;
- if (Entries != count) {
- if (!lmessage_overide)
- printf ("%d Other Items loaded\n", count - Entries);
- lmessage_overide = 0;
- Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1));
- bzero (&Entry[Entries], sizeof(*Entry) * (count + 1 - Entries));
- }
- Entries = count;
- for (i = at; i < Entries; ++i) {
- Entry[i].no = 0;
- Entry[i].status = 0;
- }
- Entry[i].fpos = File_size = file_size = ftell (fi);
- fclose (fi);
- load_file ((from0) ? 0 : at);
- if (file_size != File_size) { /* Last entry incomplete? */
- free_table (Entries - 1, NOHOLD);
- }
- changed = 0;
- if (SelAll)
- m_select (Nulav, 0);
- flock (fileno(m_fi), LOCK_UN);
- pop_break();
- return (1);
- }
-
- void
- do_flock(fd, stat)
- {
- if (flock(fd, stat | LOCK_NB) < 0) {
- puts ("File in use, Waiting for lock");
- flock (fd, stat);
- puts ("Have lock");
- }
- }
-
- static
- load_file(at)
- int at;
- {
- FILE *fi;
- char *next, *ptr;
- int i, bit, maxbit, len, count, havefrom;
-
- maxbit = 0;
- for (i = 0; Find[i].search != NULL; ++i)
- maxbit = (maxbit << 1) | 1;
- fi = fopen (mail_file, "r");
- count = -1;
- havefrom = 0;
- while (havefrom || search_from (fi)) {
- havefrom = 0;
- if (++count >= Entries)
- break;
- len = strlen(Buf) - 1;
- Buf[len] = '\0';
- next = next_word(Buf);
- len -= next - Buf;
- Entry[count].fpos = ftell (fi);
- Entry[count].from = malloc (len + 1);
- bcopy (next, Entry[count].from, len + 1);
-
- /* SEARCH FIELD LIST */
-
- bit = 0;
- if (XDebug)
- printf ("No %d ---------------------\n", count + 1);
- while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
- if (Buf[0] == '\n')
- break;
- if (isfrom(Buf)) {
- havefrom = 1;
- break;
- }
- len = strlen(Buf) - 1;
- Buf[len] = '\0';
- if (XDebug)
- printf ("CHECK: %s\n", Buf);
- next = next_word(Buf);
- len -= next - Buf;
- if (Hash[*Buf] == 0)
- continue;
- if (Hash[*Buf] > 0) {
- i = Hash[*Buf] & 0xff;
- if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
- goto found;
- continue;
- }
- for (i = -Hash[*Buf] & 0xff; Find[i].search; ++i) {
- if (*Find[i].search != *Buf)
- break;
- if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
- goto found;
- }
- continue;
- found:
- if (XDebug)
- printf ("Found: %d %s\n", i, Buf);
- if (Find[i].notnew == 0) {
- Find[i].notnew = 1;
- ptr = Buf;
- while (*ptr && *ptr != ':')
- ++ptr;
- ++ptr;
- Find[i].search =
- realloc (Find[i].search, ptr - Buf + 1);
- strncpy (Find[i].search, Buf, ptr - Buf);
- *(Find[i].search + (ptr - Buf)) = '\0';
- Find[i].len = strlen(Find[i].search);
- }
- compile_field (Buf, fi);
- Entry[count].fields[i] =
- malloc (strlen(next) + 1);
- strcpy (Entry[count].fields[i], next);
- if ((bit |= (1 << i)) == maxbit)
- break;
- }
- if (bit != maxbit) {
- for (i = 0; Find[i].search != NULL; ++i) {
- if (((1 << i) & bit) == 0) {
- Entry[count].fields[i] = quo_quo;
- }
- }
- }
- }
- File_size = ftell (fi);
- fclose (fi);
- return (1);
- }
-
-
- static void
- load_hash()
- {
- register int i, c;
-
- bzero (Hash, sizeof(Hash));
- for (i = 0; Find[i].search; ++i) {
- c = *Find[i].search;
- if (Hash[c] > 0)
- Hash[c] = -Hash[c];
- if (Hash[c] == 0)
- Hash[c] = i | 0x100;
- }
- }
-
-
- void
- free_entry()
- {
- free_table(0, NOHOLD);
- Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry));
- bzero (Entry[0].fields, sizeof(Entry[0].fields));
- File_size = Entries = 0;
- Entry->status = Entry->no = Entry->fpos = Current = 0;
- Listsize = 3;
- if (m_fi) {
- fclose (m_fi);
- m_fi = NULL;
- }
- }
-
-
- static void
- free_table(at, hold)
- {
- int i, j;
-
- for (i = at; i < Entries; ++i) {
- xfree (Entry[i].from);
- for (j = 0; Find[j].search != NULL; ++j) {
- if (Entry[i].fields[j] != quo_quo)
- xfree (Entry[i].fields[j]);
- }
- }
- Entries = (hold == HOLD) ? Entries : at;
- File_size = (at) ? Entry[Entries].fpos : 0;
- }
-
- static
- search_from(fi)
- FILE *fi;
- {
- while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
- if (isfrom (Buf))
- return (1);
- }
- return (0);
- }
-
-
- save_file(reload, mark, notmark)
- {
- FILE *fiscr;
- int fdscr;
- int i, count;
- char scratch[64];
-
- for (i = 0; i < Entries; ++i) {
- if ((Entry[i].status & mark) != mark ||
- (~Entry[i].status & notmark) != notmark)
- break;
- }
- if (i == Entries) {
- m_select (Nulav, M_RESET);
- puts ("No Changes Made");
- return (Entries);
- }
- if (m_fi == NULL)
- return (-1);
- count = 0;
- sprintf(scratch, "t:dmail%d", getpid());
- do_flock (fileno(m_fi), LOCK_EX);
- fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE);
- #ifdef AMIGA /* fix bug in Lattice C fdopen */
- fiscr = fopen("nil:", "w");
- fclose(fiscr);
- #endif
- fiscr = fdopen (fdscr, "a+");
- for (i = 0; i < Entries; ++i) {
- if ((Entry[i].status & mark) == mark &&
- (~Entry[i].status & notmark) == notmark) {
- ++count;
- fputs ("From ", fiscr);
- fputs (Entry[i].from, fiscr);
- putc ('\n', fiscr);
- fseek (m_fi, Entry[i].fpos, 0);
- while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
- if (isfrom(Buf))
- break;
- fputs (Buf, fiscr);
- }
- }
- }
-
- /*
- * If new mail has come in, append to the scratch file as well.
- * NOTE: for some machines like the Amiga an already open descriptor
- * does not know about any new data, thus we cannot simply
- * use m_fi .
- */
-
- {
- FILE *fi;
-
- if (fi = fopen(mail_file, "r")) {
- fseek(fi, File_size, 0);
- while (fgets(Buf, MAXFIELDSIZE, fi))
- fputs(Buf, fiscr);
- fclose(fi);
- }
- }
-
- /* Write scratch file back to mail file, or try to */
-
- fflush (fiscr);
- fflush (m_fi);
-
- lseek (fdscr, 0 ,0);
- #ifdef UNIX
- lseek (fileno(m_fi), 0, 0);
- while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
- write (fileno(m_fi), Buf, i);
- ftruncate (fileno(m_fi), lseek (fileno(m_fi), 0, 1));
- #else
- fclose(m_fi);
- if (m_fi = fopen (mail_file, "w")) {
- while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
- write (fileno(m_fi), Buf, i);
- fclose(m_fi);
- m_fi = fopen (mail_file, "r+");
- }
- if (m_fi == NULL) {
- printf("Unable to re-open %s !\n", mail_file);
- return(-1);
- }
- #endif
- if (lseek (fileno(m_fi), 0, 2) == 0 && !reload) {
- if (Did_cd == 0) {
- fclose(m_fi);
- m_fi = NULL;
- if (unlink (mail_file) == 0)
- printf ("%s Removed\n", mail_file);
- else
- printf ("0 messages left in %s\n", mail_file);
- }
- }
- fclose (fiscr);
- if (m_fi)
- fclose (m_fi); /* Effectively unlocks the descriptor */
- m_fi = NULL;
- unlink (scratch);
- if (reload) {
- free_entry();
- load_mail(0, 0);
- }
- m_select (Nulav, M_RESET);
- return (count);
- }
-
- void
- check_new_mail()
- {
- FILE *fi;
-
- push_break();
- if (m_fi == NULL) {
- m_fi = fopen (mail_file, "r+");
- if (m_fi == NULL) {
- pop_break();
- return;
- }
- }
- if (fi = fopen(mail_file, "r")) {
- if (fseek(fi, 0, 2) < 0 || ftell(fi) != File_size)
- load_mail(Entries, 1);
- fclose(fi);
- }
- pop_break();
- }
-
-
- write_file(file, modes, mark, notmark)
- char *file;
- {
- int i, fd = 1, notopen = 1;
- FILE *fi = NULL;
-
- for (i = 0; i < Entries; ++i) {
- if ((Entry[i].status & mark) == mark &&
- (~Entry[i].status & notmark) == notmark) {
- if (notopen) {
- notopen = 0;
- fd = open (file, O_APPEND | O_WRONLY | modes, MAILMODE);
- if (fd < 0)
- return (-1);
- do_flock (fd, LOCK_EX);
- #ifdef AMIGA /* fix bug in Lattice C fdopen */
- fi = fopen("nil:", "w");
- fclose(fi);
- #endif
- fi = fdopen (fd, "a");
-
- #ifdef NOTDEF
- if (fi) {
- printf("ptr %08lx\n", fi->_ptr);
- printf("rcnt %08lx\n", fi->_rcnt);
- printf("wcnt %08lx\n", fi->_wcnt);
- printf("base %08lx\n", fi->_base);
- printf("size %08lx\n", fi->_size);
- printf("flag %08lx\n", fi->_flag);
- printf("file %08lx\n", fi->_file);
- return(-1);
- }
- #endif
- }
- fputs ("From ", fi);
- fputs (Entry[i].from, fi);
- putc ('\n', fi);
- if (m_fi) {
- fseek (m_fi, Entry[i].fpos, 0);
- while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
- if (isfrom(Buf))
- break;
- fputs (Buf, fi);
- }
- }
- }
- }
- if (!notopen)
- fclose (fi);
- return (1);
- }
-
- /*
- * Basic scheme: Each entry has a fields list. Each entry in the fields list
- * is guarenteed to be a valid malloc'd pointer (except some may be set to
- * quo_quo).
- *
- * The find[] struct array holds the field name and length, the index
- * corresponding to the index into the field[] in an Entry.
- *
- * The header and width arrays hold the list format.
- */
-
- get_extra_ovr(str)
- char *str;
- {
- register int i;
-
- i = get_extra (str);
- if (i < 0) {
- i = add_extra (str);
- load_changes();
- }
- return (i);
- }
-
-
- /*
- * If there's room to add it, append to end.
- * Else Find oldest field which doesn't exist in the setlist and replace it
- * with the new one.
- */
-
- add_extra(str)
- char *str;
- {
- register int i, j, j_age, k;
-
- for (i = EXSTART; i < MAXTYPE; ++i) {
- if (Find[i].search == NULL)
- break;
- ++Find[i].age;
- }
- if (i == MAXTYPE) { /* No room to add onto end */
- j = j_age = -1;
- for (i = EXSTART; i < MAXTYPE; ++i) {
- for (k = 0; k < Listsize; ++k) {
- if (i == header[k])
- break;
- }
- if (k == Listsize && Find[i].age > j_age) {
- j = i;
- j_age = Find[i].age;
- }
- }
- i = j;
- }
- if (i < 0)
- return (-1);
- push_break();
- if (Find[i].search != NULL)
- xfree (Find[i].search);
- Find[i].len = strlen(str);
- Find[i].search = malloc (Find[i].len + 1);
- Find[i].notnew = Find[i].age = 0;
- strcpy (Find[i].search, str);
- changed = 1;
- for (j = 0; j < Entries; ++j) {
- if (Entry[j].fields[i] && Entry[j].fields[i] != quo_quo)
- xfree (Entry[j].fields[i]);
- Entry[j].fields[i] = quo_quo;
- }
- pop_break();
- return (i);
- }
-
-
- get_extra(str)
- char *str;
- {
- int i;
-
- for (i = 0; Find[i].search; ++i) {
- if (strncmp (str, Find[i].search, strlen(str)) == 0) {
- Find[i].age = 0;
- return (i);
- }
- }
- return (-1);
- }
-
-
- m_select(sav, mode)
- register char *sav[];
- {
- char *ptr, *dest;
- char l_map[256];
- int idx[MAXLIST], ix = 0;
- int ok, not, len, scr;
- register int i, j, avi;
-
- for (i = 0;i < 256; ++i)
- l_map[i] = i;
- for (i = 'A'; i <= 'Z'; ++i)
- l_map[i] += 'a' - 'A';
- hold_load();
- i = 0;
- idx[ix++] = get_extra_ovr (sav[i++]);
- for (; sav[i]; ++i) {
- if (strcmp (sav[i], ",") == 0 && sav[i + 1])
- idx[ix++] = get_extra_ovr (sav[++i]);
- }
- idx[ix] = -1;
- nohold_load();
- j = 1;
- push_break();
- for (i = 0; i < Entries; ++i) {
- if (mode == M_CONT && Entry[i].no == 0)
- continue;
- ix = ok = 0;
- avi = 1;
- while ((ptr = sav[avi]) != NULL) {
- if (ptr[0] == ',' && ptr[1] == '\0' && sav[avi+1]) {
- ++ix;
- avi += 2;
- continue;
- }
- if (not = (*ptr == '!'))
- ++ptr;
- len = strlen (ptr);
- dest = Entry[i].fields[idx[ix]];
- if (*ptr == '\0') {
- ok = 1;
- goto gotit;
- }
- while (*dest) {
- scr = 0;
- while (l_map[dest[scr]] == l_map[ptr[scr]] && ptr[scr])
- ++scr;
- if (ptr[scr] == '\0') {
- ok = 1;
- goto gotit;
- }
- ++dest;
- }
- ++avi;
- }
- gotit:
- Entry[i].no = (ok ^ not) ? j++ : 0;
- }
- pop_break();
- if (Current < 0)
- Current = 0;
- if (Entries) {
- if (Entry[Current].no == 0) {
- Current = indexof (1);
- if (Current < 0) {
- Current = 0;
- return (-1);
- }
- }
- } else {
- Current = -1;
- }
- return (1);
- }
-
-
-