|
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: 6916 (0x1b04) Types: TextFile Names: »smtpd.c«
└─⟦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«
/* 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); }