DMAIL REPOST -- PART III of III
Matt Dillon
dillon at ucbvax.BERKELEY.EDU
Sun Dec 8 09:38:33 AEST 1985
Sorry, it would seem that a couple problems cropped up. I will just
repost the entire thing... this time, I also have the MAN page. problems
that occured:
Make had a problem with spaces in-front of shell commands
some 4.2 systems don't have <fcntl.h>
some files were not tabbed correctly (dmail.help)
Please bear with me.... after all, this is the first time I've posted
something to this net.
I've split the program up into Three sections. Don't combine these
files with files from the first posting, just redo it with these.
Thanks,
-Matt
#-----cut here-----cut here-----cut here-----cut here-----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# main.c
# nroff.out
# range.c
# sendmail.c
# set.c
# sub.c
# This archive created: Sat Dec 7 15:29:06 1985
export PATH; PATH=/bin:$PATH
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 "'nroff.out'" '(9692 characters)'
if test -f 'nroff.out'
then
echo shar: will not over-write existing file "'nroff.out'"
else
cat << \!Funky!Stuff! > 'nroff.out'
DMAIL(1) UNIX Programmer's Manual DMAIL(1)
NAME
dmail - an original mail like interface for mail
SYNOPSIS
dmail -v -O -f [fromfile] -o [tofile] -l rcfile -L -F
[field] -F [field]...
dmail user user user user...
GENERAL
_D_m_a_i_l is a program which hopefully simplifies reading and
organizing your mail. It was designed to overcome several
gripes people had over other mailers. _D_m_a_i_l uses the
/usr/spool format for any folder's you create. To simply
matters even more, it was partially modeled on standard Mail
in terms of writing to your 'mbox' and getting items from
your 'spool', at least as default parameters. About the
only other similarity between the two programs is in the
'type', 'quit', and 'exit' commands of _d_m_a_i_l. _D_m_a_i_l _k_e_e_p_s
_m_u_l_t_i_p_l_e _m_e_s_s_a_g_e_s _p_e_r _f_i_l_e, mail (thus folders are files
rather than directories).
_D_m_a_i_l is not a glorified _M_a_i_l, however. Though most other
mailers have folders, you are usually required to read your
mail in the order it comes in. For somebody who is on three
high-volume mailing lists, it can be rather difficult. _D_m_a_i_l
provides a mechanism in which you can separate your mail by
any partial string in any Field without having to create a
folder. The _s_e_l_e_c_t command is usually instantanious, and
with aliases, you can switch between mailing lists, personal
mail, or anything you wish at a keystroke. Whenever you
_s_e_l_e_c_t on something, you get a reduced list (as if the other
messages didn't exist), and may execute such things as
'delete all' on it without effecting other mail. It serves
to allow you to read each mailing list (or whatever) one at
a time.
Mail-headers are a problem for many people, especially those
logging in over 300 or 1200 baud lines. In many cases, the
header is larger than the message; in any case, they can be
a nuisances. _D_m_a_i_l will not print any fields you do not
want printed. This seems to be a better mechanism than
Mail, which allows you to exclude certain headers. In
_d_m_a_i_l, you specify what to include. To see the entire
header, you use the _h_e_a_d_e_r command from _d_m_a_i_l.
Apart from that, _d_m_a_i_l gives you set variables, aliases,
folder's, and is generally faster than other mail programs.
OPTIONS
_D_m_a_i_l may be executed with several options, putting it in
one of two modes. Firstly, when executed with a user-name
Printed 12/7/85 6 December 1985 1
DMAIL(1) UNIX Programmer's Manual DMAIL(1)
list, _d_m_a_i_l will put you into the editor setting up the To:
field properly and allowing you to enter a letter which
would then be sent off. Secondly, if no user-list is given,
dmail will attempt to read mail from your spool file (or
from file), and put you into command mode. If the mail file
is empty or does not exist, you will be told that you have
no mail, and control will be returned to your shell. The
editor is specified by the enviroment variable VISUAL
(Default vi).
dmail -O -v -f [fromfile] -o [tofile] -l rcfile -L -F
[field] -F [field]...
-O places _d_m_a_i_l in interactive mode, even if there is no
mail to read.
-v Places sendmail in verbose mode when you mail, reply,
or forward a message. (sets the verbose variable)
-f Specify where mail should be taken from. The default
is /usr/spool/mail/$USER. This option without a
filename specifies that mail should be taken from
$HOME/mbox. Otherwise, the specified filename becomes
the fromfile. This means that by specifying just the
-f option and not the -o option will cause both the
infile and outfile to be $HOME/mbox
-o Specify where 'read' mail will be written out to. The
default is $HOME/mbox. This option without a filename
specifies that the mail should be placed in $HOME/.mbox
. Otherwise, the specified filename becomes the out-
file. Additionally, if both -f and -o are specified
without filenames, both the fromfile and the outfile
will be set to $HOME/.mbox
-l Specify the RC file (default is $HOME/.dmailrc). The
RC file consists of a list of _d_m_a_i_l commands, as if
they were typed in.
-L Disables sourcing of any RC files
-F This option tells _d_m_a_i_l to include the given field on
initial mail load. Normally, only the From:, To:, and
Subject: fields are initially loaded. When you specify
other fields, _d_m_a_i_l must scan your fromfile again.
When you have large amounts of mail (+50000 bytes),
this can take a couple of seconds. The -F option
allows you to specify a field to be loaded in addition
to the defaults listed above. You may specify multiple
-F field options. This is only a convenience feature,
normally you don't have to worry about it. Some peo-
ple, however, have spool files of several hundred
Printed 12/7/85 6 December 1985 2
DMAIL(1) UNIX Programmer's Manual DMAIL(1)
thousand bytes and would use this option to prevent
delays later on.
INTERRUPTS
_d_m_a_i_l handles the INTR character. You may use it to break
out of listings, types, or anything else without worry of
destroying something.
COMMAND OVERVIEW
The basic commands for _d_m_a_i_l are as follows (There are, of
course, many commands, these are just a few): _l_i_s_t _t_y_p_e
_h_e_a_d_e_r _d_e_l_e_t_e _n_e_x_t _s_e_l_e_c_t _q_u_i_t _e_x_i_t _a_l_i_a_s _u_n_a_l_i_a_s _s_e_t _u_n_s_e_t
and _m_a_i_l
You may abbrieviate any command you wish. It is suggested
that you do not abbreviate commands in your rc file (default
.dmailrc), as any new commands added in later versions may
change something. Using full command names in your rc file
will keep things compatible.
For many commands (e.g. delete), you may specify a message
list. You can give numerical ranges (1-4 6-9), number lists
(1 2 3 6), or any of several reserved words, such as 'all'.
See 'help keywords' from dmail for a complete list. All
lists apply only to the currently selected messages.
_l_i_s_t displays parts of the headers of messages, one message
per line, for all messages currently selected. You can set
the output format with the _s_e_t_l_i_s_t command.
_t_y_p_e prints the message text of a message. By the way, only
header fields specified by the _s_e_t_l_i_s_t command will be
printed (default- From: To: Subject:), which is useful.
_h_e_a_d_e_r prints out the entire header of a message.
_d_e_l_e_t_e deletes a message or message list (you can say
'delete all' to delete all messages currently selected).
_n_e_x_t goes to the next message and type's or header's it,
depending on what last was done (type or header).
_s_e_l_e_c_t selects what you want to look at. You can say
'select all', to select all the messages, or selects of the
form:
select Field match match match , Field match match ....
where Field is From:, To:, or any field you wish (you can
abbreviate the fields.... Fro To, etc...). match is a
string which you are attempting to match in the Field. If a
match is found, that message will become selected. Thus,
Printed 12/7/85 6 December 1985 3
DMAIL(1) UNIX Programmer's Manual DMAIL(1)
you can select all your personal mail with:
select Cc myname , To myname
Use the on-line help for more information on the _s_e_l_e_c_t or
any other command.
_q_u_i_t from _d_m_a_i_l please. Any unread messages stay in your
spool (or fromfile), any read messages are placed in your
mail-box, any deleted messages are deleted.
_e_x_i_t from _d_m_a_i_l please. Nothing is written or altered, exit
without changing anything. _a_l_i_a_s is used to alias commands
to other commands, or command sequences. For instance, you
can alias 'me' to select all personal mail:
alias me "select Cc myname , To myname"
you can alias a sequence of commands:
alias q "select all ; pre all ; quit"
The above would unread any read mail and quit (therefore,
any mail not deleted will end up staying in your spool
file). You can also _u_n_a_l_i_a_s aliases.
_s_e_t a variable to a string. You can also _u_n_s_e_t a variable.
Several variables have special meaning, use _h_e_l_p _s_e_t from
_d_m_a_i_l for a full explanation.
_m_a_i_l and _r_e_p_l_y may be used to mail out or reply to messages.
BUGS
Please send bug reports to: ...!ucbvax!dillon
dillon at ucb-vax.berkeley.edu
Printed 12/7/85 6 December 1985 4
!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'" '(7315 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 <sys/file.h>
#include <sysexits.h>
#include <signal.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