V10/cmd/nupas/print/message.c
#include <stdio.h>
#include <regexp.h>
#include <signal.h>
#include "mail.h"
#include "string.h"
#include "message.h"
#include "aux.h"
#include <sys/stat.h>
/* imported */
extern char *malloc();
extern long time();
FILE *lockopen();
FILE *lockreopen();
/* definition of UNIX message headers */
#define MSGALLOC 32
typedef struct {
message m[MSGALLOC];
int o;
} msgalloc;
static msgalloc *freep=NULL;
/* read in a message, interpret the 'From' header */
extern message *
m_get(sp)
string *sp;
{
message *mp;
register char *cp;
if (freep==NULL || freep->o >= MSGALLOC) {
freep = (msgalloc *)malloc(sizeof(msgalloc));
if (freep==NULL) {
perror("allocating message");
exit(1);
}
freep->o = 0;
}
mp = &(freep->m[freep->o++]);
mp->body = NULL;
mp->sender = s_new();
mp->date = s_new();
mp->extent = mp->prev = mp->next = NULL;
mp->status = 0;
mp->pos = 0;
if (sp->ptr >= sp->end) {
mzero = mp;
return NULL;
}
/* parse From lines */
for(cp=sp->ptr; *cp=='\n'||*cp==' '||*cp=='\t'; cp++);
for(sp->ptr=cp; *cp != '\n' && *cp; cp++);
*cp = '\0';
if (parse_header(sp->ptr, mp->sender, mp->date)<0) {
fprintf(stderr, "!mailbox format incorrect\n");
mzero = mp;
return NULL;
}
*cp++ = '\n';
sp->ptr = cp;
/* get body */
while (cp < sp->end && !IS_HEADER(cp)) {
while (*cp++ != '\n')
;
}
cp[-1] = '\0';
mp->size = cp - sp->ptr;
mp->body = s_array(sp->ptr, mp->size);
sp->ptr = cp;
return mp;
}
/* output a message, return 0 if ok -1 otherwise */
extern int
m_print(mp, fp, nl, header)
message *mp; /* the message */
FILE *fp; /* where to print it */
{
SIG_TYP pstat;
int rv = 0;
pstat = signal(SIGPIPE, SIG_IGN);
if (header)
print_header(fp, s_to_c(mp->sender), s_to_c(mp->date));
fflush(fp);
/*
* the following are writes instead of an fwrites because,
* in the case of a broken pipe, fwrite will continuously
* generate SIGPIPE's. Enough SIGPIPE's will terminate the
* process despite the SIG_IGN (at least on v9).
*/
if (mp->size > 0)
if(write(fileno(fp), s_to_c(mp->body), mp->size-1) != mp->size-1)
rv = -1;
if (rv==0 && nl)
if(write(fileno(fp), "\n", 1) != 1)
rv = -1;
signal(SIGPIPE, pstat);
return ferror(fp) ? -1 : rv;
}
/* lists of mail messages */
message *mzero; /* zeroth message */
message *mlist; /* first mail message */
message *mlast; /* last mail message */
long mbsize; /* last size of mail box */
/*
* read in the mail file. mbsize is the spot to start reading from.
* if fpp is non-zero then don't close the locked fmailbox, just
* return the file pointer to it.
*/
static FILE *
rd_mbox(file, reverse, newmail, fp)
char *file;
int reverse;
FILE *fp;
{
message *mp;
int pos = 0;
struct stat sbuf;
string *line;
char *corefile;
int len;
if(fp==NULL)
fp = lockopen(file, "r", 0, -1, -1);
if(fp==NULL)
return NULL;
if (stat(file, &sbuf) < 0){
lockclose(fp);
return NULL;
}
if (sbuf.st_size <= mbsize)
return fp;
fseek(fp, mbsize, 0);
len = sbuf.st_size-mbsize;
corefile = malloc(len+1);
if (corefile == NULL || fread(corefile, len, 1, fp)!=1) {
perror("reading mbox");
exit(1);
}
corefile[len-1] = '\n'; /* ensure last mbox char is \n */
corefile[len] = '\0'; /* ensure null termination */
line = s_array(corefile, len);
if (mbsize==0) {
switch(delivery_status(s_restart(line))) {
case MF_PIPE:
printf("mail: mail is being piped to %s\n", line->ptr);
lockclose(fp);
return NULL;
case MF_FORWARD:
printf("mail: mail is being forwarded to %s\n", line->ptr);
lockclose(fp);
return NULL;
}
}
s_restart(line);
while((mp = m_get(line)) != NULL) {
if (mlist == NULL)
mlist = mlast = mp;
else if (reverse) {
mlast->next = mp;
mp->prev = mlast;
mlast = mp;
} else {
mp->next = mlist;
mlist->prev = mp;
mlist = mp;
}
}
if (mlist==NULL)
return fp;
mzero->next = mlist;
mzero->prev = mlast;
for (mp=mzero; mp!=NULL; mp=mp->next)
mp->pos=pos++;
mbsize = sbuf.st_size;
if (newmail)
printf("mail: new message arrived\n");
return fp;
}
/* read the mailbox */
extern int
read_mbox(file, reverse)
char *file;
int reverse;
{
FILE *fp;
SIG_TYP fhup, fint, fquit;
fhup = signal(SIGHUP, SIG_IGN);
fint = signal(SIGINT, SIG_IGN);
fquit = signal(SIGQUIT, SIG_IGN);
fp = rd_mbox(file, reverse, 0, NULL);
if(fp!=NULL)
lockclose(fp);
signal(SIGHUP, fhup);
signal(SIGINT, fint);
signal(SIGQUIT, fquit);
return fp==NULL ? -1 : 0;
}
/* read the mailbox looking for new messages */
extern int
reread_mbox(file, reverse)
char *file;
int reverse;
{
FILE *fp;
SIG_TYP fhup, fint, fquit;
fhup = signal(SIGHUP, SIG_IGN);
fint = signal(SIGINT, SIG_IGN);
fquit = signal(SIGQUIT, SIG_IGN);
fp = rd_mbox(file, reverse, 1, NULL);
if(fp!=NULL)
lockclose(fp);
signal(SIGHUP, fhup);
signal(SIGINT, fint);
signal(SIGQUIT, fquit);
return fp==NULL ? -1 : 0;
}
/* read any changes from the mailbox and write out the result */
rdwr_mbox(file, reverse)
char *file;
{
int rv, err;
FILE *fp;
message *mp;
/*
* if nothing has changed, just return
*/
for (mp=mlist; mp!=NULL; mp=mp->next)
if (mp->status&DELETED)
break;
if (mp==NULL)
return 0;
/*
* read mailbox to pick up any changes
*/
fp = NULL;
if((fp=rd_mbox(file, reverse, 1, NULL)) == NULL){
fprintf(stderr, "mail: can't write mail file %s\n", file);
return 1;
}
/*
* now rewrite it. use the fp passed back from read_mbox to
* maintain the lock across both operations.
*/
if(fp==NULL)
fp = lockopen(file, "w", 0, -1, -1);
else
fp = lockreopen(file, "w", fp);
if (fp == NULL) {
fprintf(stderr, "mail: can't write mail file %s\n", file);
return 1;
} else {
rv = 0;
mlist->prev = NULL; /* ignore mzero */
err = 0;
for(mp=reverse?mlist:mlast; mp!=NULL; mp=reverse?mp->next:mp->prev)
if ((mp->status&DELETED)==0)
err += m_print(mp, fp, 1, 1);
if (err < 0) {
fprintf(stderr,"mail: error writing mail file %s\n", file);
rv = 1;
}
lockclose(fp);
}
return rv;
}
/* write out the mail file */
extern int
write_mbox(file, reverse)
char *file;
int reverse;
{
SIG_TYP fhup, fint, fquit;
int rv;
fhup = signal(SIGHUP, SIG_IGN);
fint = signal(SIGINT, SIG_IGN);
fquit = signal(SIGQUIT, SIG_IGN);
rv = rdwr_mbox(file, reverse);
signal(SIGHUP, fhup);
signal(SIGINT, fint);
signal(SIGQUIT, fquit);
return rv;
}
/* imported */
extern char *getenv();
extern int getpid();
/* global to semaphores */
static char semaphore[128];
extern void
V()
{
unlink(semaphore);
}
/* return name of tty if file is already being read, NULL otherwise */
extern int
P()
{
char file[128];
struct stat sbuf;
FILE *fp;
int pid;
char *home = getenv("HOME");
if (home == NULL)
return 0;
(void)strcpy(file, home);
(void)strcat(file, "/.Maillock");
if (stat(file, &sbuf) >= 0) {
/* lock file exists */
fp = fopen(file, "r");
if (fp != NULL) {
fscanf(fp, "%d", &pid);
fclose(fp);
}
if (fp == NULL || kill(pid, 0)==0) {
fprintf(stderr,"WARNING: You are already reading mail.\n");
fprintf(stderr, "\tThis instance of mail is read only.\n");
return -1;
}
}
/* create a semaphore file */
strcpy(semaphore, file);
V();
fp = fopen(semaphore, "w");
if (fp == NULL)
return 0; /* nothing else we can do */
fprintf(fp, "%d somewhere", getpid());
fclose(fp);
return 0;
}