From 18f6835edaf7d640a2c9e476cb1babdbdadbfd9b Mon Sep 17 00:00:00 2001 From: Ton Voon Date: Thu, 17 Jun 2010 10:16:43 +0100 Subject: [PATCH] Added state retention APIs. Implemented for check_snmp with --rate option. See http://nagiosplugin.org/c-api-private for more details on the API. Also updated check_snmp -l option to change the perfdata label. --- NEWS | 6 +- build-aux/c++defs.h | 36 +- build-aux/warn-on-use.h | 9 +- gl/Makefile.am | 34 +- gl/alloca.c | 489 ------------------------ gl/config.charset | 42 +-- gl/error.c | 32 +- gl/getopt.c | 39 +- gl/getopt_int.h | 69 ++-- gl/localcharset.c | 7 +- gl/m4/asm-underscore.m4 | 48 +++ gl/m4/getopt.m4 | 41 +- gl/m4/gettext.m4 | 6 +- gl/m4/gnulib-cache.m4 | 4 +- gl/m4/gnulib-common.m4 | 10 +- gl/m4/gnulib-comp.m4 | 12 +- gl/m4/iconv.m4 | 19 +- gl/m4/intl.m4 | 93 ++--- gl/m4/lib-link.m4 | 46 ++- gl/m4/netdb_h.m4 | 17 +- gl/m4/onceonly.m4 | 10 +- gl/m4/po.m4 | 2 +- gl/m4/printf.m4 | 4 +- gl/m4/sha1.m4 | 16 + gl/m4/sockpfaf.m4 | 3 + gl/m4/stdint.m4 | 14 +- gl/m4/stdio_h.m4 | 3 +- gl/m4/string_h.m4 | 3 +- gl/m4/strnlen.m4 | 22 +- gl/m4/time_h.m4 | 19 +- gl/m4/unistd_h.m4 | 11 +- gl/m4/vasnprintf.m4 | 14 +- gl/m4/visibility.m4 | 26 +- gl/netdb.in.h | 30 +- gl/regex_internal.c | 4 +- gl/regex_internal.h | 2 + gl/sha1.c | 428 +++++++++++++++++++++ gl/sha1.h | 92 +++++ gl/stdbool.in.h | 3 + gl/stdio-write.c | 2 - gl/stdio.in.h | 22 +- gl/strerror.c | 3 + gl/string.in.h | 15 +- gl/sys_stat.in.h | 6 +- gl/time.in.h | 12 +- gl/unistd.in.h | 56 ++- gl/vasnprintf.c | 601 +++++++++++++++++------------- gl/verify.h | 41 +- gl/wchar.in.h | 2 +- lib/Makefile.am | 1 + lib/tests/Makefile.am | 2 + lib/tests/test_utils.c | 182 ++++++++- lib/tests/var/.gitignore | 2 + lib/tests/var/baddate | 5 + lib/tests/var/missingdataline | 4 + lib/tests/var/oldformat | 5 + lib/tests/var/statefile | 5 + lib/utils_base.c | 354 +++++++++++++++++- lib/utils_base.h | 35 ++ plugins/Makefile.am | 2 +- plugins/check_snmp.c | 173 ++++++++- plugins/tests/check_snmp.t | 39 +- plugins/tests/check_snmp_agent.pl | 6 +- 63 files changed, 2320 insertions(+), 1020 deletions(-) delete mode 100644 gl/alloca.c create mode 100644 gl/m4/asm-underscore.m4 create mode 100644 gl/m4/sha1.m4 create mode 100644 gl/sha1.c create mode 100644 gl/sha1.h create mode 100644 lib/tests/var/.gitignore create mode 100644 lib/tests/var/baddate create mode 100644 lib/tests/var/missingdataline create mode 100644 lib/tests/var/oldformat create mode 100644 lib/tests/var/statefile diff --git a/NEWS b/NEWS index 3e472ed..c2917c1 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,10 @@ This file documents the major additions and syntax changes between releases. New check_ntp_peer -m and -n options to check the number of usable time sources ("truechimers") New check_disk_smb -a option which allows for specifying the IP address of the remote server New check_radius -N option which allows for specifying the value of the NAS-IP-Address attribute - Updated Nagios::Plugin perl module + New check_snmp --rate option to store differences between invocations. Saves state in PREFIX/var/{plugin} + check_snmp -l label option now also changes the perfdata label. See WARNINGS + Updated Nagios::Plugin perl module + Updated gnulib to June 2010 FIXES Fix check_ircd binding to wrong interface (#668778) Add proxy-authorization option to check_http (Marcel Kuiper - #1323230, Bryan Irvine - #2863925) @@ -28,6 +31,7 @@ This file documents the major additions and syntax changes between releases. Updated developer documentation to say that performance labels should not have an equals sign or single quote in the label check_http 1.4.14 introduced SSL SNI support - you now have to enable it explicitly with "--sni" + check_snmp -l label option is also used for the performance label. This could change history from previous uses 1.4.14 16th September 2009 check_http has options to specify the HTTP method (#2155152) diff --git a/build-aux/c++defs.h b/build-aux/c++defs.h index 7d71089..0c2fad7 100644 --- a/build-aux/c++defs.h +++ b/build-aux/c++defs.h @@ -221,10 +221,20 @@ _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) # define _GL_CXXALIASWARN_1(func,namespace) \ _GL_CXXALIASWARN_2 (func, namespace) -# define _GL_CXXALIASWARN_2(func,namespace) \ - _GL_WARN_ON_USE (func, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") +/* To work around GCC bug , + we enable the warning only when not optimizing. */ +# if !__OPTIMIZE__ +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_WARN_ON_USE (func, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +# define _GL_CXXALIASWARN_2(func,namespace) \ + extern __typeof__ (func) func +# else +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif #else # define _GL_CXXALIASWARN(func) \ _GL_EXTERN_C int _gl_cxxalias_dummy @@ -239,10 +249,20 @@ GNULIB_NAMESPACE) # define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") +/* To work around GCC bug , + we enable the warning only when not optimizing. */ +# if !__OPTIMIZE__ +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + extern __typeof__ (func) func +# else +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif #else # define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ _GL_EXTERN_C int _gl_cxxalias_dummy diff --git a/build-aux/warn-on-use.h b/build-aux/warn-on-use.h index 1cd5062..171e599 100644 --- a/build-aux/warn-on-use.h +++ b/build-aux/warn-on-use.h @@ -67,7 +67,10 @@ /* A compiler attribute is available in gcc versions 4.3.0 and later. */ # define _GL_WARN_ON_USE(function, message) \ extern __typeof__ (function) function __attribute__ ((__warning__ (message))) - +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE(function, message) \ +extern __typeof__ (function) function # else /* Unsupported. */ # define _GL_WARN_ON_USE(function, message) \ _GL_WARN_EXTERN_C int _gl_warn_on_use @@ -85,6 +88,10 @@ _GL_WARN_EXTERN_C int _gl_warn_on_use # define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ extern rettype function parameters_and_attributes \ __attribute__ ((__warning__ (msg))) +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ +extern rettype function parameters_and_attributes # else /* Unsupported. */ # define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ _GL_WARN_EXTERN_C int _gl_warn_on_use diff --git a/gl/Makefile.am b/gl/Makefile.am index e2dc38b..7954b03 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -9,7 +9,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl base64 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex timegm vasprintf vsnprintf +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex timegm vasprintf vsnprintf AUTOMAKE_OPTIONS = 1.5 gnits @@ -44,17 +44,6 @@ EXTRA_DIST += alignof.h ## end gnulib module alignof -## begin gnulib module alloca - - -EXTRA_DIST += alloca.c - -EXTRA_libgnu_a_SOURCES += alloca.c - -libgnu_a_LIBADD += @ALLOCA@ -libgnu_a_DEPENDENCIES += @ALLOCA@ -## end gnulib module alloca - ## begin gnulib module alloca-opt BUILT_SOURCES += $(ALLOCA_H) @@ -253,6 +242,15 @@ CLEANFILES += configmake.h configmake.h-t ## end gnulib module configmake +## begin gnulib module crypto/sha1 + + +EXTRA_DIST += sha1.c sha1.h + +EXTRA_libgnu_a_SOURCES += sha1.c + +## end gnulib module crypto/sha1 + ## begin gnulib module dirname @@ -833,11 +831,11 @@ EXTRA_libgnu_a_SOURCES += mountlist.c ## begin gnulib module netdb -BUILT_SOURCES += $(NETDB_H) +BUILT_SOURCES += netdb.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. -netdb.h: netdb.in.h $(ARG_NONNULL_H) +netdb.h: netdb.in.h $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -851,6 +849,7 @@ netdb.h: netdb.in.h $(ARG_NONNULL_H) -e 's|@''HAVE_DECL_GETADDRINFO''@|$(HAVE_DECL_GETADDRINFO)|g' \ -e 's|@''HAVE_DECL_GETNAMEINFO''@|$(HAVE_DECL_GETNAMEINFO)|g' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/netdb.in.h; \ } > $@-t && \ mv $@-t $@ @@ -1140,6 +1139,7 @@ stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ + -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ @@ -1333,6 +1333,7 @@ string.h: string.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ + -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ @@ -1506,6 +1507,7 @@ time.h: time.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ @@ -1577,6 +1579,7 @@ unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \ -e 's|@''GNULIB_PIPE2''@|$(GNULIB_PIPE2)|g' \ -e 's|@''GNULIB_PREAD''@|$(GNULIB_PREAD)|g' \ + -e 's|@''GNULIB_PWRITE''@|$(GNULIB_PWRITE)|g' \ -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \ -e 's|@''GNULIB_READLINKAT''@|$(GNULIB_READLINKAT)|g' \ -e 's|@''GNULIB_RMDIR''@|$(GNULIB_RMDIR)|g' \ @@ -1611,6 +1614,7 @@ unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ + -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ @@ -1638,10 +1642,12 @@ unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ + -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ + -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ diff --git a/gl/alloca.c b/gl/alloca.c deleted file mode 100644 index 75afdb9..0000000 --- a/gl/alloca.c +++ /dev/null @@ -1,489 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#include - -#include - -#include -#include - -#ifdef emacs -# include "lisp.h" -# include "blockinput.h" -# ifdef EMACS_FREE -# undef free -# define free EMACS_FREE -# endif -#else -# define memory_full() abort () -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -# ifndef alloca - -# ifdef emacs -# ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -# ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -/* Using #error here is not wise since this file should work for - old and obscure compilers. */ -# endif /* STACK_DIRECTION undefined */ -# endif /* static */ -# endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -# else -# define ADDRESS_FUNCTION(arg) &(arg) -# endif - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -# ifndef STACK_DIRECTION -# define STACK_DIRECTION 0 /* Direction unknown. */ -# endif - -# if STACK_DIRECTION != 0 - -# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -# else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -# define STACK_DIR stack_dir - -static void -find_stack_direction (void) -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -# endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -# ifndef ALIGN_SIZE -# define ALIGN_SIZE sizeof(double) -# endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -void * -alloca (size_t size) -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -# if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -# endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -# ifdef emacs - BLOCK_INPUT; -# endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free (hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -# ifdef emacs - UNBLOCK_INPUT; -# endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - /* Address of header. */ - register header *new; - - size_t combined_size = sizeof (header) + size; - if (combined_size < sizeof (header)) - memory_full (); - - new = malloc (combined_size); - - if (! new) - memory_full (); - - new->h.next = last_alloca_header; - new->h.deep = depth; - - last_alloca_header = new; - - /* User storage begins just after header. */ - - return (void *) (new + 1); - } -} - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) - -# ifdef DEBUG_I00AFUNC -# include -# endif - -# ifndef CRAY_STACK -# define CRAY_STACK -# ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -# else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -# endif /* CRAY2 */ -# endif /* not CRAY_STACK */ - -# ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -# else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -# endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -# endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -# endif /* not CRAY2 */ -# endif /* CRAY */ - -# endif /* no alloca */ -#endif /* not GCC version 3 */ diff --git a/gl/config.charset b/gl/config.charset index 2959df8..aa7d00d 100644 --- a/gl/config.charset +++ b/gl/config.charset @@ -30,21 +30,21 @@ # The current list of GNU canonical charset names is as follows. # # name MIME? used by which systems -# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin -# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin -# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin -# ISO-8859-3 Y glibc solaris +# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-3 Y glibc solaris cygwin # ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin -# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin -# ISO-8859-6 Y glibc aix hpux solaris -# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin -# ISO-8859-8 Y glibc aix hpux osf solaris -# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin -# ISO-8859-13 glibc netbsd openbsd darwin -# ISO-8859-14 glibc -# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-6 Y glibc aix hpux solaris cygwin +# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin +# ISO-8859-8 Y glibc aix hpux osf solaris cygwin +# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin +# ISO-8859-13 glibc netbsd openbsd darwin cygwin +# ISO-8859-14 glibc cygwin +# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin # KOI8-R Y glibc solaris freebsd netbsd openbsd darwin -# KOI8-U Y glibc freebsd netbsd openbsd darwin +# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin # KOI8-T glibc # CP437 dos # CP775 dos @@ -61,7 +61,7 @@ # CP869 dos # CP874 woe32 dos # CP922 aix -# CP932 aix woe32 dos +# CP932 aix cygwin woe32 dos # CP943 aix # CP949 osf darwin woe32 dos # CP950 woe32 dos @@ -71,7 +71,7 @@ # CP1129 aix # CP1131 darwin # CP1250 woe32 -# CP1251 glibc solaris netbsd openbsd darwin woe32 +# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32 # CP1252 aix woe32 # CP1253 woe32 # CP1254 woe32 @@ -80,19 +80,19 @@ # CP1257 woe32 # GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin # EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin -# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin # EUC-TW glibc aix hpux irix osf solaris netbsd -# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin +# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin # BIG5-HKSCS glibc solaris darwin -# GBK glibc aix osf solaris darwin woe32 dos +# GBK glibc aix osf solaris darwin cygwin woe32 dos # GB18030 glibc solaris netbsd darwin # SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin # JOHAB glibc solaris woe32 -# TIS-620 glibc aix hpux osf solaris +# TIS-620 glibc aix hpux osf solaris cygwin # VISCII Y glibc # TCVN5712-1 glibc # ARMSCII-8 glibc darwin -# GEORGIAN-PS glibc +# GEORGIAN-PS glibc cygwin # PT154 glibc # HP-ROMAN8 hpux # HP-ARABIC8 hpux @@ -102,7 +102,7 @@ # HP-KANA8 hpux # DEC-KANJI osf # DEC-HANYU osf -# UTF-8 Y glibc aix hpux osf solaris netbsd darwin +# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin # # Note: Names which are not marked as being a MIME name should not be used in # Internet protocols for information interchange (mail, news, etc.). diff --git a/gl/error.c b/gl/error.c index c79e8d4..ed9dba0 100644 --- a/gl/error.c +++ b/gl/error.c @@ -88,6 +88,15 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # include # include +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P # ifndef HAVE_DECL_STRERROR_R "this configure-time declaration test was not run" @@ -104,10 +113,29 @@ extern char *program_name; # endif /* HAVE_STRERROR_R || defined strerror_r */ #endif /* not _LIBC */ +#if !_LIBC +/* Return non-zero if FD is open. */ +static inline int +is_open (int fd) +{ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On Win32: The initial state of unassigned standard file descriptors is + that they are open but point to an INVALID_HANDLE_VALUE. There is no + fcntl, and the gnulib replacement fcntl does not support F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + static inline void flush_stdout (void) { -#if !_LIBC && defined F_GETFL +#if !_LIBC int stdout_fd; # if GNULIB_FREOPEN_SAFER @@ -124,7 +152,7 @@ flush_stdout (void) /* POSIX states that fflush (stdout) after fclose is unspecified; it is safe in glibc, but not on all other platforms. fflush (NULL) is always defined, but too draconian. */ - if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL)) + if (0 <= stdout_fd && is_open (stdout_fd)) #endif fflush (stdout); } diff --git a/gl/getopt.c b/gl/getopt.c index aaabc8d..3791f12 100644 --- a/gl/getopt.c +++ b/gl/getopt.c @@ -348,8 +348,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int long_only, struct _getopt_data *d, int posixly_correct) { int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; if (argc < 1) return -1; @@ -364,6 +362,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, posixly_correct); d->__initialized = 1; } + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + if (optstring[0] == ':') + print_errors = 0; /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag @@ -633,8 +635,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '--%s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -651,8 +653,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + _("%s: option '--%s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); @@ -736,13 +738,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, { char c = *d->__nextchar++; - char *temp = strchr (optstring, c); + const char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; - if (temp == NULL || c == ':') + if (temp == NULL || c == ':' || c == ';') { if (print_errors) { @@ -864,7 +866,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, pfound = p; indfound = option_index; } - else + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } @@ -876,7 +881,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + argv[0], d->optarg) >= 0) { _IO_flockfile (stderr); @@ -892,7 +897,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); + argv[0], d->optarg); #endif } d->__nextchar += strlen (d->__nextchar); @@ -955,8 +960,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -972,15 +977,17 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, free (buf); } #else - fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + fprintf (stderr, _("\ +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } + else + d->optarg = NULL; d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; diff --git a/gl/getopt_int.h b/gl/getopt_int.h index 169def5..980b750 100644 --- a/gl/getopt_int.h +++ b/gl/getopt_int.h @@ -30,6 +30,40 @@ extern int _getopt_internal (int ___argc, char **___argv, /* Reentrant versions which can handle parsing multiple argument vectors at the same time. */ +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters, or by calling getopt. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + /* Data type for reentrant functions. */ struct _getopt_data { @@ -54,39 +88,8 @@ struct _getopt_data by advancing to the next ARGV-element. */ char *__nextchar; - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - - enum - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; + /* See __ord above. */ + enum __ord __ordering; /* If the POSIXLY_CORRECT environment variable is set or getopt was called. */ diff --git a/gl/localcharset.c b/gl/localcharset.c index a04dc44..fa2207f 100644 --- a/gl/localcharset.c +++ b/gl/localcharset.c @@ -369,10 +369,9 @@ locale_charset (void) codeset = nl_langinfo (CODESET); # ifdef __CYGWIN__ - /* Cygwin 1.5.x does not have locales. nl_langinfo (CODESET) always - returns "US-ASCII". As long as this is not fixed, return the suffix - of the locale name from the environment variables (if present) or - the codepage as a number. */ + /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always + returns "US-ASCII". Return the suffix of the locale name from the + environment variables (if present) or the codepage as a number. */ if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) { const char *locale; diff --git a/gl/m4/asm-underscore.m4 b/gl/m4/asm-underscore.m4 new file mode 100644 index 0000000..1736cc4 --- /dev/null +++ b/gl/m4/asm-underscore.m4 @@ -0,0 +1,48 @@ +# asm-underscore.m4 serial 1 +dnl Copyright (C) 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. Based on as-underscore.m4 in GNU clisp. + +# gl_ASM_SYMBOL_PREFIX +# Tests for the prefix of C symbols at the assembly language level and the +# linker level. This prefix is either an underscore or empty. Defines the +# C macro USER_LABEL_PREFIX to this prefix, and sets ASM_SYMBOL_PREFIX to +# a stringified variant of this prefix. + +AC_DEFUN([gl_ASM_SYMBOL_PREFIX], +[ + dnl We don't use GCC's __USER_LABEL_PREFIX__ here, because + dnl 1. It works only for GCC. + dnl 2. It is incorrectly defined on some platforms, in some GCC versions. + AC_CACHE_CHECK( + [whether C symbols are prefixed with underscore at the linker level], + [gl_cv_prog_as_underscore], + [cat > conftest.c </dev/null 2>&1 + if grep _foo conftest.s >/dev/null ; then + gl_cv_prog_as_underscore=yes + else + gl_cv_prog_as_underscore=no + fi + rm -f conftest* + ]) + if test $gl_cv_prog_as_underscore = yes; then + USER_LABEL_PREFIX=_ + else + USER_LABEL_PREFIX= + fi + AC_DEFINE_UNQUOTED([USER_LABEL_PREFIX], [$USER_LABEL_PREFIX], + [Define to the prefix of C symbols at the assembler and linker level, + either an underscore or empty.]) + ASM_SYMBOL_PREFIX='"'${USER_LABEL_PREFIX}'"' + AC_SUBST([ASM_SYMBOL_PREFIX]) +]) diff --git a/gl/m4/getopt.m4 b/gl/m4/getopt.m4 index a19805e..5b211e5 100644 --- a/gl/m4/getopt.m4 +++ b/gl/m4/getopt.m4 @@ -1,4 +1,4 @@ -# getopt.m4 serial 24 +# getopt.m4 serial 28 dnl Copyright (C) 2002-2006, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -79,8 +79,13 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], dnl Existence of the variable, in and of itself, is not a reason to replace dnl getopt, but knowledge of the variable is needed to determine how to dnl reset and whether a reset reparses the environment. - if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then - AC_CHECK_DECLS([optreset], [], [], + dnl Solaris supports neither optreset nor optind=0, but keeps no state that + dnl needs a reset beyond setting optind=1; detect Solaris by getopt_clip. + if test -z "$gl_replace_getopt"; then + AC_CHECK_DECLS([optreset], [], + [AC_CHECK_DECLS([getopt_clip], [], [], + [[#include ]]) + ], [[#include ]]) fi @@ -89,6 +94,10 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], dnl is left over from earlier calls, and neither setting optind = 0 nor dnl setting optreset = 1 get rid of this internal state. dnl POSIX is silent on optind vs. optreset, so we allow either behavior. + dnl POSIX 2008 does not specify leading '+' behavior, but see + dnl http://austingroupbugs.net/view.php?id=191 for a recommendation on + dnl the next version of POSIX. For now, we only guarantee leading '+' + dnl behavior with getopt-gnu. if test -z "$gl_replace_getopt"; then AC_CACHE_CHECK([whether getopt is POSIX compatible], [gl_cv_func_getopt_posix], @@ -99,7 +108,7 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], #include #include -#if !HAVE_DECL_OPTRESET +#if !HAVE_DECL_OPTRESET && !HAVE_DECL_GETOPT_CLIP # define OPTIND_MIN 0 #else # define OPTIND_MIN 1 @@ -167,6 +176,20 @@ main () if (!(optind == 1)) return 12; } + /* Detect MacOS 10.5 bug. */ + { + char *argv[3] = { "program", "-ab", NULL }; + optind = OPTIND_MIN; + opterr = 0; + if (getopt (2, argv, "ab:") != 'a') + return 13; + if (getopt (2, argv, "ab:") != '?') + return 14; + if (optopt != 'b') + return 15; + if (optind != 2) + return 16; + } return 0; } @@ -174,6 +197,7 @@ main () [gl_cv_func_getopt_posix=yes], [gl_cv_func_getopt_posix=no], [case "$host_os" in mingw*) gl_cv_func_getopt_posix="guessing no";; + darwin*) gl_cv_func_getopt_posix="guessing no";; *) gl_cv_func_getopt_posix="guessing yes";; esac ]) @@ -234,6 +258,15 @@ main () if (getopt (3, argv, "-p") != 'p') return 7; } + /* This code fails on glibc 2.11. */ + { + char *argv[] = { "program", "-b", "-a", NULL }; + optind = opterr = 0; + if (getopt (3, argv, "+:a:b") != 'b') + return 8; + if (getopt (3, argv, "+:a:b") != ':') + return 9; + } return 0; ]])], [gl_cv_func_getopt_gnu=yes], diff --git a/gl/m4/gettext.m4 b/gl/m4/gettext.m4 index d6dc3fe..f84e6a5 100644 --- a/gl/m4/gettext.m4 +++ b/gl/m4/gettext.m4 @@ -1,4 +1,4 @@ -# gettext.m4 serial 62 (gettext-0.18) +# gettext.m4 serial 63 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,7 @@ dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2006. +dnl Bruno Haible , 2000-2006, 2008-2010. dnl Macro to add for using GNU gettext. @@ -60,6 +60,8 @@ AC_DEFUN([AM_GNU_GETTEXT], ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4 index 0ac6b96..97b1849 100644 --- a/gl/m4/gnulib-cache.m4 +++ b/gl/m4/gnulib-cache.m4 @@ -15,12 +15,13 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl base64 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex timegm vasprintf vsnprintf +# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files base64 crypto/sha1 dirname floorf fsusage getaddrinfo gethostname getloadavg getopt gettext mountlist regex timegm vasprintf vsnprintf # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ base64 + crypto/sha1 dirname floorf fsusage @@ -45,3 +46,4 @@ gl_LIB([libgnu]) gl_MAKEFILE_NAME([]) gl_MACRO_PREFIX([gl]) gl_PO_DOMAIN([]) +gl_VC_FILES([false]) diff --git a/gl/m4/gnulib-common.m4 b/gl/m4/gnulib-common.m4 index 9cc519e..4c7ac30 100644 --- a/gl/m4/gnulib-common.m4 +++ b/gl/m4/gnulib-common.m4 @@ -1,4 +1,4 @@ -# gnulib-common.m4 serial 18 +# gnulib-common.m4 serial 20 dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -35,6 +35,12 @@ AC_DEFUN([gl_COMMON_BODY], [ is a misnomer outside of parameter lists. */ #define _UNUSED_PARAMETER_ _GL_UNUSED ]) + dnl Preparation for running test programs: + dnl Tell glibc to write diagnostics from -D_FORTIFY_SOURCE=2 to stderr, not + dnl to /dev/tty, so they can be redirected to log files. Such diagnostics + dnl arise e.g., in the macros gl_PRINTF_DIRECTIVE_N, gl_SNPRINTF_DIRECTIVE_N. + LIBC_FATAL_STDERR_=1 + export LIBC_FATAL_STDERR_ ]) # gl_MODULE_INDICATOR_CONDITION @@ -132,6 +138,7 @@ m4_ifdef([AC_PROG_MKDIR_P], [ # so that mixed use of GNU C and GNU C++ and mixed use of Sun C and Sun C++ # works. # This definition can be removed once autoconf >= 2.62 can be assumed. +m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.62]),[-1],[ AC_DEFUN([AC_C_RESTRICT], [AC_CACHE_CHECK([for C/C++ restrict keyword], [ac_cv_c_restrict], [ac_cv_c_restrict=no @@ -169,6 +176,7 @@ AC_DEFUN([AC_C_RESTRICT], *) AC_DEFINE_UNQUOTED([restrict], [$ac_cv_c_restrict]) ;; esac ]) +]) # gl_BIGENDIAN # is like AC_C_BIGENDIAN, except that it can be AC_REQUIREd. diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4 index 4a956e4..f4031cc 100644 --- a/gl/m4/gnulib-comp.m4 +++ b/gl/m4/gnulib-comp.m4 @@ -26,7 +26,6 @@ AC_DEFUN([gl_EARLY], m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable AC_REQUIRE([AC_PROG_RANLIB]) # Code from module alignof: - # Code from module alloca: # Code from module alloca-opt: # Code from module arg-nonnull: # Code from module arpa_inet: @@ -37,6 +36,7 @@ AC_DEFUN([gl_EARLY], # Code from module cloexec: # Code from module close-hook: # Code from module configmake: + # Code from module crypto/sha1: # Code from module dirname: # Code from module dirname-lgpl: # Code from module double-slash-root: @@ -146,7 +146,6 @@ AC_DEFUN([gl_INIT], gl_COMMON gl_source_base='gl' # Code from module alignof: - # Code from module alloca: # Code from module alloca-opt: gl_FUNC_ALLOCA # Code from module arg-nonnull: @@ -166,6 +165,8 @@ AC_DEFUN([gl_INIT], gl_MODULE_INDICATOR_FOR_TESTS([cloexec]) # Code from module close-hook: # Code from module configmake: + # Code from module crypto/sha1: + gl_SHA1 # Code from module dirname: gl_DIRNAME gl_MODULE_INDICATOR([dirname]) @@ -222,7 +223,7 @@ AC_DEFUN([gl_INIT], gl_FUNC_GETOPT_POSIX # Code from module gettext: dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac. - AM_GNU_GETTEXT_VERSION([0.17]) + AM_GNU_GETTEXT_VERSION([0.18.1]) # Code from module gettext-h: AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) @@ -522,7 +523,6 @@ AC_DEFUN([gl_FILE_LIST], [ build-aux/config.rpath build-aux/warn-on-use.h lib/alignof.h - lib/alloca.c lib/alloca.in.h lib/arpa_inet.in.h lib/asnprintf.c @@ -613,6 +613,8 @@ AC_DEFUN([gl_FILE_LIST], [ lib/safe-read.h lib/safe-write.c lib/safe-write.h + lib/sha1.c + lib/sha1.h lib/size_max.h lib/snprintf.c lib/sockets.c @@ -660,6 +662,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/00gnulib.m4 m4/alloca.m4 m4/arpa_inet_h.m4 + m4/asm-underscore.m4 m4/base64.m4 m4/btowc.m4 m4/c-strtod.m4 @@ -740,6 +743,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/safe-read.m4 m4/safe-write.m4 m4/servent.m4 + m4/sha1.m4 m4/size_max.m4 m4/snprintf.m4 m4/sockets.m4 diff --git a/gl/m4/iconv.m4 b/gl/m4/iconv.m4 index f46ff14..e2041b9 100644 --- a/gl/m4/iconv.m4 +++ b/gl/m4/iconv.m4 @@ -1,4 +1,4 @@ -# iconv.m4 serial 9 (gettext-0.18) +# iconv.m4 serial 11 (gettext-0.18.1) dnl Copyright (C) 2000-2002, 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -170,7 +170,22 @@ int main () AC_SUBST([LTLIBICONV]) ]) -AC_DEFUN([AM_ICONV], +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])) +gl_iconv_AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then diff --git a/gl/m4/intl.m4 b/gl/m4/intl.m4 index 5e17fea..335b23c 100644 --- a/gl/m4/intl.m4 +++ b/gl/m4/intl.m4 @@ -1,5 +1,5 @@ -# intl.m4 serial 8 (gettext-0.17) -dnl Copyright (C) 1995-2007, 2009-2010 Free Software Foundation, Inc. +# intl.m4 serial 17 (gettext-0.18) +dnl Copyright (C) 1995-2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -15,9 +15,9 @@ dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2006. +dnl Bruno Haible , 2000-2009. -AC_PREREQ(2.52) +AC_PREREQ([2.52]) dnl Checks for all prerequisites of the intl subdirectory, dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, @@ -40,14 +40,24 @@ AC_DEFUN([AM_INTL_SUBDIR], AC_REQUIRE([gt_PRINTF_POSIX]) AC_REQUIRE([gl_GLIBC21])dnl AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl AC_REQUIRE([gt_INTL_MACOSX])dnl + dnl Support for automake's --enable-silent-rules. + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + AC_SUBST([INTL_DEFAULT_VERBOSITY]) + AC_CHECK_TYPE([ptrdiff_t], , [AC_DEFINE([ptrdiff_t], [long], [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) ]) AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) - AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) + AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) dnl Use the _snprintf function only if it is declared (because on NetBSD it dnl is defined as a weak alias of snprintf; we prefer to use the latter). @@ -78,6 +88,12 @@ AC_DEFUN([AM_INTL_SUBDIR], HAVE_SNPRINTF=0 fi AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + AC_SUBST([HAVE_NEWLOCALE]) if test "$ac_cv_func_wprintf" = yes; then HAVE_WPRINTF=1 else @@ -146,22 +162,31 @@ AC_DEFUN([AM_INTL_SUBDIR], #define __libc_lock_lock_recursive gl_recursive_lock_lock #define __libc_lock_unlock_recursive gl_recursive_lock_unlock #define glthread_in_use libintl_thread_in_use -#define glthread_lock_init libintl_lock_init -#define glthread_lock_lock libintl_lock_lock -#define glthread_lock_unlock libintl_lock_unlock -#define glthread_lock_destroy libintl_lock_destroy -#define glthread_rwlock_init libintl_rwlock_init -#define glthread_rwlock_rdlock libintl_rwlock_rdlock -#define glthread_rwlock_wrlock libintl_rwlock_wrlock -#define glthread_rwlock_unlock libintl_rwlock_unlock -#define glthread_rwlock_destroy libintl_rwlock_destroy -#define glthread_recursive_lock_init libintl_recursive_lock_init -#define glthread_recursive_lock_lock libintl_recursive_lock_lock -#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock -#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy -#define glthread_once libintl_once -#define glthread_once_call libintl_once_call +#define glthread_lock_init_func libintl_lock_init_func +#define glthread_lock_lock_func libintl_lock_lock_func +#define glthread_lock_unlock_func libintl_lock_unlock_func +#define glthread_lock_destroy_func libintl_lock_destroy_func +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded +#define glthread_rwlock_init_func libintl_rwlock_init_func +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func +#define glthread_once_func libintl_once_func #define glthread_once_singlethreaded libintl_once_singlethreaded +#define glthread_once_multithreaded libintl_once_multithreaded ]) ]) @@ -198,40 +223,24 @@ AC_DEFUN([gt_INTL_SUBDIR_CORE], AC_TRY_LINK( [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], [], - [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, + [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], [Define to 1 if the compiler understands __builtin_expect.])]) AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ - stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ - argz_next __fsetlocking]) + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking]) dnl Use the *_unlocked functions only if they are declared. dnl (because some of them were defined without being declared in Solaris dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built dnl on Solaris 2.5.1 to run on Solaris 2.6). dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. - gt_CHECK_DECL(feof_unlocked, [#include ]) - gt_CHECK_DECL(fgets_unlocked, [#include ]) + gt_CHECK_DECL([feof_unlocked], [#include ]) + gt_CHECK_DECL([fgets_unlocked], [#include ]) AM_ICONV - dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, - dnl and a _NL_LOCALE_NAME macro always. - AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, - [AC_TRY_LINK([#include -#include ], - [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)); - return !cs; - ], - gt_cv_nl_locale_name=yes, - gt_cv_nl_locale_name=no) - ]) - if test $gt_cv_nl_locale_name = yes; then - AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, - [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) - fi - dnl intl/plural.c is generated from intl/plural.y. It requires bison, dnl because plural.y uses bison specific features. It requires at least dnl bison-1.26 because earlier versions generate a plural.c that doesn't @@ -269,7 +278,7 @@ dnl gt_CHECK_DECL(FUNC, INCLUDES) dnl Check whether a function is declared. AC_DEFUN([gt_CHECK_DECL], [ - AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, + AC_CACHE_CHECK([whether $1 is declared], [ac_cv_have_decl_$1], [AC_TRY_COMPILE([$2], [ #ifndef $1 char *p = (char *) $1; diff --git a/gl/m4/lib-link.m4 b/gl/m4/lib-link.m4 index 90e1ac9..59b367d 100644 --- a/gl/m4/lib-link.m4 +++ b/gl/m4/lib-link.m4 @@ -1,4 +1,4 @@ -# lib-link.m4 serial 20 (gettext-0.18) +# lib-link.m4 serial 23 (gettext-0.18.2) dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,9 +18,9 @@ AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) - pushdef([Name],[translit([$1],[./-], [___])]) - pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" @@ -58,9 +58,9 @@ AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) - pushdef([Name],[translit([$1],[./-], [___])]) - pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. @@ -74,7 +74,17 @@ AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIB[]NAME" + dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, + dnl because these -l options might require -L options that are present in + dnl LIBS. -l options benefit only from the -L options listed before it. + dnl Otherwise, add it to the front of LIBS, because it may be a static + dnl library that depends on another static library that is present in LIBS. + dnl Static libraries benefit only from the static libraries listed after + dnl it. + case " $LIB[]NAME" in + *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; + *) LIBS="$LIB[]NAME $LIBS" ;; + esac AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) @@ -147,13 +157,13 @@ dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar dnl macro call that searches for libname. AC_DEFUN([AC_LIB_FROMPACKAGE], [ - pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) define([acl_frompackage_]NAME, [$2]) popdef([NAME]) pushdef([PACK],[$2]) - pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) define([acl_libsinpackage_]PACKUP, m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1]) popdef([PACKUP]) @@ -168,14 +178,14 @@ dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) - pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) - pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) dnl Autoconf >= 2.61 supports dots in --with options. - pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)]) + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ @@ -232,7 +242,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then diff --git a/gl/m4/netdb_h.m4 b/gl/m4/netdb_h.m4 index 40ba8f6..c870fb6 100644 --- a/gl/m4/netdb_h.m4 +++ b/gl/m4/netdb_h.m4 @@ -1,4 +1,4 @@ -# netdb_h.m4 serial 7 +# netdb_h.m4 serial 9 dnl Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,21 +10,16 @@ AC_DEFUN([gl_HEADER_NETDB], AC_CHECK_HEADERS_ONCE([netdb.h]) gl_CHECK_NEXT_HEADERS([netdb.h]) if test $ac_cv_header_netdb_h = yes; then - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[ - #include - struct addrinfo a; - int b = EAI_OVERFLOW; - int c = AI_NUMERICSERV; - ]])], - [NETDB_H=''], [NETDB_H='netdb.h']) HAVE_NETDB_H=1 else - NETDB_H='netdb.h' HAVE_NETDB_H=0 fi AC_SUBST([HAVE_NETDB_H]) - AC_SUBST([NETDB_H]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[#include ]], + [getaddrinfo freeaddrinfo gai_strerror getnameinfo]) ]) AC_DEFUN([gl_NETDB_MODULE_INDICATOR], diff --git a/gl/m4/onceonly.m4 b/gl/m4/onceonly.m4 index 4a3cd84..6a9c87b 100644 --- a/gl/m4/onceonly.m4 +++ b/gl/m4/onceonly.m4 @@ -1,4 +1,4 @@ -# onceonly.m4 serial 6 +# onceonly.m4 serial 7 dnl Copyright (C) 2002-2003, 2005-2006, 2008-2010 Free Software Foundation, dnl Inc. dnl This file is free software, distributed under the terms of the GNU @@ -39,16 +39,16 @@ AC_PREREQ([2.59]) AC_DEFUN([AC_CHECK_HEADERS_ONCE], [ : m4_foreach_w([gl_HEADER_NAME], [$1], [ - AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, - [./-], [___])), [ + AC_DEFUN([gl_CHECK_HEADER_]m4_quote(m4_translit(gl_HEADER_NAME, + [./-], [___])), [ m4_divert_text([INIT_PREPARE], [gl_header_list="$gl_header_list gl_HEADER_NAME"]) gl_HEADERS_EXPANSION AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_HEADER_NAME])), [Define to 1 if you have the <]m4_defn([gl_HEADER_NAME])[> header file.]) ]) - AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, - [./-], [___]))) + AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(m4_translit(gl_HEADER_NAME, + [./-], [___]))) ]) ]) m4_define([gl_HEADERS_EXPANSION], [ diff --git a/gl/m4/po.m4 b/gl/m4/po.m4 index 960efe1..47f36a4 100644 --- a/gl/m4/po.m4 +++ b/gl/m4/po.m4 @@ -29,7 +29,7 @@ AC_DEFUN([AM_PO_SUBDIRS], dnl Release version of the gettext macros. This is used to ensure that dnl the gettext macros and po/Makefile.in.in are in sync. - AC_SUBST([GETTEXT_MACRO_VERSION], [0.17]) + AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. diff --git a/gl/m4/printf.m4 b/gl/m4/printf.m4 index ebca536..b31efe3 100644 --- a/gl/m4/printf.m4 +++ b/gl/m4/printf.m4 @@ -1,4 +1,4 @@ -# printf.m4 serial 33 +# printf.m4 serial 34 dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -1101,7 +1101,7 @@ dnl } dnl --------------------------------------------------------------------- dnl Result is gl_cv_func_snprintf_retval_c99. -AC_DEFUN([gl_SNPRINTF_RETVAL_C99], +AC_DEFUN_ONCE([gl_SNPRINTF_RETVAL_C99], [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles diff --git a/gl/m4/sha1.m4 b/gl/m4/sha1.m4 new file mode 100644 index 0000000..0d18d85 --- /dev/null +++ b/gl/m4/sha1.m4 @@ -0,0 +1,16 @@ +# sha1.m4 serial 9 +dnl Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 Free Software +dnl Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SHA1], +[ + AC_LIBOBJ([sha1]) + + dnl Prerequisites of lib/sha1.c. + AC_REQUIRE([gl_BIGENDIAN]) + AC_REQUIRE([AC_C_INLINE]) + : +]) diff --git a/gl/m4/sockpfaf.m4 b/gl/m4/sockpfaf.m4 index 8a0c236..8806705 100644 --- a/gl/m4/sockpfaf.m4 +++ b/gl/m4/sockpfaf.m4 @@ -47,6 +47,9 @@ AC_DEFUN([gl_SOCKET_FAMILIES], #endif #ifdef HAVE_WINSOCK2_H #include +#endif +#ifdef HAVE_WS2TCPIP_H +#include #endif]], [[int x = AF_INET6; struct in6_addr y; struct sockaddr_in6 z; if (&x && &y && &z) return 0;]])], diff --git a/gl/m4/stdint.m4 b/gl/m4/stdint.m4 index 1cc57e6..c5e813a 100644 --- a/gl/m4/stdint.m4 +++ b/gl/m4/stdint.m4 @@ -1,4 +1,4 @@ -# stdint.m4 serial 34 +# stdint.m4 serial 35 dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -309,7 +309,7 @@ AC_DEFUN([gl_STDINT_BITSIZEOF], dnl config.h.in, dnl - extra AC_SUBST calls, so that the right substitutions are made. m4_foreach_w([gltype], [$1], - [AH_TEMPLATE([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [AH_TEMPLATE([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), [Define to the number of bits in type ']gltype['.])]) for gltype in $1 ; do AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}], @@ -334,7 +334,7 @@ AC_DEFUN([gl_STDINT_BITSIZEOF], eval BITSIZEOF_${GLTYPE}=\$result done m4_foreach_w([gltype], [$1], - [AC_SUBST([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) + [AC_SUBST([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) ]) dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES) @@ -347,7 +347,7 @@ AC_DEFUN([gl_CHECK_TYPES_SIGNED], dnl config.h.in, dnl - extra AC_SUBST calls, so that the right substitutions are made. m4_foreach_w([gltype], [$1], - [AH_TEMPLATE([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [AH_TEMPLATE([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), [Define to 1 if ']gltype[' is a signed integer type.])]) for gltype in $1 ; do AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed], @@ -367,7 +367,7 @@ AC_DEFUN([gl_CHECK_TYPES_SIGNED], fi done m4_foreach_w([gltype], [$1], - [AC_SUBST([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) + [AC_SUBST([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) ]) dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES) @@ -380,7 +380,7 @@ AC_DEFUN([gl_INTEGER_TYPE_SUFFIX], dnl config.h.in, dnl - extra AC_SUBST calls, so that the right substitutions are made. m4_foreach_w([gltype], [$1], - [AH_TEMPLATE(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX], + [AH_TEMPLATE(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX], [Define to l, ll, u, ul, ull, etc., as suitable for constants of type ']gltype['.])]) for gltype in $1 ; do @@ -419,7 +419,7 @@ AC_DEFUN([gl_INTEGER_TYPE_SUFFIX], AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], [$result]) done m4_foreach_w([gltype], [$1], - [AC_SUBST(translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])]) + [AC_SUBST(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])]) ]) dnl gl_STDINT_INCLUDES diff --git a/gl/m4/stdio_h.m4 b/gl/m4/stdio_h.m4 index 1d1d95e..f5650cd 100644 --- a/gl/m4/stdio_h.m4 +++ b/gl/m4/stdio_h.m4 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 30 +# stdio_h.m4 serial 31 dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -8,6 +8,7 @@ AC_DEFUN([gl_STDIO_H], [ AC_REQUIRE([gl_STDIO_H_DEFAULTS]) AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([gl_ASM_SYMBOL_PREFIX]) gl_CHECK_NEXT_HEADERS([stdio.h]) dnl No need to create extra modules for these functions. Everyone who uses dnl likely needs them. diff --git a/gl/m4/string_h.m4 b/gl/m4/string_h.m4 index cf26123..1977aec 100644 --- a/gl/m4/string_h.m4 +++ b/gl/m4/string_h.m4 @@ -5,7 +5,7 @@ # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 16 +# serial 17 # Written by Paul Eggert. @@ -105,6 +105,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], REPLACE_STRERROR=0; AC_SUBST([REPLACE_STRERROR]) REPLACE_STRNCAT=0; AC_SUBST([REPLACE_STRNCAT]) REPLACE_STRNDUP=0; AC_SUBST([REPLACE_STRNDUP]) + REPLACE_STRNLEN=0; AC_SUBST([REPLACE_STRNLEN]) REPLACE_STRSIGNAL=0; AC_SUBST([REPLACE_STRSIGNAL]) REPLACE_STRTOK_R=0; AC_SUBST([REPLACE_STRTOK_R]) UNDEFINE_STRTOK_R=0; AC_SUBST([UNDEFINE_STRTOK_R]) diff --git a/gl/m4/strnlen.m4 b/gl/m4/strnlen.m4 index cd48948..52bb838 100644 --- a/gl/m4/strnlen.m4 +++ b/gl/m4/strnlen.m4 @@ -1,4 +1,4 @@ -# strnlen.m4 serial 10 +# strnlen.m4 serial 12 dnl Copyright (C) 2002-2003, 2005-2007, 2009-2010 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -7,23 +7,23 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_STRNLEN], [ + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + dnl Persuade glibc to declare strnlen(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) - AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) AC_CHECK_DECLS_ONCE([strnlen]) if test $ac_cv_have_decl_strnlen = no; then HAVE_DECL_STRNLEN=0 + else + AC_FUNC_STRNLEN + dnl Note: AC_FUNC_STRNLEN does AC_LIBOBJ([strnlen]). + if test $ac_cv_func_strnlen_working = no; then + REPLACE_STRNLEN=1 + fi fi - - AC_FUNC_STRNLEN - if test $ac_cv_func_strnlen_working = no; then - # This is necessary because automake-1.6.1 doesn't understand - # that the above use of AC_FUNC_STRNLEN means we may have to use - # lib/strnlen.c. - #AC_LIBOBJ([strnlen]) - AC_DEFINE([strnlen], [rpl_strnlen], - [Define to rpl_strnlen if the replacement function should be used.]) + if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then + AC_LIBOBJ([strnlen]) gl_PREREQ_STRNLEN fi ]) diff --git a/gl/m4/time_h.m4 b/gl/m4/time_h.m4 index b88ba94..a45a10a 100644 --- a/gl/m4/time_h.m4 +++ b/gl/m4/time_h.m4 @@ -2,6 +2,8 @@ # Copyright (C) 2000-2001, 2003-2007, 2009-2010 Free Software Foundation, Inc. +# serial 2 + # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -24,7 +26,7 @@ AC_DEFUN([gl_HEADER_TIME_H_BODY], ]) dnl Define HAVE_STRUCT_TIMESPEC if `struct timespec' is declared -dnl in time.h or sys/time.h. +dnl in time.h, sys/time.h, or pthread.h. AC_DEFUN([gl_CHECK_TYPE_STRUCT_TIMESPEC], [ @@ -41,6 +43,7 @@ AC_DEFUN([gl_CHECK_TYPE_STRUCT_TIMESPEC], TIME_H_DEFINES_STRUCT_TIMESPEC=0 SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=0 + PTHREAD_H_DEFINES_STRUCT_TIMESPEC=0 if test $gl_cv_sys_struct_timespec_in_time_h = yes; then TIME_H_DEFINES_STRUCT_TIMESPEC=1 else @@ -55,10 +58,24 @@ AC_DEFUN([gl_CHECK_TYPE_STRUCT_TIMESPEC], [gl_cv_sys_struct_timespec_in_sys_time_h=no])]) if test $gl_cv_sys_struct_timespec_in_sys_time_h = yes; then SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=1 + else + AC_CACHE_CHECK([for struct timespec in ], + [gl_cv_sys_struct_timespec_in_pthread_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[static struct timespec x; x.tv_sec = x.tv_nsec;]])], + [gl_cv_sys_struct_timespec_in_pthread_h=yes], + [gl_cv_sys_struct_timespec_in_pthread_h=no])]) + if test $gl_cv_sys_struct_timespec_in_pthread_h = yes; then + PTHREAD_H_DEFINES_STRUCT_TIMESPEC=1 + fi fi fi AC_SUBST([TIME_H_DEFINES_STRUCT_TIMESPEC]) AC_SUBST([SYS_TIME_H_DEFINES_STRUCT_TIMESPEC]) + AC_SUBST([PTHREAD_H_DEFINES_STRUCT_TIMESPEC]) ]) AC_DEFUN([gl_TIME_MODULE_INDICATOR], diff --git a/gl/m4/unistd_h.m4 b/gl/m4/unistd_h.m4 index 8c2eec6..48d06c7 100644 --- a/gl/m4/unistd_h.m4 +++ b/gl/m4/unistd_h.m4 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 45 +# unistd_h.m4 serial 46 dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -38,8 +38,9 @@ AC_DEFUN([gl_UNISTD_H], ]], [chown dup2 dup3 environ euidaccess faccessat fchdir fchownat fsync ftruncate getcwd getdomainname getdtablesize getgroups gethostname getlogin getlogin_r getpagesize getusershell setusershell - endusershell lchown link linkat lseek pipe2 pread readlink readlinkat - rmdir sleep symlink symlinkat ttyname_r unlink unlinkat usleep]) + endusershell lchown link linkat lseek pipe2 pread pwrite readlink + readlinkat rmdir sleep symlink symlinkat ttyname_r unlink unlinkat + usleep]) ]) AC_DEFUN([gl_UNISTD_MODULE_INDICATOR], @@ -79,6 +80,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) GNULIB_PIPE2=0; AC_SUBST([GNULIB_PIPE2]) GNULIB_PREAD=0; AC_SUBST([GNULIB_PREAD]) + GNULIB_PWRITE=0; AC_SUBST([GNULIB_PWRITE]) GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) GNULIB_READLINKAT=0; AC_SUBST([GNULIB_READLINKAT]) GNULIB_RMDIR=0; AC_SUBST([GNULIB_RMDIR]) @@ -113,6 +115,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], HAVE_LINKAT=1; AC_SUBST([HAVE_LINKAT]) HAVE_PIPE2=1; AC_SUBST([HAVE_PIPE2]) HAVE_PREAD=1; AC_SUBST([HAVE_PREAD]) + HAVE_PWRITE=1; AC_SUBST([HAVE_PWRITE]) HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) HAVE_READLINKAT=1; AC_SUBST([HAVE_READLINKAT]) HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) @@ -140,10 +143,12 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], REPLACE_LINKAT=0; AC_SUBST([REPLACE_LINKAT]) REPLACE_LSEEK=0; AC_SUBST([REPLACE_LSEEK]) REPLACE_PREAD=0; AC_SUBST([REPLACE_PREAD]) + REPLACE_PWRITE=0; AC_SUBST([REPLACE_PWRITE]) REPLACE_READLINK=0; AC_SUBST([REPLACE_READLINK]) REPLACE_RMDIR=0; AC_SUBST([REPLACE_RMDIR]) REPLACE_SLEEP=0; AC_SUBST([REPLACE_SLEEP]) REPLACE_SYMLINK=0; AC_SUBST([REPLACE_SYMLINK]) + REPLACE_TTYNAME_R=0; AC_SUBST([REPLACE_TTYNAME_R]) REPLACE_UNLINK=0; AC_SUBST([REPLACE_UNLINK]) REPLACE_UNLINKAT=0; AC_SUBST([REPLACE_UNLINKAT]) REPLACE_USLEEP=0; AC_SUBST([REPLACE_USLEEP]) diff --git a/gl/m4/vasnprintf.m4 b/gl/m4/vasnprintf.m4 index 50a20cc..ebe3c52 100644 --- a/gl/m4/vasnprintf.m4 +++ b/gl/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 29 +# vasnprintf.m4 serial 31 dnl Copyright (C) 2002-2004, 2006-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -54,6 +54,7 @@ AC_DEFUN([gl_PREREQ_PRINTF_PARSE], # Prerequisites of lib/vasnprintf.c. AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF], [ + AC_REQUIRE([AC_C_INLINE]) AC_REQUIRE([AC_FUNC_ALLOCA]) AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) AC_REQUIRE([gt_TYPE_WCHAR_T]) @@ -62,6 +63,17 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF], dnl Use the _snprintf function only if it is declared (because on NetBSD it dnl is defined as a weak alias of snprintf; we prefer to use the latter). AC_CHECK_DECLS([_snprintf], , , [#include ]) + dnl We can avoid a lot of code by assuming that snprintf's return value + dnl conforms to ISO C99. So check that. + AC_REQUIRE([gl_SNPRINTF_RETVAL_C99]) + case "$gl_cv_func_snprintf_retval_c99" in + *yes) + AC_DEFINE([HAVE_SNPRINTF_RETVAL_C99], [1], + [Define if the return value of the snprintf function is the number of + of bytes (excluding the terminating NUL) that would have been produced + if the buffer had been large enough.]) + ;; + esac ]) # Extra prerequisites of lib/vasnprintf.c for supporting 'long double' diff --git a/gl/m4/visibility.m4 b/gl/m4/visibility.m4 index 6d3f9c9..077c476 100644 --- a/gl/m4/visibility.m4 +++ b/gl/m4/visibility.m4 @@ -1,4 +1,4 @@ -# visibility.m4 serial 2 (gettext-0.18) +# visibility.m4 serial 3 (gettext-0.18) dnl Copyright (C) 2005, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -26,15 +26,37 @@ AC_DEFUN([gl_VISIBILITY], CFLAG_VISIBILITY= HAVE_VISIBILITY=0 if test -n "$GCC"; then + dnl First, check whether -Werror can be added to the command line, or + dnl whether it leads to an error because of some other option that the + dnl user has put into $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether the -Werror option is usable]) + AC_CACHE_VAL([gl_cv_cc_vis_werror], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([], [], + [gl_cv_cc_vis_werror=yes], + [gl_cv_cc_vis_werror=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_vis_werror]) + dnl Now check whether visibility declarations are supported. AC_MSG_CHECKING([for simple visibility declarations]) AC_CACHE_VAL([gl_cv_cc_visibility], [ gl_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden" + dnl We use the option -Werror and a function dummyfunc, because on some + dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning + dnl "visibility attribute not supported in this configuration; ignored" + dnl at the first function definition in every compilation unit, and we + dnl don't want to use the option in this case. + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi AC_TRY_COMPILE( [extern __attribute__((__visibility__("hidden"))) int hiddenvar; extern __attribute__((__visibility__("default"))) int exportedvar; extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); - extern __attribute__((__visibility__("default"))) int exportedfunc (void);], + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {}], [], [gl_cv_cc_visibility=yes], [gl_cv_cc_visibility=no]) diff --git a/gl/netdb.in.h b/gl/netdb.in.h index 73db46a..f800cac 100644 --- a/gl/netdb.in.h +++ b/gl/netdb.in.h @@ -41,6 +41,8 @@ /* The definition of _GL_ARG_NONNULL is copied here. */ +/* The definition of _GL_WARN_ON_USE is copied here. */ + /* Declarations for a platform that lacks , or where it is incomplete. */ @@ -186,7 +188,33 @@ extern int getnameinfo (const struct sockaddr *restrict sa, socklen_t salen, # define NI_NUMERICSERV 2 # endif -#endif /* @GNULIB_GETADDRINFO@ */ +#elif defined GNULIB_POSIXCHECK + +# undef getaddrinfo +# if HAVE_RAW_DECL_GETADDRINFO +_GL_WARN_ON_USE (getaddrinfo, "getaddrinfo is unportable - " + "use gnulib module getaddrinfo for portability"); +# endif + +# undef freeaddrinfo +# if HAVE_RAW_DECL_FREEADDRINFO +_GL_WARN_ON_USE (freeaddrinfo, "freeaddrinfo is unportable - " + "use gnulib module getaddrinfo for portability"); +# endif + +# undef gai_strerror +# if HAVE_RAW_DECL_GAI_STRERROR +_GL_WARN_ON_USE (gai_strerror, "gai_strerror is unportable - " + "use gnulib module getaddrinfo for portability"); +# endif + +# undef getnameinfo +# if HAVE_RAW_DECL_GETNAMEINFO +_GL_WARN_ON_USE (getnameinfo, "getnameinfo is unportable - " + "use gnulib module getaddrinfo for portability"); +# endif + +#endif #endif /* _GL_NETDB_H */ #endif /* _GL_NETDB_H */ diff --git a/gl/regex_internal.c b/gl/regex_internal.c index 17eafaa..98b8d5d 100644 --- a/gl/regex_internal.c +++ b/gl/regex_internal.c @@ -733,15 +733,17 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) mbstate_t cur_state; wchar_t wc2; Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; size_t mbclen; +#if 0 /* dead code: buf is set but never used */ + unsigned char buf[6]; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; } +#endif /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); diff --git a/gl/regex_internal.h b/gl/regex_internal.h index 2cb8c4d..5aa5aa2 100644 --- a/gl/regex_internal.h +++ b/gl/regex_internal.h @@ -467,6 +467,8 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, # else /* alloca is implemented with malloc, so just use malloc. */ # define __libc_use_alloca(n) 0 +# undef alloca +# define alloca(n) malloc (n) # endif #endif diff --git a/gl/sha1.c b/gl/sha1.c new file mode 100644 index 0000000..7251ca8 --- /dev/null +++ b/gl/sha1.c @@ -0,0 +1,428 @@ +/* sha1.c - Functions to compute SHA1 message digest of files or + memory blocks according to the NIST specification FIPS-180-1. + + Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2008, 2009, 2010 Free + Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Scott G. Miller + Credits: + Robert Klep -- Expansion function fix +*/ + +#include + +#include "sha1.h" + +#include +#include +#include + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) (n) +#else +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#endif + +#define BLOCKSIZE 32768 +#if BLOCKSIZE % 64 != 0 +# error "invalid BLOCKSIZE" +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Take a pointer to a 160 bit block of data (five 32 bit ints) and + initialize it to the start constants of the SHA1 algorithm. This + must be called before using hash in the call to sha1_hash. */ +void +sha1_init_ctx (struct sha1_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + ctx->E = 0xc3d2e1f0; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Copy the 4 byte value from v into the memory location pointed to by *cp, + If your architecture allows unaligned access this is equivalent to + * (uint32_t *) cp = v */ +static inline void +set_uint32 (char *cp, uint32_t v) +{ + memcpy (cp, &v, sizeof v); +} + +/* Put result from CTX in first 20 bytes following RESBUF. The result + must be in little endian byte order. */ +void * +sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) +{ + char *r = resbuf; + set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); + set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); + set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); + set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); + set_uint32 (r + 4 * sizeof ctx->E, SWAP (ctx->E)); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + uint32_t bytes = ctx->buflen; + size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); + ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3); + + memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); + + /* Process last bytes. */ + sha1_process_block (ctx->buffer, size * 4, ctx); + + return sha1_read_ctx (ctx, resbuf); +} + +/* Compute SHA1 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +sha1_stream (FILE *stream, void *resblock) +{ + struct sha1_ctx ctx; + size_t sum; + + char *buffer = malloc (BLOCKSIZE + 72); + if (!buffer) + return 1; + + /* Initialize the computation context. */ + sha1_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + { + free (buffer); + return 1; + } + goto process_partial_block; + } + + /* We've read at least one byte, so ignore errors. But always + check for EOF, since feof may be true even though N > 0. + Otherwise, we could end up calling fread after EOF. */ + if (feof (stream)) + goto process_partial_block; + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + sha1_process_block (buffer, BLOCKSIZE, &ctx); + } + + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + sha1_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + sha1_finish_ctx (&ctx, resblock); + free (buffer); + return 0; +} + +/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha1_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha1_ctx ctx; + + /* Initialize the computation context. */ + sha1_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha1_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha1_finish_ctx (&ctx, resblock); +} + +void +sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, + &((char *) ctx->buffer)[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +# define alignof(type) offsetof (struct { char c; type x; }, x) +# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha1_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha1_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[16], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between md5.c and sha1.c --- */ + +/* SHA1 round constants */ +#define K1 0x5a827999 +#define K2 0x6ed9eba1 +#define K3 0x8f1bbcdc +#define K4 0xca62c1d6 + +/* Round functions. Note that F2 is the same as F4. */ +#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) +#define F2(B,C,D) (B ^ C ^ D) +#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) +#define F4(B,C,D) (B ^ C ^ D) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + const uint32_t *words = buffer; + size_t nwords = len / sizeof (uint32_t); + const uint32_t *endp = words + nwords; + uint32_t x[16]; + uint32_t a = ctx->A; + uint32_t b = ctx->B; + uint32_t c = ctx->C; + uint32_t d = ctx->D; + uint32_t e = ctx->E; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + +#define rol(x, n) (((x) << (n)) | ((uint32_t) (x) >> (32 - (n)))) + +#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ + ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ + , (x[I&0x0f] = rol(tm, 1)) ) + +#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ + + F( B, C, D ) \ + + K \ + + M; \ + B = rol( B, 30 ); \ + } while(0) + + while (words < endp) + { + uint32_t tm; + int t; + for (t = 0; t < 16; t++) + { + x[t] = SWAP (*words); + words++; + } + + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + a = ctx->A += a; + b = ctx->B += b; + c = ctx->C += c; + d = ctx->D += d; + e = ctx->E += e; + } +} diff --git a/gl/sha1.h b/gl/sha1.h new file mode 100644 index 0000000..de209b2 --- /dev/null +++ b/gl/sha1.h @@ -0,0 +1,92 @@ +/* Declarations of functions and data types used for SHA1 sum + library functions. + Copyright (C) 2000, 2001, 2003, 2005, 2006, 2008, 2009, 2010 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef SHA1_H +# define SHA1_H 1 + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +#define SHA1_DIGEST_SIZE 20 + +/* Structure to save state of computation between the single steps. */ +struct sha1_ctx +{ + uint32_t A; + uint32_t B; + uint32_t C; + uint32_t D; + uint32_t E; + + uint32_t total[2]; + uint32_t buflen; + uint32_t buffer[32]; +}; + + +/* Initialize structure containing state of computation. */ +extern void sha1_init_ctx (struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void sha1_process_block (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha1_process_bytes (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 20 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. */ +extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 20 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. */ +extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); + + +/* Compute SHA1 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 20 bytes + beginning at RESBLOCK. */ +extern int sha1_stream (FILE *stream, void *resblock); + +/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha1_buffer (const char *buffer, size_t len, void *resblock); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/gl/stdbool.in.h b/gl/stdbool.in.h index e2312ec..574c281 100644 --- a/gl/stdbool.in.h +++ b/gl/stdbool.in.h @@ -50,6 +50,9 @@ with this substitute. With this substitute, only the values 0 and 1 give the expected result when converted to _Bool' or 'bool'. + - C99 allows the use of (_Bool)0.0 in constant expressions, but + this substitute cannot always provide this property. + Also, it is suggested that programs use 'bool' rather than '_Bool'; this isn't required, but 'bool' is more common. */ diff --git a/gl/stdio-write.c b/gl/stdio-write.c index f7da9e4..a6a0eb1 100644 --- a/gl/stdio-write.c +++ b/gl/stdio-write.c @@ -63,7 +63,6 @@ } # if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ -# if !DEPENDS_ON_LIBINTL /* avoid collision with intl/printf.c */ int printf (const char *format, ...) { @@ -76,7 +75,6 @@ printf (const char *format, ...) return retval; } -# endif # endif # if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ diff --git a/gl/stdio.in.h b/gl/stdio.in.h index dcb8ee5..80b9dbf 100644 --- a/gl/stdio.in.h +++ b/gl/stdio.in.h @@ -63,6 +63,10 @@ /* The definition of _GL_WARN_ON_USE is copied here. */ +/* Macros for stringification. */ +#define _GL_STDIO_STRINGIZE(token) #token +#define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) + #if @GNULIB_DPRINTF@ # if @REPLACE_DPRINTF@ @@ -640,16 +644,26 @@ _GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " #if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ # if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) /* Don't break __attribute__((format(printf,M,N))). */ -# define printf __printf__ -# endif -# define GNULIB_overrides_printf 1 +# define printf __printf__ +# endif _GL_FUNCDECL_RPL_1 (__printf__, int, (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) __attribute__ ((__format__ (__printf__, 1, 2))) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); +# else +_GL_FUNCDECL_RPL (printf, int, + (const char *format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (printf, int, (const char *format, ...)); +# endif +# define GNULIB_overrides_printf 1 # else _GL_CXXALIAS_SYS (printf, int, (const char *format, ...)); # endif diff --git a/gl/strerror.c b/gl/strerror.c index b0df778..46153ab 100644 --- a/gl/strerror.c +++ b/gl/strerror.c @@ -32,6 +32,9 @@ # include "intprops.h" +/* Use the system functions, not the gnulib overrides in this file. */ +# undef sprintf + # undef strerror # if ! HAVE_DECL_STRERROR # define strerror(n) NULL diff --git a/gl/string.in.h b/gl/string.in.h index eb8d758..13c0f09 100644 --- a/gl/string.in.h +++ b/gl/string.in.h @@ -372,12 +372,23 @@ _GL_WARN_ON_USE (strndup, "strndup is unportable - " MAXLEN bytes. If no '\0' terminator is found in that many bytes, return MAXLEN. */ #if @GNULIB_STRNLEN@ -# if ! @HAVE_DECL_STRNLEN@ +# if @REPLACE_STRNLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strnlen +# define strnlen rpl_strnlen +# endif +_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__string, size_t __maxlen) + __attribute__ ((__pure__)) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__string, size_t __maxlen)); +# else +# if ! @HAVE_DECL_STRNLEN@ _GL_FUNCDECL_SYS (strnlen, size_t, (char const *__string, size_t __maxlen) __attribute__ ((__pure__)) _GL_ARG_NONNULL ((1))); -# endif +# endif _GL_CXXALIAS_SYS (strnlen, size_t, (char const *__string, size_t __maxlen)); +# endif _GL_CXXALIASWARN (strnlen); #elif defined GNULIB_POSIXCHECK # undef strnlen diff --git a/gl/sys_stat.in.h b/gl/sys_stat.in.h index a64bf02..dc7ef51 100644 --- a/gl/sys_stat.in.h +++ b/gl/sys_stat.in.h @@ -56,7 +56,8 @@ /* Before doing "#define mkdir rpl_mkdir" below, we need to include all headers that may declare mkdir(). */ #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -# include +# include /* mingw32, mingw64 */ +# include /* mingw64 */ #endif #ifndef S_IFMT @@ -455,7 +456,8 @@ _GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); #else /* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. Additionally, it declares _mkdir (and depending on compile flags, an - alias mkdir), only in the nonstandard , which is included above. */ + alias mkdir), only in the nonstandard includes and , + which are included above. */ # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ static inline int diff --git a/gl/time.in.h b/gl/time.in.h index 8e364fe..6fb4fd7 100644 --- a/gl/time.in.h +++ b/gl/time.in.h @@ -48,10 +48,20 @@ /* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3). Or they define it with the wrong member names or define it in - (e.g., FreeBSD circa 1997). */ + (e.g., FreeBSD circa 1997). Stock Mingw does not define it, but the + pthreads-win32 library defines it in . */ # if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ # if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ # include +# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +# include +/* The pthreads-win32 also defines a couple of broken macros. */ +# undef asctime_r +# undef ctime_r +# undef gmtime_r +# undef localtime_r +# undef rand_r +# undef strtok_r # else # ifdef __cplusplus diff --git a/gl/unistd.in.h b/gl/unistd.in.h index 45fc5dc..7914f22 100644 --- a/gl/unistd.in.h +++ b/gl/unistd.in.h @@ -86,7 +86,7 @@ #endif #if (@GNULIB_WRITE@ || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ - || @GNULIB_PREAD@ || defined GNULIB_POSIXCHECK) + || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK) /* Get ssize_t. */ # include #endif @@ -1016,6 +1016,40 @@ _GL_WARN_ON_USE (pread, "pread is unportable - " #endif +#if @GNULIB_PWRITE@ +/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. + Return the number of bytes written if successful, otherwise + set errno and return -1. 0 indicates nothing written. See the + POSIX:2001 specification + . */ +# if @REPLACE_PWRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define pwrite rpl_pwrite +# endif +_GL_FUNCDECL_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PWRITE@ +_GL_FUNCDECL_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pwrite); +#elif defined GNULIB_POSIXCHECK +# undef pwrite +# if HAVE_RAW_DECL_PWRITE +_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " + "use gnulib module pwrite for portability"); +# endif +#endif + + #if @GNULIB_READLINK@ /* Read the contents of the symbolic link FILE and place the first BUFSIZE bytes of it into BUF. Return the number of bytes placed into BUF if @@ -1164,12 +1198,23 @@ _GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " #if @GNULIB_TTYNAME_R@ /* Store at most BUFLEN characters of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ -# if !@HAVE_TTYNAME_R@ +# if @REPLACE_TTYNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ttyname_r +# define ttyname_r rpl_ttyname_r +# endif +_GL_FUNCDECL_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# else +# if !@HAVE_TTYNAME_R@ _GL_FUNCDECL_SYS (ttyname_r, int, (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); -# endif +# endif _GL_CXXALIAS_SYS (ttyname_r, int, (int fd, char *buf, size_t buflen)); +# endif _GL_CXXALIASWARN (ttyname_r); #elif defined GNULIB_POSIXCHECK # undef ttyname_r @@ -1268,7 +1313,10 @@ _GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) _GL_ARG_NONNULL ((2))); _GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); # else -_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count)); +/* Need to cast, because on mingw, the third parameter is + unsigned int count + and the return type is 'int'. */ +_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count)); # endif _GL_CXXALIASWARN (write); #endif diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c index 99d921e..e618901 100644 --- a/gl/vasnprintf.c +++ b/gl/vasnprintf.c @@ -148,8 +148,14 @@ # define USE_SNPRINTF 1 # if HAVE_DECL__SNWPRINTF /* On Windows, the function swprintf() has a different signature than - on Unix; we use the _snwprintf() function instead. */ -# define SNPRINTF _snwprintf + on Unix; we use the function _snwprintf() or - on mingw - snwprintf() + instead. The mingw function snwprintf() has fewer bugs than the + MSVCRT function _snwprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snwprintf +# else +# define SNPRINTF _snwprintf +# endif # else /* Unix. */ # define SNPRINTF swprintf @@ -167,8 +173,15 @@ # define USE_SNPRINTF 0 # endif # if HAVE_DECL__SNPRINTF - /* Windows. */ -# define SNPRINTF _snprintf + /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT + function _snprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snprintf + /* Here we need to call the native snprintf, not rpl_snprintf. */ +# undef snprintf +# else +# define SNPRINTF _snprintf +# endif # else /* Unix. */ # define SNPRINTF snprintf @@ -194,7 +207,7 @@ #undef remainder #define remainder rem -#if !USE_SNPRINTF && !WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION # if (HAVE_STRNLEN && !defined _AIX) # define local_strnlen strnlen # else @@ -210,7 +223,7 @@ local_strnlen (const char *string, size_t maxlen) # endif #endif -#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR) +#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen # else @@ -233,7 +246,7 @@ local_wcslen (const wchar_t *s) # endif #endif -#if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION # if HAVE_WCSNLEN # define local_wcsnlen wcsnlen # else @@ -1474,6 +1487,258 @@ is_borderline (const char *digits, size_t precision) #endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 + +/* Use a different function name, to make it possible that the 'wchar_t' + parametrization and the 'char' parametrization get compiled in the same + translation unit. */ +# if WIDE_CHAR_VERSION +# define MAX_ROOM_NEEDED wmax_room_needed +# else +# define MAX_ROOM_NEEDED max_room_needed +# endif + +/* Returns the number of TCHAR_T units needed as temporary space for the result + of sprintf or SNPRINTF of a single conversion directive. */ +static inline size_t +MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, + arg_type type, int flags, size_t width, int has_precision, + size_t precision, int pad_ourselves) +{ + size_t tmp_length; + + switch (conversion) + { + case 'd': case 'i': case 'u': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Multiply by 2, as an estimate for FLAG_GROUP. */ + tmp_length = xsum (tmp_length, tmp_length); + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'o': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'x': case 'X': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 2, to account for a leading sign or alternate form. */ + tmp_length = xsum (tmp_length, 2); + break; + + case 'f': case 'F': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + else + tmp_length = + (unsigned int) (DBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'e': case 'E': case 'g': case 'G': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'a': case 'A': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (DBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + break; + + case 'c': +# if HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# if HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + { +# if WIDE_CHAR_VERSION + /* ISO C says about %ls in fwprintf: + "If the precision is not specified or is greater than the size + of the array, the array shall contain a null wide character." + So if there is a precision, we must not use wcslen. */ + const wchar_t *arg = ap->arg[arg_index].a.a_wide_string; + + if (has_precision) + tmp_length = local_wcsnlen (arg, precision); + else + tmp_length = local_wcslen (arg); +# else + /* ISO C says about %ls in fprintf: + "If a precision is specified, no more than that many bytes are + written (including shift sequences, if any), and the array + shall contain a null wide character if, to equal the multibyte + character sequence length given by the precision, the function + would need to access a wide character one past the end of the + array." + So if there is a precision, we must not use wcslen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# endif + } + else +# endif + { +# if WIDE_CHAR_VERSION + /* ISO C says about %s in fwprintf: + "If the precision is not specified or is greater than the size + of the converted array, the converted array shall contain a + null wide character." + So if there is a precision, we must not use strlen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# else + /* ISO C says about %s in fprintf: + "If the precision is not specified or greater than the size of + the array, the array shall contain a null character." + So if there is a precision, we must not use strlen. */ + const char *arg = ap->arg[arg_index].a.a_string; + + if (has_precision) + tmp_length = local_strnlen (arg, precision); + else + tmp_length = strlen (arg); +# endif + } + break; + + case 'p': + tmp_length = + (unsigned int) (sizeof (void *) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + break; + + default: + abort (); + } + + if (!pad_ourselves) + { +# if ENABLE_UNISTDIO + /* Padding considers the number of characters, therefore the number of + elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); +# else + /* Padding considers the number of elements, says POSIX. */ + if (tmp_length < width) + tmp_length = width; +# endif + } + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + return tmp_length; +} + +#endif + DCHAR_T * VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, const FCHAR_T *format, va_list args) @@ -2103,7 +2368,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } #endif -#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T else if (dp->conversion == 's' # if WIDE_CHAR_VERSION && a.arg[dp->arg_index].type != TYPE_WIDE_STRING @@ -2592,8 +2857,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, count = wctomb (cbuf, *arg); # endif if (count <= 0) - /* Inconsistency. */ - abort (); + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } ENSURE_ALLOCATION (xsum (length, count)); memcpy (result + length, cbuf, count); length += count; @@ -2616,8 +2889,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, length += n; } } - } # endif + } #endif #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL else if ((dp->conversion == 'a' || dp->conversion == 'A') @@ -4301,11 +4574,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int has_width; size_t width; #endif -#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION int has_precision; size_t precision; #endif @@ -4330,7 +4603,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T *tmp; #endif -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION has_width = 0; width = 0; if (dp->width_start != dp->width_end) @@ -4364,7 +4637,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION has_precision = 0; precision = 6; if (dp->precision_start != dp->precision_end) @@ -4437,246 +4710,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !USE_SNPRINTF /* Allocate a temporary buffer of sufficient size for calling sprintf. */ - { - switch (dp->conversion) - { - - case 'd': case 'i': case 'u': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Multiply by 2, as an estimate for FLAG_GROUP. */ - tmp_length = xsum (tmp_length, tmp_length); - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'o': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'x': case 'X': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 2, to account for a leading sign or alternate form. */ - tmp_length = xsum (tmp_length, 2); - break; - - case 'f': case 'F': - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) (LDBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - else - tmp_length = - (unsigned int) (DBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'e': case 'E': case 'g': case 'G': - tmp_length = - 12; /* sign, decimal point, exponent etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'a': case 'A': - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) (LDBL_DIG - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (DBL_DIG - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Account for sign, decimal point etc. */ - tmp_length = xsum (tmp_length, 12); - break; - - case 'c': -# if HAVE_WINT_T && !WIDE_CHAR_VERSION - if (type == TYPE_WIDE_CHAR) - tmp_length = MB_CUR_MAX; - else -# endif - tmp_length = 1; - break; - - case 's': -# if HAVE_WCHAR_T - if (type == TYPE_WIDE_STRING) - { -# if WIDE_CHAR_VERSION - /* ISO C says about %ls in fwprintf: - "If the precision is not specified or is greater - than the size of the array, the array shall - contain a null wide character." - So if there is a precision, we must not use - wcslen. */ - const wchar_t *arg = - a.arg[dp->arg_index].a.a_wide_string; - - if (has_precision) - tmp_length = local_wcsnlen (arg, precision); - else - tmp_length = local_wcslen (arg); -# else - /* ISO C says about %ls in fprintf: - "If a precision is specified, no more than that - many bytes are written (including shift - sequences, if any), and the array shall contain - a null wide character if, to equal the - multibyte character sequence length given by - the precision, the function would need to - access a wide character one past the end of the - array." - So if there is a precision, we must not use - wcslen. */ - /* This case has already been handled above. */ - abort (); -# endif - } - else -# endif - { -# if WIDE_CHAR_VERSION - /* ISO C says about %s in fwprintf: - "If the precision is not specified or is greater - than the size of the converted array, the - converted array shall contain a null wide - character." - So if there is a precision, we must not use - strlen. */ - /* This case has already been handled above. */ - abort (); -# else - /* ISO C says about %s in fprintf: - "If the precision is not specified or greater - than the size of the array, the array shall - contain a null character." - So if there is a precision, we must not use - strlen. */ - const char *arg = a.arg[dp->arg_index].a.a_string; - - if (has_precision) - tmp_length = local_strnlen (arg, precision); - else - tmp_length = strlen (arg); -# endif - } - break; - - case 'p': - tmp_length = - (unsigned int) (sizeof (void *) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1 /* turn floor into ceil */ - + 2; /* account for leading 0x */ - break; - - default: - abort (); - } - - if (!pad_ourselves) - { -# if ENABLE_UNISTDIO - /* Padding considers the number of characters, therefore - the number of elements after padding may be - > max (tmp_length, width) - but is certainly - <= tmp_length + width. */ - tmp_length = xsum (tmp_length, width); -# else - /* Padding considers the number of elements, - says POSIX. */ - if (tmp_length < width) - tmp_length = width; -# endif - } - - tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - } + tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type, + flags, width, has_precision, precision, + pad_ourselves); if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) tmp = tmpbuf; @@ -4916,6 +4953,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif + errno = 0; switch (type) { case TYPE_SCHAR: @@ -5062,15 +5100,44 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Look at the snprintf() return value. */ if (retcount < 0) { +# if !HAVE_SNPRINTF_RETVAL_C99 /* HP-UX 10.20 snprintf() is doubly deficient: It doesn't understand the '%n' directive, *and* it returns -1 (rather than the length that would have been required) when the - buffer is too small. */ - size_t bigger_need = - xsum (xtimes (allocated, 2), 12); - ENSURE_ALLOCATION (bigger_need); - continue; + buffer is too small. + But a failure at this point can also come + from other reasons than a too small buffer, + such as an invalid wide string argument to + the %ls directive, or possibly an invalid + floating-point argument. */ + size_t tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, + dp->conversion, type, flags, + width, has_precision, + precision, pad_ourselves); + + if (maxlen < tmp_length) + { + /* Make more room. But try to do through + this reallocation only once. */ + size_t bigger_need = + xsum (length, + xsum (tmp_length, + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + /* And always grow proportionally. + (There may be several arguments, each + needing a little more room than the + previous one.) */ + size_t bigger_need2 = + xsum (xtimes (allocated, 2), 12); + if (bigger_need < bigger_need2) + bigger_need = bigger_need2; + ENSURE_ALLOCATION (bigger_need); + continue; + } +# endif } else count = retcount; @@ -5081,12 +5148,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Attempt to handle failure. */ if (count < 0) { + /* SNPRINTF or sprintf failed. Save and use the errno + that it has set, if any. */ + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) free (result); if (buf_malloced != NULL) free (buf_malloced); CLEANUP (); - errno = EINVAL; + errno = + (saved_errno != 0 + ? saved_errno + : (dp->conversion == 'c' || dp->conversion == 's' + ? EILSEQ + : EINVAL)); return NULL; } @@ -5422,6 +5498,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, length += count; break; } +#undef pad_ourselves +#undef prec_ourselves } } } @@ -5473,6 +5551,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } +#undef MAX_ROOM_NEEDED #undef TCHARS_PER_DCHAR #undef SNPRINTF #undef USE_SNPRINTF diff --git a/gl/verify.h b/gl/verify.h index bcd3f5a..4ad780c 100644 --- a/gl/verify.h +++ b/gl/verify.h @@ -69,13 +69,14 @@ if the entity names are not disambiguated. A workaround is to attach the current line number to the entity name: - #define GL_CONCAT0(x, y) x##y - #define GL_CONCAT(x, y) GL_CONCAT0 (x, y) - extern struct {...} * GL_CONCAT(dummy,__LINE__); + #define _GL_CONCAT0(x, y) x##y + #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) + extern struct {...} * _GL_CONCAT (dummy, __LINE__); But this has the problem that two invocations of verify from within the same macro would collide, since the __LINE__ value - would be the same for both invocations. + would be the same for both invocations. (The GCC __COUNTER__ + macro solves this problem, but is not portable.) A solution is to use the sizeof operator. It yields a number, getting rid of the identity of the type. Declarations like @@ -103,20 +104,41 @@ extern int (*dummy (void)) [sizeof (struct {...})]; + * GCC warns about duplicate declarations of the dummy function if + -Wredundant_decls is used. GCC 4.3 and later have a builtin + __COUNTER__ macro that can let us generate unique identifiers for + each dummy function, to suppress this warning. + * This implementation exploits the fact that GCC does not warn about the last declaration mentioned above. If a future version of GCC introduces a warning for this, the problem could be worked around - by using code specialized to GCC, e.g.,: + by using code specialized to GCC, just as __COUNTER__ is already + being used if available. #if 4 <= __GNUC__ - # define verify(R) \ - extern int (* verify_function__ (void)) \ - [__builtin_constant_p (R) && (R) ? 1 : -1] + # define verify(R) [another version to keep GCC happy] #endif * In C++, any struct definition inside sizeof is invalid. Use a template type to work around the problem. */ +/* Concatenate two preprocessor tokens. */ +# define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) +# define _GL_CONCAT0(x, y) x##y + +/* _GL_COUNTER is an integer, preferably one that changes each time we + use it. Use __COUNTER__ if it works, falling back on __LINE__ + otherwise. __LINE__ isn't perfect, but it's better than a + constant. */ +# if defined __COUNTER__ && __COUNTER__ != __COUNTER__ +# define _GL_COUNTER __COUNTER__ +# else +# define _GL_COUNTER __LINE__ +# endif + +/* Generate a symbol with the given prefix, making it unique if + possible. */ +# define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) /* Verify requirement R at compile-time, as an integer constant expression. Return 1. */ @@ -135,6 +157,7 @@ template /* Verify requirement R at compile-time, as a declaration without a trailing ';'. */ -# define verify(R) extern int (* verify_function__ (void)) [verify_true (R)] +# define verify(R) \ + extern int (* _GL_GENSYM (verify_function) (void)) [verify_true (R)] #endif diff --git a/gl/wchar.in.h b/gl/wchar.in.h index dd41d35..88d47db 100644 --- a/gl/wchar.in.h +++ b/gl/wchar.in.h @@ -407,7 +407,7 @@ _GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - " _GL_FUNCDECL_RPL (wcwidth, int, (wchar_t)); _GL_CXXALIAS_RPL (wcwidth, int, (wchar_t)); # else -# if !defined wcwidth && !@HAVE_DECL_WCWIDTH@ +# if !@HAVE_DECL_WCWIDTH@ /* wcwidth exists but is not declared. */ _GL_FUNCDECL_SYS (wcwidth, int, (wchar_t)); # endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 17e4c1b..99fa591 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -4,6 +4,7 @@ SUBDIRS = . tests noinst_LIBRARIES = libnagiosplug.a +AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" libnagiosplug_a_SOURCES = utils_base.c utils_disk.c utils_tcp.c utils_cmd.c EXTRA_DIST = utils_base.h utils_disk.h utils_tcp.h utils_cmd.h parse_ini.h extra_opts.h diff --git a/lib/tests/Makefile.am b/lib/tests/Makefile.am index 694baf0..06a4b42 100644 --- a/lib/tests/Makefile.am +++ b/lib/tests/Makefile.am @@ -5,6 +5,8 @@ noinst_PROGRAMS = @EXTRA_TEST@ TESTS = @EXTRA_TEST@ check_PROGRAMS = @EXTRA_TEST@ +AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" + INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins EXTRA_PROGRAMS = test_utils test_disk test_tcp test_cmd test_base64 test_ini1 test_ini3 test_opts1 test_opts2 test_opts3 diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c index 3a45944..5336907 100644 --- a/lib/tests/test_utils.c +++ b/lib/tests/test_utils.c @@ -21,6 +21,11 @@ #include "tap.h" +#include +#include + +#include "utils_base.c" + int main (int argc, char **argv) { @@ -28,8 +33,31 @@ main (int argc, char **argv) double temp; thresholds *thresholds = NULL; int rc; + char *temp_string; + state_key *temp_state_key = NULL; + state_data *temp_state_data; + time_t current_time; + char *temp_filename; + FILE *temp_fp; + + plan_tests(141); + + ok( this_nagios_plugin==NULL, "nagios_plugin not initialised"); + + np_init( "check_test", argc, argv ); + + ok( this_nagios_plugin!=NULL, "nagios_plugin now initialised"); + ok( !strcmp(this_nagios_plugin->plugin_name, "check_test"), "plugin name initialised" ); + + ok( this_nagios_plugin->argc==argc, "Argc set" ); + ok( this_nagios_plugin->argv==argv, "Argv set" ); - plan_tests(81+23); + np_set_args(0,0); + + ok( this_nagios_plugin->argc==0, "argc changed" ); + ok( this_nagios_plugin->argv==0, "argv changed" ); + + np_set_args(argc, argv); range = parse_range_string("6"); ok( range != NULL, "'6' is valid range"); @@ -251,5 +279,157 @@ main (int argc, char **argv) test=np_extract_ntpvar("", "foo"); ok(!test, "Empty string return NULL"); + + /* This is the result of running ./test_utils */ + temp_string = (char *) _np_state_generate_key(); + ok(!strcmp(temp_string, "83d877b6cdfefb5d6f06101fd6fe76762f21792c"), "Got hash with exe and no parameters" ) || + diag( "You are probably running in wrong directory. Must run as ./test_utils" ); + + + this_nagios_plugin->argc=4; + this_nagios_plugin->argv[0] = "./test_utils"; + this_nagios_plugin->argv[1] = "here"; + this_nagios_plugin->argv[2] = "--and"; + this_nagios_plugin->argv[3] = "now"; + temp_string = (char *) _np_state_generate_key(); + ok(!strcmp(temp_string, "94b5e17bf5abf51cb15aff5f69b96f2f8dac5ecd"), "Got based on expected argv" ); + + unsetenv("NAGIOS_PLUGIN_STATE_DIRECTORY"); + temp_string = (char *) _np_state_calculate_location_prefix(); + ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory" ); + + setenv("NAGIOS_PLUGIN_STATE_DIRECTORY", "", 1); + temp_string = (char *) _np_state_calculate_location_prefix(); + ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory even with empty string" ); + + setenv("NAGIOS_PLUGIN_STATE_DIRECTORY", "/usr/local/nagios/var", 1); + temp_string = (char *) _np_state_calculate_location_prefix(); + ok(!strcmp(temp_string, "/usr/local/nagios/var"), "Got default directory" ); + + + + ok(temp_state_key==NULL, "temp_state_key initially empty"); + + this_nagios_plugin->argc=1; + this_nagios_plugin->argv[0] = "./test_utils"; + np_enable_state(NULL, 51); + temp_state_key = this_nagios_plugin->state; + ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); + ok( !strcmp(temp_state_key->name, "83d877b6cdfefb5d6f06101fd6fe76762f21792c"), "Got generated filename" ); + + + np_enable_state("allowedchars_in_keyname", 77); + temp_state_key = this_nagios_plugin->state; + ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); + ok( !strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars" ); + ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/allowedchars_in_keyname"), "Got internal filename" ); + + + /* Don't do this test just yet. Will die */ + /* + np_enable_state("bad^chars$in@here", 77); + temp_state_key = this_nagios_plugin->state; + ok( !strcmp(temp_state_key->name, "bad_chars_in_here"), "Got key name with bad chars replaced" ); + */ + + np_enable_state("funnykeyname", 54); + temp_state_key = this_nagios_plugin->state; + ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); + ok( !strcmp(temp_state_key->name, "funnykeyname"), "Got key name" ); + + + + ok( !strcmp(temp_state_key->_filename, "/usr/local/nagios/var/check_test/funnykeyname"), "Got internal filename" ); + ok( temp_state_key->data_version==54, "Version set" ); + + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Got no state data as file does not exist" ); + + +/* + temp_fp = fopen("var/statefile", "r"); + if (temp_fp==NULL) + printf("Error opening. errno=%d\n", errno); + printf("temp_fp=%s\n", temp_fp); + ok( _np_state_read_file(temp_fp) == TRUE, "Can read state file" ); + fclose(temp_fp); +*/ + + temp_state_key->_filename="var/statefile"; + temp_state_data = np_state_read(temp_state_key); + ok( this_nagios_plugin->state->state_data!=NULL, "Got state data now" ) || diag("Are you running in right directory? Will get coredump next if not"); + ok( this_nagios_plugin->state->state_data->time==1234567890, "Got time" ); + ok( !strcmp((char *)this_nagios_plugin->state->state_data->data, "String to read"), "Data as expected" ); + + temp_state_key->data_version=53; + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Older data version gives NULL" ); + temp_state_key->data_version=54; + + temp_state_key->_filename="var/nonexistant"; + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Missing file gives NULL" ); + ok( this_nagios_plugin->state->state_data==NULL, "No state information" ); + + temp_state_key->_filename="var/oldformat"; + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Old file format gives NULL" ); + + temp_state_key->_filename="var/baddate"; + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Bad date gives NULL" ); + + temp_state_key->_filename="var/missingdataline"; + temp_state_data = np_state_read(temp_state_key); + ok( temp_state_data==NULL, "Missing data line gives NULL" ); + + + + + unlink("var/generated"); + temp_state_key->_filename="var/generated"; + current_time=1234567890; + np_state_write_string(current_time, "String to read"); + ok(system("cmp var/generated var/statefile")==0, "Generated file same as expected"); + + + + + unlink("var/generated_directory/statefile"); + unlink("var/generated_directory"); + temp_state_key->_filename="var/generated_directory/statefile"; + current_time=1234567890; + np_state_write_string(current_time, "String to read"); + ok(system("cmp var/generated_directory/statefile var/statefile")==0, "Have created directory"); + + /* This test to check cannot write to dir - can't automate yet */ + /* + unlink("var/generated_bad_dir"); + mkdir("var/generated_bad_dir", S_IRUSR); + np_state_write_string(current_time, "String to read"); + */ + + + temp_state_key->_filename="var/generated"; + time(¤t_time); + np_state_write_string(0, "String to read"); + temp_state_data = np_state_read(temp_state_key); + /* Check time is set to current_time */ + ok(system("cmp var/generated var/statefile > /dev/null")!=0, "Generated file should be different this time"); + ok(this_nagios_plugin->state->state_data->time-current_time<=1, "Has time generated from current time"); + + + /* Don't know how to automatically test this. Need to be able to redefine die and catch the error */ + /* + temp_state_key->_filename="/dev/do/not/expect/to/be/able/to/write"; + np_state_write_string(0, "Bad file"); + */ + + + np_cleanup(); + + ok( this_nagios_plugin==NULL, "Free'd this_nagios_plugin" ); + return exit_status(); } + diff --git a/lib/tests/var/.gitignore b/lib/tests/var/.gitignore new file mode 100644 index 0000000..95a59c1 --- /dev/null +++ b/lib/tests/var/.gitignore @@ -0,0 +1,2 @@ +generated +generated_directory/ diff --git a/lib/tests/var/baddate b/lib/tests/var/baddate new file mode 100644 index 0000000..2fda432 --- /dev/null +++ b/lib/tests/var/baddate @@ -0,0 +1,5 @@ +# NP State file +1 +54 +2147483647 +Date in future!!!! diff --git a/lib/tests/var/missingdataline b/lib/tests/var/missingdataline new file mode 100644 index 0000000..d87f73a --- /dev/null +++ b/lib/tests/var/missingdataline @@ -0,0 +1,4 @@ +# NP State file +1 +54 +1234567890 diff --git a/lib/tests/var/oldformat b/lib/tests/var/oldformat new file mode 100644 index 0000000..102f8c9 --- /dev/null +++ b/lib/tests/var/oldformat @@ -0,0 +1,5 @@ +# NP State file +0 +54 +1234567890 +String to read diff --git a/lib/tests/var/statefile b/lib/tests/var/statefile new file mode 100644 index 0000000..5002139 --- /dev/null +++ b/lib/tests/var/statefile @@ -0,0 +1,5 @@ +# NP State file +1 +54 +1234567890 +String to read diff --git a/lib/utils_base.c b/lib/utils_base.c index 4303e15..6de92cb 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c @@ -27,6 +27,56 @@ #include "common.h" #include #include "utils_base.h" +#include + +#define np_free(ptr) { if(ptr) { free(ptr); ptr = NULL; } } + +nagios_plugin *this_nagios_plugin=NULL; + +void np_init( char *plugin_name, int argc, char **argv ) { + if (this_nagios_plugin==NULL) { + this_nagios_plugin = malloc(sizeof(nagios_plugin)); + if (this_nagios_plugin==NULL) { + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + } + this_nagios_plugin->plugin_name = strdup(plugin_name); + if (this_nagios_plugin->plugin_name==NULL) + die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); + this_nagios_plugin->argc = argc; + this_nagios_plugin->argv = argv; + } +} + +void np_set_args( int argc, char **argv ) { + if (this_nagios_plugin==NULL) + die(STATE_UNKNOWN, _("This requires np_init to be called")); + + this_nagios_plugin->argc = argc; + this_nagios_plugin->argv = argv; +} + + +void np_cleanup() { + if (this_nagios_plugin!=NULL) { + if(this_nagios_plugin->state!=NULL) { + if(this_nagios_plugin->state->state_data) { + np_free(this_nagios_plugin->state->state_data->data); + np_free(this_nagios_plugin->state->state_data); + } + np_free(this_nagios_plugin->state->name); + np_free(this_nagios_plugin->state); + } + np_free(this_nagios_plugin->plugin_name); + np_free(this_nagios_plugin); + } + this_nagios_plugin=NULL; +} + +/* Hidden function to get a pointer to this_nagios_plugin for testing */ +void _get_nagios_plugin( nagios_plugin **pointer ){ + *pointer = this_nagios_plugin; +} void die (int result, const char *fmt, ...) @@ -35,6 +85,9 @@ die (int result, const char *fmt, ...) va_start (ap, fmt); vprintf (fmt, ap); va_end (ap); + if(this_nagios_plugin!=NULL) { + np_cleanup(); + } exit (result); } @@ -102,7 +155,7 @@ _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_st thresholds *temp_thresholds = NULL; if ((temp_thresholds = malloc(sizeof(thresholds))) == NULL) - die(STATE_UNKNOWN, _("Cannot allocate memory: %s\n"), + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno)); temp_thresholds->warning = NULL; @@ -310,3 +363,302 @@ char *np_extract_value(const char *varlist, const char *name, char sep) { return value; } +/* + * Returns a string to use as a keyname, based on an md5 hash of argv, thus + * hopefully a unique key per service/plugin invocation. Use the extra-opts + * parse of argv, so that uniqueness in parameters are reflected there. + */ +char *_np_state_generate_key() { + struct sha1_ctx ctx; + int i; + char **argv = this_nagios_plugin->argv; + unsigned char result[20]; + char keyname[41]; + char *p=NULL; + + sha1_init_ctx(&ctx); + + for(i=0; iargc; i++) { + sha1_process_bytes(argv[i], strlen(argv[i]), &ctx); + } + + sha1_finish_ctx(&ctx, &result); + + for (i=0; i<20; ++i) { + sprintf(&keyname[2*i], "%02x", result[i]); + } + keyname[40]='\0'; + + p = strdup(keyname); + if(p==NULL) { + die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); + } + return p; +} + +void _cleanup_state_data() { + if (this_nagios_plugin->state->state_data!=NULL) { + np_free(this_nagios_plugin->state->state_data->data); + np_free(this_nagios_plugin->state->state_data); + } +} + +/* + * Internal function. Returns either: + * envvar NAGIOS_PLUGIN_STATE_DIRECTORY + * statically compiled shared state directory + */ +char* _np_state_calculate_location_prefix(){ + char *env_dir; + + env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY"); + if(env_dir && env_dir[0] != '\0') + return env_dir; + return NP_STATE_DIR_PREFIX; +} + +/* + * Initiatializer for state routines. + * Sets variables. Generates filename. Returns np_state_key. die with + * UNKNOWN if exception + */ +void np_enable_state(char *keyname, int expected_data_version) { + state_key *this_state = NULL; + char *temp_filename = NULL; + char *temp_keyname = NULL; + char *p=NULL; + + if(this_nagios_plugin==NULL) + die(STATE_UNKNOWN, _("This requires np_init to be called")); + + this_state = (state_key *) malloc(sizeof(state_key)); + if(this_state==NULL) + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + + if(keyname==NULL) { + temp_keyname = _np_state_generate_key(); + } else { + temp_keyname = strdup(keyname); + if(temp_keyname==NULL) + die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); + } + /* Die if invalid characters used for keyname */ + p = temp_keyname; + while(*p!='\0') { + if(! (isalnum(*p) || *p == '_')) { + die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'")); + } + p++; + } + this_state->name=temp_keyname; + this_state->plugin_name=this_nagios_plugin->plugin_name; + this_state->data_version=expected_data_version; + this_state->state_data=NULL; + + /* Calculate filename */ + asprintf(&temp_filename, "%s/%s/%s", _np_state_calculate_location_prefix(), this_nagios_plugin->plugin_name, this_state->name); + this_state->_filename=temp_filename; + + this_nagios_plugin->state = this_state; +} + +/* + * Will return NULL if no data is available (first run). If key currently + * exists, read data. If state file format version is not expected, return + * as if no data. Get state data version number and compares to expected. + * If numerically lower, then return as no previous state. die with UNKNOWN + * if exceptional error. + */ +state_data *np_state_read() { + state_key *my_state_key; + state_data *this_state_data=NULL; + FILE *statefile; + int c; + int rc = FALSE; + + if(this_nagios_plugin==NULL) + die(STATE_UNKNOWN, _("This requires np_init to be called")); + + /* Open file. If this fails, no previous state found */ + statefile = fopen( this_nagios_plugin->state->_filename, "r" ); + if(statefile!=NULL) { + + this_state_data = (state_data *) malloc(sizeof(state_data)); + if(this_state_data==NULL) + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + + this_state_data->data=NULL; + this_nagios_plugin->state->state_data = this_state_data; + + rc = _np_state_read_file(statefile); + + fclose(statefile); + } + + if(rc==FALSE) { + _cleanup_state_data(); + } + + return this_nagios_plugin->state->state_data; +} + +/* + * Read the state file + */ +int _np_state_read_file(FILE *f) { + int c, status=FALSE; + size_t pos; + char *line; + int i; + int failure=0; + time_t current_time, data_time; + enum { STATE_FILE_VERSION, STATE_DATA_VERSION, STATE_DATA_TIME, STATE_DATA_TEXT, STATE_DATA_END } expected=STATE_FILE_VERSION; + + time(¤t_time); + + /* Note: This introduces a limit of 1024 bytes in the string data */ + line = (char *) malloc(1024); + if(line==NULL) + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + + while(!failure && (fgets(line,1024,f))!=NULL){ + pos=strlen(line); + if(line[pos-1]=='\n') { + line[pos-1]='\0'; + } + + if(line[0] == '#') continue; + + switch(expected) { + case STATE_FILE_VERSION: + i=atoi(line); + if(i!=NP_STATE_FORMAT_VERSION) + failure++; + else + expected=STATE_DATA_VERSION; + break; + case STATE_DATA_VERSION: + i=atoi(line); + if(i != this_nagios_plugin->state->data_version) + failure++; + else + expected=STATE_DATA_TIME; + break; + case STATE_DATA_TIME: + /* If time > now, error */ + data_time=strtoul(line,NULL,10); + if(data_time > current_time) + failure++; + else { + this_nagios_plugin->state->state_data->time = data_time; + expected=STATE_DATA_TEXT; + } + break; + case STATE_DATA_TEXT: + this_nagios_plugin->state->state_data->data = strdup(line); + if(this_nagios_plugin->state->state_data->data==NULL) + die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); + expected=STATE_DATA_END; + status=TRUE; + break; + case STATE_DATA_END: + ; + } + } + + np_free(line); + return status; +} + +/* + * If time=NULL, use current time. Create state file, with state format + * version, default text. Writes version, time, and data. Avoid locking + * problems - use mv to write and then swap. Possible loss of state data if + * two things writing to same key at same time. + * Will die with UNKNOWN if errors + */ +void np_state_write_string(time_t data_time, char *data_string) { + FILE *fp; + char *temp_file=NULL; + int fd=0, result=0; + time_t current_time; + size_t len; + char *directories=NULL; + char *p=NULL; + + if(data_time==0) + time(¤t_time); + else + current_time=data_time; + + /* If file doesn't currently exist, create directories */ + if(access(this_nagios_plugin->state->_filename,F_OK)!=0) { + asprintf(&directories, "%s", this_nagios_plugin->state->_filename); + if(directories==NULL) + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + + for(p=directories+1; *p; p++) { + if(*p=='/') { + *p='\0'; + if((access(directories,F_OK)!=0) && (mkdir(directories, S_IRWXU)!=0)) { + /* Can't free this! Otherwise error message is wrong! */ + /* np_free(directories); */ + die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories); + } + *p='/'; + } + } + np_free(directories); + } + + asprintf(&temp_file,"%s.XXXXXX",this_nagios_plugin->state->_filename); + if(temp_file==NULL) + die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), + strerror(errno)); + + if((fd=mkstemp(temp_file))==-1) { + np_free(temp_file); + die(STATE_UNKNOWN, _("Cannot create temporary filename")); + } + + fp=(FILE *)fdopen(fd,"w"); + if(fp==NULL) { + close(fd); + unlink(temp_file); + np_free(temp_file); + die(STATE_UNKNOWN, _("Unable to open temporary state file")); + } + + fprintf(fp,"# NP State file\n"); + fprintf(fp,"%d\n",NP_STATE_FORMAT_VERSION); + fprintf(fp,"%d\n",this_nagios_plugin->state->data_version); + fprintf(fp,"%lu\n",current_time); + fprintf(fp,"%s\n",data_string); + + fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP); + + fflush(fp); + + result=fclose(fp); + + fsync(fd); + + if(result!=0) { + unlink(temp_file); + np_free(temp_file); + die(STATE_UNKNOWN, _("Error writing temp file")); + } + + if(rename(temp_file, this_nagios_plugin->state->_filename)!=0) { + unlink(temp_file); + np_free(temp_file); + die(STATE_UNKNOWN, _("Cannot rename state temp file")); + } + + np_free(temp_file); +} + diff --git a/lib/utils_base.h b/lib/utils_base.h index 49e40a6..0cb371f 100644 --- a/lib/utils_base.h +++ b/lib/utils_base.h @@ -2,6 +2,8 @@ #define _UTILS_BASE_ /* Header file for nagios plugins utils_base.c */ +#include "sha1.h" + /* This file holds header information for thresholds - use this in preference to individual plugin logic */ @@ -28,6 +30,30 @@ typedef struct thresholds_struct { range *critical; } thresholds; +#define NP_STATE_FORMAT_VERSION 1 + +typedef struct state_data_struct { + time_t time; + void *data; + int length; /* Of binary data */ + } state_data; + + +typedef struct state_key_struct { + char *name; + char *plugin_name; + int data_version; + char *_filename; + state_data *state_data; + } state_key; + +typedef struct np_struct { + char *plugin_name; + state_key *state; + int argc; + char **argv; + } nagios_plugin; + range *parse_range_string (char *); int _set_thresholds(thresholds **, char *, char *); void set_thresholds(thresholds **, char *, char *); @@ -67,4 +93,13 @@ char *np_extract_value(const char*, const char*, char); */ #define np_extract_ntpvar(l, n) np_extract_value(l, n, ',') + +void np_enable_state(char *, int); +state_data *np_state_read(); +void np_state_write_string(time_t, char *); + +void np_init(char *, int argc, char **argv); +void np_set_args(int argc, char **argv); +void np_cleanup(); + #endif /* _UTILS_BASE_ */ diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 4570fb7..36a28b0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -39,7 +39,7 @@ EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \ check_nagios check_by_ssh check_dns check_nt check_ide_smart \ check_procs check_mysql_query check_apt -EXTRA_DIST = t utils.c netutils.c sslutils.c popen.c utils.h netutils.h \ +EXTRA_DIST = t tests utils.c netutils.c sslutils.c popen.c utils.h netutils.h \ popen.h common.h runcmd.c runcmd.h PLUGINHDRS = common.h diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index 2bc6024..bf21022 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c @@ -59,6 +59,10 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #define MAX_OIDS 8 +/* Longopts only arguments */ +#define L_CALCULATE_RATE CHAR_MAX+1 +#define L_RATE_MULTIPLIER CHAR_MAX+2 + /* Gobble to string - stop incrementing c when c[0] match one of the * characters in s */ #define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } @@ -131,12 +135,16 @@ char *delimiter; char *output_delim; char *miblist = NULL; int needmibs = FALSE; +int calculate_rate = 0; +int rate_multiplier = 1; +state_data *previous_state; +double previous_value[MAX_OIDS]; int main (int argc, char **argv) { - int i, len, line; + int i, len, line, total_oids; unsigned int bk_count = 0, dq_count = 0; int iresult = STATE_UNKNOWN; int result = STATE_UNKNOWN; @@ -154,6 +162,17 @@ main (int argc, char **argv) char *th_crit=NULL; char type[8] = ""; output chld_out, chld_err; + char *previous_string=NULL; + char *ap=NULL; + char *state_string=NULL; + size_t response_length, current_length, string_length; + char *temp_string=NULL; + int is_numeric=0; + time_t current_time; + double temp_double; + time_t duration; + char *conv = "12345678"; + int is_counter=0; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -173,12 +192,33 @@ main (int argc, char **argv) timeout_interval = DEFAULT_TIMEOUT; retries = DEFAULT_RETRIES; + np_init( (char *) progname, argc, argv ); + /* Parse extra opts if any */ argv=np_extra_opts (&argc, argv, progname); + np_set_args(argc, argv); + if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); + if(calculate_rate) { + if (!strcmp(label, "SNMP")) + label = strdup("SNMP RATE"); + time(¤t_time); + i=0; + previous_state = np_state_read(); + if(previous_state!=NULL) { + /* Split colon separated values */ + previous_string = strdup((char *) previous_state->data); + while((ap = strsep(&previous_string, ":")) != NULL) { + if(verbose>2) + printf("State for %d=%s\n", i, ap); + previous_value[i++]=strtod(ap,NULL); + } + } + } + /* Populate the thresholds */ th_warn=warning_thresholds; th_crit=critical_thresholds; @@ -271,7 +311,10 @@ main (int argc, char **argv) } for (line=0, i=0; line < chld_out.lines; line++, i++) { - const char *conv = "%.0f"; + if(calculate_rate) + conv = "%.10g"; + else + conv = "%.0f"; ptr = chld_out.line[line]; oidname = strpcpy (oidname, ptr, delimiter); @@ -286,21 +329,34 @@ main (int argc, char **argv) /* Clean up type array - Sol10 does not necessarily zero it out */ bzero(type, sizeof(type)); + is_counter=0; /* We strip out the datatype indicator for PHBs */ - if (strstr (response, "Gauge: ")) + if (strstr (response, "Gauge: ")) { show = strstr (response, "Gauge: ") + 7; - else if (strstr (response, "Gauge32: ")) + is_numeric++; + } + else if (strstr (response, "Gauge32: ")) { show = strstr (response, "Gauge32: ") + 9; + is_numeric++; + } else if (strstr (response, "Counter32: ")) { show = strstr (response, "Counter32: ") + 11; - strcpy(type, "c"); + is_numeric++; + is_counter=1; + if(!calculate_rate) + strcpy(type, "c"); } else if (strstr (response, "Counter64: ")) { show = strstr (response, "Counter64: ") + 11; - strcpy(type, "c"); + is_numeric++; + is_counter=1; + if(!calculate_rate) + strcpy(type, "c"); } - else if (strstr (response, "INTEGER: ")) + else if (strstr (response, "INTEGER: ")) { show = strstr (response, "INTEGER: ") + 9; + is_numeric++; + } else if (strstr (response, "STRING: ")) { show = strstr (response, "STRING: ") + 8; conv = "%.10g"; @@ -345,14 +401,33 @@ main (int argc, char **argv) iresult = STATE_DEPENDENT; - /* Process this block for integer comparisons */ - if (thlds[i]->warning || thlds[i]->critical) { + /* Process this block for numeric comparisons */ + if (is_numeric) { ptr = strpbrk (show, "0123456789"); if (ptr == NULL) die (STATE_UNKNOWN,_("No valid data returned")); response_value[i] = strtod (ptr, NULL); - iresult = get_status(response_value[i], thlds[i]); - asprintf (&show, conv, response_value[i]); + + if(calculate_rate) { + if (previous_state!=NULL) { + duration = current_time-previous_state->time; + if(duration<=0) + die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); + temp_double = (response_value[i]-previous_value[i])/duration; + /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ + if(is_counter) { + if(temp_double<(double)0.0) + temp_double+=(double)4294967296.0; /* 2^32 */ + if(temp_double<(double)0.0) + temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; + } + iresult = get_status(temp_double, thlds[i]); + asprintf (&show, conv, temp_double); + } + } else { + iresult = get_status(response_value[i], thlds[i]); + asprintf (&show, conv, response_value[i]); + } } /* Process this block for string matching */ @@ -380,6 +455,7 @@ main (int argc, char **argv) } /* Process this block for existence-nonexistence checks */ + /* TV: Should this be outside of this else block? */ else { if (eval_method[i] & CRIT_PRESENT) iresult = STATE_CRITICAL; @@ -393,7 +469,7 @@ main (int argc, char **argv) result = max_state (result, iresult); /* Prepend a label for this OID if there is one */ - if (nlabels > (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) + if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) asprintf (&outbuff, "%s%s%s %s%s%s", outbuff, (i == 0) ? " " : output_delim, labels[i], mark (iresult), show, mark (iresult)); @@ -409,7 +485,13 @@ main (int argc, char **argv) ptr = NULL; strtod(show, &ptr); if (ptr > show) { - strncat(perfstr, oidname, sizeof(perfstr)-strlen(perfstr)-1); + if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) + temp_string=labels[i]; + else + temp_string=oidname; + if(calculate_rate) + asprintf(&temp_string,"%s-rate",temp_string); + strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); len = sizeof(perfstr)-strlen(perfstr)-1; strncat(perfstr, show, len>ptr-show ? ptr-show : len); @@ -419,6 +501,44 @@ main (int argc, char **argv) strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); } } + total_oids=i; + + /* Save state data, as all data collected now */ + if(calculate_rate) { + string_length=1024; + state_string=malloc(string_length); + if(state_string==NULL) + die(STATE_UNKNOWN, _("Cannot malloc")); + + current_length=0; + for(i=0; istring_length) { + string_length=current_length+1024; + state_string=realloc(state_string,string_length); + if(state_string==NULL) + die(STATE_UNKNOWN, _("Cannot realloc()")); + } + strcpy(&state_string[current_length],temp_string); + current_length=current_length+response_length; + state_string[current_length]=':'; + current_length++; + free(temp_string); + } + state_string[--current_length]='\0'; + if (verbose > 2) + printf("State string=%s\n",state_string); + + /* This is not strictly the same as time now, but any subtle variations will cancel out */ + np_state_write_string(current_time, state_string ); + if(previous_state==NULL) { + /* Or should this be highest state? */ + die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); + } + } printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); if (mult_resp) printf ("%s", mult_resp); @@ -462,6 +582,8 @@ process_arguments (int argc, char **argv) {"authpasswd", required_argument, 0, 'A'}, {"privpasswd", required_argument, 0, 'X'}, {"next", no_argument, 0, 'n'}, + {"rate", no_argument, 0, L_CALCULATE_RATE}, + {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, {0, 0, 0, 0} }; @@ -609,7 +731,6 @@ process_arguments (int argc, char **argv) output_delim = strscpy (output_delim, optarg); break; case 'l': /* label */ - label = optarg; nlabels++; if (nlabels >= labels_size) { labels_size += 8; @@ -666,7 +787,15 @@ process_arguments (int argc, char **argv) unitv[nunits - 1] = ptr; } break; - + case L_CALCULATE_RATE: + if(calculate_rate==0) + np_enable_state(NULL, 1); + calculate_rate = 1; + break; + case L_RATE_MULTIPLIER: + if(!is_integer(optarg)||(rate_multiplier=atoi(optarg)<=0)) + usage2(_("Rate multiplier must be a positive integer"),optarg); + break; } } @@ -905,6 +1034,8 @@ print_help (void) printf (" %s\n", _("Warning threshold range(s)")); printf (" %s\n", "-c, --critical=THRESHOLD(s)"); printf (" %s\n", _("Critical threshold range(s)")); + printf (" %s\n", "--rate"); + printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); /* Tests Against Strings */ printf (" %s\n", "-s, --string=STRING"); @@ -914,7 +1045,7 @@ print_help (void) printf (" %s\n", "-R, --eregi=REGEX"); printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); printf (" %s\n", "-l, --label=STRING"); - printf (" %s\n", _("Prefix label for output from plugin (default -s 'SNMP')")); + printf (" %s\n", _("Prefix label for output from plugin (default -l 'SNMP')")); /* Output Formatting */ printf (" %s\n", "-u, --units=STRING"); @@ -945,6 +1076,16 @@ print_help (void) printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); + printf("\n"); + printf("%s\n", _("Rate Calculation:")); + printf(" %s\n", _("In many places, SNMP returns counters that are only meaningful when")); + printf(" %s\n", _("calculating the counter difference since the last check. check_snmp")); + printf(" %s\n", _("saves the last state information in a file so that the rate can be")); + printf(" %s\n", _("calculated. Use the --rate option to save state information. On the")); + printf(" %s\n", _("first run, there will be no prior state - this will return with OK.")); + printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so")); + printf(" %s\n", _("changing the arguments will create a new state file.")); + printf (UT_SUPPORT); } diff --git a/plugins/tests/check_snmp.t b/plugins/tests/check_snmp.t index b5f3f89..1742079 100755 --- a/plugins/tests/check_snmp.t +++ b/plugins/tests/check_snmp.t @@ -51,7 +51,7 @@ if ($ARGV[0] && $ARGV[0] eq "-d") { } } -my $tests = 9; +my $tests = 21; if (-x "./check_snmp") { plan tests => $tests; } else { @@ -106,3 +106,40 @@ like($res->output, '/'.quotemeta('SNMP OK - And now have fun with with this: \"C "And now have fun with with this: \"C:\\\\\" because we\'re not done yet!"').'/m', "Attempt to confuse parser No.3"); +system("rm /usr/local/nagios/var/check_snmp/*"); +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); +is($res->return_code, 0, "Returns OK"); +is($res->output, "No previous data to calculate rate - assume okay"); + +# Need to sleep, otherwise duration=0 +sleep 1; + +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); +is($res->return_code, 1, "WARNING - due to going above rate calculation" ); +is($res->output, "SNMP RATE WARNING - *666* | iso.3.6.1.4.1.8072.3.2.67.10-rate=666 "); + +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" ); +is($res->return_code, 3, "UNKNOWN - basically the divide by zero error" ); +is($res->output, "Time duration between plugin calls is invalid"); + + +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); +is($res->return_code, 0, "OK for first call" ); +is($res->output, "No previous data to calculate rate - assume okay" ); + +# Need to sleep, otherwise duration=0 +sleep 1; + +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); +is($res->return_code, 0, "OK as no thresholds" ); +is($res->output, "SNMP RATE OK - inoctets 666 | inoctets-rate=666 ", "Check label"); + +sleep 2; + +$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" ); +is($res->return_code, 0, "OK as no thresholds" ); +is($res->output, "SNMP RATE OK - inoctets 333 | inoctets-rate=333 ", "Check rate decreases due to longer interval"); + + + + diff --git a/plugins/tests/check_snmp_agent.pl b/plugins/tests/check_snmp_agent.pl index 302ba6e..425caeb 100644 --- a/plugins/tests/check_snmp_agent.pl +++ b/plugins/tests/check_snmp_agent.pl @@ -33,9 +33,9 @@ ends with with this: C:\\'; my $multilin5 = 'And now have fun with with this: "C:\\" because we\'re not done yet!'; -my @fields = (ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_UNSIGNED, ASN_UNSIGNED, ASN_COUNTER, ASN_COUNTER64, ASN_UNSIGNED); -my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32))); -my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef); +my @fields = (ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_UNSIGNED, ASN_UNSIGNED, ASN_COUNTER, ASN_COUNTER64, ASN_UNSIGNED, ASN_COUNTER); +my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32)), 64000); +my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef, 666); # Number of elements in our OID my $oidelts; -- 2.30.2