|
|
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 t
Length: 41322 (0xa16a)
Types: TextFile
Names: »tables.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Src/qmgr/tables.c«
/* tables.c: table handling routines */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Src/qmgr/RCS/tables.c,v 5.0 90/09/20 16:21:49 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Src/qmgr/RCS/tables.c,v 5.0 90/09/20 16:21:49 pp Exp Locker: pp $
*
* $Log: tables.c,v $
* Revision 5.0 90/09/20 16:21:49 pp
* rcsforce : 5.0 public release
*
*/
#include "util.h"
#include "types.h"
#include "qmgr.h"
/* Variables */
MsgStruct *msg_hash[HASHSIZE];
Chanlist **chan_list;
int nchanlist = 0;
/* Procedures & functions */
extern char *strdup ();
int hash ();
void addtochan ();
void create_chan ();
Mtalist *findmtalist ();
MsgStruct *find_msg ();
Mlist *findmtamsg ();
Chanlist *delete_chan = NULLCHANLIST;
Chanlist *loader_chan = NULLCHANLIST;
Chanlist *trash_chan = NULLCHANLIST;
Chanlist *timeout_chan = NULLCHANLIST;
Chanlist *findchanlist ();
static void mcontrol ();
static int chaninsert ();
static int insertinmta ();
static int addmtaid ();
static int filtermatch ();
static int compmpduid ();
static int nullstrcmp ();
static int bind_result ();
static int bind_error ();
static void setchannels ();
void insertinchan ();
void insertindelchan ();
void insertindrchan ();
void zapmtamsg ();
/* External functions */
extern struct type_Qmgr_PrioritisedChannel *lpchan ();
extern struct type_Qmgr_ChannelInfo *lchani ();
extern struct type_Qmgr_PrioritisedMta *lpmta ();
extern struct type_Qmgr_MtaInfo *lmta ();
extern struct type_Qmgr_ProcStatus *lstatus ();
extern struct type_Qmgr_MsgStruct *lmessage ();
extern struct type_Qmgr_MsgStruct *l_cm_message ();
extern struct type_UNIV_UTCTime *ltime ();
extern MsgStruct *newmsgstruct ();
extern Filter *newfilter ();
#define STR2QB(s) str2qb ((s), strlen((s)), 1)
static int check_credentails (cb, name, passwd)
Connblk *cb;
char *name, *passwd;
{
extern char *crypt ();
char result[BUFSIZ];
static Table *auth= NULLTBL;
char *av[30], ac;
char *tbl_passwd = NULLCP;
char *tbl_rights = NULLCP;
char *tbl_name;
extern char *qmgr_auth_tbl;
cb -> cb_authenticated = 0;
if (auth == NULLTBL) {
if ((auth = tb_nm2struct(qmgr_auth_tbl)) == NULLTBL) {
PP_NOTICE (("Accepted Limited Access for %s",
name));
return int_Qmgr_result_acceptedLimitedAccess;
}
}
if (name == NULLCP)
tbl_name = "anon";
else tbl_name = name;
if (tb_k2val (auth, tbl_name, result) == NOTOK) {
if (name == NULLCP) {
PP_NOTICE (("Accepted Limited Access for %s",
tbl_name));
return int_Qmgr_result_acceptedLimitedAccess;
}
else {
PP_NOTICE (("Refused connection for %s", tbl_name));
return NOTOK;
}
}
ac = sstr2arg (result, 30, av, ", \t");
for (ac --; ac >= 0; ac --) {
char *cp;
if ((cp = index (av[ac], '=')) == NULLCP)
tbl_passwd = av[ac];
else {
*cp ++ = '\0';
if (lexequ (av[ac], "passwd") == 0)
tbl_passwd = cp;
else if (lexequ (av[ac], "rights") == 0)
tbl_rights = cp;
}
}
if (tbl_passwd) {
if (passwd == NULLCP) {
PP_LOG (LLOG_EXCEPTIONS,
("Password required, none given for %s",
tbl_name));
return NOTOK;
}
if (strcmp (tbl_passwd, crypt (passwd, tbl_passwd)) != 0) {
PP_LOG (LLOG_EXCEPTIONS,
("Password mismatch for %s", tbl_name));
return NOTOK;
}
}
/* now authenticated, if required */
if (tbl_rights == NULLCP) {
PP_NOTICE (("Limited Access granted for %s (no default rights)",
tbl_name));
cb -> cb_authenticated = 0;
return int_Qmgr_result_acceptedLimitedAccess;
}
if (lexequ (tbl_rights, "none") == 0) {
PP_NOTICE (("%s explicitly refused", tbl_name));
return NOTOK;
}
if (lexequ (tbl_rights, "limited") == 0) {
PP_NOTICE (("Limited access granted for %s", tbl_name));
return int_Qmgr_result_acceptedLimitedAccess;
}
if (lexequ (tbl_rights, "full") == 0) {
PP_NOTICE (("Full Access granted for %s", tbl_name));
cb -> cb_authenticated = 1;
return int_Qmgr_result_acceptedFullAccess;
}
PP_LOG (LLOG_EXCEPTIONS, ("Unknown rights '%s'", tbl_rights));
return NOTOK;
}
int start_routine (sd, acs, pep, npe)
int sd;
struct AcSAPstart *acs;
PE *pep;
int *npe;
{
struct type_Qmgr_BindArgument *ba;
Connblk *cb;
PP_TRACE (("start_routine (%d)", sd));
*pep = NULLPE;
cb = newcblk (cb_responder);
cb -> cb_fd = sd;
*npe = 0;
if (acs -> acs_ninfo == 0) {
cb -> cb_authenticated = 0;
return bind_result (pep, npe, cb,
int_Qmgr_result_acceptedLimitedAccess);
}
if (decode_Qmgr_BindArgument (acs -> acs_info[0], 1,
NULLVP, NULLIP, &ba) == NOTOK) {
PP_LOG (LLOG_EXCEPTIONS, ("failed to parse connect data [%s]",
PY_pepy));
cb -> cb_authenticated = 0;
return bind_result (pep, npe, cb,
int_Qmgr_result_acceptedLimitedAccess);
}
if (ba -> offset == type_Qmgr_BindArgument_noAuthentication) {
cb -> cb_authenticated = 0;
free_Qmgr_BindArgument (ba);
if (check_credentails (cb, NULLCP, NULLCP) == NOTOK)
return bind_error (pep, npe, cb,
int_Qmgr_reason_badCredentials);
return bind_result (pep, npe, cb,
int_Qmgr_result_acceptedLimitedAccess);
}
if (ba -> offset == type_Qmgr_BindArgument_weakAuthentication) {
char *username;
char *pass;
int result;
username = qb2str (ba -> un.weakAuthentication -> username);
if (ba -> un.weakAuthentication -> passwd)
pass = qb2str (ba -> un.weakAuthentication -> passwd);
else pass = NULLCP;
result = check_credentails (cb, username, pass);
free (username);
free (pass);
free_Qmgr_BindArgument (ba);
if (result == NOTOK)
return bind_error (pep, npe, cb,
int_Qmgr_reason_badCredentials);
else
return bind_result (pep, npe, cb, result);
}
free_Qmgr_BindArgument (ba);
return bind_error (pep, npe, cb, int_Qmgr_reason_congested);
}
static int bind_result (pep, npe, cb, type)
PE *pep;
int *npe;
Connblk *cb;
int type;
{
struct type_Qmgr_BindResult *br;
extern char *qmgr_hostname, *ppversion;
PP_TRACE (("bind_result"));
br = (struct type_Qmgr_BindResult *) smalloc (sizeof *br);
br -> result = type;
br -> information = STR2QB (qmgr_hostname);
br -> version = STR2QB (ppversion);
if (encode_Qmgr_BindResult (pep, 1, NULLCP, 0, br) == NOTOK) {
PP_LOG (LLOG_EXCEPTIONS, ("failed to encode BindResult [%s]",
PY_pepy));
free_Qmgr_BindResult (br);
return bind_error (pep, npe, cb,
int_Qmgr_reason_congested);
}
(*pep) -> pe_context = 3;
free_Qmgr_BindResult (br);
*npe = 1;
return ACS_ACCEPT;
}
static int bind_error (pep, npe, cb, type)
PE *pep;
int *npe;
Connblk *cb;
int type;
{
struct type_Qmgr_BindError *be;
PP_TRACE (("bind_error"));
be = (struct type_Qmgr_BindError *) smalloc (sizeof *be);
be -> reason = type;
be -> information = NULL;
cb -> cb_fd = NOTOK;
freecblk (cb);
if (encode_Qmgr_BindError (pep, 1, NULLCP, 0, be) == NOTOK) {
PP_LOG (LLOG_EXCEPTIONS,
("Failed to build BindError [%s]", PY_pepy));
*pep = NULLPE;
*npe = 0;
free_Qmgr_BindError (be);
return ACS_PERMANENT;
}
(*pep) -> pe_context = 3;
*npe = 1;
free_Qmgr_BindError (be);
return ACS_PERMANENT;
}
int add_msg (sd, msg, rox, roi)
int sd;
struct type_Qmgr_MsgStruct *msg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
MsgStruct *ms, *oldms;
int result;
PP_TRACE (("add_msg (%d, msg, rox, roi)", sd));
if (submission_disabled == 1) /* not submitting right now */
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if ((ms = newmsgstruct (msg)) == NULLMS)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (ms -> inchan && ms -> inchan -> ch_chan_type == CH_IN) {
Chanlist *clp;
if ((clp = findchanlist (ms -> inchan)) &&
clp -> lastsuccess < ms -> age)
clp -> lastsuccess = ms -> age;
}
if (oldms = find_msg (ms -> queid)) {
result = updatemessage (oldms, ms);
freems (ms);
}
else
result = insertmessage (ms);
if (result == OK)
return RyDsResult (sd, rox -> rox_id, (caddr_t) NULL,
ROS_NOPRIO, roi);
else
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
}
int updatemessage (old, new)
MsgStruct *old, *new;
{
PP_TRACE (("updatemessage ()"));
/* to be written !! */
PP_NOTICE (("update on message %s - ignored", new -> queid));
return OK;
}
int insertmessage (ms)
MsgStruct *ms;
{
MsgStruct **msp;
PP_TRACE (("insertmessage ()"));
for (msp = &msg_hash[hash(ms -> queid, HASHSIZE)]; *msp;
msp = &(*msp) -> ms_forw)
continue;
(*msp) = ms;
if (chaninsert (ms) == NOTOK) { /* back out change */
freems (ms);
(*msp) = NULLMS;
return NOTOK;
}
return OK;
}
/* ARGSUSED */
int read_msg (sd, rma, rox, roi)
int sd;
struct type_Qmgr_ReadMessageArgument *rma;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
MsgStruct **msp, *ms;
struct type_Qmgr_MsgStructList **mlp;
struct type_Qmgr_MsgList *base;
Filter *filter;
PP_TRACE (("read_msg (%d)", sd));
if ((base = (struct type_Qmgr_MsgList *) calloc (1, sizeof *base))
== NULL)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
mlp = &base -> msgs;
filter = newfilter (rma -> filters);
for (msp = msg_hash; msp < &msg_hash[HASHSIZE]; msp++) {
for (ms = *msp; ms; ms = ms -> ms_forw) {
if (filtermatch (filter, ms)) {
*mlp = (struct type_Qmgr_MsgStructList *)
calloc (1, sizeof (**mlp));
(*mlp) -> MsgStruct = lmessage (ms);
mlp = &(*mlp) -> next;
}
}
}
freefilter (filter);
if (RyDsResult (sd, rox -> rox_id, (caddr_t) base, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_MsgList (base);
return OK;
}
int channel_list (sd, arg, rox, roi)
int sd;
struct type_UNIV_UTCTime *arg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
struct type_Qmgr_ChannelReadResult *crr;
struct type_Qmgr_PrioritisedChannelList **list;
Chanlist **clp;
extern double load_avg[];
extern int maxchansrunning, nchansrunning;
PP_TRACE (("channel_list (%d)", sd));
crr = (struct type_Qmgr_ChannelReadResult *) smalloc (sizeof *crr);
list = &crr -> channels;
crr -> channels = NULL;
crr -> load1 = 100 * load_avg[0];
crr -> load2 = 100 * load_avg[1];
crr -> currchans = nchansrunning;
crr -> maxchans = maxchansrunning;
for (clp = chan_list; clp < &chan_list[nchanlist]; clp ++) {
*list = (struct type_Qmgr_PrioritisedChannelList *)
calloc (1, sizeof (**list));
if (*list == NULL ||
((*list) -> PrioritisedChannel = lpchan (*clp)) == NULL) {
free_Qmgr_ChannelReadResult (crr);
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
}
list = &((*list) -> next);
}
if (RyDsResult (sd, rox -> rox_id, (caddr_t) crr, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_ChannelReadResult (crr);
return OK;
}
int chan_control (sd, in, rox, roi)
int sd;
struct type_Qmgr_ChannelControl *in;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
Chanlist *clp;
struct type_Qmgr_PrioritisedChannelList *pcl;
struct type_Qmgr_PrioritisedChannel *pc;
Connblk *cb;
char *p;
PP_TRACE (("chan_control (%d)", sd));
if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (cb -> cb_authenticated == 0)
return error (sd, error_Qmgr_authenticationFailure,
(caddr_t) NULL, rox, roi);
p = qb2str (in -> channel);
clp = findchanlist (ch_nm2struct (p));
free (p);
if (clp == NULLCHANLIST)
return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL,
rox, roi);
switch (in -> control -> offset) {
case type_Qmgr_Control_stop:
clp -> chan_enabled = 0;
break;
case type_Qmgr_Control_start:
clp -> chan_enabled = 1;
break;
case type_Qmgr_Control_cacheClear:
cache_clear (&clp -> cache);
break;
case type_Qmgr_Control_cacheAdd:
cache_set (&clp -> cache, in -> control -> un.cacheAdd);
break;
default:
return error (sd, error_Qmgr_illegalOperation, (caddr_t) NULL,
rox, roi);
}
clp -> chan_update = 1;
pcl = (struct type_Qmgr_PrioritisedChannelList *) malloc (sizeof *pcl);
if ((pc = lpchan (clp)) == NULL)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
pcl -> PrioritisedChannel = pc;
pcl -> next = NULL;
if (RyDsResult (sd, rox -> rox_id, (caddr_t) pcl, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_PrioritisedChannelList (pcl);
return OK;
}
int chan_begin (sd, arg, rox, roi)
int sd;
struct type_Qmgr_FilterList *arg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
struct type_Qmgr_FilterList *out;
PP_TRACE (("chan_begin (%d)", sd));
out = (struct type_Qmgr_FilterList *) calloc (1, sizeof(*out));
if (out == NULL || (out -> Filter = (struct type_Qmgr_Filter *)
calloc (1, sizeof (struct type_Qmgr_Filter)))
== NULL)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (RyDsResult (sd, rox -> rox_id, (caddr_t) out, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_FilterList (out);
return OK;
}
int mta_control (sd, arg, rox, roi)
int sd;
struct type_Qmgr_MtaControl *arg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
Chanlist *clp = NULLCHANLIST;
Mtalist *mlp;
struct type_Qmgr_MtaInfo *mta;
CHAN *chan;
Connblk *cb;
char *p;
PP_TRACE (("mta_control (%d)", sd));
if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (cb -> cb_authenticated == 0)
return error (sd, error_Qmgr_authenticationFailure,
(caddr_t) NULL, rox, roi);
p = qb2str (arg -> channel);
if ((chan = ch_nm2struct (p)) != NULLCHAN)
clp = findchanlist (chan);
free (p);
if (clp == NULLCHANLIST)
return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL,
rox, roi);
p = qb2str (arg -> mta);
mlp = findmtalist (clp, p);
free(p);
if (mlp == NULLMTALIST)
return error (sd, error_Qmgr_mtaNotInQueue, (caddr_t) NULL,
rox, roi);
switch (arg -> control -> offset) {
case type_Qmgr_Control_stop:
mlp -> mta_enabled = 0;
break;
case type_Qmgr_Control_start:
mlp -> mta_enabled = 1;
break;
case type_Qmgr_Control_cacheClear:
cache_clear (&mlp -> cache);
break;
case type_Qmgr_Control_cacheAdd:
cache_set (&mlp -> cache, arg -> control -> un.cacheAdd);
break;
default:
return error (sd, error_Qmgr_illegalOperation, (caddr_t) NULL,
rox, roi);
}
mlp -> mta_changed = 1;
clp -> chan_update = 1;
if ((mta = lmta (mlp, clp)) == NULL)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (RyDsResult (sd, rox -> rox_id, (caddr_t) mta, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_MtaInfo (mta);
return OK;
}
int mta_read (sd, arg, rox, roi)
int sd;
struct type_Qmgr_MtaRead *arg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
Chanlist *clp;
struct type_Qmgr_PrioritisedMtaList **qmlpp, *qmlp;
char *p;
Mtalist *mlp;
PP_TRACE (("mta_read (%d)", sd));
qmlp = 0;
qmlpp = &qmlp;
p = qb2str (arg -> channel);
clp = findchanlist (ch_nm2struct (p));
free (p);
if (clp == NULLCHANLIST)
return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL,
rox, roi);
for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas;
mlp = mlp -> mta_forw) {
*qmlpp = (struct type_Qmgr_PrioritisedMtaList *)
calloc (1, sizeof(**qmlpp));
if (*qmlpp == NULL ||
((*qmlpp) -> PrioritisedMta = lpmta (mlp, clp)) == NULL) {
free_Qmgr_PrioritisedMtaList (qmlp);
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
}
qmlpp = &((*qmlpp) -> next);
}
if (RyDsResult (sd, rox -> rox_id, (caddr_t) qmlp, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_PrioritisedMtaList (qmlp);
return OK;
}
int msg_control (sd, arg, rox, roi)
int sd;
struct type_Qmgr_MsgControl *arg;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
char *q;
Reciplist *rl;
struct type_Qmgr_UserList *ul;
Connblk *cb;
MsgStruct *ms;
PP_TRACE (("msg_control (%d)", sd));
if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (cb -> cb_authenticated == 0)
return error (sd, error_Qmgr_authenticationFailure,
(caddr_t) NULL, rox, roi);
q = qb2str (arg -> qid);
if ((ms = find_msg (q)) == NULLMS)
return error (sd, error_Qmgr_noSuchChannel, (caddr_t)NULL,
rox, roi);
for (rl = ms -> recips; rl; rl = rl -> rp_next) {
for (ul = arg -> users; ul; ul = ul -> next) {
if (ul -> RecipientId -> parm == rl -> id)
mcontrol (ms, rl, arg -> control);
}
}
if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
return OK;
}
static void mcontrol (ms, rl, ctrl)
MsgStruct *ms;
Reciplist *rl;
struct type_Qmgr_Control *ctrl;
{
LIST_RCHAN *cl;
char *p;
Chanlist *clp = NULL;
Mlist *ml;
Mtalist *mlp;
int i;
PP_TRACE (("mcontrol (%s, %d)", ms -> queid, rl -> id));
switch (rl -> status) {
case st_normal:
for (cl = rl -> chans, i = rl -> chans_done; i > 0;
i--, cl = cl -> li_next)
continue;
if (cl == NULL)
return;
clp = findchanlist (cl -> li_chan);
p = chan2mta (cl -> li_chan, rl);
break;
case st_dr:
{
Reciplist *rlp2;
for (rlp2 = ms -> recips; rlp2; rlp2 = rlp2 -> rp_next)
if (rlp2 -> id == 0)
break;
if (rlp2 == NULL)
return;
clp = findchanlist(rlp2 -> chans->li_chan);
p = chan2mta (clp -> chan, rlp2);
break;
}
case st_delete:
clp = delete_chan;
p = delete_chan -> channame;
break;
case st_timeout:
clp = timeout_chan;
p = timeout_chan -> channame;
break;
default:
return;
}
if (clp == NULLCHANLIST)
return;
if ((mlp = findmtalist (clp, p)) == NULLMTALIST)
return;
for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs;
ml = ml -> ml_forw) {
if (ml -> ms == ms)
break;
}
if (ml == mlp -> msgs)
return;
switch (ctrl -> offset) {
case type_Qmgr_Control_stop:
rl -> msg_enabled = 0;
break;
case type_Qmgr_Control_start:
rl -> msg_enabled = 1;
break;
case type_Qmgr_Control_cacheClear:
cache_clear (&rl -> cache);
break;
case type_Qmgr_Control_cacheAdd:
cache_set (&rl -> cache, ctrl -> un.cacheAdd);
break;
}
mlp -> mta_changed = 1;
clp -> chan_update = 1;
}
int qmgrcontrol (sd, op, rox, roi)
int sd;
int op;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
Connblk *cb;
PP_TRACE (("qmgrcontrol (%d)", sd));
if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder)
return error (sd, error_Qmgr_congested, (caddr_t) NULL,
rox, roi);
if (cb -> cb_authenticated == 0)
return error (sd, error_Qmgr_authenticationFailure,
(caddr_t) NULL, rox, roi);
switch (op) {
case int_Qmgr_QMGROp_abort:
exit (0);
break;
case int_Qmgr_QMGROp_gracefulTerminate:
setchannels (1);
opmode = OP_SHUTDOWN;
break;
case int_Qmgr_QMGROp_restart:
setchannels (0);
opmode = OP_RESTART;
break;
case int_Qmgr_QMGROp_rereadQueue:
if (loader_chan) {
cache_clear (&loader_chan -> cache);
loader_chan -> chan_update = 1;
}
break;
case int_Qmgr_QMGROp_disableSubmission:
submission_disabled = 1;
break;
case int_Qmgr_QMGROp_enableSubmission:
submission_disabled = 0;
if (loader_chan) {
cache_clear (&loader_chan -> cache);
loader_chan -> chan_update = 1;
}
break;
case int_Qmgr_QMGROp_disableAll:
case int_Qmgr_QMGROp_enableAll:
setchannels (op == int_Qmgr_QMGROp_enableAll ? 1 : 0);
break;
case int_Qmgr_QMGROp_increasemaxchans:
maxchansrunning ++;
break;
case int_Qmgr_QMGROp_decreasemaxchans:
maxchansrunning --;
maxchansrunning = max (1, maxchansrunning);
break;
default:
PP_LOG (LLOG_EXCEPTIONS, ("Unknown operation %d", op));
break;
}
if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
return OK;
}
int msgread (sd, mr, rox, roi)
int sd;
struct type_Qmgr_MsgRead *mr;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
struct type_Qmgr_MsgStructList **qmlpp;
struct type_Qmgr_MsgList *base;
Mtalist *mlp;
Chanlist *clp;
Mlist *ml;
char *p;
PP_TRACE (("msgread (%d)", sd));
p = qb2str (mr -> channel);
clp = findchanlist (ch_nm2struct (p));
free (p);
if (clp == NULLCHANLIST)
return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL,
rox, roi);
p = qb2str (mr -> mta);
mlp = findmtalist (clp, p);
free (p);
if (mlp == NULLMTALIST)
return error (sd, error_Qmgr_mtaNotInQueue, (caddr_t) NULL,
rox, roi);
base = (struct type_Qmgr_MsgList *) calloc (1, sizeof *base);
qmlpp = &base -> msgs;
for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs;
ml = ml -> ml_forw) {
*qmlpp = (struct type_Qmgr_MsgStructList *)
calloc (1, sizeof **qmlpp);
(*qmlpp) -> MsgStruct = l_cm_message (ml);
qmlpp = &(*qmlpp) -> next;
}
if (RyDsResult (sd, rox -> rox_id, (caddr_t)base, ROS_NOPRIO, roi)
== NOTOK)
ros_adios (&roi -> roi_preject, "RESULT");
free_Qmgr_MsgList (base);
return OK;
}
/* private functions */
/* Channel functions */
static int chaninsert (ms)
MsgStruct *ms;
{
LIST_RCHAN *clp;
Reciplist *rlp;
int i;
int num = 0;
PP_TRACE (("chaninsert ()"));
for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) {
if ( rlp -> id == 0)
continue;
num ++;
rlp -> status = st_normal;
for (clp = rlp -> chans,
i = rlp -> chans_done; clp && i > 0;
clp = clp -> li_next, i--)
continue;
if (i == 0 && clp == NULL) {
insertindrchan (ms, rlp);
PP_NOTICE (("Message %s to %s added - DR",
ms -> queid, rlp -> user));
continue;
}
if (clp == NULL)
continue;
insertinchan (clp -> li_chan, ms, rlp,
chan2mta (clp -> li_chan, rlp));
PP_NOTICE (("Message %s to %s added",
ms -> queid, rlp -> user));
}
if (num == 0) {
ms -> recips -> chans_done ++;
insertindelchan (ms);
PP_NOTICE (("Message %s added - for deletion", ms -> queid));
}
return OK;
}
void insertinchan (chan, ms, ri, mta)
CHAN *chan;
MsgStruct *ms;
Reciplist *ri;
char *mta;
{
Mtalist *mlp;
Chanlist *clp;
PP_TRACE (("insertinchan (%s, %s, id=%d, mta=%s)", chan -> ch_name,
ms -> queid, ri -> id, mta));
clp = findchanlist (chan);
if (clp == NULLCHANLIST) {
advise (LLOG_EXCEPTIONS, NULLCP, "No channel for %s",
chan -> ch_name);
return;
}
if (ri -> realmta)
free (ri -> realmta);
ri -> realmta = strdup (mta);
if ((mlp = findmtalist(clp, mta)) == NULLMTALIST) {
mlp = (Mtalist *) calloc (1, sizeof *mlp);
mlp -> msgs = (Mlist *) calloc (1, sizeof *mlp -> msgs);
mlp -> msgs -> ml_back = mlp -> msgs -> ml_forw = mlp -> msgs;
insque (mlp, clp -> mtas -> mta_back);
mlp -> mtaname = strdup (mta);
mlp -> mta_enabled = 1;
}
if (insertinmta (mlp, ms, ri, clp) == OK ) {
if (ri -> status == st_dr)
clp -> num_drs ++;
else
clp -> num_msgs ++;
clp -> volume += ms -> size;
clp -> chan_update = 1;
}
}
void insertindelchan (ms)
MsgStruct *ms;
{
Reciplist *ri;
PP_TRACE (("insertindelchan ()"));
if (delete_chan == NULLCHANLIST) {
advise (LLOG_EXCEPTIONS, NULLCP, "No delete channel!");
return;
}
ri = ms -> recips;
ri -> status = st_delete;
insertinchan (delete_chan -> chan, ms, ri, delete_chan -> channame);
}
void insertindrchan (ms, rlp)
MsgStruct *ms;
Reciplist *rlp;
{
Reciplist *r;
PP_TRACE (("insertindrchan ()"));
rlp -> status = st_dr;
for (r = ms -> recips; r; r = r -> rp_next)
if (r -> id == 0)
break;
if (r == NULLRL)
return;
insertinchan (r -> chans -> li_chan, ms,
rlp, chan2mta (r -> chans -> li_chan, r));
}
Chanlist *findchanlist (chan)
CHAN *chan;
{
Chanlist **clpp;
if (chan == NULLCHAN)
return NULLCHANLIST;
for (clpp = chan_list; clpp < &chan_list[nchanlist]; clpp++)
if ((*clpp) -> chan == chan)
return *clpp;
return NULLCHANLIST;
}
static void setchannels (state)
int state;
{
Chanlist **cpp;
for (cpp = chan_list; cpp < &chan_list[nchanlist]; cpp++) {
(*cpp) -> chan_enabled = state;
(*cpp) -> chan_update = 1;
}
}
void create_chan (chan)
CHAN *chan;
{
Chanlist *clp;
extern int chan_state;
PP_TRACE (("create_chan (%s)", chan -> ch_name));
if (nchanlist == 0)
chan_list = (Chanlist **) malloc (sizeof (Chanlist *));
else
chan_list = (Chanlist **) realloc ((char *)chan_list,
(unsigned)(nchanlist + 1)
* sizeof (Chanlist *));
chan_list[nchanlist] = clp = (Chanlist *) calloc (1, sizeof (Chanlist));
clp -> channame = chan -> ch_name;
clp -> chan = chan;
clp -> mtas = (struct Mtalist *) calloc (1, sizeof (Mtalist));
clp -> mtas -> mta_back = clp -> mtas -> mta_forw = clp -> mtas;
clp -> chan_enabled = chan_state;
switch (chan -> ch_chan_type) {
case CH_DELETE:
delete_chan = clp;
break;
case CH_QMGR_LOAD:
clp -> chan_special = 1;
loader_chan = clp;
break;
case CH_DEBRIS:
clp -> chan_special = 1;
trash_chan = clp;
break;
case CH_TIMEOUT:
timeout_chan = clp;
break;
}
nchanlist ++;
}
static int chan_sort (clp1, clp2)
Chanlist **clp1, **clp2;
{
switch ((*clp1) -> chan -> ch_chan_type) {
case CH_WARNING:
case CH_DELETE:
case CH_QMGR_LOAD:
case CH_DEBRIS:
case CH_TIMEOUT:
case CH_SHAPER:
switch ((*clp2) -> chan -> ch_chan_type) {
case CH_BOTH:
case CH_OUT:
case CH_IN:
return -1;
default:
return 0;
}
break;
case CH_IN:
switch ((*clp2) -> chan -> ch_chan_type) {
case CH_IN:
return 0;
default:
return 1;
}
break;
case CH_BOTH:
case CH_OUT:
switch ((*clp2) -> chan -> ch_chan_type) {
case CH_IN:
return -1;
case CH_OUT:
case CH_BOTH:
return ((*clp1) -> averaget -
(*clp2) -> averaget) * 100.0;
default:
return 1;
}
break;
}
return 0;
}
void sort_chans ()
{
int i;
if (nchanlist)
qsort ((char *)chan_list, nchanlist,
sizeof (Chanlist *), chan_sort);
PP_TRACE (("Channels resorted"));
for (i = 0; i < nchanlist; i++)
PP_TRACE (("Channel %d - %s (%g)", i,
chan_list[i] -> channame,
chan_list[i] -> averaget));
}
void delfromchan (clp, mta, ml, rno)
Chanlist *clp;
char *mta;
Mlist *ml;
int rno;
{
Mtalist *mlp;
int i;
enum rstatus st = st_normal;
PP_TRACE (("delfromchan (chan=%s, id=%d)",
clp -> channame, rno));
mlp = findmtalist (clp, mta);
msg_unlock (ml -> ms);
for (i = 0; i < ml -> rcount; i++)
if (rno == ml -> recips[i] -> id)
break;
if (i < ml -> rcount) {
st = ml -> recips[i] -> status;
for (i++; i < ml -> rcount; i++)
ml -> recips[i-1] = ml -> recips[i];
}
ml -> rcount --;
if (ml -> rcount == 0)
zapmtamsg (ml, mlp, clp, st);
}
/* Host functions */
static int csort_prio (ml1, ml2)
Mlist *ml1, *ml2;
{
if (ml1 -> ms -> priority == ml2 -> ms -> priority)
return 0;
if (ml1 -> ms -> priority == int_Qmgr_Priority_high)
return 1;
if (ml2 -> ms -> priority == int_Qmgr_Priority_high)
return -1;
if (ml1 -> ms -> priority == int_Qmgr_Priority_normal)
return 1;
if (ml1 -> ms -> priority == int_Qmgr_Priority_normal)
return -1;
return 0;
}
static int csort_time (ml1, ml2)
Mlist *ml1, *ml2;
{
if (ml1 -> ms -> age < ml2 -> ms -> age)
return 1;
if (ml2 -> ms -> age < ml1 -> ms -> age)
return -1;
return 0;
}
static int csort_size (ml1, ml2)
Mlist *ml1, *ml2;
{
if (ml1 -> ms -> size < ml2 -> ms -> size)
return 1;
if (ml2 -> ms -> size > ml1 -> ms -> size)
return -1;
return 0;
}
static mtaenqueue (ml, mlp, clp)
Mlist *ml;
Mtalist *mlp;
Chanlist *clp;
{
int i, msort;
Mlist *m;
IFP sfnx[CH_MAX_SORT - 1];
if (clp -> chan -> ch_sort[1] == 0) {
insque (ml, mlp -> msgs -> ml_back);
return;
}
msort = 0;
for (i = 1; i < CH_MAX_SORT && clp -> chan -> ch_sort[i]; i++) {
switch (clp -> chan -> ch_sort[i]) {
case CH_SORT_USR:
case CH_SORT_MTA:
PP_LOG (LLOG_EXCEPTIONS, ("Bad sort criteria for %s",
clp -> channame));
insque (ml, mlp -> msgs -> ml_back);
return;
case CH_SORT_PRIORITY:
sfnx[msort++] = csort_prio;
continue;
case CH_SORT_TIME:
sfnx[msort++] = csort_time;
continue;
case CH_SORT_SIZE:
sfnx[msort++] = csort_size;
continue;
default:
break;
}
break;
}
for (m = mlp -> msgs -> ml_forw; m != mlp -> msgs; m = m -> ml_forw) {
int res;
for (i = 0; i < msort; i++) {
switch ((*sfnx[i])(m, ml)) {
case 0:
continue;
case -1:
insque (ml, m -> ml_back);
return;
case 1:
break;
}
break;
}
}
insque (ml, mlp -> msgs -> ml_back);
}
static int insertinmta (mlp, ms, rlp, clp)
Mtalist *mlp;
MsgStruct *ms;
Reciplist *rlp;
Chanlist *clp;
{
Mlist *ml;
int result;
PP_TRACE (("insertinmta (%s, id=%d)",
mlp -> mtaname, rlp -> id));
if (rlp -> status != st_dr) {
for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs;
ml = ml -> ml_forw) {
if (ml -> ms -> m_locked)
continue;
if (ml -> ms == ms) {
(void) addmtaid (ml, rlp);
return DONE;
}
}
}
ml = (Mlist *) calloc (1, sizeof *ml);
ml -> ms = ms;
ms -> count ++;
PP_TRACE (("Message reference count = %d", ms -> count));
mtaenqueue (ml, mlp, clp);
if ((result = addmtaid (ml, rlp)) == OK) {
if (rlp -> status == st_dr)
mlp -> num_drs ++;
else
mlp -> num_msgs ++;
mlp -> volume += ms -> size;
mlp -> mta_changed = 1;
}
return result;
}
static int addmtaid (ml, rlp)
Mlist *ml;
Reciplist *rlp;
{
Reciplist **ri;
PP_TRACE (("addmtaid (%d)", rlp -> id));
for (ri = ml -> recips; ri && ri < &ml->recips[ml->rcount];
ri ++)
if (*ri == rlp)
return DONE;
if (ml -> rcount == 0) {
ml -> recips = (Reciplist **) malloc (sizeof (ri));
ml -> recips[0] = rlp;
ml -> rcount = 1;
return OK;
}
ml -> rcount ++;
ml -> recips = (Reciplist **) realloc ((char *)ml -> recips,
(unsigned) ml -> rcount * sizeof (ri));
ml -> recips[ml -> rcount - 1] = rlp;
return DONE;
}
Mtalist *findmtalist (clp, mta)
Chanlist *clp;
char *mta;
{
Mtalist *mlp;
PP_TRACE (("findmtalist (%s)", mta));
for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas;
mlp = mlp -> mta_forw)
if (lexequ (mta, mlp -> mtaname) == 0)
return mlp;
return NULLMTALIST;
}
int zapmta (mlp)
Mtalist *mlp;
{
PP_TRACE (("zapmta (%s)", mlp -> mtaname));
if (mlp -> num_msgs != 0 || mlp -> num_drs != 0)
return NOTOK;
remque (mlp);
free ((char *) mlp -> msgs);
if (mlp -> info)
free (mlp -> info);
free ((char *) mlp);
return DONE;
}
void zapmtamsg (ml, mlp, clp, st)
Mlist *ml;
Mtalist *mlp;
Chanlist *clp;
enum rstatus st;
{
PP_TRACE (("zapmtamsg (mta=%s, chan=%s)",
mlp -> mtaname, clp -> channame));
if (st == st_dr)
clp -> num_drs --;
else
clp -> num_msgs --;
clp -> volume -= ml -> ms -> size;
clp -> chan_update = 1;
if (st == st_dr)
mlp -> num_drs --;
else
mlp -> num_msgs --;
mlp -> volume -= ml -> ms -> size;
mlp -> mta_changed = 1;
remque (ml);
ml -> ms -> count --;
PP_TRACE (("Message reference count = %d",
ml -> ms -> count));
if (ml -> info)
free (ml -> info);
free ((char *)ml -> recips);
free ((char *)ml);
if (mlp -> num_msgs == 0 && mlp -> num_drs == 0)
zapmta (mlp);
}
static Mlist *findnextml ();
/* Msg functions */
Mlist *nextmsg (clp, mtap, lock)
Chanlist *clp;
char **mtap;
int lock;
{
Mtalist *mlp;
char *mta = *mtap;
Mlist *ml;
PP_TRACE (("nextmsg (clp, mlp)"));
if (mta && (mlp = findmtalist (clp, mta))) {
if (mlp -> mta_enabled &&
mlp -> cache.cachetime <= current_time &&
(ml = findnextml (clp, mlp, current_time, lock)) != NULL)
return ml;
mlp -> nactive --;
}
if (mta) {
PP_TRACE (("nothing on current MTA list - trying others"));
free (mta);
*mtap = NULL;
}
for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas;
mlp = mlp -> mta_forw) {
if (! mtaready (mlp)) {
PP_TRACE (("mta %s not ready", mlp -> mtaname));
continue;
}
if (mlp -> cache.cachetime > current_time) {
PP_TRACE (("Mta %s cached for %d seconds",
mlp -> mtaname,
mlp -> cache.cachetime - current_time));
continue;
}
if ((ml = findnextml (clp, mlp, current_time, lock)) != NULL) {
if (lock)
mlp -> nactive ++;
*mtap = strdup (mlp -> mtaname);
PP_TRACE (("Found a ml"));
return ml;
}
PP_TRACE (("Mta %s no messages ready", mlp -> mtaname));
}
return (Mlist *)0;
}
static Mlist *findnextml (clp, mlp, now, lock)
Chanlist *clp;
Mtalist *mlp;
time_t now;
int lock;
{
Mlist *ml;
PP_TRACE (("findnextml (mta=%s)", mlp -> mtaname));
for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs;
ml = ml -> ml_forw) {
if (!msgready (ml)) {
PP_TRACE (("Message %s not ready", ml -> ms -> queid));
continue;
}
if (msgiscached (ml, now)) {
PP_TRACE (("Message %s cached", ml -> ms -> queid));
continue;
}
if (ml -> ms -> defferedtime &&
ml -> ms -> defferedtime > now) {
PP_TRACE (("Message defered"));
continue;
}
if (lock)
ml -> ms -> m_locked = 1;
return ml;
}
return (Mlist *)0;
}
void zapmsg (ms)
MsgStruct *ms;
{
MsgStruct **mspp;
PP_TRACE (("zapmsg (%s)", ms -> queid));
mspp = &msg_hash[hash(ms -> queid, HASHSIZE)];
for (; *mspp; mspp = &(*mspp) -> ms_forw)
if (*mspp == ms) {
*mspp = (*mspp) -> ms_forw;
freems (ms);
PP_TRACE (("Message zapped"));
return;
}
advise (LLOG_EXCEPTIONS, NULLCP, "Can't locate message");
}
Mlist *findmtamsg (mlp, qid)
Mtalist *mlp;
char *qid;
{
MsgStruct *ms;
Mlist *ml;
ms = find_msg (qid);
for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs;
ml = ml -> ml_forw)
if (ml -> ms == ms)
return ml;
return NULL;
}
MsgStruct *find_msg (qid)
char *qid;
{
MsgStruct *ms;
PP_TRACE (("find_msg (%s)", qid));
for (ms = msg_hash[hash (qid, HASHSIZE)]; ms; ms = ms -> ms_forw)
if ( strcmp (ms -> queid, qid) == 0)
return ms;
return NULLMS;
}
void maybezapmsg (ms)
MsgStruct *ms;
{
if (ms -> count == 0)
zapmsg (ms);
}
void kill_msg (ms)
MsgStruct *ms;
{
PP_TRACE (("kill_msg"));
}
static int filtermatch (f, ms)
Filter *f;
MsgStruct *ms;
{
PP_TRACE (("filtermatch ()"));
if (f == NULLFL)
return 0;
if (f -> cont) {
if (lexequ (f -> cont, ms -> contenttype) != 0)
return filtermatch (f -> next, ms);
}
if (f -> eit) {
LIST_BPT *bp, *bp2;
for (bp = ms -> eit; bp; bp = bp -> li_next) {
for (bp2 = f -> eit; bp2; bp2 = bp2 -> li_next) {
if (lexequ (bp -> li_name,
bp2 -> li_name) != 0)
return filtermatch (f -> next, ms);
}
}
}
if (f -> orig) {
if (lexequ (f -> orig, ms -> originator) != 0)
return filtermatch (f -> next, ms);
}
if (f -> recip) {
Reciplist *rl, *rl0;
for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next)
if (rl0 -> id == 0)
break;
for (rl = ms -> recips; rl; rl = rl -> rp_next) {
switch (rl -> status) {
case st_delete:
continue; /* we ignore recips that dead */
case st_timeout:
case st_normal:
if (rl -> id == 0)
continue;
if (lexequ (rl -> user, f -> recip) == 0)
break;
continue;
case st_dr:
if (rl0 &&
lexequ (rl0 -> user, f -> recip) == 0)
break;
continue;
}
break;
}
if (rl == NULLRL)
return filtermatch (f -> next, ms);
}
if (f -> channel) {
int cc;
Reciplist *rl, *rl0;
LIST_RCHAN *chans;
for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next)
if (rl0 -> id == 0)
break;
if (rl0 == NULLRL)
return filtermatch (f -> next, ms);
for (rl = ms -> recips; rl; rl = rl -> rp_next) {
if (rl -> status == st_dr) {
if (f -> channel == rl0 -> chans -> li_chan)
break;
else continue;
}
if (rl -> status == st_delete) {
if (f -> channel == delete_chan -> chan)
break;
else continue;
}
if (rl -> status == st_timeout) {
if (f -> channel == timeout_chan -> chan)
break;
else continue;
}
for (chans = rl -> chans, cc = rl -> chans_done;
chans; chans = chans -> li_next, cc--) {
if (cc == 0)
break;
}
if (chans && f -> channel == chans -> li_chan)
break;
}
if (rl == NULLRL)
return filtermatch (f -> next, ms);
}
if (f -> mta) {
Reciplist *rl;
for (rl = ms -> recips; rl; rl = rl -> rp_next) {
switch (rl -> status) {
case st_dr:
case st_normal:
if (lexequ (rl -> mta, f -> mta) == 0)
break;
if (rl -> realmta &&
lexequ (rl -> realmta, f -> mta) == 0)
break;
continue;
case st_delete:
if (delete_chan &&
lexequ (f -> mta,
delete_chan -> channame) == 0)
break;
continue;
case st_timeout:
if (timeout_chan &&
lexequ (f -> mta,
timeout_chan -> channame) == 0)
break;
continue;
default:
PP_TRACE (("Bad state %d", rl -> status));
continue;
}
break;
}
if (rl == NULLRL)
return filtermatch (f -> next, ms);
}
if (f -> queid) {
if (lexequ (f -> queid, ms -> queid) != 0)
return filtermatch (f -> next, ms);
}
if (f -> mpduid) {
if (!compmpduid (f -> mpduid, ms -> mpduid))
return filtermatch (f -> next, ms);
}
if (f -> uacontent) {
if (lexequ (f -> uacontent, ms -> uacontent) != 0)
return filtermatch (f -> next, ms);
}
if (f ->morerecent) {
if (ms -> age <= f -> morerecent)
return filtermatch (f -> next, ms);
}
if (f -> earlier) {
if (ms -> age >= f -> earlier)
return filtermatch (f -> next, ms);
}
if (f -> priority != -1) {
if (ms -> priority != f -> priority)
return filtermatch (f -> next, ms);
}
if (f -> maxsize) {
if (ms -> size > f -> maxsize)
return filtermatch (f -> next, ms);
}
return 1;
}
static int compmpduid (m1, m2)
MPDUid *m1, *m2;
{
PP_TRACE (("compmpduid ()"));
if (!nullstrcmp (m1 -> mpduid_string, m2 -> mpduid_string))
return 0;
if (!nullstrcmp (m1 -> mpduid_DomId.global_Country,
m2 -> mpduid_DomId.global_Country))
return 0;
if (!nullstrcmp (m1 -> mpduid_DomId.global_Admin,
m2 -> mpduid_DomId.global_Admin))
return 0;
if (!nullstrcmp (m1 -> mpduid_DomId.global_Private,
m2 -> mpduid_DomId.global_Private))
return 0;
return 1;
}
static int nullstrcmp (s1, s2)
char *s1, *s2;
{
if (s1 && s2)
return lexequ (s1, s2) == 0;
if (s1 == NULLCP && s2 == NULLCP)
return 1;
return 0;
}
int mtaready (mlp)
Mtalist *mlp;
{
if (mlp -> nactive > 0) {
PP_TRACE (("mta %s started already",
mlp -> mtaname));
return FALSE;
}
if (mlp -> mta_enabled == 0) {
PP_TRACE (("Mta %s not enabled",
mlp -> mtaname));
return FALSE;
}
return TRUE;
}
msgready (ml)
Mlist *ml;
{
Reciplist **rl;
if (ml -> ms -> m_locked) {
PP_TRACE (("Message locked"));
return FALSE;
}
for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) {
if ((*rl) -> msg_enabled == 0) {
PP_TRACE (("Message disabled"));
return FALSE;
}
}
return TRUE;
}
msgiscached (ml, now)
Mlist *ml;
time_t now;
{
Reciplist **rl;
for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) {
if ((*rl) -> cache.cachetime < now)
return FALSE;
}
return TRUE;
}
clear_msgcache (ml)
Mlist *ml;
{
Reciplist **rl;
for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) {
cache_clear (&(*rl) -> cache);
}
return TRUE;
}
msgcache_inc (ml, plus)
Mlist *ml;
time_t plus;
{
Reciplist **rl;
for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) {
cache_inc (&(*rl) -> cache, plus);
}
return TRUE;
}
time_t msgmincache (ml)
Mlist *ml;
{
time_t minc = 0;
int flag = 0;
Reciplist **rl;
for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) {
if (!flag) {
flag = 1;
minc = (*rl) -> cache.cachetime;
}
else
minc = minc < (*rl) -> cache.cachetime ? minc :
(*rl) -> cache.cachetime;
}
return minc;
}
msg_unlock (ms)
MsgStruct *ms;
{
Reciplist *rlp, *r, *rp;
LIST_RCHAN *cl;
Chanlist *clp;
Mtalist *mlp;
int i;
PP_TRACE (("msg_unlock"));
ms -> m_locked = 0;
for (rlp = r = ms -> recips; rlp; rlp = rlp -> rp_next) {
if ( rlp -> id == 0)
continue;
for (cl = rlp -> chans,
i = rlp -> chans_done; cl && i > 0;
cl = cl -> li_next, i--)
continue;
if (i == 0 && cl == NULL) {
cl = r -> chans;
rp = r;
}
else if (cl == NULL)
continue;
else
rp = rlp;
clp = findchanlist (cl -> li_chan);
clp -> chan_update = 1;
PP_TRACE (("setting update bit on %s", clp -> channame));
if ((mlp = findmtalist (clp, chan2mta (cl -> li_chan, rp)))
== NULLMTALIST)
continue;
PP_TRACE (("Setting update bit on MTA %s", mlp -> mtaname));
mlp -> mta_changed = 1;
}
}
char *chan2mta (chan, rlp)
CHAN *chan;
Reciplist *rlp;
{
if (chan -> ch_chan_type != CH_OUT &&
chan -> ch_chan_type != CH_BOTH)
return chan -> ch_name;
if (chan -> ch_sort[0] == CH_SORT_USR)
return rlp -> user;
else if (chan -> ch_mta)
return chan -> ch_mta;
else
return rlp -> mta;
}