OSSP CVS Repository

ossp - Check-in [1049]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1049
Date: 2001-Oct-02 15:27:44 (local)
2001-Oct-02 13:27:44 (UTC)
User:rse
Branch:
Comment: Initial revision
Tickets:
Inspections:
Files:
ossp-pkg/sa/Makefile.in      added-> 1.1
ossp-pkg/sa/README      added-> 1.1
ossp-pkg/sa/aclocal.m4      added-> 1.1
ossp-pkg/sa/autogen.sh      added-> 1.1
ossp-pkg/sa/configure.ac      added-> 1.1
ossp-pkg/sa/sa.ac      added-> 1.1
ossp-pkg/sa/sa.c      added-> 1.1

ossp-pkg/sa/Makefile.in -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,44 ----
+ 
+ CC      = @CC@
+ CFLAGS  = @CFLAGS@ @DEFS@
+ LDFLAGS = @LDFLAGS@
+ LIBS    = @LIBS@
+ AR      = @AR@
+ RANLIB  = @RANLIB@
+ RM      = rm -f
+ 
+ PRG_NAME = test
+ PRG_OBJS = test.o
+ 
+ LIB_NAME = libsa.a
+ LIB_OBJS = sa.o
+ 
+ all: $(LIB_NAME)
+ 
+ .c.o:
+        $(CC) $(CFLAGS) -c $<
+ 
+ $(LIB_NAME): $(LIB_OBJS)
+        $(AR) rc $(LIB_NAME) $(LIB_OBJS)
+        $(RANLIB) $(LIB_NAME)
+ 
+ $(PRG_NAME): $(PRG_OBJS) $(LIB_NAME)
+        $(CC) $(LDFLAGS) -o $(PRG_NAME) $(PRG_OBJS) $(LIB_NAME) $(LIBS)
+ 
+ check: $(PRG_NAME)
+        ./$(PRG_NAME)
+ 
+ clean: 
+        $(RM) $(LIB_NAME) $(LIB_OBJS)
+        $(RM) $(PRG_NAME) $(PRG_OBJS)
+ 
+ distclean: clean
+        $(RM) config.cache config.log config.status
+        $(RM) config.h
+        $(RM) Makefile
+ 
+ realclean: distclean
+        $(RM) config.h.in configure
+ 
+ install:
+ 


ossp-pkg/sa/README -> 1.1



ossp-pkg/sa/aclocal.m4 -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,88 ----
+ 
+ dnl ##
+ dnl ##  Check whether compiler option works
+ dnl ##
+ dnl ##  configure.in:
+ dnl ##    AC_COMPILER_OPTION(<name>, <display>, <option>,
+ dnl ##                       <action-success>, <action-failure>)
+ dnl ##
+ 
+ AC_DEFUN(AC_COMPILER_OPTION,[dnl
+ AC_MSG_CHECKING(whether compiler option(s) $2 work)
+ AC_CACHE_VAL(ac_cv_compiler_option_$1,[
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $3"
+ AC_TRY_COMPILE([],[], ac_cv_compiler_option_$1=yes, ac_cv_compiler_option_$1=no)
+ CFLAGS="$SAVE_CFLAGS"
+ ])dnl
+ if test ".$ac_cv_compiler_option_$1" = .yes; then
+     ifelse([$4], , :, [$4])
+ else
+     ifelse([$5], , :, [$5])
+ fi
+ AC_MSG_RESULT([$ac_cv_compiler_option_$1])
+ ])dnl
+ 
+ dnl ##
+ dnl ##  Debugging Support
+ dnl ##
+ dnl ##  configure.in:
+ dnl ##    AC_CHECK_DEBUGGING
+ dnl ##
+ 
+ AC_DEFUN(AC_CHECK_DEBUGGING,[dnl
+ AC_ARG_ENABLE(debug,dnl
+ [  --enable-debug          build for debugging (default=no)],
+ [dnl
+ if test ".$ac_cv_prog_gcc" = ".yes"; then
+     case "$CFLAGS" in
+         *-O* ) ;;
+            * ) CFLAGS="$CFLAGS -O2" ;;
+     esac
+     case "$CFLAGS" in
+         *-g* ) ;;
+            * ) CFLAGS="$CFLAGS -g" ;;
+     esac
+     case "$CFLAGS" in
+         *-pipe* ) ;;
+               * ) AC_COMPILER_OPTION(pipe, -pipe, -pipe, CFLAGS="$CFLAGS -pipe") ;;
+     esac
+     AC_COMPILER_OPTION(defdbg, -DDEBUG, -DDEBUG, CFLAGS="$CFLAGS -DDEBUG")
+     AC_COMPILER_OPTION(ggdb3, -ggdb3, -ggdb3, CFLAGS="$CFLAGS -ggdb3")
+     CFLAGS="$CFLAGS -pedantic"
+     CFLAGS="$CFLAGS -Wall"
+     WMORE="-Wshadow -Wpointer-arith -Wcast-align -Winline"
+     WMORE="$WMORE -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
+     AC_COMPILER_OPTION(wmore, -W<xxx>, $WMORE, CFLAGS="$CFLAGS $WMORE")
+     AC_COMPILER_OPTION(wnolonglong, -Wno-long-long, -Wno-long-long, CFLAGS="$CFLAGS -Wno-long-long")
+ else
+     case "$CFLAGS" in
+         *-g* ) ;;
+            * ) CFLAGS="$CFLAGS -g" ;;
+     esac
+ fi
+ msg="enabled"
+ ],[
+ if test ".$ac_cv_prog_gcc" = ".yes"; then
+ case "$CFLAGS" in
+     *-pipe* ) ;;
+           * ) AC_COMPILER_OPTION(pipe, -pipe, -pipe, CFLAGS="$CFLAGS -pipe") ;;
+ esac
+ fi
+ case "$CFLAGS" in
+     *-g* ) CFLAGS=`echo "$CFLAGS" |\
+                    sed -e 's/ -g / /g' -e 's/ -g$//' -e 's/^-g //g' -e 's/^-g$//'` ;;
+ esac
+ case "$CXXFLAGS" in
+     *-g* ) CXXFLAGS=`echo "$CXXFLAGS" |\
+                      sed -e 's/ -g / /g' -e 's/ -g$//' -e 's/^-g //g' -e 's/^-g$//'` ;;
+ esac
+ msg=disabled
+ ])dnl
+ AC_MSG_CHECKING(for compilation debug mode)
+ AC_MSG_RESULT([$msg])
+ if test ".$msg" = .enabled; then
+     enable_shared=no
+ fi
+ ])
+ 


ossp-pkg/sa/autogen.sh -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,47 ----
+ #!/bin/sh
+ 
+ #   generator tools version sanity check
+ #    "libtoolize --version 4 1.4.2 1.4*"
+ #    "shtoolize  -v        3 1.5.4 1.5.*"
+ for spec in \
+     "autoconf   --version 4 2.52  2.5*"
+ do
+     set -- $spec
+     t="$1"
+     o="$2"
+     p="$3"
+     e="$4"
+     a="$5"
+     v=`($t $o | head -1 | awk "{ print \\\$$p; }") 2>/dev/null`
+     if [ ".$v" = . ]; then
+         echo "$0:ERROR: unable to determine version of $t" 1>&2
+         exit 1
+     fi
+     eval "${t}_version=\"$v\""
+     case "$v" in
+         $e )
+             ;;
+         $a )
+             echo "$0:WARNING: $t version $v still accepted, although expected $e." 1>&2
+             ;;
+         * )
+             echo "$0:ERROR: $t version $e expected, but found $v." 1>&2
+             ;;
+     esac
+ done
+ 
+ #   GNU Libtool generation
+ # echo "GNU Libtool $libtoolize_version -> ltmain.sh, libtool.m4, config.guess, config.sub"
+ # libtoolize --force --copy >/dev/null 2>&1
+ # cp `libtoolize --force --copy --dry-run | grep "add the contents of" |\
+ #     sed -e 's;^[^\`]*\`;;' -e "s;'.*;;"` libtool.m4
+ 
+ #   GNU Autoconf generation
+ echo "GNU Autoconf $autoconf_version -> configure, config.h.in"
+ autoconf
+ autoheader
+ 
+ #   GNU Shtool generation
+ # echo "GNU Shtool $shtoolize_version -> shtool"
+ # shtoolize -q all
+ 


ossp-pkg/sa/configure.ac -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,26 ----
+ dnl ##
+ dnl ##  Autoconf specification for SA library
+ dnl ##
+ 
+ AC_PREREQ(2.52)dnl
+ AC_REVISION(1.0)
+ 
+ AC_INIT(README)
+ AC_PREFIX_DEFAULT(/usr/local)
+ AC_CONFIG_HEADER(config.h)
+ 
+ AC_SET_MAKE
+ AC_PROG_CC
+ AC_PROG_CPP
+ AC_CHECK_PROG(AR, ar, ar)
+ AC_PROG_RANLIB
+ 
+ AC_CHECK_DEBUGGING
+ 
+ sinclude(sa.ac)
+ AC_CHECK_SA
+ 
+ AC_OUTPUT(dnl
+ Makefile dnl
+ )dnl
+ 


ossp-pkg/sa/sa.ac -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,44 ----
+ ##
+ ##  SA - OSSP Socket Abstraction Library
+ ##  Copyright (c) 2001 The OSSP Project (http://www.ossp.org/)
+ ##  Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/)
+ ##
+ ##  This file is part of OSSP SA, a socket abstraction library which
+ ##  can be found at http://www.ossp.org/pkg/sa/.
+ ##
+ ##  Permission to use, copy, modify, and distribute this software for
+ ##  any purpose with or without fee is hereby granted, provided that
+ ##  the above copyright notice and this permission notice appear in all
+ ##  copies.
+ ##
+ ##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ ##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ ##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+ ##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ ##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ ##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ ##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ ##  SUCH DAMAGE.
+ ##
+ ##  sa.ac: socket abstraction Autoconf checks
+ ##
+ 
+ AC_DEFUN(AC_CHECK_SA,[
+     #   make sure libnsl and libsocket are linked in if they exist
+     AC_CHECK_LIB(nsl, gethostname)
+     if test ".`echo $LIBS | grep nsl`" = .; then
+         AC_CHECK_LIB(nsl, gethostbyname)
+     fi  
+     AC_CHECK_LIB(socket, accept)
+     
+     #   check for system headers
+     AC_CHECK_HEADERS(string.h sys/types.h sys/socket.h netdb.h netinet/in.h)
+ 
+     #   check for system functions
+     AC_CHECK_FUNCS(inet_aton inet_pton inet_ntoa inet_ntop snprintf vsnprintf)
+ ])
+ 


ossp-pkg/sa/sa.c -> 1.1

*** /dev/null    Fri Apr 19 09:15:37 2024
--- -    Fri Apr 19 09:16:20 2024
***************
*** 0 ****
--- 1,957 ----
+ /*
+ **  SA - OSSP Socket Abstraction Library
+ **  Copyright (c) 2001 The OSSP Project (http://www.ossp.org/)
+ **  Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/)
+ **
+ **  This file is part of OSSP SA, a socket abstraction library which
+ **  can be found at http://www.ossp.org/pkg/sa/.
+ **
+ **  Permission to use, copy, modify, and distribute this software for
+ **  any purpose with or without fee is hereby granted, provided that
+ **  the above copyright notice and this permission notice appear in all
+ **  copies.
+ **
+ **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ **  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ **  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+ **  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ **  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ **  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ **  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ **  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ **  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ **  SUCH DAMAGE.
+ **
+ **  sa.c: socket abstraction library
+ */
+ 
+ /* include optional Autoconf header */
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ 
+ /* include system API headers */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <time.h>
+ #include <sys/time.h>
+ #include <netdb.h>
+ #include <sys/types.h>
+ #include <sys/un.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ 
+ /* include own API header */
+ #include "sa.h"
+ 
+ /* socket address abstraction object */
+ struct sa_addr_st {
+     struct sockaddr *saBuf;
+     socklen_t        slBuf;
+     int              nFamily;
+     int              nProto;
+ };
+ 
+ /* socket abstraction object */
+ struct sa_st {
+     int              sSocket;
+     int              bTimeout;
+     struct timeval   tvTimeout;
+     int              nReadLen;
+     int              nReadSize;
+     char            *cpReadBuf;
+     int              nWriteLen;
+     int              nWriteSize;
+     char            *cpWriteBuf;
+ };
+ 
+ /* make sure AF_LOCAL define exists */
+ #if !defined(AF_LOCAL) && defined(AF_UNIX)
+ #define AF_LOCAL AF_UNIX
+ #endif
+ 
+ /* make sure inet_pton() exists */
+ #if defined(HAVE_INET_PTON)
+ #define sa_inet_pton inet_pton
+ #elif defined(HAVE_INET_ATON)
+ static int inet_pton(int family, const char *strptr, void *addrptr)
+ {
+     struct in_addr in_val;
+ 
+     if (family == AF_INET) {
+         if (inet_aton(strptr, &in_val)) {
+             memcpy(addrptr, &in_val, sizeof(struct in_addr));
+             return 1;
+         }
+         return 0;
+     }
+     errno = EAFNOSUPPORT;
+     return -1;
+ }
+ #else
+ #error "neither inet_pton nor inet_aton available"
+ #endif
+ 
+ /* make sure inet_ntop() exists */
+ #if defined(HAVE_INET_NTOP)
+ #define sa_inet_ntop inet_ntop
+ #elif defined(HAVE_INET_NTOA)
+ static char *inet_ntop(int family, const void *src, char *dst, size_t size)
+ {
+     struct in_addr in_val;
+     char *cp;
+     int n;
+ 
+     if (family == AF_INET) {
+         if ((cp = inet_ntoa(src)) != NULL) {
+             n = strlen(cp);
+             if (n > size-1)
+                 n = size-1;
+             memcpy(dst, cp, n);
+             dst[n] = '\0';
+             return 1;
+         }
+         return 0;
+     }
+     errno = EAFNOSUPPORT;
+     return -1;
+ }
+ #else
+ #error "neither inet_ntop nor inet_ntoa available"
+ #endif
+ 
+ /* make sure vsnprintf() exists */
+ #if defined(HAVE_VSNPRINTF)
+ #define sa_vsnprintf vsnprintf
+ #elif defined(HAVE_VSPRINTF)
+ static int sa_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
+ {
+     int rv;
+     
+     rv = vsprintf(str, fmt, ap);
+     if (rv > size) {
+         fprintf(stderr, "ERROR: vsprintf(3) buffer overflow!\n");
+         abort();
+     }
+ }
+ #else
+ #error "neither vsnprintf nor vsprintf available"
+ #endif
+ 
+ /* make sure snprintf() exists */
+ #if defined(HAVE_SNPRINTF)
+ #define sa_snprintf snprintf
+ #else
+ static int sa_snprintf(char *str, size_t size, const char *fmt, ...)
+ {
+     va_list ap;
+     int rv;
+ 
+     va_start(ap, fmt);
+     rv = sa_vsnprintf(str, size, fmt, ap);
+     va_end(ap);
+     return rv;
+ }
+ #endif
+ 
+ sa_rc_t sa_u2a(sa_addr_t **saa, const char *uri, ...)
+ {
+     va_list ap;
+     int nPort;
+     socklen_t sl;
+     struct sockaddr *sa;
+     struct sockaddr_in sa4;
+ #ifdef AF_INET6
+     struct sockaddr_in6 sa6;
+ #endif
+     struct hostent *he;
+     struct servent *se;
+     struct protoent *pe;
+     int bNumeric;
+     int i;
+     char *cpProto;
+     int   nProto;
+     char *cpHost;
+     char *cpPort;
+     char uribuf[1024];
+     char *cp;
+     int sf;
+ 
+     /* argument sanity check */
+     if (saa == NULL || uri == NULL)
+         return SA_ERR_ARG;
+ 
+     /* on-the-fly create or just take over URI */
+     va_start(ap, uri);
+     sa_vsnprintf(uribuf, sizeof(uribuf), uri, ap);
+     va_end(ap);
+ 
+     /* parse URI into protocol, host and port parts */
+     uri = uribuf;
+     cpProto = "tcp";
+     if ((cp = strstr(uri, "://")) != NULL) {
+         cpProto = (char *)uri;
+         *cp = '\0';
+         uri = cp+3;
+     }
+     cpHost = (char *)uri;
+     if ((cp = strchr(uri, ':')) == NULL)
+         return SA_ERR_ARG;
+     *cp++ = '\0';
+     cpPort = cp;
+ 
+     /* resolve protocol */
+     if ((pe = getprotobyname(cpProto)) == NULL)
+         return SA_ERR_SYS;
+     nProto = pe->p_proto;
+ 
+     /* resolve port */
+     bNumeric = 1;
+     for (i = 0; cpPort[i] != '\0'; i++) {
+         if (!isdigit((int)cpPort[i])) {
+             bNumeric = 0;
+             break;
+         }
+     }
+     if (bNumeric)
+         nPort = atoi(cpPort);
+     else {
+         if ((se = getservbyname(cpPort, cpProto)) == NULL)
+             return SA_ERR_SYS;
+         nPort = ntohs(se->s_port);
+     }
+ 
+     /* mandatory(!) socket address structure initialization */
+     memset(&sa4, 0, sizeof(sa4));
+ #ifdef AF_INET6
+     memset(&sa6, 0, sizeof(sa6));
+ #endif
+ 
+     /* resolve host by trying to parse it as either directly a IPv4 or
+        IPv6 address or by resolving it to either a IPv4 or IPv6 address */
+     sa = NULL;
+     sl = 0;
+     sf = 0;
+     if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) {
+         sa4.sin_family = AF_INET;
+         sa4.sin_port = htons(nPort);
+         sa = (struct sockaddr *)&sa4;
+         sl = sizeof(sa4);
+         sf = AF_INET;
+     }
+ #ifdef AF_INET6
+     else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) {
+         sa6.sin6_family = AF_INET6;
+         sa6.sin6_port = htons(nPort);
+         sa = (struct sockaddr *)&sa6;
+         sl = sizeof(sa6);
+         sf = AF_INET6;
+     }
+ #endif
+     else if ((he = gethostbyname(cpHost)) != NULL) {
+         if (he->h_addrtype == AF_INET) {
+             sa4.sin_family = AF_INET;
+             sa4.sin_port = htons(nPort);
+             memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr));
+             sa = (struct sockaddr *)&sa4;
+             sl = sizeof(sa4);
+             sf = AF_INET;
+         }
+ #ifdef AF_INET6
+         else if (he->h_addrtype == AF_INET6) {
+             sa6.sin6_family = AF_INET6;
+             sa6.sin6_port = htons(nPort);
+             memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0], sizeof(sa6.sin6_addr.s6_addr));
+             sa = (struct sockaddr *)&sa6;
+             sl = sizeof(sa6);
+             sf = AF_INET6;
+         }
+ #endif
+     }
+     if (sa == NULL)
+         return SA_ERR_ARG;
+         
+     /* create result address structure */
+     if ((*saa = (sa_addr_t *)malloc(sizeof(sa_addr_t))) == NULL)
+         return SA_ERR_MEM;
+     if (((*saa)->saBuf = (struct sockaddr *)malloc(sl)) == NULL) {
+         free(*saa);
+         return SA_ERR_MEM;
+     }
+     memcpy((*saa)->saBuf, sa, sl);
+     (*saa)->slBuf = sl;
+     (*saa)->nFamily = sf;
+     (*saa)->nProto = nProto;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_s2a(sa_addr_t **saa, const struct sockaddr *sabuf, socklen_t salen)
+ {
+     struct sockaddr_in *sa4;
+ #ifdef AF_INET6
+     struct sockaddr_in6 *sa6;
+ #endif
+     struct protoent *pe;
+     int sf;
+ 
+     if (saa == NULL || sabuf == NULL || salen == 0)
+         return SA_ERR_ARG;
+ 
+     /* create result address structure */
+     if ((*saa = (sa_addr_t *)malloc(sizeof(sa_addr_t))) == NULL)
+         return SA_ERR_MEM;
+     if (((*saa)->saBuf = (struct sockaddr *)malloc(salen)) == NULL) {
+         free(*saa);
+         return SA_ERR_MEM;
+     }
+     memcpy((*saa)->saBuf, sabuf, salen);
+     (*saa)->slBuf = salen;
+ 
+     /* fill in family */
+     sf = 0;
+     if (sizeof(struct sockaddr_in) == salen) {
+         sa4 = (struct sockaddr_in *)((void *)sabuf);
+         if (sa4->sin_family == AF_INET)
+             sf = AF_INET;
+     }
+ #ifdef AF_INET6
+     else if (sizeof(struct sockaddr_in6) == salen) {
+         sa6 = (struct sockaddr_in6 *)((void *)sabuf);
+         if (sa6->sin6_family == AF_INET6)
+             sf = AF_INET6;
+     }
+ #endif
+     (*saa)->nFamily = sf;
+ 
+     /* fill in protocol */
+     if ((pe = getprotobyname("tcp")) != NULL)
+         (*saa)->nProto = pe->p_proto;
+     else
+         (*saa)->nProto = 0;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_a2u(const sa_addr_t *saa, char **uri)
+ {
+     char uribuf[1024];
+     struct protoent *pe;
+     struct sockaddr_in *sa4;
+ #ifdef AF_INET6
+     struct sockaddr_in6 *sa6;
+ #endif
+     char caHost[512];
+     int nPort;
+ 
+     if (saa == NULL || uri == NULL)
+         return SA_ERR_ARG;
+     if ((pe = getprotobynumber(saa->nProto)) == NULL)
+         return SA_ERR_SYS;
+     if (saa->nFamily == AF_INET) {
+         sa4 = (struct sockaddr_in *)((void *)saa->saBuf);
+         inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost));
+         nPort = ntohs(sa4->sin_port);
+     }
+ #ifdef AF_INET6
+     else if (saa->nFamily == AF_INET6) {
+         sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf);
+         inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost));
+         nPort = ntohs(sa6->sin6_port);
+     }
+ #endif
+     else
+         return SA_ERR_ARG;
+     sa_snprintf(uribuf, sizeof(uribuf), "%s://%s:%d", pe->p_name, caHost, nPort);
+     *uri = strdup(uribuf);
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_a2s(const sa_addr_t *saa, struct sockaddr **sabuf, socklen_t *salen)
+ {
+     if (saa == NULL || sabuf == NULL || salen == 0)
+         return SA_ERR_ARG;
+ 
+     if ((*sabuf = (struct sockaddr *)malloc(saa->slBuf)) == NULL)
+         return SA_ERR_MEM;
+     memmove(*sabuf, saa->saBuf, saa->slBuf);
+     *salen = saa->slBuf;
+     return SA_OK;
+ }
+ 
+ static sa_rc_t sa_socket_init(sa_t *sa, int family, int proto)
+ {
+     int type;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (proto == IPPROTO_TCP)
+         type = SOCK_STREAM;
+     else if (proto == IPPROTO_UDP)
+         type = SOCK_DGRAM;
+     else
+         return SA_ERR_ARG;
+     if (sa->sSocket != -1)
+         return SA_ERR_USE;
+     if ((sa->sSocket = socket(family, type, proto)) == -1)
+         return SA_ERR_SYS;
+     return SA_OK;
+ }
+ 
+ static sa_rc_t sa_socket_kill(sa_t *sa)
+ {
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (sa->sSocket != -1) {
+         close(sa->sSocket);
+         sa->sSocket = -1;
+     }
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_create(sa_t **sap)
+ {
+     sa_t *sa;
+ 
+     if ((sa = (sa_t *)malloc(sizeof(sa_t))) == NULL)
+         return SA_ERR_MEM;
+     sa->sSocket    = -1;
+     sa->bTimeout   = 0;
+     sa->nReadLen   = 0;
+     sa->nReadSize  = 1024;
+     if ((sa->cpReadBuf = (char *)malloc(sa->nReadSize)) == NULL) {
+         free(sa);
+         return SA_ERR_MEM;
+     }
+     sa->nWriteLen  = 0;
+     sa->nWriteSize = 1024;
+     if ((sa->cpWriteBuf = (char *)malloc(sa->nWriteSize)) == NULL) {
+         free(sa->cpReadBuf);
+         free(sa);
+         return SA_ERR_MEM;
+     }
+     *sap = sa;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_destroy(sa_t *sa)
+ {
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     sa_socket_kill(sa);
+     if (sa->cpReadBuf != NULL)
+         free(sa->cpReadBuf);
+     if (sa->cpWriteBuf != NULL)
+         free(sa->cpWriteBuf);
+     free(sa);
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_timeout(sa_t *sa, long sec, long usec)
+ {
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (sec == 0 && usec == 0) {
+         sa->bTimeout = 0;
+         sa->tvTimeout.tv_sec  = 0;
+         sa->tvTimeout.tv_usec = 0;
+     }
+     else {
+         sa->bTimeout = 1;
+         sa->tvTimeout.tv_sec  = sec;
+         sa->tvTimeout.tv_usec = usec;
+     }
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_buffers(sa_t *sa, size_t rsize, size_t wsize)
+ {
+     char *cp;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (sa->nReadLen > rsize || sa->nWriteLen > wsize)
+         return SA_ERR_ARG;
+     if ((cp = (char *)realloc(sa->cpReadBuf, rsize)) == NULL)
+         return SA_ERR_SYS;
+     sa->cpReadBuf = cp;
+     sa->nReadSize  = rsize;
+     if ((cp = (char *)realloc(sa->cpWriteBuf, wsize)) == NULL)
+         return SA_ERR_SYS;
+     sa->cpWriteBuf = cp;
+     sa->nWriteSize = wsize;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_bind(sa_t *sa, sa_addr_t *laddr)
+ {
+     sa_rc_t rv;
+ 
+     if (sa == NULL || laddr == NULL)
+         return SA_ERR_ARG;
+     if (sa->sSocket == -1)
+         if ((rv = sa_socket_init(sa, laddr->nFamily, laddr->nProto)) != SA_OK)
+             return rv;
+     if (bind(sa->sSocket, laddr->saBuf, laddr->slBuf) == -1)
+         return SA_ERR_SYS;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_connect(sa_t *sa, sa_addr_t *raddr)
+ {
+     int flags, n, error;
+     fd_set rset, wset;
+     socklen_t len;
+     sa_rc_t rv;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+ 
+     if (sa->sSocket == -1)
+         if ((rv = sa_socket_init(sa, raddr->nFamily, raddr->nProto)) != SA_OK)
+             return rv;
+ 
+     if (!sa->bTimeout)
+         return connect(sa->sSocket, raddr->saBuf, raddr->slBuf);
+ 
+     error = 0;
+     rv = SA_OK;
+ 
+     /* remember socket flags */
+     flags = fcntl(sa->sSocket, F_GETFL, 0);
+ 
+     /* switch to non-blocking mode */
+     fcntl(sa->sSocket, F_SETFL, flags|O_NONBLOCK);
+ 
+     /* perform the connect */
+     if ((n = connect(sa->sSocket, raddr->saBuf, raddr->slBuf)) < 0) {
+         if (errno != EINPROGRESS) {
+             error = errno;
+             goto done;
+         }
+     }
+ 
+     /* if connect completed immediately */
+     if (n == 0)
+         goto done; 
+ 
+     /* wait for read or write possibility */
+     FD_ZERO(&rset);
+     FD_ZERO(&wset);
+     FD_SET(sa->sSocket, &rset);
+     FD_SET(sa->sSocket, &wset);
+     do {
+         n = select(sa->sSocket+1, &rset, &wset, NULL, &sa->tvTimeout);
+     } while (n == -1 && errno == EINTR);
+ 
+     /* decide on return semantic */
+     if (n < 0) {
+         error = errno;
+         goto done;
+     }
+     else if (n == 0) {
+         error = ETIMEDOUT;
+         goto done;
+     }
+ 
+     /* fetch pending error */
+     len = sizeof(error);
+     if (getsockopt(sa->sSocket, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+         error = errno;
+ 
+     done:
+ 
+     /* reset socket flags */
+     fcntl(sa->sSocket, F_SETFL, flags);
+ 
+     /* optionally set errno */
+     if (error != 0) {
+         errno = error;
+         rv = SA_ERR_SYS;
+     }
+ 
+     return rv;
+ }
+ 
+ sa_rc_t sa_listen(sa_t *sa, int backlog)
+ {
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (sa->sSocket == -1)
+         /* at least sa_bind() has to be already performed */
+         return SA_ERR_USE;
+     if (listen(sa->sSocket, backlog) == -1)
+         return SA_ERR_SYS;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_accept(sa_t *sa, sa_addr_t **caddr, sa_t **csa)
+ {
+     sa_rc_t rv;
+     int n;
+     fd_set fds;
+     union {
+         struct sockaddr_in sa4;
+ #ifdef AF_INET6
+         struct sockaddr_in6 sa6;
+ #endif
+     } sa_buf;
+     socklen_t sa_len;
+     int s;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     if (sa->sSocket == -1)
+         /* at least sa_listen() has to be already performed */
+         return SA_ERR_USE;
+     if (sa->bTimeout) {
+         FD_ZERO(&fds);
+         FD_SET(sa->sSocket, &fds);
+         do {
+             n = select(sa->sSocket+1, &fds, NULL, NULL, &sa->tvTimeout);
+         } while (n == -1 && errno == EINTR);
+         if (n == 0) 
+             errno = ETIMEDOUT;
+         if (n <= 0)
+             return SA_ERR_SYS;
+     }
+     sa_len = sizeof(sa_buf);
+     if ((s = accept(sa->sSocket, (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+         return SA_ERR_SYS;
+     if ((rv = sa_s2a(caddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK)
+         return rv;
+     if ((rv = sa_create(csa)) != SA_OK) {
+         free(*caddr);
+         return rv;
+     }
+     (*csa)->sSocket = s;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_getremote(sa_t *sa, sa_addr_t **raddr)
+ {
+     sa_rc_t rv;
+     union {
+         struct sockaddr_in sa4;
+ #ifdef AF_INET6
+         struct sockaddr_in6 sa6;
+ #endif
+     } sa_buf;
+     socklen_t sa_len;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     sa_len = sizeof(sa_buf);
+     if (getpeername(sa->sSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
+         return SA_ERR_SYS;
+     if ((rv = sa_s2a(raddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK)
+         return rv;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_getlocal(sa_t *sa, sa_addr_t **laddr)
+ {
+     sa_rc_t rv;
+     union {
+         struct sockaddr_in sa4;
+ #ifdef AF_INET6
+         struct sockaddr_in6 sa6;
+ #endif
+     } sa_buf;
+     socklen_t sa_len;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     sa_len = sizeof(sa_buf);
+     if (getsockname(sa->sSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
+         return SA_ERR_SYS;
+     if ((rv = sa_s2a(laddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK)
+         return rv;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_getfd(sa_t *sa, int *fd)
+ {
+     if (sa == NULL || fd == NULL)
+         return SA_ERR_ARG;
+     *fd = sa->sSocket;
+     return SA_OK;
+ }
+ 
+ static int sa_read_raw(sa_t *sa, char *cpBuf, int nBufLen)
+ {
+     int rv;
+     fd_set fds;
+ 
+     if (sa->bTimeout) {
+         FD_ZERO(&fds);
+         FD_SET(sa->sSocket, &fds);
+         do {
+             rv = select(sa->sSocket+1, &fds, NULL, NULL, &sa->tvTimeout);
+         } while (rv == -1 && errno == EINTR);
+         if (rv == 0) {
+             errno = ETIMEDOUT;
+             return -1;
+         }
+     }
+     do {
+         rv = read(sa->sSocket, cpBuf, nBufLen);
+     } while (rv == -1 && errno == EINTR);
+     return rv;
+ }
+ 
+ sa_rc_t sa_read(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes)
+ {
+     int n;
+     int rv;
+     size_t res;
+ 
+     if (sa == NULL || cpBuf == NULL || nBufReq == 0)
+         return 0;
+     
+     /* flush write buffer */
+     if (sa->nWriteLen > 0)
+         sa_flush(sa);
+     rv = SA_OK;
+     res = 0;
+     while (1) {
+         if (nBufReq <= sa->nReadLen) {
+             /* buffer holds enough data, so use this */
+             memmove(cpBuf, sa->cpReadBuf, nBufReq);
+             memmove(sa->cpReadBuf, sa->cpReadBuf+nBufReq, sa->nReadLen-nBufReq);
+             sa->nReadLen -= nBufReq;
+             res += nBufReq;
+         }
+         else {
+             if (sa->nReadLen > 0) {
+                 /* fetch already existing buffer contents as a start */
+                 memmove(cpBuf, sa->cpReadBuf, sa->nReadLen);
+                 nBufReq -= sa->nReadLen;
+                 cpBuf   += sa->nReadLen;
+                 res     += sa->nReadLen;
+                 sa->nReadLen = 0;
+             }
+             if (nBufReq >= sa->nReadSize) {
+                 /* buffer is too small at all, so read directly */
+                 n = sa_read_raw(sa, cpBuf, nBufReq);
+                 if (n > 0)
+                     res += n;
+                 else if (n <= 0)
+                     rv = SA_ERR_SYS;
+             }
+             else {
+                 /* fill buffer with new data */
+                 n = sa_read_raw(sa, sa->cpReadBuf, sa->nReadSize);
+                 if (n <= 0)
+                     rv = SA_ERR_SYS;
+                 else {
+                     sa->nReadLen = n;
+                     continue;
+                 }
+             }
+         }
+         break;
+     }
+     if (nBufRes != NULL)
+         *nBufRes = res;
+     return rv;
+ }
+ 
+ sa_rc_t sa_readfrom(sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t **raddr)
+ {
+     sa_rc_t rv;
+     union {
+         struct sockaddr_in sa4;
+ #ifdef AF_INET6
+         struct sockaddr_in6 sa6;
+ #endif
+     } sa_buf;
+     socklen_t sa_len;
+     size_t n;
+     fd_set fds;
+ 
+     if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
+         return SA_ERR_ARG;
+     if (sa->bTimeout) {
+         FD_ZERO(&fds);
+         FD_SET(sa->sSocket, &fds);
+         do {
+             n = select(sa->sSocket+1, &fds, NULL, NULL, &sa->tvTimeout);
+         } while (n == -1 && errno == EINTR);
+         if (n == 0) 
+             errno = ETIMEDOUT;
+         if (n <= 0)
+             return SA_ERR_SYS;
+     }
+     sa_len = sizeof(sa_buf);
+     if ((n = recvfrom(sa->sSocket, buf, buflen, 0, (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+         return SA_ERR_SYS;
+     if ((rv = sa_s2a(raddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK)
+         return rv;
+     if (bufdone != NULL)
+         *bufdone = n;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_readline(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes)
+ {
+     char c;
+     size_t n;
+     size_t res;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     res = 0;
+     while (res < (nBufReq-1)) {
+         sa_read(sa, &c, 1, &n);
+         if (n <= 0)
+             break;
+         cpBuf[res++] = c;
+         if (c == '\n')
+             break;
+     }
+     cpBuf[res] = '\0';
+     if (nBufRes != NULL)
+         *nBufRes = res;
+     return SA_OK;
+ }
+ 
+ static int sa_write_raw(sa_t *sa, const char *cpBuf, int nBufLen)
+ {
+     int rv;
+     fd_set fds;
+ 
+     if (sa->bTimeout) {
+         FD_ZERO(&fds);
+         FD_SET(sa->sSocket, &fds);
+         do {
+             rv = select(sa->sSocket+1, NULL, &fds, NULL, &sa->tvTimeout);
+         } while (rv == -1 && errno == EINTR);
+         if (rv == 0) {
+             errno = ETIMEDOUT;
+             return -1;
+         }
+     }
+     do {
+         rv = write(sa->sSocket, cpBuf, nBufLen);
+     } while (rv == -1 && errno == EINTR);
+     return rv;
+ }
+ 
+ sa_rc_t sa_write(sa_t *sa, const char *cpBuf, size_t nBufReq, size_t *nBufRes)
+ {
+     size_t n;
+     size_t res;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+ 
+     if (nBufReq > (sa->nWriteSize - sa->nWriteLen)) {
+         /* not enough space in buffer, so flush buffer */
+         sa_flush(sa);
+     }
+     res = 0;
+     if (nBufReq >= sa->nWriteSize) {
+         /* buffer too small at all, so write immediately */
+         while (nBufReq > 0) {
+             n = sa_write_raw(sa, cpBuf, nBufReq);
+             if (n <= 0)
+                 break;
+             nBufReq  -= n;
+             cpBuf    += n;
+             res      += n;
+         }
+     }
+     else {
+         /* (again) enough sprace in buffer, so store data */
+         memmove(sa->cpWriteBuf+sa->nWriteLen, cpBuf, nBufReq);
+         sa->nWriteLen += nBufReq;
+         res = nBufReq;
+     }
+     if (nBufRes != NULL)
+         *nBufRes = res;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_writeto(sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *raddr)
+ {
+     size_t n;
+     fd_set fds;
+ 
+     if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
+         return SA_ERR_ARG;
+     if (sa->bTimeout) {
+         FD_ZERO(&fds);
+         FD_SET(sa->sSocket, &fds);
+         do {
+             n = select(sa->sSocket+1, NULL, &fds, NULL, &sa->tvTimeout);
+         } while (n == -1 && errno == EINTR);
+         if (n == 0) 
+             errno = ETIMEDOUT;
+         if (n <= 0)
+             return SA_ERR_SYS;
+     }
+     if ((n = sendto(sa->sSocket, buf, buflen, 0, raddr->saBuf, raddr->slBuf)) == -1)
+         return SA_ERR_SYS;
+     if (bufdone != NULL)
+         *bufdone = n;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_printf(sa_t *sa, const char *cpFmt, ...)
+ {
+     va_list ap;
+     size_t n;
+     char caBuf[1024];
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     va_start(ap, cpFmt);
+     n = sa_vsnprintf(caBuf, sizeof(caBuf), cpFmt, ap);
+     sa_write(sa, caBuf, n, &n);
+     va_end(ap);
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_flush(sa_t *sa)
+ {
+     size_t n;
+ 
+     if (sa == NULL)
+         return SA_ERR_ARG;
+     while (sa->nWriteLen > 0) {
+         n = sa_write_raw(sa, sa->cpWriteBuf, sa->nWriteLen);
+         if (n <= 0)
+             break;
+         memmove(sa->cpWriteBuf, sa->cpWriteBuf+n, sa->nWriteLen-n);
+         sa->nWriteLen -= n;
+     }
+     sa->nWriteLen = 0;
+     return SA_OK;
+ }
+ 
+ sa_rc_t sa_shutdown(sa_t *sa, char *flags)
+ {
+     int how;
+ 
+     if (sa == NULL || flags == NULL)
+         return SA_ERR_ARG;
+     how = 0;
+     if (strcmp(flags, "r") == 0)
+         how = SHUT_RD;
+     else if (strcmp(flags, "w") == 0)
+         how = SHUT_WR;
+     else if (strcmp(flags, "rw") == 0)
+         how = SHUT_RDWR;
+     if (shutdown(sa->sSocket, how) == -1)
+         return SA_ERR_SYS;
+     return SA_OK;
+ }
+ 

CVSTrac 2.0.1