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

⟦6a9cb2f54⟧ TextFile

    Length: 6916 (0x1b04)
    Types: TextFile
    Names: »smtpd.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Chans/smtp/smtpd.c« 

TextFile

/* smtpd: daemon for smtp */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/smtp/RCS/smtpd.c,v 5.0 90/09/20 15:54:29 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Chans/smtp/RCS/smtpd.c,v 5.0 90/09/20 15:54:29 pp Exp Locker: pp $
 *
 * $Log:	smtpd.c,v $
 * Revision 5.0  90/09/20  15:54:29  pp
 * rcsforce : 5.0 public release
 * 
 */



/*
 * new version - detects if it is running under inetd.
 */


#include "util.h"
#include <signal.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <errno.h>

static char usage[] = "usage: smptd [-p port] [-i maxconn] \
program channel";

static int smtpport;
static int	maxconn = 5;
static struct sockaddr_in rmtaddr, laddr;
static int	numconnections = 0;
static char thishost[LINESIZE];
static char *Channel, Smtpserver[BUFSIZ];
static char *nstimeout;

static void envinit ();

#if sparc && defined(__GNUC__)	/* work around bug in gcc 1.37 sparc version */
#define inet_ntoa myinet_ntoa

static char *myinet_ntoa (in)
struct in_addr in;
{
	static char buf[80];

	(void) sprintf (buf, "%d.%d.%d.%d",
			(in.s_addr >> 24) & 0xff,
			(in.s_addr >> 16) & 0xff,
			(in.s_addr >> 8 ) & 0xff,
			(in.s_addr	) & 0xff);
	return buf;
}
#else
extern char	*inet_ntoa ();
#endif

extern int errno;

char	*myname;
int	debug;

main (argc, argv)
int	argc;
char	**argv;
{
	extern char	*optarg;
	extern int	optind;
	int	opt;
	struct servent *sp;
	int	alen, i, skt;

	myname = argv[0];
	sys_init (myname);

	if ((sp = getservbyname ("smtp", "tcp")) == NULL)
		smtpport = htons (25);
	else	smtpport = sp -> s_port;

	while((opt = getopt(argc, argv, "p:i:t:")) != EOF)
		switch (opt) {
		    case 'i':
			maxconn = atoi (optarg);
			break;
		    case 'p':
			smtpport = htons ((short)atoi (optarg));
			break;
		    case 't':
			nstimeout = optarg;
			break;
		    default:
			fprintf (stderr, "bad switch -%c: %s\n", opt, usage);
			PP_OPER (NULLCP, ("Bad argument -%c: %s", opt, usage));
			exit (1);
		}
	argc -= optind;
	argv += optind;

	initialise (argc, argv);

	alen = sizeof rmtaddr;
	if (getpeername (0, &rmtaddr, &alen) == 0) { /* under inetd */
		PP_TRACE (("Running under inetd..."));
		doit (0);
		_exit (0);
	}

	envinit ();

	laddr.sin_family = AF_INET;
	laddr.sin_addr.s_addr = INADDR_ANY;
	laddr.sin_port = smtpport;

	for (i = 0; i < 10; sleep (2 * ++i)) {
		if ((skt = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
			PP_SLOG (LLOG_EXCEPTIONS, "socket",
				 ("can't create "));
			continue;
		}

		if (bind (skt, &laddr, sizeof laddr) == -1) {
			PP_SLOG (LLOG_EXCEPTIONS, "bind",
				 ("socket can't "));
			(void) close (skt);
			continue;
		}

		if (listen (skt, 5) == -1) {
			PP_SLOG (LLOG_EXCEPTIONS, "listen",
				 ("socket can't "));
			(void) close (skt);
			continue;
		}
		break;
	}

	PP_NOTICE (("%s listening on port %d", myname, ntohs(smtpport)));
#define tcp_still_alive_and_kicking 1

	while (tcp_still_alive_and_kicking) {
		int	snew;
		int	pid;

		alen = sizeof (rmtaddr);
		if ((snew = accept (skt, &rmtaddr, &alen)) == NOTOK) {
			if (errno != EINTR)
				PP_SLOG (LLOG_EXCEPTIONS, "failed",
					 ("accept "));
			continue;
		}
		PP_TRACE (("Accepted new connection from %s",
			   inet_ntoa (rmtaddr.sin_addr)));
		if ((pid = tryfork ()) == NOTOK) {
			PP_SLOG (LLOG_EXCEPTIONS, "failed", ("fork "));
			sleep (10);
			continue;
		}
		if (pid == 0) {	/* child */
			doit (snew);
			_exit(0);
		}
		(void) close (snew);

		numconnections ++;

		while (numconnections >= maxconn) {
			PP_TRACE (("Too many connections -- waiting"));
			sigpause (0);
			PP_TRACE (("Finished waiting"));
		}
	}
}

reaper ()
{
	union wait status;

	while (wait3 (&status, WNOHANG, (caddr_t)0) > 0)
		numconnections --;
}

doit (fd)
int	fd;
{
	char *argv[10];
	int argc = 0;

	if (fd != 0) {
		(void) dup2 (fd, 0);
		(void) dup2 (fd, 1 );
		if (fd > 1 )
			(void) close (fd);
	}
	argv[argc++] = "smtpsrvr";
	if (nstimeout) {
		argv[argc++] = "-t";
		argv[argc++] = nstimeout;
	}
	argv[argc++] = Channel;
	argv[argc] = NULLCP;
	execv (Smtpserver, argv);
	PP_OPER (Smtpserver, ("server exec "));
	_exit (99);
}

static void  envinit () 
{
	int     i,
		nbits,
		sd;

	nbits = getdtablesize ();

	if (!(debug = isatty (2))) {
		for (i = 0; i < 5; i++) {
			switch (fork ()) {
			    case NOTOK: 
				sleep (5);
				continue;

			    case OK: 
				break;

			    default: 
				_exit (0);
			}
			break;
		}

		if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) {
			PP_OPER ("/dev/null", ("unable to read"));
			exit (3);
		}
		if (sd != 0)
			(void) dup2 (sd, 0), (void) close (sd);
		(void) dup2 (0, 1);
		(void) dup2 (0, 2);

#ifdef  TIOCNOTTY
		if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
			(void) ioctl (sd, TIOCNOTTY, NULLCP);
			(void) close (sd);
		}
#else
#ifdef  SYS5
		(void) setpgrp ();
		(void) signal (SIGINT, SIG_IGN);
		(void) signal (SIGQUIT, SIG_IGN);
#endif
#endif
	}
	else
		ll_dbinit (pp_log_norm, myname);

#ifdef notdef			/* damn YP... */
	for (sd = 3; sd < nbits; sd++)
		(void) close (sd);
#endif

	(void) signal (SIGPIPE, SIG_IGN);

	ll_hdinit (pp_log_norm, myname);

	(void) signal (SIGCHLD, reaper);

	PP_TRACE (("starting"));
}

initialise (argc, argv)
int	argc;
char	**argv;
{
	int	i;
	struct hostent *hp;
	extern char *chndfldir;

	if (argc > 0)
	{
		getfpath (chndfldir, argv[0], Smtpserver);

		if (access (Smtpserver, X_OK) < 0 ) { /* execute privs? */
			PP_OPER (Smtpserver, ("Cannot access server program"));
			fprintf (stderr, "Cannot access server program %s\n",
				 Smtpserver);
			exit (99);
		}
		PP_TRACE (("server is '%s'", Smtpserver ));
	} else {
		fprintf (stderr, "Smtpserver program not specified! (%s)\n",
			 usage);
		PP_OPER (NULLCP, ("Smtpserver program not specified! (%s)",
				  usage));
		exit (99);
	}

	if( argc > 1 ) {
		Channel = argv[1];
		PP_TRACE (("channel is '%s'", Channel));
	} else {
		PP_OPER (NULLCP, ("Channel not specified! (%s)", usage));
		fprintf (stderr, "Channel not specified! (%s)\n", usage);
		exit (99);
	}

        /*
         * must get full name for this host from nameserver (or file)
         */

	if (gethostname (thishost, sizeof thishost) == -1)
		PP_SLOG (LLOG_EXCEPTIONS, "gethostname",
			 ("Can't find out who I am"));

        for(i = 0 ; i < 10 ; i++){
                hp = gethostbyname(thishost);
                if(hp != NULL)
                        break;
                if(i > 2)
                        sleep(i*2);
        }
        if(hp == NULL) {
		PP_OPER (NULLCP, 
                  ("Cannot find 'official' name of host '%s'\n",
						thishost));
                fprintf(stderr,
		  "Cannot find 'official' name of host '%s'\n",
                                                   thishost);
                exit(-1);
        }
        (void) strcpy(thishost, hp->h_name);
}