Next MEP shar
John Antypas
jantypas at hope.UUCP
Sun Oct 12 04:43:21 AEST 1986
Less buggy -- it works locally, but I can't be sure how many are
getting their requests out there. It now has security. Any command
requested NOT in a .commands file in your $HOME will be returned
unexecuted.
# To unbundle this package, use sh <name> NOT csh
echo commands.c 1>&2
cat >commands.c << 'End of commands.c'
# include <stdio.h>
# include "typedefs.h"
# include "globals.h"
# include "string2.h"
/*
* Check command to see if it's OK
*/
ok_command(line)
char line[];
{
int i;
for (i=0; i<=num_cmds; i++)
{
if ((strindex(line,comlist[i]) != -1) &&
(strcmp(line,"") != 0))
{
return(0);
}
}
return(-1);
}
/*
* Commands.c -- Does @ checking
*
* Called by check_commands()
*
*/
do_command(line)
char line[];
{
char *c;
FILE *fp, *fopen();
char name[80];
char buffer[80], buffer2[80];
int proc_id, result;
int status;
char comline[80];
line[strlen(line)-1] = '\0';
if (strncmp(line,"@RR",3) == 0)
{
sprintf(namet,"/usr/ucb/Mail -s \"Return Receipt\" %s",fromline);
fp = popen(namet,"w");
fprintf(fp,"\nHere is the return receipt you requested.\n\n");
pclose(fp);
}
if ((strncmp(line,"@SH",3) == 0) &&
(strcmp(subline,"Command") == 0))
{
c = line; c += 4;
strcpy(buffer,c);
if (ok_command(buffer) == 0)
{
sprintf(buffer2,"%s | /usr/ucb/Mail -s",buffer);
sprintf(buffer2,"%s \"%s\" %s",buffer2,line,fromline);
proc_id = fork();
if (proc_id == 0)
{ execlp("/bin/sh","sh","-c",buffer2,(char *)0); }
wait(&status);
} else
{
sprintf(namet,"/usr/ucb/Mail -s \"MEP\" %s",fromline);
fp = popen(namet,"w");
fprintf(fp,"\nYou do not have access to the command:\n");
fprintf(fp,"\n%s\n",buffer);
pclose(fp);
}
}
}
check_commands()
{
FILE *md, *fopen();
char buffer[512];
md = fopen(namem,"r");
fgets(buffer,512,md);
while (!feof(md))
{
if (buffer[0] == '@') do_command(buffer);
fgets(buffer,512,md);
}
fclose(md);
}
End of commands.c
echo mep.c 1>&2
cat >mep.c << 'End of mep.c'
# include <stdio.h>
# include <sys/types.h>
# include <sys/timeb.h>
# include <time.h>
main(argc,argv)
int argc;
char *argv[];
{
FILE *ip, *fp, *fopen();
char buffer[80], buffer2[80];
ip = fopen("/class/maj/jantypas/shar","r");
sprintf(buffer2,"/usr/ucb/Mail -s \"MEP-Shar\" %s",argv[1]);
fp = popen(buffer2,"w");
fgets(buffer,512,ip);
while (!(feof(ip)))
{
fputs(buffer,fp);
fgets(buffer,512,ip);
}
fclose(ip);
pclose(fp);
printf("%s\n",buffer2);
printf("A copy of MEP is on it's way\n");
}
End of mep.c
echo mepinit.c 1>&2
cat >mepinit.c << 'End of mepinit.c'
# include <stdio.h>
# include <pwd.h>
# include <string.h>
# include "typedefs.h"
# include "globals.h"
/*
* MepInit -- Will load configuration options at runtime
*
*/
kill_newline(buffer)
char *buffer;
{
int i;
for (i = 0; i< strlen(buffer); i++)
{
if (buffer[i] == '\n')
{
buffer[i] = '\0';
break;
}
}
}
read_config()
{
int result;
FILE *fp, *fopen();
char buffer[512];
char buffer2[80];
result = chdir(homedir);
fp = fopen(".configmep","r");
fgets(buffer,512,fp);
kill_newline(buffer);
while (!feof(fp))
{
if (strncmp(buffer,"notify=",6) == 0)
{
strcpy(buffer2,&buffer[7]);
if (strcmp(buffer2,"yes") == 0)
{ notify = TRUE; } else { notify = FALSE; }
}
if (strncmp(buffer,"stat=",5) == 0)
{
strcpy(buffer2,&buffer[5]);
if (strcmp(buffer2,"none") == 0)
{
log = FALSE;
}
else
{
log = TRUE;
strcpy(logfile,&buffer[5]);
}
}
fgets(buffer,512,fp);
kill_newline(buffer);
}
fclose(fp);
}
mep_init(id)
int id;
{
int result;
char *p;
char buffer[80];
char envvalue[80]; /* Variable value */
FILE *fp, *fopen();
struct passwd entry;
/* Go to home and try to get the variables */
memcpy(&entry, getpwuid(id), sizeof(entry));
p = entry.pw_dir;
if (p == NULL)
error("Can't find home directory!",-1);
strcpy(envvalue,p);
result = chdir(envvalue); /* Change to dir */
if (result != 0)
{
fprintf(stderr,"Tried to switch to %s\n",envvalue);
fprintf(stderr,"Got %d\n",result);
error("Can't switch to home directory!",-1);
}
strcpy(homedir,envvalue);
strcpy(username,entry.pw_name);
read_config();
result = chdir(homedir);
/*
Only 100 twits allowed please. If you have more
than 100 people you don't want mail from, you need
an agent, not a mail extension
*/
num_twits = 0; /* We assume no twits for now */
fp = fopen(".twitlist","r");
if (fp == NULL) { /* No twits lucky you */ }
else /* Oh well, you can't expect perfection */
{
strcpy(twitlist[0],"TWITS");
while (!feof(fp))
{
num_twits++;
fgets(buffer,80,fp);
buffer[strlen(buffer)-1] = 0;
strcpy(twitlist[num_twits],buffer);
}
fclose(fp);
}
num_cmds = 0;
fp = fopen(".commands","r");
if (fp == NULL) { /* No stuff OK */ }
else
{
strcpy(twitlist[0],"");
while (!feof(fp))
{
num_cmds++;
fgets(buffer,80,fp);
buffer[strlen(buffer)-1] = 0;
strcpy(comlist[num_cmds],buffer);
}
fclose(fp);
}
}
End of mepinit.c
echo message.c 1>&2
cat >message.c << 'End of message.c'
/*
* Message - Gathers incoming mail and sends it to be processed
* John Antypas
* ...!ucbvax!ucdavis!ucrmath!hope!jantypas
*
* For each message in the input stream, separate off the message and
* record the following:
*
* From line:
* user
* Subject
*
* And then process any message for twits and @ commands.
*
*/
# include <stdio.h> /* System file and string routines */
# include <sys/types.h>
# include <string.h>
# include <fcntl.h>
# include <errno.h>
# include "typedefs.h"
# include "globals.var"
# include "process.h"
extern mep_init();
/* Error message, Print message in s and return value v to shell */
error(s,v)
char s[];
int v;
{
fprintf(stderr,"ERROR: \007%s\n",s);
fprintf(stderr,"MEP returning to shell!\n");
exit(v);
}
main(argc,argv)
int argc;
char *argv[];
{
char *c, buffer[80];
FILE *inf; /* Spool file */
int gfd; /* Generic file descripter */
int loop;
int id;
id = getuid();
mep_init(id);
firstmessage = TRUE; /* No messages read yet */
while (!feof(stdin)) /* As long as we have input */
{
fgets(linebuffer,512,stdin); /* Get line */
/* Now see if this is a From line */
/* If it is a From line, word = 'From ' */
if ((strncmp(linebuffer, "From ", 5) == 0) &&
(strlen(linebuffer) > 5))
{
/* Now see if this is our first From */
if (!firstmessage)
{
/* This is after a previous */
/* Message, process the old one */
fclose(md);
process_message();
strcpy(namem,mktemp("/tmp/XXXXXX"));
md = fopen(namem,"w+");
}
/* New message, so open needed files, */
/* and start gathering fields etc. */
c = linebuffer;
c += 5;
strcpy(fromline,c);
fromline[strlen(fromline)-1] = 0;
for (loop = 0; (fromline[loop] != ' ')
&& (fromline[loop] != '\0'); loop++) ;
fromline[loop] = '\0';
strcpy(namem,mktemp("/tmp/XXXXXX"));
md = fopen(namem,"w+");
firstmessage = FALSE;
}
/* Not a from line so check To:/Subject: */
if (strncmp(linebuffer, "To:", 3) == 0)
{
c = linebuffer; c += 3;
strcpy(toline,c);
toline[strlen(toline)-1] = 0;
}
/* Not a To: line so check subject */
if (strncmp(linebuffer, "Subject:", 8) == 0)
{
c = linebuffer;
if (strlen(linebuffer) > 9)
{ c += 9; } else {c += 8; }
strcpy(subline,c);
subline[strlen(subline)-1] = 0;
}
/* Not any of these so just copy to message */
if (!feof(stdin))
{
fputs(linebuffer,md);
}
}
if (!firstmessage)
{
fclose(md);
process_message();
}
}
End of message.c
echo process.c 1>&2
cat >process.c << 'End of process.c'
# include <stdio.h>
# include "typedefs.h"
# include "globals.h"
# include "string2.h"
extern int check_commands();
/*
* Twit(name)
*
* Returns TRUE if name is a twit, false otherwise
*
*/
twit(name)
char name[];
{
int loop = 1;
while (loop <= num_twits)
{
if (strindex(name,twitlist[loop]) != -1)
{
return(TRUE);
}
loop++;
}
return(FALSE);
}
/*
* Do_Notify. Notify user if twit sends mail if NOTIFY variable is set
*/
do_notify()
{
FILE *od, *md, *fopen();
char buffer[80];
if (notify == TRUE)
{
strcpy(namet,mktemp("/tmp/XXXXXX"));
md = fopen(namet,"w+");
fprintf(md,"From MEP\n");
fprintf(md,"To: %s\n",username);
fprintf(md,"Subject: Twit Alert\n");
fprintf(md,"\nFor: %s@%s\n\n",username,homedir);
fprintf(md,"\nSomeone at address:\n");
fprintf(md,"\t%s\n",fromline);
fprintf(md,"has tried to send you mail. ");
fprintf(md,"TwitMinder has discarded it.\n\n");
fclose(md);
sprintf(buffer,"/usr/ucb/Mail -s Twit-Alert %s",username);
od = popen(buffer,"w");
md = fopen(namet,"r");
fgets(buffer,512,md);
while (!feof(md))
{
fputs(buffer,od);
fgets(buffer,512,md);
}
fclose(md);
pclose(od);
unlink(namet);
}
}
/*
* Process_message
*
* When given a message, performs the following:
*
* - Checks to see if person wants logging done
* If so, performs the log entry
* - Checks to see if sender is on twitlist and if
* so, will discard mail to bit bucket and if notify
* option is set will send mail to that effect
* - Process @commands
*
*/
process_message()
{
FILE *fp, *md, *fopen();
char buffer[512];
printf("\n\n");
if (twit(fromline) == TRUE)
/*
This is a twit, notify is requested and discard message
*/
{
do_notify();
unlink(namem);
return(0);
}
else
{
if (log == TRUE)
{
/*
Ok, so write down in log file when each message
arrives and the sender.
*/
char buffer2[80];
FILE *pd, *popen();
pd = popen("date","r");
fgets(buffer2,80,pd);
pclose(pd);
md = fopen(logfile,"a");
sprintf(buffer,"From: %s @ %s",fromline,buffer2);
fputs(buffer,md);
fclose(md);
}
check_commands();
fp = fopen(namem,"r");
fgets(buffer,512,fp);
while (!feof(fp))
{
fputs(buffer,stdout);
fgets(buffer,512,fp);
}
fclose(fp);
unlink(namem);
}
}
End of process.c
echo string2.c 1>&2
cat >string2.c << 'End of string2.c'
/*
Strings2 - Provides even more string functions for C.
I don't know why these weren't included in strings(3).
John Antypas -- ...!sdcsvax!jantypas
strword1(r,s,c,i) -- Returns 1st word in s to r. c is the character
which separates words.
strindex(s,t) -- returns first occurrence of t in s or -1.
strreplace(s,p,r) -- replace first pattern p with pattern r.
This can be used to strinsert and delete functions.
It returns a pointer to the new string s.
All parameters are character pointers.
*/
#define NULL 0
#include <string.h> /* Need strcat, strcpy */
int strindex(s,t)
char *s, *t;
{
int loop, n; /* Loop counter */
n = strlen(t);
for (loop=0; s[loop] != '\0'; loop++)
{
if ((strncmp(s+loop, t, n) == 0) && (n != 0)) { return(loop); }
}
return (-1);
}
char *strreplace(s,p,r)
char *s, *p, *r;
{
int f, n;
char *m; /* Used for temporary */
m = (char *)malloc( strlen(s) + strlen(r) - strlen(p) );
/* Get enough memory for the new string */
/* If it doesn't work, die here */
if (m == NULL) return(m);
f = strindex(s,p);
strncpy(m,s,f); /* Copy up to p. */
strcat(m,r); /* Add in r. */
/* Now add the part after the replacement */
strcat(m,s+f+strlen(p));
/* Copy it back to s */
strcpy(s,m);
free(m);
return(s);
}
int strword(r,s,c,i)
char *s, *r, c;
int i;
/*
Function: Returns number of words/specific word in string s.
Returns in string r the word requested. If i<0;
returns # words in s, else reurns ith word in r.
c is the character used to mark separate words.
Usually is a space (32).
*/
{
int l;
l = strlen(s);
if (i<0) /* Count words */
{
int nw,j; /* # words and loop var */
for (j=0,nw=0; j<l; j++)
{
if (*(s+j) == c) nw++;
}
if (nw != 0) nw++;
return(nw);
}
else
{
char *sp,t[2];
int nw,m; /* Loops and length(s) */
t[0] = c; t[1] = 0;
/* Find begining of ith word */
nw = 0; sp = s;
while ((nw<i) && (*sp != NULL))
{
if ((*sp) == c) nw++;
sp++;
}
/* Now find end of that word */
m = strindex(sp,t);
if (m>0) { strncpy(r,sp,m); } else { strcpy(r,sp); }
return(0);
}
}
End of string2.c
echo globals.h 1>&2
cat >globals.h << 'End of globals.h'
# define TRUE 1
# define FALSE 0
extern int notify, log;
extern int firstmessage; /* First message read = 1 else 0 */
extern char fromline[2048],/* From line from message */
toline[2048], /* To: line from message */
subline[2048], /* Message subject */
linebuffer[8192], /* Big buffer for messages */
logfile[80];
extern char namem[80], names[80], namet[80];
extern char username[20], homedir[80];
extern int num_cmds;
extern int num_twits;
extern STRING twitlist[100]; /* Twit list */
extern STRING comlist[100];
extern error(); /* Error messages */
End of globals.h
echo process.h 1>&2
cat >process.h << 'End of process.h'
/*
* Process.c header file process.h
* John Antypas
* Used in message.c to handle each individual mail message
* All messages are passed through process_message here.
* It can call features such as twit_list(name) which will
* return TRUE if that person is on the twitlist and
* command(line) which will handle the @ commands
*/
extern void proces_message(); /* Handles message */
End of process.h
echo string2.h 1>&2
cat >string2.h << 'End of string2.h'
/*
String2 -- String2 header file
Make sure to link with string2.o
strindex(s,t) -- Return index to pattern t in string s or -1
strreplace(s,p,r) -- Replace pattern p by pattern r in string s.
Return char pointer to s or NULL if error.
strword(r,s,c,i) -- Returns:
If (i<0) ; the number of words in string s is returned sa result.
(i>0) ; the ith word is returned in r from string s.
*/
extern int strword();
extern int strindex();
extern char *strreplace();
#define strdelete(s,p,q) strreplace(s,p,q,"");
End of string2.h
echo typedefs.h 1>&2
cat >typedefs.h << 'End of typedefs.h'
/*
* System data types
*/
typedef char STRING[80];
End of typedefs.h
echo globals.var 1>&2
cat >globals.var << 'End of globals.var'
# define TRUE 1
# define FALSE 0
int notify, log = FALSE;
int firstmessage; /* First message read = 1 else 0 */
char fromline[2048], /* From line from message */
toline[2048], /* To: line from message */
subline[2048], /* Message subject */
linebuffer[8192], /* Big buffer for messages */
logfile[80];
char namem[80], names[80], namet[80];
char username[20], homedir[80];
FILE *md; /* Message file, item file */
FILE *fopen();
int num_cmds;
int num_twits; /* # of twits in twitlist */
STRING comlist[100];
STRING twitlist[100];
End of globals.var
echo Makefile 1>&2
cat >Makefile << 'End of Makefile'
# Makefile for Mail Extensions Package
# John Antypas
CFILES = message.c process.c commands.c mepinit.c string2.c
OFILES = message.o process.o commands.o mepinit.o string2.o
CFLAGS = -O
mep: $(CFILES)
cc $(CFLAGS) $(CFILES) -o message
End of Makefile
echo README 1>&2
cat >README << 'End of README'
Instructions for Installing MEP:
I. Compile the following programs:
cc -O message.c process.c commands.c mepinit.c string2.c -o message
II Put the following line in your .forward home in your home
directory:
"|/fullpathnameforyou/youruserid/message >> /usr/spool/mail/youruserid"
III. Place message in /pathname/youruserid/
Example: Let us say your account is frob and the full path from root
(easily obtained by saying ~<return>) is /usr/acct/frob.
Compile the code above and place message in /usr/acct/frob
cd ~
ls
....files
message
Fix the .forward file.
vi .forward
a
"|/usr/acct/frob/message >> /usr/spool/mail/frob"
<esc>
:wq
IV. Test
This is not the complete version of MEP. It only support three of the
four functions in plan. twitlist, logging and @RR.
Twitlist:
There are people you want mail from and people you DON'T want mail
from. TwitMinder will handle that. All twits will be discarded.
Merely place a file called .twitlist containing the userids (one/line)
in the file.
bob
ralph
MAILER-DAEMON
root
then if any of these people send you mail, that mail will be
discarded. If you want to still be told that they tried, but don't
want to actually READ their mail, setenv NOTIFY.
setenv NOTIFY<return>
This will have the mailer send you a TwitAlert message.
NOTE: You are only allowed to have 100 twits. If you have more,
contact me for a bigger version or so I can modify the code to
discard everyone BUT the people in the twitlist.
Logging:
setenv STAT=<pathname/filename>
When this is set, all mail coming in will have a timestamp put into a
file at /pathname/filename. (Usually just filename will do as it will
go into your home directory.) Entries are:
>From <path!user> @ Date/Time
>From <path!user> @ Date/Time
...
@RR:
This is a neat little feature which allows you ask someone who i
More information about the Comp.sources.unix
mailing list