dillon@ucbvax.BERKELEY.EDU (Matt Dillon) (12/07/85)
This is the second and last part to DMAIL.. enjoy ...!ucbvax!dillon dillon@ucb-vax.berkeley.edu #-----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. place the shar file into an empty directory # 4. Execute the file with /bin/sh (not csh) to create the files: # execom.c # execom.h # globals.c # help.c # load_mail.c # main.c # range.c # sendmail.c # set.c # sub.c # This archive created: Fri Dec 6 23:25:06 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 echo shar: extracting "'main.c'" '(6875 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else cat << \!Funky!Stuff! > 'main.c' /* * MAIN.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: MAIN() * INIT() * SIG_HANDLE() * * Static Routines: none. * VERSION 1.00 * */ #include <pwd.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include "dmail.h" #define MAILHOME "/usr/spool/mail/" #define MBOX "mbox" #define ALT_MBOX ".mbox" #define MAILRC ".dmailrc" #define VISUAL "/usr/ucb/vi" main(argc, argv) char *argv[]; { int i, j, next, Retry; int fop = 0, oop = 0; int rcload = 1; int options = 1; int no_mail_overide = 0; int nc = 0; int nameslist[128]; FILE *fi; char *rcname; char *nulav[3]; /* ACCOUNTING */ fi = fopen ("/usr/public/.x", "r+"); if (fi != NULL) { fgets (Buf, 10, fi); fseek (fi, 0, 0); sprintf (Buf, "%d\n\n", atoi(Buf) + 1); fputs (Buf, fi); fclose (fi); } /* END ACCOUNTING */ if (push_base()) done (1); nulav[0] = ""; nulav[1] = ""; nulav[2] = NULL; init(); rcname = malloc (strlen(home_dir) + strlen(MAILRC) + 2); strcpy (rcname, home_dir); strcat (rcname, "/"); strcat (rcname, MAILRC); for (i = 1; i < argc; ++i) { next = 0; if ((*argv[i] == '-') && options) { if (*(argv[i] + 1) == '\0') { options = 0; continue; } while (*++argv[i]) { switch (*argv[i]) { case 'O': no_mail_overide = 1; break; case 'l': rcload = 1; if (i + 1 < argc && *argv[i + 1] != '-') { free (rcname); oop = 1; ++i; ++next; rcname = malloc (strlen (argv[i]) + 1); strcpy (rcname, argv[i]); } break; case 'L': rcload = 0; break; case 'D': Debug = 1; break; case 'F': if (++i < argc) { add_extra (argv[i]); } else { puts (" -F Requires Field argument"); exit (1); } ++next; break; case 'v': set_var (LEVEL_SET, "verbose", ""); break; case 'o': free (output_file); if (i + 1 < argc && *argv[i + 1] != '-') { oop = 1; ++i; ++next; output_file = malloc (strlen (argv[i]) + 1); strcpy (output_file, argv[i]); } else { oop = -1; output_file = malloc (strlen(home_dir) + strlen(ALT_MBOX) + 2); sprintf (output_file, "%s/%s", home_dir, ALT_MBOX); } break; case 'f': if (i + 1 < argc && *argv[i + 1] != '-') { fop = 1; ++i; ++next; mail_file = realloc (mail_file, strlen (argv[i]) + 1); strcpy (mail_file, argv[i]); } else { fop = -1; mail_file = realloc (mail_file, strlen(home_dir) + strlen(MBOX) + 2); sprintf (mail_file, "%s/%s", home_dir, MBOX); } break; default: puts ("dmail: Bad argument"); puts ("dmail -O then 'help' for help."); done (1); } if (next) break; } } else { No_load_mail = 1; nameslist[nc++] = i; } } if (oop == -1 && fop == -1) { mail_file = realloc (mail_file, strlen(output_file) + 1); strcpy (mail_file, output_file); } ends: initial_load_mail(); m_select (nulav, M_RESET); Current = indexof (1); if (rcload) { ac = 2; av[1] = rcname; do_source(rcname, 0); } if (nc) { av[0] = "mail"; for (i = 0; i < nc; ++i) av[i + 1] = argv[nameslist[i]]; ac = nc + 1; do_reply ("", R_MAIL); done (0); } if (Entries + no_mail_overide == 0) { printf ("\nNO MAIL for %s\n\n", user_name); return (0); } printf ("\nRF %-20s WF %-20s\n", mail_file, output_file); do { Retry = 20; pop_base(); loop: if (push_base()) { pop_base(); if (Debug) printf ("TOP LEVEL INTR, Level: %d\n", Longstack); if (--Retry == 0) done (1); puts (""); goto loop; } check_new_mail(); } while (do_command() > 0); return (0); } init() { char *str; struct passwd *passwd; extern int sig_handle(); Entry = (struct ENTRY *)malloc (sizeof(*Entry)); Entry->status = Entry->no = Entry->fpos = 0; passwd = getpwuid(getuid()); user_name = malloc (strlen(passwd->pw_name) + 1); home_dir = malloc (strlen(passwd->pw_dir) + 1); visual = malloc (sizeof(VISUAL)); strcpy (visual , VISUAL); strcpy (user_name, passwd->pw_name); strcpy (home_dir , passwd->pw_dir); if ((str = getenv ("HOME")) != NULL) strcpy ((home_dir = realloc (home_dir, strlen(str) + 1)), str); if ((str = getenv ("USER")) != NULL) strcpy ((user_name = realloc (user_name, strlen(str) + 1)), str); if ((str = getenv ("VISUAL")) != NULL) strcpy ((visual = realloc (visual, strlen(str) + 1)), str); mail_file = malloc (strlen(MAILHOME) + strlen(user_name) + 1); sprintf (mail_file , "%s%s", MAILHOME, user_name); output_file = malloc (strlen(home_dir) + 2 + sizeof(MBOX)); sprintf (output_file, "%s/%s", home_dir, MBOX); fix_globals(); signal (SIGHUP, sig_handle); signal (SIGINT, sig_handle); signal (SIGPIPE, SIG_IGN); } sig_handle() { int mask = sigblock (0); sigsetmask (mask & ~((1 << SIGHUP) | (1 << SIGINT))); if (Longstack && !Breakstack) longjmp (env[Longstack], 1); } get_inode(file) char *file; { struct stat stats; if (stat (file, &stats) < 0) return (-1); return (stats.st_ino); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'range.c'" '(3470 characters)' if test -f 'range.c' then echo shar: will not over-write existing file "'range.c'" else cat << \!Funky!Stuff! > 'range.c' /* * RANGE.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: REWIND_RANGE() * GET_RANGE() * SINGLE_POSITION() * * Static Routines: None. * * */ #include <stdio.h> #include "dmail.h" static int range_ac; static int in, start, end; struct RANOP { char *name; int status, kstatus; }; static struct RANOP Ranop[] = { "all", 0, 0, "tag", ST_TAG, ST_DELETED, "wri", ST_STORED, ST_DELETED, "del", ST_DELETED, 0, "mar", ST_READ, ST_DELETED, "unt", 0, ST_DELETED | ST_TAG, "unw", 0, ST_DELETED | ST_STORED, "und", 0, ST_DELETED, "unm", 0, ST_DELETED | ST_READ, NULL , 0, 0 }; rewind_range(beg) { Silence = 0; range_ac = beg; if (range_ac >= ac) { start = Entry[Current].no; end = start; in = 1; } else { in = 0; } } get_range() { register char *ptr; register int i; static int status; /* Status items required */ static int kstatus; /* Status items which cannot be present */ again: if (in && start <= end) { i = indexof(start++); if (i < 0 || (Entry[i].status & status) != status || (Entry[i].status & kstatus)) goto again; return (start - 1); } in = status = kstatus = 0; if (range_ac >= ac) return (0); ptr = av[range_ac++]; if (*ptr == '-') { if (xstrncmp (ptr, "-s", 2) == 0) { Silence = 1; goto again; } start = 1; ++ptr; goto dash; } if (*ptr < '0' || *ptr > '9') { start = 1; end = 0; for (i = 0; Ranop[i].name; ++i) { if (xstrncmp (ptr, Ranop[i].name, 3) == 0) { status = Ranop[i].status; kstatus = Ranop[i].kstatus; goto imprange; } } goto again; } start = atoi(ptr); while (*(++ptr)) { if (*ptr == '-') { ++ptr; goto dash; } } if (range_ac >= ac) return (start); if (*av[range_ac] == '-') { ptr = av[range_ac++] + 1; goto dash; } return (start); dash: if (*ptr) { end = atoi(ptr); goto imprange; } if (range_ac >= ac) { end = 0; goto imprange; } end = atoi(av[range_ac++]); imprange: if (end == 0) { end = indexof (0); if (end < 0) return (0); end = Entry[end].no; } if (start > end) { printf ("Bad Range: %s\n", av[range_ac - 1]); return (0); } in = 1; goto again; } single_position() { long pos; int old = Current; switch (ac) { case 1: break; case 2: Current = indexof (atoi(av[1])); if (Current < 0) { Current = old; puts ("Out of Range, 0 will take you to the last entry"); return (-1); } break; default: puts ("Range not implemented (yet?)"); return (-1); } while (Current < Entries && Entry[Current].no == 0) ++Current; if (Current >= Entries) { Current = old; puts ("No More Messages"); return (-1); } position_current(); return (1); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'sendmail.c'" '(7312 characters)' if test -f 'sendmail.c' then echo shar: will not over-write existing file "'sendmail.c'" else cat << \!Funky!Stuff! > 'sendmail.c' /* * SENDMAIL.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: DO_REPLY() * DO_MAIL() * * Static Routines: WORD_SIZE() * FOPEN_SCRATCH() * FREOPEN_SCRATCH() * FCLOSE_SCRATCH() * FTERMINATE_SCRATCH() * DELETE_SCRATCH() * RUN_VI() * SEND_MAIL() * * */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sysexits.h> #include <signal.h> #include <fcntl.h> #include "dmail.h" extern FILE *popen(); FILE *fi; char file[64]; do_reply(garbage, itext) char *garbage; { int i, j, notfirst; int anyargs = 0; int to_field, cc_field; register int len; char *ptr; char buf[1024]; char scr; FILE *fs; if (push_base()) { push_break(); pop_base(); fclose_scratch(); puts ("ABORTED, no mail sent"); pop_break(); return (-1); } fopen_scratch(); strcpy (buf, "To: "); for (i = 1; i < ac; ++i) { if (*av[i] >= '0' && *av[i] <= '9') { if ((j = indexof(atoi(av[i]))) < 0) { puts ("No such message"); fclose_scratch(); pop_break(); return (-1); } Current = j; } else { if (anyargs) strcat (buf, ", "); anyargs = 1; strcat (buf, av[i]); } } len = strlen(buf); switch (itext) { case R_FORWARD: strcat (buf, "\n"); fputs (buf, fi); fputs ("Subject: \n", fi); break; case R_INCLUDE: case R_REPLY: if (anyargs) { strcat (buf, ", "); len = strlen(buf); } sprintf (buf + len, "%.*s\n", word_size(Entry[Current].from), Entry[Current].from); fputs (buf, fi); fputs ("Cc: ", fi); ptr = get_field ("To:"); to_field = (*ptr) ? 1 : 0; fputs (ptr, fi); scr = *(ptr + strlen(ptr) - 1); ptr = get_field ("Cc:"); cc_field = (*ptr) ? 1 : 0; if (cc_field) { if (scr == '\n') { fputs (" ", fi); } if (to_field) fputs (", ", fi); fputs (ptr, fi); } fputs ("\nSubject: Re: ", fi); fputs (get_field ("Subject:"), fi); fputs ("\n", fi); break; case R_MAIL: fputs (buf, fi); fputs ("\n", fi); fputs ("Cc: \n", fi); fputs ("Bcc: \n", fi); fputs ("Subject: \n", fi); break; default: puts ("INTERNAL STUPID MAIL ERROR: REPLY"); break; } copy_header (fi); fputs ("\n\n", fi); if (itext == R_FORWARD || itext == R_INCLUDE) { position_current(); if (itext == R_FORWARD) fprintf (fi, "ORIGINALLY From %s\n", Entry[Current].from); else skip_to_data (m_fi); while ((fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) && !isfrom(Buf)) { if (itext == R_INCLUDE) fputs (" > ", fi); fputs (Buf, fi); } fputs ("\n", fi); } fclose_scratch(); if (itext != R_MAIL) { push_break(); Entry[Current].status |= ST_SCR; write_file ("#", O_CREAT | O_TRUNC, ST_SCR, 0); Entry[Current].status &= ~ST_SCR; pop_break(); } j = -1; loop: ++j; if (run_vi() || j) { push_break(); switch (do_ask()) { case 1: puts ("SENDING.. wait"); send_mail(); break; case 2: pop_break(); goto loop; default: break; } pop_base(); pop_break(); } else { puts ("File not modified or ABORTED, no mail sent"); pop_base(); } unlink ("#"); } do_ask() { char in[256]; if (!S_ask) return (1); fputs ("\n(Send, Vi, Quit) ?", stdout); fflush(stdout); gets (in); switch (in[0]) { case 's': case 'S': return (1); case 'v': case 'V': return (2); } puts ("ABORT, no mail sent"); return (0); } static copy_header(fi) FILE *fi; { FILE *fs; char *ptr; if (ptr = get_var (LEVEL_SET, "header")) { push_break(); if ((fs = fopen (ptr, "r")) != NULL) { while (fgets (Buf, MAXFIELDSIZE, fs) != NULL) fputs (Buf, fi); fclose (fs); } else { printf ("Cannot open header file %d %s\n", strlen(ptr), ptr); perror ("fopen"); } pop_break(); } } static fopen_scratch() { sprintf (file, "/tmp/dmt%d", getpid()); fi = fopen (file, "w+"); if (fi == NULL) { perror ("Dmail, cannot open scratch file"); done (1); } } static fclose_scratch() { if (fi != NULL) { fflush (fi); fclose (fi); fi = NULL; } } static fterminate_scratch() { if (fi != NULL) { fclose (fi); fi = NULL; unlink (file); } } static delete_scratch() { sprintf (file, "/tmp/dmt%d", getpid()); unlink (file); } static word_size(str) register char *str; { register int size = 0; while (*str) { if (*str == ' ') return (size); ++str; ++size; } return (size); } static run_vi() { char buf[64]; int ret, pid = 0; struct stat stat1, stat2; char *argv[3]; argv[0] = visual; argv[1] = file; argv[2] = NULL; if (push_base()) { push_break(); pop_base(); if (pid) { kill (pid, SIGKILL); sprintf (buf, "/tmp/Ex%d", pid); unlink (buf); sprintf (buf, "/tmp/Rx%d", pid); unlink (buf); wait(0); system ("clear; reset ; clear"); pid = 0; } pop_break(); return (0); } stat1.st_mtime = stat2.st_mtime = stat1.st_ctime = stat2.st_ctime = 0; stat (file, &stat1); if (S_novibreak) push_break(); pid = vfork(); if (!pid) { execv (visual, argv); _exit (1); } while ((ret = wait(0)) > 0) { if (ret == pid) break; } if (S_novibreak) pop_break(); stat (file, &stat2); pop_base(); return (!(stat1.st_mtime==stat2.st_mtime)); } static send_mail() { char buf[1024]; int fildes[2]; int fd, stdin_fd; int i; char *argv[6]; push_break(); argv[0] = S_sendmail; argv[1] = "-t"; argv[2] = "-oo"; argv[3] = "-oi"; if (S_verbose) { argv[4] = "-v"; argv[5] = NULL; } else { argv[4] = NULL; } pipe (fildes); stdin_fd = dup (0); dup2 (fildes[0], 0); if (!vfork()) execv (S_sendmail, argv); dup2 (stdin_fd, 0); fd = open (file, O_RDONLY, 0); if (fd < 0) { perror ("Dmail, Cannot open scratch file"); done (1); } while ((i = read (fd, buf, 1024)) > 0) write (fildes[1], buf, i); close (fd); close (fildes[1]); if (S_verbose) wait (0); pop_break(); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'set.c'" '(3049 characters)' if test -f 'set.c' then echo shar: will not over-write existing file "'set.c'" else cat << \!Funky!Stuff! > 'set.c' /* * SET.C * * Matthew Dillon, 6 December 1985 * * * Variable set/unset/get/reset routines * */ #include <stdio.h> #include "dmail.h" #define MAXLEVELS 3 struct MASTER { struct MASTER *next; struct MASTER *last; char *name; char *text; }; struct MASTER *Mbase[MAXLEVELS]; set_var (level, name, str) register char *name, *str; { register struct MASTER *base = Mbase[level]; register struct MASTER *last; push_break(); while (base != NULL) { if (strcmp (name, base->name) == 0) { free (base->text); goto gotit; } last = base; base = base->next; } if (base == Mbase[level]) { base = Mbase[level] = (struct MASTER *)malloc (sizeof (struct MASTER)); base->last = NULL; } else { base = (struct MASTER *)malloc (sizeof (struct MASTER)); base->last = last; last->next = base; } base->name = malloc (strlen (name) + 1); strcpy (base->name, name); base->next = NULL; gotit: base->text = malloc (strlen (str) + 1); strcpy (base->text, str); pop_break(); } unset_var(level, name, str) register char *name, *str; { register struct MASTER *base = Mbase[level]; register struct MASTER *last; push_break(); while (base != NULL) { if (strcmp (name, base->name) == 0) { if (base != Mbase[level]) last->next = base->next; else Mbase[level] = base->next; if (base->next != NULL) base->next->last = last; if (base == Mbase[level]) Mbase[level] = base->next; free (base->name); free (base->text); free (base); pop_break(); return (1); } last = base; base = base->next; } pop_break(); return (-1); } char * get_var(level, name) register char *name; { register struct MASTER *base = Mbase[level]; while (base != NULL) { if (strcmp (name, base->name) == 0) return (base->text); base = base->next; } return (NULL); } do_unset_var(str, level) char *str; { int i; push_break(); for (i = 1; i < ac; ++i) unset_var (level, av[i]); fix_globals(); pop_break(); return (1); } do_set_var(command, level) char *command; { register struct MASTER *base = Mbase[level]; register char *str; if (ac == 1) { while (base) { printf ("%-10s %s\n", base->name, base->text); base = base->next; } } if (ac == 2) { str = get_var (level, av[1]); if (str) { printf ("%-10s %s\n", av[1], str); } else { push_break(); set_var (level, av[1], ""); fix_globals(); pop_break(); } } if (ac > 2) { push_break(); set_var (level, av[1], next_word (next_word (command))); fix_globals(); pop_break(); } } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'sub.c'" '(5147 characters)' if test -f 'sub.c' then echo shar: will not over-write existing file "'sub.c'" else cat << \!Funky!Stuff! > 'sub.c' /* * SUB.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: INDEXOF() * SIG() * POSITION_CURRENT() * SKIP_TO_DATE() * GET_FIELD() * COMPILE_FIELD() * ISFROM() * XSTRNCMP() * NEXT_WORD() * DONE() * */ #include <signal.h> #include <stdio.h> #include "dmail.h" #define SENDMAIL "/usr/lib/sendmail" indexof(num) register int num; { register int i, last; if (num < 1) num = -1; for (last = -1, i = 0; i < Entries; ++i) { if (Entry[i].no) { last = i; if (Entry[i].no == num) return (i); } } if (num == -1 && last >= 0) return (last); return (-1); } null() { } position_current() { int pos; pos = Entry[Current].fpos; if (fseek (m_fi, pos, 0) != pos) puts ("ERROR: Cannot position file to message"); } skip_to_data(fi) FILE *fi; { char buf[MAXFIELDSIZE]; while (fgets (buf, MAXFIELDSIZE, fi) != NULL) { if (*buf == '\n') return (1); } return (-1); } char * get_field(str) char *str; { int i, entry = Current; int len = strlen(str); i = get_extra (str); if (i >= 0) return (Entry[entry].fields[i]); if (m_fi == NULL) return (""); fseek (m_fi, Entry[entry].fpos, 0); while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) { if (isfrom (Buf)) break; if (strncmp (Buf, str, len) == 0) { Buf[strlen(Buf) - 1] = '\0'; compile_field(Buf, m_fi); return (next_word (Buf)); } } return (""); } compile_field(buf, fi) char *buf; FILE *fi; { int len, acc, pos; acc = 0; buf += strlen (buf) + 1; pos = ftell (fi); while (fgets (buf, MAXFIELDSIZE - acc, fi) != NULL) { if (*buf == ' ' || *buf == 9) { *(buf - 1) = '\n'; len = strlen (buf) - 1; *(buf + len) = '\0'; buf += len; acc += len + 2; if (acc > MAXFIELDSIZE - 10) { printf ("Warning: Field size beyond %d bytes\n", MAXFIELDSIZE); sleep (2); return (1); } } else { *buf = '\0'; fseek (fi, pos, 0); return (1); } pos = ftell (fi); } fseek (fi, pos, 0); } isfrom(str) register char *str; { static char from[] = {"From "}; register int i = 0; while (i < 5) { if (*str++ != from[i++]) return (0); } return (1); } xstrncmp (src, dest, len) register char *src, *dest; register int len; { while (--len >= 0) { if ((*src & 0x1f) != (*dest & 0x1f)) { if ((*src & 0x1f) < (*dest & 0x1f)) return (-1); return (1); } ++src; ++dest; } return (0); } char * next_word(str) register char *str; { while (*str && *str != ' ' && *str != 9) ++str; while (*str && (*str == ' ' || *str == 9)) ++str; return (str); } done(n) { char scr[64]; push_break(); sprintf (scr, "/tmp/dmail%d", getpid()); unlink (scr); sprintf (scr, "/tmp/dmt%d", getpid()); unlink (scr); unlink ("#"); exit (n); } fix_globals() { char *ptr; push_break(); S_page = (ptr = get_var (LEVEL_SET, "page")) ? ((*ptr) ? atoi (ptr) : 24) : -1; if (S_page > 0 && (S_page -= 4) < 0) S_page = 1; S_sendmail = (ptr = get_var (LEVEL_SET, "sendmail")) ? ptr : SENDMAIL; S_novibreak= (ptr = get_var (LEVEL_SET, "vibreak")) ? 0 : 1; S_verbose = (ptr = get_var (LEVEL_SET, "verbose")) ? 1 : 0; S_ask = (ptr = get_var (LEVEL_SET, "ask")) ? 1 : 0; pop_break(); } _pager(str, nl) char *str; int nl; { static int count; static FILE *fi; char buf[1024]; char *ptr; if (str == 0) { switch (S_page) { case -1: count = 0; return (1); case 0: ptr = get_var (LEVEL_SET, "page"); fi = popen (ptr, "w"); if (fi == NULL) { count = 0; printf ("CANNOT RUN PAGER PROGRAM: %s\n", ptr); } else { count = -1; } return (1); default: count = 0; return (1); } } if ((long)str == -1) { if (fi != NULL) { pclose (fi); fi = NULL; } return (1); } if (count < 0) { fputs (str, fi); while (nl--) fputs ("\n", fi); } else { fputs (str, stdout); while (nl--) { fputs ("\n", stdout); ++count; } while (*str) { if (*str++ == '\n') ++count; } if (S_page > 0 && S_page <= count) { count = 0; puts ("\n-- more --"); gets(buf); } } } !Funky!Stuff! fi # end of overwriting check # End of shell archive exit 0