diff options
Diffstat (limited to 'sal/osl/unx/system.c')
-rw-r--r-- | sal/osl/unx/system.c | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/sal/osl/unx/system.c b/sal/osl/unx/system.c new file mode 100644 index 000000000..867b44220 --- /dev/null +++ b/sal/osl/unx/system.c @@ -0,0 +1,454 @@ +/************************************************************************* + * + * $RCSfile: system.c,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:17:21 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#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 || defined MACOSX +#include <pwd.h> +#include <sys/types.h> + + +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; +} + +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 + +#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 + +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, ncntaddr_list, 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; + + result->h_aliases = buffer; + parray = (char**)buffer; + 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; + + result->h_addr_list = buffer; + parray = (char**)buffer; + 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 /* 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 +*/ +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 + +#ifdef PTHREAD_NONE_INIT +pthread_t _pthread_none_ = PTHREAD_NONE_INIT; +#endif + +#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 + |