[net.sources] DMAIL, Bug Fixes et all, Part 4 of 4

dillon@ucbvax.BERKELEY.EDU (Matt Dillon) (12/22/85)

	Thank you all for your bug reports and everything, here is, what I
hope to be, the final v1 dmail with all the bug fixes.  It comes in four
parts.  DMAIL WORKS ON 4.2 AND 4.3 SYSTEMS.  I cannot guarentee it will
work on other systems, though the code should be easy to port.

	Please make sure you get all four parts.  Do not mix this source
with the older version.

This is part 4 of 4

				-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:
#	main.c
#	range.c
#	sendmail.c
#	set.c
#	sub.c
# This archive created: Sun Dec 22 12:29:54 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'main.c'" '(6876 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, 17 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'" '(3471 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, 17 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'" '(7302 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, 17 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 <sys/file.h>
#include <signal.h>
#include "dmail.h"

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 'q':
	case 'Q':
    	puts ("ABORT, no mail sent");
		return (3);
    case 'v':
    case 'V':
	default:
        return (2);
    }
}



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'" '(3050 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, 17 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'" '(5167 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, 17 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) < 0 || ftell(m_fi) != 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