masqmail
view src/connect.c @ 421:f37384470855
Changed lockdir to /var/lock/masqmail; Create lockdir and piddir on startup.
Moved the lockdir out of the spool dir. (When /var/lock is a ramdisk
we do well to have the lock files there.) Added the new configure option
--with-lockdir to change that location. Nontheless, if we run_as_user,
then lock files are always stored in the spool dir directly.
Instead of installing the lockdir and piddir at installation time, we
create them on startup time now if they are missing. This is necessary
if lockdir or piddir are a tmpfs.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Wed, 30 May 2012 09:38:38 +0200 |
parents | 6500db550a03 |
children |
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 1999 Oliver Kurth
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include "masqmail.h"
21 static GList*
22 resolve_ip(gchar *ip)
23 {
24 struct in_addr ia;
25 mxip_addr mxip;
27 if (!inet_aton(ip, &ia)) {
28 /* No dots-and-numbers notation. */
29 return NULL;
30 }
31 mxip.name = g_strdup(ip);
32 mxip.pref = 0;
33 mxip.ip = (guint32) * (guint32 *) (&ia);
34 return g_list_append(NULL, g_memdup(&mxip, sizeof(mxip)));
35 }
37 mxip_addr*
38 connect_hostlist(int *psockfd, gchar *host, guint port, GList *addr_list)
39 {
40 GList *addr_node;
41 struct sockaddr_in saddr;
42 int saved_errno;
44 DEBUG(5) debugf("connect_hostlist entered\n");
46 for (addr_node = g_list_first(addr_list); addr_node;
47 addr_node = g_list_next(addr_node)) {
48 mxip_addr *addr = (mxip_addr *) (addr_node->data);
49 *psockfd = socket(PF_INET, SOCK_STREAM, 0);
51 memset(&saddr, 0, sizeof(saddr));
52 saddr.sin_family = AF_INET;
53 saddr.sin_port = htons(port);
54 /* clumsy, but makes compiler happy: */
55 saddr.sin_addr = *(struct in_addr *) (&(addr->ip));
57 DEBUG(5) debugf(" trying ip %s port %d\n",
58 inet_ntoa(saddr.sin_addr), port);
60 if (connect(*psockfd, (struct sockaddr *) &saddr,
61 sizeof(saddr))==0) {
62 DEBUG(5) debugf(" connected to %s\n",
63 inet_ntoa(saddr.sin_addr));
64 return addr;
65 }
67 saved_errno = errno;
68 close(*psockfd);
69 logwrite(LOG_WARNING, "connection to %s failed: %s\n",
70 inet_ntoa(saddr.sin_addr), strerror(errno));
71 errno = saved_errno;
73 if ((saved_errno != ECONNREFUSED) &&
74 (saved_errno != ETIMEDOUT) &&
75 (saved_errno != ENETUNREACH) &&
76 (saved_errno != EHOSTUNREACH)) {
77 return NULL;
78 }
79 }
80 return NULL;
81 }
83 /*
84 ** Given a list of resolver functions, this function
85 ** resolve the host and tries to connect to the addresses
86 ** returned. If a connection attemp is timed out or refused,
87 ** the next address is tried.
88 **
89 ** TODO: the resolver functions might return duplicate addresses,
90 ** if attempt failed for one it should not be tried again.
91 */
92 mxip_addr*
93 connect_resolvelist(int *psockfd, gchar *host, guint port,
94 GList *res_func_list)
95 {
96 GList *res_node;
97 GList *addr_list;
99 DEBUG(5) debugf("connect_resolvelist entered\n");
101 h_errno = 0;
102 if (isdigit(*host)) {
103 mxip_addr *addr;
105 if ((addr_list = resolve_ip(host))) {
106 addr = connect_hostlist(psockfd, host, port,
107 addr_list);
108 g_list_free(addr_list);
109 return addr;
110 }
111 /*
112 ** Probably a hostname that begins with a digit.
113 ** E.g. '3dwars.de'. Thus fall ...
114 */
115 }
117 if (!res_func_list) {
118 logwrite(LOG_ALERT, "res_funcs not set!\n");
119 exit(1);
120 }
122 foreach(res_func_list, res_node) {
123 resolve_func res_func;
124 DEBUG(6) debugf(" foreach() body\n");
126 res_func = (resolve_func) res_node->data;
127 if (!res_func) {
128 logwrite(LOG_ALERT, "Empty res_func!\n");
129 exit(1);
130 }
132 errno = 0;
133 if ((addr_list = res_func(NULL, host))) {
135 mxip_addr *addr;
136 if ((addr = connect_hostlist(psockfd, host, port,
137 addr_list))) {
138 return addr;
139 }
140 DEBUG(5) debugf("connect_hostlist failed: %s\n",
141 strerror(errno));
142 g_list_free(addr_list);
143 } else if (!g_list_next(res_node)) {
144 logwrite(LOG_ALERT, "could not resolve %s: %s\n",
145 host, hstrerror(h_errno));
146 }
147 }
148 return NULL;
150 }