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 s

⟦c9a7ffe10⟧ TextFile

    Length: 8858 (0x229a)
    Types: TextFile
    Names: »submit.c«

Derivation

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

TextFile

/* 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);
}