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;
+}