|
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; }