|
|
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 l
Length: 11210 (0x2bca)
Types: TextFile
Names: »loc_parent.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Chans/822-local/loc_parent.c«
/* loc_parent.c: local delivery channel - parent process */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/822-local/RCS/loc_parent.c,v 5.0 90/09/20 15:44:59 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Chans/822-local/RCS/loc_parent.c,v 5.0 90/09/20 15:44:59 pp Exp Locker: pp $
*
* $Log: loc_parent.c,v $
* Revision 5.0 90/09/20 15:44:59 pp
* rcsforce : 5.0 public release
*
*/
/*
Works as parent & child. New child for each message. Child does
actual delivery of message, parent interacts with PP.
*/
#include "util.h"
#include "retcode.h"
#include "prm.h"
#include "q.h"
#include "dr.h"
#include "qmgr.h"
#include <isode/logger.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <signal.h>
#include "loc_user.h"
#ifndef USRPATH
#define USRPATH "."
#endif
extern char *mquedir;
extern char *quedfldir;
extern CHAN *ch_nm2struct ();
extern char *mboxname;
extern char *delim1;
extern char *delim2;
extern char *hdr_822_bp;
extern char *ad_getlocal ();
extern void chan_init(), err_abrt(), rd_end();
CHAN *mychan;
static char *this_msg;
static int initproc ();
static int douser ();
static int deliver ();
static void dirinit ();
static struct type_Qmgr_DeliveryStatus *process ();
Q_struct Qstruct;
static char env_user[LINESIZE];
static char env_shell[LINESIZE];
static char env_home[LINESIZE];
int restrict = 0;
char env_path[LINESIZE];
char *envp[] = {
env_user, env_shell, env_home, env_path, NULLCP
};
char *usrpathname = USRPATH;
long message_size;
int firstSuccessDR, firstFailDR;
char *local_user;
/* --------------------- Begin Routines --------------------------------- */
main (argc, argv)
int argc;
char **argv;
{
char *p;
if (p = rindex(argv[0], '/'))
p++;
else p = argv[0];
/* -- 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);
PP_NOTICE (("Starting %s (%s)",
mychan -> ch_name, mychan -> ch_show));
if (lexequ (mychan -> ch_info, "restricted") == 0)
restrict = 1;
else
restrict = 0;
(void) signal (SIGCHLD, SIG_DFL);
if (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 *)&prm, sizeof prm);
bzero ((char *)qp, sizeof *qp);
firstFailDR = TRUE;
firstSuccessDR = TRUE;
if (this_msg)
free (this_msg);
this_msg = qb2str (arg -> qid);
PP_NOTICE (("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, ("rd_msg err: %s", this_msg));
return delivery_setallstate (int_Qmgr_status_messageFailure,
"Can't read message");
}
for (up = arg -> users; up; up = up -> next)
douser (up -> RecipientId -> parm, ad_recip, msgq);
rd_end();
prm_free (&prm);
q_free (qp);
return deliverystate;
}
/*
Change into pp queue space
*/
static void dirinit ()
{
PP_TRACE (("dirinit ()"));
if (chdir (quedfldir) < 0)
err_abrt (RP_LIO, "Uanble to change directory to '%s'",
quedfldir);
}
/*
* process one extension-id for this message
*/
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;
else {
deliver (ap, msgd);
return;
}
}
PP_LOG (LLOG_EXCEPTIONS,
("user not recipient of %s", this_msg));
delivery_setstate (rno, int_Qmgr_status_messageFailure,
"user is not a recipient");
}
static char *formatdir = NULLCP;
/*
Do the delivery
*/
static int deliver (ap, msgd)
ADDR *ap;
char *msgd;
{
char buffer[BUFSIZ],
filename[FILNSIZE];
int hdr_fd, body_fd,
retval;
LocUser *loc;
char *cp;
PP_TRACE (("deliver msgd=%s", msgd));
if (local_user)
free(local_user);
if ((local_user = ad_getlocal (ap -> ad_r822adr, AD_822_TYPE)) == NULLCP) {
(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 (local_user, mychan)) == NULL) {
(void) sprintf (buffer,
"User %s not registerd in channel table %s",
local_user, mychan -> ch_name);
PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer));
delivery_set (ap -> ad_no,
(firstFailDR == TRUE) ?
int_Qmgr_status_negativeDR :
int_Qmgr_status_failureSharedDR);
firstFailDR = FALSE;
set_1dr (&Qstruct, ap -> ad_no,
DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer);
wr_q2dr (&Qstruct, this_msg);
return RP_USER;
}
PP_TRACE (("Found entry for '%s' uid '%s' directory '%s' mailbox '%s'",
ap -> ad_r822adr,
loc -> username ? loc -> username : local_user,
loc -> directory, loc -> mailbox));
if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) {
PP_LOG (LLOG_EXCEPTIONS,
("Can't locate message %s", this_msg));
delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure,
"Can't find the message");
return RP_MECH;
}
if (rp_isbad (retval = msg_rinit (formatdir))) {
PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit can't init %s",
formatdir));
delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure,
"can't read the body");
return RP_MECH;
}
if (msg_rfile (filename) != RP_OK) {
PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise hdr"));
delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure,
"No message header");
msg_rend ();
return RP_MECH;
}
if (cp = rindex (filename, '/'))
cp ++;
else cp = filename;
if (lexnequ (cp, hdr_822_bp, strlen (hdr_822_bp)) != 0) {
PP_LOG (LLOG_EXCEPTIONS, ("Bad header type, %s", cp));
delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR);
set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER,
DRD_IMPLICITCONV_NOTREGISTERED,
"Header of message is not RFC-822 based");
wr_q2dr (&Qstruct, this_msg);
msg_rend ();
return RP_MECH;
}
if ((hdr_fd = open (filename, O_RDONLY, 0)) < 0) {
PP_SLOG (LLOG_EXCEPTIONS, filename,
("Can't open file"));
(void) sprintf (buffer, "Can't open file %s", filename);
delivery_setstate (ap -> ad_no,
int_Qmgr_status_messageFailure,
buffer);
return RP_MECH;
}
switch (msg_rfile (filename)) {
case RP_OK:
if ((body_fd = open (filename, O_RDONLY, 0)) < 0) {
PP_SLOG (LLOG_EXCEPTIONS, filename,
("Can't open file"));
(void) sprintf (buffer, "Can't open file %s",
filename);
delivery_setstate (ap -> ad_no,
int_Qmgr_status_messageFailure,
buffer);
(void) close (hdr_fd);
msg_rend ();
return RP_MECH;
}
break;
case RP_DONE:
PP_NOTICE (("Message with header part only"));
if ((body_fd = open ("/dev/null", O_RDONLY, 0)) < 0) {
PP_SLOG (LLOG_EXCEPTIONS, "/dev/null",
("Can't open file"));
delivery_set (ap -> ad_no,
int_Qmgr_status_messageFailure);
(void) close (hdr_fd);
msg_rend ();
return RP_MECH;
}
break;
default:
PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise body"));
delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure,
"Can't initialise body");
(void) close (hdr_fd);
msg_rend ();
return RP_MECH;
}
if (msg_rfile (filename) != RP_DONE) {
PP_LOG (LLOG_EXCEPTIONS, ("Extra body parts in message %s",
this_msg));
delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR);
set_1dr (&Qstruct, ap -> ad_no, DRR_UNABLE_TO_TRANSFER,
DRD_IMPLICITCONV_NOTREGISTERED,
"Extra body part that has not been converted to 822");
wr_q2dr (&Qstruct, this_msg);
(void) close (hdr_fd);
(void) close (body_fd);
msg_rend ();
return RP_USER;
}
msg_rend ();
/* set up the env */
(void) sprintf (env_home, "HOME=%s", loc -> home ? loc -> home :
(loc -> directory ? loc -> directory : "."));
(void) sprintf (env_shell, "SHELL=%s",
loc -> shell ? loc -> shell : "/bin/sh");
(void) sprintf (env_user, "USER=%s",
loc -> username ? loc -> username : local_user);
(void) sprintf (env_path, "PATH=%s", USRPATH);
message_size = Qstruct.msgsize;
retval = child_process (loc, hdr_fd, body_fd);
(void) close (hdr_fd);
(void) close (body_fd);
switch (retval) {
case int_Qmgr_status_negativeDR:
{
char buf[LINESIZE];
(void) sprintf (buf, "Delivery to %s (%d) failed",
loc -> username ?
loc -> username : local_user,
loc -> uid);
set_1dr (&Qstruct, ap -> ad_no, DRR_TRANSFER_FAILURE,
DRD_UA_UNAVAILABLE, buf);
wr_q2dr (&Qstruct, this_msg);
delivery_set (ap -> ad_no,
(firstFailDR == TRUE) ?
retval :
int_Qmgr_status_failureSharedDR);
firstFailDR = FALSE;
free_loc_user (loc);
return RP_MECH;
}
break;
case int_Qmgr_status_success:
break;
case int_Qmgr_status_mtaFailure:
case int_Qmgr_status_messageFailure:
case int_Qmgr_status_mtaAndMessageFailure:
delivery_set (ap -> ad_no, retval);
free_loc_user (loc);
return RP_MECH;
case NOTOK:
default:
PP_LOG (LLOG_EXCEPTIONS,
("child process failed"));
delivery_setstate (ap -> ad_no,
int_Qmgr_status_messageFailure,
"Child process failed");
free_loc_user (loc);
return RP_MECH;
}
if (loc -> username)
PP_NOTICE ((">>> local : Message delivered to %s (%s)",
local_user, loc -> username));
else
PP_NOTICE ((">>> local: Message delivered to %s (id %d/%d)",
local_user, loc -> uid, loc -> gid));
free_loc_user (loc);
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,
(firstSuccessDR == TRUE) ?
int_Qmgr_status_positiveDR :
int_Qmgr_status_successSharedDR);
}
else {
(void) wr_ad_status (ap, AD_STAT_DONE);
delivery_set (ap -> ad_no, int_Qmgr_status_success);
}
return RP_OK;
}