DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦ee64407b2⟧ TextFile

    Length: 16763 (0x417b)
    Types: TextFile
    Names: »dirlist.c«

Derivation

└─⟦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« 

TextFile

/* 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