|
|
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 s
Length: 8858 (0x229a)
Types: TextFile
Names: »submit.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Src/submit/submit.c«
/* submit.c: the mail enqueuer */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/submit.c,v 5.0 90/09/20 16:23:12 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/submit.c,v 5.0 90/09/20 16:23:12 pp Exp Locker: pp $
*
* $Log: submit.c,v $
* Revision 5.0 90/09/20 16:23:12 pp
* rcsforce : 5.0 public release
*
*/
#include "head.h"
#include "prm.h"
#include "q.h"
#include <varargs.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include <pwd.h>
#include <isode/cmd_srch.h>
/* -- externals -- */
extern char *msg_unique, /* unique part of msg queue name */
*mgt_inhost,
*qmgr_hostname,
*rcmd_srch(),
*quedfldir, /* dir w/mail queue directories */
auth2submit_msg[];
extern int mgt_adtype,
adr_count,
protocol_mode;
extern ADDR *ad_originator,
*ad_recip;
extern struct passwd *getpwuid();
extern long msg_size;
extern CHAN *ch_inbound;
extern CMD_TABLE qtbl_mt_type[];
/* -- globals -- */
char *username; /* login name of usr running me */
int effecid, /* id providing access priviliges */
privileged, /* am I a priveledged user ? */
userid, /* id of user running me */
accept_all,
notrace,
end_of_file; /* eof encountered on stdin */
Q_struct Qstruct;
/* -- static variables -- */
static struct prm_vars Prm;
static int qmgr_fd = NOTOK;
static int log_msgtype;
/* -- local routines -- */
void err_abrt();
void pro_reply();
static int priv_user();
static void _pro_reply();
static void dir_init();
static void done();
static void msg_init();
static void set_qadr();
static void user_init();
/* -------------------- Main Routine ---------------------------------- */
/* ARGSUSED */
main (argc, argv)
int argc;
char **argv;
{
int retval;
(void) umask (0);
sys_init (argv[0]);
user_init();
dir_init();
or_myinit();
fmt_init();
ap_use_percent();
(void) signal (SIGPIPE, done);
/* temp hack */ (void) signal(SIGSEGV, SIG_DFL);
(void) signal (SIGBUS, SIG_DFL);
while (!end_of_file) {
/*
Reset various parameters
*/
msg_init();
protocol_mode = 1;
/*
Read the parameter settings for a Message
*/
if (rp_isbad (retval = rd_prm_info (&Prm))) {
if (end_of_file) continue;
err_abrt (retval, "bad parameters");
}
else
pro_reply (RP_OK, "Got the parameters");
/*
Read the queue structure
*/
if (rp_isbad (retval = rd_q_info (&Qstruct)))
err_abrt (retval, "Bad queue read");
/*
Perform management functions on parameters
*/
if (rp_isbad (retval = cntrl_mgt (&Prm, &Qstruct)))
err_abrt (retval, "Bad parameter settings");
/*
Perform management functions on the queue
*/
if (rp_isbad (retval = q_mgt (&Qstruct)))
err_abrt (retval, "Bad queue parameter settings");
pro_reply (RP_OK, "Starting fine, sender please");
/*
Validate the sender
*/
validate_sender();
pro_reply (RP_AOK, "Continuing fine, addresses please");
/*
Validate the Recipients
*/
validate_recip();
/*
Authorisation - main routines
*/
auth_start();
/*
Sets the Qstruct's Originator and Recipient fields
*/
set_qadr();
time_mgt();
/*
Initialize to the queue directory for output
*/
winit_q();
/*
if (DMPDU)
parse DR from incoming channel
else if (body)
splat the body into a file
*/
log_msgtype = Qstruct.msgtype;
switch (Qstruct.msgtype) {
case MT_DMPDU:
pro_reply (RP_AOK, "Addresses ok, DR info please");
if (rp_isbad (retval = gen_io2dr())) {
if (end_of_file)
continue;
err_abrt (retval, "Bad DR struct");
}
Qstruct.msgtype = MT_UMPDU;
break;
case MT_PMPDU:
msg_size = Qstruct.msgsize;
break;
default:
pro_reply (RP_AOK, "Addresses ok, text please");
/*
For fast rejection of a message containing
invalid body parts or where message size is too
big, the auth_content() checks should go into
txt_input(). But for now ...
*/
txt_input (notrace == 0 &&
ch_inbound -> ch_access == CH_MTA);
break;
}
protocol_mode = 0; /* end of protocol phase */
/*
finish authorisation tests on message
size/body parts and perform channel binding
*/
if (rp_isbad (retval = auth_finish()))
if (!accept_all)
err_abrt (retval, "%s : %s",
"At least one recipient fails authorisation",
auth2submit_msg);
check_crits (&Qstruct);
check_conversions (&Qstruct);
/*
Generate the appropriate Delivery Notifications
*/
switch (Qstruct.msgtype) {
case MT_PMPDU:
gen_probedr();
break;
default:
gen_ndr();
break;
}
write_q (&Qstruct, &Prm);
move_q();
pro_reply (RP_MOK, "Submitted & queued (%s)", msg_unique);
/*
generate authorisation statistics logs
now that msg_unique is known
*/
auth_log();
/* Tell qmgr */
if (qmgr_fd == NOTOK)
qmgr_fd = qmgr_start (qmgr_hostname);
if (qmgr_fd != NOTOK)
(void) message_send (qmgr_fd, msg_unique, &Prm,
&Qstruct, ad_originator,
ad_recip, adr_count);
if (ch_inbound != NULL && ch_inbound->ch_access == CH_MTS)
PP_NOTICE (("<<< local %s %s %s %s %s",
rcmd_srch(log_msgtype, qtbl_mt_type),
msg_unique,
ch_inbound -> ch_name,
username,
mgt_inhost));
else
PP_NOTICE (("<<< remote %s %s %s %s",
rcmd_srch(log_msgtype, qtbl_mt_type),
msg_unique,
ch_inbound -> ch_name,
mgt_inhost == NULLCP ? "<unknown-host>" :
mgt_inhost));
}
if (qmgr_fd != NOTOK)
(void) qmgr_end (qmgr_fd);
PP_TRACE (("Submit normal end"));
exit (RP_OK);
}
/* -------------------- Static Routines ------------------------------- */
/*
Get information on the incomming channel calling submit
*/
static void user_init()
{
register struct passwd *pw;
PP_LOG (LLOG_DEBUG, ("submit/user_init()"));
privileged = FALSE;
userid = getuid();
effecid = geteuid();
if ((pw = getpwuid (userid)) == NULL)
err_abrt (RP_LIO,
"No login for UID %d, call Support.", userid);
endpwent();
username = strdup (pw->pw_name);
if (priv_user (userid, effecid) == TRUE)
privileged = TRUE;
if (pp_setuserid() == NOTOK)
err_abrt (RP_LIO, "Unable to set user id");
}
static int priv_user (id, eid)
int id, eid;
{
struct passwd *pwd;
extern char *pplogin;
if (id == 0 || eid == id)
return TRUE;
if ((pwd = getpwnam (pplogin)) == (struct passwd *)0)
return FALSE;
if (id == pwd -> pw_uid)
return TRUE;
return FALSE;
}
/*
chdir
*/
static void dir_init()
{
/*
cd into the queue directory
*/
if (chdir (quedfldir) < 0)
err_abrt (RP_LIO,
"Unable to change directory. '%s'", quedfldir);
}
/*
Initialise a msg
*/
static void msg_init()
{
msg_unique = NULLCP; /* for logging failed messages */
msg_mgt();
ad_init();
}
static void set_qadr()
{
extern ADDR *ad_recip,
*ad_originator;
PP_DBG (("submit/set_qadr()"));
Qstruct.Raddress = ad_recip;
Qstruct.Oaddress = ad_originator;
}
/* -------------------- Reply Routines -------------------------------- */
#ifdef lint
/*VARARGS2*/
void pro_reply (code, fmt)
int code;
char *fmt;
{
pro_reply (code, fmt);
}
#else
void pro_reply (va_alist)
va_dcl
{
va_list ap;
int code;
va_start(ap);
code = va_arg (ap, int);
_pro_reply (code, ap);
va_end (ap);
}
static void _pro_reply (code, ap)
int code;
va_list ap;
{
char buffer[BUFSIZ];
register char *errchar = NULLCP;
if (rp_isbad (code))
switch (code) {
case RP_HUH: /* not if it was a user error */
case RP_PARM:
case RP_USER:
case RP_PARSE:
case RP_BHST:
case RP_NAUTH:
break;
default:
errchar = " ";
break;
}
_asprintf (buffer, errchar, ap);
PP_LOG (rp_isbad (code) ? LLOG_EXCEPTIONS : LLOG_PDUS|LLOG_TRACE,
("submit/pro_reply(%s) '%s'", rp_valstr (code),
buffer));
(void) fputc (code, stdout);
(void) fputs (buffer, stdout);
(void) fputc ('\n', stdout);
(void) fflush (stdout);
}
#endif
/* --------------- (err_) GENERAL ERROR-HANDLING ----------------------- */
#ifdef lint
/*VARARGS2*/
void err_abrt (code, fmt)
int code;
char *fmt;
{
clear_q();
pro_reply (code, fmt);
}
#else
void err_abrt (va_alist) /* terminate the process */
va_dcl
{
va_list ap;
int code;
va_start (ap);
code = va_arg (ap, int);
PP_TRACE (("err_abrt (%d)", code));
_pro_reply (code, ap);
va_end (ap);
done (-1); /* pass the reply code to caller */
}
#endif
static void done (n)
int n;
{
PP_TRACE (("done (%d)", n));
clear_q();
exit (n);
}