diff options
Diffstat (limited to 'sal/osl/unx/system.c')
-rw-r--r-- | sal/osl/unx/system.c | 599 |
1 files changed, 599 insertions, 0 deletions
diff --git a/sal/osl/unx/system.c b/sal/osl/unx/system.c new file mode 100644 index 000000000000..0ea3b819438c --- /dev/null +++ b/sal/osl/unx/system.c @@ -0,0 +1,599 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 |