masqmail

view src/libident/id_open.c @ 3:8c55886cacd8

man pages will be maintained in troff now
author meillo@marmaro.de
date Fri, 26 Sep 2008 21:40:10 +0200
parents
children 26e34ae9a3e3
line source
1 /*
2 ** id_open.c Establish/initiate a connection to an IDENT server
3 **
4 ** Author: Peter Eriksson <pen@lysator.liu.se>
5 ** Fixes: Pär Emanuelsson <pell@lysator.liu.se>
6 */
8 #ifdef NeXT3
9 # include <libc.h>
10 #endif
12 #include <stdio.h>
13 #include <errno.h>
14 #include <fcntl.h>
16 #ifdef HAVE_ANSIHEADERS
17 # include <stdlib.h>
18 # include <string.h>
19 # include <unistd.h>
20 # if !defined(__sgi) && !defined(VMS)
21 # define bzero(p,l) memset(p, 0, l)
22 # endif
23 #endif
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/wait.h>
28 #include <sys/time.h>
29 #include <sys/file.h>
31 #define IN_LIBIDENT_SRC
32 #include "ident.h"
34 #include <arpa/inet.h>
36 #ifdef _AIX
37 # include <sys/select.h>
38 #endif
41 /*
42 ident_t *id_open __P3(struct in_addr *, laddr,
43 struct in_addr *, faddr,
44 struct timeval *, timeout)
45 */
47 ident_t *id_open __P(( __STRUCT_IN_ADDR_P laddr,
48 __STRUCT_IN_ADDR_P faddr,
49 __STRUCT_TIMEVAL_P timeout))
50 {
51 ident_t *id;
52 int res, tmperrno;
53 struct sockaddr_in sin_laddr, sin_faddr;
54 fd_set rs, ws, es;
55 #ifndef OLD_SETSOCKOPT
56 int on = 1;
57 struct linger linger;
58 #endif
60 if ((id = (ident_t *) malloc(sizeof(*id))) == 0)
61 return 0;
63 if ((id->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
64 {
65 free(id);
66 return 0;
67 }
69 if (timeout)
70 {
71 if ((res = fcntl(id->fd, F_GETFL, 0)) < 0)
72 goto ERROR;
74 #ifndef VMS
75 if (fcntl(id->fd, F_SETFL, res | FNDELAY) < 0)
76 goto ERROR;
77 #endif
78 }
80 /* We silently ignore errors if we can't change LINGER */
81 #ifdef OLD_SETSOCKOPT
82 /* Old style setsockopt() */
83 (void) setsockopt(id->fd, SOL_SOCKET, SO_DONTLINGER);
84 (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR);
85 #else
86 /* New style setsockopt() */
87 linger.l_onoff = 0;
88 linger.l_linger = 0;
90 (void) setsockopt(id->fd, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
91 (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
92 #endif
94 id->buf[0] = '\0';
96 bzero((char *)&sin_laddr, sizeof(sin_laddr));
97 sin_laddr.sin_family = AF_INET;
98 sin_laddr.sin_addr = *laddr;
99 sin_laddr.sin_port = 0;
101 if (bind(id->fd, (struct sockaddr *) &sin_laddr, sizeof(sin_laddr)) < 0)
102 {
103 #ifdef DEBUG
104 perror("libident: bind");
105 #endif
106 goto ERROR;
107 }
109 bzero((char *)&sin_faddr, sizeof(sin_faddr));
110 sin_faddr.sin_family = AF_INET;
111 sin_faddr.sin_addr = *faddr;
112 sin_faddr.sin_port = htons(IDPORT);
114 errno = 0;
115 res = connect(id->fd, (struct sockaddr *) &sin_faddr, sizeof(sin_faddr));
116 if (res < 0 && errno != EINPROGRESS)
117 {
118 #ifdef DEBUG
119 perror("libident: connect");
120 #endif
121 goto ERROR;
122 }
124 if (timeout)
125 {
126 FD_ZERO(&rs);
127 FD_ZERO(&ws);
128 FD_ZERO(&es);
130 FD_SET(id->fd, &rs);
131 FD_SET(id->fd, &ws);
132 FD_SET(id->fd, &es);
134 #ifdef __hpux
135 if ((res = select(FD_SETSIZE, (int *) &rs, (int *) &ws, (int *) &es, timeout)) < 0)
136 #else
137 if ((res = select(FD_SETSIZE, &rs, &ws, &es, timeout)) < 0)
138 #endif
139 {
140 #ifdef DEBUG
141 perror("libident: select");
142 #endif
143 goto ERROR;
144 }
146 if (res == 0)
147 {
148 errno = ETIMEDOUT;
149 goto ERROR;
150 }
152 if (FD_ISSET(id->fd, &es))
153 goto ERROR;
155 if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws))
156 goto ERROR;
157 }
159 return id;
161 ERROR:
162 tmperrno = errno; /* Save, so close() won't erase it */
163 close(id->fd);
164 free(id);
165 errno = tmperrno;
166 return 0;
167 }