=> Building www/kannel Started : Thursday, 7 MAR 2019 at 13:58:47 UTC Platform: 5.5-DEVELOPMENT DragonFly v5.5.0.192.g15ae7f0-DEVELOPMENT #34: Tue Feb 19 09:07:07 PST 2019 root@pkgbox64.dragonflybsd.org:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 -------------------------------------------------- -- Environment -------------------------------------------------- UNAME_r=5.5-SYNTH UNAME_m=x86_64 UNAME_p=x86_64 UNAME_v=DragonFly 5.5-SYNTH UNAME_s=DragonFly PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin SSL_NO_VERIFY_PEER=1 TERM=dumb PKG_CACHEDIR=/var/cache/pkg8 PKG_DBDIR=/var/db/pkg8 PORTSDIR=/xports LANG=C HOME=/root USER=root -------------------------------------------------- -- Options -------------------------------------------------- ===> The following configuration options are available for kannel-1.4.4_8,1: MYSQL=on: MySQL database support PGSQL=off: PostgreSQL database support SQLITE3=off: SQLite 3 database support ===> Use 'make config' to modify these settings -------------------------------------------------- -- CONFIGURE_ENV -------------------------------------------------- MAKE=gmake XDG_DATA_HOME=/construction/www/kannel XDG_CONFIG_HOME=/construction/www/kannel HOME=/construction/www/kannel TMPDIR="/tmp" PATH=/construction/www/kannel/.bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin SHELL=/bin/sh CONFIG_SHELL=/bin/sh CCVER=gcc80 LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 CONFIG_SITE=/xports/Templates/config.site lt_cv_sys_max_cmd_len=262144 -------------------------------------------------- -- CONFIGURE_ARGS -------------------------------------------------- --enable-pcre=yes --enable-docs=no --with-malloc=native --enable-start-stop-daemon=no --with-mysql --without-pgsql --without-sqlite3 --prefix=/usr/local ${_LATE_CONFIGURE_ARGS} -------------------------------------------------- -- MAKE_ENV -------------------------------------------------- OPENSSLBASE=/usr/local OPENSSLDIR=/usr/local/openssl OPENSSLINC=/usr/local/include OPENSSLLIB=/usr/local/lib OPENSSLRPATH=/usr/local/lib XDG_DATA_HOME=/construction/www/kannel XDG_CONFIG_HOME=/construction/www/kannel HOME=/construction/www/kannel TMPDIR="/tmp" PATH=/construction/www/kannel/.bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin NO_PIE=yes MK_DEBUG_FILES=no MK_KERNEL_SYMBOLS=no SHELL=/bin/sh NO_LINT=YES CCVER=gcc80 LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 PREFIX=/usr/local LOCALBASE=/usr/local NOPROFILE=1 CC="gcc" CFLAGS="-pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing " CPP="cpp" CPPFLAGS="-DLIBICONV_PLUG" LDFLAGS=" -Wl,-rpath,/usr/local/lib " LIBS="" CXX="g++" CXXFLAGS=" -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -DLIBICONV_PLUG " MANPREFIX="/usr/local" BSD_INSTALL_PROGRAM="install -s -m 555" BSD_INSTALL_LIB="install -s -m 0644" BSD_INSTALL_SCRIPT="install -m 555" BSD_INSTALL_DATA="install -m 0644" BSD_INSTALL_MAN="install -m 444" -------------------------------------------------- -- MAKE_ARGS -------------------------------------------------- DESTDIR=/construction/www/kannel/stage -------------------------------------------------- -- PLIST_SUB -------------------------------------------------- GTK2_VERSION="2.10.0" GTK3_VERSION="3.0.0" OSREL=5.5 PREFIX=%D LOCALBASE=/usr/local RESETPREFIX=/usr/local LIB32DIR=lib PROFILE="@comment " DOCSDIR="share/doc/kannel" EXAMPLESDIR="share/examples/kannel" DATADIR="share/kannel" WWWDIR="www/kannel" ETCDIR="etc/kannel" -------------------------------------------------- -- SUB_LIST -------------------------------------------------- PREFIX=/usr/local LOCALBASE=/usr/local DATADIR=/usr/local/share/kannel DOCSDIR=/usr/local/share/doc/kannel EXAMPLESDIR=/usr/local/share/examples/kannel WWWDIR=/usr/local/www/kannel ETCDIR=/usr/local/etc/kannel -------------------------------------------------- -- /etc/make.conf -------------------------------------------------- SYNTHPROFILE=Release-BE USE_PACKAGE_DEPENDS_ONLY=yes PACKAGE_BUILDING=yes BATCH=yes PKG_CREATE_VERBOSE=yes PORTSDIR=/xports DISTDIR=/distfiles WRKDIRPREFIX=/construction PORT_DBDIR=/options PACKAGES=/packages MAKE_JOBS_NUMBER_LIMIT=5 LICENSES_ACCEPTED= NONE HAVE_COMPAT_IA32_KERN= CONFIGURE_MAX_CMD_LEN=262144 _PERL5_FROM_BIN=5.26.2 _ALTCCVERSION_921dbbb2=none _OBJC_ALTCCVERSION_921dbbb2=none _SMP_CPUS=8 UID=0 ARCH=x86_64 OPSYS=DragonFly DFLYVERSION=500500 OSVERSION=9999999 OSREL=5.5 _OSRELEASE=5.5-SYNTH PYTHONBASE=/usr/local _PKG_CHECKED=1 -------------------------------------------------------------------------------- -- Phase: check-sanity -------------------------------------------------------------------------------- ===> License The_Kannel_Software_License accepted by the user -------------------------------------------------------------------------------- -- Phase: pkg-depends -------------------------------------------------------------------------------- ===> kannel-1.4.4_8,1 depends on file: /usr/local/sbin/pkg - not found ===> Installing existing package /packages/All/pkg-1.10.5_5.txz Installing pkg-1.10.5_5... Extracting pkg-1.10.5_5: .......... done ===> kannel-1.4.4_8,1 depends on file: /usr/local/sbin/pkg - found ===> Returning to build of kannel-1.4.4_8,1 -------------------------------------------------------------------------------- -- Phase: fetch-depends -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Phase: fetch -------------------------------------------------------------------------------- ===> License The_Kannel_Software_License accepted by the user ===> Fetching all distfiles required by kannel-1.4.4_8,1 for building -------------------------------------------------------------------------------- -- Phase: checksum -------------------------------------------------------------------------------- ===> License The_Kannel_Software_License accepted by the user ===> Fetching all distfiles required by kannel-1.4.4_8,1 for building => SHA256 Checksum OK for gateway-1.4.4.tar.bz2. -------------------------------------------------------------------------------- -- Phase: extract-depends -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Phase: extract -------------------------------------------------------------------------------- ===> License The_Kannel_Software_License accepted by the user ===> Fetching all distfiles required by kannel-1.4.4_8,1 for building ===> Extracting for kannel-1.4.4_8,1 => SHA256 Checksum OK for gateway-1.4.4.tar.bz2. -------------------------------------------------------------------------------- -- Phase: patch-depends -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Phase: patch -------------------------------------------------------------------------------- ===> Patching for kannel-1.4.4_8,1 ===> Applying ports patches for kannel-1.4.4_8,1 -------------------------------------------------------------------------------- -- Phase: build-depends -------------------------------------------------------------------------------- ===> kannel-1.4.4_8,1 depends on executable: gmake - not found ===> Installing existing package /packages/All/gmake-4.2.1_3.txz Installing gmake-4.2.1_3... `-- Installing gettext-runtime-0.19.8.1_2... | `-- Installing indexinfo-0.3.1... | `-- Extracting indexinfo-0.3.1: .... done `-- Extracting gettext-runtime-0.19.8.1_2: .......... done Extracting gmake-4.2.1_3: .......... done ===> kannel-1.4.4_8,1 depends on executable: gmake - found ===> Returning to build of kannel-1.4.4_8,1 ===> kannel-1.4.4_8,1 depends on file: /usr/local/lib/libcrypto.so.44 - not found ===> Installing existing package /packages/All/libressl-2.8.3.txz Installing libressl-2.8.3... Extracting libressl-2.8.3: .......... done ===> kannel-1.4.4_8,1 depends on file: /usr/local/lib/libcrypto.so.44 - found ===> Returning to build of kannel-1.4.4_8,1 -------------------------------------------------------------------------------- -- Phase: lib-depends -------------------------------------------------------------------------------- ===> kannel-1.4.4_8,1 depends on shared library: libpcre.so - not found ===> Installing existing package /packages/All/pcre-8.42_1.txz Installing pcre-8.42_1... Extracting pcre-8.42_1: .......... done ===> kannel-1.4.4_8,1 depends on shared library: libpcre.so - found (/usr/local/lib/libpcre.so) ===> Returning to build of kannel-1.4.4_8,1 ===> kannel-1.4.4_8,1 depends on shared library: libmysqlclient.so.18 - not found ===> Installing existing package /packages/All/mysql56-client-5.6.43.txz Installing mysql56-client-5.6.43... `-- Installing libedit-3.1.20181209_2,1... | `-- Installing ncurses-6.1.20190112... | `-- Extracting ncurses-6.1.20190112: .......... done `-- Extracting libedit-3.1.20181209_2,1: .......... done `-- Installing libevent-2.1.8_2... `-- Extracting libevent-2.1.8_2: .......... done `-- Installing liblz4-1.8.3,1... `-- Extracting liblz4-1.8.3,1: .......... done `-- Installing perl5-5.28.1... `-- Extracting perl5-5.28.1: .......... done Extracting mysql56-client-5.6.43: .......... done Message from perl5-5.28.1: The /usr/bin/perl symlink has been removed starting with Perl 5.20. For shebangs, you should either use: #!/usr/local/bin/perl or #!/usr/bin/env perl The first one will only work if you have a /usr/local/bin/perl, the second will work as long as perl is in PATH. Message from mysql56-client-5.6.43: * * * * * * * * * * * * * * * * * * * * * * * * Please be aware the database client is vulnerable to CVE-2015-3152 - SSL Downgrade aka "BACKRONYM". You may find more information at the following URL: http://www.vuxml.org/freebsd/36bd352d-299b-11e5-86ff-14dae9d210b8.html Although this database client is not listed as "affected", it is vulnerable and will not be receiving a patch. Please take note of this when deploying this software. * * * * * * * * * * * * * * * * * * * * * * * * ===> kannel-1.4.4_8,1 depends on shared library: libmysqlclient.so.18 - found (/usr/local/lib/mysql/libmysqlclient.so.18) ===> Returning to build of kannel-1.4.4_8,1 ===> kannel-1.4.4_8,1 depends on shared library: libxml2.so - not found ===> Installing existing package /packages/All/libxml2-2.9.8.txz Installing libxml2-2.9.8... Extracting libxml2-2.9.8: .......... done ===> kannel-1.4.4_8,1 depends on shared library: libxml2.so - found (/usr/local/lib/libxml2.so) ===> Returning to build of kannel-1.4.4_8,1 -------------------------------------------------------------------------------- -- Phase: configure -------------------------------------------------------------------------------- ===> Configuring for kannel-1.4.4_8,1 configure: loading site script /xports/Templates/config.site Configuring for Kannel gateway version 1.4.4 ... Running system checks ... checking build system type... x86_64-portbld-dragonfly5.5 checking host system type... x86_64-portbld-dragonfly5.5 checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for gcc option to accept ISO C99... none needed checking for a BSD-compatible install... /usr/bin/install -c checking for ranlib... ranlib checking for bison... no checking for byacc... byacc checking for flex... flex checking lex output file root... lex.yy checking lex library... -lfl checking whether yytext is a pointer... yes checking for ar... ar checking for convert... no checking for perl... /usr/local/bin/perl checking for inline... inline checking for special C compiler options needed for large files... no checking for _FILE_OFFSET_BITS value needed for large files... no checking how to run the C preprocessor... cpp checking for grep that handles long lines and -e... (cached) /usr/bin/grep checking for egrep... (cached) /usr/bin/egrep checking for ANSI C header files... (cached) yes checking for sys/types.h... (cached) yes checking for sys/stat.h... (cached) yes checking for stdlib.h... (cached) yes checking for string.h... (cached) yes checking for memory.h... (cached) yes checking for strings.h... (cached) yes checking for inttypes.h... (cached) yes checking for stdint.h... (cached) yes checking for unistd.h... (cached) yes checking size of short... 2 checking size of int... 4 checking size of long... 8 checking size of long long... 8 checking for log in -lm... yes checking for accept in -lsocket... no checking for inet_ntoa in -lnsl... no checking for inet_ntop in -lresolv... no checking for inet_ntop in -lbind... no checking for pthread_exit in -lpthread... yes checking for ANSI C header files... (cached) yes checking for sys/ioctl.h... (cached) yes checking for sys/time.h... (cached) yes checking for sys/types.h... (cached) yes checking for unistd.h... (cached) yes checking for sys/poll.h... (cached) yes checking for pthread.h... (cached) yes checking for getopt.h... (cached) yes checking syslog.h usability... yes checking syslog.h presence... yes checking for syslog.h... yes checking for zlib.h... (cached) yes checking execinfo.h usability... yes checking execinfo.h presence... yes checking for execinfo.h... yes checking for stdlib.h... (cached) yes checking for sys/socket.h... (cached) yes checking sys/sockio.h usability... yes checking sys/sockio.h presence... yes checking for sys/sockio.h... yes checking for netinet/in.h... (cached) yes checking for net/if.h... (cached) yes checking sys/ucontext.h usability... yes checking sys/ucontext.h presence... yes checking for sys/ucontext.h... yes checking for ld used by gcc... /usr/bin/ld checking if the linker (/usr/bin/ld) is GNU ld... yes checking for shared library run path origin... done checking for iconv... yes checking for working iconv... yes checking for iconv declaration... extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); checking for gettimeofday... (cached) yes checking for select... (cached) yes checking for socket... yes checking for strdup... (cached) yes checking for getopt_long... yes checking for localtime_r... yes checking for gmtime_r... yes checking for backtrace... no checking for srandom... (cached) yes checking for initgroups... yes checking for strtoll... (cached) yes checking for strtoq... yes checking for getopt... (cached) yes checking for gethostbyname_r... yes checking for which type of gethostbyname_r... 6 checking for socklen_t in ... yes checking for getopt in ... no checking for getopt in ... yes checking ftw.h usability... yes checking ftw.h presence... yes checking for ftw.h... yes checking for nftw... yes checking regex.h usability... yes checking regex.h presence... yes checking for regex.h... yes checking for regcomp... yes Checking for POSIX threads support ... checking for working pthreads... yes checking for pthread_spinlock support... yes checking for pthread_rwlock support... yes checking for sem_init in -lrt... yes checking for semaphore support... yes Checking for libxml2 support ... checking for xml2-config... /usr/local/bin/xml2-config checking libxml version... 2.9.8 Configuring for PCRE support ... checking whether to compile with PCRE support... searching checking for pcre-config... /usr/local/bin/pcre-config checking PCRE version... 8.42 checking for POSIX regex provider... PCRE library checking pcreposix.h usability... yes checking pcreposix.h presence... no configure: WARNING: pcreposix.h: accepted by the compiler, rejected by the preprocessor! configure: WARNING: pcreposix.h: proceeding with the compiler's result checking for pcreposix.h... yes checking for regcomp in -lpcreposix... yes checking pcre.h usability... yes checking pcre.h presence... no configure: WARNING: pcre.h: accepted by the compiler, rejected by the preprocessor! configure: WARNING: pcre.h: proceeding with the compiler's result checking for pcre.h... yes checking for pcre_compile... yes Configuring DocBook support ... checking for jade... no checking for openjade... no checking for jadetex... no checking for pdfjadetex... no checking for dvips... no checking for fig2dev... no checking for convert... no checking for /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl... no checking for /usr/lib/sgml/stylesheets/nwalsh-modular/html/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets-1.*/html/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets/html/docbook.dsl... no checking for /usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl/modular/html/docbook.dsl... no checking for /usr/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl... no checking for /usr/share/dsssl/docbook-dsssl/html/docbook.dsl... no checking for /usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl... no checking for /usr/local/lib/sgml/stylesheets/nwalsh-modular/html/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets-1.*/html/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets/html/docbook.dsl... no checking for /usr/local/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl... no checking for /usr/local/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl... no checking for /usr/local/share/dsssl/docbook-dsssl/html/docbook.dsl... no checking for /sw/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl... no checking for /sw/lib/sgml/stylesheets/nwalsh-modular/html/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets-1.*/html/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets/html/docbook.dsl... no checking for /sw/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl/modular/html/docbook.dsl... no checking for /sw/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl... no checking for /sw/share/dsssl/docbook-dsssl/html/docbook.dsl... no checking for /opt/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl... no checking for /opt/local/lib/sgml/stylesheets/nwalsh-modular/html/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets-1.*/html/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets/html/docbook.dsl... no checking for /opt/local/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl... no checking for /opt/local/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl... no checking for /opt/local/share/dsssl/docbook-dsssl/html/docbook.dsl... no checking for /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl... no checking for /usr/lib/sgml/stylesheets/nwalsh-modular/print/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets-1.*/print/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets/print/docbook.dsl... no checking for /usr/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl... no checking for /usr/share/sgml/docbook/dsssl/modular/print/docbook.dsl... no checking for /usr/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl... no checking for /usr/share/dsssl/docbook-dsssl/print/docbook.dsl... no checking for /usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl... no checking for /usr/local/lib/sgml/stylesheets/nwalsh-modular/print/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets-1.*/print/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets/print/docbook.dsl... no checking for /usr/local/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl... no checking for /usr/local/share/sgml/docbook/dsssl/modular/print/docbook.dsl... no checking for /usr/local/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl... no checking for /usr/local/share/dsssl/docbook-dsssl/print/docbook.dsl... no checking for /sw/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl... no checking for /sw/lib/sgml/stylesheets/nwalsh-modular/print/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets-1.*/print/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets/print/docbook.dsl... no checking for /sw/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl... no checking for /sw/share/sgml/docbook/dsssl/modular/print/docbook.dsl... no checking for /sw/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl... no checking for /sw/share/dsssl/docbook-dsssl/print/docbook.dsl... no checking for /opt/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl... no checking for /opt/local/lib/sgml/stylesheets/nwalsh-modular/print/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets-1.*/print/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets/print/docbook.dsl... no checking for /opt/local/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl... no checking for /opt/local/share/sgml/docbook/dsssl/modular/print/docbook.dsl... no checking for /opt/local/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl... no checking for /opt/local/share/dsssl/docbook-dsssl/print/docbook.dsl... no checking for /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/dtds/decls/xml.dcl... no checking for /usr/lib/sgml/stylesheets/nwalsh-modular/dtds/decls/xml.dcl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets-1.*/dtds/decls/xml.dcl... no checking for /usr/share/sgml/docbook/dsssl-stylesheets/dtds/decls/xml.dcl... no checking for /usr/share/sgml/docbook/stylesheet/dsssl/modular/dtds/decls/xml.dcl... no checking for /usr/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl... no checking for /usr/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl... no checking for /usr/share/dsssl/docbook-dsssl/dtds/decls/xml.dcl... no checking for /usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/dtds/decls/xml.dcl... no checking for /usr/local/lib/sgml/stylesheets/nwalsh-modular/dtds/decls/xml.dcl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets-1.*/dtds/decls/xml.dcl... no checking for /usr/local/share/sgml/docbook/dsssl-stylesheets/dtds/decls/xml.dcl... no checking for /usr/local/share/sgml/docbook/stylesheet/dsssl/modular/dtds/decls/xml.dcl... no checking for /usr/local/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl... no checking for /usr/local/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl... no checking for /usr/local/share/dsssl/docbook-dsssl/dtds/decls/xml.dcl... no checking for /sw/lib/sgml/stylesheet/dsssl/docbook/nwalsh/dtds/decls/xml.dcl... no checking for /sw/lib/sgml/stylesheets/nwalsh-modular/dtds/decls/xml.dcl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets-1.*/dtds/decls/xml.dcl... no checking for /sw/share/sgml/docbook/dsssl-stylesheets/dtds/decls/xml.dcl... no checking for /sw/share/sgml/docbook/stylesheet/dsssl/modular/dtds/decls/xml.dcl... no checking for /sw/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl... no checking for /sw/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl... no checking for /sw/share/dsssl/docbook-dsssl/dtds/decls/xml.dcl... no checking for /opt/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh/dtds/decls/xml.dcl... no checking for /opt/local/lib/sgml/stylesheets/nwalsh-modular/dtds/decls/xml.dcl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets-1.*/dtds/decls/xml.dcl... no checking for /opt/local/share/sgml/docbook/dsssl-stylesheets/dtds/decls/xml.dcl... no checking for /opt/local/share/sgml/docbook/stylesheet/dsssl/modular/dtds/decls/xml.dcl... no checking for /opt/local/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl... no checking for /opt/local/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl... no checking for /opt/local/share/dsssl/docbook-dsssl/dtds/decls/xml.dcl... no Not building documentation. Configuring parameters ... checking which malloc to use... native malloc enabling local time enabling cookies enabling HTTP/1.1 keep-alive Configuring OpenSSL support ... checking whether to compile with SSL support... trying /usr/include/openssl Configuring DB support ... checking whether to compile with MySQL support... searching checking for mysql_config... /usr/local/bin/mysql_config checking mysql version... 5.6.43 -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto checking mysql reentrant libs... -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto checking for mysql_init in -lmysqlclient_r... yes checking mysql includes... -I/usr/local/include/mysql checking mysql/mysql.h usability... -I/usr/local/include/mysql yes checking mysql/mysql.h presence... no configure: WARNING: mysql/mysql.h: accepted by the compiler, rejected by the preprocessor! configure: WARNING: mysql/mysql.h: proceeding with the compiler's result checking for mysql/mysql.h... yes checking mysql/mysql_version.h usability... yes checking mysql/mysql_version.h presence... no configure: WARNING: mysql/mysql_version.h: accepted by the compiler, rejected by the preprocessor! configure: WARNING: mysql/mysql_version.h: proceeding with the compiler's result checking for mysql/mysql_version.h... yes checking for mysql_stmt_init in -lmysqlclient_r... yes checking whether to compile with MySQL support... yes checking whether to compile with LibSDB support... disabled checking whether to compile with SQLite2 support... disabled checking whether to compile with SQLite3 support... disabled checking whether to compile with Oracle support... disabled checking whether to compile with PostgresSQL support... disabled checking whether to compile with Redis support... disabled checking whether to compile with FreeTDS Ct-Lib support... disabled Configuring for gSOAP support ... checking whether to compile with SOAP support... disabled Generating output files ... configure: creating ./config.status config.status: creating gwlib/gw_uuid_types.h config.status: creating Makefile config.status: creating soap/Makefile config.status: creating gw-config.h License information ... +--------------------------------------------------------------------+ | License: | | This software is subject to the Kannel Software License, available | | in this distribution in the file LICENSE. By continuing this | | installation process, you are bound by the terms of this license | | agreement. If you do not agree with the terms of this license, you | | must abort the installation process at this point. | | | | The Kannel Group | +--------------------------------------------------------------------+ Thank you for using Kannel. -------------------------------------------------------------------------------- -- Phase: build -------------------------------------------------------------------------------- ===> Building for kannel-1.4.4_8,1 gmake[1]: Entering directory '/construction/www/kannel/gateway-1.4.4' for dir in gw gw/smsc gwlib test utils wmlscript checks wap radius; do \ for file in $dir/*.c; do \ gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -MM $file -MT $dir/`basename $file .c`.o -MT $dir/`basename $file .c`.i; done; done > .depend utils/start-stop-daemon.c:94:2: error: #error Unknown architecture - cannot build start-stop-daemon #error Unknown architecture - cannot build start-stop-daemon ^~~~~ gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_pgsql.o -c gw/dlr_pgsql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_ota.o -c gw/wap_push_ota.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_mssql.o -c gw/dlr_mssql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr.o -c gw/dlr.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_oracle.o -c gw/dlr_oracle.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/ota_prov.o -c gw/ota_prov.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/urltrans.o -c gw/urltrans.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/mime_decompiler.o -c gw/mime_decompiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap-maps.o -c gw/wap-maps.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_redis.o -c gw/dlr_redis.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_boxc.o -c gw/bb_boxc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_sqlite3.o -c gw/dlr_sqlite3.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_si_compiler.o -c gw/wap_push_si_compiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_ppg_pushuser.o -c gw/wap_push_ppg_pushuser.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_ppg.o -c gw/wap_push_ppg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/ota_compiler.o -c gw/ota_compiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_sl_compiler.o -c gw/wap_push_sl_compiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/heartbeat.o -c gw/heartbeat.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/msg.o -c gw/msg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_sdb.o -c gw/dlr_sdb.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/shared.o -c gw/shared.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/sms.o -c gw/sms.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_alog.o -c gw/bb_alog.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_store_file.o -c gw/bb_store_file.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/load.o -c gw/load.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_pap_compiler.o -c gw/wap_push_pap_compiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_mem.o -c gw/dlr_mem.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wml_compiler.o -c gw/wml_compiler.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap-appl.o -c gw/wap-appl.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/html.o -c gw/html.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/numhash.o -c gw/numhash.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_mysql.o -c gw/dlr_mysql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap-error.o -c gw/wap-error.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/meta_data.o -c gw/meta_data.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/xml_shared.o -c gw/xml_shared.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wap_push_pap_mime.o -c gw/wap_push_pap_mime.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_store_spool.o -c gw/bb_store_spool.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smscconn.o -c gw/smscconn.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_http.o -c gw/bb_http.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/dlr_spool.o -c gw/dlr_spool.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_udp.o -c gw/bb_udp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_smscconn.o -c gw/bb_smscconn.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bb_store.o -c gw/bb_store.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_sema.o -c gw/smsc/smsc_sema.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_http.o -c gw/smsc/smsc_http.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_soap.o -c gw/smsc/smsc_soap.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smpp_pdu.o -c gw/smsc/smpp_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_cimd.o -c gw/smsc/smsc_cimd.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_emi_x25.o -c gw/smsc/smsc_emi_x25.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_at.o -c gw/smsc/smsc_at.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_soap_parlayx.o -c gw/smsc/smsc_soap_parlayx.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_smpp.o -c gw/smsc/smsc_smpp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_cimd2.o -c gw/smsc/smsc_cimd2.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_smasi.o -c gw/smsc/smsc_smasi.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smasi_pdu.o -c gw/smsc/smasi_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_emi.o -c gw/smsc/smsc_emi.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_ois.o -c gw/smsc/smsc_ois.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/emimsg.o -c gw/smsc/emimsg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_fake.o -c gw/smsc/smsc_fake.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_cgw.o -c gw/smsc/smsc_cgw.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_loopback.o -c gw/smsc/smsc_loopback.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc.o -c gw/smsc/smsc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_oisd.o -c gw/smsc/smsc_oisd.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsc/smsc_wrapper.o -c gw/smsc/smsc_wrapper.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsstree.o -c wmlscript/wsstree.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wmlsc.o -c wmlscript/wmlsc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wserror.o -c wmlscript/wserror.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/ws.o -c wmlscript/ws.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsstream_file.o -c wmlscript/wsstream_file.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsstream_data.o -c wmlscript/wsstream_data.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsieee754.o -c wmlscript/wsieee754.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wslexer.o -c wmlscript/wslexer.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsbuffer.o -c wmlscript/wsbuffer.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsstream.o -c wmlscript/wsstream.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wmlsdasm.o -c wmlscript/wmlsdasm.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsstdlib.o -c wmlscript/wsstdlib.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsutf8.o -c wmlscript/wsutf8.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsencode.o -c wmlscript/wsencode.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsfalloc.o -c wmlscript/wsfalloc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wshash.o -c wmlscript/wshash.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsbc.o -c wmlscript/wsbc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsalloc.o -c wmlscript/wsalloc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsgram.o -c wmlscript/wsgram.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsasm.o -c wmlscript/wsasm.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wmlscript/wsopt.o -c wmlscript/wsopt.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wap_addr.o -c wap/wap_addr.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wap_events.o -c wap/wap_events.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp_pack.o -c wap/wtp_pack.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtls_pdu.o -c wap/wtls_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtls_statesupport.o -c wap/wtls_statesupport.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp_resp.o -c wap/wtp_resp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_session.o -c wap/wsp_session.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/timers.o -c wap/timers.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/cookies.o -c wap/cookies.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_caps.o -c wap/wsp_caps.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wap.o -c wap/wap.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp.o -c wap/wtp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtls-secmgr.o -c wap/wtls-secmgr.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_strings.o -c wap/wsp_strings.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtls.o -c wap/wtls.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp_init.o -c wap/wtp_init.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtls_pdusupport.o -c wap/wtls_pdusupport.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp_tid.o -c wap/wtp_tid.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wtp_pdu.o -c wap/wtp_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_unit.o -c wap/wsp_unit.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_pdu.o -c wap/wsp_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_headers.o -c wap/wsp_headers.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp_push_client.o -c wap/wsp_push_client.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o wap/wsp.o -c wap/wsp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o radius/radius_acct.o -c radius/radius_acct.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o radius/radius_pdu.o -c radius/radius_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/utils.o -c gwlib/utils.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/fdset.o -c gwlib/fdset.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/http.o -c gwlib/http.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/thread.o -c gwlib/thread.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/parse.o -c gwlib/parse.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/cfg.o -c gwlib/cfg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/date.o -c gwlib/date.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_redis.o -c gwlib/dbpool_redis.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/octstr.o -c gwlib/octstr.c gwlib/octstr.c: In function 'octstr_format_valist_real': gwlib/octstr.c:89:21: warning: passing argument 3 of 'format_width' from incompatible pointer type [-Wincompatible-pointer-types] #define VARGS(x) (&x) ~^~~ gwlib/octstr.c:2495:37: note: in expansion of macro 'VARGS' format_width(&format, &fmt, VARGS(args)); ^~~~~ gwlib/octstr.c:2241:34: note: expected '__va_list_tag (*)[1]' but argument is of type '__va_list_tag **' #define VALPARM(y) va_list *y ~~~~~~~~~~ #define VALST(z) (*z) ~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Definitions of data structures. These are not visible to the external ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * world -- they may be accessed only via the functions declared in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr.h. This ensures they really are abstract. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * The octet string. ~~~~~~~~~~~~~~~~~~~ * ~ * `data' is a pointer to dynamically allocated memory are where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets in the string. It may be bigger than the actual length of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. ~~~~~~~~~ * ~ * `len' is the length of the string. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * `size' is the size of the memory area `data' points at. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * When `size' is greater than zero, it is at least `len+1', and the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * character at `len' is '\0'. This is so that octstr_get_cstr will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * always work. ~~~~~~~~~~~~~~ * ~ * `immutable' defines whether the octet string is immutable or not. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct Octstr ~~~~~~~~~~~~~ { ~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long len; ~~~~~~~~~ long size; ~~~~~~~~~~ int immutable; ~~~~~~~~~~~~~~ }; ~~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Hash table of immutable octet strings. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define MAX_IMMUTABLES 1024 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Octstr *immutables[MAX_IMMUTABLES]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Mutex immutables_mutex; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static int immutables_init = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static char is_safe[UCHAR_MAX + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * Convert a pointer to a C string literal to a long that can be used ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * for hashing. This is done by converting the pointer into an integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and discarding the lowest to bits to get rid of typical alignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bits. ~~~~~~~ */ ~~ #define CSTR_TO_LONG(ptr) (((unsigned long) ptr) >> 2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * HEX to ASCII preprocessor macro ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define H2B(a) (a >= '0' && a <= '9' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - '0' : (a >= 'a' && a <= 'f' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) \ ~~~ ) ~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Declarations of internal functions. These are defined at the end of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the file. ~~~~~~~~~~~ */ ~~ static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *function); ~~~~~~~~~~~~~~~~~~~~~~ #ifdef NO_GWASSERT ~~~~~~~~~~~~~~~~~~ #define seems_valid(ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~ #else ~~~~~ #define seems_valid(ostr) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ (seems_valid_real(ostr, __FILE__, __LINE__, __func__)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Implementations of the functions declared in octstr.h. See the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * header for explanations of what they should do. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* Reserve space for at least 'size' octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static void octstr_grow(Octstr *ostr, long size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(size >= 0); ~~~~~~~~~~~~~~~~~~~~~ size++; /* make room for the invisible terminating NUL */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (size > ostr->size) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* always reallocate in 1kB chunks */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ size += 1024 - (size % 1024); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_realloc(ostr->data, size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = size; ~~~~~~~~~~~~~~~~~~ } ~ } ~ /* ~~ * Fill is_safe table. is_safe[c] means that c can be left as such when ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * url-encoded. ~~~~~~~~~~~~~~ * RFC 2396 defines the list of characters that need to be encoded. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Space is treated as an exception by the encoding routine; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * it's listed as safe here, but is actually changed to '+'. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void urlcode_init(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i; ~~~~~~ unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; safe[i] != '\0'; ++i) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is_safe[safe[i]] = 1; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_init(void) ~~~~~~~~~~~~~~~~~~~~~~ { ~ urlcode_init(); ~~~~~~~~~~~~~~~ mutex_init_static(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ immutables_init = 1; ~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_shutdown(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n; ~~~~~~~~~~ n = 0; ~~~~~~ for (i = 0; i < MAX_IMMUTABLES; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (immutables[i] != NULL) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_free(immutables[i]); ~~~~~~~~~~~~~~~~~~~~~~~ ++n; ~~~~ } ~ } ~ if(n>0) ~~~~~~~ debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_destroy(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_real(const char *cstr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(cstr, strlen(cstr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_from_data_real(const char *data, long len, const char *file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long line, const char *func) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (data == NULL) ~~~~~~~~~~~~~~~~~ gw_assert(len == 0); ~~~~~~~~~~~~~~~~~~~~ /* if gw_assert is disabled just return NULL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and caller will check for NULL or just crash. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (len < 0 || (data == NULL && len != 0)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ ostr = gw_malloc_trace(sizeof(*ostr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ ostr->len = 0; ~~~~~~~~~~~~~~ ostr->size = 0; ~~~~~~~~~~~~~~~ ostr->data = NULL; ~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->size = len + 1; ~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc_trace(ostr->size, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->immutable = 0; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ Octstr *octstr_imm(const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ long i, index; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ gw_assert(immutables_init); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data = (unsigned char *) cstr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_lock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ i = index; ~~~~~~~~~~ for (; ; ) { ~~~~~~~~~~~~ if (immutables[i] == NULL || immutables[i]->data == data) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ i = (i + 1) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (i == index) ~~~~~~~~~~~~~~~ panic(0, "Too many immutable strings."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ os = immutables[i]; ~~~~~~~~~~~~~~~~~~~ if (os == NULL) { ~~~~~~~~~~~~~~~~~ /* ~~ * Can't use octstr_create() because it copies the string, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which would break our hashing. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ os = gw_malloc(sizeof(*os)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ os->data = data; ~~~~~~~~~~~~~~~~ os->len = strlen(data); ~~~~~~~~~~~~~~~~~~~~~~~ os->size = os->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~ os->immutable = 1; ~~~~~~~~~~~~~~~~~~ immutables[i] = os; ~~~~~~~~~~~~~~~~~~~ seems_valid(os); ~~~~~~~~~~~~~~~~ } ~ mutex_unlock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ } ~ void octstr_destroy(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr != NULL) { ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (!ostr->immutable) { ~~~~~~~~~~~~~~~~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ gw_free(ostr); ~~~~~~~~~~~~~~ } ~ } ~ } ~ void octstr_destroy_item(void *os) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ } ~ long octstr_len(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr->len; ~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (len > ostr->len - from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - from; ~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data + from, len, file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ line, func); ~~~~~~~~~~~~ } ~ Octstr *octstr_duplicate_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data, ostr->len, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len = ostr1->len + ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = ostr->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc(ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr1->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, ostr1->data, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ int octstr_get_char(const Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len || pos < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_char(Octstr *ostr, long pos, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos < ostr->len) ~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = ch; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(buf != NULL); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (pos + len > ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - pos; ~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) ~~~~~~~~~~~~ memcpy(buf, ostr->data + pos, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ char *octstr_get_cstr_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (!ostr) ~~~~~~~~~~ return "(null)"; ~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return ""; ~~~~~~~~~~ return ostr->data; ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_from_hex(Octstr *ostr, char *hex) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *output; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ output = octstr_create(hex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_hex_to_binary(output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append(ostr, output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_destroy(output); ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_binary_to_hex(Octstr *ostr, int uppercase) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *hexits; ~~~~~~~~~~~~~~~~~~~~~~ long i, tmp; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* In-place modification must be done back-to-front to avoid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * overwriting the data while we read it. Even the order of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the two assignments is important, to get i == 0 right. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = ostr->len - 1; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tmp = i << 1; /* tmp = i * 2; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp] = hexits[ostr->data[i] >> 4]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = ostr->len * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_hex_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len, i; ~~~~~~~~~~~~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ /* Check if it's in the right format */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ /* Convert ascii data to binary values */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, p = ostr->data; i < len; i++, p++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (*p >= '0' && *p <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p -= '0'; ~~~~~~~~~~ else if (*p >= 'a' && *p <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'a' + 10; ~~~~~~~~~~~~~~~~~~~ else if (*p >= 'A' && *p <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'A' + 10; ~~~~~~~~~~~~~~~~~~~ else { ~~~~~~ /* isxdigit checked the whole string, so we should ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not be able to get here. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(0); ~~~~~~~~~~~~~ *p = 0; ~~~~~~~ } ~ } ~ /* De-hexing will compress data by factor of 2 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len / 2; ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ void octstr_binary_to_base64(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ static const unsigned char base64[64] = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long triplets; ~~~~~~~~~~~~~~ long lines; ~~~~~~~~~~~ long orig_len; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long from, to; ~~~~~~~~~~~~~~ int left_on_line; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) { ~~~~~~~~~~~~~~~~~~~~~ /* Always terminate with CR LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr, octstr_imm("\015\012"), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* The lines must be 76 characters each (or less), and each ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplet will expand to 4 characters, so we can fit 19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplets on one line. We need a CR LF after each line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which will add 2 octets per 19 triplets (rounded up). */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ triplets = (ostr->len + 2) / 3; /* round up */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lines = (triplets + 18) / 19; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, triplets * 4 + lines * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ orig_len = ostr->len; ~~~~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ ostr->len = triplets * 4 + lines * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ /* This function works back-to-front, so that encoded data will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not overwrite source data. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * from points to the start of the last triplet (which may be ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an odd-sized one), and to points to the start of where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * last quad should go. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ from = (triplets - 1) * 3; ~~~~~~~~~~~~~~~~~~~~~~~~~~ to = (triplets - 1) * 4 + (lines - 1) * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* First write the CR LF after the last quad */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = triplets - ((lines - 1) * 19); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* base64 encoding is in 3-octet units. To handle leftover ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets, conceptually we have to zero-pad up to the next ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 6-bit unit, and pad with '=' characters for missing 6-bit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * units. ~~~~~~~~ * We do it by first completing the first triplet with ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * zero-octets, and after the loop replacing some of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * result characters with '=' characters. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * There is enough room for this, because even with a 1 or 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octet source string, space for four octets of output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * will be reserved. ~~~~~~~~~~~~~~~~~~~ */ ~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ data[orig_len] = 0; ~~~~~~~~~~~~~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ /* Now we only have perfect triplets. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (from >= 0) { ~~~~~~~~~~~~~~~~~~~ long whole_triplet; ~~~~~~~~~~~~~~~~~~~ /* Add a newline, if necessary */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (left_on_line == 0) { ~~~~~~~~~~~~~~~~~~~~~~~~ to -= 2; ~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = 19; ~~~~~~~~~~~~~~~~~~ } ~ whole_triplet = (data[from] << 16) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (data[from + 1] << 8) | ~~~~~~~~~~~~~~~~~~~~~~~ data[from + 2]; ~~~~~~~~~~~~~~~ data[to + 3] = base64[whole_triplet % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 2] = base64[(whole_triplet >> 6) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 1] = base64[(whole_triplet >> 12) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to] = base64[(whole_triplet >> 18) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ to -= 4; ~~~~~~~~ from -= 3; ~~~~~~~~~~ left_on_line--; ~~~~~~~~~~~~~~~ } ~ gw_assert(left_on_line == 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from == -3); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(to == -4); ~~~~~~~~~~~~~~~~~~~~ /* Insert padding characters in the last quad. Remember that ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * there is a CR LF between the last quad and the end of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. */ ~~~~~~~~~~~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(data[ostr->len - 4] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 4] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_base64_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long triplet; ~~~~~~~~~~~~~ long pos, len; ~~~~~~~~~~~~~~ long to; ~~~~~~~~ int quadpos = 0; ~~~~~~~~~~~~~~~~ int warned = 0; ~~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ to = 0; ~~~~~~~ triplet = 0; ~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ for (pos = 0; pos < len; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c = data[pos]; ~~~~~~~~~~~~~~~~~~ int sixbits; ~~~~~~~~~~~~ if (c >= 'A' && c <= 'Z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = c - 'A'; ~~~~~~~~~~~~~~~~~~ } else if (c >= 'a' && c <= 'z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 26 + c - 'a'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c >= '0' && c <= '9') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 52 + c - '0'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c == '+') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 62; ~~~~~~~~~~~~~ } else if (c == '/') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 63; ~~~~~~~~~~~~~ } else if (c == '=') { ~~~~~~~~~~~~~~~~~~~~~~ /* These can only occur at the end of encoded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * text. RFC 2045 says we can assume it really ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is the end. */ ~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (isspace(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* skip whitespace */ ~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } else { ~~~~~~~~ if (!warned) { ~~~~~~~~~~~~~~ warning(0, "Unusual characters in base64 " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "encoded text."); ~~~~~~~~~~~~~~~~~ warned = 1; ~~~~~~~~~~~ } ~ continue; ~~~~~~~~~ } ~ triplet = (triplet << 6) | sixbits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos++; ~~~~~~~~~~ if (quadpos == 4) { ~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 16) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 8) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = triplet & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ } ~ } ~ /* Deal with leftover octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ switch (quadpos) { ~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 3: /* triplet has 18 bits, we want the first 16 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 10) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 2) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: /* triplet has 12 bits, we want the first 8 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 4) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ warning(0, "Bad padding in base64 encoded text."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ ostr->len = to; ~~~~~~~~~~~~~~~ data[to] = '\0'; ~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtol wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ long number; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(base == 0 || (base >= 2 && base <= 36)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtol(ostr->data + pos, &endptr, base); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_double(double *nump, Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtod wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ double number; ~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtod(ostr->data + pos, &endptr); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_check_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t filter) ~~~~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!filter(ostr->data[pos])) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ return 1; ~~~~~~~~~ } ~ void octstr_convert_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t map) ~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = map(ostr->data[pos]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ static int inline make_printable(int c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return isprint(c) ? c : '.'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_convert_printable(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_convert_range(ostr, 0, ostr->len, make_printable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_compare(const Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int ret; ~~~~~~~~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len == 0 && ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr1->len > 0 && ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ ret = memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ else if (ostr1->len > ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = 1; ~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_case_compare(const Octstr *os1, const Octstr *os2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c1, c2; ~~~~~~~~~~~ long i, len; ~~~~~~~~~~~~ seems_valid(os1); ~~~~~~~~~~~~~~~~~ seems_valid(os2); ~~~~~~~~~~~~~~~~~ if (os1->len < os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~ len = os1->len; ~~~~~~~~~~~~~~~ else ~~~~ len = os2->len; ~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (os1->len == 0 && os2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (os1->len > 0 && os2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ c1 = c2 = 0; ~~~~~~~~~~~~ for (i = 0; i < len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (i == len) { ~~~~~~~~~~~~~~~ if (i == os1->len && i == os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (i == os1->len) ~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 1; ~~~~~~~~~ } else { ~~~~~~~~ /* ~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (c1 < c2) ~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (c1 == c2) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return 1; ~~~~~~~~~ } ~ } ~ int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if ((ostr1->len < ostr2->len) && (ostr1->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else if ((ostr2->len < ostr1->len) && (ostr2->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = n; ~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_case_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_ncompare(const Octstr *ostr, const char *str, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return 1; /* str grater */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ return strncmp(ostr->data, str, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_search_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ p = memchr(ostr->data + pos, ch, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!p) ~~~~~~~ return -1; ~~~~~~~~~~ return p - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_rsearch_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ for (i = pos; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->data[i] == ch) ~~~~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ seems_valid(chars); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < octstr_len(chars); i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = octstr_search_char(ostr, octstr_get_char(chars, i), pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (j != -1) ~~~~~~~~~~~~ return j; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (needle->len == 1) ~~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle->data[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle->data[0]; ~~~~~~~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle->data, needle->len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len && i < n; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len && j < n; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_str_search(const Octstr *haystack, const char *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ int needle_len; ~~~~~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle == NULL || needle[0] == '\0') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ needle_len = strlen(needle); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle_len == 1) ~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle[0]; ~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle_len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle, needle_len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ int octstr_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (fwrite(ostr->data, ostr->len, 1, f) != 1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error(errno, "Couldn't write all of octet string to file."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return 0; ~~~~~~~~~ } ~ int octstr_pretty_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ long i; ~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ for (i = 0; i < ostr->len; ++i, ++p) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isprint(*p)) ~~~~~~~~~~~~~~~~ fprintf(f, "%c", *p); ~~~~~~~~~~~~~~~~~~~~~ else ~~~~ fprintf(f, "\\x%02x", *p); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (ferror(f)) ~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ int octstr_write_to_socket(int socket, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ int ret; ~~~~~~~~ gw_assert(socket >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ while (len > 0) { ~~~~~~~~~~~~~~~~~ ret = write(socket, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == -1) { ~~~~~~~~~~~~~~~~ if (errno != EINTR) { ~~~~~~~~~~~~~~~~~~~~~ error(errno, "Writing to socket failed"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ } else { ~~~~~~~~ /* ret may be less than len */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len -= ret; ~~~~~~~~~~~ data += ret; ~~~~~~~~~~~~ } ~ } ~ return 0; ~~~~~~~~~ } ~ long octstr_write_data(Octstr *ostr, int fd, long from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long ret; ~~~~~~~~~ gw_assert(fd >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ ret = write(fd, ostr->data + from, ostr->len - from); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret < 0) { ~~~~~~~~~~~~~~ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ error(errno, "Error writing %ld octets to fd %d:", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len - from, fd); ~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_append_from_socket(Octstr *ostr, int socket) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char buf[4096]; ~~~~~~~~~~~~~~~~~~~~~~~~ int len; ~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ again: ~~~~~~ len = recv(socket, buf, sizeof(buf), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len < 0 && errno == EINTR) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ goto again; ~~~~~~~~~~~ if (len < 0) { ~~~~~~~~~~~~~~ error(errno, "Could not read from socket %d", socket); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ octstr_append_data(ostr, buf, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return len; ~~~~~~~~~~~ } ~ void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr2 == NULL) ~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr1, ostr1->len + ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr1->data + pos + ostr2->len, ostr1->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos); ~~~~~~~~~~~~~~~~~~ memcpy(ostr1->data + pos, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len += ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ void octstr_truncate(Octstr *ostr, int new_len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(new_len >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ if (new_len >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ ostr->len = new_len; ~~~~~~~~~~~~~~~~~~~~ ostr->data[new_len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ static int iscrlf(unsigned char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return c == '\n' || c == '\r'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_crlfs(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_nonalphanums(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_shrink_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i, j, end; ~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = octstr_len(text); ~~~~~~~~~~~~~~~~~~~~~~~ /* Shrink white spaces to one */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < end; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isspace(octstr_get_char(text, i))) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Change the remaining space into single space. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (octstr_get_char(text, i) != ' ') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_set_char(text, i, ' '); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = i = i + 1; ~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, j))) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j ++; ~~~~~ if (j - i > 1) ~~~~~~~~~~~~~~ octstr_delete(text, i, j - i); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr, ostr->len + len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) { /* only if neccessary*/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + len, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ memcpy(ostr->data + pos, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += len; ~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_char(Octstr *ostr, long pos, const char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) ~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + 1, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + pos, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += 1; ~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_data(Octstr *ostr, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append(Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr1 != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr1, ostr2, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_cstr(Octstr *ostr, const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_insert_data(ostr, ostr->len, cstr, strlen(cstr)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_char(Octstr *ostr, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char c = ch; ~~~~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_delete(Octstr *ostr1, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~ pos = ostr1->len; ~~~~~~~~~~~~~~~~~ if (pos + len > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len - pos; ~~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) { ~~~~~~~~~~~~~~ memmove(ostr1->data + pos, ostr1->data + pos + len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos - len); ~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len -= len; ~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_read_file(const char *filename) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ FILE *f; ~~~~~~~~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ long n; ~~~~~~~ gw_assert(filename != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ f = fopen(filename, "r"); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (f == NULL) { ~~~~~~~~~~~~~~~~ error(errno, "fopen failed: couldn't open `%s'", filename); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while ((n = fread(buf, 1, sizeof(buf), f)) > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(os, octstr_len(os), buf, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ Octstr *octstr_read_pipe(FILE *f) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while (fgets(buf, sizeof(buf), f) != NULL) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_data(os, buf, strlen(buf)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ List *octstr_split_words(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ List *list; ~~~~~~~~~~~ Octstr *word; ~~~~~~~~~~~~~ long i, start, end; ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ i = 0; ~~~~~~ for (; ; ) { ~~~~~~~~~~~~ while (i < ostr->len && isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ start = i; ~~~~~~~~~~ while (i < ostr->len && !isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ end = i; ~~~~~~~~ if (start == end) ~~~~~~~~~~~~~~~~~ break; ~~~~~~ word = octstr_create_from_data(ostr->data + start, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end - start); ~~~~~~~~~~~~~ gwlist_append(list, word); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return list; ~~~~~~~~~~~~ } ~ List *octstr_split(const Octstr *os, const Octstr *sep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ List *list; ~~~~~~~~~~~ long next, pos, seplen; ~~~~~~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ pos = 0; ~~~~~~~~ seplen = octstr_len(sep); ~~~~~~~~~~~~~~~~~~~~~~~~~ while ((next = octstr_search(os, sep, pos)) >= 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, next - pos)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pos = next + seplen; ~~~~~~~~~~~~~~~~~~~~ } ~ if (pos < octstr_len(os)) ~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, octstr_len(os))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return list; ~~~~~~~~~~~~ } ~ int octstr_item_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_item_case_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_case_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_url_encode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n, len = 0; ~~~~~~~~~~~~~~~~~~~ int all_safe; ~~~~~~~~~~~~~ unsigned char c, *str, *str2, *res, *hexits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ /* calculate new length */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = n = 0, str = ostr->data, all_safe = 1; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ all_safe = 0; ~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ n++; ~~~~ all_safe = 0; ~~~~~~~~~~~~~ } ~ } ~ if (all_safe) /* we are done, all chars are safe */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = "0123456789ABCDEF"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * no need to reallocate if n == 0, so we make replace in place. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * NOTE: we don't do if (xxx) ... else ... because conditional jump ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is not so fast as just compare (alex). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ res = str2 = (n ? gw_malloc((len = ostr->len + 2 * n + 1)) : ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, str = ostr->data; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ *str2++ = '+'; ~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ *str2++ = '%'; ~~~~~~~~~~~~~~ *str2++ = hexits[c >> 4 & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *str2++ = hexits[c & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ *str2++ = c; ~~~~~~~~~~~~ } ~ *str2 = 0; ~~~~~~~~~~ /* we made replace in place */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (n) { ~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ ostr->data = res; ~~~~~~~~~~~~~~~~~ ostr->size = len; ~~~~~~~~~~~~~~~~~ ostr->len = len - 1; ~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_url_decode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *string; ~~~~~~~~~~~~~~~~~~~~~~ unsigned char *dptr; ~~~~~~~~~~~~~~~~~~~~ int code, code2, ret = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ string = ostr->data; ~~~~~~~~~~~~~~~~~~~~ dptr = ostr->data; ~~~~~~~~~~~~~~~~~~ do { ~~~~ if (*string == '%') { ~~~~~~~~~~~~~~~~~~~~~ if (*(string + 1) == '\0' || *(string + 2) == '\0') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ break; ~~~~~~ } ~ code = H2B(*(string + 1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~ code2 = H2B(*(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (code == -1 || code2 == -1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *string, *(string + 1), *(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ continue; ~~~~~~~~~ } ~ *dptr++ = code << 4 | code2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string += 3; ~~~~~~~~~~~~ } ~ else if (*string == '+') { ~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = ' '; ~~~~~~~~~~~~~~ string++; ~~~~~~~~~ } else ~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ } while (*string); /* we stop here because it terimates encoded string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr = '\0'; ~~~~~~~~~~~~~ ostr->len = (dptr - ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ret; ~~~~~~~~~~~ } ~ long octstr_get_bits(Octstr *ostr, long bitpos, int numbits) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ long result; ~~~~~~~~~~~~ int mask; ~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* This also takes care of the len == 0 case */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* It's easy if the range fits in one octet */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return (ostr->data[pos] >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ result = 0; ~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ result = (result << 8) | ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return (result << numbits) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ result <<= numbits; ~~~~~~~~~~~~~~~~~~~ result |= ostr->data[pos] >> (8 - numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return result & mask; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ unsigned long value) ~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ unsigned long mask; ~~~~~~~~~~~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ int bits; ~~~~~~~~~ int maxlen; ~~~~~~~~~~~ int c; ~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ maxlen = (bitpos + numbits + 7) / 8; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (maxlen > ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, maxlen); ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Make sure the new octets start out with value 0 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = ostr->len; pos < maxlen; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = 0; ~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = maxlen; ~~~~~~~~~~~~~~~~~~~ ostr->data[maxlen] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* mask is also the largest value that fits */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(value <= mask); ~~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* Does the range fit in one octet? */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Extract the bits we don't want to affect */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ /* If speed is a problem here, we could have separate cases for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the first octet (which may have bitpos > 0), and the rest, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which don't. */ ~~~~~~~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* We want this many bits from the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bits = 8 - bitpos; ~~~~~~~~~~~~~~~~~~ /* There are this many bits to their right in the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = numbits - bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Construct a mask for "bits" bits on the far right */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << bits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~ /* Get the bits we want */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ c = (value >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Merge them with the bits that are already there */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = (ostr->data[pos] & ~mask) | c; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Set remaining bits. This is just like the single-octet case ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * before the loop, except that we know bitpos is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - numbits; ~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_uintvar(Octstr *ostr, unsigned long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* A uintvar is defined to be up to 32 bits large, so it will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in 5 octets. */ ~~~~~~~~~~~~~~~~~~~~~ unsigned char octets[5]; ~~~~~~~~~~~~~~~~~~~~~~~~ int i; ~~~~~~ int start; ~~~~~~~~~~ /* Handle last byte separately; it has no continuation bit, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and must be encoded even if value is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[4] = value & 0x7f; ~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ for (i = 3; value > 0 && i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[i] = 0x80 | (value & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ } ~ start = i + 1; ~~~~~~~~~~~~~~ octstr_append_data(ostr, octets + start, 5 - start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c; ~~~~~~ int count; ~~~~~~~~~~ unsigned long ui; ~~~~~~~~~~~~~~~~~ ui = 0; ~~~~~~~ for (count = 0; count < 5; count++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos + count); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c < 0) ~~~~~~~~~~ return -1; ~~~~~~~~~~ ui = (ui << 7) | (c & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!(c & 0x80)) { ~~~~~~~~~~~~~~~~~~ *value = ui; ~~~~~~~~~~~~ return pos + count + 1; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ return -1; ~~~~~~~~~~ } ~ void octstr_append_decimal(Octstr *ostr, long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char tmp[128]; ~~~~~~~~~~~~~~ sprintf(tmp, "%ld", value); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_cstr(ostr, tmp); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_dump... and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void octstr_dump_debug(const Octstr *ostr, int level) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p, *d, buf[1024], charbuf[256]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; ~~~~~~~~~ const int octets_per_line = 16; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); ~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s len: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s size: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s immutable: %d", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); ~~~~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = 0; ~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); ~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); ~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) ~~~~~~~~~~~~~~~ *d++ = c; ~~~~~~~~~ else ~~~~ *d++ = '.'; ~~~~~~~~~~~ ++pos; ~~~~~~ if (pos - this_line_begins_at == octets_per_line) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); ~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ charbuf[0] = '\0'; ~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = pos; ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (pos - this_line_begins_at > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %-*.*s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, ~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* ~~ * We do some pre-processor mangling here in order to reduce code for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the 3 log levels info(), warning() and error() that have the same ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * argument list. ~~~~~~~~~~~~~~~~ * We need to map the function calls via ## concatenation and revert ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * to the original function call by a define. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The do-while loop emulates a function call. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define LLinfo info ~~~~~~~~~~~~~~~~~~~ #define LLwarning warning ~~~~~~~~~~~~~~~~~~~~~~~~~ #define LLerror error ~~~~~~~~~~~~~~~~~~~~~ #define octstr_dump_LOGLEVEL(loglevel, ostr, level) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ do { \ ~~~~~~ unsigned char *p, *d, buf[1024], charbuf[256]; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; \ ~~~~~~~~~~~ const int octets_per_line = 16; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ ~ if (ostr == NULL) \ ~~~~~~~~~~~~~~~~~~~ return; \ ~~~~~~~~~ \ ~ seems_valid(ostr); \ ~~~~~~~~~~~~~~~~~~~~ \ ~ LL##loglevel(0, "%*sOctet string at %p:", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); \ ~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s len: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s size: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s immutable: %d", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); \ ~~~~~~~~~~~~~~~~~~~ \ ~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = 0; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); \ ~~~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); \ ~~~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) \ ~~~~~~~~~~~~~~~~~ *d++ = c; \ ~~~~~~~~~~~ else \ ~~~~~~ *d++ = '.'; \ ~~~~~~~~~~~~~ ++pos; \ ~~~~~~~~ if (pos - this_line_begins_at == octets_per_line) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); \ ~~~~~~~~~~~~~~~~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ charbuf[0] = '\0'; \ ~~~~~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = pos; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ } \ ~~~ if (pos - this_line_begins_at > 0) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %-*.*s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, \ ~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ \ ~ LL##loglevel(0, "%*sOctet string dump ends.", level, ""); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } while (0) ~~~~~~~~~~~ void octstr_dump_real(const Octstr *ostr, int level, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ va_list p; ~~~~~~~~~~ unsigned int loglevel; ~~~~~~~~~~~~~~~~~~~~~~ va_start(p, level); ~~~~~~~~~~~~~~~~~~~ loglevel = va_arg(p, unsigned int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(p); ~~~~~~~~~~ switch (loglevel) { ~~~~~~~~~~~~~~~~~~~ case GW_DEBUG: ~~~~~~~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_INFO: ~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(info, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_WARNING: ~~~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(warning, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_ERROR: ~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(error, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ } ~ void octstr_dump_short(Octstr *ostr, int level, const char *name) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char buf[100]; ~~~~~~~~~~~~~~ char *p; ~~~~~~~~ long i; ~~~~~~~ int c; ~~~~~~ if (ostr == NULL) { ~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len < 20) { ~~~~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ for (i = 0; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[i]; ~~~~~~~~~~~~~~~~~~ if (c == '\n') { ~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = 'n'; ~~~~~~~~~~~ } else if (!isprint(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (c == '"') { ~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '"'; ~~~~~~~~~~~ } else if (c == '\\') { ~~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ } else { ~~~~~~~~ *p++ = c; ~~~~~~~~~ } ~ } ~ if (i == ostr->len) { ~~~~~~~~~~~~~~~~~~~~~ *p++ = 0; ~~~~~~~~~ /* We got through the loop without hitting nonprintable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * characters. */ ~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: \"%s\"", level, "", name, buf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ } ~ debug("gwlib.octstr", 0, "%*s%s:", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_dump(ostr, level + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_format and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * A parsed form of the format string. This struct has been carefully ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * defined so that it can be initialized with {0} and it will have ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the correct defaults. ~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct format ~~~~~~~~~~~~~ { ~ int minus; ~~~~~~~~~~ int zero; ~~~~~~~~~ long min_width; ~~~~~~~~~~~~~~~ int has_prec; ~~~~~~~~~~~~~ long prec; ~~~~~~~~~~ long type; ~~~~~~~~~~ }; ~~ static void format_flags(struct format *format, const char **fmt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int done; ~~~~~~~~~ done = 0; ~~~~~~~~~ do ~~ { ~ switch (**fmt) { ~~~~~~~~~~~~~~~~ case '-': ~~~~~~~~~ format->minus = 1; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case '0': ~~~~~~~~~ format->zero = 1; ~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ done = 1; ~~~~~~~~~ } ~ if (!done) ~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } while (!done); ~~~~~~~~~~~~~~~~ } ~ static void format_width(struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~^~~~ gwlib/octstr.c:90:29: note: in definition of macro 'VALPARM' #define VALPARM(y) va_list *y ^ gwlib/octstr.c:89:21: warning: passing argument 3 of 'format_prec' from incompatible pointer type [-Wincompatible-pointer-types] #define VARGS(x) (&x) ~^~~ gwlib/octstr.c:2496:36: note: in expansion of macro 'VARGS' format_prec(&format, &fmt, VARGS(args)); ^~~~~ gwlib/octstr.c:2259:33: note: expected '__va_list_tag (*)[1]' but argument is of type '__va_list_tag **' #define VALPARM(y) va_list *y ~~~~~~~~~~ #define VALST(z) (*z) ~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Definitions of data structures. These are not visible to the external ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * world -- they may be accessed only via the functions declared in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr.h. This ensures they really are abstract. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * The octet string. ~~~~~~~~~~~~~~~~~~~ * ~ * `data' is a pointer to dynamically allocated memory are where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets in the string. It may be bigger than the actual length of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. ~~~~~~~~~ * ~ * `len' is the length of the string. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * `size' is the size of the memory area `data' points at. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * When `size' is greater than zero, it is at least `len+1', and the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * character at `len' is '\0'. This is so that octstr_get_cstr will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * always work. ~~~~~~~~~~~~~~ * ~ * `immutable' defines whether the octet string is immutable or not. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct Octstr ~~~~~~~~~~~~~ { ~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long len; ~~~~~~~~~ long size; ~~~~~~~~~~ int immutable; ~~~~~~~~~~~~~~ }; ~~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Hash table of immutable octet strings. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define MAX_IMMUTABLES 1024 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Octstr *immutables[MAX_IMMUTABLES]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Mutex immutables_mutex; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static int immutables_init = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static char is_safe[UCHAR_MAX + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * Convert a pointer to a C string literal to a long that can be used ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * for hashing. This is done by converting the pointer into an integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and discarding the lowest to bits to get rid of typical alignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bits. ~~~~~~~ */ ~~ #define CSTR_TO_LONG(ptr) (((unsigned long) ptr) >> 2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * HEX to ASCII preprocessor macro ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define H2B(a) (a >= '0' && a <= '9' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - '0' : (a >= 'a' && a <= 'f' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) \ ~~~ ) ~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Declarations of internal functions. These are defined at the end of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the file. ~~~~~~~~~~~ */ ~~ static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *function); ~~~~~~~~~~~~~~~~~~~~~~ #ifdef NO_GWASSERT ~~~~~~~~~~~~~~~~~~ #define seems_valid(ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~ #else ~~~~~ #define seems_valid(ostr) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ (seems_valid_real(ostr, __FILE__, __LINE__, __func__)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Implementations of the functions declared in octstr.h. See the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * header for explanations of what they should do. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* Reserve space for at least 'size' octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static void octstr_grow(Octstr *ostr, long size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(size >= 0); ~~~~~~~~~~~~~~~~~~~~~ size++; /* make room for the invisible terminating NUL */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (size > ostr->size) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* always reallocate in 1kB chunks */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ size += 1024 - (size % 1024); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_realloc(ostr->data, size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = size; ~~~~~~~~~~~~~~~~~~ } ~ } ~ /* ~~ * Fill is_safe table. is_safe[c] means that c can be left as such when ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * url-encoded. ~~~~~~~~~~~~~~ * RFC 2396 defines the list of characters that need to be encoded. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Space is treated as an exception by the encoding routine; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * it's listed as safe here, but is actually changed to '+'. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void urlcode_init(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i; ~~~~~~ unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; safe[i] != '\0'; ++i) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is_safe[safe[i]] = 1; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_init(void) ~~~~~~~~~~~~~~~~~~~~~~ { ~ urlcode_init(); ~~~~~~~~~~~~~~~ mutex_init_static(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ immutables_init = 1; ~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_shutdown(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n; ~~~~~~~~~~ n = 0; ~~~~~~ for (i = 0; i < MAX_IMMUTABLES; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (immutables[i] != NULL) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_free(immutables[i]); ~~~~~~~~~~~~~~~~~~~~~~~ ++n; ~~~~ } ~ } ~ if(n>0) ~~~~~~~ debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_destroy(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_real(const char *cstr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(cstr, strlen(cstr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_from_data_real(const char *data, long len, const char *file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long line, const char *func) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (data == NULL) ~~~~~~~~~~~~~~~~~ gw_assert(len == 0); ~~~~~~~~~~~~~~~~~~~~ /* if gw_assert is disabled just return NULL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and caller will check for NULL or just crash. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (len < 0 || (data == NULL && len != 0)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ ostr = gw_malloc_trace(sizeof(*ostr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ ostr->len = 0; ~~~~~~~~~~~~~~ ostr->size = 0; ~~~~~~~~~~~~~~~ ostr->data = NULL; ~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->size = len + 1; ~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc_trace(ostr->size, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->immutable = 0; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ Octstr *octstr_imm(const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ long i, index; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ gw_assert(immutables_init); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data = (unsigned char *) cstr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_lock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ i = index; ~~~~~~~~~~ for (; ; ) { ~~~~~~~~~~~~ if (immutables[i] == NULL || immutables[i]->data == data) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ i = (i + 1) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (i == index) ~~~~~~~~~~~~~~~ panic(0, "Too many immutable strings."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ os = immutables[i]; ~~~~~~~~~~~~~~~~~~~ if (os == NULL) { ~~~~~~~~~~~~~~~~~ /* ~~ * Can't use octstr_create() because it copies the string, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which would break our hashing. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ os = gw_malloc(sizeof(*os)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ os->data = data; ~~~~~~~~~~~~~~~~ os->len = strlen(data); ~~~~~~~~~~~~~~~~~~~~~~~ os->size = os->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~ os->immutable = 1; ~~~~~~~~~~~~~~~~~~ immutables[i] = os; ~~~~~~~~~~~~~~~~~~~ seems_valid(os); ~~~~~~~~~~~~~~~~ } ~ mutex_unlock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ } ~ void octstr_destroy(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr != NULL) { ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (!ostr->immutable) { ~~~~~~~~~~~~~~~~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ gw_free(ostr); ~~~~~~~~~~~~~~ } ~ } ~ } ~ void octstr_destroy_item(void *os) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ } ~ long octstr_len(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr->len; ~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (len > ostr->len - from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - from; ~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data + from, len, file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ line, func); ~~~~~~~~~~~~ } ~ Octstr *octstr_duplicate_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data, ostr->len, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len = ostr1->len + ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = ostr->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc(ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr1->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, ostr1->data, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ int octstr_get_char(const Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len || pos < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_char(Octstr *ostr, long pos, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos < ostr->len) ~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = ch; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(buf != NULL); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (pos + len > ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - pos; ~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) ~~~~~~~~~~~~ memcpy(buf, ostr->data + pos, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ char *octstr_get_cstr_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (!ostr) ~~~~~~~~~~ return "(null)"; ~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return ""; ~~~~~~~~~~ return ostr->data; ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_from_hex(Octstr *ostr, char *hex) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *output; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ output = octstr_create(hex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_hex_to_binary(output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append(ostr, output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_destroy(output); ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_binary_to_hex(Octstr *ostr, int uppercase) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *hexits; ~~~~~~~~~~~~~~~~~~~~~~ long i, tmp; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* In-place modification must be done back-to-front to avoid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * overwriting the data while we read it. Even the order of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the two assignments is important, to get i == 0 right. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = ostr->len - 1; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tmp = i << 1; /* tmp = i * 2; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp] = hexits[ostr->data[i] >> 4]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = ostr->len * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_hex_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len, i; ~~~~~~~~~~~~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ /* Check if it's in the right format */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ /* Convert ascii data to binary values */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, p = ostr->data; i < len; i++, p++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (*p >= '0' && *p <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p -= '0'; ~~~~~~~~~~ else if (*p >= 'a' && *p <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'a' + 10; ~~~~~~~~~~~~~~~~~~~ else if (*p >= 'A' && *p <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'A' + 10; ~~~~~~~~~~~~~~~~~~~ else { ~~~~~~ /* isxdigit checked the whole string, so we should ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not be able to get here. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(0); ~~~~~~~~~~~~~ *p = 0; ~~~~~~~ } ~ } ~ /* De-hexing will compress data by factor of 2 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len / 2; ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ void octstr_binary_to_base64(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ static const unsigned char base64[64] = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long triplets; ~~~~~~~~~~~~~~ long lines; ~~~~~~~~~~~ long orig_len; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long from, to; ~~~~~~~~~~~~~~ int left_on_line; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) { ~~~~~~~~~~~~~~~~~~~~~ /* Always terminate with CR LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr, octstr_imm("\015\012"), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* The lines must be 76 characters each (or less), and each ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplet will expand to 4 characters, so we can fit 19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplets on one line. We need a CR LF after each line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which will add 2 octets per 19 triplets (rounded up). */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ triplets = (ostr->len + 2) / 3; /* round up */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lines = (triplets + 18) / 19; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, triplets * 4 + lines * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ orig_len = ostr->len; ~~~~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ ostr->len = triplets * 4 + lines * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ /* This function works back-to-front, so that encoded data will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not overwrite source data. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * from points to the start of the last triplet (which may be ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an odd-sized one), and to points to the start of where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * last quad should go. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ from = (triplets - 1) * 3; ~~~~~~~~~~~~~~~~~~~~~~~~~~ to = (triplets - 1) * 4 + (lines - 1) * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* First write the CR LF after the last quad */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = triplets - ((lines - 1) * 19); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* base64 encoding is in 3-octet units. To handle leftover ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets, conceptually we have to zero-pad up to the next ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 6-bit unit, and pad with '=' characters for missing 6-bit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * units. ~~~~~~~~ * We do it by first completing the first triplet with ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * zero-octets, and after the loop replacing some of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * result characters with '=' characters. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * There is enough room for this, because even with a 1 or 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octet source string, space for four octets of output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * will be reserved. ~~~~~~~~~~~~~~~~~~~ */ ~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ data[orig_len] = 0; ~~~~~~~~~~~~~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ /* Now we only have perfect triplets. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (from >= 0) { ~~~~~~~~~~~~~~~~~~~ long whole_triplet; ~~~~~~~~~~~~~~~~~~~ /* Add a newline, if necessary */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (left_on_line == 0) { ~~~~~~~~~~~~~~~~~~~~~~~~ to -= 2; ~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = 19; ~~~~~~~~~~~~~~~~~~ } ~ whole_triplet = (data[from] << 16) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (data[from + 1] << 8) | ~~~~~~~~~~~~~~~~~~~~~~~ data[from + 2]; ~~~~~~~~~~~~~~~ data[to + 3] = base64[whole_triplet % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 2] = base64[(whole_triplet >> 6) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 1] = base64[(whole_triplet >> 12) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to] = base64[(whole_triplet >> 18) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ to -= 4; ~~~~~~~~ from -= 3; ~~~~~~~~~~ left_on_line--; ~~~~~~~~~~~~~~~ } ~ gw_assert(left_on_line == 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from == -3); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(to == -4); ~~~~~~~~~~~~~~~~~~~~ /* Insert padding characters in the last quad. Remember that ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * there is a CR LF between the last quad and the end of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. */ ~~~~~~~~~~~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(data[ostr->len - 4] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 4] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_base64_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long triplet; ~~~~~~~~~~~~~ long pos, len; ~~~~~~~~~~~~~~ long to; ~~~~~~~~ int quadpos = 0; ~~~~~~~~~~~~~~~~ int warned = 0; ~~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ to = 0; ~~~~~~~ triplet = 0; ~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ for (pos = 0; pos < len; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c = data[pos]; ~~~~~~~~~~~~~~~~~~ int sixbits; ~~~~~~~~~~~~ if (c >= 'A' && c <= 'Z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = c - 'A'; ~~~~~~~~~~~~~~~~~~ } else if (c >= 'a' && c <= 'z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 26 + c - 'a'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c >= '0' && c <= '9') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 52 + c - '0'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c == '+') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 62; ~~~~~~~~~~~~~ } else if (c == '/') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 63; ~~~~~~~~~~~~~ } else if (c == '=') { ~~~~~~~~~~~~~~~~~~~~~~ /* These can only occur at the end of encoded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * text. RFC 2045 says we can assume it really ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is the end. */ ~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (isspace(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* skip whitespace */ ~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } else { ~~~~~~~~ if (!warned) { ~~~~~~~~~~~~~~ warning(0, "Unusual characters in base64 " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "encoded text."); ~~~~~~~~~~~~~~~~~ warned = 1; ~~~~~~~~~~~ } ~ continue; ~~~~~~~~~ } ~ triplet = (triplet << 6) | sixbits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos++; ~~~~~~~~~~ if (quadpos == 4) { ~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 16) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 8) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = triplet & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ } ~ } ~ /* Deal with leftover octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ switch (quadpos) { ~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 3: /* triplet has 18 bits, we want the first 16 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 10) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 2) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: /* triplet has 12 bits, we want the first 8 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 4) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ warning(0, "Bad padding in base64 encoded text."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ ostr->len = to; ~~~~~~~~~~~~~~~ data[to] = '\0'; ~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtol wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ long number; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(base == 0 || (base >= 2 && base <= 36)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtol(ostr->data + pos, &endptr, base); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_double(double *nump, Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtod wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ double number; ~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtod(ostr->data + pos, &endptr); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_check_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t filter) ~~~~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!filter(ostr->data[pos])) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ return 1; ~~~~~~~~~ } ~ void octstr_convert_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t map) ~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = map(ostr->data[pos]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ static int inline make_printable(int c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return isprint(c) ? c : '.'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_convert_printable(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_convert_range(ostr, 0, ostr->len, make_printable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_compare(const Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int ret; ~~~~~~~~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len == 0 && ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr1->len > 0 && ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ ret = memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ else if (ostr1->len > ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = 1; ~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_case_compare(const Octstr *os1, const Octstr *os2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c1, c2; ~~~~~~~~~~~ long i, len; ~~~~~~~~~~~~ seems_valid(os1); ~~~~~~~~~~~~~~~~~ seems_valid(os2); ~~~~~~~~~~~~~~~~~ if (os1->len < os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~ len = os1->len; ~~~~~~~~~~~~~~~ else ~~~~ len = os2->len; ~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (os1->len == 0 && os2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (os1->len > 0 && os2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ c1 = c2 = 0; ~~~~~~~~~~~~ for (i = 0; i < len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (i == len) { ~~~~~~~~~~~~~~~ if (i == os1->len && i == os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (i == os1->len) ~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 1; ~~~~~~~~~ } else { ~~~~~~~~ /* ~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (c1 < c2) ~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (c1 == c2) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return 1; ~~~~~~~~~ } ~ } ~ int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if ((ostr1->len < ostr2->len) && (ostr1->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else if ((ostr2->len < ostr1->len) && (ostr2->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = n; ~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_case_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_ncompare(const Octstr *ostr, const char *str, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return 1; /* str grater */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ return strncmp(ostr->data, str, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_search_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ p = memchr(ostr->data + pos, ch, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!p) ~~~~~~~ return -1; ~~~~~~~~~~ return p - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_rsearch_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ for (i = pos; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->data[i] == ch) ~~~~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ seems_valid(chars); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < octstr_len(chars); i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = octstr_search_char(ostr, octstr_get_char(chars, i), pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (j != -1) ~~~~~~~~~~~~ return j; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (needle->len == 1) ~~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle->data[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle->data[0]; ~~~~~~~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle->data, needle->len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len && i < n; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len && j < n; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_str_search(const Octstr *haystack, const char *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ int needle_len; ~~~~~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle == NULL || needle[0] == '\0') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ needle_len = strlen(needle); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle_len == 1) ~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle[0]; ~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle_len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle, needle_len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ int octstr_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (fwrite(ostr->data, ostr->len, 1, f) != 1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error(errno, "Couldn't write all of octet string to file."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return 0; ~~~~~~~~~ } ~ int octstr_pretty_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ long i; ~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ for (i = 0; i < ostr->len; ++i, ++p) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isprint(*p)) ~~~~~~~~~~~~~~~~ fprintf(f, "%c", *p); ~~~~~~~~~~~~~~~~~~~~~ else ~~~~ fprintf(f, "\\x%02x", *p); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (ferror(f)) ~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ int octstr_write_to_socket(int socket, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ int ret; ~~~~~~~~ gw_assert(socket >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ while (len > 0) { ~~~~~~~~~~~~~~~~~ ret = write(socket, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == -1) { ~~~~~~~~~~~~~~~~ if (errno != EINTR) { ~~~~~~~~~~~~~~~~~~~~~ error(errno, "Writing to socket failed"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ } else { ~~~~~~~~ /* ret may be less than len */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len -= ret; ~~~~~~~~~~~ data += ret; ~~~~~~~~~~~~ } ~ } ~ return 0; ~~~~~~~~~ } ~ long octstr_write_data(Octstr *ostr, int fd, long from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long ret; ~~~~~~~~~ gw_assert(fd >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ ret = write(fd, ostr->data + from, ostr->len - from); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret < 0) { ~~~~~~~~~~~~~~ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ error(errno, "Error writing %ld octets to fd %d:", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len - from, fd); ~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_append_from_socket(Octstr *ostr, int socket) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char buf[4096]; ~~~~~~~~~~~~~~~~~~~~~~~~ int len; ~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ again: ~~~~~~ len = recv(socket, buf, sizeof(buf), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len < 0 && errno == EINTR) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ goto again; ~~~~~~~~~~~ if (len < 0) { ~~~~~~~~~~~~~~ error(errno, "Could not read from socket %d", socket); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ octstr_append_data(ostr, buf, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return len; ~~~~~~~~~~~ } ~ void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr2 == NULL) ~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr1, ostr1->len + ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr1->data + pos + ostr2->len, ostr1->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos); ~~~~~~~~~~~~~~~~~~ memcpy(ostr1->data + pos, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len += ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ void octstr_truncate(Octstr *ostr, int new_len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(new_len >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ if (new_len >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ ostr->len = new_len; ~~~~~~~~~~~~~~~~~~~~ ostr->data[new_len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ static int iscrlf(unsigned char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return c == '\n' || c == '\r'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_crlfs(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_nonalphanums(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_shrink_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i, j, end; ~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = octstr_len(text); ~~~~~~~~~~~~~~~~~~~~~~~ /* Shrink white spaces to one */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < end; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isspace(octstr_get_char(text, i))) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Change the remaining space into single space. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (octstr_get_char(text, i) != ' ') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_set_char(text, i, ' '); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = i = i + 1; ~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, j))) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j ++; ~~~~~ if (j - i > 1) ~~~~~~~~~~~~~~ octstr_delete(text, i, j - i); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr, ostr->len + len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) { /* only if neccessary*/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + len, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ memcpy(ostr->data + pos, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += len; ~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_char(Octstr *ostr, long pos, const char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) ~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + 1, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + pos, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += 1; ~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_data(Octstr *ostr, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append(Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr1 != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr1, ostr2, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_cstr(Octstr *ostr, const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_insert_data(ostr, ostr->len, cstr, strlen(cstr)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_char(Octstr *ostr, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char c = ch; ~~~~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_delete(Octstr *ostr1, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~ pos = ostr1->len; ~~~~~~~~~~~~~~~~~ if (pos + len > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len - pos; ~~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) { ~~~~~~~~~~~~~~ memmove(ostr1->data + pos, ostr1->data + pos + len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos - len); ~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len -= len; ~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_read_file(const char *filename) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ FILE *f; ~~~~~~~~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ long n; ~~~~~~~ gw_assert(filename != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ f = fopen(filename, "r"); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (f == NULL) { ~~~~~~~~~~~~~~~~ error(errno, "fopen failed: couldn't open `%s'", filename); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while ((n = fread(buf, 1, sizeof(buf), f)) > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(os, octstr_len(os), buf, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ Octstr *octstr_read_pipe(FILE *f) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while (fgets(buf, sizeof(buf), f) != NULL) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_data(os, buf, strlen(buf)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ List *octstr_split_words(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ List *list; ~~~~~~~~~~~ Octstr *word; ~~~~~~~~~~~~~ long i, start, end; ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ i = 0; ~~~~~~ for (; ; ) { ~~~~~~~~~~~~ while (i < ostr->len && isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ start = i; ~~~~~~~~~~ while (i < ostr->len && !isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ end = i; ~~~~~~~~ if (start == end) ~~~~~~~~~~~~~~~~~ break; ~~~~~~ word = octstr_create_from_data(ostr->data + start, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end - start); ~~~~~~~~~~~~~ gwlist_append(list, word); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return list; ~~~~~~~~~~~~ } ~ List *octstr_split(const Octstr *os, const Octstr *sep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ List *list; ~~~~~~~~~~~ long next, pos, seplen; ~~~~~~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ pos = 0; ~~~~~~~~ seplen = octstr_len(sep); ~~~~~~~~~~~~~~~~~~~~~~~~~ while ((next = octstr_search(os, sep, pos)) >= 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, next - pos)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pos = next + seplen; ~~~~~~~~~~~~~~~~~~~~ } ~ if (pos < octstr_len(os)) ~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, octstr_len(os))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return list; ~~~~~~~~~~~~ } ~ int octstr_item_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_item_case_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_case_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_url_encode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n, len = 0; ~~~~~~~~~~~~~~~~~~~ int all_safe; ~~~~~~~~~~~~~ unsigned char c, *str, *str2, *res, *hexits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ /* calculate new length */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = n = 0, str = ostr->data, all_safe = 1; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ all_safe = 0; ~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ n++; ~~~~ all_safe = 0; ~~~~~~~~~~~~~ } ~ } ~ if (all_safe) /* we are done, all chars are safe */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = "0123456789ABCDEF"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * no need to reallocate if n == 0, so we make replace in place. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * NOTE: we don't do if (xxx) ... else ... because conditional jump ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is not so fast as just compare (alex). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ res = str2 = (n ? gw_malloc((len = ostr->len + 2 * n + 1)) : ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, str = ostr->data; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ *str2++ = '+'; ~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ *str2++ = '%'; ~~~~~~~~~~~~~~ *str2++ = hexits[c >> 4 & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *str2++ = hexits[c & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ *str2++ = c; ~~~~~~~~~~~~ } ~ *str2 = 0; ~~~~~~~~~~ /* we made replace in place */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (n) { ~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ ostr->data = res; ~~~~~~~~~~~~~~~~~ ostr->size = len; ~~~~~~~~~~~~~~~~~ ostr->len = len - 1; ~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_url_decode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *string; ~~~~~~~~~~~~~~~~~~~~~~ unsigned char *dptr; ~~~~~~~~~~~~~~~~~~~~ int code, code2, ret = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ string = ostr->data; ~~~~~~~~~~~~~~~~~~~~ dptr = ostr->data; ~~~~~~~~~~~~~~~~~~ do { ~~~~ if (*string == '%') { ~~~~~~~~~~~~~~~~~~~~~ if (*(string + 1) == '\0' || *(string + 2) == '\0') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ break; ~~~~~~ } ~ code = H2B(*(string + 1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~ code2 = H2B(*(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (code == -1 || code2 == -1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *string, *(string + 1), *(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ continue; ~~~~~~~~~ } ~ *dptr++ = code << 4 | code2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string += 3; ~~~~~~~~~~~~ } ~ else if (*string == '+') { ~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = ' '; ~~~~~~~~~~~~~~ string++; ~~~~~~~~~ } else ~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ } while (*string); /* we stop here because it terimates encoded string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr = '\0'; ~~~~~~~~~~~~~ ostr->len = (dptr - ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ret; ~~~~~~~~~~~ } ~ long octstr_get_bits(Octstr *ostr, long bitpos, int numbits) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ long result; ~~~~~~~~~~~~ int mask; ~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* This also takes care of the len == 0 case */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* It's easy if the range fits in one octet */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return (ostr->data[pos] >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ result = 0; ~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ result = (result << 8) | ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return (result << numbits) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ result <<= numbits; ~~~~~~~~~~~~~~~~~~~ result |= ostr->data[pos] >> (8 - numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return result & mask; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ unsigned long value) ~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ unsigned long mask; ~~~~~~~~~~~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ int bits; ~~~~~~~~~ int maxlen; ~~~~~~~~~~~ int c; ~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ maxlen = (bitpos + numbits + 7) / 8; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (maxlen > ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, maxlen); ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Make sure the new octets start out with value 0 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = ostr->len; pos < maxlen; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = 0; ~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = maxlen; ~~~~~~~~~~~~~~~~~~~ ostr->data[maxlen] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* mask is also the largest value that fits */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(value <= mask); ~~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* Does the range fit in one octet? */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Extract the bits we don't want to affect */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ /* If speed is a problem here, we could have separate cases for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the first octet (which may have bitpos > 0), and the rest, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which don't. */ ~~~~~~~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* We want this many bits from the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bits = 8 - bitpos; ~~~~~~~~~~~~~~~~~~ /* There are this many bits to their right in the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = numbits - bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Construct a mask for "bits" bits on the far right */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << bits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~ /* Get the bits we want */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ c = (value >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Merge them with the bits that are already there */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = (ostr->data[pos] & ~mask) | c; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Set remaining bits. This is just like the single-octet case ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * before the loop, except that we know bitpos is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - numbits; ~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_uintvar(Octstr *ostr, unsigned long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* A uintvar is defined to be up to 32 bits large, so it will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in 5 octets. */ ~~~~~~~~~~~~~~~~~~~~~ unsigned char octets[5]; ~~~~~~~~~~~~~~~~~~~~~~~~ int i; ~~~~~~ int start; ~~~~~~~~~~ /* Handle last byte separately; it has no continuation bit, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and must be encoded even if value is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[4] = value & 0x7f; ~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ for (i = 3; value > 0 && i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[i] = 0x80 | (value & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ } ~ start = i + 1; ~~~~~~~~~~~~~~ octstr_append_data(ostr, octets + start, 5 - start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c; ~~~~~~ int count; ~~~~~~~~~~ unsigned long ui; ~~~~~~~~~~~~~~~~~ ui = 0; ~~~~~~~ for (count = 0; count < 5; count++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos + count); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c < 0) ~~~~~~~~~~ return -1; ~~~~~~~~~~ ui = (ui << 7) | (c & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!(c & 0x80)) { ~~~~~~~~~~~~~~~~~~ *value = ui; ~~~~~~~~~~~~ return pos + count + 1; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ return -1; ~~~~~~~~~~ } ~ void octstr_append_decimal(Octstr *ostr, long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char tmp[128]; ~~~~~~~~~~~~~~ sprintf(tmp, "%ld", value); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_cstr(ostr, tmp); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_dump... and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void octstr_dump_debug(const Octstr *ostr, int level) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p, *d, buf[1024], charbuf[256]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; ~~~~~~~~~ const int octets_per_line = 16; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); ~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s len: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s size: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s immutable: %d", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); ~~~~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = 0; ~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); ~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); ~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) ~~~~~~~~~~~~~~~ *d++ = c; ~~~~~~~~~ else ~~~~ *d++ = '.'; ~~~~~~~~~~~ ++pos; ~~~~~~ if (pos - this_line_begins_at == octets_per_line) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); ~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ charbuf[0] = '\0'; ~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = pos; ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (pos - this_line_begins_at > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %-*.*s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, ~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* ~~ * We do some pre-processor mangling here in order to reduce code for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the 3 log levels info(), warning() and error() that have the same ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * argument list. ~~~~~~~~~~~~~~~~ * We need to map the function calls via ## concatenation and revert ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * to the original function call by a define. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The do-while loop emulates a function call. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define LLinfo info ~~~~~~~~~~~~~~~~~~~ #define LLwarning warning ~~~~~~~~~~~~~~~~~~~~~~~~~ #define LLerror error ~~~~~~~~~~~~~~~~~~~~~ #define octstr_dump_LOGLEVEL(loglevel, ostr, level) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ do { \ ~~~~~~ unsigned char *p, *d, buf[1024], charbuf[256]; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; \ ~~~~~~~~~~~ const int octets_per_line = 16; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ ~ if (ostr == NULL) \ ~~~~~~~~~~~~~~~~~~~ return; \ ~~~~~~~~~ \ ~ seems_valid(ostr); \ ~~~~~~~~~~~~~~~~~~~~ \ ~ LL##loglevel(0, "%*sOctet string at %p:", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); \ ~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s len: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s size: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s immutable: %d", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); \ ~~~~~~~~~~~~~~~~~~~ \ ~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = 0; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); \ ~~~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); \ ~~~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) \ ~~~~~~~~~~~~~~~~~ *d++ = c; \ ~~~~~~~~~~~ else \ ~~~~~~ *d++ = '.'; \ ~~~~~~~~~~~~~ ++pos; \ ~~~~~~~~ if (pos - this_line_begins_at == octets_per_line) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); \ ~~~~~~~~~~~~~~~~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ charbuf[0] = '\0'; \ ~~~~~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = pos; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ } \ ~~~ if (pos - this_line_begins_at > 0) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %-*.*s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, \ ~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ \ ~ LL##loglevel(0, "%*sOctet string dump ends.", level, ""); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } while (0) ~~~~~~~~~~~ void octstr_dump_real(const Octstr *ostr, int level, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ va_list p; ~~~~~~~~~~ unsigned int loglevel; ~~~~~~~~~~~~~~~~~~~~~~ va_start(p, level); ~~~~~~~~~~~~~~~~~~~ loglevel = va_arg(p, unsigned int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(p); ~~~~~~~~~~ switch (loglevel) { ~~~~~~~~~~~~~~~~~~~ case GW_DEBUG: ~~~~~~~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_INFO: ~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(info, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_WARNING: ~~~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(warning, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_ERROR: ~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(error, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ } ~ void octstr_dump_short(Octstr *ostr, int level, const char *name) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char buf[100]; ~~~~~~~~~~~~~~ char *p; ~~~~~~~~ long i; ~~~~~~~ int c; ~~~~~~ if (ostr == NULL) { ~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len < 20) { ~~~~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ for (i = 0; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[i]; ~~~~~~~~~~~~~~~~~~ if (c == '\n') { ~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = 'n'; ~~~~~~~~~~~ } else if (!isprint(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (c == '"') { ~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '"'; ~~~~~~~~~~~ } else if (c == '\\') { ~~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ } else { ~~~~~~~~ *p++ = c; ~~~~~~~~~ } ~ } ~ if (i == ostr->len) { ~~~~~~~~~~~~~~~~~~~~~ *p++ = 0; ~~~~~~~~~ /* We got through the loop without hitting nonprintable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * characters. */ ~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: \"%s\"", level, "", name, buf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ } ~ debug("gwlib.octstr", 0, "%*s%s:", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_dump(ostr, level + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_format and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * A parsed form of the format string. This struct has been carefully ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * defined so that it can be initialized with {0} and it will have ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the correct defaults. ~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct format ~~~~~~~~~~~~~ { ~ int minus; ~~~~~~~~~~ int zero; ~~~~~~~~~ long min_width; ~~~~~~~~~~~~~~~ int has_prec; ~~~~~~~~~~~~~ long prec; ~~~~~~~~~~ long type; ~~~~~~~~~~ }; ~~ static void format_flags(struct format *format, const char **fmt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int done; ~~~~~~~~~ done = 0; ~~~~~~~~~ do ~~ { ~ switch (**fmt) { ~~~~~~~~~~~~~~~~ case '-': ~~~~~~~~~ format->minus = 1; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case '0': ~~~~~~~~~ format->zero = 1; ~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ done = 1; ~~~~~~~~~ } ~ if (!done) ~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } while (!done); ~~~~~~~~~~~~~~~~ } ~ static void format_width(struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~~~~~~~ { ~ char *end; ~~~~~~~~~~ if (**fmt == '*') ~~~~~~~~~~~~~~~~~ { ~ format->min_width = va_arg(VALST(args), int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } else if (isdigit(**(const unsigned char **) fmt)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ format->min_width = strtol(*fmt, &end, 10); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *fmt = end; ~~~~~~~~~~~ /* XXX error checking is missing from here */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static void format_prec(struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~^~~~ gwlib/octstr.c:90:29: note: in definition of macro 'VALPARM' #define VALPARM(y) va_list *y ^ gwlib/octstr.c:89:21: warning: passing argument 4 of 'convert' from incompatible pointer type [-Wincompatible-pointer-types] #define VARGS(x) (&x) ~^~~ gwlib/octstr.c:2498:36: note: in expansion of macro 'VARGS' convert(os, &format, &fmt, VARGS(args)); ^~~~~ gwlib/octstr.c:2300:29: note: expected '__va_list_tag (*)[1]' but argument is of type '__va_list_tag **' #define VALPARM(y) va_list *y ~~~~~~~~~~ #define VALST(z) (*z) ~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Definitions of data structures. These are not visible to the external ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * world -- they may be accessed only via the functions declared in ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr.h. This ensures they really are abstract. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * The octet string. ~~~~~~~~~~~~~~~~~~~ * ~ * `data' is a pointer to dynamically allocated memory are where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets in the string. It may be bigger than the actual length of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. ~~~~~~~~~ * ~ * `len' is the length of the string. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * `size' is the size of the memory area `data' points at. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~ * When `size' is greater than zero, it is at least `len+1', and the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * character at `len' is '\0'. This is so that octstr_get_cstr will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * always work. ~~~~~~~~~~~~~~ * ~ * `immutable' defines whether the octet string is immutable or not. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct Octstr ~~~~~~~~~~~~~ { ~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long len; ~~~~~~~~~ long size; ~~~~~~~~~~ int immutable; ~~~~~~~~~~~~~~ }; ~~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Hash table of immutable octet strings. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define MAX_IMMUTABLES 1024 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Octstr *immutables[MAX_IMMUTABLES]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Mutex immutables_mutex; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static int immutables_init = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static char is_safe[UCHAR_MAX + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * Convert a pointer to a C string literal to a long that can be used ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * for hashing. This is done by converting the pointer into an integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and discarding the lowest to bits to get rid of typical alignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bits. ~~~~~~~ */ ~~ #define CSTR_TO_LONG(ptr) (((unsigned long) ptr) >> 2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * HEX to ASCII preprocessor macro ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define H2B(a) (a >= '0' && a <= '9' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - '0' : (a >= 'a' && a <= 'f' ? \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) \ ~~~ ) ~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Declarations of internal functions. These are defined at the end of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the file. ~~~~~~~~~~~ */ ~~ static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *function); ~~~~~~~~~~~~~~~~~~~~~~ #ifdef NO_GWASSERT ~~~~~~~~~~~~~~~~~~ #define seems_valid(ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~ #else ~~~~~ #define seems_valid(ostr) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ (seems_valid_real(ostr, __FILE__, __LINE__, __func__)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endif ~~~~~~ /*********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Implementations of the functions declared in octstr.h. See the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * header for explanations of what they should do. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* Reserve space for at least 'size' octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static void octstr_grow(Octstr *ostr, long size) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(size >= 0); ~~~~~~~~~~~~~~~~~~~~~ size++; /* make room for the invisible terminating NUL */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (size > ostr->size) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* always reallocate in 1kB chunks */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ size += 1024 - (size % 1024); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_realloc(ostr->data, size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = size; ~~~~~~~~~~~~~~~~~~ } ~ } ~ /* ~~ * Fill is_safe table. is_safe[c] means that c can be left as such when ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * url-encoded. ~~~~~~~~~~~~~~ * RFC 2396 defines the list of characters that need to be encoded. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Space is treated as an exception by the encoding routine; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * it's listed as safe here, but is actually changed to '+'. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void urlcode_init(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i; ~~~~~~ unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; safe[i] != '\0'; ++i) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ is_safe[safe[i]] = 1; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_init(void) ~~~~~~~~~~~~~~~~~~~~~~ { ~ urlcode_init(); ~~~~~~~~~~~~~~~ mutex_init_static(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ immutables_init = 1; ~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_shutdown(void) ~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n; ~~~~~~~~~~ n = 0; ~~~~~~ for (i = 0; i < MAX_IMMUTABLES; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (immutables[i] != NULL) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_free(immutables[i]); ~~~~~~~~~~~~~~~~~~~~~~~ ++n; ~~~~ } ~ } ~ if(n>0) ~~~~~~~ debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_destroy(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_real(const char *cstr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(cstr, strlen(cstr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_create_from_data_real(const char *data, long len, const char *file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long line, const char *func) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (data == NULL) ~~~~~~~~~~~~~~~~~ gw_assert(len == 0); ~~~~~~~~~~~~~~~~~~~~ /* if gw_assert is disabled just return NULL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and caller will check for NULL or just crash. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (len < 0 || (data == NULL && len != 0)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ ostr = gw_malloc_trace(sizeof(*ostr), file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ ostr->len = 0; ~~~~~~~~~~~~~~ ostr->size = 0; ~~~~~~~~~~~~~~~ ostr->data = NULL; ~~~~~~~~~~~~~~~~~~ } else { ~~~~~~~~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->size = len + 1; ~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc_trace(ostr->size, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->immutable = 0; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ Octstr *octstr_imm(const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ long i, index; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ gw_assert(immutables_init); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(cstr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data = (unsigned char *) cstr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mutex_lock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ i = index; ~~~~~~~~~~ for (; ; ) { ~~~~~~~~~~~~ if (immutables[i] == NULL || immutables[i]->data == data) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ i = (i + 1) % MAX_IMMUTABLES; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (i == index) ~~~~~~~~~~~~~~~ panic(0, "Too many immutable strings."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ os = immutables[i]; ~~~~~~~~~~~~~~~~~~~ if (os == NULL) { ~~~~~~~~~~~~~~~~~ /* ~~ * Can't use octstr_create() because it copies the string, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which would break our hashing. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ os = gw_malloc(sizeof(*os)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ os->data = data; ~~~~~~~~~~~~~~~~ os->len = strlen(data); ~~~~~~~~~~~~~~~~~~~~~~~ os->size = os->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~ os->immutable = 1; ~~~~~~~~~~~~~~~~~~ immutables[i] = os; ~~~~~~~~~~~~~~~~~~~ seems_valid(os); ~~~~~~~~~~~~~~~~ } ~ mutex_unlock(&immutables_mutex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ } ~ void octstr_destroy(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr != NULL) { ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (!ostr->immutable) { ~~~~~~~~~~~~~~~~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ gw_free(ostr); ~~~~~~~~~~~~~~ } ~ } ~ } ~ void octstr_destroy_item(void *os) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ } ~ long octstr_len(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr->len; ~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (len > ostr->len - from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - from; ~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data + from, len, file, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ line, func); ~~~~~~~~~~~~ } ~ Octstr *octstr_duplicate_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return octstr_create_from_data_trace(ostr->data, ostr->len, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *ostr; ~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len = ostr1->len + ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->size = ostr->len + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data = gw_malloc(ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr1->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data, ostr1->data, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ostr; ~~~~~~~~~~~~ } ~ int octstr_get_char(const Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len || pos < 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_char(Octstr *ostr, long pos, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos < ostr->len) ~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = ch; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(buf != NULL); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (pos + len > ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len - pos; ~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) ~~~~~~~~~~~~ memcpy(buf, ostr->data + pos, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ char *octstr_get_cstr_real(const Octstr *ostr, const char *file, long line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *func) ~~~~~~~~~~~~~~~~~ { ~ if (!ostr) ~~~~~~~~~~ return "(null)"; ~~~~~~~~~~~~~~~~ seems_valid_real(ostr, file, line, func); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return ""; ~~~~~~~~~~ return ostr->data; ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_from_hex(Octstr *ostr, char *hex) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *output; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ output = octstr_create(hex); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_hex_to_binary(output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append(ostr, output); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_destroy(output); ~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_binary_to_hex(Octstr *ostr, int uppercase) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *hexits; ~~~~~~~~~~~~~~~~~~~~~~ long i, tmp; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* In-place modification must be done back-to-front to avoid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * overwriting the data while we read it. Even the order of ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the two assignments is important, to get i == 0 right. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = ostr->len - 1; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tmp = i << 1; /* tmp = i * 2; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[tmp] = hexits[ostr->data[i] >> 4]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = ostr->len * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_hex_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len, i; ~~~~~~~~~~~~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ /* Check if it's in the right format */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ /* Convert ascii data to binary values */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, p = ostr->data; i < len; i++, p++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (*p >= '0' && *p <= '9') ~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p -= '0'; ~~~~~~~~~~ else if (*p >= 'a' && *p <= 'f') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'a' + 10; ~~~~~~~~~~~~~~~~~~~ else if (*p >= 'A' && *p <= 'F') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *p = *p - 'A' + 10; ~~~~~~~~~~~~~~~~~~~ else { ~~~~~~ /* isxdigit checked the whole string, so we should ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not be able to get here. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(0); ~~~~~~~~~~~~~ *p = 0; ~~~~~~~ } ~ } ~ /* De-hexing will compress data by factor of 2 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len / 2; ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = len; ~~~~~~~~~~~~~~~~ ostr->data[len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ void octstr_binary_to_base64(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ static const unsigned char base64[64] = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long triplets; ~~~~~~~~~~~~~~ long lines; ~~~~~~~~~~~ long orig_len; ~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ long from, to; ~~~~~~~~~~~~~~ int left_on_line; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) { ~~~~~~~~~~~~~~~~~~~~~ /* Always terminate with CR LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr, octstr_imm("\015\012"), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* The lines must be 76 characters each (or less), and each ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplet will expand to 4 characters, so we can fit 19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * triplets on one line. We need a CR LF after each line, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which will add 2 octets per 19 triplets (rounded up). */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ triplets = (ostr->len + 2) / 3; /* round up */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lines = (triplets + 18) / 19; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, triplets * 4 + lines * 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ orig_len = ostr->len; ~~~~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ ostr->len = triplets * 4 + lines * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~ /* This function works back-to-front, so that encoded data will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * not overwrite source data. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * from points to the start of the last triplet (which may be ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an odd-sized one), and to points to the start of where the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * last quad should go. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ from = (triplets - 1) * 3; ~~~~~~~~~~~~~~~~~~~~~~~~~~ to = (triplets - 1) * 4 + (lines - 1) * 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* First write the CR LF after the last quad */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = triplets - ((lines - 1) * 19); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* base64 encoding is in 3-octet units. To handle leftover ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octets, conceptually we have to zero-pad up to the next ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * 6-bit unit, and pad with '=' characters for missing 6-bit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * units. ~~~~~~~~ * We do it by first completing the first triplet with ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * zero-octets, and after the loop replacing some of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * result characters with '=' characters. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * There is enough room for this, because even with a 1 or 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octet source string, space for four octets of output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * will be reserved. ~~~~~~~~~~~~~~~~~~~ */ ~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ data[orig_len] = 0; ~~~~~~~~~~~~~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ data[orig_len + 1] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ /* Now we only have perfect triplets. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (from >= 0) { ~~~~~~~~~~~~~~~~~~~ long whole_triplet; ~~~~~~~~~~~~~~~~~~~ /* Add a newline, if necessary */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (left_on_line == 0) { ~~~~~~~~~~~~~~~~~~~~~~~~ to -= 2; ~~~~~~~~ data[to + 5] = 10; /* LF */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 4] = 13; /* CR */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ left_on_line = 19; ~~~~~~~~~~~~~~~~~~ } ~ whole_triplet = (data[from] << 16) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (data[from + 1] << 8) | ~~~~~~~~~~~~~~~~~~~~~~~ data[from + 2]; ~~~~~~~~~~~~~~~ data[to + 3] = base64[whole_triplet % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 2] = base64[(whole_triplet >> 6) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to + 1] = base64[(whole_triplet >> 12) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to] = base64[(whole_triplet >> 18) % 64]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ to -= 4; ~~~~~~~~ from -= 3; ~~~~~~~~~~ left_on_line--; ~~~~~~~~~~~~~~~ } ~ gw_assert(left_on_line == 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(from == -3); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(to == -4); ~~~~~~~~~~~~~~~~~~~~ /* Insert padding characters in the last quad. Remember that ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * there is a CR LF between the last quad and the end of the ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * string. */ ~~~~~~~~~~~~ switch (orig_len % 3) { ~~~~~~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(data[ostr->len - 4] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 4] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: ~~~~~~~ gw_assert(data[ostr->len - 3] == 'A'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[ostr->len - 3] = '='; ~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_base64_to_binary(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long triplet; ~~~~~~~~~~~~~ long pos, len; ~~~~~~~~~~~~~~ long to; ~~~~~~~~ int quadpos = 0; ~~~~~~~~~~~~~~~~ int warned = 0; ~~~~~~~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ to = 0; ~~~~~~~ triplet = 0; ~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ for (pos = 0; pos < len; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c = data[pos]; ~~~~~~~~~~~~~~~~~~ int sixbits; ~~~~~~~~~~~~ if (c >= 'A' && c <= 'Z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = c - 'A'; ~~~~~~~~~~~~~~~~~~ } else if (c >= 'a' && c <= 'z') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 26 + c - 'a'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c >= '0' && c <= '9') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sixbits = 52 + c - '0'; ~~~~~~~~~~~~~~~~~~~~~~~ } else if (c == '+') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 62; ~~~~~~~~~~~~~ } else if (c == '/') { ~~~~~~~~~~~~~~~~~~~~~~ sixbits = 63; ~~~~~~~~~~~~~ } else if (c == '=') { ~~~~~~~~~~~~~~~~~~~~~~ /* These can only occur at the end of encoded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * text. RFC 2045 says we can assume it really ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is the end. */ ~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (isspace(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~ /* skip whitespace */ ~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } else { ~~~~~~~~ if (!warned) { ~~~~~~~~~~~~~~ warning(0, "Unusual characters in base64 " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "encoded text."); ~~~~~~~~~~~~~~~~~ warned = 1; ~~~~~~~~~~~ } ~ continue; ~~~~~~~~~ } ~ triplet = (triplet << 6) | sixbits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos++; ~~~~~~~~~~ if (quadpos == 4) { ~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 16) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 8) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = triplet & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ quadpos = 0; ~~~~~~~~~~~~ } ~ } ~ /* Deal with leftover octets */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ switch (quadpos) { ~~~~~~~~~~~~~~~~~~ case 0: ~~~~~~~ break; ~~~~~~ case 3: /* triplet has 18 bits, we want the first 16 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 10) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 2) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 2: /* triplet has 12 bits, we want the first 8 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ data[to++] = (triplet >> 4) & 0xff; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case 1: ~~~~~~~ warning(0, "Bad padding in base64 encoded text."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ ostr->len = to; ~~~~~~~~~~~~~~~ data[to] = '\0'; ~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtol wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ long number; ~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(base == 0 || (base >= 2 && base <= 36)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtol(ostr->data + pos, &endptr, base); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_parse_double(double *nump, Octstr *ostr, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* strtod wants a char *, and we have to compare the result to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * an unsigned char *. The easiest way to avoid warnings without ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * introducing typecasts is to use two variables. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *endptr; ~~~~~~~~~~~~~ unsigned char *endpos; ~~~~~~~~~~~~~~~~~~~~~~ double number; ~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(nump != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ errno = 0; ~~~~~~~~~~ number = strtod(ostr->data + pos, &endptr); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ endpos = endptr; ~~~~~~~~~~~~~~~~ if (errno == ERANGE) ~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (endpos == ostr->data + pos) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ errno = EINVAL; ~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ *nump = number; ~~~~~~~~~~~~~~~ return endpos - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_check_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t filter) ~~~~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!filter(ostr->data[pos])) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ return 1; ~~~~~~~~~ } ~ void octstr_convert_range(Octstr *ostr, long pos, long len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_func_t map) ~~~~~~~~~~~~~~~~~~ { ~ long end = pos + len; ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(len >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ if (end > ostr->len) ~~~~~~~~~~~~~~~~~~~~ end = ostr->len; ~~~~~~~~~~~~~~~~ for ( ; pos < end; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = map(ostr->data[pos]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ static int inline make_printable(int c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return isprint(c) ? c : '.'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_convert_printable(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_convert_range(ostr, 0, ostr->len, make_printable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_compare(const Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int ret; ~~~~~~~~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len == 0 && ostr2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr1->len > 0 && ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ ret = memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == 0) { ~~~~~~~~~~~~~~~ if (ostr1->len < ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ else if (ostr1->len > ostr2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = 1; ~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_case_compare(const Octstr *os1, const Octstr *os2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c1, c2; ~~~~~~~~~~~ long i, len; ~~~~~~~~~~~~ seems_valid(os1); ~~~~~~~~~~~~~~~~~ seems_valid(os2); ~~~~~~~~~~~~~~~~~ if (os1->len < os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~ len = os1->len; ~~~~~~~~~~~~~~~ else ~~~~ len = os2->len; ~~~~~~~~~~~~~~~ if (len == 0) { ~~~~~~~~~~~~~~~ if (os1->len == 0 && os2->len > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (os1->len > 0 && os2->len == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 1; ~~~~~~~~~ return 0; ~~~~~~~~~ } ~ c1 = c2 = 0; ~~~~~~~~~~~~ for (i = 0; i < len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (i == len) { ~~~~~~~~~~~~~~~ if (i == os1->len && i == os2->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (i == os1->len) ~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 1; ~~~~~~~~~ } else { ~~~~~~~~ /* ~~ c1 = toupper(os1->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(os2->data[i]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ if (c1 < c2) ~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (c1 == c2) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return 1; ~~~~~~~~~ } ~ } ~ int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ if ((ostr1->len < ostr2->len) && (ostr1->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len; ~~~~~~~~~~~~~~~~~ else if ((ostr2->len < ostr1->len) && (ostr2->len < n)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr2->len; ~~~~~~~~~~~~~~~~~ else ~~~~ len = n; ~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return 0; ~~~~~~~~~ return memcmp(ostr1->data, ostr2->data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~ return strcmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_case_compare(const Octstr *ostr, const char *str) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp("", str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ return strcasecmp(ostr->data, str); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_str_ncompare(const Octstr *ostr, const char *str, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (str == NULL) ~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ if (ostr->data == NULL) ~~~~~~~~~~~~~~~~~~~~~~~ return 1; /* str grater */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ return strncmp(ostr->data, str, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_search_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ p = memchr(ostr->data + pos, ch, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!p) ~~~~~~~ return -1; ~~~~~~~~~~ return p - ostr->data; ~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_rsearch_char(const Octstr *ostr, int ch, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ for (i = pos; i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->data[i] == ch) ~~~~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ seems_valid(chars); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < octstr_len(chars); i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = octstr_search_char(ostr, octstr_get_char(chars, i), pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (j != -1) ~~~~~~~~~~~~ return j; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (needle->len == 1) ~~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle->data[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle->data[0]; ~~~~~~~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle->data, needle->len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, j; ~~~~~~~~~~ int c1, c2; ~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ seems_valid(needle); ~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle->len == 0) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ for (i = pos; i <= haystack->len - needle->len && i < n; ++i) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (j = 0; j < needle->len && j < n; ++j) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c1 = toupper(haystack->data[i + j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c2 = toupper(needle->data[j]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c1 != c2) ~~~~~~~~~~~~~ break; ~~~~~~ } ~ if (j == needle->len) ~~~~~~~~~~~~~~~~~~~~~ return i; ~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ long octstr_str_search(const Octstr *haystack, const char *needle, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int first; ~~~~~~~~~~ int needle_len; ~~~~~~~~~~~~~~~ seems_valid(haystack); ~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos >= 0); ~~~~~~~~~~~~~~~~~~~~ /* Always "find" an empty string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle == NULL || needle[0] == '\0') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ needle_len = strlen(needle); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (needle_len == 1) ~~~~~~~~~~~~~~~~~~~~ return octstr_search_char(haystack, needle[0], pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* For each occurrence of needle's first character in ostr, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * check if the rest of needle follows. Stop if there are no ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * more occurrences, or if the rest of needle can't possibly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in the haystack. */ ~~~~~~~~~~~~~~~~~~~~~~~~~ first = needle[0]; ~~~~~~~~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (pos >= 0 && haystack->len - pos >= needle_len) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (memcmp(haystack->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ needle, needle_len) == 0) ~~~~~~~~~~~~~~~~~~~~~~~~~ return pos; ~~~~~~~~~~~ pos = octstr_search_char(haystack, first, pos + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return -1; ~~~~~~~~~~ } ~ int octstr_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ if (fwrite(ostr->data, ostr->len, 1, f) != 1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error(errno, "Couldn't write all of octet string to file."); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return 0; ~~~~~~~~~ } ~ int octstr_pretty_print(FILE *f, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ long i; ~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ for (i = 0; i < ostr->len; ++i, ++p) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isprint(*p)) ~~~~~~~~~~~~~~~~ fprintf(f, "%c", *p); ~~~~~~~~~~~~~~~~~~~~~ else ~~~~ fprintf(f, "\\x%02x", *p); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ if (ferror(f)) ~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ return 0; ~~~~~~~~~ } ~ int octstr_write_to_socket(int socket, Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long len; ~~~~~~~~~ unsigned char *data; ~~~~~~~~~~~~~~~~~~~~ int ret; ~~~~~~~~ gw_assert(socket >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ data = ostr->data; ~~~~~~~~~~~~~~~~~~ len = ostr->len; ~~~~~~~~~~~~~~~~ while (len > 0) { ~~~~~~~~~~~~~~~~~ ret = write(socket, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret == -1) { ~~~~~~~~~~~~~~~~ if (errno != EINTR) { ~~~~~~~~~~~~~~~~~~~~~ error(errno, "Writing to socket failed"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ } else { ~~~~~~~~ /* ret may be less than len */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ len -= ret; ~~~~~~~~~~~ data += ret; ~~~~~~~~~~~~ } ~ } ~ return 0; ~~~~~~~~~ } ~ long octstr_write_data(Octstr *ostr, int fd, long from) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long ret; ~~~~~~~~~ gw_assert(fd >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(from >= 0); ~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (from >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ ret = write(fd, ostr->data + from, ostr->len - from); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ret < 0) { ~~~~~~~~~~~~~~ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ error(errno, "Error writing %ld octets to fd %d:", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len - from, fd); ~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ return ret; ~~~~~~~~~~~ } ~ int octstr_append_from_socket(Octstr *ostr, int socket) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char buf[4096]; ~~~~~~~~~~~~~~~~~~~~~~~~ int len; ~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ again: ~~~~~~ len = recv(socket, buf, sizeof(buf), 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len < 0 && errno == EINTR) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ goto again; ~~~~~~~~~~~ if (len < 0) { ~~~~~~~~~~~~~~ error(errno, "Could not read from socket %d", socket); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return -1; ~~~~~~~~~~ } ~ octstr_append_data(ostr, buf, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return len; ~~~~~~~~~~~ } ~ void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr2 == NULL) ~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr2); ~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr2->len == 0) ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr1, ostr1->len + ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr1->data + pos + ostr2->len, ostr1->data + pos, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos); ~~~~~~~~~~~~~~~~~~ memcpy(ostr1->data + pos, ostr2->data, ostr2->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len += ostr2->len; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ void octstr_truncate(Octstr *ostr, int new_len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(new_len >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ if (new_len >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ ostr->len = new_len; ~~~~~~~~~~~~~~~~~~~~ ostr->data[new_len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ static int iscrlf(unsigned char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return c == '\n' || c == '\r'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_crlfs(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (iscrlf(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_strip_nonalphanums(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int start = 0, end, len = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Remove white space from the beginning of the text */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, start)) && ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start <= octstr_len(text)) ~~~~~~~~~~~~~~~~~~~~~~~~~~ start ++; ~~~~~~~~~ if (start > 0) ~~~~~~~~~~~~~~ octstr_delete(text, 0, start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* and from the end. */ ~~~~~~~~~~~~~~~~~~~~~~~ if ((len = octstr_len(text)) > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = len = len - 1; ~~~~~~~~~~~~~~~~~~~~ while (!isalnum(octstr_get_char(text, end)) && end >= 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end--; ~~~~~~ octstr_delete(text, end + 1, len - end); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_shrink_blanks(Octstr *text) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int i, j, end; ~~~~~~~~~~~~~~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ gw_assert(!text->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end = octstr_len(text); ~~~~~~~~~~~~~~~~~~~~~~~ /* Shrink white spaces to one */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0; i < end; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (isspace(octstr_get_char(text, i))) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Change the remaining space into single space. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (octstr_get_char(text, i) != ' ') ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_set_char(text, i, ' '); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j = i = i + 1; ~~~~~~~~~~~~~~ while (isspace(octstr_get_char(text, j))) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ j ++; ~~~~~ if (j - i > 1) ~~~~~~~~~~~~~~ octstr_delete(text, i, j - i); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ seems_valid(text); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (len == 0) ~~~~~~~~~~~~~ return; ~~~~~~~ octstr_grow(ostr, ostr->len + len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) { /* only if neccessary*/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + len, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ memcpy(ostr->data + pos, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += len; ~~~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_insert_char(Octstr *ostr, long pos, const char c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos <= ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, ostr->len + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len > pos) ~~~~~~~~~~~~~~~~~~~~ memmove(ostr->data + pos + 1, ostr->data + pos, ostr->len - pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ memcpy(ostr->data + pos, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->len += 1; ~~~~~~~~~~~~~~~ ostr->data[ostr->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_data(Octstr *ostr, const char *data, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, data, len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append(Octstr *ostr1, const Octstr *ostr2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ gw_assert(ostr1 != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert(ostr1, ostr2, ostr1->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_cstr(Octstr *ostr, const char *cstr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ octstr_insert_data(ostr, ostr->len, cstr, strlen(cstr)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_char(Octstr *ostr, int ch) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char c = ch; ~~~~~~~~~~~~~~~~~~~~~ gw_assert(ch >= 0); ~~~~~~~~~~~~~~~~~~~ gw_assert(ch <= UCHAR_MAX); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(ostr, ostr->len, &c, 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_delete(Octstr *ostr1, long pos, long len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ gw_assert(!ostr1->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~ pos = ostr1->len; ~~~~~~~~~~~~~~~~~ if (pos + len > ostr1->len) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ len = ostr1->len - pos; ~~~~~~~~~~~~~~~~~~~~~~~ if (len > 0) { ~~~~~~~~~~~~~~ memmove(ostr1->data + pos, ostr1->data + pos + len, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len - pos - len); ~~~~~~~~~~~~~~~~~~~~~~~~ ostr1->len -= len; ~~~~~~~~~~~~~~~~~~ ostr1->data[ostr1->len] = '\0'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr1); ~~~~~~~~~~~~~~~~~~~ } ~ Octstr *octstr_read_file(const char *filename) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ FILE *f; ~~~~~~~~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ long n; ~~~~~~~ gw_assert(filename != NULL); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ f = fopen(filename, "r"); ~~~~~~~~~~~~~~~~~~~~~~~~~ if (f == NULL) { ~~~~~~~~~~~~~~~~ error(errno, "fopen failed: couldn't open `%s'", filename); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while ((n = fread(buf, 1, sizeof(buf), f)) > 0) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_insert_data(os, octstr_len(os), buf, n); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ (void) fclose(f); ~~~~~~~~~~~~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ Octstr *octstr_read_pipe(FILE *f) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ Octstr *os; ~~~~~~~~~~~ char buf[4096]; ~~~~~~~~~~~~~~~ gw_assert(f != NULL); ~~~~~~~~~~~~~~~~~~~~~ os = octstr_create(""); ~~~~~~~~~~~~~~~~~~~~~~~ if (os == NULL) ~~~~~~~~~~~~~~~ goto error; ~~~~~~~~~~~ while (fgets(buf, sizeof(buf), f) != NULL) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_data(os, buf, strlen(buf)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return os; ~~~~~~~~~~ error: ~~~~~~ octstr_destroy(os); ~~~~~~~~~~~~~~~~~~~ return NULL; ~~~~~~~~~~~~ } ~ List *octstr_split_words(const Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p; ~~~~~~~~~~~~~~~~~ List *list; ~~~~~~~~~~~ Octstr *word; ~~~~~~~~~~~~~ long i, start, end; ~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ p = ostr->data; ~~~~~~~~~~~~~~~ i = 0; ~~~~~~ for (; ; ) { ~~~~~~~~~~~~ while (i < ostr->len && isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ start = i; ~~~~~~~~~~ while (i < ostr->len && !isspace(*p)) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++p; ~~~~ ++i; ~~~~ } ~ end = i; ~~~~~~~~ if (start == end) ~~~~~~~~~~~~~~~~~ break; ~~~~~~ word = octstr_create_from_data(ostr->data + start, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end - start); ~~~~~~~~~~~~~ gwlist_append(list, word); ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ return list; ~~~~~~~~~~~~ } ~ List *octstr_split(const Octstr *os, const Octstr *sep) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ List *list; ~~~~~~~~~~~ long next, pos, seplen; ~~~~~~~~~~~~~~~~~~~~~~~ list = gwlist_create(); ~~~~~~~~~~~~~~~~~~~~~~~ pos = 0; ~~~~~~~~ seplen = octstr_len(sep); ~~~~~~~~~~~~~~~~~~~~~~~~~ while ((next = octstr_search(os, sep, pos)) >= 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, next - pos)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pos = next + seplen; ~~~~~~~~~~~~~~~~~~~~ } ~ if (pos < octstr_len(os)) ~~~~~~~~~~~~~~~~~~~~~~~~~ gwlist_append(list, octstr_copy(os, pos, octstr_len(os))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return list; ~~~~~~~~~~~~ } ~ int octstr_item_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ int octstr_item_case_match(void *item, void *pattern) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ return octstr_case_compare(item, pattern) == 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_url_encode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long i, n, len = 0; ~~~~~~~~~~~~~~~~~~~ int all_safe; ~~~~~~~~~~~~~ unsigned char c, *str, *str2, *res, *hexits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ /* calculate new length */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = n = 0, str = ostr->data, all_safe = 1; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ all_safe = 0; ~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ n++; ~~~~ all_safe = 0; ~~~~~~~~~~~~~ } ~ } ~ if (all_safe) /* we are done, all chars are safe */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ hexits = "0123456789ABCDEF"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* ~~ * no need to reallocate if n == 0, so we make replace in place. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * NOTE: we don't do if (xxx) ... else ... because conditional jump ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * is not so fast as just compare (alex). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ res = str2 = (n ? gw_malloc((len = ostr->len + 2 * n + 1)) : ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (i = 0, str = ostr->data; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = *str++; ~~~~~~~~~~~ if (c == ' ') { ~~~~~~~~~~~~~~~ *str2++ = '+'; ~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ if (!is_safe[c]) { ~~~~~~~~~~~~~~~~~~ *str2++ = '%'; ~~~~~~~~~~~~~~ *str2++ = hexits[c >> 4 & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *str2++ = hexits[c & 0xf]; ~~~~~~~~~~~~~~~~~~~~~~~~~~ continue; ~~~~~~~~~ } ~ *str2++ = c; ~~~~~~~~~~~~ } ~ *str2 = 0; ~~~~~~~~~~ /* we made replace in place */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (n) { ~~~~~~~~ gw_free(ostr->data); ~~~~~~~~~~~~~~~~~~~~ ostr->data = res; ~~~~~~~~~~~~~~~~~ ostr->size = len; ~~~~~~~~~~~~~~~~~ ostr->len = len - 1; ~~~~~~~~~~~~~~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ int octstr_url_decode(Octstr *ostr) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *string; ~~~~~~~~~~~~~~~~~~~~~~ unsigned char *dptr; ~~~~~~~~~~~~~~~~~~~~ int code, code2, ret = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr->len == 0) ~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ string = ostr->data; ~~~~~~~~~~~~~~~~~~~~ dptr = ostr->data; ~~~~~~~~~~~~~~~~~~ do { ~~~~ if (*string == '%') { ~~~~~~~~~~~~~~~~~~~~~ if (*(string + 1) == '\0' || *(string + 2) == '\0') { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ break; ~~~~~~ } ~ code = H2B(*(string + 1)); ~~~~~~~~~~~~~~~~~~~~~~~~~~ code2 = H2B(*(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (code == -1 || code2 == -1) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *string, *(string + 1), *(string + 2)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ ret = -1; ~~~~~~~~~ continue; ~~~~~~~~~ } ~ *dptr++ = code << 4 | code2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string += 3; ~~~~~~~~~~~~ } ~ else if (*string == '+') { ~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr++ = ' '; ~~~~~~~~~~~~~~ string++; ~~~~~~~~~ } else ~~~~~~ *dptr++ = *string++; ~~~~~~~~~~~~~~~~~~~~ } while (*string); /* we stop here because it terimates encoded string */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *dptr = '\0'; ~~~~~~~~~~~~~ ostr->len = (dptr - ostr->data); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ return ret; ~~~~~~~~~~~ } ~ long octstr_get_bits(Octstr *ostr, long bitpos, int numbits) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ long result; ~~~~~~~~~~~~ int mask; ~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* This also takes care of the len == 0 case */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return 0; ~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* It's easy if the range fits in one octet */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return (ostr->data[pos] >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ result = 0; ~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ result = (result << 8) | ostr->data[pos]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ if (pos >= ostr->len) ~~~~~~~~~~~~~~~~~~~~~ return (result << numbits) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ result <<= numbits; ~~~~~~~~~~~~~~~~~~~ result |= ostr->data[pos] >> (8 - numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return result & mask; ~~~~~~~~~~~~~~~~~~~~~ } ~ void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ unsigned long value) ~~~~~~~~~~~~~~~~~~~~ { ~ long pos; ~~~~~~~~~ unsigned long mask; ~~~~~~~~~~~~~~~~~~~ int shiftwidth; ~~~~~~~~~~~~~~~ int bits; ~~~~~~~~~ int maxlen; ~~~~~~~~~~~ int c; ~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ gw_assert(!ostr->immutable); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(bitpos >= 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits <= 32); ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(numbits >= 0); ~~~~~~~~~~~~~~~~~~~~~~~~ maxlen = (bitpos + numbits + 7) / 8; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (maxlen > ostr->len) { ~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_grow(ostr, maxlen); ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Make sure the new octets start out with value 0 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = ostr->len; pos < maxlen; pos++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = 0; ~~~~~~~~~~~~~~~~~~~~ } ~ ostr->len = maxlen; ~~~~~~~~~~~~~~~~~~~ ostr->data[maxlen] = 0; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ /* mask is also the largest value that fits */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(value <= mask); ~~~~~~~~~~~~~~~~~~~~~~~~~ pos = bitpos / 8; ~~~~~~~~~~~~~~~~~ bitpos = bitpos % 8; ~~~~~~~~~~~~~~~~~~~~ /* Does the range fit in one octet? */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (bitpos + numbits <= 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* shiftwidth is the number of bits to ignore on the right. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * bitpos 0 is the leftmost bit. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - (bitpos + numbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Extract the bits we don't want to affect */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ /* Otherwise... */ ~~~~~~~~~~~~~~~~~~ /* If speed is a problem here, we could have separate cases for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the first octet (which may have bitpos > 0), and the rest, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * which don't. */ ~~~~~~~~~~~~~~~~~ while (bitpos + numbits > 8) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* We want this many bits from the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bits = 8 - bitpos; ~~~~~~~~~~~~~~~~~~ /* There are this many bits to their right in the value */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = numbits - bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Construct a mask for "bits" bits on the far right */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << bits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~ /* Get the bits we want */ ~~~~~~~~~~~~~~~~~~~~~~~~~~ c = (value >> shiftwidth) & mask; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Merge them with the bits that are already there */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = (ostr->data[pos] & ~mask) | c; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ numbits -= (8 - bitpos); ~~~~~~~~~~~~~~~~~~~~~~~~ bitpos = 0; ~~~~~~~~~~~ pos++; ~~~~~~ } ~ gw_assert(bitpos == 0); ~~~~~~~~~~~~~~~~~~~~~~~ gw_assert(pos < ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Set remaining bits. This is just like the single-octet case ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * before the loop, except that we know bitpos is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mask = (1 << numbits) - 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~ shiftwidth = 8 - numbits; ~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[pos] & ~(mask << shiftwidth); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c |= value << shiftwidth; ~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->data[pos] = c; ~~~~~~~~~~~~~~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ } ~ void octstr_append_uintvar(Octstr *ostr, unsigned long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ /* A uintvar is defined to be up to 32 bits large, so it will ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * fit in 5 octets. */ ~~~~~~~~~~~~~~~~~~~~~ unsigned char octets[5]; ~~~~~~~~~~~~~~~~~~~~~~~~ int i; ~~~~~~ int start; ~~~~~~~~~~ /* Handle last byte separately; it has no continuation bit, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * and must be encoded even if value is 0. */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[4] = value & 0x7f; ~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ for (i = 3; value > 0 && i >= 0; i--) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets[i] = 0x80 | (value & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value >>= 7; ~~~~~~~~~~~~ } ~ start = i + 1; ~~~~~~~~~~~~~~ octstr_append_data(ostr, octets + start, 5 - start); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int c; ~~~~~~ int count; ~~~~~~~~~~ unsigned long ui; ~~~~~~~~~~~~~~~~~ ui = 0; ~~~~~~~ for (count = 0; count < 5; count++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos + count); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (c < 0) ~~~~~~~~~~ return -1; ~~~~~~~~~~ ui = (ui << 7) | (c & 0x7f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!(c & 0x80)) { ~~~~~~~~~~~~~~~~~~ *value = ui; ~~~~~~~~~~~~ return pos + count + 1; ~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ return -1; ~~~~~~~~~~ } ~ void octstr_append_decimal(Octstr *ostr, long value) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char tmp[128]; ~~~~~~~~~~~~~~ sprintf(tmp, "%ld", value); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_append_cstr(ostr, tmp); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_dump... and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ static void octstr_dump_debug(const Octstr *ostr, int level) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ unsigned char *p, *d, buf[1024], charbuf[256]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; ~~~~~~~~~ const int octets_per_line = 16; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (ostr == NULL) ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); ~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s len: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); ~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s size: %lu", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s immutable: %d", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); ~~~~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = 0; ~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); ~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); ~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) ~~~~~~~~~~~~~~~ *d++ = c; ~~~~~~~~~ else ~~~~ *d++ = '.'; ~~~~~~~~~~~ ++pos; ~~~~~~ if (pos - this_line_begins_at == octets_per_line) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); ~~~~~~~~~~~~~~ buf[0] = '\0'; ~~~~~~~~~~~~~~ charbuf[0] = '\0'; ~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ d = charbuf; ~~~~~~~~~~~~ this_line_begins_at = pos; ~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ if (pos - this_line_begins_at > 0) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; ~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s data: %-*.*s %s", level, "", ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, ~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /* ~~ * We do some pre-processor mangling here in order to reduce code for ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the 3 log levels info(), warning() and error() that have the same ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * argument list. ~~~~~~~~~~~~~~~~ * We need to map the function calls via ## concatenation and revert ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * to the original function call by a define. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The do-while loop emulates a function call. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ #define LLinfo info ~~~~~~~~~~~~~~~~~~~ #define LLwarning warning ~~~~~~~~~~~~~~~~~~~~~~~~~ #define LLerror error ~~~~~~~~~~~~~~~~~~~~~ #define octstr_dump_LOGLEVEL(loglevel, ostr, level) \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ do { \ ~~~~~~ unsigned char *p, *d, buf[1024], charbuf[256]; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long pos; \ ~~~~~~~~~~~ const int octets_per_line = 16; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int c, this_line_begins_at; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ ~ if (ostr == NULL) \ ~~~~~~~~~~~~~~~~~~~ return; \ ~~~~~~~~~ \ ~ seems_valid(ostr); \ ~~~~~~~~~~~~~~~~~~~~ \ ~ LL##loglevel(0, "%*sOctet string at %p:", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (void *) ostr); \ ~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s len: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->len); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s size: %lu", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (unsigned long) ostr->size); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL##loglevel(0, "%*s immutable: %d", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ostr->immutable); \ ~~~~~~~~~~~~~~~~~~~ \ ~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = 0; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~ for (pos = 0; pos < octstr_len(ostr); ) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = octstr_get_char(ostr, pos); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sprintf(p, "%02x ", c); \ ~~~~~~~~~~~~~~~~~~~~~~~~~ p = strchr(p, '\0'); \ ~~~~~~~~~~~~~~~~~~~~~~ if (isprint(c)) \ ~~~~~~~~~~~~~~~~~ *d++ = c; \ ~~~~~~~~~~~ else \ ~~~~~~ *d++ = '.'; \ ~~~~~~~~~~~~~ ++pos; \ ~~~~~~~~ if (pos - this_line_begins_at == octets_per_line) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buf, charbuf); \ ~~~~~~~~~~~~~~~~ buf[0] = '\0'; \ ~~~~~~~~~~~~~~~~ charbuf[0] = '\0'; \ ~~~~~~~~~~~~~~~~~~~~ p = buf; \ ~~~~~~~~~~ d = charbuf; \ ~~~~~~~~~~~~~~ this_line_begins_at = pos; \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ } \ ~~~ if (pos - this_line_begins_at > 0) { \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *d = '\0'; \ ~~~~~~~~~~~~ LL##loglevel(0, "%*s data: %-*.*s %s", level, "", \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, \ ~~~~~~~~~~~~~~~~~~~~ octets_per_line*3, buf, charbuf); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } \ ~~~ \ ~ LL##loglevel(0, "%*sOctet string dump ends.", level, ""); \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } while (0) ~~~~~~~~~~~ void octstr_dump_real(const Octstr *ostr, int level, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ va_list p; ~~~~~~~~~~ unsigned int loglevel; ~~~~~~~~~~~~~~~~~~~~~~ va_start(p, level); ~~~~~~~~~~~~~~~~~~~ loglevel = va_arg(p, unsigned int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ va_end(p); ~~~~~~~~~~ switch (loglevel) { ~~~~~~~~~~~~~~~~~~~ case GW_DEBUG: ~~~~~~~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_INFO: ~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(info, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_WARNING: ~~~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(warning, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case GW_ERROR: ~~~~~~~~~~~~~~ octstr_dump_LOGLEVEL(error, ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ octstr_dump_debug(ostr, level); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } ~ } ~ void octstr_dump_short(Octstr *ostr, int level, const char *name) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ char buf[100]; ~~~~~~~~~~~~~~ char *p; ~~~~~~~~ long i; ~~~~~~~ int c; ~~~~~~ if (ostr == NULL) { ~~~~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ seems_valid(ostr); ~~~~~~~~~~~~~~~~~~ if (ostr->len < 20) { ~~~~~~~~~~~~~~~~~~~~~ p = buf; ~~~~~~~~ for (i = 0; i < ostr->len; i++) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c = ostr->data[i]; ~~~~~~~~~~~~~~~~~~ if (c == '\n') { ~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = 'n'; ~~~~~~~~~~~ } else if (!isprint(c)) { ~~~~~~~~~~~~~~~~~~~~~~~~~ break; ~~~~~~ } else if (c == '"') { ~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '"'; ~~~~~~~~~~~ } else if (c == '\\') { ~~~~~~~~~~~~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ *p++ = '\\'; ~~~~~~~~~~~~ } else { ~~~~~~~~ *p++ = c; ~~~~~~~~~ } ~ } ~ if (i == ostr->len) { ~~~~~~~~~~~~~~~~~~~~~ *p++ = 0; ~~~~~~~~~ /* We got through the loop without hitting nonprintable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * characters. */ ~~~~~~~~~~~~~~~~ debug("gwlib.octstr", 0, "%*s%s: \"%s\"", level, "", name, buf); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return; ~~~~~~~ } ~ } ~ debug("gwlib.octstr", 0, "%*s%s:", level, "", name); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ octstr_dump(ostr, level + 1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ /********************************************************************** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * octstr_format and related private functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ /* ~~ * A parsed form of the format string. This struct has been carefully ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * defined so that it can be initialized with {0} and it will have ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * the correct defaults. ~~~~~~~~~~~~~~~~~~~~~~~ */ ~~ struct format ~~~~~~~~~~~~~ { ~ int minus; ~~~~~~~~~~ int zero; ~~~~~~~~~ long min_width; ~~~~~~~~~~~~~~~ int has_prec; ~~~~~~~~~~~~~ long prec; ~~~~~~~~~~ long type; ~~~~~~~~~~ }; ~~ static void format_flags(struct format *format, const char **fmt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ int done; ~~~~~~~~~ done = 0; ~~~~~~~~~ do ~~ { ~ switch (**fmt) { ~~~~~~~~~~~~~~~~ case '-': ~~~~~~~~~ format->minus = 1; ~~~~~~~~~~~~~~~~~~ break; ~~~~~~ case '0': ~~~~~~~~~ format->zero = 1; ~~~~~~~~~~~~~~~~~ break; ~~~~~~ default: ~~~~~~~~ done = 1; ~~~~~~~~~ } ~ if (!done) ~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } while (!done); ~~~~~~~~~~~~~~~~ } ~ static void format_width(struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~~~~~~~ { ~ char *end; ~~~~~~~~~~ if (**fmt == '*') ~~~~~~~~~~~~~~~~~ { ~ format->min_width = va_arg(VALST(args), int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } else if (isdigit(**(const unsigned char **) fmt)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ format->min_width = strtol(*fmt, &end, 10); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *fmt = end; ~~~~~~~~~~~ /* XXX error checking is missing from here */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static void format_prec(struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~~~~~~~ { ~ char *end; ~~~~~~~~~~ if (**fmt != '.') ~~~~~~~~~~~~~~~~~ return; ~~~~~~~ ++(*fmt); ~~~~~~~~~ if (**fmt == '*') ~~~~~~~~~~~~~~~~~ { ~ format->has_prec = 1; ~~~~~~~~~~~~~~~~~~~~~ format->prec = va_arg(VALST(args), int); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } else if (isdigit(**(const unsigned char **) fmt)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ format->has_prec = 1; ~~~~~~~~~~~~~~~~~~~~~ format->prec = strtol(*fmt, &end, 10); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *fmt = end; ~~~~~~~~~~~ /* XXX error checking is missing from here */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } ~ } ~ static void format_type(struct format *format, const char **fmt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { ~ switch (**fmt) { ~~~~~~~~~~~~~~~~ case 'h': ~~~~~~~~~ format->type = **fmt; ~~~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ break; ~~~~~~ case 'l': ~~~~~~~~~ if (*(*fmt + 1) == 'l'){ ~~~~~~~~~~~~~~~~~~~~~~~~ format->type = 'L'; ~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ } else format->type = **fmt; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++(*fmt); ~~~~~~~~~ break; ~~~~~~ } ~ } ~ static void convert(Octstr *os, struct format *format, const char **fmt, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VALPARM(args)) ~~~~~~~~^~~~ gwlib/octstr.c:90:29: note: in definition of macro 'VALPARM' #define VALPARM(y) va_list *y ^ gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gw-prioqueue.o -c gwlib/gw-prioqueue.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/pcre.o -c gwlib/pcre.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_mysql.o -c gwlib/dbpool_mysql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/accesslog.o -c gwlib/accesslog.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/counter.o -c gwlib/counter.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_mssql.o -c gwlib/dbpool_mssql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/md5.o -c gwlib/md5.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/pki.o -c gwlib/pki.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_pgsql.o -c gwlib/dbpool_pgsql.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool.o -c gwlib/dbpool.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gwpoll.o -c gwlib/gwpoll.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/list.o -c gwlib/list.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/regex.o -c gwlib/regex.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/log.o -c gwlib/log.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/protected.o -c gwlib/protected.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gw-timer.o -c gwlib/gw-timer.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_sqlite3.o -c gwlib/dbpool_sqlite3.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gwmem-native.o -c gwlib/gwmem-native.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gwmem-check.o -c gwlib/gwmem-check.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gw_uuid.o -c gwlib/gw_uuid.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gwthread-pthread.o -c gwlib/gwthread-pthread.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/conn.o -c gwlib/conn.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/charset.o -c gwlib/charset.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/semaphore.o -c gwlib/semaphore.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/ssl.o -c gwlib/ssl.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_oracle.o -c gwlib/dbpool_oracle.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dict.o -c gwlib/dict.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/mime.o -c gwlib/mime.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/xmlrpc.o -c gwlib/xmlrpc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gwlib.o -c gwlib/gwlib.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/socket.o -c gwlib/socket.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_sdb.o -c gwlib/dbpool_sdb.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/dbpool_sqlite.o -c gwlib/dbpool_sqlite.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gwlib/gw-rwlock.o -c gwlib/gw-rwlock.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o utils/seewbmp.o -c utils/seewbmp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o utils/mtbatch.o -c utils/mtbatch.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o utils/decode_emimsg.o -c utils/decode_emimsg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/bearerbox.o -c gw/bearerbox.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/smsbox.o -c gw/smsbox.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o gw/wapbox.o -c gw/wapbox.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o utils/run_kannel_box.o -c utils/run_kannel_box.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_hash.o -c test/test_hash.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_pcre.o -c test/test_pcre.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_conn.o -c test/test_conn.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_ota.o -c test/test_ota.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_pdu.o -c test/test_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_dbpool.o -c test/test_dbpool.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_wakeup.o -c test/test_wakeup.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_msg.o -c test/test_msg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_pap.o -c test/test_pap.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_mime_multipart.o -c test/test_mime_multipart.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_file_traversal.o -c test/test_file_traversal.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_http_server.o -c test/test_http_server.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/timestamp.o -c test/timestamp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_list.o -c test/test_list.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_urltrans.o -c test/test_urltrans.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/fakesmsc.o -c test/fakesmsc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_prioqueue.o -c test/test_prioqueue.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_headers.o -c test/test_headers.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/wml_tester.o -c test/wml_tester.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_si.o -c test/test_si.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/udpfeed.o -c test/udpfeed.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/drive_smpp.o -c test/drive_smpp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_hmac.o -c test/test_hmac.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_uuid.o -c test/test_uuid.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_udp.o -c test/test_udp.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_radius_pdu.o -c test/test_radius_pdu.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_store_dump.o -c test/test_store_dump.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_regex.o -c test/test_regex.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_mime.o -c test/test_mime.c test/test_regex.c: In function 'main': test/test_regex.c:116:26: warning: iteration 10 invokes undefined behavior [-Waggressive-loop-optimizations] if (pmatch[i].rm_so != -1 && pmatch[i].rm_eo != -1) { ~~~~~~~~~^~~~~~ test/test_regex.c:115:9: note: within this loop for (i = 0; i <= REGEX_MAX_SUB_MATCH; i++) { ^~~ gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_cfg.o -c test/test_cfg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_xmlrpc.o -c test/test_xmlrpc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/fakewap.o -c test/fakewap.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_octstr_dump.o -c test/test_octstr_dump.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/wapproxy.o -c test/wapproxy.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_cimd2.o -c test/test_cimd2.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_mem.o -c test/test_mem.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_octstr_format.o -c test/test_octstr_format.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_http.o -c test/test_http.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_smsc.o -c test/test_smsc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/decompile.o -c test/decompile.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_charset.o -c test/test_charset.c test/decompile.c: In function 'BufferLength': test/decompile.c:1439:26: warning: comparison between pointer and zero character constant [-Wpointer-compare] while (buffer->m_curpos != '\0') ^~ test/decompile.c:1439:9: note: did you mean to dereference the pointer? while (buffer->m_curpos != '\0') ^ gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_dict.o -c test/test_dict.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_ppg.o -c test/test_ppg.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_radius_acct.o -c test/test_radius_acct.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/drive_wapbox.o -c test/drive_wapbox.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_date.o -c test/test_date.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_sl.o -c test/test_sl.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_octstr_immutables.o -c test/test_octstr_immutables.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o test/test_boxc.o -c test/test_boxc.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o checks/check_octstr.o -c checks/check_octstr.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o checks/check_ipcheck.o -c checks/check_ipcheck.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o checks/check_date.o -c checks/check_date.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o checks/check_counter.o -c checks/check_counter.c gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -o checks/check_list.o -c checks/check_list.c ./utils/foobar-config.sh "-I/usr/local/include/kannel -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql" \ "-L/usr/local/lib/kannel -lgw -lwap -lgwlib -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto " \ "1.4.4" > gw-config chmod 0755 gw-config ar rc libgw.a gw/dlr_pgsql.o gw/wap_push_ota.o gw/ota_compiler.o gw/wap_push_sl_compiler.o gw/heartbeat.o gw/dlr_mysql.o gw/dlr_sdb.o gw/wap_push_pap_compiler.o gw/wap-appl.o gw/html.o gw/numhash.o gw/meta_data.o gw/wap_push_pap_mime.o gw/dlr_mssql.o gw/bb_alog.o gw/bb_smscconn.o gw/bb_store.o gw/dlr.o gw/ota_prov.o gw/urltrans.o gw/mime_decompiler.o gw/bb_http.o gw/xml_shared.o gw/sms.o gw/bb_boxc.o gw/dlr_sqlite3.o gw/wap_push_si_compiler.o gw/wap_push_ppg_pushuser.o gw/dlr_oracle.o gw/shared.o gw/msg.o gw/bb_store_file.o gw/load.o gw/bb_store_spool.o gw/dlr_mem.o gw/dlr_redis.o gw/wap-error.o gw/wap-maps.o gw/wml_compiler.o gw/smscconn.o gw/dlr_spool.o gw/bb_udp.o gw/wap_push_ppg.o gw/smsc/smsc_sema.o gw/smsc/smsc_http.o gw/smsc/smsc_soap.o gw/smsc/smpp_pdu.o gw/smsc/smsc_cimd.o gw/smsc/smsc_emi_x25.o gw/smsc/smsc_at.o gw/smsc/smsc_soap_parlayx.o gw/smsc/smsc_smpp.o gw/smsc/smsc_cimd2.o gw/smsc/smsc_smasi.o gw/smsc/smasi_pdu.o gw/smsc/smsc_emi.o gw/smsc/smsc_ois.o gw/smsc/emimsg.o gw/smsc/smsc_fake.o gw/smsc/smsc_cgw.o gw/smsc/smsc_loopback.o gw/smsc/smsc.o gw/smsc/smsc_oisd.o gw/smsc/smsc_wrapper.o ar rc libwmlscript.a wmlscript/wsstree.o wmlscript/wmlsc.o wmlscript/wserror.o wmlscript/ws.o wmlscript/wsstream_file.o wmlscript/wsstream_data.o wmlscript/wsieee754.o wmlscript/wslexer.o wmlscript/wsbuffer.o wmlscript/wsstream.o wmlscript/wmlsdasm.o wmlscript/wsstdlib.o wmlscript/wsutf8.o wmlscript/wsencode.o wmlscript/wsfalloc.o wmlscript/wshash.o wmlscript/wsbc.o wmlscript/wsalloc.o wmlscript/wsgram.o wmlscript/wsasm.o wmlscript/wsopt.o ranlib libgw.a ranlib libwmlscript.a ar rc libwap.a wap/wtls_pdu.o wap/wtp_resp.o wap/wsp_session.o wap/wap.o wap/wtp_tid.o wap/wsp_strings.o wap/cookies.o wap/wtls.o wap/wtls_pdusupport.o wap/wtp_init.o wap/wsp_unit.o wap/wsp_headers.o wap/wap_events.o wap/wtls_statesupport.o wap/wtp_pdu.o wap/wsp_caps.o wap/wtls-secmgr.o wap/wtp.o wap/wap_addr.o wap/timers.o wap/wsp_pdu.o wap/wsp.o wap/wsp_push_client.o wap/wtp_pack.o radius/radius_acct.o radius/radius_pdu.o ranlib libwap.a ar rc libgwlib.a gwlib/fdset.o gwlib/http.o gwlib/accesslog.o gwlib/dbpool_redis.o gwlib/octstr.o gwlib/gw-prioqueue.o gwlib/pcre.o gwlib/mime.o gwlib/md5.o gwlib/parse.o gwlib/date.o gwlib/charset.o gwlib/dbpool_oracle.o gwlib/dbpool_pgsql.o gwlib/list.o gwlib/regex.o gwlib/log.o gwlib/protected.o gwlib/gw-timer.o gwlib/dict.o gwlib/gwmem-check.o gwlib/gw_uuid.o gwlib/gwthread-pthread.o gwlib/gw-rwlock.o gwlib/semaphore.o gwlib/ssl.o gwlib/dbpool_mysql.o gwlib/xmlrpc.o gwlib/dbpool_sdb.o gwlib/utils.o gwlib/thread.o gwlib/cfg.o gwlib/counter.o gwlib/dbpool_mssql.o gwlib/gwpoll.o gwlib/pki.o gwlib/dbpool_sqlite3.o gwlib/gwmem-native.o gwlib/conn.o gwlib/gwlib.o gwlib/dbpool.o gwlib/socket.o gwlib/dbpool_sqlite.o ranlib libgwlib.a gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o wmlscript/wmlsc wmlscript/wmlsc.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o wmlscript/wmlsdasm wmlscript/wmlsdasm.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o utils/seewbmp utils/seewbmp.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o utils/mtbatch utils/mtbatch.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o utils/decode_emimsg utils/decode_emimsg.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o gw/bearerbox gw/bearerbox.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o gw/smsbox gw/smsbox.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o gw/wapbox gw/wapbox.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o utils/run_kannel_box utils/run_kannel_box.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_hash test/test_hash.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_pcre test/test_pcre.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_conn test/test_conn.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_ota test/test_ota.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_pdu test/test_pdu.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_dbpool test/test_dbpool.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_wakeup test/test_wakeup.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_msg test/test_msg.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_pap test/test_pap.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_mime_multipart test/test_mime_multipart.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_file_traversal test/test_file_traversal.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_http_server test/test_http_server.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/timestamp test/timestamp.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_list test/test_list.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_urltrans test/test_urltrans.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/fakesmsc test/fakesmsc.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_prioqueue test/test_prioqueue.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_headers test/test_headers.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/wml_tester test/wml_tester.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_si test/test_si.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/udpfeed test/udpfeed.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/drive_smpp test/drive_smpp.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_hmac test/test_hmac.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_uuid test/test_uuid.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_udp test/test_udp.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_radius_pdu test/test_radius_pdu.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_store_dump test/test_store_dump.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_regex test/test_regex.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_mime test/test_mime.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_cfg test/test_cfg.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_xmlrpc test/test_xmlrpc.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/fakewap test/fakewap.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_octstr_dump test/test_octstr_dump.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/wapproxy test/wapproxy.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_cimd2 test/test_cimd2.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_mem test/test_mem.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_octstr_format test/test_octstr_format.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_http test/test_http.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_smsc test/test_smsc.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/decompile test/decompile.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_charset test/test_charset.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_dict test/test_dict.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_ppg test/test_ppg.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_radius_acct test/test_radius_acct.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/drive_wapbox test/drive_wapbox.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_date test/test_date.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_sl test/test_sl.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_octstr_immutables test/test_octstr_immutables.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o test/test_boxc test/test_boxc.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o checks/check_octstr checks/check_octstr.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o checks/check_ipcheck checks/check_ipcheck.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o checks/check_date checks/check_date.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o checks/check_counter checks/check_counter.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gcc -D_REENTRANT=1 -I. -Igw -pipe -DLIBICONV_PLUG -O2 -fno-strict-aliasing -D_LARGE_FILES= -I/usr/local/include/libxml2 -I/usr/include -I/usr/local/include -I/usr/local/include/mysql -Wl,-rpath,/usr/local/lib -o checks/check_list checks/check_list.o libgw.a libwmlscript.a libwap.a libgwlib.a -lmysqlclient_r -lpcreposix -lrt -lm -lpthread -L/usr/local/lib -lxml2 -lz -L/usr/lib -llzma -L/usr/lib -lm -L/usr/local/lib -lpcreposix -lpcre -L/usr/local/lib/mysql -lmysqlclient -pthread -lz -lm -lexecinfo -L/usr/local/lib -lssl -lcrypto gmake[1]: Leaving directory '/construction/www/kannel/gateway-1.4.4' -------------------------------------------------------------------------------- -- Phase: run-depends -------------------------------------------------------------------------------- ===> kannel-1.4.4_8,1 depends on file: /usr/local/lib/libcrypto.so.44 - found -------------------------------------------------------------------------------- -- Phase: stage -------------------------------------------------------------------------------- ===> Staging for kannel-1.4.4_8,1 ===> Generating temporary packing list ===> Creating groups. ===> Creating users gmake[1]: Entering directory '/construction/www/kannel/gateway-1.4.4' /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/bin for prog in wmlscript/wmlsc wmlscript/wmlsdasm utils/seewbmp utils/mtbatch utils/decode_emimsg gw-config; do \ /usr/bin/install -c $prog \ /construction/www/kannel/stage/usr/local/bin/`basename $prog`; \ done test -r /construction/www/kannel/stage/usr/local/bin/gw-config || \ ln -sf gw-config /construction/www/kannel/stage/usr/local/bin/gw-config /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/sbin for prog in gw/bearerbox gw/smsbox gw/wapbox utils/run_kannel_box; do \ /usr/bin/install -c $prog \ /construction/www/kannel/stage/usr/local/sbin/`basename $prog`; \ done /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/man/man1 /usr/bin/install -c utils/seewbmp.1 utils/mtbatch.1 wmlscript/wmlsc.1 wmlscript/wmlsdasm.1 /construction/www/kannel/stage/usr/local/man/man1 /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/man/man8 /usr/bin/install -c gw/kannel.8 utils/run_kannel_box.8 /construction/www/kannel/stage/usr/local/man/man8 /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/include/kannel/gwlib install -m 0644 ./gwlib/*.h /construction/www/kannel/stage/usr/local/include/kannel/gwlib install -m 0644 ./gwlib/*.def /construction/www/kannel/stage/usr/local/include/kannel/gwlib /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/include/kannel/gw install -m 0644 ./gw/*.h /construction/www/kannel/stage/usr/local/include/kannel/gw install -m 0644 ./gw/*.def /construction/www/kannel/stage/usr/local/include/kannel/gw /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/include/kannel/gw/smsc install -m 0644 ./gw/smsc/*.h /construction/www/kannel/stage/usr/local/include/kannel/gw/smsc install -m 0644 ./gw/smsc/*.def /construction/www/kannel/stage/usr/local/include/kannel/gw/smsc /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/include/kannel/wap install -m 0644 ./wap/*.h /construction/www/kannel/stage/usr/local/include/kannel/wap install -m 0644 ./wap/*.def /construction/www/kannel/stage/usr/local/include/kannel/wap install -m 0644 gw-config.h /construction/www/kannel/stage/usr/local/include/kannel /usr/bin/install -c -d /construction/www/kannel/stage/usr/local/lib/kannel install -m 0644 lib*.a /construction/www/kannel/stage/usr/local/lib/kannel gmake[1]: Leaving directory '/construction/www/kannel/gateway-1.4.4' install -m 0644 /construction/www/kannel/gateway-1.4.4/gw/wapkannel.conf /construction/www/kannel/stage/usr/local/etc/wapkannel.conf.sample install -m 0644 /construction/www/kannel/gateway-1.4.4/gw/smskannel.conf /construction/www/kannel/stage/usr/local/etc/smskannel.conf.sample ====> Compressing man pages (compress-man) ===> Staging rc.d startup script(s) -------------------------------------------------------------------------------- -- Phase: package -------------------------------------------------------------------------------- ===> Building package for kannel-1.4.4_8,1 file sizes/checksums [159]: .. done packing files [159]: .. done packing directories [2]: . done -------------------------------------------------- -- Termination -------------------------------------------------- Finished: Thursday, 7 MAR 2019 at 14:02:17 UTC Duration: 00:03:29