home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
stg_v4.lzh
/
postman.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-11
|
42KB
|
2,286 lines
/*
* postman - mail delivery
*
* 93/04/18 StG new version from scratch
*
* TODO: go through each write() and rig delay for no free and proper
* handling for segment list full (and match read len)
*
* USER DELIVERY MODE:
* postman [-tTO] {-sSUBJ} {-f} (file)
* -f indicates binary message
* message is processed and placed in .mq file
* file is not deleted
*
* SERVICE DELIVERY MODE:
* postman (file)
* file must be in std STG mail format, must exist in spool dir, and
* calling process must be service or sysop
* file is renamed to .sq extension
*
* SPOOL DIRECTORY EXTENSIONS:
* mq - mail queue (must be tagged)
* mh - mail hold (postman hold queue)
* si - service in
* so - service out
* sq - service queue (must be tagged & named by service)
* ns - network send
* nr - network recv
* nq - network queue (must be tagged & named by system)
* pi - postman in (postman to postman service request)
*
* no external programs should use any of these extensions except
* network routines which can create .nq files.
*/
#include "stgnet.h"
#include "pwd.h"
#include "pm_util.h"
#include "nodes.h"
#include "db9.h"
#include <time.h>
#ifdef _OSK
/* stupid OSK implimentation of dirent! */
#include <direct.h>
#include <dir.h>
#define dirent direct
#else
#include <dirent.h>
#endif
#define LOCK_FILE "postman.lck"
struct passwd *pw;
char hostname[32];
int iPM_ID;
int iPM_PRI;
char tempfile[32];
long lTime;
struct tm *psTime;
/************************************************************************/
/* DAEMON globals */
int hLock; /* handle to lock file */
int hNet; /* handle to stgnet.db9 file */
int resetroute=1; /* update routing */
DIR *dp; /* directory handle */
char rcvd_from[64]; /* RCVD: system/service name */
int iOnHold=0; /* file being processed is on hold flag */
int iDebug=0; /* debug mode flag */
int iFromPM=0; /* message is from postman flag */
struct sNode sNode;
#ifdef _OSK
#define MAX_ROUTE 25
#else
#define MAX_ROUTE 10
#endif
struct route
{
char dest[32]; /* destination file/user */
int type; /* type of route */
int path; /* open handle to file */
};
/* route type codes */
#define RT_RTS 1 /* return to sender (misc reasons) */
#define RT_HOLD 2 /* hold for later (misc reasons) */
#define RT_NODE 3 /* deliver to node (name.ni) */
#define RT_SERV 4 /* deliver to service (name.si) */
#define RT_USER 5 /* deliver to user (file=user name) */
struct route asRoute[MAX_ROUTE];
int routes;
char fromline[128];
char fileline[128];
char toline[128];
/************************************************************************/
Help()
{
writeln(2,"postman - mail delivery\n",80);
writeln(2," FOR SYSTEM USE ONLY\n",80);
STGVER;
exit(0);
}
pmlog(code,fmt,va_alist)
int code;
char *fmt;
va_dcl
{
va_list ap;
char pm_buf[256];
va_start(ap);
if (iDebug)
{
writeln(iDebug,"LOG: ",5);
_strfmt(pm_buf,fmt,ap);
writeln(iDebug,pm_buf,strlen(pm_buf));
writeln(iDebug,"\n",1);
}
return(vsyslog(code,fmt,ap));
va_end(ap);
}
tag(path)
int path;
{
#ifdef _OSK
int tag;
struct fildes fd;
if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
return(ERR);
tag=fd.fd_date[2]*fd.fd_date[3];
fd.fd_date[4]=tag%60;
if (_ss_pfd(path,&fd)==ERR)
return(ERR);
#endif
return(0);
}
untag(path)
int path;
{
#ifdef _OSK
int tag;
struct fildes fd;
if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
return(ERR);
tag=fd.fd_date[2]*fd.fd_date[3]+1;
fd.fd_date[4]=tag%60;
if (_ss_pfd(path,&fd)==ERR)
return(ERR);
#endif
return(0);
}
tagged(path)
{
#ifdef _OSK
int tag;
struct fildes fd;
if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
return(0);
tag=fd.fd_date[2]*fd.fd_date[3];
if (fd.fd_date[4]==tag%60)
return(1);
#endif
return(0);
}
char *vers[]=
{
"stg_net",
"smon",
"syslog",
"error",
"slogin",
"password",
"smenu",
"postman",
"smail",
"msgedt",
"termlist",
"userlist",
"servlist",
"nodelist",
"sroute",
0
};
Interactive()
{
int n;
char *args[8];
char **ppcTemp;
/* run as user postman - all commands should be okay for public use */
setuid(iPM_ID);
openerr("postman",0,LOG_STGNET);
stringf(b,"POSTMAN @ %s - StG-Net %s\n",hostname,STG_VER);
writeln(1,b,80);
writeln(1,"\n",1);
writeln(1,"Enter 'help' for command list\n",80);
prompt:
writeln(1,"\n",1);
write(1,"postman: ",9);
n=readln(0,b,70);
if (n==ERR)
exit(syserr("readln: %m"));
if (!n)
{
writeln(1,"[EOF]\n",80);
goto quit;
}
if (!isatty(0))
writeln(1,b,n);
b[n-1]=0;
if (!stricmp(b,"quit"))
goto quit;
if (*b=='?' || !stricmp(b,"help"))
{
writeln(1,"versions - list version of modules on this node\n",80);
writeln(1,"nodelist - list all network nodes\n",80);
writeln(1,"servlist - list availabile services\n",80);
writeln(1,"userlist - list known users\n",80);
writeln(1,"userinfo (name) - show details about user\n",80);
writeln(1,"finduser (name) - search for user by partial name\n",80);
writeln(1,"sroute - show network routing for this node\n",80);
writeln(1,"help -or- ? - this list\n",80);
writeln(1,"quit - exit postman\n",80);
goto prompt;
}
if (!stricmp(b,"versions"))
{
ppcTemp=vers;
while (*ppcTemp)
{
args[0]=*ppcTemp++;
args[1]="-#";
args[2]=0;
if (_fork(*args,args,environ)==ERR)
syserr("fork %s: %m",*args);
else
wait(0);
}
goto prompt;
}
if
(
!stricmp(b,"nodelist") ||
!stricmp(b,"servlist") ||
!stricmp(b,"userlist") ||
!stricmp(b,"sroute")
)
{
args[0]=b;
args[1]=0;
goto fork_it;
}
if (!strincmp(b,"nodeinfo ",9) && b[9]!='-')
{
args[0]="nodelist";
args[1]=b+9;
args[2]=0;
goto fork_it;
}
if (!strincmp(b,"userinfo ",9) && b[9]!='-')
{
args[0]="userlist";
args[1]=b+9;
args[2]=0;
goto fork_it;
}
if (!strincmp(b,"finduser ",9) && b[9]!='-')
{
args[0]="userlist";
args[1]="-f";
args[2]=b+9;
args[3]=0;
goto fork_it;
}
writeln(2,"Unknown command - enter 'help' for list\n",80);
goto prompt;
fork_it:
if (_fork(*args,args,environ)==ERR)
syserr("fork %s: %m",*args);
else
wait(0);
goto prompt;
quit:
writeln(1,"\n",1);
writeln(1,"Nice chatting with you.\n");
exit(0);
}
/* create asRoute[] entry, open file, write fromline, to, etc */
void
Route(to)
char *to;
{
char dest[32]; /* destination file/user */
int type; /* destination type */
char *reason; /* reason for rts */
int n,r;
int temp;
char rb[80]; /* route buffer (@*) */
*dest=0;
if (iDebug)
writeln(iDebug,to,80);
if (_pm_addr(to+6)==ERR)
{
type=RT_RTS;
reason="invalid destination address";
pmlog(LOG_INFO,"bad destination: %s (rts)",to+6);
goto route;
}
if (*A_host)
{
if (!*hostname)
{
type=RT_RTS;
reason="network not configured";
pmlog(LOG_ERR,"message to %s w/o network loaded (rts)",A_host);
goto route;
}
if (!strcmp(A_host,"*"))
{
/* all hosts mode */
_db9(DB_SEEK,hNet,0,0); /* rewind */
while (n=_db9(DB_NEXT,hNet,&sNode,sizeof(sNode)))
{
if (n==ERR)
goto db_err;
_db9(DB_ULOCK,hNet,0,0);
stringf(rb,"TO : %s@%s\n",A_user,sNode.acN_Name);
if (sNode.bN_Status!=NS_DEAD)
Route(rb);
}
return;
}
if (stricmp(A_host,sNode.acN_Name))
{
n=_db9(DB_SEEK,hNet,A_host,strlen(A_host)+1);
if (n==ERR)
goto db_err;
if (!n)
{
type=RT_RTS;
reason="destination node is unknown";
goto route;
}
}
if (stricmp(hostname,A_host))
{
/* need to forward to another node */
if (stricmp(A_host,sNode.acN_Name))
{
if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
goto db_err;
_db9(DB_ULOCK,hNet,0,0);
}
if (sNode.bN_Status==NS_DEAD)
{
pmlog(LOG_INFO,"node %s is dead, RTS",A_host);
type=RT_RTS;
reason="destination node is dead";
goto route;
}
if (!*sNode.sRoute.acN2_Name)
{
pmlog(LOG_INFO,"no route to node %s, holding message",sNode.acN_Name);
type=RT_HOLD;
goto route;
}
type=RT_NODE;
strcpy(dest,sNode.sRoute.acN2_Name);
goto route;
}
}
/* if drops through to here, message is local */
pw=getpwnam(A_user);
if (!pw)
{
type=RT_RTS;
reason="unknown user";
goto route;
}
if (*pw->pw_shell=='!' || *pw->pw_shell=='%')
{
type=RT_SERV;
strcpy(dest,pw->pw_name);
goto route;
}
if (!*pw->pw_dir)
{
if (iDebug)
wstringf(iDebug,"user has no directory\n");
type=RT_RTS;
reason="user is not accepting mail";
goto route;
}
/* home dir must be accessable as user */
setuid(pw->pw_uid);
if (access(pw->pw_dir,
#ifdef _OS9
O_DIR|O_RDWR
#else
0
#endif
)==ERR)
{
if (iDebug)
wstringf(iDebug,"user directory not accessable: %m");
setuid(0);
type=RT_RTS;
reason="user is not accepting mail";
goto route;
}
setuid(0);
type=RT_USER;
strcpy(dest,pw->pw_name);
goto route;
db_err:
pmlog(LOG_ERR,"DB9 error (holding msg): %m");
type=RT_HOLD;
route:
/* check route table for duplicate path */
r=0;
while (r<routes)
{
if (asRoute[r].type==type)
{
if (!*dest || !stricmp(asRoute[r].dest,dest))
break;
}
r++;
}
if (r<routes)
{
if (iDebug)
wstringf(iDebug,"using existing route entry path=%d\n",
asRoute[r].path);
goto addto;
}
if (routes==MAX_ROUTE-1)
{
/* if about to re-use last route entry, put on hold */
if (iDebug)
wstringf(iDebug,"route table limit hit - putting msg on hold\n");
*dest=0;
type=RT_HOLD;
goto route;
}
/* select destination file */
switch (type)
{
case RT_RTS:
if (iDebug)
wstringf(iDebug,"route: RTS \"%s\"\n",reason);
/* create normal mail queue file */
_pm_temp(b);
strcat(b,".mq");
temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"create %s: %m",b);
type=RT_HOLD;
goto route;
}
/* mail comes from postman */
strcpy(b,"FROM: postman");
if (*hostname)
{
strcat(b,"@");
strcat(b,hostname);
}
strcat(b," (mail delivery service)\n");
writeln(temp,b,strlen(b));
if (iFromPM)
{
/* mail was already from postman, send to sysop instead */
strcpy(b,"TO : sysop\n");
writeln(temp,b,strlen(b));
strcpy(b,"SUBJ: message returned to postman\n");
writeln(temp,b,strlen(b));
}
else
{
/* create to: from from: */
strcpy(b,"TO : ");
strcpy(b+6,fromline+6);
writeln(temp,b,strlen(b));
/* and subject (mostly to separate real to: from error to: */
strcpy(b,"SUBJ: message returned to sender\n");
writeln(temp,b,strlen(b));
}
/* add to route table */
*asRoute[r].dest=0;
asRoute[r].type=RT_RTS;
asRoute[r].path=temp;
routes++;
if (iDebug)
wstringf(iDebug,"new route path=%d\n",temp);
break;
case RT_HOLD:
if (iOnHold) /* was already on hold */
break;
_pm_temp(b);
strcat(b,".mh");
if (iDebug)
wstringf(iDebug,"route: HOLD %s\n",b);
temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"creat %s: %m",b);
if (iDebug)
wstringf(iDebug,"sleeping 5 min\n");
/* what the heck do I do now??? */
/* try sleeping for a while and retry */
/* and hope the sysop catches it */
sleep(5*60);
goto route;
}
writeln(temp,fromline,strlen(fromline));
*asRoute[r].dest=0;
asRoute[r].type=RT_HOLD;
asRoute[r].path=temp;
routes++;
if (iDebug)
wstringf(iDebug,"new route path=%d\n",temp);
break;
case RT_NODE:
if (iDebug)
wstringf(iDebug,"route: NODE %s\n",dest);
strcpy(b,dest);
strcat(b,".ni");
temp=open(b,O_EXCL|O_RDWR);
if (temp==ERR)
{
if (errno==253) /* file is busy */
{
type=RT_HOLD;
*dest=0;
goto route;
}
if (errno!=216) /* file not found */
{
pmlog(LOG_ERR,"open %s: %m",b);
type=RT_HOLD;
*dest=0;
goto route;
}
temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"creat %s: %m",b);
type=RT_HOLD;
*dest=0;
goto route;
}
}
lseek(temp,0L,2);
/* put check in for ~ termination ? */
writeln(temp,fromline,strlen(fromline));
strcpy(asRoute[r].dest,dest);
asRoute[r].type=RT_NODE;
asRoute[r].path=temp;
routes++;
if (iDebug)
wstringf(iDebug,"new route path=%d\n",temp);
break;
case RT_SERV:
if (iDebug)
wstringf(iDebug,"route: SERV %s\n",dest);
strcpy(b,dest);
if (iFromPM)
strcat(b,".pi");
else
strcat(b,".si");
temp=open(b,0);
if (temp!=ERR)
{
/* if file exists, put on hold */
close(temp);
*dest=0;
type=RT_HOLD;
goto route;
}
if (temp==ERR && errno!=216) /* if not not found, exists */
{
if (errno!=253)
pmlog(LOG_ERR,"open %s: %m",b);
*dest=0;
type=RT_HOLD;
goto route;
}
temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"creat %s: %m",b);
type=RT_HOLD;
*dest=0;
goto route;
}
writeln(temp,fromline,strlen(fromline));
strcpy(asRoute[r].dest,dest);
asRoute[r].type=RT_SERV;
asRoute[r].path=temp;
routes++;
if (iDebug)
wstringf(iDebug,"new route path=%d\n",temp);
break;
case RT_USER:
if (iDebug)
wstringf(iDebug,"route: USER %s\n",dest);
pw=getpwnam(dest);
if (!pw)
{
/* say what!? */
pmlog(LOG_ERR,"internal bug #1: dest='%s'",dest);
type=RT_RTS;
*dest=0;
goto route;
}
stringf(b,"%s/mailbox",pw->pw_dir);
/* don't open exclusive 'cuz mail is written to detect new msgs */
temp=open(b,/*O_EXCL|*/O_RDWR);
if (temp==ERR)
{
if (errno!=216)
{
pmlog(LOG_ERR,"open %s: %m",b);
type=RT_HOLD;
*dest=0;
goto route;
}
temp=create(b,O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"creat %s: %m",b);
type=RT_HOLD;
*dest=0;
goto route;
}
}
lseek(temp,0L,2);
/* check for ~ ? */
writeln(temp,fromline,strlen(fromline));
strcpy(asRoute[r].dest,dest);
asRoute[r].type=RT_USER;
asRoute[r].path=temp;
routes++;
if (iDebug)
wstringf(iDebug,"new route path=%d\n",temp);
break;
}
addto:
/* write to: line */
write(asRoute[r].path,to,strlen(to));
switch (type)
{
case RT_RTS:
stringf(b,"ERR : %s\n",reason);
writeln(asRoute[r].path,b,strlen(b));
break;
}
}
/* check tag and return !0 if not okay */
ChkTag(file)
char *file;
{
int path;
path=open(file,0);
if (path==ERR)
{
if (errno==253);
{
if (iDebug)
wstringf(iDebug,"File is busy\n");
return(1); /* file is busy, try again later */
}
pmlog(LOG_ERR,"open %s: %m",file);
return(1);
}
if (!tagged(path))
{
/* move to temp file, bug sysop about it */
_pm_temp(tempfile);
strcat(tempfile,".err");
close(path);
if (_rename(file,tempfile)==ERR)
{
pmlog(LOG_ERR,"rename %s %s: %m",file,tempfile);
return(1);
}
if (iDebug)
wstringf(iDebug,"File is not tagged - saved to %s\n",tempfile);
/* MailSysop(tempfile,"file not tagged"); */
return(1);
}
close(path);
return(0);
}
void
Process(file)
char *file;
{
int path,temp;
long frompos,currpos,filesize;
int n,r;
int da; /* done already flg */
if (iDebug)
wstringf(iDebug,"Process(\"%s\")\n",file);
*sNode.acN_Name=0;
if (ChkTag(file))
return;
path=open(file,O_EXCL|O_RDWR);
if (path==ERR)
{
if (errno==253)
{
if (iDebug)
wstringf(iDebug,"File is busy\n");
return; /* file open by another process??? */
}
pmlog(LOG_ERR,"open %s: %m",file);
return;
}
iOnHold=(!strcmp(file+strlen(file)-3,".mh"));
while (1)
{
da=0;
*fileline=0;
routes=0;
frompos=lseek(path,0L,1);
n=readln(path,fromline,80);
if (!n)
break;
if (n==ERR)
{
pmlog(LOG_ERR,"read (from): %m");
break;
}
if (iDebug)
writeln(iDebug,fromline,n);
fromline[n]=0;
if (*fromline=='f')
{
if (iDebug)
wstringf(iDebug,"Message has been processed already\n");
da=1;
*fromline='F';
}
if (strncmp(fromline,"FROM: ",6))
{
_pm_temp(tempfile);
strcat(tempfile,".err");
temp=create(tempfile,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (temp==ERR)
{
pmlog(LOG_ERR,"creat %s: %m",tempfile);
return;
}
lseek(path,frompos,0);
while (1)
{
n=readln(path,b,80);
if (!n || n==ERR)
break;
writeln(temp,b,n);
if (n==2 && *b=='~')
break;
}
if (iDebug)
wstringf(iDebug,"missing FROM: - saved to %s\n",tempfile);
/* MailSysop(tempfile,"missing FROM: header (out of sync)"); */
continue;
}
_pm_addr(fromline+6);
iFromPM=!stricmp(A_user,"postman");
while (1)
{
errno=211;
n=readln(path,toline,80);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (to): %m");
goto die;
}
if (strncmp(toline,"TO : ",6))
break;
toline[n]=0;
if (!da)
Route(toline);
}
if (!da && !routes)
{
if (iOnHold)
{
if (iDebug)
writeln(iDebug,"Leaving file on hold\n",80);
tag(path);
close(path);
return;
}
Route("TO : sysop\n");
strcpy(b,"ERR : message routed to sysop because it has no destination address\n");
if (routes)
writeln(asRoute[0].path,b,strlen(b));
if (iDebug)
writeln(iDebug,b,strlen(b));
}
strcpy(b,toline);
while (1)
{
/* if line is terminator, skip back and continue */
if (n==2 && *b=='~')
{
lseek(path,-2l,1);
break;
}
if (iDebug)
writeln(iDebug,b,strlen(b));
r=0;
if (!strncmp(b,"FILE: ",6))
strcpy(fileline,b);
else
while (r<routes)
writeln(asRoute[r++].path,b,n);
errno=211;
n=readln(path,b,80);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (header): %m");
goto die;
}
b[n]=0;
if (n==1)
break;
}
if (*rcvd_from)
{
time(&lTime);
psTime=localtime(&lTime);
stringf(b,"RCVD: %02d/%02d/%02d %02d:%02d:%02d %s\n",
psTime->tm_year,
psTime->tm_mon+1,
psTime->tm_mday,
psTime->tm_hour,
psTime->tm_min,
psTime->tm_sec,
rcvd_from);
n=strlen(b);
r=0;
while (r<routes)
writeln(asRoute[r++].path,b,n);
}
if (*fileline)
{
currpos=lseek(path,0L,1);
filesize=atol(fileline+6);
lseek(path,filesize,1);
n=readln(path,b,80);
if (n!=2 || *b!='~')
{
pmlog(LOG_ERR,"file lost: sync error");
strncpy(fileline,"LOST",4);
filesize=0;
if (iDebug)
writeln(iDebug,fileline,strlen(fileline));
}
lseek(path,currpos,0);
n=strlen(fileline);
r=0;
while (r<routes)
{
writeln(asRoute[r].path,b,n);
writeln(asRoute[r++].path,"\n",1);
}
while (filesize)
{
if (filesize>BUF_SIZE)
n=BUF_SIZE;
else
n=filesize;
errno=211;
n=read(path,b,n);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (file): %m");
goto die;
}
r=0;
while (r<routes)
write(asRoute[r++].path,b,n);
filesize-=n;
}
r=0;
while (r<routes)
{
/* don't terminate service file */
if (asRoute[r].type!=RT_SERV)
write(asRoute[r].path,"~\n",2);
r++;
}
}
else
{
r=0;
while (r<routes)
writeln(asRoute[r++].path,"\n",1);
while (1)
{
errno=211;
n=readln(path,b,BUF_SIZE);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (msg): %m");
goto die;
}
if (n==2 && *b=='~')
break;
r=0;
while (r<routes)
writeln(asRoute[r++].path,b,n);
}
r=0;
while (r<routes)
{
/* don't terminate service file */
if (asRoute[r].type!=RT_SERV)
write(asRoute[r].path,"~\n",2);
r++;
}
}
r=0;
while (r<routes)
{
tag(asRoute[r].path);
close(asRoute[r].path);
r++;
}
currpos=lseek(path,0L,1);
lseek(path,frompos,0);
write(path,"f",1);
lseek(path,currpos,0);
}
goto dun;
die:
strcpy(b,"*** READ ERROR IN POSTMAN ***\n");
n=strlen(b);
r=0;
while (r<routes)
{
writeln(asRoute[r].path,b,n);
writeln(asRoute[r].path,"~\n",2);
tag(asRoute[r].path);
close(asRoute[r].path);
r++;
}
dun:
if (_ss_size(path,0L)==ERR)
pmlog(LOG_ERR,"_ss_size 0: %m");
close(path);
if (unlink(file)==ERR)
pmlog(LOG_ERR,"unlink %s: %m",file);
if (iDebug)
wstringf(iDebug,"processing of %s complete\n",file);
}
void
Service(file)
char *file;
{
int path;
int outfile;
int status;
int n;
char *args[10];
char **ppc;
if (iDebug)
wstringf(iDebug,"Service(\"%s\")\n",file);
if (ChkTag(file))
return;
path=open(file,O_EXCL|O_RDWR);
if (path==ERR)
{
if (errno==253)
{
if (iDebug)
wstringf(iDebug,"File should not be busy!\n");
return;
}
pmlog(LOG_ERR,"open %s: %m",file);
return;
}
errno=211;
n=readln(path,fromline,80);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (from): %m");
close(path);
return;
}
if (iDebug)
writeln(iDebug,fromline,n);
fromline[n]=0;
if (strncmp(fromline,"FROM: ",6))
{
pmlog(LOG_ERR,"unexpected header in %s\n",file);
close(path);
return;
}
while (n>1)
{
errno=211;
n=readln(path,b,BUF_SIZE);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (hdr): %m");
close(path);
return;
}
}
strcpy(b,file);
strcut(b,'.');
pw=getpwnam(b);
if (!pw || !pw->pw_shell | !*pw->pw_shell)
{
pmlog(LOG_ERR,"cant find service '%s'",b);
close(path);
return;
}
if (*pw->pw_shell!='!')
{
pmlog(LOG_ERR,"unknown service code '%s'",pw->pw_shell);
close(path);
return;
}
_pm_temp(tempfile);
strcat(tempfile,".tmp");
outfile=create(tempfile,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (outfile==ERR)
{
pmlog(LOG_ERR,"create %s: %m",tempfile);
close(path);
return;
}
if (pw->pw_dir && *pw->pw_dir)
if (chdir(pw->pw_dir)==ERR)
{
pmlog(LOG_ERR,"chd %s: %m",pw->pw_dir);
close(path);
return;
}
#ifdef _OS9
setpr(getpid(),pw->pw_pri);
#endif
setuid(pw->pw_uid);
close(0); dup(path);
close(1); dup(outfile);
close(2); dup(outfile);
strcpy(b,pw->pw_shell);
/* should process into b for %f=from, %s=subj here */
if (iDebug)
wstringf(iDebug,"forking '%s'\n",b);
retry1:
ppc=arglist(b,0);
if (!ppc)
{
pmlog(LOG_ERR,"arglist (malloc): %m");
sleep(60);
goto retry1;
}
if (_fork(*ppc+1,ppc,environ)==ERR)
pmlog(LOG_ERR,"fork: %s: %m",*ppc+1);
else
{
wait(&status);
if (status)
{
errno=status;
wstringf(2,"%s exited with error: %m",b);
}
}
free(ppc);
close(0); close(1); close(2);
dup(hLock); dup(hLock); dup(hLock);
if (_gs_size(outfile))
{
close(outfile);
strcpy(b,fromline+6);
strcut(b,' ');
if (iDebug)
wstringf(iDebug,"returning output to %s\n",b);
args[0]="postman";
args[1]="-t";
args[2]=b;
args[3]="-sOutput from service request";
args[4]=tempfile;
args[5]=0;
if (_fork(*args,args,environ)==ERR)
pmlog(LOG_ERR,"fork %s: %m",*args);
else
wait(0);
}
else
close(outfile);
setuid(0);
if (chdir(SPL_DIR)==ERR)
{
pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
exit(errno);
}
close(path);
unlink(file);
unlink(tempfile);
#ifdef _OS9
setpr(getpid(),iPM_PRI);
#endif
if (iDebug)
wstringf(iDebug,"processing of %s complete\n",file);
}
pm_nu(path,node)
int path;
char *node;
{
int n,found;
char **args;
if (!stricmp(node,hostname))
{
/* another node is sending me my info - ignore it */
return(0);
}
if (iDebug)
wstringf(iDebug,"Processing nu for %s\n",node);
resetroute=1; /* force update of routing */
found=_db9(DB_SEEK,hNet,node,strlen(node)+1);
if (found==ERR)
{
pmlog(LOG_ERR,"DB9 seek %s: %m",node);
return(ERR);
}
if (found)
{
if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
{
pmlog(LOG_ERR,"DB9 read %s: %m",node);
return(ERR);
}
}
else
{
memset(&sNode,0,sizeof(sNode));
strcpy(sNode.acN_Name,node);
}
while (n=readln(path,b,BUF_SIZE))
{
if (!n)
{
n=ERR;
errno=211;
}
if (n==ERR)
{
pmlog(LOG_ERR,"read (nu): %m");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
if (n==1)
break;
b[n-1]=0;
switch (*b)
{
case 'P':
args=arglist(b+1,'|');
if (!args[0] || !args[1] || !args[2] || !args[3] || !args[4])
{
pmlog("postman nu P: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
strcpy(sNode.acN_ICode,args[0]);
strcpy(sNode.acN_Phone,args[1]);
sNode.wN_Speed=atoi(args[2]);
strcpy(sNode.acN_ISDN,args[3]);
strcpy(b,args[4]);
if (*b)
{
free(args);
args=arglist(b,'.');
if (!args[0] || !args[1] || !args[2] || !args[3])
{
pmlog(LOG_ERR,"postman nu P: bad INET");
memset(sNode.abN_INET,0,4);
}
else
{
sNode.abN_INET[0]=atoi(args[0]);
sNode.abN_INET[1]=atoi(args[1]);
sNode.abN_INET[2]=atoi(args[2]);
sNode.abN_INET[3]=atoi(args[3]);
}
}
else
memset(sNode.abN_INET,0,4);
free(args);
break;
case 'D':
strcpy(sNode.acN_Desc,b+1);
break;
case 'A':
args=arglist(b+1,'|');
if (!args[0] || !args[1] || !args[2] || !args[3] || !args[4])
{
pmlog("postman nu A: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
strcpy(sNode.acN_Addr,args[0]);
strcpy(sNode.acN_City,args[1]);
strcpy(sNode.acN_State,args[2]);
strcpy(sNode.acN_Zip,args[3]);
strcpy(sNode.acN_Country,args[4]);
free(args);
break;
case 'O':
args=arglist(b+1,'|');
if (!args[0] || !args[1])
{
pmlog("postman nu O: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
strcpy(sNode.acN_Sysop,args[0]);
strcpy(sNode.acN_SPhone,args[1]);
free(args);
break;
case 'T':
args=arglist(b+1,'|');
if (!args[0] || !args[1] || !args[2] || !args[3] ||
!args[4] || !args[5] || !args[6] || !args[7])
{
pmlog("postman nu T: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
sNode.cN_UTC=atoi(args[0]);
sNode.bN_DST=atoi(args[1]);
sNode.abN_WkdHrs[0]=atoi(args[2]);
sNode.abN_WkdHrs[1]=atoi(args[3]);
sNode.abN_WkeHrs[0]=atoi(args[4]);
sNode.abN_WkeHrs[1]=atoi(args[5]);
sNode.abN_NetHrs[0]=atoi(args[6]);
sNode.abN_NetHrs[1]=atoi(args[7]);
free(args);
break;
case 'S':
args=arglist(b+1,'|');
if (!args[0] || !args[1])
{
pmlog("postman nu S: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
sNode.bN_Status=atoi(args[0]);
sNode.bN_MType=atoi(args[1]);
free(args);
break;
case '1':
case '2':
case '3':
case '4':
n=*b-'1';
if (b[1])
{
args=arglist(b+1,'|');
if (!args[0] || !args[1] || !args[2] ||
!args[3] || !args[4])
{
pmlog("postman nu #: missing argument");
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
strcpy(sNode.asNode2[n].acN2_Name,args[0]);
sNode.asNode2[n].bN2_MaxAge=atoi(args[1]);
sNode.asNode2[n].bN2_MinAge=atoi(args[2]);
sNode.asNode2[n].bN2_MaxSize=atoi(args[3]);
sNode.asNode2[n].bN2_MinSize=atoi(args[4]);
free(args);
}
else
memset(sNode.asNode2[n],0,sizeof(struct sNode2));
break;
default:
pmlog(LOG_ERR,"postman nu: unknown code '%c'",*b);
_db9(DB_ULOCK,hNet,0,0);
return(ERR);
}
}
if (found)
{
if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
{
pmlog(LOG_ERR,"DB9 write %s: %m",node);
return(ERR);
}
}
else
{
if (_db9(DB_ADD,hNet,&sNode,sizeof(sNode))==ERR)
{
pmlog(LOG_ERR,"DB9 add %s: %m",node);
return(ERR);
}
}
}
void
PostServ(file)
char *file;
{
int path;
int n;
char *pcTemp;
if (iDebug)
wstringf(iDebug,"Service(\"%s\")\n",file);
if (ChkTag(file))
return;
path=open(file,O_EXCL|O_RDWR);
if (path==ERR)
{
pmlog(LOG_ERR,"open %s: %m",file);
return;
}
errno=211;
n=readln(path,fromline,80);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (from): %m");
close(path);
return;
}
if (iDebug)
writeln(iDebug,fromline,n);
fromline[n]=0;
if (strncmp(fromline,"FROM: ",6))
{
pmlog(LOG_ERR,"unexpected header in %s",file);
close(path);
return;
}
_pm_addr(fromline+6);
if (stricmp(A_user,"postman"))
{
pmlog(LOG_ERR,"bad from '%s'",fromline+6);
close(path);
return;
}
if (!stricmp(A_host,hostname))
{
/* ignore nu from myself */
close(path);
unlink(file);
return;
}
while (n>1)
{
errno=211;
n=readln(path,b,BUF_SIZE);
if (!n || n==ERR)
{
pmlog(LOG_ERR,"read (hdr): %m");
close(path);
return;
}
}
while (n=readln(path,b,BUF_SIZE))
{
if (n==ERR)
{
pmlog(LOG_ERR,"read (cmd): %m");
close(path);
return;
}
if (n==1)
continue;
b[n-1]=0;
pcTemp=strcut(b,' ');
if (!strcmp(b,"nu"))
{
if (!pcTemp)
{
pmlog(LOG_ERR,"postman cmd nu missing argument");
close(path);
return;
}
if (pm_nu(path,pcTemp))
{
close(path);
return;
}
}
else
{
pmlog(LOG_ERR,"unknown postman cmd '%s'",b);
}
}
close(path);
unlink(file);
}
void
Scan()
{
struct dirent *d;
char *e;
int n;
if (iDebug)
wstringf(iDebug,"Scan()\n");
rewinddir(dp);
while (d=readdir(dp))
{
e=d->d_name;
while (*e && *e!='.')
e++;
if (!*e)
continue;
n=e-d->d_name;
if (!strcmp(e,".mq"))
{
*rcvd_from=0;
Process(d->d_name);
}
else
if (!strcmp(e,".mh"))
{
*rcvd_from=0;
Process(d->d_name);
}
else
if (!strcmp(e,".sq"))
{
strcpy(rcvd_from,d->d_name);
rcvd_from[n]=0;
if (*hostname)
{
strcat(rcvd_from,"@");
strcat(rcvd_from,hostname);
}
Process(d->d_name);
}
else
if (!strcmp(e,".nq"))
{
strcpy(rcvd_from,d->d_name);
rcvd_from[n]=0;
Process(d->d_name);
}
else
if (!strcmp(e,".si"))
{
Service(d->d_name);
}
else
if (!strcmp(e,".pi"))
{
PostServ(d->d_name);
}
}
}
void
MailSyslog()
{
#ifndef _UNIX
char *args[8];
int hLog;
struct fildes fd;
hLog=open(LOG_FILE,0);
if (hLog==ERR)
{
if (errno!=ENOENT)
pmlog(LOG_ERR,"open %s: %m",LOG_FILE);
return;
}
if (_gs_gfd(hLog,&fd,sizeof(fd))==ERR)
{
pmlog(LOG_ERR,"_gs_gfd %s: %m",LOG_FILE);
close(hLog);
return;
}
close(hLog);
time(&lTime);
psTime=localtime(&lTime);
if (psTime->tm_mday==fd.fd_dcr[2])
return;
/* log file was not created today, rename and mail it */
unlink("../syslog.old");
if (_rename(LOG_FILE,"syslog.old")==ERR)
{
pmlog(LOG_ERR,"rename %s %s: %m",LOG_FILE,"syslog.old");
return;
}
setuid(iPM_ID);
args[0]="postman";
args[1]="-tsysop";
args[2]="-sSystem Log";
args[3]="../syslog.old";
args[4]=0;
if (_fork(*args,args,environ)==ERR)
pmlog(LOG_ERR,"fork %s: %m",*args);
else
wait(0);
setuid(0);
#endif
}
Minute()
{
}
Hourly()
{
}
Nightly()
{
MailSyslog();
}
void
Sleep()
{
static int last_min;
static int last_hour;
static int last_mday;
tm_update:
time(&lTime);
psTime=localtime(&lTime);
if (last_min!=psTime->tm_min)
{
Minute();
last_min=psTime->tm_min;
goto tm_update;
}
if (last_hour!=psTime->tm_hour)
{
Hourly();
last_hour=psTime->tm_hour;
goto tm_update;
}
if (last_mday!=psTime->tm_mday)
{
Nightly();
last_mday=psTime->tm_mday;
goto tm_update;
}
/* sleep until next minute */
endpwent();
sleep(60-psTime->tm_sec);
}
Daemon()
{
openlog("postman",0,LOG_STGNET);
if (chdir(SPL_DIR)==ERR)
{
pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
exit(errno);
}
unlink(LOCK_FILE);
hLock=create(LOCK_FILE,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (hLock==ERR)
{
if (errno==253)
exit(0); /* already running */
pmlog(LOG_ERR,"creat %s: %m",LOCK_FILE);
exit(errno);
}
if (iDebug)
{
iDebug=hLock=dup(iDebug);
}
else
{
close(0); close(1); close(2);
dup(hLock); dup(hLock); dup(hLock);
}
hNet=open(STG_FILE,O_RDWR|O_BINARY);
if (hNet==ERR)
{
pmlog(LOG_ERR,"open %s: %m",STG_FILE);
exit(errno);
}
if (_db9(DB_OPEN,hNet,"nodes",6)==ERR)
{
pmlog(LOG_ERR,"DB9 open nodes: %m");
exit(errno);
}
/* select case insensitive seek */
if (_db9(DB_MATCH,hNet,-1,0)==ERR)
{
pmlog(LOG_ERR,"DB9 match c-i: %m");
exit(errno);
}
dp=opendir(".");
if (!dp)
{
pmlog(LOG_ERR,"opendir: %m");
exit(errno);
}
#ifdef _OS9
setpr(getpid(),iPM_PRI);
#endif
MailSyslog();
while (1)
{
if (resetroute)
{
/* ResetRoute(); */
resetroute=0;
}
Scan();
Sleep();
}
}
ForkDaemon()
{
int hLock;
char *args[2];
if (chdir(SPL_DIR)==ERR)
{
pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
/* don't exit w/error!!! */
exit(0);
}
hLock=open(LOCK_FILE,O_RDWR);
if (hLock==ERR && errno==253)
exit(0); /* postman already running */
pmlog(LOG_ERR,"postman daemon has died - restarting");
args[0]="@postman";
args[1]=0;
if (_fork(*args+1,args,environ)==ERR)
pmlog(LOG_ERR,"fork postman: %m");
exit(0);
}
NodeUpd(hSpool,flag)
int hSpool;
byte flag;
{
int i;
wstringf(hSpool,"nu %s\n",sNode.acN_Name);
if (flag&NU_PHONE)
wstringf(hSpool,"P%s|%s|%d|%s|%d.%d.%d.%d\n",
sNode.acN_ICode,
sNode.acN_Phone,
(int)sNode.wN_Speed,
sNode.acN_ISDN,
(int)sNode.abN_INET[0],
(int)sNode.abN_INET[1],
(int)sNode.abN_INET[2],
(int)sNode.abN_INET[3]);
if (flag&NU_DESC)
wstringf(hSpool,"D%s\n",sNode.acN_Desc);
if (flag&NU_ADDR)
wstringf(hSpool,"A%s|%s|%s|%s|%s\n",
sNode.acN_Addr,
sNode.acN_City,
sNode.acN_State,
sNode.acN_Zip,
sNode.acN_Country);
if (flag&NU_OPER)
wstringf(hSpool,"O%s|%s\n",
sNode.acN_Sysop,
sNode.acN_SPhone);
if (flag&NU_TIME)
wstringf(hSpool,"T%d|%d|%d|%d|%d|%d|%d|%d\n",
(int)sNode.cN_UTC,
(int)sNode.bN_DST,
(int)sNode.abN_WkdHrs[0],
(int)sNode.abN_WkdHrs[1],
(int)sNode.abN_WkeHrs[0],
(int)sNode.abN_WkeHrs[1],
(int)sNode.abN_NetHrs[0],
(int)sNode.abN_NetHrs[1]);
if (flag&NU_STATUS)
wstringf(hSpool,"S%d|%d\n",
(int)sNode.bN_Status,
(int)sNode.bN_MType);
if (flag&NU_ROUTE)
{
i=0;
while (i<4)
{
if (!*sNode.asNode2[i].acN2_Name)
wstringf(hSpool,"%d\n",i+1);
else
wstringf(hSpool,"%d%s|%d|%d|%d|%d\n",
i+1,
sNode.asNode2[i].acN2_Name,
(int)sNode.asNode2[i].bN2_MaxAge,
(int)sNode.asNode2[i].bN2_MinAge,
(int)sNode.asNode2[i].bN2_MaxSize,
(int)sNode.asNode2[i].bN2_MinSize);
i++;
}
}
wstringf(hSpool,"\n");
}
NetUpd(node)
char *node;
{
int hSpool;
int n;
hNet=open(STG_FILE,O_RDWR|O_BINARY);
if (hNet==ERR)
exit(syserr("open %s: %m",STG_FILE));
if (_db9(DB_OPEN,hNet,"nodes",6)==ERR)
exit(syserr("DB9 open nodes: %m"));
if (_db9(DB_MATCH,hNet,-1,0)==ERR)
exit(syserr("DB9 match c-i: %m"));
_pm_temp(tempfile);
stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
hSpool=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (hSpool==ERR)
exit(syserr("create %s: %m",b));
stringf(b,"FROM: postman");
if (*hostname)
{
strcat(b,"@");
strcat(b,hostname);
}
strcat(b,"\n");
writeln(hSpool,b,80);
strcpy(b,"TO : postman@*\n");
writeln(hSpool,b,80);
writeln(hSpool,"\n",1);
if (!node)
node=hostname;
/* loop here sending network update commands */
if (*node=='*')
{
while (n=_db9(DB_NEXT,hNet,&sNode,sizeof(sNode)))
{
if (n==ERR)
exit(syserr("DB9 next node: %m"));
_db9(DB_ULOCK,hNet,0,0);
NodeUpd(hSpool,-1); /* send all fields */
}
}
else
{
n=_db9(DB_SEEK,hNet,node,strlen(node)+1);
if (n==ERR)
exit(syserr("DB9 seek %s: %m",node));
if (!n)
exit(syserr("node %s not found",node));
if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 read node: %m"));
NodeUpd(hSpool,-1); /* for now, update all fields */
sNode.bN_Update=0;
if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
exit(syserr("DB9 write node: %m"));
}
writeln(hSpool,"~\n",2);
tag(hSpool);
close(hSpool);
/* put in queue */
stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
strcat(tempfile,".mq");
if (_rename(b,tempfile)==ERR)
exit(syserr("rename %s %s: %m",b,tempfile));
exit(0);
}
Queue(file)
char *file;
{
int hSpool;
/* must be user 0 or a mail service to queue file directly */
/* no, mail services must deliver the hard way */
if (pw->pw_uid)
/* if (!pw->pw_shell || *pw->pw_shell!='!') */
Help();
setuid(0);
/* should already be in spl dir, but force the issue anyway */
if (chdir(SPL_DIR)==ERR)
{
pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
exit(errno);
}
hSpool=open(file,O_EXCL|O_RDWR);
if (hSpool==ERR)
{
pmlog(LOG_ERR,"open %s: %m",file);
exit(errno);
}
tag(hSpool);
close(hSpool);
stringf(b,"%s.sq",pw->pw_name);
if (_rename(file,b)==ERR)
{
pmlog(LOG_ERR,"rename %s %s: %m",file,b);
exit(errno);
}
ForkDaemon();
}
main(argc,argv)
char **argv;
{
int hSpool,hMail;
int n;
gethostname(hostname,32);
pw=getpwnam("postman");
if (!pw)
exit(syserr("user 'postman' not found"));
iPM_ID=pw->pw_uid;
#ifdef _OS9
iPM_PRI=pw->pw_pri;
#endif
switch (**argv)
{
case '@':
if (!getuid())
Daemon();
case '-':
case '!':
Interactive();
}
if (!*++argv)
Help();
if (!strcmp(*argv,"-#"))
{
wstringf(2,"postman: %s\n",STG_VER);
exit(0);
}
/* check for option flags the hard way here */
if (!stricmp(*argv,"-i"))
Interactive();
if (!stricmp(*argv,"-z") && !getuid())
{
iDebug=2;
Daemon();
}
if (!stricmp(*argv,"-nu") && !getuid())
NetUpd(*++argv);
pw=getpwuid(getuid());
if (!pw)
exit(syserr("who are you?"));
if (**argv && **argv!='-')
Queue(*argv);
if (strncmp(*argv,"-t",2))
Help();
/* set to user 0 and create temporary file */
setuid(0);
_pm_temp(tempfile);
stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
hSpool=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
if (hSpool==ERR)
exit(syserr("create %s: %m",b));
if (pw->pw_gecos)
strcut(pw->pw_gecos,':');
strcpy(b,"FROM: ");
strcat(b,pw->pw_name);
if (*hostname)
{
strcat(b,"@");
strcat(b,hostname);
}
if (pw->pw_gecos && *pw->pw_gecos)
{
strcat(b," (");
strcat(b,pw->pw_gecos);
strcat(b,")");
}
b[79]=0;
strcat(b,"\n");
writeln(hSpool,b,80);
while (*argv && !strncmp(*argv,"-t",2))
{
(*argv)+=2;
if (!**argv)
argv++;
strcpy(b,"TO : ");
strcat(b,*argv);
argv++;
b[79]=0;
strcat(b,"\n");
writeln(hSpool,b,80);
}
if (*argv && !strncmp(*argv,"-s",2))
{
(*argv)+=2;
if (!**argv)
argv++;
strcpy(b,"SUBJ: ");
strcat(b,*argv);
argv++;
b[79]=0;
strcat(b,"\n");
writeln(hSpool,b,80);
}
time(&lTime);
psTime=localtime(&lTime);
stringf(b,"DATE: %02d/%02d/%02d %02d:%02d:%02d\n",
psTime->tm_year,
psTime->tm_mon+1,
psTime->tm_mday,
psTime->tm_hour,
psTime->tm_min,
psTime->tm_sec);
writeln(hSpool,b,80);
writeln(hSpool,"\n",1);
if (!*argv)
exit(syserr("mail file not specified"));
hMail=open(*argv,O_RDONLY);
while (n=readln(hMail,b,80))
{
if (n==ERR)
exit(syserr("readln %s: %m",*argv));
if (n==2 && *b=='~')
{
strcpy(b,"~ \n");
n=3;
}
writeln(hSpool,b,n);
}
close(hMail);
writeln(hSpool,"~\n",2);
tag(hSpool);
close(hSpool);
/* rename spool file to put in queue (.mq) */
stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
strcat(tempfile,".mq");
if (_rename(b,tempfile)==ERR)
exit(syserr("rename %s %s: %m",b,tempfile));
/* check to insure a postman is spooling */
ForkDaemon();
}
#ifdef BOGUS
/* decide routing */
if (_pm_test(pcTo))
{
pmlog(LOG_CRIT,"message cannot be delivered");
exit(1);
}
pw=getpwnam(A_user);
if (!pw)
{
pmlog(LOG_CRIT,"unknown user '%s'",A_user);
exit(1);
}
/* deliver message */
if (*argv)
{
close(0);
if (open(*argv,O_RDONLY)==ERR)
{
pmlog(LOG_CRIT,"open %s: %m",*argv);
exit(1);
}
}
setuid(0);
#ifdef _OS9
if (access(pw->pw_dir,0x83)==ERR)
#else
if (access(pw->pw_dir,R_OK)==ERR)
#endif
{
#ifdef _OS9
strucs(pw->pw_dir);
#endif
#ifdef _OS9
if (mknod(pw->pw_dir,O_RDWR)==ERR)
#else
if (mkdir(pw->pw_dir,S_IREAD|S_IWRITE)==ERR)
#endif
{
pmlog(LOG_ERR,"makdir %s: %m",pw->pw_dir);
exit(1);
}
/* set owner of directory */
chown(pw->pw_dir,pw->pw_uid,-1);
}
strcpy(b,pw->pw_dir);
strcat(b,"/mailbox");
hTemp=open(b,O_RDWR);
if (hTemp==ERR)
{
if (errno!=216)
{
pmlog(LOG_ERR,"open %s: %m",b);
exit(1);
}
hTemp=create(b,O_RDWR,S_IREAD|S_IWRITE);
if (hTemp==ERR)
{
pmlog(LOG_ERR,"create %s: %m",b);
exit(1);
}
fchown(hTemp,pw->pw_uid,-1);
}
_ss_lock(hTemp,-1);
lseek(hTemp,0L,2);
stringf(b,"FROM: %s\n",pcFrom);
writeln(hTemp,b,BUF_SIZE);
stringf(b,"TO : %s\n",pcTo);
writeln(hTemp,b,BUF_SIZE);
pcTemp=pcHead;
while (pcTemp)
{
stringf(b,"%s\n",pcTemp+4);
writeln(hTemp,b,80);
pcTemp=*(char**)pcTemp;
}
writeln(hTemp,"\n",1);
while (1)
{
n=read(0,b,BUF_SIZE);
if (n==ERR)
{
pmlog(LOG_ERR,"error reading message: %m");
break;
}
if (!n)
break;
write(hTemp,b,n);
}
writeln(hTemp,"~\n",2);
close(hTemp);
#endif