|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 16411 (0x401b)
Types: TextFile
Names: »slocal.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Chans/slocal/slocal.c«
/* slocal.c: structured message local delivery channel */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/slocal/RCS/slocal.c,v 5.0 90/09/20 15:54:05 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Chans/slocal/RCS/slocal.c,v 5.0 90/09/20 15:54:05 pp Exp Locker: pp $
*
* $Log: slocal.c,v $
* Revision 5.0 90/09/20 15:54:05 pp
* rcsforce : 5.0 public release
*
*/
/*********************************************************************\
* *
* local channel - deliver as structured messages *
* (based on local.c 10/01/89) *
* *
* *
\*********************************************************************/
#include "head.h"
#include "util.h"
#include "prm.h"
#include "q.h"
#include "qmgr.h"
#include "dr.h"
#include <isode/logger.h>
#include <sys/stat.h>
#include "loc_user.h"
#include <sys/file.h>
#include <isode/usr.dirent.h>
#define NULLDIR ((DIR*)0)
#define NULLDCT ((struct dirent *)0)
extern char *ad_getlocal();
extern char *mquedir;
extern char *quedfldir;
extern CHAN *ch_nm2struct();
extern void err_abrt(), getfpath(), rd_end(), chan_init();
static Q_struct Qstruct;
static char *basename();
static CHAN *mychan;
static char *this_msg;
static char *formatdir=NULLCP;
static int initproc();
static void dirinit();
static struct type_Qmgr_DeliveryStatus *process();
static char mboxdir[] = "PPMail"; /* main PP mail directory */
static char inboxdir[] = "inbox"; /* inbox */
static char tempdir[] = "slocal"; /* temporary directory name */
static char alert_file[] = "/alert"; /* alert script in PPMail */
static char alert_message[] = "You have new mail from PP"; /* system call */
static char base_string[] = "base"; /* basename target in file */
/* from msg_rfile */
/* ----------------------- Begin Routines ------------------------------ */
main (argc, argv)
int argc;
char **argv;
{
char *p;
p = argv[0];
if (*p == '/') {
p = rindex (p, '/');
p++;
}
/* Init the channel - and find out who we are */
chan_init (p);
dirinit();
#ifdef PP_DEBUG
if (argc > 1 && strcmp (argv[1], "debug") == 0)
debug_channel_control (argc,argv, initproc, process, NULLIFP);
else
#endif
channel_control (argc, argv, initproc, process, NULLIFP);
exit (0);
}
static int initproc (arg)
struct type_Qmgr_Channel *arg;
{
char *p;
p = qb2str (arg);
PP_TRACE (("initproc (%s)", p));
if ((mychan = ch_nm2struct (p)) == NULLCHAN)
err_abrt (RP_PARM, "Channel '%s' not known", p);
free (p);
return OK;
}
static struct type_Qmgr_DeliveryStatus *process (arg)
struct type_Qmgr_ProcMsg *arg;
{
struct type_Qmgr_UserList *up;
struct prm_vars prm;
Q_struct *qp = &Qstruct;
ADDR *ad_sendr = NULL,
*ad_recip = NULL;
char msgq[FILNSIZE];
int ad_count,
retval;
bzero ((char *) qp, sizeof (*qp));
if (this_msg) free (this_msg);
this_msg = qb2str (arg -> qid);
PP_TRACE (("slocal/processing msg %s", this_msg));
(void) sprintf (msgq, "%s%s", mquedir, this_msg);
delivery_init (arg -> users);
retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count);
if (rp_isbad (retval)) {
PP_LOG (LLOG_EXCEPTIONS, ("slocal/rd_msg err: %s", this_msg));
return delivery_setall (int_Qmgr_status_messageFailure);
}
for (up = arg -> users; up; up = up -> next)
douser (up -> RecipientId -> parm, ad_recip, msgq);
rd_end();
return deliverystate;
}
static void dirinit() /* Change into pp queue space */
{
PP_TRACE (("dirinit()"));
if (chdir (quedfldir) < 0)
err_abrt (RP_LIO, "Uanble to change directory to '%s'",
quedfldir);
}
/* process one extension-id for this msg */
static int douser (rno, ad_recip, msgd)
int rno;
ADDR *ad_recip;
char *msgd;
{
ADDR *ap;
PP_TRACE (("douser (%d, ad_recip, %s)", rno, msgd));
for (ap = ad_recip; ap ; ap = ap->ad_next) {
if (rno != ap -> ad_no)
continue;
if (lchan_acheck (ap, mychan, 1, NULLVP) == NOTOK)
return RP_MECH;
else {
deliver (ap, msgd);
return RP_OK;
}
}
PP_LOG (LLOG_EXCEPTIONS, ("slocal/user not recipient of %s",
this_msg));
delivery_set (rno, int_Qmgr_status_messageFailure);
return RP_MECH;
}
static int deliver (ap, msgd)
ADDR *ap;
char *msgd;
{
static LocUser *loc;
char umaildir[FILNSIZE]; /* usr structured mail dir - PPMail */
char uinboxdir[FILNSIZE]; /* usr structured inbox dir - PPMail*/
char utempdir[FILNSIZE]; /* temp dir - PPMail/inbox/.slocal */
char newname [FILNSIZE]; /* new name i.e. 12/, 13/ etc. */
char fname [FILNSIZE]; /* filename */
char fnameout[FILNSIZE]; /* output name */
/* PPMail/inbox/.slocal/filename */
char new_directory[FILNSIZE]; /* place for new dir names to */
/* be generated in message */
char ualert_file[FILNSIZE]; /* users alert file name */
char s_string[LOTS]; /* system call string */
char *p,*q;
char *user;
int next_msgno;
int alert_exists;
int i;
int retval,sysreply;
RP_Buf rps, *rp = &rps;
PP_TRACE (("slocal/deliver msgd=%s", msgd));
if (ap->ad_outchan->li_chan != mychan) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/this extension-id (%d) is not for this channel",
ap->ad_extension));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_BAD;
}
if ((user = ad_getlocal (ap -> ad_r822adr, AD_822_TYPE)) == NULLCP) {
char buffer[BUFSIZ];
(void) sprintf (buffer, "User %s not local!", ap -> ad_r822adr);
PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer));
delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR);
set_1dr (&Qstruct, ap -> ad_no,
DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer);
wr_q2dr (&Qstruct, this_msg);
return RP_USER;
}
if ((loc = tb_getlocal (user, mychan)) == NULL) {
PP_LOG (LLOG_EXCEPTIONS,
("User %s not registered in chan %s table",
user, mychan -> ch_name));
free (user);
delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR);
set_1dr (&Qstruct, ap -> ad_no,
DRR_UNABLE_TO_TRANSFER,
DRD_UA_UNAVAILABLE,
"User not registered in delivery table");
wr_q2dr (&Qstruct, this_msg);
return RP_USER;
}
PP_TRACE (("Found entry for '%s' uid '%s' (%d) directory '%s'",
ap -> ad_r822adr,
loc -> username ? loc -> username : "<none>",
loc -> uid, loc -> directory));
if (rp_isbad (loc_init (loc))) {
PP_LOG (LLOG_EXCEPTIONS, ("loc_init error"));
delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure);
return RP_MECH;
}
/*
Find the correctly formatted version of the message
*/
if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) {
PP_LOG (LLOG_EXCEPTIONS,
("Can't locate message %s", this_msg));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_MECH;
}
/* --- *** ---
Try to cd into umaildir - if unable to do so then create
the directory and log it. Then try opening.
--- *** --- */
(void) sprintf (umaildir, "%s/%s", loc -> directory, mboxdir);
if (rp_isbad (loc_cd (umaildir, rp))) {
if (rp_isbad (loc_mkdir (umaildir, 0700, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Unable to create '%s'", umaildir));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_FOPN;
}
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Created directory '%s'", umaildir));
}
if (rp_isbad (loc_opendir (umaildir, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Unable to open directory '%s'", umaildir));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_FOPN;
}
if (rp_isbad (loc_closedir (rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Unable to close directory '%s'", umaildir));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_FOPN;
}
getfpath (mychan -> ch_info, umaildir, ualert_file);
(void) strcat (ualert_file, alert_file);
if (rp_isbad (loc_open (ualert_file, "r", 1, rp))) {
alert_exists=FALSE;
loc_close (rp);
}
else
alert_exists=TRUE;
(void) sprintf (uinboxdir, "%s/%s", umaildir, inboxdir);
/*
Try to open uinboxdir - if unable then create in user's
directory and log it. Retry open - fail if cannot open.
*/
if (rp_isbad (loc_cd (uinboxdir, rp))) {
if (rp_isbad (loc_mkdir (uinboxdir, 0700, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Unable to create user inbox directory '%s'",
uinboxdir));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_FOPN;
}
else {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/Created user inbox directory '%s'",
uinboxdir));
}
}
if (rp_isbad (loc_opendir (uinboxdir, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't open user inbox '%s'", uinboxdir));
return RP_FOPN;
}
/* Generate new (temp) dir, then copy all body part files into it. */
(void) sprintf (utempdir, "%s/%s", uinboxdir, tempdir);
if (rp_isbad (loc_mkdir (utempdir, 0700, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't create user mail temporary directory '%s'",
utempdir));
if (rp_isbad (loc_isdir (utempdir, rp))) {
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_FOPN;
}
else {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/using existing temporary directory %s",
utempdir));
}
}
PP_TRACE (("delivering to mail temporary directory %s", utempdir));
if (rp_isbad (retval = msg_rinit (formatdir))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/msg_rinit can't init %s", formatdir));
loc_closedir (rp); /* close directory */
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_MECH;
}
PP_TRACE (("slocal msg_rinit formatdir %s", formatdir));
/* --- *** ---
* Strategy for decoding filenames from queue :
* look for first occurence of `base' in name - then skip
* to the next `/' - all that follows is the structure
* of the message itself.
* basename() returns the path/filename component
* following the `/'
--- *** --- */
if (dump_mtsparams (&Qstruct, utempdir, ap) != OK) {
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_FIO;
}
while ((retval = msg_rfile (fname)) == RP_OK) {
PP_TRACE (("slocal msg_rfile returned %s", fname));
if ((p = basename (fname)) == NULLCP ) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/basename() cannot extract real message"));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_FOPN;
}
q = p;
while (q = index (q,'/')) { /* keep making directories */
strcpy (new_directory,utempdir);
strcat (new_directory,"/");
strncat (new_directory,p,q-p);
if (rp_isbad (loc_mkdir (new_directory, 0700, rp))) {
if (rp_isbad (loc_isdir (new_directory, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/'%s' is not a directory",
new_directory));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_FOPN;
}
else {
PP_DBG (("slocal/using existing message directory %s",new_directory));
}
}
else {
PP_TRACE (("slocal/created message directory %s", new_directory));
}
q++; /* step past current '/' */
}
(void) sprintf (fnameout,"%s/%s",utempdir,p);
if ((i = slocal_copy (fname, fnameout)) != RP_OK) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/slocal_copy from %s to %s failed - error %d", fname, fnameout,i));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
return RP_MECH;
}
}
retval = msg_rend();
if (retval != RP_OK) {
delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure);
return retval;
}
if (rp_isbad (loc_nextmess (uinboxdir, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/cannot determine next message number for %s", uinboxdir));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_MECH;
}
PP_DBG (("slocal/next message number in %s = %s",
uinboxdir,rp -> rp_line));
next_msgno = atoi (rp ->rp_line);
(void) sprintf (newname, "%s/%d\0", uinboxdir, next_msgno);
if (rp_isbad (loc_closedir (rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't close directory '%s'", uinboxdir));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_FOPN;
}
PP_TRACE (("slocal/renaming temp. dir. %s to %s", utempdir,newname));
if (rp_isbad (loc_move (utempdir, newname, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't rename user mail temporary directory %s to %s", utempdir,newname));
delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure);
return RP_MECH;
}
PP_NOTICE ((">>> slocal: Message delivered to %s", user));
if (ap -> ad_usrreq == AD_USR_CONFIRM ||
ap -> ad_mtarreq == AD_MTA_CONFIRM ||
ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) {
set_1dr (&Qstruct, ap -> ad_no, DRR_NO_REASON,
-1, NULLCP);
wr_q2dr (&Qstruct, this_msg);
delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR);
}
else {
(void) wr_ad_status (ap, AD_STAT_DONE);
delivery_set (ap -> ad_no, int_Qmgr_status_success);
}
retval = wr_ad_status (ap, AD_STAT_DONE);
if (alert_exists) {
(void) sprintf (s_string,"%s %s %d %s &\n",
ualert_file, loc -> username,
next_msgno, alert_message);
PP_TRACE (("slocal/calling system with '%s'", s_string));
if (sysreply = loc_system (s_string, rp)) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/system() call returns value %d",
sysreply));
}
}
/* --- free locations --- */
if (loc) {
(void) loc_end();
free_loc_user (loc);
}
if (user)
free (user);
delivery_set (ap -> ad_no,
rp_isbad (retval) ? int_Qmgr_status_messageFailure :
int_Qmgr_status_success);
return retval;
}
/* --- open fname, copy to fnameout in smailbox --- */
static slocal_copy (fname, fnameout)
char *fname;
char *fnameout;
{
FILE *ifp;
char buf[BUFSIZ];
int n, retval = RP_OK;
RP_Buf rps, *rp = &rps;
PP_TRACE (("slocal_copy (%s, fp)", fname));
if ((ifp = fopen (fname,"r")) == NULL) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't read file '%s'", fname));
return (RP_FOPN);
}
if (rp_isbad (loc_open (fnameout, "w", 1, rp))) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't open file '%s'", fnameout));
return (RP_FOPN);
}
while ((n = fread (buf, sizeof (char), sizeof (buf), ifp)) > 0)
if (loc_write (buf, n, rp) != RP_OK) {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/can't write to file %s [%s]",
fnameout, rp ->rp_line));
retval = rp ->rp_val;
break;
}
(void) fclose (ifp);
(void) loc_close (rp);
return (retval);
}
/* --- extract basename from full path --- */
static char *basename (f)
char *f;
{
char *p,*q;
int i;
i=strlen (base_string); /* length of "base" (probably 4) */
for (p=f;*p;++p) {
if (!strncmp (p,base_string,i))
break; /* found it */
}
if (*p == '\0') {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/basename can't find %s in %s", base_string,f));
return (NULLCP);
}
if (q = index (p,'/'))
return (++q);
else {
PP_LOG (LLOG_EXCEPTIONS,
("slocal/basename can't find '/' after %s",
base_string));
return (NULLCP);
}
}
static dump_mtsparams (qp, tmp, ap2)
Q_struct *qp;
char *tmp;
ADDR *ap2;
{
char buf[BUFSIZ], buf2[BUFSIZ];
ADDR *ap;
FILE *fp;
(void) strcpy (buf, "/tmp/mtsXXXXXX");
mktemp (buf);
if ((fp = fopen (buf, "w+")) == NULL)
return NOTOK;
if (rp_isbad (wr_q (qp, fp))) {
(void) fclose (fp);
(void) unlink (buf);
return NOTOK;
}
if (rp_isbad (wr_adr (qp -> Oaddress, fp, AD_ORIGINATOR))) {
(void) fclose (fp);
(void) unlink (buf);
return NOTOK;
}
for (ap = qp -> Raddress; ap; ap = ap -> ad_next) {
if (ap -> ad_no != ap2 -> ad_no)
ap -> ad_resp = FALSE;
if (rp_isbad (wr_adr (ap, fp, AD_RECIPIENT))) {
(void) fclose (fp);
(void) unlink (buf);
return NOTOK;
}
}
(void) fflush (fp);
(void) fclose (fp);
(void) sprintf (buf2, "%s/MTS-parameters", tmp);
if (rp_isbad (slocal_copy (buf, buf2))) {
(void) unlink (buf);
return NOTOK;
}
(void) unlink (buf);
return OK;
}