summaryrefslogtreecommitdiffstats
path: root/httpserver/support.cc
diff options
context:
space:
mode:
Diffstat (limited to 'httpserver/support.cc')
-rw-r--r--httpserver/support.cc640
1 files changed, 640 insertions, 0 deletions
diff --git a/httpserver/support.cc b/httpserver/support.cc
new file mode 100644
index 0000000..6a011fd
--- /dev/null
+++ b/httpserver/support.cc
@@ -0,0 +1,640 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community 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 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community 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 rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "mymalloc/mymalloc.h"
+/*------------------------------------------------------------------------*/
+/* support.c - support functions for the gateway httpd. */
+/*------------------------------------------------------------------------*/
+/*
+ * RCS:
+ * $RCSfile: support.c,v $ $Revision: 1.6 $ $State: Exp $
+ * $Locker: $
+ */
+
+#include <ctype.h>
+
+#include "defs.h"
+#include "types.h"
+#include "protos.h"
+#include "server.h"
+
+
+/****** support/Get_OpenMax **************************************************
+*
+* NAME
+* Get_OpenMax -- get the maximum of file descriptors per process.
+*
+* SYNOPSIS
+* int Get_OpenMax( void );
+*
+* FUNCTION
+* Get the systems maximum number of file descriptors per process. Uses
+* OPEN_MAX -- if defined -- else asks the system per sysconf() call.
+* If this still doesn't succeed, returns some kind of "reasonable
+* default".
+*
+* INPUTS
+* openmax - A global variable that holds the value of OPEN_MAX,
+* if defined, else '0'.
+*
+* RESULT
+* Returns the number of file descriptors, may be zero or a positive
+* int value.
+* openmax will be set to an appropriate value if it was set to '0'
+* when Get_OpenMax() was called.
+*
+* NOTES
+* Uses ErrMsg() to report problems with sysconf(). Hmmm...
+*
+* BUGS
+* Does also return the guessed value if sysconf() reported an error.
+* This seems to be okay for my needs...
+*
+* SEE ALSO
+* Richard W. Stevens: "Advanced Programming in the UNIX Environment",
+* 1992 Addison-Wesley Publishing Company, Inc.
+*
+******************************************************************************
+*
+*/
+
+#ifdef OPEN_MAX
+static size_t openmax = OPEN_MAX; /* Wenn vorhanden, dann ist das alles */
+#else /* was gebraucht wird. */
+static size_t openmax = 0;
+#endif
+
+#ifdef NOFILE
+#define OPEN_MAX_GUESS NOFILE
+#else
+#define OPEN_MAX_GUESS 256 /* Falls OPEN_MAX undefiniert (dynamisch) */
+#endif /* ist, ist dies u.U. nicht adaequat! */
+
+int Get_OpenMax( void )
+{
+ if( openmax == 0 )
+ {
+ errno = 0;
+ if( ( openmax = sysconf( _SC_OPEN_MAX ) ) < 0 )
+ {
+ if( errno == 0 )
+ {
+ openmax = OPEN_MAX_GUESS;
+ }
+ else
+ {
+ /* sysconf() returned an error... strange, but... */
+ /* Does it justify to break the program? */
+ /* Naah, I don't think so... So we just print a note */
+ /* and give back our "reasonable default"... */
+ ErrorMsg( E_SYS, WARN, "WARN: sysconf error for _SC_OPEN_MAX." );
+ openmax = OPEN_MAX_GUESS;
+ }
+ }
+ }
+
+ return( openmax );
+}
+
+
+/****** support/PathAlloc ****************************************************
+*
+* NAME
+* PathAlloc -- allocate memory as buffer for pathnames.
+*
+* SYNOPSIS
+* char *PathAlloc( size_t *size );
+*
+* FUNCTION
+* Get the systems maximum of characters in absolute pathnames. Uses
+* PATH_MAX -- if defined -- else asks the system per pathconf() call.
+* If this still doesn't succeed, uses some kind of "reasonable
+* default".
+* Then it calls malloc() to allocate the buffer.
+*
+* INPUTS
+* size - A pointer to a variable, which will set to the size of
+* the buffer. If it is NULL, you won't get any size
+* information.
+* pathmax - A global variable that holds the value of PATH_MAX,
+* if defined, else '0'
+*
+* RESULT
+* Returns a "char" pointer to the allocated buffer.
+* NULL, if the allocation failed. Then it will also print a log
+* message.
+* pathmax will be set to an appropriate value if it was set to '0'
+* when PathAlloc() was called.
+*
+* NOTES
+* Uses ErrMsg() to report problems with pathconf() and malloc().
+*
+* BUGS
+* Does also use the guessed value if pathconf() reported an error.
+* This seems to be okay for my needs...
+*
+* SEE ALSO
+* Richard W. Stevens: "Advanced Programming in the UNIX Environment",
+* 1992 Addison-Wesley Publishing Company, Inc.
+*
+******************************************************************************
+*
+*/
+
+#ifdef PATH_MAX
+static size_t pathmax = PATH_MAX; /* Wenn vorhanden, dann ist das alles */
+#else /* was gebraucht wird. */
+static size_t pathmax = 0;
+#endif
+
+#ifdef MAXPATHLEN
+#define PATH_MAX_GUESS MAXPATHLEN
+#else
+#define PATH_MAX_GUESS 1024 /* Falls PATH_MAX undefiniert (dynamisch) */
+#endif /* ist, ist dies u.U. nicht adäquat! */
+
+char *PathAlloc( size_t *size )
+{
+ char *Ptr;
+
+ if( pathmax == 0 )
+ {
+ errno = 0;
+ if( ( pathmax = pathconf( "/", _PC_PATH_MAX ) ) < 0 )
+ {
+ if( errno == 0 )
+ {
+ pathmax = PATH_MAX_GUESS;
+ }
+ else
+ {
+ /* pathconf() returned an error... strange, but... */
+ /* See also Get_OpenMax(). */
+ /* We give back our "reasonable default"... */
+ ErrorMsg( E_SYS, WARN, "WARN: pathconf error for _PC_PATH_MAX." );
+ pathmax = PATH_MAX_GUESS;
+ }
+ }
+ }
+ else
+ {
+ // it appears that every call makes the path 1 byte longer. Anyway, the config file
+ // is not read too often and I am not willing to debug it now
+ pathmax++; /* Don't forget the "/" character... */
+ }
+
+ if( ( Ptr = (char*)mymalloc( pathmax + 1 ) ) == NULL )
+ {
+ if( size != NULL )
+ *size = 0;
+ ErrorMsg( E_SYS, ERROR, "ERROR: malloc error for pathname buffer." );
+ }
+ else
+ {
+ if( size != NULL )
+ *size = pathmax + 1;
+ }
+ return( Ptr );
+}
+
+
+/****** support/ReadN ********************************************************
+*
+* NAME
+*
+*
+* SYNOPSIS
+*
+*
+* FUNCTION
+*
+*
+* INPUTS
+*
+*
+* RESULT
+*
+*
+* NOTES
+*
+*
+* BUGS
+*
+*
+* SEE ALSO
+*
+*
+******************************************************************************
+*
+*/
+/**************************************************************************
+ * Read "n" bytes from a descriptor.
+ * Use in place of read() when fd is a stream socket.
+ * Checks for error 'EAGAIN', in case of nonblocking IO.
+ */
+
+int ReadN( register int fd, register char *ptr, register int nbytes )
+{
+ int nleft;
+ int nread;
+
+ nleft = nbytes;
+ while( nleft > 0 )
+ {
+ nread = read( fd, ptr, nleft );
+ if( nread < 0 )
+ if( errno != EAGAIN )
+ return( nread ); /* error, return < 0 */
+ else
+ continue;
+ else if( nread == 0 )
+ break; /* EOF */
+ nleft -= nread;
+ ptr += nread;
+ }
+ return( nbytes - nleft ); /* return >= 0 */
+}
+
+
+/****** support/WriteN *******************************************************
+*
+* NAME
+*
+*
+* SYNOPSIS
+*
+*
+* FUNCTION
+*
+*
+* INPUTS
+*
+*
+* RESULT
+*
+*
+* NOTES
+*
+*
+* BUGS
+*
+*
+* SEE ALSO
+*
+*
+******************************************************************************
+*
+*/
+/**************************************************************************
+ * Write "n" bytes to a descriptor.
+ * Use in place of write() when fd is a stream socket.
+ * Checks for error 'EAGAIN', in case of nonblocking IO.
+ */
+
+int WriteN( register int fd, register char *ptr, register int nbytes )
+{
+ long nleft;
+ long nwritten = 0;
+
+ nleft = nbytes;
+ while( nleft > 0 )
+ {
+ nwritten = write( fd, ptr, nleft );
+ if( nwritten < 0 )
+ {
+ if( errno != EAGAIN )
+ return( nwritten ); /* error */
+ else
+ continue;
+ }
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+ return( nbytes - nleft );
+}
+
+
+/****** support/ReadLine *****************************************************
+*
+* NAME
+*
+*
+* SYNOPSIS
+*
+*
+* FUNCTION
+*
+*
+* INPUTS
+*
+*
+* RESULT
+*
+*
+* NOTES
+*
+*
+* BUGS
+*
+*
+* SEE ALSO
+*
+*
+******************************************************************************
+*
+*/
+/**************************************************************************
+ * Read a line from a descriptor.
+ * Checks for error 'EAGAIN', in case of nonblocking IO.
+ */
+
+int ReadLine( register int fd, register char *ptr, register int maxlen )
+{
+ int n;
+ int rc;
+ char c;
+
+ for( n = 1; n < maxlen; n++ )
+ {
+ if( ( rc = read( fd, &c, 1 ) ) == 1 )
+ {
+ *ptr++ = c;
+ if( c == '\n' )
+ break;
+ }
+ else if( rc == 0 )
+ if( n == 1 )
+ return( 0 ); /* EOF, no data read */
+ else
+ break; /* EOF, some data was read */
+ else
+ if( errno != EAGAIN )
+ return( -1 ); /* error */
+ }
+ *ptr = 0;
+ return( n );
+}
+
+
+/****** support/ParseString **************************************************
+*
+* NAME
+* ParseString -- Break string into words.
+*
+* SYNOPSIS
+* int ParseString( char *String, char *Token, ... );
+*
+* FUNCTION
+*
+* RESULT
+*
+* NOTES
+*
+* BUGS
+*
+* SEE ALSO
+*
+******************************************************************************
+*
+*/
+
+rc_t ParseString( char *String, char *Token, ... )
+{
+ /* ###TODO: Das letzte Argument sollte den kompletten Reststring erhalten */
+ /* Buffer loeschen vor Austritt */
+ va_list ArgPtr;
+ char *Keyword;
+ char *Value;
+ char *NextToken;
+ char *NNextToken;
+ char *Delim = " \t\n\r"; /* Begrenzungszeichen */
+
+ if( ( String[0] == '#' ) || /* Kommentar, */
+ ( String[0] == '\n' ) || /* oder Leerzeile? */
+ ( String[0] == '\r' ) )
+ return( ERROR ); /* => Zurück. */
+
+ Keyword = strtok( String, Delim ); /* 1. Token suchen */
+ if( Keyword != NULL ) /* Etwas gefunden? */
+ {
+ if( Keyword[0] == '#' ) /* Auch Kommentarzeile: */
+ return( ERROR ); /* => Zurück. */
+ strcpy( Token, Keyword ); /* Keyword in Buffer kopieren */
+
+ /* Var.Arg. Liste abarbeiten bis Arg == NULL. */
+ /* Letztes Arg. muss NULL sein, da va_arg() nicht selbst in der Lage */
+ /* ist das letzte Argument zu erkennen. */
+
+ va_start( ArgPtr, Token ); /* VarArg initialisieren */
+ NextToken = va_arg( ArgPtr, char * ); /* 1. zus. Argument holen. */
+ if( NextToken != NULL)
+ {
+ NNextToken = va_arg( ArgPtr, char * ); /* 2. zus. Arg. holen */
+ while( NNextToken != NULL ) /* Argument vorhanden? */
+ {
+ Value = strtok( NULL, Delim ); /* Weiteres Token suchen */
+ if( Value != NULL ) /* Wort gefunden? */
+ strcpy( NextToken, Value ); /* Token in Buffer kopieren */
+ else /* Ansonsten: */
+ strcpy( NextToken, "\0" ); /* Leerstring uebergeben */
+ NextToken = NNextToken;
+ NNextToken = va_arg( ArgPtr, char * ); /* Zeiger auf nächstes Arg. */
+ }
+ Value = strtok( NULL, "\n\r" ); /* Zeiger auf Reststring holen */
+ if( Value != NULL ) /* Wenn vorhanden, */
+ strcpy( NextToken, Value ); /* in letztes Arg. übergeben */
+ else /* wenn nicht, */
+ strcpy( NextToken, "\0" ); /* Leerstring übergeben */
+ }
+ va_end( ArgPtr ); /* VarArg aufräumen */
+ return( OK ); /* OK: Es wurde etwas gefunden */
+ }
+ return( ERROR ); /* ERROR: String war leer. */
+}
+
+
+/****** support/SNPrintf *****************************************************
+*
+* NAME
+* SNPrintf -- print into buffer with size-check.
+*
+* SYNOPSIS
+* int SNPrintf( char *String, size_t *Size, const char *Format, ... );
+*
+* FUNCTION
+*
+* RESULT
+*
+* NOTES
+*
+* BUGS
+*
+* SEE ALSO
+*
+******************************************************************************
+*
+*/
+
+int SNPrintf( char *String, size_t *Size, const char *Format, ... )
+{
+ va_list ArgPtr;
+ int n = 0;
+
+ if( *Size > 0 )
+ {
+ va_start( ArgPtr, Format );
+ n = VSNPrintf( String, *Size, Format, ArgPtr );
+ va_end( ArgPtr );
+
+ if( n >= 0 )
+ *Size = *Size - n;
+ else
+ *Size = 0;
+ }
+ return( n );
+}
+
+
+/****** support/VSNPrintf ****************************************************
+*
+* NAME
+* VSNPrintf -- print variable argument list into buffer with size-check.
+*
+* SYNOPSIS
+* int VSNPrintf( char *String, size_t Size,
+* const char *Format, va_list ArgPtr );
+*
+* FUNCTION
+*
+* RESULT
+*
+* NOTES
+*
+* BUGS
+*
+* SEE ALSO
+*
+******************************************************************************
+*
+*/
+
+int VSNPrintf( char *String, size_t Size, const char *Format, va_list ArgPtr )
+{
+ int n = 0;
+ char *Buffer = NULL;
+
+#ifdef NO_vsnprintf
+ if( Size == 0 )
+ n = 0;
+ else if( Size > 0 )
+ {
+ if( ( Buffer = (char*)mymalloc( BUFFSIZE ) ) != NULL )
+ {
+ n = vsprintf( Buffer, Format, ArgPtr );
+ if( n < Size )
+ strncpy( String, Buffer, Size );
+ else
+ {
+ strncpy( String, Buffer, Size-1 );
+ *( String + Size ) = '\0';
+ n = -1;
+ }
+ free( Buffer );
+ }
+ else
+ n = -1;
+ }
+ else
+ n = -1;
+#else
+ n = vsnprintf( String, Size, Format, ArgPtr );
+#endif
+ return( n );
+}
+
+
+/****** support/StrError *****************************************************
+*
+* NAME
+* StrError - return error string for given error code.
+*
+* SYNOPSIS
+* char *StrError( int ErrNum );
+*
+* FUNCTION
+*
+* RESULT
+*
+* NOTES
+*
+* BUGS
+*
+* SEE ALSO
+*
+******************************************************************************
+*
+*/
+
+char *StrError( int ErrNum )
+{
+#ifdef NO_strerror
+ char Buffer[20];
+
+ bzero( Buffer, 20 );
+ sprintf( Buffer, "Error %d", ErrNum );
+ return( Buffer );
+#else
+ return( strerror( ErrNum ) );
+#endif
+}
+
+/****** support/StrToLower ***************************************************
+*
+* NAME
+* StrToLower - make all characters of a string lower case.
+*
+* SYNOPSIS
+* char *StrToLower( char *String );
+*
+* FUNCTION
+*
+* RESULT
+*
+* NOTES
+*
+* BUGS
+*
+* SEE ALSO
+*
+******************************************************************************
+*
+*/
+
+char *StrToLower( char *String )
+{
+ while( *String != '\0' )
+ {
+ *String = tolower( *String );
+ String++;
+ }
+ return( String );
+}