|
|
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: 15468 (0x3c6c)
Types: TextFile
Names: »list.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Chans/list/list.c«
/* list.c: list processor channel */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/list/RCS/list.c,v 5.0 90/09/20 15:48:54 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Chans/list/RCS/list.c,v 5.0 90/09/20 15:48:54 pp Exp Locker: pp $
*
* $Log: list.c,v $
* Revision 5.0 90/09/20 15:48:54 pp
* rcsforce : 5.0 public release
*
*/
#include "util.h"
#include "head.h"
#include "qmgr.h"
#include "chan.h"
#include "q.h"
#include "dr.h"
#include "or.h"
#include "prm.h"
#include "dl.h"
#include "retcode.h"
#include <sys/file.h>
extern void rd_end(), sys_init(), err_abrt();
extern struct type_Qmgr_DeliveryStatus *delivery_resetDRs();
extern ADDR *adr_new();
extern char *rindex();
extern char *ad_getlocal();
extern char *quedfldir;
extern ADDR *tb_getModerator();
extern char *loc_dom_site;
extern char *postmaster;
extern char *hdr_822_bp, *ia5_bp;
extern OR_ptr or_std2or(),
or_default(),
or_std2or();
static int expandList();
static char *get_adrstr();
static void dirinit();
static void set_success();
static int initialise(), endfunc ();
static ADDR *getnthrecip();
static int submit_error();
static int processMsg();
static int expansionLoop;
static struct type_Qmgr_DeliveryStatus *process();
static Q_struct qs;
CHAN *mychan;
char *this_msg = NULL, *this_chan = NULL;
int start_submit;
int first_successDR, first_failureDR;
int adrno;
int expandSublists = FALSE;
/* ----------------------- Begin Routines ------------------------------- */
main (argc, argv)
int argc;
char **argv;
{
sys_init (argv[0]);
or_myinit();
dirinit();
#ifdef PP_DEBUG
if (argc>1 && (strcmp (argv[1], "debug") == 0))
debug_channel_control (argc,argv,initialise,process,endfunc);
else
#endif
channel_control (argc,argv,initialise,process,endfunc);
}
/* ----------------------- Static Routines ------------------------------- */
/* --- routine to move to correct place in file system --- */
static void dirinit()
{
if (chdir (quedfldir) < 0)
err_abrt (RP_LIO,
"Unable to change directory to '%s'", quedfldir);
}
/* ARGSUSED */
static int endfunc (arg)
struct type_Qmgr_Channel *arg;
{
if (start_submit == FALSE)
io_end (OK);
start_submit = TRUE;
}
/* --- \f
channel initialise routine --- */
static int initialise (arg)
struct type_Qmgr_Channel *arg;
{
char *name;
name = qb2str (arg);
if ((mychan = ch_nm2struct (name)) == NULLCHAN) {
PP_OPER (NULLCP, ("Chans/list : Channel '%s' not known", name));
if (name != NULLCP)
free (name);
return NOTOK;
}
start_submit = TRUE;
if (mychan -> ch_info != NULLCP
&& lexequ(mychan -> ch_info, "dosublists") == 0)
expandSublists = TRUE;
else
expandSublists = FALSE;
/* --- check if a list channel --- */
if (name != NULLCP)
free (name);
return OK;
}
/* --- \f
routine to check if allowed to list process this message --- */
static int security_check (msg)
struct type_Qmgr_ProcMsg *msg;
{
char *msg_file = NULLCP,
*msg_chan = NULLCP;
int result;
result = TRUE;
msg_file = qb2str (msg->qid);
msg_chan = qb2str (msg->channel);
if ((mychan == NULLCHAN) || (strcmp (msg_chan,mychan->ch_name) !=0)) {
PP_LOG (LLOG_EXCEPTIONS,
("Chans/list channel err: '%s'", msg_chan));
result = FALSE;
}
if (msg_file != NULLCP) free (msg_file);
if (msg_chan != NULLCP) free (msg_chan);
return result;
}
/* --- \f
routine called to do list processing --- */
static struct type_Qmgr_DeliveryStatus *process (arg)
struct type_Qmgr_ProcMsg *arg;
{
struct prm_vars prm;
Q_struct que;
ADDR *sender = NULL;
ADDR *recips = NULL;
int rcount,
retval;
struct type_Qmgr_UserList *ix;
ADDR *adr;
RP_Buf reply;
bzero ((char *)&prm, sizeof (prm));
bzero ((char *)&que, sizeof (que));
delivery_init (arg->users);
delivery_setall (int_Qmgr_status_messageFailure);
first_failureDR = first_successDR = TRUE;
if (security_check (arg) != TRUE)
return deliverystate;
if (this_msg != NULLCP) free (this_msg);
if (this_chan != NULLCP) free (this_chan);
this_msg = qb2str (arg->qid);
this_chan = qb2str (arg->channel);
PP_LOG (LLOG_NOTICE,
("processing msg '%s' through '%s'",this_msg, this_chan));
if (rp_isbad (rd_msg (this_msg,&prm,&que,&sender,&recips,&rcount))) {
PP_LOG (LLOG_EXCEPTIONS,
("Chans/list rd_msg err: '%s'",this_msg));
rd_end();
return delivery_setallstate(int_Qmgr_status_messageFailure,
"Can't read message");
}
for (ix = arg->users; ix; ix = ix->next) {
if ((adr = getnthrecip (&que, ix->RecipientId->parm)) == NULL) {
PP_LOG (LLOG_EXCEPTIONS,
("Chans/list : failed to find recipient %d of msg '%s'",
ix->RecipientId->parm, this_msg));
delivery_setstate (ix->RecipientId->parm,
int_Qmgr_status_messageFailure,
"Unable to find specified recipient");
continue;
}
if (start_submit == TRUE && rp_isbad (io_init (&reply))) {
submit_error (adr,"io_init",&reply);
rd_end();
return delivery_setallstate (int_Qmgr_status_messageFailure,
"Unable to start submit");
}
else
start_submit = FALSE;
switch (chan_acheck (adr, mychan, 1, (char **)NULL)) {
default:
case NOTOK:
break;
case OK:
processMsg (this_msg,&prm,&que,adr);
break;
}
}
if (rp_isbad (retval = wr_q2dr (&que, this_msg))) {
PP_LOG (LLOG_EXCEPTIONS,
("%s wr_q2dr failure '%d'",mychan->ch_name,retval));
(void) delivery_resetDRs (int_Qmgr_status_messageFailure);
}
rd_end();
return deliverystate;
}
/* --- \f
--- */
static int submit_error (recip, proc, reply)
ADDR *recip;
char *proc;
RP_Buf *reply;
{
char buf[BUFSIZ];
PP_LOG (LLOG_EXCEPTIONS,
("Chans/list %s failure [%s]", proc, reply->rp_line));
if (recip != NULLADDR) {
(void) sprintf (buf,
"'%s' failure [%s]",
proc,
reply -> rp_line);
delivery_setstate (recip->ad_no,
int_Qmgr_status_messageFailure,
buf);
}
start_submit = TRUE;
io_end (NOTOK);
return OK;
}
extern char *cont_822;
static int processMsg (msg, prm, que, recip)
char *msg;
struct prm_vars *prm;
Q_struct *que;
ADDR *recip;
{
ADDR *expanded,
*ix,
*sender;
RP_Buf reply;
char *msgdir = NULLCP,
file[FILNSIZE],
buf[BUFSIZ],
*strippedname,
*local;
int dirlen,
n,
fd_in;
if (qid2dir (msg, recip, TRUE, &msgdir) != OK) {
PP_LOG (LLOG_EXCEPTIONS,
("Chans/list msg dir not found for recip %d of msg '%s'",
recip->ad_no, msg));
delivery_setstate (recip->ad_no,
int_Qmgr_status_messageFailure,
"source directory not found");
return 0;
}
msg_rinit (msgdir);
/* --- expand list and resubmit message --- */
q_init (&qs);
qs.encodedinfo.eit_g3parms = 0;
qs.encodedinfo.eit_tTXparms = 0;
qs.encodedinfo.eit_presentation = 0;
if (recip -> ad_content != NULLCP)
qs.cont_type = strdup(recip -> ad_content);
else if (que -> cont_type != NULLCP)
qs.cont_type = strdup(que -> cont_type);
/* This is a hack */
if (qs.cont_type != NULLCP
&& lexequ(qs.cont_type, cont_822) == 0) {
free(qs.cont_type);
qs.cont_type = NULLCP;
}
if (recip -> ad_eit != NULLIST_BPT)
qs.encodedinfo.eit_types = list_bpt_dup (recip->ad_eit);
else
qs.encodedinfo.eit_types = list_bpt_dup (que->encodedinfo.eit_types);
/* qs.ua_id = strdup (que->ua_id); */
qs.dl_expansion_history = dlh_dup (que->dl_expansion_history);
qs.priority = PRIO_NONURGENT;
adrno = 1;
if (que->dl_expansion_prohibited == TRUE) {
delivery_set (recip -> ad_no,
(first_failureDR == TRUE) ?
int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR);
first_failureDR = FALSE;
(void) sprintf (buf, "DL expansion prohibited for this message");
set_1dr (que, recip -> ad_no,
DRR_UNABLE_TO_TRANSFER, DRD_DL_EXPANSION_PROHIBITED,
buf);
return 0;
}
expansionLoop = FALSE;
if (expandList (recip,&expanded,& (qs.dl_expansion_history)) == FALSE) {
delivery_set (recip->ad_no,
(first_failureDR == TRUE) ?
int_Qmgr_status_negativeDR :
int_Qmgr_status_failureSharedDR);
first_failureDR = FALSE;
(void) sprintf (buf, "Unable to expand list '%s'",get_adrstr (recip));
set_1dr (que, recip->ad_no,
DRR_UNABLE_TO_TRANSFER, DRD_DL_EXPANSION_FAILURE, buf);
return 0;
}
/* --- expands to nothing so done --- */
if (expanded == NULLADDR) {
if (expansionLoop == TRUE)
set_success(recip, que);
PP_LOG(LLOG_EXCEPTIONS,
("list '%s' is an empty list", recip->ad_value));
return 0;
}
if ((local = ad_getlocal (recip->ad_r822adr, AD_822_TYPE)) == NULLCP)
sender = tb_getModerator(recip->ad_r822adr);
else {
sender = tb_getModerator (local);
free (local);
}
if (sender == NULLADDR)
return 0;
qs.inbound = list_rchan_new (loc_dom_site,mychan->ch_name);
sender->ad_status = AD_STAT_DONE;
sender->ad_resp = NO;
prm->prm_opts = prm->prm_opts | PRM_ACCEPTALL | PRM_NOTRACE;
/* --- now resubmit --- */
if (rp_isbad (io_wprm (prm, &reply)))
return submit_error (recip,"io_wprm",&reply);
if (rp_isbad (io_wrq (&qs, &reply)))
return submit_error (recip,"io_wrq",&reply);
if (rp_isbad (io_wadr (sender, AD_ORIGINATOR, &reply)))
return submit_error (recip,"io_wadr",&reply);
ix = expanded;
while (ix != NULL) {
if (rp_isbad (io_wadr (ix, AD_RECIPIENT, &reply)))
return submit_error (recip,"io_wadr", &reply);
ix = ix->ad_next;
}
if (rp_isbad (io_adend (&reply)))
return submit_error (recip,"io_adend", &reply);
/* --- send over body --- */
if (rp_isbad (io_tinit (&reply)))
return submit_error (recip,"io_tinit",&reply);
dirlen = strlen (msgdir) +1;
while (msg_rfile (file) != RP_DONE) {
/* --- transmit file --- */
strippedname = file + dirlen;
if (rp_isbad (io_tpart (strippedname, FALSE, &reply)))
return submit_error (recip,"io_tpart",&reply);
if ((fd_in = open (file, O_RDONLY)) == -1) {
(void) strcpy (reply.rp_line,file);
return submit_error (recip,"open",&reply);
}
while ((n = read (fd_in, buf, BUFSIZ)) > 0) {
if (rp_isbad (io_tdata (buf, n))) {
(void) strcpy (reply.rp_line,"???");
return submit_error (recip,"io_tdata",&reply);
}
}
close (fd_in);
if (rp_isbad (io_tdend (&reply)))
return submit_error (recip,"io_tdend", &reply);
}
if (rp_isbad (io_tend (&reply)))
return submit_error (recip,"io_tend", &reply);
set_success (recip,que);
return 0;
}
static void set_success (recip, que)
ADDR *recip;
Q_struct *que;
{
if (recip->ad_usrreq == AD_USR_CONFIRM ||
recip->ad_mtarreq == AD_MTA_CONFIRM ||
recip->ad_mtarreq == AD_MTA_AUDIT_CONFIRM)
{
set_1dr (que, recip->ad_no, DRR_NO_REASON, -1, NULLCP);
delivery_set (recip->ad_no,
(first_successDR == TRUE) ?
int_Qmgr_status_positiveDR :
int_Qmgr_status_successSharedDR);
first_successDR = FALSE;
}
else {
(void) wr_ad_status (recip, AD_STAT_DONE);
delivery_set (recip->ad_no, int_Qmgr_status_success);
}
}
/* --- \f
--- */
static ADDR *getnthrecip (que, num)
Q_struct *que;
int num;
{
ADDR *ix = que->Raddress;
int icount = 1;
if (num == 0)
return que->Oaddress;
while ((ix != NULL) && (icount++ < num))
ix = ix->ad_next;
return ix;
}
/* --- \f
--- */
static char *getORname (adr)
ADDR *adr;
{
OR_ptr tree = NULLOR,
new = NULLOR;
char buf[BUFSIZ],
*value;
bzero (buf, BUFSIZ);
if (adr -> ad_r400adr != NULLCP)
return strdup(adr -> ad_r400adr);
value = adr -> ad_value;
if ((or_rfc2or (value, &tree) != OK) || tree == NULLOR) {
PP_LOG (LLOG_EXCEPTIONS,
("getORname: Failed to parse '%s'", value));
return NULLCP;
}
new = or_default (tree);
or_or2std (new, buf, 0);
if (new) or_free (new);
return strdup (buf);
}
static void postExpansion (adr, pdlh)
ADDR *adr;
DLHistory **pdlh;
{
char *orname;
if ((orname = getORname (adr)) == NULLCP)
return;
dlh_add (pdlh,dlh_new (orname, NULLCP, NULLUTC));
free (orname);
}
static int expandedBefore (adr, dlh)
ADDR *adr;
DLHistory *dlh;
{
char *orname;
int found = FALSE;
if ((orname = getORname (adr)) == NULLCP)
return FALSE;
while (found == FALSE && dlh != NULL) {
if (strcmp (orname, dlh->dlh_addr) == 0)
found = TRUE;
else
dlh = dlh -> dlh_next;
}
free (orname);
return found;
}
static ADDR *dl2addr (indl, pnum)
dl *indl;
int *pnum;
{
ADDR *ret = NULLADDR;
Name *list = indl -> dl_list;
int type = AD_ANY_TYPE;
for (*pnum=0; list != NULL; list = list -> next, (*pnum)++)
adr_add (&ret, adr_new (list->name, type, adrno++));
return ret;
}
static int attemptExpansion (key, type, padr, complain)
char *key;
int type;
ADDR **padr;
int complain;
{
dl *list;
char *local;
int count;
*padr = NULLADDR;
if ((local = ad_getlocal (key,type)) != NULLCP) {
PP_NOTICE(("Attempting to expand list '%s'", local));
if (tb_getdl (local, &list,complain) == OK) {
*padr = dl2addr (list, &count);
dl_free (list);
PP_NOTICE(("Expanded list '%s' to %d recipients",
local, count));
free (local);
return OK;
}
PP_NOTICE (("Failed to expand list '%s'", local));
free (local);
}
PP_NOTICE(("Attempting to expand list '%s'", key));
if (tb_getdl (key,&list,complain) != OK) {
PP_NOTICE (("Failed to expand list '%s'", key));
return NOTOK;
} else {
*padr = dl2addr (list, &count);
dl_free (list);
PP_NOTICE(("Expanded list '%s' to %d recipients",
key, count));
return OK;
}
}
/* --- rm this from the list --- */
static adr_rm (this, list)
ADDR *this,
**list;
{
ADDR *ix;
/* --- bullet proofing --- */
if (this == NULLADDR || list == NULL)
return;
if (this == *list)
/* --- first in list (easy) --- */
*list = (*list) -> ad_next;
else {
ix = *list;
while ( ix != NULLADDR
&& ix -> ad_next != this)
ix = ix -> ad_next;
if (ix != NULLADDR)
ix -> ad_next = this -> ad_next;
}
}
static int expandList (orig, plist, pdlh)
ADDR *orig,
**plist;
DLHistory **pdlh;
{
ADDR *new,
*temp,
*ix;
RP_Buf rp;
int do_next = TRUE;
*plist = NULLADDR;
if (expandedBefore (orig, *pdlh) == TRUE) {
expansionLoop = TRUE;
return TRUE;
}
if (attemptExpansion (orig -> ad_r822adr,
AD_822_TYPE,
&new,
OK) != OK)
/* --- cannot expand starting list --- */
return FALSE;
else
postExpansion (orig,pdlh);
adr_add (plist, new);
ix = new;
while (expandSublists == TRUE && ix != NULLADDR) {
if (!rp_isbad(ad_parse(ix, &rp, CH_USA_PREF))
&& ix->ad_outchan
&& ix->ad_outchan->li_chan
&& lexequ(ix->ad_outchan->li_chan->ch_name,
mychan->ch_name) == 0) {
/* attempt to expand sublist */
if (expandedBefore (ix, *pdlh) == TRUE) {
temp = ix;
ix = ix -> ad_next;
do_next = FALSE;
expansionLoop = TRUE;
adr_rm (temp, plist);
adr_free (temp);
}
else if (attemptExpansion (ix -> ad_r822adr,
AD_822_TYPE,
&new,
NOTOK) == OK) {
postExpansion (ix, pdlh);
temp = ix;
adr_rm (temp, plist);
adr_free (temp);
adr_add (plist, new);
ix = new;
do_next = FALSE;
}
}
if (do_next == TRUE)
ix = ix -> ad_next;
else
do_next = TRUE;
}
return TRUE;
}
static char *get_adrstr (adr)
ADDR *adr;
{
char *key;
switch (adr->ad_type) {
case AD_X400_TYPE:
key = adr->ad_r400adr;
break;
case AD_822_TYPE:
key = adr->ad_r822adr;
break;
default:
key = adr->ad_value;
break;
}
return key;
}