1: # include <errno.h>
   2: # include "sendmail.h"
   3: 
   4: #ifndef DAEMON
   5: SCCSID(@(#)daemon.c	4.4		8/28/83	(w/o daemon mode));
   6: #else
   7: 
   8: #include <sys/socket.h>
   9: #include <netinet/in.h>
  10: #include <netdb.h>
  11: #include <sys/wait.h>
  12: 
  13: SCCSID(@(#)daemon.c	4.4		8/28/83	(with daemon mode));
  14: 
  15: /*
  16: **  DAEMON.C -- routines to use when running as a daemon.
  17: **
  18: **	This entire file is highly dependent on the 4.2 BSD
  19: **	interprocess communication primitives.  No attempt has
  20: **	been made to make this file portable to Version 7,
  21: **	Version 6, MPX files, etc.  If you should try such a
  22: **	thing yourself, I recommend chucking the entire file
  23: **	and starting from scratch.  Basic semantics are:
  24: **
  25: **	getrequests()
  26: **		Opens a port and initiates a connection.
  27: **		Returns in a child.  Must set InChannel and
  28: **		OutChannel appropriately.
  29: **	clrdaemon()
  30: **		Close any open files associated with getting
  31: **		the connection; this is used when running the queue,
  32: **		etc., to avoid having extra file descriptors during
  33: **		the queue run and to avoid confusing the network
  34: **		code (if it cares).
  35: **	makeconnection(host, port, outfile, infile)
  36: **		Make a connection to the named host on the given
  37: **		port.  Set *outfile and *infile to the files
  38: **		appropriate for communication.  Returns zero on
  39: **		success, else an exit status describing the
  40: **		error.
  41: **
  42: **	The semantics of both of these should be clean.
  43: */
  44: /*
  45: **  GETREQUESTS -- open mail IPC port and get requests.
  46: **
  47: **	Parameters:
  48: **		none.
  49: **
  50: **	Returns:
  51: **		none.
  52: **
  53: **	Side Effects:
  54: **		Waits until some interesting activity occurs.  When
  55: **		it does, a child is created to process it, and the
  56: **		parent waits for completion.  Return from this
  57: **		routine is always in the child.  The file pointers
  58: **		"InChannel" and "OutChannel" should be set to point
  59: **		to the communication channel.
  60: */
  61: 
  62: struct sockaddr_in  SendmailAddress;/* internet address of sendmail */
  63: int DaemonSocket = -1;      /* fd describing socket */
  64: 
  65: getrequests()
  66: {
  67:     int t;
  68:     union wait status;
  69:     register struct servent *sp;
  70: 
  71:     /*
  72: 	**  Set up the address for the mailer.
  73: 	*/
  74: 
  75:     sp = getservbyname("smtp", "tcp");
  76:     if (sp == NULL)
  77:     {
  78:         syserr("server \"smtp\" unknown");
  79:         goto severe;
  80:     }
  81:     SendmailAddress.sin_family = AF_INET;
  82:     SendmailAddress.sin_addr.s_addr = INADDR_ANY;
  83:     SendmailAddress.sin_port = sp->s_port;
  84: 
  85:     /*
  86: 	**  Try to actually open the connection.
  87: 	*/
  88: 
  89: # ifdef DEBUG
  90:     if (tTd(15, 1))
  91:         printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
  92: # endif DEBUG
  93: 
  94:     /* get a socket for the SMTP connection */
  95:     DaemonSocket = socket(AF_INET, SOCK_STREAM, 0, 0);
  96:     if (DaemonSocket < 0)
  97:     {
  98:         /* probably another daemon already */
  99:         syserr("getrequests: can't create socket");
 100:       severe:
 101: # ifdef LOG
 102:         if (LogLevel > 0)
 103:             syslog(LOG_SALERT, "cannot get connection");
 104: # endif LOG
 105:         finis();
 106:     }
 107: 
 108: #ifdef DEBUG
 109:     /* turn on network debugging? */
 110:     if (tTd(15, 15))
 111:         (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 0, 0);
 112: #endif DEBUG
 113: 
 114:     if (bind(DaemonSocket, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
 115:     {
 116:         syserr("getrequests: cannot bind");
 117:         (void) close(DaemonSocket);
 118:         goto severe;
 119:     }
 120:     listen(DaemonSocket, 10);
 121: 
 122: # ifdef DEBUG
 123:     if (tTd(15, 1))
 124:         printf("getrequests: %d\n", DaemonSocket);
 125: # endif DEBUG
 126: 
 127:     for (;;)
 128:     {
 129:         register int pid;
 130:         auto int lotherend;
 131:         struct sockaddr_in otherend;
 132:         extern int RefuseLA;
 133: 
 134:         /* see if we are rejecting connections */
 135:         while (getla() > RefuseLA)
 136:             sleep(5);
 137: 
 138:         /* wait for a connection */
 139:         do
 140:         {
 141:             errno = 0;
 142:             lotherend = sizeof otherend;
 143:             t = accept(DaemonSocket, &otherend, &lotherend, 0);
 144:         } while (t < 0 && errno == EINTR);
 145:         if (t < 0)
 146:         {
 147:             syserr("getrequests: accept");
 148:             sleep(5);
 149:             continue;
 150:         }
 151: 
 152:         /*
 153: 		**  Create a subprocess to process the mail.
 154: 		*/
 155: 
 156: # ifdef DEBUG
 157:         if (tTd(15, 2))
 158:             printf("getrequests: forking (fd = %d)\n", t);
 159: # endif DEBUG
 160: 
 161:         pid = fork();
 162:         if (pid < 0)
 163:         {
 164:             syserr("daemon: cannot fork");
 165:             sleep(10);
 166:             (void) close(t);
 167:             continue;
 168:         }
 169: 
 170:         if (pid == 0)
 171:         {
 172:             extern struct hostent *gethostbyaddr();
 173:             register struct hostent *hp;
 174:             extern char *RealHostName;  /* srvrsmtp.c */
 175:             char buf[MAXNAME];
 176: 
 177:             /*
 178: 			**  CHILD -- return to caller.
 179: 			**	Collect verified idea of sending host.
 180: 			**	Verify calling user id if possible here.
 181: 			*/
 182: 
 183:             /* determine host name */
 184:             hp = gethostbyaddr(&otherend.sin_addr, sizeof otherend.sin_addr, AF_INET);
 185:             if (hp != NULL)
 186:                 (void) sprintf(buf, "%s.ARPA", hp->h_name);
 187:             else
 188:                 /* this should produce a dotted quad */
 189:                 (void) sprintf(buf, "%lx", otherend.sin_addr.s_addr);
 190:             RealHostName = newstr(buf);
 191: 
 192:             (void) close(DaemonSocket);
 193:             InChannel = fdopen(t, "r");
 194:             OutChannel = fdopen(t, "w");
 195: # ifdef DEBUG
 196:             if (tTd(15, 2))
 197:                 printf("getreq: returning\n");
 198: # endif DEBUG
 199: # ifdef LOG
 200:             if (LogLevel > 11)
 201:                 syslog(LOG_DEBUG, "connected, pid=%d", getpid());
 202: # endif LOG
 203:             return;
 204:         }
 205: 
 206:         /*
 207: 		**  PARENT -- wait for child to terminate.
 208: 		**	Perhaps we should allow concurrent processing?
 209: 		*/
 210: 
 211: # ifdef DEBUG
 212:         if (tTd(15, 2))
 213:         {
 214:             sleep(2);
 215:             printf("getreq: parent waiting\n");
 216:         }
 217: # endif DEBUG
 218: 
 219:         /* close the port so that others will hang (for a while) */
 220:         (void) close(t);
 221: 
 222:         /* pick up old zombies */
 223:         while (wait3(&status, WNOHANG, 0) > 0)
 224:             continue;
 225:     }
 226:     /*NOTREACHED*/
 227: }
 228: /*
 229: **  CLRDAEMON -- reset the daemon connection
 230: **
 231: **	Parameters:
 232: **		none.
 233: **
 234: **	Returns:
 235: **		none.
 236: **
 237: **	Side Effects:
 238: **		releases any resources used by the passive daemon.
 239: */
 240: 
 241: clrdaemon()
 242: {
 243:     if (DaemonSocket >= 0)
 244:         (void) close(DaemonSocket);
 245:     DaemonSocket = -1;
 246: }
 247: /*
 248: **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
 249: **
 250: **	Parameters:
 251: **		host -- the name of the host.
 252: **		port -- the port number to connect to.
 253: **		outfile -- a pointer to a place to put the outfile
 254: **			descriptor.
 255: **		infile -- ditto for infile.
 256: **
 257: **	Returns:
 258: **		An exit code telling whether the connection could be
 259: **			made and if not why not.
 260: **
 261: **	Side Effects:
 262: **		none.
 263: */
 264: 
 265: makeconnection(host, port, outfile, infile)
 266:     char *host;
 267:     u_short port;
 268:     FILE **outfile;
 269:     FILE **infile;
 270: {
 271:     register int s;
 272: 
 273:     /*
 274: 	**  Set up the address for the mailer.
 275: 	**	Accept "[a.b.c.d]" syntax for host name.
 276: 	*/
 277: 
 278:     if (host[0] == '[')
 279:     {
 280:         long hid;
 281:         register char *p = index(host, ']');
 282: 
 283:         if (p != NULL)
 284:         {
 285:             *p = '\0';
 286:             hid = inet_addr(&host[1]);
 287:             *p = ']';
 288:         }
 289:         if (p == NULL || hid == -1)
 290:         {
 291:             usrerr("Invalid numeric domain spec \"%s\"", host);
 292:             return (EX_NOHOST);
 293:         }
 294:         SendmailAddress.sin_addr.s_addr = hid;
 295:     }
 296:     else
 297:     {
 298:         register struct hostent *hp = gethostbyname(host);
 299: 
 300:         if (hp == NULL)
 301:             return (EX_NOHOST);
 302:         bmove(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
 303:     }
 304: 
 305:     /*
 306: 	**  Determine the port number.
 307: 	*/
 308: 
 309:     if (port != 0)
 310:         SendmailAddress.sin_port = htons(port);
 311:     else
 312:     {
 313:         register struct servent *sp = getservbyname("smtp", "tcp");
 314: 
 315:         if (sp == NULL)
 316:         {
 317:             syserr("makeconnection: server \"smtp\" unknown");
 318:             return (EX_OSFILE);
 319:         }
 320:         SendmailAddress.sin_port = sp->s_port;
 321:     }
 322: 
 323:     /*
 324: 	**  Try to actually open the connection.
 325: 	*/
 326: 
 327: # ifdef DEBUG
 328:     if (tTd(16, 1))
 329:         printf("makeconnection (%s)\n", host);
 330: # endif DEBUG
 331: 
 332:     s = socket(AF_INET, SOCK_STREAM, 0, 0);
 333:     if (s < 0)
 334:     {
 335:         syserr("makeconnection: no socket");
 336:         goto failure;
 337:     }
 338: 
 339: # ifdef DEBUG
 340:     if (tTd(16, 1))
 341:         printf("makeconnection: %d\n", s);
 342: 
 343:     /* turn on network debugging? */
 344:     if (tTd(16, 14))
 345:         (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0);
 346: # endif DEBUG
 347:     (void) fflush(CurEnv->e_xfp);           /* for debugging */
 348:     errno = 0;                  /* for debugging */
 349:     SendmailAddress.sin_family = AF_INET;
 350:     if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
 351:     {
 352:         /* failure, decide if temporary or not */
 353:     failure:
 354:         switch (errno)
 355:         {
 356:           case EISCONN:
 357:           case ETIMEDOUT:
 358:           case EINPROGRESS:
 359:           case EALREADY:
 360:           case EADDRINUSE:
 361:           case EHOSTDOWN:
 362:           case ENETDOWN:
 363:           case ENETRESET:
 364:           case ENOBUFS:
 365:           case ECONNREFUSED:
 366:           case ECONNRESET:
 367:           case EHOSTUNREACH:
 368:           case ENETUNREACH:
 369:             /* there are others, I'm sure..... */
 370:             return (EX_TEMPFAIL);
 371: 
 372:           case EPERM:
 373:             /* why is this happening? */
 374:             syserr("makeconnection: funny failure, addr=%lx, port=%x",
 375:                 SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
 376:             return (EX_TEMPFAIL);
 377: 
 378:           default:
 379:             return (EX_UNAVAILABLE);
 380:         }
 381:     }
 382: 
 383:     /* connection ok, put it into canonical form */
 384:     *outfile = fdopen(s, "w");
 385:     *infile = fdopen(s, "r");
 386: 
 387:     return (EX_OK);
 388: }
 389: /*
 390: **  MYHOSTNAME -- return the name of this host.
 391: **
 392: **	Parameters:
 393: **		hostbuf -- a place to return the name of this host.
 394: **		size -- the size of hostbuf.
 395: **
 396: **	Returns:
 397: **		A list of aliases for this host.
 398: **
 399: **	Side Effects:
 400: **		none.
 401: */
 402: 
 403: char **
 404: myhostname(hostbuf, size)
 405:     char hostbuf[];
 406:     int size;
 407: {
 408:     extern struct hostent *gethostbyname();
 409:     struct hostent *hp;
 410:     auto int i = size;
 411: 
 412:     gethostname(hostbuf, &i);
 413:     hp = gethostbyname(hostbuf);
 414:     if (hp != NULL)
 415:         return (hp->h_aliases);
 416:     else
 417:         return (NULL);
 418: }
 419: 
 420: # else DAEMON
 421: 
 422: /*
 423: **  MYHOSTNAME -- stub version for case of no daemon code.
 424: **
 425: **	Can't convert to upper case here because might be a UUCP name.
 426: **
 427: **	Mark, you can change this to be anything you want......
 428: */
 429: 
 430: char **
 431: myhostname(hostbuf, size)
 432:     char hostbuf[];
 433:     int size;
 434: {
 435:     register FILE *f;
 436: 
 437:     hostbuf[0] = '\0';
 438:     f = fopen("/usr/include/whoami", "r");
 439:     if (f != NULL)
 440:     {
 441:         (void) fgets(hostbuf, size, f);
 442:         fixcrlf(hostbuf, TRUE);
 443:         (void) fclose(f);
 444:     }
 445:     return (NULL);
 446: }
 447: 
 448: #endif DAEMON

Defined functions

clrdaemon defined in line 241; never used
getrequests defined in line 65; never used
makeconnection defined in line 265; never used
myhostname defined in line 430; never used

Defined variables

DaemonSocket defined in line 63; used 12 times
SendmailAddress defined in line 62; used 15 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1201
Valid CSS Valid XHTML 1.0 Strict