Add $[ and $] as RHS operators to look up the contents and pass them
[unix-history] / usr / src / usr.sbin / sendmail / src / daemon.c
CommitLineData
1ab402f2 1# include <errno.h>
ef34cbda 2# include "sendmail.h"
6b6d57eb 3# include <sys/mx.h>
ef34cbda 4
14a39063 5#ifndef DAEMON
217a0102 6SCCSID(@(#)daemon.c 4.11 %G% (w/o daemon mode));
14a39063
EA
7#else
8
7f108496
EA
9#include <sys/socket.h>
10#include <netinet/in.h>
11#include <netdb.h>
c4f1844c 12#include <sys/wait.h>
14a39063 13
217a0102 14SCCSID(@(#)daemon.c 4.11 %G% (with daemon mode));
ef34cbda
EA
15
16/*
17** DAEMON.C -- routines to use when running as a daemon.
2a16bae3
EA
18**
19** This entire file is highly dependent on the 4.2 BSD
20** interprocess communication primitives. No attempt has
21** been made to make this file portable to Version 7,
22** Version 6, MPX files, etc. If you should try such a
23** thing yourself, I recommend chucking the entire file
24** and starting from scratch. Basic semantics are:
25**
26** getrequests()
27** Opens a port and initiates a connection.
28** Returns in a child. Must set InChannel and
29** OutChannel appropriately.
eb8af3ce
EA
30** clrdaemon()
31** Close any open files associated with getting
32** the connection; this is used when running the queue,
33** etc., to avoid having extra file descriptors during
34** the queue run and to avoid confusing the network
35** code (if it cares).
2a16bae3
EA
36** makeconnection(host, port, outfile, infile)
37** Make a connection to the named host on the given
38** port. Set *outfile and *infile to the files
39** appropriate for communication. Returns zero on
40** success, else an exit status describing the
41** error.
42**
43** The semantics of both of these should be clean.
ef34cbda 44*/
6b6d57eb
EA
45
46static FILE *MailPort; /* port that mail comes in on */
ef34cbda
EA
47\f/*
48** GETREQUESTS -- open mail IPC port and get requests.
49**
50** Parameters:
51** none.
52**
53** Returns:
54** none.
55**
56** Side Effects:
57** Waits until some interesting activity occurs. When
58** it does, a child is created to process it, and the
59** parent waits for completion. Return from this
40d27fed
EA
60** routine is always in the child. The file pointers
61** "InChannel" and "OutChannel" should be set to point
62** to the communication channel.
ef34cbda
EA
63*/
64
eb8af3ce 65struct sockaddr_in SendmailAddress;/* internet address of sendmail */
c72f7eca
EA
66
67int DaemonSocket = -1; /* fd describing socket */
dc661374 68char *NetName; /* name of home (local?) network */
14a39063 69
7f108496 70getrequests()
14a39063 71{
7e3417e6 72 int t;
7f108496 73 union wait status;
7f108496 74 register struct servent *sp;
14a39063
EA
75
76 /*
77 ** Set up the address for the mailer.
78 */
79
7f108496
EA
80 sp = getservbyname("smtp", "tcp");
81 if (sp == NULL)
82 {
83 syserr("server \"smtp\" unknown");
a1e665f3 84 goto severe;
7f108496
EA
85 }
86 SendmailAddress.sin_family = AF_INET;
87 SendmailAddress.sin_addr.s_addr = INADDR_ANY;
a0221fb9 88 SendmailAddress.sin_port = sp->s_port;
14a39063
EA
89
90 /*
91 ** Try to actually open the connection.
92 */
93
94# ifdef DEBUG
9678c96d 95 if (tTd(15, 1))
7f108496 96 printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
14a39063
EA
97# endif DEBUG
98
7f108496 99 /* get a socket for the SMTP connection */
eb8af3ce
EA
100 DaemonSocket = socket(AF_INET, SOCK_STREAM, 0, 0);
101 if (DaemonSocket < 0)
4b5cf74c 102 {
7f108496
EA
103 /* probably another daemon already */
104 syserr("getrequests: can't create socket");
105 severe:
106# ifdef LOG
107 if (LogLevel > 0)
108 syslog(LOG_SALERT, "cannot get connection");
109# endif LOG
110 finis();
111 }
78c9dc29
EA
112
113#ifdef DEBUG
114 /* turn on network debugging? */
115 if (tTd(15, 15))
116 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 0, 0);
117#endif DEBUG
118
eb8af3ce 119 if (bind(DaemonSocket, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
7f108496
EA
120 {
121 syserr("getrequests: cannot bind");
eb8af3ce 122 (void) close(DaemonSocket);
7f108496
EA
123 goto severe;
124 }
eb8af3ce 125 listen(DaemonSocket, 10);
14a39063
EA
126
127# ifdef DEBUG
7f108496 128 if (tTd(15, 1))
eb8af3ce 129 printf("getrequests: %d\n", DaemonSocket);
14a39063 130# endif DEBUG
2a16bae3 131
7f108496
EA
132 struct wh wbuf;
133
134 wbuf.index = index;
135 wbuf.count = 0;
136 wbuf.ccount = cnt;
137 wbuf.data = buf;
138 write(MailPort, &wbuf, sizeof wbuf);
14a39063 139}
1ab402f2
EA
140\f/*
141** MAKECONNECTION -- make a connection to an SMTP socket on another machine.
142**
143** Parameters:
144** host -- the name of the host.
e2d7c32a 145** port -- the port number to connect to.
1ab402f2
EA
146** outfile -- a pointer to a place to put the outfile
147** descriptor.
148** infile -- ditto for infile.
149**
150** Returns:
151** An exit code telling whether the connection could be
152** made and if not why not.
153**
154** Side Effects:
155** none.
156*/
157
e2d7c32a 158makeconnection(host, port, outfile, infile)
1ab402f2 159 char *host;
f7eb07a3 160 u_short port;
1ab402f2
EA
161 FILE **outfile;
162 FILE **infile;
163{
164 register int s;
165
166 /*
167 ** Set up the address for the mailer.
b3e29341 168 ** Accept "[a.b.c.d]" syntax for host name.
1ab402f2
EA
169 */
170
b3e29341
EA
171 if (host[0] == '[')
172 {
e56baaff
EA
173 long hid;
174 register char *p = index(host, ']');
b3e29341 175
e56baaff 176 if (p != NULL)
b3e29341 177 {
e56baaff
EA
178 *p = '\0';
179 hid = inet_addr(&host[1]);
180 *p = ']';
b3e29341 181 }
e56baaff 182 if (p == NULL || hid == -1)
b3e29341
EA
183 {
184 usrerr("Invalid numeric domain spec \"%s\"", host);
185 return (EX_NOHOST);
186 }
187 SendmailAddress.sin_addr.s_addr = hid;
188 }
7f108496
EA
189 else
190 {
191 register struct hostent *hp = gethostbyname(host);
192
e56baaff 193 if (hp == NULL)
7f108496 194 return (EX_NOHOST);
83f674d8 195 bcopy(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
7f108496
EA
196 }
197
198 /*
199 ** Determine the port number.
200 */
201
372c9e7f
EA
202 if (port != 0)
203 SendmailAddress.sin_port = htons(port);
204 else
7f108496
EA
205 {
206 register struct servent *sp = getservbyname("smtp", "tcp");
207
208 if (sp == NULL)
209 {
210 syserr("makeconnection: server \"smtp\" unknown");
211 return (EX_OSFILE);
212 }
372c9e7f 213 SendmailAddress.sin_port = sp->s_port;
7f108496 214 }
1ab402f2
EA
215
216 /*
217 ** Try to actually open the connection.
218 */
219
220# ifdef DEBUG
9678c96d 221 if (tTd(16, 1))
1ab402f2
EA
222 printf("makeconnection (%s)\n", host);
223# endif DEBUG
224
7e3417e6
EA
225#ifdef NVMUNIX
226 s = socket(AF_INET, SOCK_STREAM, 0, 0);
227#else NVMUNIX
7f108496 228 s = socket(AF_INET, SOCK_STREAM, 0, 0);
7e3417e6 229#endif NVMUNIX
1ab402f2
EA
230 if (s < 0)
231 {
232 syserr("makeconnection: no socket");
233 goto failure;
234 }
235
236# ifdef DEBUG
9678c96d 237 if (tTd(16, 1))
1ab402f2 238 printf("makeconnection: %d\n", s);
78c9dc29
EA
239
240 /* turn on network debugging? */
241 if (tTd(16, 14))
242 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0);
1ab402f2 243# endif DEBUG
912acb74 244 (void) fflush(CurEnv->e_xfp); /* for debugging */
54f71ceb 245 errno = 0; /* for debugging */
7e3417e6
EA
246#ifdef NVMUNIX
247 bind(s, &SendmailAddress, sizeof SendmailAddress, 0);
248 if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
249#else NVMUNIX
7f108496 250 SendmailAddress.sin_family = AF_INET;
7f108496 251 if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
7e3417e6 252#endif NVMUNIX
1ab402f2
EA
253 {
254 /* failure, decide if temporary or not */
255 failure:
256 switch (errno)
257 {
258 case EISCONN:
259 case ETIMEDOUT:
a82f298c
EA
260 case EINPROGRESS:
261 case EALREADY:
262 case EADDRINUSE:
7934dd80 263 case EHOSTDOWN:
a82f298c
EA
264 case ENETDOWN:
265 case ENETRESET:
266 case ENOBUFS:
e31f6e62 267 case ECONNREFUSED:
e5b251f1 268 case ECONNRESET:
8b189b5a 269 case EHOSTUNREACH:
1aaa7dec 270 case ENETUNREACH:
1ab402f2 271 /* there are others, I'm sure..... */
83f674d8 272 CurEnv->e_flags &= ~EF_FATALERRS;
1ab402f2
EA
273 return (EX_TEMPFAIL);
274
e56baaff
EA
275 case EPERM:
276 /* why is this happening? */
277 syserr("makeconnection: funny failure, addr=%lx, port=%x",
278 SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
54f71ceb 279 return (EX_TEMPFAIL);
e56baaff 280
1ab402f2
EA
281 default:
282 return (EX_UNAVAILABLE);
283 }
284 }
285
286 /* connection ok, put it into canonical form */
287 *outfile = fdopen(s, "w");
288 *infile = fdopen(s, "r");
289
1aaa7dec 290 return (EX_OK);
1ab402f2 291}
2ec2faaa
EA
292\f/*
293** MYHOSTNAME -- return the name of this host.
294**
295** Parameters:
296** hostbuf -- a place to return the name of this host.
05894fc6 297** size -- the size of hostbuf.
2ec2faaa
EA
298**
299** Returns:
300** A list of aliases for this host.
301**
302** Side Effects:
303** none.
304*/
305
306char **
05894fc6 307myhostname(hostbuf, size)
2ec2faaa 308 char hostbuf[];
05894fc6 309 int size;
2ec2faaa
EA
310{
311 extern struct hostent *gethostbyname();
e56baaff 312 struct hostent *hp;
2ec2faaa 313
9da54d8f 314 gethostname(hostbuf, size);
e56baaff
EA
315 hp = gethostbyname(hostbuf);
316 if (hp != NULL)
b9b481e2
EA
317 {
318 strcpy(hostbuf, hp->h_name);
e56baaff 319 return (hp->h_aliases);
b9b481e2 320 }
2ec2faaa
EA
321 else
322 return (NULL);
323}
217a0102
EA
324\f/*
325** MAPHOSTNAME -- turn a hostname into canonical form
326**
327** Parameters:
328** hbuf -- a buffer containing a hostname.
329** hbsize -- the size of hbuf.
330**
331** Returns:
332** none.
333**
334** Side Effects:
335** Looks up the host specified in hbuf. If it is not
336** the canonical name for that host, replace it with
337** the canonical name. If the name is unknown, or it
338** is already the canonical name, leave it unchanged.
339*/
340
341maphostname(hbuf, hbsize)
342 char *hbuf;
343 int hbsize;
344{
345 register struct hostent *hp;
346 extern struct hostent *gethostbyname();
347
348 makelower(hbuf);
349 hp = gethostbyname(hbuf);
350 if (hp != NULL)
351 {
352 int i = strlen(hp->h_name);
2ec2faaa 353
217a0102
EA
354 if (i >= hbsize)
355 hp->h_name[--i] = '\0';
356 strcpy(hbuf, hp->h_name);
357 }
358}
359\f
2ec2faaa 360# else DAEMON
217a0102 361/* code for systems without sophisticated networking */
2ec2faaa
EA
362
363/*
364** MYHOSTNAME -- stub version for case of no daemon code.
69f904e0
EA
365**
366** Can't convert to upper case here because might be a UUCP name.
05894fc6
EA
367**
368** Mark, you can change this to be anything you want......
2ec2faaa
EA
369*/
370
371char **
05894fc6 372myhostname(hostbuf, size)
2ec2faaa 373 char hostbuf[];
05894fc6 374 int size;
2ec2faaa
EA
375{
376 register FILE *f;
377
378 hostbuf[0] = '\0';
379 f = fopen("/usr/include/whoami", "r");
380 if (f != NULL)
381 {
05894fc6 382 (void) fgets(hostbuf, size, f);
2ec2faaa
EA
383 fixcrlf(hostbuf, TRUE);
384 (void) fclose(f);
385 }
386 return (NULL);
387}
217a0102
EA
388\f/*
389** MAPHOSTNAME -- turn a hostname into canonical form
390**
391** Parameters:
392** hbuf -- a buffer containing a hostname.
393** hbsize -- the size of hbuf.
394**
395** Returns:
396** none.
397**
398** Side Effects:
399** Looks up the host specified in hbuf. If it is not
400** the canonical name for that host, replace it with
401** the canonical name. If the name is unknown, or it
402** is already the canonical name, leave it unchanged.
403*/
404
405/*ARGSUSED*/
406maphostname(hbuf, hbsize)
407 char *hbuf;
408 int hbsize;
409{
410 return;
411}
412
14a39063
EA
413
414#endif DAEMON