|
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