dillon@ucbvax.BERKELEY.EDU (Matt Dillon) (12/08/85)
Sorry, it would seem that a couple problems cropped up. I will just repost the entire thing... this time, I also have the MAN page. problems that occured: Make had a problem with spaces in-front of shell commands some 4.2 systems don't have <fcntl.h> some files were not tabbed correctly (dmail.help) Please bear with me.... after all, this is the first time I've posted something to this net. I've split the program up into Three sections. Don't combine these files with files from the first posting, just redo it with these. Thanks, -Matt #-----cut here-----cut here-----cut here-----cut here----- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # execom.c # execom.h # globals.c # help.c # load_mail.c # This archive created: Sat Dec 7 15:27:26 1985 export PATH; PATH=/bin:$PATH echo shar: extracting "'execom.c'" '(14695 characters)' if test -f 'execom.c' then echo shar: will not over-write existing file "'execom.c'" else cat << \!Funky!Stuff! > 'execom.c' /* * EXECOM.C * * Matthew Dillon, 6 December 1985 * * * (C) 1985 Matthew Dillon * * Routines to parse and execute command lines. * * Global Routines: DO_COMMAND() * EXEC_COMMAND() * FIX() * * Static Routines: E_COMMAND() * BREAKOUT() * FIND_COMMAND() */ #include <pwd.h> #include <stdio.h> #include <strings.h> #include "dmail.h" #include "execom.h" #define C_NO 1 #define C_NOEXPN 2 #define F_EXACT 0 #define F_ABBR 1 #define SCRBUF 1024 extern char *breakout(); extern int do_quit(), do_exit(), do_help(), do_list(), do_setlist(); extern int do_select(), do_type(), do_header(), do_next(), do_mark(); extern int do_unmark(), do_reply(), do_delnext(); extern int do_write(), do_shell(), do_set_var(), do_unset_var(); extern int do_number(), do_cd(), do_source(), do_defer(), do_echo(); extern int do_go(); struct COMMAND Command[] = { do_number , 0, 0, "", do_mark , 0, ST_DELETED, "delete", do_unmark , 0, ST_DELETED, "undelete", do_header , 0, 0, "header", do_type , 0, 0, "type", do_echo , 0, 0, "echo", do_go , 0, 0, "go", do_reply , 0, R_REPLY, "reply", do_reply , 0, R_INCLUDE, "Reply", do_reply , 0, R_MAIL, "mail", do_reply , 0, R_FORWARD, "forward", do_select , 0, 0, "select", do_select , 0, 1, "reselect", do_defer , 0, 1, "defer", do_list , 0, 0, "list", do_next , 0, 1, "next", do_next , 0, -1, "back", do_next , 0, 2, "_next", do_next , 0, -2, "_back", do_delnext , 0, 0, "dt", do_set_var , 0, 0, "set", do_unset_var, 0, 0, "unset", do_set_var , C_NOEXPN, 1, "alias", do_unset_var, C_NOEXPN, 1, "unalias", do_set_var , C_NO, 2, "malias", do_unset_var, C_NO, 2, "munalias", do_setlist , 0, 0, "setlist", do_cd , 0, 0, "cd", do_source , 0, 0, "source", do_unmark , 0, ST_READ | ST_STORED,"preserve", do_mark , 0, ST_READ, "mark", do_mark , 0, ST_TAG, "tag", do_unmark , 0, ST_TAG, "untag", do_unmark , 0, ST_STORED, "unwrite", do_write , 0, 0, "write", do_shell , 0, 0, "!", do_exit , 0, 0, "x", do_quit , 0, 0, "quit", do_exit , 0, 1, "xswitch", do_quit , 0, 1, "qswitch", do_help , 0, 0, "help", do_help , 0, 0, "?", NULL , 0, 0, NULL }; char *Desc[] = { "", "<list> mark messages for deletion", "<list> UNDELETE & UNMARK messages", "[msg] Display header of a message", "[msg] type a message", "args.... Echo to the screen", "# Go to a message, don't print out", " reply to mail", " reply to mail, include recv'd text", "user user ... send mail to users", "user user ... forward mail to users", "Field [!]match [match][ , Field match.] SELECT from entire message list", "Field [!]match [match][ , Field match.] SELECT from current message list", " De-select any read messages", "<list> list mail as specified by SETLIST", "[msg] type/header next or message #", "[msg] type/header previous or message #", "[msg] go to next or message #", "[msg] go to previous or message #", " delete current, type next", "[var [string]] set a variable", "var var var ... unset a variable", "[var [string]] set an alias", "var var var ... unset an alias", "[var [string]] set a mail alias", "var var var ... unset a mail alias", "[-s] [cols] Field [cols] Field... SET LIST format for LIST", "path CD to a directory", "file Source a file", "<list> UNREAD & UNMARK messages", "<list> mark messages as 'read'", "<list> tag messages for whatever", "<list> untag messages", "<list> unwrite messages", "file <list> append messages to a file, delete on quit", "[command] execute a shell [command]", " EXIT, do not save changes", " QUIT, update files", "from to Exit and switch to a new from/to file", "from to Quit and switch to a new from/to file", "[topic] help on a topic", "[topic] alternate form of HELP", NULL }; do_command() { int i; char *str; static char comline[1024]; printf ("%3d:", Entry[Current].no); fflush (stdout); if (gets (comline) == NULL) done (1); exec_command(comline); return (1); } /* * EXEC_COMMAND() * * */ struct MLIST { struct MLIST *next; }; static struct MLIST *Mlist; char * mpush(amount) int amount; { struct MLIST *ml; push_break(); ml = (struct MLIST *)malloc (amount + sizeof(Mlist)); ml->next = Mlist; Mlist = ml; pop_break(); return ((char *)Mlist + sizeof(Mlist)); } char * mpop() { char *old = NULL; push_break(); if (Mlist == NULL) { puts ("MLIST INTERNAL ERROR"); } else { old = (char *)Mlist + sizeof(Mlist); free (Mlist); Mlist = Mlist->next; } pop_break(); return (old); } mrm() { push_break(); while (Mlist) { free (Mlist); Mlist = Mlist->next; } pop_break(); } exec_command(base) char *base; { char *str; int i; if (push_base()) { push_break(); pop_base(); mrm(); pop_break(); return (-1); } strcpy (str = mpush(strlen(base) + 1), base); i = e_command(str); if (mpop() != str) puts ("POP ERROR"); pop_base(); return (i); } static e_command(base) char *base; { char *com, *start, *Scr, *avline, *alias; int flag = 0; int i, pcount, len, ccno; loop: com = breakout (&base, &flag); if (*com == '\0') { if (flag > 1) return (1); goto loop; } if ((ccno = find_command(com, F_EXACT)) < 0) { if (*com == '$') alias = get_var (LEVEL_SET, com + 1); else alias = get_var (LEVEL_ALIAS, com); if (alias == NULL) { if ((ccno = find_command (com, F_ABBR)) < 0) { printf ("%s Command Not found\n", com); return (-1); } else { goto good_command; } } /* At this point, base points to arguments */ start = (flag == 0) ? base : ""; while (flag == 0) { /* find ';' or end of string */ flag = -1; /* disable breakout's "" terminator */ breakout (&base, &flag); } /* * At this point, start points to all arguments, base set up for next * string */ if (*alias == '%') { int xx = 0; char *select; alias = strcpy (mpush (strlen(alias) + 1), alias); select = breakout (&alias, &xx); set_var (LEVEL_SET, select + 1, start); i = e_command (alias); unset_var (LEVEL_SET, select + 1); mpop(); } else { com = mpush (strlen(alias) + strlen(start) + 2); strcpy (com, alias); strcat (com, (flag == 1) ? ";" : " "); strcat (com, start); i = e_command (com); if (mpop() != com) puts ("ME BAE ERROR"); } if (i < 0) return (-1); if (flag > 1) return (1); goto loop; } good_command: pcount = 0; if (Command[ccno].stat & C_NO && Debug == 0) { printf ("%s Is currently being developed\n", Command[ccno].name); return (-1); } if (Debug) printf ("Good command, Raw: %s\n", com); i = pcount = 0; av[i] = mpush (strlen(com) + 1); ++pcount; strcpy (av[i++], com); while (flag < 1) { com = breakout (&base, &flag); if (Debug) printf ("BREAKOUT %d %s\n", strlen(com), com); if (*com == '\0') continue; switch (*com) { case '~': if (com[1] == '/' || com[1] == '\0') { av[i] = mpush (strlen(home_dir) + strlen(com + 1) + 1); ++pcount; strcpy (av[i], home_dir); strcat (av[i], com + 1); } else { struct passwd *passwd; char *user = com; while (*com) { if (*com == '/') { *com = '\0'; ++com; break; } ++com; } if ((passwd = getpwnam(user)) == NULL) { printf ("USER %s Not found\n", user); while (pcount--) mpop(); return (-1); } av[i] = mpush (strlen(passwd->pw_dir) + strlen(com) + 2); ++pcount; strcpy (av[i], passwd->pw_dir); if (*com) { strcat (av[i], "/"); strcat (av[i], com); } } break; case '\"': av[i] = com + 1; while (*++com && *com != '\"'); *com = '\0'; break; case '$': av[i] = get_var (LEVEL_SET, com + 1); if (av[i] == NULL) { printf ("Variable: %s Not found\n", com + 1); while (pcount--) mpop(); return (-1); } av[i] = strcpy (mpush(strlen(av[i]) + 1), av[i]); ++pcount; break; default: av[i] = com; break; } ++i; } av[i] = NULL; ac = i; for (len = 0, i = 0; i < ac; ++i) len += strlen (av[i]) + 1; avline = mpush (len + 1); *avline = '\0'; for (i = 0; i < ac; ++i) { strcat (avline, av[i]); if (i + 1 < ac) strcat (avline, " "); } if (Debug) printf ("DEST: %s\n", avline); i = (*Command[ccno].func)(avline, Command[ccno].val); if (mpop() != avline) puts ("AVLINE ERROR"); while (pcount--) mpop(); fix(); if (i < 0) return (i); if (flag < 2) goto loop; return (1); } /* * BREAKOUT * * Breakout next argument. If FLAG is set to 1 on return, the argument * returned is the last in the command. If FLAG is set to 2 on return, the * argument returned is the last, period. * */ static char * breakout(base, flag) int *flag; char **base; { register char *str, *scr; loop: str = *base; /* next start */ while (*str == ' ' || *str == 9) /* skip spaces and such */ ++str; switch (*str) { case '\0': /* no more arguments */ *flag = 2; *base = str; return (str); case ';': /* no more args in this command */ *flag = 1; *str = '\0'; *base = str + 1; return (str); } scr = str; for (;;) { /* valid argument of somesort */ switch (*scr) { case ' ': case 9: if (*flag >= 0) *scr = '\0'; *base = scr + 1; *flag = 0; return (str); case '\"': ++scr; while (*scr && (*scr++ != '\"')); /* place to end of quote */ break; case '\0': *flag = 2; *base = scr; return (str); case ';': *flag = 1; *base = scr + 1; *scr = '\0'; return (str); default: ++scr; } } } fix() { register int i; for (i = Current; i < Entries; ++i) { if (Entry[i].no && !(Entry[i].status & ST_DELETED)) { Current = i; return (1); } } if (Current >= Entries) { Current = Entries - 1; if (Current < 0) Current = 0; } for (i = Current; i >= 0; --i) { if (Entry[i].no && !(Entry[i].status & ST_DELETED)) { Current = i; return (-1); } } Current = 0; return (-1); } static find_command(str, arg) char *str; int arg; { int i; int len = strlen (str); if (*str >= '0' && *str <= '9') return (0); for (i = 0; Command[i].func; ++i) { if (strncmp (str, Command[i].name, len) == 0) { if (arg == F_ABBR) return (i); if (strcmp (str, Command[i].name) == 0) return (i); return (-1); } } return (-1); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'execom.h'" '(142 characters)' if test -f 'execom.h' then echo shar: will not over-write existing file "'execom.h'" else cat << \!Funky!Stuff! > 'execom.h' struct COMMAND { int (*func)(); int stat; int val; char *name; }; extern struct COMMAND Command[]; extern char *Desc[]; !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'globals.c'" '(1900 characters)' if test -f 'globals.c' then echo shar: will not over-write existing file "'globals.c'" else cat << \!Funky!Stuff! > 'globals.c' /* * GLOBALS.C * * Matthew Dillon, 6 December 1985 * * * (C) 1985 Matthew Dillon * * Declarations for most global variables. * */ #include <stdio.h> #include "dmail.h" FILE *m_fi; /* open file ptr to spool file */ char *mail_file; /* name of from (spool) file */ char *output_file; /* name of out file (i.e. mbox) */ char *user_name; /* user name from password entry*/ char *home_dir; /* home directory of user */ char *visual; /* visual editor path */ char Buf[MAXFIELDSIZE]; /* Scratch Buffer */ char Puf[MAXFIELDSIZE]; /* Another Scratch Buffer */ jmp_buf env[LONGSTACK]; /* Holds longjump stack */ int Debug; /* Debug mode */ int _ls, Longstack, Breakstack; /* longjump/break level stack */ int Entries, Current; /* #Entries and Current entry */ int ac; /* internal argc, from/to stat */ int No_load_mail; /* disable loading of mail */ int Silence; /* -s command option status */ struct ENTRY *Entry; /* Base of Entry list */ char *av[128]; /* internal argv[] */ int width[MAXLIST] = { 18, 38, 10 }; /* Default setlist params */ int header[MAXLIST] = { 0, 2, 1 }; int Listsize = 3; /* The following are globals variables definable from the 'set' command */ char *S_sendmail; /* sendmail program path */ int S_page; /* Paging status */ int S_novibreak; /* vi-break status */ int S_verbose; /* sendmail verbose status */ int S_ask; !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'help.c'" '(2873 characters)' if test -f 'help.c' then echo shar: will not over-write existing file "'help.c'" else cat << \!Funky!Stuff! > 'help.c' /* * HELP.C * * Matthew Dillon, 6 December 1985 * * * (C) 1985 Matthew Dillon * * Global Routines: DO_HELP() * */ #include <stdio.h> #include "dmail.h" #include "execom.h" #ifndef HELPFILE static char *help[] = { #include ".dmkout" }; do_help() { int i, j; char *ptr; if (push_base()) { push_break(); pop_base(); PAGER (-1); pop_break(); return; } PAGER (0); if (ac == 1) { for (j = 0; help[j] && *help[j] != '.'; ++j) PAGER (help[j]); for (i = 0; Command[i].name != NULL; ++i) { if (*Command[i].name) { sprintf (Puf, "%-10s %s", Command[i].name, Desc[i]); PAGER (Puf); } } } PAGER (""); for (i = 1; i < ac; ++i) { j = 0; again: while (help[j] && *help[j] != '.') ++j; if (help[j]) { if (strncmp (av[i], help[j] + 1, strlen(av[i]))) { ++j; goto again; } while (help[j] && *help[j] == '.') ++j; while (help[j] && *help[j] != '.') PAGER (help[j++]); PAGER (""); goto again; } } PAGER (-1); pop_base(); } #else do_help() { int i, j; FILE *fi = NULL; char *ptr; char *eof; if (push_base()) { push_break(); pop_base(); PAGER (-1); if (fi != NULL) { fclose (fi); fi = NULL; } pop_break(); return (-1); } fi = fopen (HELPFILE, "r"); if (fi == NULL) { printf ("Cannot open help file: %s\n", HELPFILE); PAGER (-1); pop_base(); return (-1); } PAGER (0); if (ac == 1) { while (fgets (Puf, MAXFIELDSIZE, fi) && *Puf != '.') FPAGER (Puf); fclose (fi); fi = NULL; for (i = 0; Command[i].name != NULL; ++i) { if (*Command[i].name) { sprintf (Puf, "%-10s %s", Command[i].name, Desc[i]); PAGER (Puf); } } PAGER (-1); pop_base(); return (1); } PAGER (""); for (i = 1; i < ac; ++i) { fseek (fi, 0, 0); again: while ((eof = fgets (Puf, MAXFIELDSIZE, fi)) && *Puf != '.'); if (!eof) continue; if (strncmp (av[i], Puf + 1, strlen(av[i]))) goto again; while ((eof = fgets (Puf, MAXFIELDSIZE, fi)) && *Puf == '.'); if (!eof) continue; FPAGER (Puf); while ((eof = fgets (Puf, MAXFIELDSIZE, fi)) && *Puf != '.') FPAGER (Puf); PAGER (""); if (!eof) continue; goto again; } fclose (fi); fi = NULL; PAGER (-1); pop_base(); } #endif !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'load_mail.c'" '(13693 characters)' if test -f 'load_mail.c' then echo shar: will not over-write existing file "'load_mail.c'" else cat << \!Funky!Stuff! > 'load_mail.c' /* * LOAD_MAIL.C * * Matthew Dillon, 6 December 1985 * * * 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" #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, "To:" , 3, 1, "Subject:", 8, 1 }; static int File_size; static int changed, load_hold; static int Hash[256]; hold_load() { load_hold = 1; } nohold_load() { load_hold = 0; load_changes(); } 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); 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) return (-1); flock (m_fi->_file, 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) { printf ("%d New Items loaded\n", count - Entries); Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1)); } Entries = count; for (i = at; i < Entries; ++i) Entry[i].no = 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; flock (m_fi->_file, LOCK_UN); return (1); } 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 (Debug) 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 (Debug) 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 (Debug) 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] = malloc (1); *(Entry[count].fields[i]) = '\0'; } } } } File_size = ftell (fi); fclose (fi); return (1); } static 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; } } free_entry() { free_table(0, NOHOLD); Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry)); File_size = Entries = 0; Entry->status = Entry->no = Entry->fpos = Current = 0; if (m_fi) fclose (m_fi); } static free_table(at, hold) { int i, j; for (i = at; i < Entries; ++i) { free (Entry[i].from); for (j = 0; Find[j].search != NULL; ++j) free (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 *fi, *fiscr; int fd, fdscr; int new_size, i; char scratch[64]; char buf[MAXFIELDSIZE]; char *avnul[1]; avnul[0] = NULL; if (m_fi) fclose (m_fi); for (i = 0; i < Entries; ++i) { if ((Entry[i].status & mark) != mark || (~Entry[i].status & notmark) != notmark) break; } if (i == Entries) { m_select (avnul, M_RESET); puts ("No Changes Made"); return (Entries); } sprintf (scratch, "/tmp/dmail%d", getpid()); fd = open (mail_file, O_RDWR, 0); if (fd < 0) return (-1); flock (fd, LOCK_EX); fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE); fi = fdopen (fd, "r+"); fiscr = fdopen (fdscr, "a+"); for (i = 0; i < Entries; ++i) { if ((Entry[i].status & mark) == mark && (~Entry[i].status & notmark) == notmark) { fputs ("From ", fiscr); fputs (Entry[i].from, fiscr); fputc ('\n', fiscr); fseek (fi, Entry[i].fpos, 0); while (fgets (buf, MAXFIELDSIZE, fi) != NULL) { if (isfrom(buf)) break; fputs (buf, fiscr); } } } /* If NEW MAIL has come in, append that to the scratch file also */ new_size = fseek (fi, 0, 2); if (File_size != new_size) { fseek (fi, File_size, 0); while (fgets (buf, MAXFIELDSIZE, fi) != NULL) fputs (buf, fiscr); } /* Write scratch file back to mail file, or try to */ fflush (fi); fflush (fiscr); fseek (fi , 0, 0); fseek (fiscr, 0, 0); lseek (fd , 0, 0); lseek (fdscr, 0, 0); while ((i = read (fdscr, buf, MAXFIELDSIZE)) > 0) write (fd, buf, i); ftruncate (fd, lseek (fd, 0, 1)); if (lseek (fd, 0, 2) == 0 && !reload) { printf ("%s Removed\n", mail_file); unlink (mail_file); } fclose (fi); fclose (fiscr); unlink (scratch); if (reload) { free_entry(); load_mail(0, 0); } m_select (avnul, M_RESET); return (0); } check_new_mail() { push_break(); if (m_fi == NULL) { m_fi = fopen (mail_file, "r"); if (m_fi == NULL) { pop_break(); return; } } if (fseek (m_fi, 0, 2) != File_size) load_mail(Entries, 1); pop_break(); } write_file(file, modes, mark, notmark) char *file; { int i, fd, notopen = 1; FILE *fi; char buf[MAXFIELDSIZE]; 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); flock (fd, LOCK_EX); fi = fdopen (fd, "a"); } fputs ("From ", fi); fputs (Entry[i].from, fi); fputc ('\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); } get_extra_ovr(str) char *str; { register int i; i = get_extra (str); if (i < 0) { i = add_extra (str); load_changes(); } return (i); } add_extra(str) char *str; { int i, j; for (i = 0; i < MAXTYPE; ++i) { if (Find[i].search == NULL) break; } if (i == MAXTYPE) i = EXSTART; for (; i < MAXTYPE; ++i) { for (j = 0; j < Listsize; ++j) { if (i == header[j]) break; } if (j == Listsize) break; } if (i >= MAXTYPE) return (-1); if (Find[i].search != NULL) free (Find[i].search); Find[i].len = strlen(str); Find[i].search = malloc (Find[i].len + 1); Find[i].notnew = 0; strcpy (Find[i].search, str); changed = 1; return (i); } delete_extra(str) char *str; { int i; for (i = EXSTART; Find[i].search; ++i) { if (strncmp (Find[i].search, str, strlen(str)) == 0) { free (Find[i].search); do { Find[i].search = Find[i + 1].search; } while (Find[++i].search); changed = 1; return (i); } } return (-1); } delete_all() { int i; for (i = EXSTART; Find[i].search; ++i) { free (Find[i].search); changed = 1; } return (1); } get_extra(str) char *str; { int i; for (i = 0; Find[i].search; ++i) { if (strncmp (str, Find[i].search, strlen(str)) == 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; 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; } if (Entry[Current].no == 0) { Current = indexof (1); if (Current < 0) { Current = 0; return (-1); } } return (1); } !Funky!Stuff! fi # end of overwriting check # End of shell archive exit 0