SCCSID(@
(#)4.1a_daemon.c 3.35+ 12/5/82 (w/o daemon mode));
SCCSID(@
(#)4.1a_daemon.c 3.35+ 12/5/82 (with daemon mode));
** DAEMON.C -- routines to use when running as a daemon.
** 4.1a BSD version -- this version is not well supported.
** This entire file is highly dependent on the 4.1a BSD
** interprocess communication primitives. No attempt has
** been made to make this file portable to Version 7,
** Version 6, MPX files, etc. If you should try such a
** thing yourself, I recommend chucking the entire file
** and starting from scratch. Basic semantics are:
** Opens a port and initiates a connection.
** Returns in a child. Must set InChannel and
** OutChannel appropriately.
** makeconnection(host, port, outfile, infile)
** Make a connection to the named host on the given
** port. Set *outfile and *infile to the files
** appropriate for communication. Returns zero on
** success, else an exit status describing the
** The semantics of both of these should be clean.
** GETREQUESTS -- open mail IPC port and get requests.
** Waits until some interesting activity occurs. When
** it does, a child is created to process it, and the
** parent waits for completion. Return from this
** routine is always in the child.
int MaxConnections
= 4; /* maximum simultaneous sendmails */
** Wait for a connection.
while ((port
= getconnection()) < 0)
syslog(LOG_SALERT
, "cannot get connection");
** Create a subprocess to process the mail.
printf("getrequests: forking (port = %d)\n", port
);
syserr("daemon: cannot fork");
** CHILD -- return to caller.
** Verify calling user id if possible here.
InChannel
= fdopen(port
, "r");
OutChannel
= fdopen(port
, "w");
printf("getreq: returning\n");
syslog(LOG_DEBUG
, "connected, pid=%d", getpid());
** PARENT -- wait for child to terminate.
** Perhaps we should allow concurrent processing?
printf("getreq: parent waiting\n");
/* close the port so that others will hang (for a while) */
/* pick up old zombies; implement load limiting */
while (wait3(&status
, numconnections
< MaxConnections
? WNOHANG
: 0, 0) > 0)
** GETCONNECTION -- make a connection with the outside world
** This routine is horribly contorted to try to get around a bunch
** of 4.1a IPC bugs. There appears to be nothing we can do to make
** it "right" -- the code to interrupt accepts just doesn't work
** right. However, this is an attempt to minimize the probablity
** The port for mail traffic.
** Waits for a connection.
#define IPPORT_PLAYPORT 3055 /* random number */
struct sockaddr_in SendmailAddress
= { AF_INET
, IPPORT_SMTP
};
struct sockaddr otherend
;
** Set up the address for the mailer.
SendmailAddress
.sin_addr
.s_addr
= 0;
SendmailAddress
.sin_port
= IPPORT_SMTP
;
SendmailAddress
.sin_port
= IPPORT_PLAYPORT
;
SendmailAddress
.sin_port
= htons(SendmailAddress
.sin_port
);
** Try to actually open the connection.
printf("getconnection\n");
/* get a socket for the SMTP connection */
s
= socket(AF_INET
, SOCK_STREAM
, 0, 0);
bind(s
, &SendmailAddress
, sizeof SendmailAddress
, 0);
/* do loop is to avoid 4.1b kernel bug (?) */
s
= socket(SOCK_STREAM
, 0, &SendmailAddress
, SO_ACCEPTCONN
);
} while (--i
> 0 && s
< 0);
/* probably another daemon already */
syserr("getconnection: can't create socket");
printf("getconnection: %d\n", s
);
/* wait for a connection */
lotherend
= sizeof otherend
;
t
= accept(s
, &otherend
, &lotherend
, 0);
if (accept(s
, &otherend
) >= 0)
} while (errno
== EINTR
);
syserr("getconnection: accept");
** MAKECONNECTION -- make a connection to an SMTP socket on another machine.
** host -- the name of the host.
** port -- the port number to connect to.
** outfile -- a pointer to a place to put the outfile
** infile -- ditto for infile.
** An exit code telling whether the connection could be
** made and if not why not.
makeconnection(host
, port
, outfile
, infile
)
** Set up the address for the mailer.
** Accept "[a.b.c.d]" syntax for host name.
for (i
= 3; i
>= 0 && *p
!= ']' && *p
!= '\0'; i
--)
if (*p
!= (i
== 0 ? ']' : '.') || j
> 255 || j
< 0)
hid
|= j
<< ((3 - i
) * 8);
if (i
>= 0 || *p
!= ']' || *++p
!= '\0')
usrerr("Invalid numeric domain spec \"%s\"", host
);
SendmailAddress
.sin_addr
.s_addr
= hid
;
else if ((SendmailAddress
.sin_addr
.s_addr
= rhost(&host
)) == -1)
SendmailAddress
.sin_port
= htons(port
);
** Try to actually open the connection.
printf("makeconnection (%s)\n", host
);
s
= socket(AF_INET
, SOCK_STREAM
, 0, 0);
s
= socket(SOCK_STREAM
, 0, (struct sockaddr_in
*) 0, 0);
syserr("makeconnection: no socket");
printf("makeconnection: %d\n", s
);
(void) fflush(CurEnv
->e_xfp
); /* for debugging */
bind(s
, &SendmailAddress
, sizeof SendmailAddress
, 0);
if (connect(s
, &SendmailAddress
, sizeof SendmailAddress
, 0) < 0)
if (connect(s
, &SendmailAddress
) < 0)
/* failure, decide if temporary or not */
/* there are others, I'm sure..... */
/* connection ok, put it into canonical form */
*outfile
= fdopen(s
, "w");
*infile
= fdopen(s
, "r");