home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
philmail.lzh
/
basicmail.c
next >
Wrap
Text File
|
1992-06-27
|
12KB
|
493 lines
/* UGG!!
* Okay, I FINALLY split up the durn philmail package.
* SHEESH, it was getting large...
* This file has the "simple" utility routines....
*/
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <strings.h>
typedef struct article ARTICLE;
struct article {
long position;
char From[512];
char Subject[512];
char Cc[1024];
};
#define MAXARTICLES 50
#define TRUE 1
#define FALSE 0
extern FILE *fp;
extern ARTICLE *articles[MAXARTICLES];
extern char buf[1024];
extern int numofarticles,currentarticle,lastread;
extern char *includestring;
extern char *progname;
extern ARTICLE *newarticle();
usage()
{
fprintf(stderr," [ philmail v1.01]\n");
fprintf(stderr,"%s is an off-line mail reader for UNIX mail\n",progname);
fprintf(stderr,"The idea being, you grab your /usr/spool/mail file to your home machine\n");
fprintf(stderr," and invoke this program on it\n\n");
fprintf(stderr,"It will read your mail for you, and ask whether to reply or not.\n");
fprintf(stderr," NOTE: to reply, your EDITOR env. variable Must be defined appropriately\n");
fprintf(stderr,"It SHOULD offer inclusion of original message, \n");
fprintf(stderr," and reply to original sender, or ALL recipients \n");
fprintf(stderr,"It is meant to be used in conjunction with a shell-script that\n");
fprintf(stderr," takes first and second lines of a file as recipient and subject,\n");
fprintf(stderr," and then mails the file. [on the UNIX end]\n");
fprintf(stderr,"WARINING: this version can only handle %d messages\n",MAXARTICLES);
fprintf(stderr,"\nThis will check the $MAIL file if non is specified.\n");
fprintf(stderr," It will also allow you to make a mailfile to send \n");
fprintf(stderr," ie: \"philmail machine\!blah\!person \" \n");
fprintf(stderr,"FURTHER NOTE: the ~ escape is recognised (while composing without editor),\n");
fprintf(stderr," but doesn't do much currently\n");
}
format(){
fprintf(stderr,"Oops.. format for mail files should be:\n");
fprintf(stderr,"All articles start with:\n");
fprintf(stderr," 'From<space>Address_goes_here'\n");
fprintf(stderr,"as first line,\n");
fprintf(stderr,"with optional\n");
fprintf(stderr," 'Subject: <blah blah>' \n\n");
}
/* readmsg:
Prints out message on given file pointer thing.
Has special handling for stdout. (and NON-stdout )
sets "lastread", appropriately enough.
*/
void readmsg(out)
FILE *out;
{
char *checkforeof;
long endofarticle;
if(currentarticle >= numofarticles){
fprintf(stdout,"No more messages\n");
return;
}
if(currentarticle == numofarticles - 1)
endofarticle = 0x7fffffff;
else
endofarticle = articles[currentarticle+1]->position;
/* find beginning of message */
fseek(fp,articles[currentarticle]->position,0);
fgets(buf,1023,fp);
/* now file pointer is automatically positioned around the
* proper place!!
* So print out pre-read header, then message body
*/
if(out == stdout){
fprintf(out,"From %s\n",articles[currentarticle]->From);
fprintf(out,"Subject: %s",articles[currentarticle]->Subject);
fprintf(out," --------------------------------------- \n");
} else {
fprintf(out,"%s[From %s]\n",includestring,articles[currentarticle]->From);
}
/* skip over ALL headers now... */
while(buf[0] != 13){
if(fgets(buf,1023,fp)== NULL) {
puts("\n\n[empty message?]\n\n");
return;
}
}
/* have read blank line marker. now read until beginning of
* next message
*/
do{
checkforeof = fgets(buf,1023,fp);
if(out == stdout)
fprintf(out,"%s",buf);
else /* want to make quoted article stand out!! */
fprintf(out,"%s%s",includestring,buf);
} while((ftell(fp) <endofarticle ) && (checkforeof != NULL));
if(out == stdout){
printf("\n[end of message %d]\n",currentarticle);
lastread = currentarticle;
currentarticle++;
}
}
/* writemessage():
Pass writemessage a file pointer to a file,
With the headers already set up.
It will let the user write a message.
***writemessage will then close the file pointer ***
FURTHER HACK:
I am attempting to support philmail as a replacement mailer
for standard "mail". TO this end, after we close the file,
IF it is appropriate, we attempt to actually send the
mail, and delete the file.
*/
extern char *sendmail;
void writemessage(filep,filename)
FILE *filep;
char *filename;
{
char *editor;
char forkstring[1024];
editor = (char *) getenv("EDITOR");
if( editor != NULL){
fclose(filep);
/* Fork off EDITOR now !! */
sprintf(forkstring,"%s %s",editor,filename);
if(system(forkstring) != 0){
fflush(stdout);
fprintf(stderr,"Error forking editor\n");
fprintf(stderr,"continue with line-by-line?\n");
fgets(buf,1023,stdin);
if((buf[0] == 'y') || (buf[0] == 'Y')){
editor = NULL;
if((filep = fopen(filename,"a+")) == NULL){
fprintf(stderr,"Sorry.. cannot reopen file\n");
return;
}
} else {
fprintf(stderr,"Please delete file %s\n",filename);
return;
}
/* line-mode will then fall through to below */
}
}
/* MUST KEEP THIS TEST, so that if editor fork fails, we can
* fall through to line-mode
*/
if(editor == NULL){
puts("Input body of message now.");
puts("\".\" at beginning of line, or EOF, to end");
while(fgets(buf,1023,stdin) != NULL){
if(buf[0] == '.')
break;
/* handle UNIX type escapes.... */
/* Except that I only care about ~e, and
* we do that by default!!!
*/
if(buf[0] == '~'){
switch(buf[1]){
case 'e':
fclose(filep);
sprintf(forkstring,"%s %s",&buf[2],filename);
if(system(forkstring) != 0){
fprintf(stderr,"Error attempting to fork editor\n");
}
/* try append, THEN create */
filep=fopen(filename,"a+");
if (filep == NULL){
fprintf(stderr,"Error: cannot reopen file\n");
return;
}
case '?':
puts("possible \"~\" escapes:");
puts("~e <editorname> to edit message");
puts("~?: help");
puts(" Sorry.. that's all we do for now! ");
break;
default:
fputs(buf,filep);
}
} else
fputs(buf,filep);
}
fclose(filep);
}
/* and now try to SEND FILE?!!! */
if(sendmail != NULL){
char tempbuf[512];
filep= fopen(filename,"r");
if(filep == NULL){
fprintf(stderr,"error sending mail: could not open file %s\n",filename);
return;
}
fgets(buf,1023,filep);
fclose(filep);
/* the "To:" thing should be nicely set up as FIRST line*/
sprintf(tempbuf,"%s %s <%s",sendmail,&buf[3],filename);
/* this line forks off "sendmail" or something */
system(tempbuf);
/*and now delete mail file!*/
sprintf(tempbuf,"del %s",filename);
system(tempbuf);
}
return;
}
/* reply:
sets up editor, etc for replying.
includes Cc: line IFF all is true
*/
void reply(all)
int all;
{
char filename[100];
char *parse;
long timeval;
FILE *replyfile;
/* _getsys() is an OS9 specific. basically, gets the number of ticks
* since system started. Just to "ensure" unique files.
* the UNIX equivalent would be _secsince70() or something
*/
timeval = _getsys(D_Ticks,4);
sprintf(filename,"mail.%d",timeval);
if((replyfile=fopen(filename,"w")) == NULL){
fprintf(stderr,"Error: could not open file to send mail\n");
return;
}
printf("Successfully opened \"%s\" for reply\n",filename);
/* FIRST do "To: " header */
/* note: CANNOT use printheader for this */
parse=articles[currentarticle]->From;
fprintf(replyfile,"To: %s\n",parse);
/* now handle "Subject: " header..
* add "Re:" if not already there.
*/
if(articles[currentarticle]->Subject[0] != 0){
parse=articles[currentarticle]->Subject;
if((parse[0] == 'R') && ((parse[1] &0xdf) == 'E') && (parse[2] == ':'))
fprintf(replyfile,"Subject: %s",parse);
else {
fprintf(replyfile,"Subject: Re: %s",parse);
}
} else
fprintf(replyfile,"Subject: <None>\n");
if(all){
if(articles[currentarticle]->Cc[0] != 0)
fprintf(replyfile,"Cc: %s",articles[currentarticle]->Cc);
else fprintf(stderr,"No CC to add\n");
}
fprintf(replyfile,"X-Mailer: philmail\n");
/* and don't forget header terminator */
fprintf(replyfile,"\n");
fprintf(stdout,"Include original article? "); fflush(stdout);
fgets(buf,1023,stdin);
if((buf[0] == 'y') || (buf[0] == 'Y')){
readmsg(replyfile);
/* "reads" message INTO replyfile */
}
writemessage(replyfile,filename);
/* note that "readmsg" also set lastread, etc, again. ug */
/* but.. but.. should increment curentarticle again?? !! */
/* YES! So I have decided.. ;-)*/
currentarticle++;
/* does not matter if overrun.. readmsg is only way we view
* articles, I think, and that checks for overrun
*/
/* we MUST close replyfile ABOVE[ in writemessage() ]!!! */
return;
}
/* saves "lastread" article in file "name".
* (note that command interface sets lastread, if given number )
* saves WHOLE article, headers and all
* need to check for overrun!!
*/
void save(name)
char *name;
{
int lastflag=0;
FILE *savefile;
char filenam[512];
strcpy(filenam,name);
name = filenam;
if(lastread >= numofarticles){
puts("past last article");
return;
}
if(lastread == numofarticles-1) lastflag = 1;
if((savefile = fopen(name,"w+")) == NULL){
fprintf(stderr,"Error: cannot open %s for saving message\n",name);
return;
}
printf("file is %s\n",name);
fseek(fp,articles[lastread]->position,0);
/* write first "From " line, stupid!! */
fgets(buf,1023,fp);
fputs(buf,savefile);
while(fgets(buf,1023,fp) != NULL){
if(lastflag == 0){ /* NOT last article, then... */
if(strncmp("From ",buf,5) == 0){
break;
}
/* we hit next article */
}/* otherwise, read until end-of-file */
fputs(buf,savefile);
}
fclose(savefile);
printf("saved message %d to file %s\n",lastread,name);
}
/* setfrom:
* sets the From line properly, given a header to the "From: " thing.
*
* header is ASSUMED to be AFTER the "From:" header, thus
* "CLEAN"
*/
void setfrom(From,header)
char *From,*header;
{
char *place;
/* header is after "From: ", and could be
* "from me" <eric@gloriantha>
* person@address (my name here)
* <boring@person.dumb.place>
* real!address@this.time
*/
/* ergo, either there's a "<>" in there, or the first
* string is the address?? !!
*/
place = index(header,'<');
if(place == NULL) {
/* no strange brackets */
place = header;
while(*++place != ' '){
if(*place == 0) break;
if((*place == 10) || (*place == 13))
break;
}
*place = '\0';
strcpy(From,header);
return;
}
else /* we can now assume that there is the funky bracket thing */
{
char *start = ++place;
while(*++place != '>') {
switch(*place){
case 0:
case 10:
case 13:
fprintf(stderr,"Error! Error! bad From line [no closing '>'] !\n");
fprintf(stderr,"%s",start);
exit(-1);
default:
break;
}
}
*place = '\0';
strcpy(From,start);
}
return;
}
/*
* "printheader" really only prints subject and from lines,
* as seen ONLY from "header" command.
*/
printheader(out,i)
FILE *out;
int i;
{
fprintf(out," %s ",articles[i]->From);
if(articles[i]->Subject[0] != 0L){
fprintf(out," |: %s",articles[i]->Subject);
}
}
/* restart:
* reset things, so we can use readfile on another mail folder
*/
void restart(){
int i;
for(i=0; i<numofarticles; i++){
free(articles[i]);
}
numofarticles = 0;
currentarticle = lastread = 0;
}
/* readfile:
* given a name of a mail folder,
* reads it , sets "fp", and initialises stuff.
*/
readfile(file)
char *file;
{
char filenam[512];
strcpy(filenam,file);
file = filenam;
if( (fp=fopen(file,"r")) == NULL){
fprintf(stderr,"Error: could not open mail file %s\n",file);
exit(0);
}
printf("successfully opened %s\n",file);
if(fgets(buf,1023,fp) == NULL) {
puts("Mail file empty!!");
exit(0);
}
if( strncmp("From ",buf,5) != 0){
format();
exit(-1);
}
articles[0] = newarticle();
/* now find all the subjects and stuffs. */
getpositions();
puts("File seems to be okay\n");
}
/* setarticle:
Given a char pointer with ascii number,
( and FIRST CHAR being a diget!! )
sets currentarticle appropriately.
DOES set lastread.
assumed max of two digits;
*/
void setarticle(parse)
char *parse;
{
if(isdigit(parse[1])){
currentarticle =10 * (parse[0] - '0') + parse[1] - '0';
} else
currentarticle= parse[0] - '0';
if(currentarticle >numofarticles)
currentarticle = numofarticles;
lastread = currentarticle;
}