dmail part II or II
Matt Dillon
dillon at ucbvax.BERKELEY.EDU
Sat Dec 7 17:47:17 AEST 1985
This is the second and last part to DMAIL.. enjoy
...!ucbvax!dillon
dillon at 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
More information about the Comp.sources.unix
mailing list