xref: /original-bsd/usr.sbin/sendmail/src/daemon.c (revision 9a96b58b)
1 # include <errno.h>
2 # include "sendmail.h"
3 
4 #ifndef DAEMON
5 SCCSID(@(#)daemon.c	3.11		05/06/82	(w/o daemon mode));
6 #else
7 
8 # include <sys/socket.h>
9 # include <net/in.h>
10 
11 SCCSID(@(#)daemon.c	3.11		05/06/82	(with daemon mode));
12 
13 /*
14 **  DAEMON.C -- routines to use when running as a daemon.
15 */
16 /*
17 **  GETREQUESTS -- open mail IPC port and get requests.
18 **
19 **	Parameters:
20 **		none.
21 **
22 **	Returns:
23 **		none.
24 **
25 **	Side Effects:
26 **		Waits until some interesting activity occurs.  When
27 **		it does, a child is created to process it, and the
28 **		parent waits for completion.  Return from this
29 **		routine is always in the child.
30 */
31 
32 getrequests()
33 {
34 	for (;;)
35 	{
36 		register int pid;
37 		auto int st;
38 		register int port;
39 
40 		/*
41 		**  Wait for a connection.
42 		*/
43 
44 		while ((port = getconnection()) < 0)
45 		{
46 			syserr("getrequests: getconnection failed");
47 			sleep(30);
48 		}
49 
50 		/*
51 		**  Create a subprocess to process the mail.
52 		*/
53 
54 # ifdef DEBUG
55 		if (Debug > 1)
56 			printf("getrequests: forking (port = %d)\n", port);
57 # endif DEBUG
58 
59 		pid = fork();
60 		if (pid < 0)
61 		{
62 			syserr("daemon: cannot fork");
63 			sleep(10);
64 			close(port);
65 			continue;
66 		}
67 
68 		if (pid == 0)
69 		{
70 			/*
71 			**  CHILD -- return to caller.
72 			**	Verify calling user id if possible here.
73 			*/
74 
75 			InChannel = fdopen(port, "r");
76 			OutChannel = fdopen(port, "w");
77 			initsys();
78 # ifdef DEBUG
79 			if (Debug > 1)
80 				printf("getreq: returning\n");
81 # endif DEBUG
82 			return;
83 		}
84 
85 		/*
86 		**  PARENT -- wait for child to terminate.
87 		**	Perhaps we should allow concurrent processing?
88 		*/
89 
90 # ifdef DEBUG
91 		if (Debug > 1)
92 		{
93 			sleep(2);
94 			printf("getreq: parent waiting\n");
95 		}
96 # endif DEBUG
97 
98 		(void) wait(&st);
99 		close(port);
100 	}
101 }
102 /*
103 **  GETCONNECTION -- make a connection with the outside world
104 **
105 **	Parameters:
106 **		none.
107 **
108 **	Returns:
109 **		The port for mail traffic.
110 **
111 **	Side Effects:
112 **		Waits for a connection.
113 */
114 
115 struct sockaddr_in SendmailAddress = { AF_INET, IPPORT_SMTP };
116 
117 getconnection()
118 {
119 	register int s;
120 	struct sockaddr otherend;
121 
122 	/*
123 	**  Set up the address for the mailer.
124 	*/
125 
126 	SendmailAddress.sin_addr.s_addr = 0;
127 	SendmailAddress.sin_port = IPPORT_SMTP;
128 
129 	/*
130 	**  Try to actually open the connection.
131 	*/
132 
133 # ifdef DEBUG
134 	if (Debug)
135 		printf("getconnection\n");
136 # endif DEBUG
137 
138 	s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN);
139 
140 # ifdef DEBUG
141 	if (Debug)
142 		printf("getconnection: %d\n", s);
143 # endif DEBUG
144 	accept(s, &otherend);
145 
146 	return (s);
147 }
148 /*
149 **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
150 **
151 **	Parameters:
152 **		host -- the name of the host.
153 **		port -- the port number to connect to.
154 **		outfile -- a pointer to a place to put the outfile
155 **			descriptor.
156 **		infile -- ditto for infile.
157 **
158 **	Returns:
159 **		An exit code telling whether the connection could be
160 **			made and if not why not.
161 **
162 **	Side Effects:
163 **		none.
164 */
165 
166 makeconnection(host, port, outfile, infile)
167 	char *host;
168 	int port;
169 	FILE **outfile;
170 	FILE **infile;
171 {
172 	register int s;
173 
174 	/*
175 	**  Set up the address for the mailer.
176 	*/
177 
178 	if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1)
179 		return (EX_NOHOST);
180 	if (port == 0)
181 		port = IPPORT_SMTP;
182 	SendmailAddress.sin_port = port;
183 
184 	/*
185 	**  Try to actually open the connection.
186 	*/
187 
188 # ifdef DEBUG
189 	if (Debug)
190 		printf("makeconnection (%s)\n", host);
191 # endif DEBUG
192 
193 	s = socket(SOCK_STREAM, 0, 0, 0);
194 	if (s < 0)
195 	{
196 		syserr("makeconnection: no socket");
197 		goto failure;
198 	}
199 
200 # ifdef DEBUG
201 	if (Debug)
202 		printf("makeconnection: %d\n", s);
203 # endif DEBUG
204 	if (connect(s, &SendmailAddress) < 0)
205 	{
206 		/* failure, decide if temporary or not */
207 	failure:
208 		switch (errno)
209 		{
210 		  case EISCONN:
211 		  case ETIMEDOUT:
212 			/* there are others, I'm sure..... */
213 			return (EX_TEMPFAIL);
214 
215 		  default:
216 			return (EX_UNAVAILABLE);
217 		}
218 	}
219 
220 	/* connection ok, put it into canonical form */
221 	*outfile = fdopen(s, "w");
222 	*infile = fdopen(s, "r");
223 
224 	return (0);
225 }
226 
227 #endif DAEMON
228