blob: c0098c5fbb4589bb76a66dbe92dbef703197d2dd [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "system.h"
#ifdef NO_PTHREAD_RTL
static pthread_mutex_t getrtl_mutex = PTHREAD_MUTEX_INITIALIZER;
/* struct passwd differs on some platforms */
#if defined NETBSD
struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
{
struct passwd* res;
pthread_mutex_lock(&getrtl_mutex);
if ( (res = getpwnam(name)) )
{
int nname, npasswd, nclass, ngecos, ndir;
nname= strlen(res->pw_name)+1;
npasswd= strlen(res->pw_passwd)+1;
nclass= strlen(res->pw_class)+1;
ngecos= strlen(res->pw_gecos)+1;
ndir= strlen(res->pw_dir)+1;
if (nname+npasswd+nclass+ngecos
+ndir+strlen(res->pw_shell) < size)
{
memcpy(s, res, sizeof(struct passwd));
strcpy(buffer, res->pw_name);
s->pw_name = buffer;
buffer += nname;
strcpy(buffer, res->pw_passwd);
s->pw_passwd = buffer;
buffer += npasswd;
strcpy(buffer, res->pw_class);
s->pw_class = buffer;
buffer += nclass;
strcpy(buffer, res->pw_gecos);
s->pw_gecos = buffer;
buffer += ngecos;
strcpy(buffer, res->pw_dir);
s->pw_dir = buffer;
buffer += ndir;
strcpy(buffer, res->pw_shell);
s->pw_shell = buffer;
res = s;
}
else
res = 0;
}
pthread_mutex_unlock(&getrtl_mutex);
return(res);
}
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
size_t buflen, struct passwd **result)
{
struct passwd* res;
int retval = 0;
pthread_mutex_lock(&getrtl_mutex);
if ( (res = getpwuid(uid)) )
{
size_t pw_name, pw_passwd, pw_class, pw_gecos, pw_dir, pw_shell;
pw_name = strlen(res->pw_name)+1;
pw_passwd = strlen(res->pw_passwd)+1;
pw_class = strlen(res->pw_class)+1;
pw_gecos = strlen(res->pw_gecos)+1;
pw_dir = strlen(res->pw_dir)+1;
pw_shell = strlen(res->pw_shell)+1;
if (pw_name+pw_passwd+pw_class+pw_gecos
+pw_dir+pw_shell < buflen)
{
memcpy(pwd, res, sizeof(struct passwd));
strncpy(buffer, res->pw_name, pw_name);
pwd->pw_name = buffer;
buffer += pw_name;
strncpy(buffer, res->pw_passwd, pw_passwd);
pwd->pw_passwd = buffer;
buffer += pw_passwd;
strncpy(buffer, res->pw_class, pw_class);
pwd->pw_class = buffer;
buffer += pw_class;
strncpy(buffer, res->pw_gecos, pw_gecos);
pwd->pw_gecos = buffer;
buffer += pw_gecos;
strncpy(buffer, res->pw_dir, pw_dir);
pwd->pw_dir = buffer;
buffer += pw_dir;
strncpy(buffer, res->pw_shell, pw_shell);
pwd->pw_shell = buffer;
buffer += pw_shell;
*result = pwd ;
retval = 0 ;
}
else
retval = ENOMEM;
}
else
retval = errno ;
pthread_mutex_unlock(&getrtl_mutex);
return retval;
}
struct tm *localtime_r(const time_t *timep, struct tm *buffer)
{
struct tm* res;
pthread_mutex_lock(&getrtl_mutex);
if ( (res = localtime(timep)))
{
memcpy(buffer, res, sizeof(struct tm));
res = buffer;
}
pthread_mutex_unlock(&getrtl_mutex);
return res;
}
struct tm *gmtime_r(const time_t *timep, struct tm *buffer)
{
struct tm* res;
pthread_mutex_lock(&getrtl_mutex);
if ( (res = gmtime(timep)) )
{
memcpy(buffer, res, sizeof(struct tm));
res = buffer;
}
pthread_mutex_unlock(&getrtl_mutex);
return res;
}
#endif /* defined NETBSD */
#ifdef SCO
#include <pwd.h>
#include <shadow.h>
#include <sys/types.h>
struct spwd *getspnam_r(const char *name, struct spwd* s, char* buffer, int size )
{
struct spwd* res;
pthread_mutex_lock(&getrtl_mutex);
if ( res = getspnam(name) )
{
int nnamp;
nnamp = strlen(res->sp_namp)+1;
if (nnamp+strlen(res->sp_pwdp) < size) {
memcpy(s, res, sizeof(struct spwd));
strcpy(buffer, res->sp_namp);
s->sp_namp = buffer;
buffer += nnamp;
strcpy(buffer, res->sp_pwdp);
s->sp_pwdp = buffer;
res = s;
}
else
res = 0;
}
pthread_mutex_unlock(&getrtl_mutex);
return res;
}
struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
{
struct passwd* res;
pthread_mutex_lock(&getrtl_mutex);
if ( res = getpwnam(name) )
{
int nname, npasswd, nage;
int ncomment, ngecos, ndir;
nname= strlen(res->pw_name)+1;
npasswd= strlen(res->pw_passwd)+1;
nage= strlen(res->pw_age)+1;
ncomment= strlen(res->pw_comment)+1;
ngecos= strlen(res->pw_gecos)+1;
ndir= strlen(res->pw_dir)+1;
if (nname+npasswd+nage+ncomment+ngecos+ndir
+strlen(res->pw_shell) < size)
{
memcpy(s, res, sizeof(struct passwd));
strcpy(buffer, res->pw_name);
s->pw_name = buffer;
buffer += nname;
strcpy(buffer, res->pw_passwd);
s->pw_passwd = buffer;
buffer += npasswd;
strcpy(buffer, res->pw_age);
s->pw_age = buffer;
buffer += nage;
strcpy(buffer, res->pw_comment);
s->pw_comment = buffer;
buffer += ncomment;
strcpy(buffer, res->pw_gecos);
s->pw_gecos = buffer;
buffer += ngecos;
strcpy(buffer, res->pw_dir);
s->pw_dir = buffer;
buffer += ndir;
strcpy(buffer, res->pw_shell);
s->pw_shell = buffer;
res = s;
}
else
res = 0;
}
pthread_mutex_unlock(&getrtl_mutex);
return res;
}
#endif /* defined SCO */
#if !defined(FREEBSD) || (__FreeBSD_version < 601103)
extern int h_errno;
struct hostent *gethostbyname_r(const char *name, struct hostent *result,
char *buffer, int buflen, int *h_errnop)
{
/* buffer layout: name\0
* array_of_pointer_to_aliases
* NULL
* alias1\0...aliasn\0
* array_of_pointer_to_addresses
* NULL
* addr1addr2addr3...addrn
*/
struct hostent* res;
pthread_mutex_lock(&getrtl_mutex);
if ( (res = gethostbyname(name)) )
{
int nname, naliases, naddr_list, naliasesdata, n;
char **p, **parray, *data;
/* Check buffer size before copying, we want to leave the
* buffers unmodified in case something goes wrong.
*
* Is this required?
*/
nname= strlen(res->h_name)+1;
naliases = naddr_list = naliasesdata = 0;
for ( p = res->h_aliases; *p != NULL; p++) {
naliases++;
naliasesdata += strlen(*p)+1;
}
for ( p = res->h_addr_list; *p != NULL; p++)
naddr_list++;
if ( nname
+ (naliases+1)*sizeof(char*) + naliasesdata
+ (naddr_list+1)*sizeof(char*) + naddr_list*res->h_length
<= buflen )
{
memcpy(result, res, sizeof(struct hostent));
strcpy(buffer, res->h_name);
result->h_name = buffer;
buffer += nname;
parray = (char**)buffer;
result->h_aliases = parray;
data = buffer + (naliases+1)*sizeof(char*);
for ( p = res->h_aliases; *p != NULL; p++) {
n = strlen(*p)+1;
*parray++ = data;
memcpy(data, *p, n);
data += n;
}
*parray = NULL;
buffer = data;
parray = (char**)buffer;
result->h_addr_list = parray;
data = buffer + (naddr_list+1)*sizeof(char*);
for ( p = res->h_addr_list; *p != NULL; p++) {
*parray++ = data;
memcpy(data, *p, res->h_length);
data += res->h_length;
}
*parray = NULL;
res = result;
}
else
{
errno = ERANGE;
res = NULL;
}
}
else
{
*h_errnop = h_errno;
}
pthread_mutex_unlock(&getrtl_mutex);
return res;
}
#endif /* !defined(FREEBSD) || (__FreeBSD_version < 601103) */
#if defined(MACOSX)
/*
* Add support for resolving Mac native alias files (not the same as unix alias files)
* returns 0 on success.
*/
int macxp_resolveAlias(char *path, int buflen)
{
FSRef aFSRef;
OSStatus nErr;
Boolean bFolder;
Boolean bAliased;
char *unprocessedPath = path;
if ( *unprocessedPath == '/' )
unprocessedPath++;
int nRet = 0;
while ( !nRet && unprocessedPath && *unprocessedPath )
{
unprocessedPath = strchr( unprocessedPath, '/' );
if ( unprocessedPath )
*unprocessedPath = '\0';
nErr = noErr;
bFolder = FALSE;
bAliased = FALSE;
if ( FSPathMakeRef( (const UInt8 *)path, &aFSRef, 0 ) == noErr )
{
nErr = FSResolveAliasFileWithMountFlags( &aFSRef, TRUE, &bFolder, &bAliased, kResolveAliasFileNoUI );
if ( nErr == nsvErr )
{
errno = ENOENT;
nRet = -1;
}
else if ( nErr == noErr && bAliased )
{
char tmpPath[ PATH_MAX ];
if ( FSRefMakePath( &aFSRef, (UInt8 *)tmpPath, PATH_MAX ) == noErr )
{
int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 );
if ( nLen < buflen && nLen < PATH_MAX )
{
if ( unprocessedPath )
{
int nTmpPathLen = strlen( tmpPath );
strcat( tmpPath, "/" );
strcat( tmpPath, unprocessedPath + 1 );
strcpy( path, tmpPath);
unprocessedPath = path + nTmpPathLen;
}
else if ( !unprocessedPath )
{
strcpy( path, tmpPath);
}
}
else
{
errno = ENAMETOOLONG;
nRet = -1;
}
}
}
}
if ( unprocessedPath )
*unprocessedPath++ = '/';
}
return nRet;
}
#endif /* defined MACOSX */
#endif /* NO_PTHREAD_RTL */
#if (defined (LINUX) && (GLIBC >= 2))
/* The linux kernel thread implemention, always return the pid of the
thread subprocess and not of the main process. So we save the main
pid at startup
*/
// Directly from libc.so.6, obviously missing from some unistd.h:
extern __pid_t __getpid(void);
static pid_t pid = -1;
static void savePid(void) __attribute__((constructor));
static void savePid(void)
{
if (pid == -1)
pid = __getpid();
}
pid_t getpid(void)
{
if (pid == -1)
savePid();
return (pid);
}
#endif /* (defined (LINUX) && (GLIBC >= 2)) */
#ifdef NO_PTHREAD_SEMAPHORES
int sem_init(sem_t* sem, int pshared, unsigned int value)
{
pthread_mutex_init(&sem->mutex, PTHREAD_MUTEXATTR_DEFAULT);
pthread_cond_init(&sem->increased, PTHREAD_CONDATTR_DEFAULT);
sem->value = (int)value;
return 0;
}
int sem_destroy(sem_t* sem)
{
pthread_mutex_destroy(&sem->mutex);
pthread_cond_destroy(&sem->increased);
sem->value = 0;
return 0;
}
int sem_wait(sem_t* sem)
{
pthread_mutex_lock(&sem->mutex);
while (sem->value <= 0)
{
pthread_cond_wait(&sem->increased, &sem->mutex);
}
sem->value--;
pthread_mutex_unlock(&sem->mutex);
return 0;
}
int sem_trywait(sem_t* sem)
{
int result = 0;
pthread_mutex_lock(&sem->mutex);
if (sem->value > 0)
{
sem->value--;
}
else
{
errno = EAGAIN;
result = -1;
}
pthread_mutex_unlock(&sem->mutex);
return result;
}
int sem_post(sem_t* sem)
{
pthread_mutex_lock(&sem->mutex);
sem->value++;
pthread_mutex_unlock(&sem->mutex);
pthread_cond_signal(&sem->increased);
return 0;
}
#endif
#if defined(FREEBSD)
char *fcvt(double value, int ndigit, int *decpt, int *sign)
{
static char ret[256];
char buf[256],zahl[256],format[256]="%";
char *v1,*v2;
if (value==0.0) value=1e-30;
if (value<0.0) *sign=1; else *sign=0;
if (value<1.0)
{
*decpt=(int)log10(value);
value*=pow(10.0,1-*decpt);
ndigit+=*decpt-1;
if (ndigit<0) ndigit=0;
}
else
{
*decpt=(int)log10(value)+1;
}
sprintf(zahl,"%d",ndigit);
strcat(format,zahl);
strcat(format,".");
strcat(format,zahl);
strcat(format,"f");
sprintf(buf,format,value);
if (ndigit!=0)
{
v1=strtok(buf,".");
v2=strtok(NULL,".");
strcpy(ret,v1);
strcat(ret,v2);
}
else
{
strcpy(ret,buf);
}
return(ret);
}
#endif