1: # include <errno.h> 2: # include "sendmail.h" 3: 4: #ifndef DAEMON 5: SCCSID(@(#)bbn_daemon.c 3.36+ 12/13/82 (w/o daemon mode)); 6: #else 7: SCCSID(@(#)bbn_daemon.c 3.36+ 12/13/82 (w/ daemon mode)); 8: 9: /* 10: ** DAEMON.C -- routines to use when running as a daemon. 11: ** 12: ** BB&N Version. Hack attack!! This version is not supported, 13: ** and probably has some bugs...... 14: ** 15: ** Basic semantics are: 16: ** 17: ** getrequests() 18: ** Opens a port and initiates a connection. 19: ** Returns in a child. Must set InChannel and 20: ** OutChannel appropriately. 21: ** makeconnection(host, port, outfile, infile) 22: ** Make a connection to the named host on the given 23: ** port. Set *outfile and *infile to the files 24: ** appropriate for communication. Returns zero on 25: ** success, else an exit status describing the 26: ** error. 27: ** 28: ** The semantics of both of these should be clean. 29: */ 30: 31: #include "netlib.h" 32: #include "con.h" 33: #include <wait.h> 34: 35: #define SMTPSOCK 25 36: /* 37: ** GETREQUESTS -- open mail IPC port and get requests. 38: ** 39: ** Parameters: 40: ** none. 41: ** 42: ** Returns: 43: ** none. 44: ** 45: ** Side Effects: 46: ** Waits until some interesting activity occurs. When 47: ** it does, a child is created to process it, and the 48: ** parent waits for completion. Return from this 49: ** routine is always in the child. 50: */ 51: 52: getrequests() 53: { 54: int t; 55: int iretval; 56: union wait status; 57: struct con openparams; 58: 59: /* 60: ** Set up the address for the mailer. 61: */ 62: 63: bzero (&openparams, sizeof openparams); /* clear out the structure */ 64: 65: 66: openparams.c_mode = CONTCP; 67: openparams.c_lport = SMTPSOCK; 68: openparams.c_rbufs = 2; /* 2k receive buffer */ 69: 70: /* 71: ** Try to actually open the connection. 72: */ 73: 74: # ifdef DEBUG 75: if (tTd(15, 1)) 76: printf("getrequests\n"); 77: # endif DEBUG 78: 79: for (;;) 80: { 81: /* wait for a connection */ 82: register int pid; 83: 84: do 85: { 86: errno = 0; 87: t = open("/dev/net/net", &openparams); 88: } while (t < 0 && errno == EINTR); 89: if (t < 0) 90: { 91: syserr("getrequests: open"); 92: sleep(500); 93: continue; 94: } 95: 96: 97: /* set 'eol' mode in connection */ 98: 99: ioctl (t, NETSETE, 0); 100: 101: /* 102: ** Create a subprocess to process the mail. 103: */ 104: 105: # ifdef DEBUG 106: if (tTd(15, 2)) 107: printf("getrequests: forking (fd = %d)\n", t); 108: # endif DEBUG 109: 110: pid = fork(); 111: if (pid < 0) 112: { 113: syserr("daemon: cannot fork"); 114: sleep(10); 115: (void) close(t); 116: continue; 117: } 118: 119: if (pid == 0) 120: { 121: /* 122: ** CHILD -- return to caller. 123: ** Verify calling user id if possible here. 124: */ 125: 126: InChannel = fdopen(t, "r"); 127: OutChannel = fdopen(t, "w"); 128: # ifdef DEBUG 129: if (tTd(15, 2)) 130: printf("getreq: returning\n"); 131: # endif DEBUG 132: # ifdef LOG 133: if (LogLevel > 11) 134: syslog(LOG_DEBUG, "connected, pid=%d", getpid()); 135: # endif LOG 136: return; 137: } 138: 139: /* 140: ** PARENT -- wait for child to terminate. 141: ** Perhaps we should allow concurrent processing? 142: */ 143: 144: # ifdef DEBUG 145: if (tTd(15, 2)) 146: { 147: sleep(2); 148: printf("getreq: parent waiting\n"); 149: } 150: # endif DEBUG 151: 152: /* close the port so that others will hang (for a while) */ 153: if ((iretval = close(t)) < 0) 154: syserr("getreq: cannot close port 25: %d", iretval) ; 155: 156: 157: /* pick up old zombies; implement load limiting */ 158: while (wait3(&status, WNOHANG, 0) > 0) 159: continue; 160: } 161: } 162: /* 163: ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 164: ** 165: ** Parameters: 166: ** host -- the name of the host. 167: ** port -- the port number to connect to. 168: ** outfile -- a pointer to a place to put the outfile 169: ** descriptor. 170: ** infile -- ditto for infile. 171: ** 172: ** Returns: 173: ** An exit code telling whether the connection could be 174: ** made and if not why not. 175: ** 176: ** Side Effects: 177: ** none. 178: */ 179: 180: makeconnection(host, port, outfile, infile) 181: char *host; 182: u_short port; 183: FILE **outfile; 184: FILE **infile; 185: { 186: register int s; 187: struct con openparams; 188: 189: bzero (&openparams, sizeof openparams); /* clear structure's memory */ 190: 191: openparams.c_mode = CONACT | CONTCP; 192: openparams.c_timeo = 60; 193: 194: /* 195: ** Set up the address for the mailer. 196: ** Accept "[a.b.c.d]" syntax for host name. 197: */ 198: 199: if (host[0] == '[') 200: { 201: long hid = 0; 202: int i, j; 203: register char *p = host; 204: 205: for (i = 3; i >= 0 && *p != ']' && *p != '\0'; i--) 206: { 207: j = 0; 208: while (isdigit(*++p)) 209: j = j * 10 + (*p - '0'); 210: if (*p != (i == 0 ? ']' : '.') || j > 255 || j < 0) 211: break; 212: hid |= j << ((3 - i) * 8); 213: } 214: if (i >= 0 || *p != ']' || *++p != '\0') 215: { 216: usrerr("Invalid numeric domain spec \"%s\"", host); 217: return (EX_NOHOST); 218: } 219: openparams.c_fcon._na_l = hid; 220: } 221: else 222: { 223: 224: openparams.c_fcon = gethost(host); 225: if (isbadhost(openparams.c_fcon)) 226: return (EX_NOHOST); 227: } 228: 229: /* 230: ** Determine the port number. 231: */ 232: 233: if (port == 0) 234: openparams.c_fport = SMTPSOCK; 235: else 236: openparams.c_fport = port; 237: 238: /* 239: ** Try to actually open the connection. 240: */ 241: 242: # ifdef DEBUG 243: if (tTd(16, 1)) 244: printf("makeconnection(%s=%X)\n", host, openparams.c_fcon._na_l); 245: # endif DEBUG 246: 247: s = open("/dev/net/net", &openparams); 248: 249: # ifdef DEBUG 250: if (tTd(16, 1)) 251: printf("makeconnection: %d\n", s); 252: # endif DEBUG 253: 254: if (s < 0) 255: return (EX_TEMPFAIL); 256: 257: /* connection ok, put it into canonical form */ 258: *outfile = fdopen(s, "w"); 259: *infile = fdopen(s, "r"); 260: 261: return (0); 262: } 263: 264: # endif DAEMON 265: /* 266: ** MYHOSTNAME -- return the name of this host. 267: ** 268: ** This is a hideous hack.... It should be fixed to really work 269: ** under the BB&N code. However, since Brendan's configuration 270: ** tables don't use this feature it won't matter. 271: ** 272: ** Parameters: 273: ** hostbuf -- a place to return the name of this host. 274: ** size -- the size of hostbuf. 275: ** 276: ** Returns: 277: ** A list of aliases for this host. 278: ** NULL if it cannot be found. 279: ** 280: ** Side Effects: 281: ** none. 282: */ 283: 284: char ** 285: myhostname(hostbuf, size) 286: char hostbuf[]; 287: int size; 288: { 289: register FILE *f; 290: 291: hostbuf[0] = '\0'; 292: f = fopen("/usr/include/whoami", "r"); 293: if (f != NULL) 294: { 295: (void) fgets(hostbuf, size, f); 296: fixcrlf(hostbuf, TRUE); 297: (void) fclose(f); 298: } 299: return (NULL); 300: }