Mercurial > masqmail
diff src/libident/id_open.c @ 0:08114f7dcc23 0.2.21
this is masqmail-0.2.21 from oliver kurth
author | meillo@marmaro.de |
---|---|
date | Fri, 26 Sep 2008 17:05:23 +0200 |
parents | |
children | 26e34ae9a3e3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libident/id_open.c Fri Sep 26 17:05:23 2008 +0200 @@ -0,0 +1,167 @@ +/* +** id_open.c Establish/initiate a connection to an IDENT server +** +** Author: Peter Eriksson <pen@lysator.liu.se> +** Fixes: Pär Emanuelsson <pell@lysator.liu.se> +*/ + +#ifdef NeXT3 +# include <libc.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> + +#ifdef HAVE_ANSIHEADERS +# include <stdlib.h> +# include <string.h> +# include <unistd.h> +# if !defined(__sgi) && !defined(VMS) +# define bzero(p,l) memset(p, 0, l) +# endif +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/file.h> + +#define IN_LIBIDENT_SRC +#include "ident.h" + +#include <arpa/inet.h> + +#ifdef _AIX +# include <sys/select.h> +#endif + + +/* +ident_t *id_open __P3(struct in_addr *, laddr, + struct in_addr *, faddr, + struct timeval *, timeout) +*/ + +ident_t *id_open __P(( __STRUCT_IN_ADDR_P laddr, + __STRUCT_IN_ADDR_P faddr, + __STRUCT_TIMEVAL_P timeout)) +{ + ident_t *id; + int res, tmperrno; + struct sockaddr_in sin_laddr, sin_faddr; + fd_set rs, ws, es; +#ifndef OLD_SETSOCKOPT + int on = 1; + struct linger linger; +#endif + + if ((id = (ident_t *) malloc(sizeof(*id))) == 0) + return 0; + + if ((id->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + free(id); + return 0; + } + + if (timeout) + { + if ((res = fcntl(id->fd, F_GETFL, 0)) < 0) + goto ERROR; + +#ifndef VMS + if (fcntl(id->fd, F_SETFL, res | FNDELAY) < 0) + goto ERROR; +#endif + } + + /* We silently ignore errors if we can't change LINGER */ +#ifdef OLD_SETSOCKOPT + /* Old style setsockopt() */ + (void) setsockopt(id->fd, SOL_SOCKET, SO_DONTLINGER); + (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR); +#else + /* New style setsockopt() */ + linger.l_onoff = 0; + linger.l_linger = 0; + + (void) setsockopt(id->fd, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); + (void) setsockopt(id->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); +#endif + + id->buf[0] = '\0'; + + bzero((char *)&sin_laddr, sizeof(sin_laddr)); + sin_laddr.sin_family = AF_INET; + sin_laddr.sin_addr = *laddr; + sin_laddr.sin_port = 0; + + if (bind(id->fd, (struct sockaddr *) &sin_laddr, sizeof(sin_laddr)) < 0) + { +#ifdef DEBUG + perror("libident: bind"); +#endif + goto ERROR; + } + + bzero((char *)&sin_faddr, sizeof(sin_faddr)); + sin_faddr.sin_family = AF_INET; + sin_faddr.sin_addr = *faddr; + sin_faddr.sin_port = htons(IDPORT); + + errno = 0; + res = connect(id->fd, (struct sockaddr *) &sin_faddr, sizeof(sin_faddr)); + if (res < 0 && errno != EINPROGRESS) + { +#ifdef DEBUG + perror("libident: connect"); +#endif + goto ERROR; + } + + if (timeout) + { + FD_ZERO(&rs); + FD_ZERO(&ws); + FD_ZERO(&es); + + FD_SET(id->fd, &rs); + FD_SET(id->fd, &ws); + FD_SET(id->fd, &es); + +#ifdef __hpux + if ((res = select(FD_SETSIZE, (int *) &rs, (int *) &ws, (int *) &es, timeout)) < 0) +#else + if ((res = select(FD_SETSIZE, &rs, &ws, &es, timeout)) < 0) +#endif + { +#ifdef DEBUG + perror("libident: select"); +#endif + goto ERROR; + } + + if (res == 0) + { + errno = ETIMEDOUT; + goto ERROR; + } + + if (FD_ISSET(id->fd, &es)) + goto ERROR; + + if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws)) + goto ERROR; + } + + return id; + + ERROR: + tmperrno = errno; /* Save, so close() won't erase it */ + close(id->fd); + free(id); + errno = tmperrno; + return 0; +}