/*
* 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 .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
#include "mymalloc/mymalloc.h"
/*------------------------------------------------------------------------*/
/* support.c - support functions for the gateway httpd. */
/*------------------------------------------------------------------------*/
/*
* RCS:
* $RCSfile: support.c,v $ $Revision: 1.6 $ $State: Exp $
* $Locker: $
*/
#include
#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 );
}