|
|
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 d
Length: 16763 (0x417b)
Types: TextFile
Names: »dirlist.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Chans/dirlist/dirlist.c«
/* dirlist.c: directory list channel */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/dirlist/RCS/dirlist.c,v 5.0 90/09/20 15:45:22 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Chans/dirlist/RCS/dirlist.c,v 5.0 90/09/20 15:45:22 pp Exp Locker: pp $
*
* $Log: dirlist.c,v $
* Revision 5.0 90/09/20 15:45:22 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 "dlist.h"
#include <isode/quipu/attrvalue.h>
#include <sys/file.h>
#include <varargs.h>
extern ADDR *adr_new();
extern char *rindex();
extern char *ad_getlocal();
extern char *quedfldir;
extern char *loc_dom_site;
extern OR_ptr or_std2or(),
or_default(),
or_std2or();
extern LLog *log_dsap;
static int expandList();
static char *get_adrstr();
static void dirinit();
static void set_success();
static int initialise(), endfunc ();
static int verifyAddr();
static ADDR *getnthrecip();
static int submit_error();
static int processMsg();
static struct type_Qmgr_DeliveryStatus *process();
static ADDR *construct_sender();
CHAN *mychan;
char *this_msg = NULL, *this_chan = NULL;
int start_submit;
int first_successDR, first_failureDR;
int adrno;
Attr_Sequence this_list = NULLATTR;
extern Attr_Sequence dir_getdl();
extern AttributeType at_Owner;
extern AttributeType at_Policy;
extern AttributeType at_Member;
extern ADDR *ORName2ADDR();
/* ----------------------- Begin Routines ------------------------------- */
main (argc, argv)
int argc;
char **argv;
{
#ifdef PP_DEBUG
char pp_debug = FALSE;
#endif
sys_init (argv[0]);
or_myinit();
dirinit();
quipu_syntaxes ();
pp_syntaxes();
#ifdef PP_DEBUG
if (argc>1 && (strcmp(argv[1], "debug") == 0))
pp_debug = TRUE;
#endif
dsap_init ((int *)NULL, (char ***)NULL);
(void) pp_quipu_run ();
#ifdef PP_DEBUG
if (pp_debug)
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/dirlist : Channel '%s' not known", name));
if (name != NULLCP)
free (name);
return NOTOK;
}
start_submit = TRUE;
/* --- 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/dirlist 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/dirlist 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/dirlist : 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/dirlist %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;
}
static int processMsg (msg, prm, que, recip,origsender)
char *msg;
struct prm_vars *prm;
Q_struct *que;
ADDR *recip;
ADDR *origsender;
{
Q_struct qs;
ADDR *expanded,
*ix,
*sender;
RP_Buf reply;
char *msgdir = NULLCP,
file[FILNSIZE],
buf[BUFSIZ],
*strippedname;
int dirlen,
n,
fd_in;
Attr_Sequence policy_as;
if (qid2dir (msg, recip, TRUE, &msgdir) != OK) {
PP_LOG (LLOG_EXCEPTIONS,
("Chans/dirlist 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);
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.content_return_request = FALSE; /* POLICY: do not return contents through a DL */
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;
}
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) {
PP_LOG(LLOG_EXCEPTIONS,
("list '%s' is an empty list", recip->ad_value));
return 0;
}
if (check_dl_permission (origsender,this_list) == NOTOK) {
delivery_set(recip->ad_no,
(first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR);
first_failureDR = FALSE;
(void) sprintf(buf, "Distribution list policy prevents expansion of '%s'",get_adrstr(recip));
set_1dr(que, recip->ad_no,
DRR_UNABLE_TO_TRANSFER,
DRD_DL_EXPANSION_FAILURE,
buf);
return 0;
}
if ((policy_as = as_find_type(this_list,at_Policy)) != NULLATTR) {
struct dl_policy * policy;
policy = (struct dl_policy *) policy_as->attr_value->avseq_av.av_struct;
if (! policy->dp_expand)
qs.dl_expansion_prohibited = TRUE;
switch (policy->dp_priority) {
case DP_LOW:
qs.priority = PRIO_NONURGENT; break;
case DP_HIGH:
qs.priority = PRIO_URGENT; break;
case DP_NORMAL:
qs.priority = PRIO_NORMAL; break;
case DP_ORIGINAL:
qs.priority = que->priority; break;
}
switch (policy->dp_convert) {
case DP_ORIGINAL:
qs.implicit_conversion = que->implicit_conversion ; break;
case DP_FALSE:
qs.implicit_conversion = FALSE; break;
case DP_TRUE:
qs.implicit_conversion = TRUE; break;
}
} else {
/* Assume default policy */
qs.dl_expansion_prohibited = TRUE;
qs.priority = PRIO_NONURGENT;
qs.implicit_conversion = que->implicit_conversion;
}
if ((sender = construct_sender(this_list)) == NULLADDR)
return submit_error(recip,"construct sender",&reply);
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 ADDR *construct_sender(as)
Attr_Sequence as;
{
ADDR *ret = NULLADDR;
ADDR *get_manager();
ADDR *get_postmaster();
if ((ret = get_manager(as)) == NULLADDR)
return (get_postmaster());
return ret;
}
/* --- \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));
if (adr->ad_dn)
return strdup (adr->ad_dn);
else
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(as)
Attr_Sequence as;
{
Attr_Sequence tmp;
ADDR *ret = NULLADDR;
ADDR *next;
AV_Sequence avs;
int num = 0;
/* Find mhsDLmembers */
if ((tmp = as_find_type(as,at_Member)) == NULLATTR)
return NULLADDR;
/* Convert to ADDR */
for (avs=tmp->attr_value; avs!= NULLAV; avs=avs->avseq_next) {
if ((next = ORName2ADDR ((ORName *)avs->avseq_av.av_struct,TRUE)) == NULLADDR)
return NULLADDR;
next->ad_extension = num;
next->ad_no = num;
num++;
adr_add(&ret, next);
}
return ret;
}
static ADDR *attemptExpansion(key, type)
char *key;
int type;
{
ADDR *ret;
char *local;
if (key == NULLCP)
return NULLADDR;
if ((local = ad_getlocal(key,type)) != NULLCP) {
if ((this_list = dir_getdl(local)) != NULLATTR) {
ret = dl2addr(this_list);
free(local);
return ret;
}
free(local);
}
if ((this_list = dir_getdl(key)) == NULLATTR)
return NULLADDR;
else {
ret = dl2addr(this_list);
return ret;
}
}
/* --- 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;
Attr_Sequence save_as;
*plist = NULLADDR;
if (expandedBefore (orig, *pdlh) == TRUE)
return TRUE;
if ((new = attemptExpansion (get_adrstr (orig),
orig->ad_type)) == NULLADDR)
/* cannot expand starting list */
return FALSE;
else
postExpansion (orig,pdlh);
adr_add (plist, new);
ix = new;
save_as = this_list;
while (ix != NULLADDR) {
if (expandedBefore(ix, *pdlh) == TRUE) {
temp = ix;
ix = ix -> ad_next;
adr_rm(temp, plist);
adr_free(temp);
} else if ((new = attemptExpansion(
get_adrstr(ix),
ix->ad_type))
!= NULLADDR) {
postExpansion(ix, pdlh);
temp = ix;
ix = ix -> ad_next;
adr_rm(temp, plist);
adr_free(temp);
adr_add(plist, new);
} else
ix = ix -> ad_next;
}
this_list = save_as;
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;
}
#ifndef lint
void advise (va_alist)
va_dcl
{
int code;
va_list ap;
va_start (ap);
code = va_arg (ap, int);
(void) _ll_log (log_dsap, code, ap);
va_end (ap);
}
#else
/* VARARGS */
void advise (code, what, fmt)
char *what,
*fmt;
int code;
{
advise (code, what, fmt);
}
#endif