xref: /aoo41x/main/sal/osl/unx/system.c (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "system.h"
29 
30 #ifdef NO_PTHREAD_RTL
31 
32 static pthread_mutex_t getrtl_mutex = PTHREAD_MUTEX_INITIALIZER;
33 
34 /* struct passwd differs on some platforms */
35 #if defined NETBSD
36 struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
37 {
38   	struct passwd* res;
39 
40   	pthread_mutex_lock(&getrtl_mutex);
41 
42   	if ( (res = getpwnam(name)) )
43   	{
44 		int nname, npasswd, nclass, ngecos, ndir;
45 
46 		nname= strlen(res->pw_name)+1;
47 		npasswd= strlen(res->pw_passwd)+1;
48 		nclass= strlen(res->pw_class)+1;
49 		ngecos= strlen(res->pw_gecos)+1;
50 		ndir= strlen(res->pw_dir)+1;
51 
52 		if (nname+npasswd+nclass+ngecos
53 				+ndir+strlen(res->pw_shell) < size)
54 		{
55     		memcpy(s, res, sizeof(struct passwd));
56 
57         	strcpy(buffer, res->pw_name);
58       		s->pw_name = buffer;
59 			buffer += nname;
60 
61         	strcpy(buffer, res->pw_passwd);
62       		s->pw_passwd = buffer;
63 			buffer += npasswd;
64 
65         	strcpy(buffer, res->pw_class);
66       		s->pw_class = buffer;
67 			buffer += nclass;
68 
69         	strcpy(buffer, res->pw_gecos);
70       		s->pw_gecos = buffer;
71 			buffer += ngecos;
72 
73         	strcpy(buffer, res->pw_dir);
74       		s->pw_dir = buffer;
75 			buffer += ndir;
76 
77         	strcpy(buffer, res->pw_shell);
78       		s->pw_shell = buffer;
79 
80    			res = s;
81 		}
82 		else
83 			res = 0;
84 	}
85 
86 	pthread_mutex_unlock(&getrtl_mutex);
87 
88         return(res);
89 }
90 
91 int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
92            size_t buflen, struct passwd **result)
93 {
94   struct passwd* res;
95   int retval = 0;
96 
97   pthread_mutex_lock(&getrtl_mutex);
98 
99   if ( (res = getpwuid(uid)) )
100   {
101     size_t pw_name, pw_passwd, pw_class, pw_gecos, pw_dir, pw_shell;
102 
103     pw_name = strlen(res->pw_name)+1;
104     pw_passwd = strlen(res->pw_passwd)+1;
105     pw_class = strlen(res->pw_class)+1;
106     pw_gecos = strlen(res->pw_gecos)+1;
107     pw_dir = strlen(res->pw_dir)+1;
108     pw_shell = strlen(res->pw_shell)+1;
109 
110     if (pw_name+pw_passwd+pw_class+pw_gecos
111                                  +pw_dir+pw_shell < buflen)
112     {
113       memcpy(pwd, res, sizeof(struct passwd));
114 
115       strncpy(buffer, res->pw_name, pw_name);
116       pwd->pw_name = buffer;
117       buffer += pw_name;
118 
119       strncpy(buffer, res->pw_passwd, pw_passwd);
120       pwd->pw_passwd = buffer;
121       buffer += pw_passwd;
122 
123       strncpy(buffer, res->pw_class, pw_class);
124       pwd->pw_class = buffer;
125       buffer += pw_class;
126 
127       strncpy(buffer, res->pw_gecos, pw_gecos);
128       pwd->pw_gecos = buffer;
129       buffer += pw_gecos;
130 
131       strncpy(buffer, res->pw_dir, pw_dir);
132       pwd->pw_dir = buffer;
133       buffer += pw_dir;
134 
135       strncpy(buffer, res->pw_shell, pw_shell);
136       pwd->pw_shell = buffer;
137       buffer += pw_shell;
138 
139       *result = pwd ;
140       retval = 0 ;
141 
142     }
143     else
144         retval =  ENOMEM;
145   }
146   else
147       retval = errno ;
148 
149   pthread_mutex_unlock(&getrtl_mutex);
150 
151   return retval;
152 }
153 
154 struct tm *localtime_r(const time_t *timep, struct tm *buffer)
155 {
156 	struct tm* res;
157 
158   	pthread_mutex_lock(&getrtl_mutex);
159 
160 	if ( (res = localtime(timep)))
161 	{
162 		memcpy(buffer, res, sizeof(struct tm));
163 		res = buffer;
164 	}
165 
166 	pthread_mutex_unlock(&getrtl_mutex);
167 
168 	return res;
169 }
170 
171 struct tm *gmtime_r(const time_t *timep, struct tm *buffer)
172 {
173 	struct tm* res;
174 
175   	pthread_mutex_lock(&getrtl_mutex);
176 
177 	if ( (res = gmtime(timep)) )
178 	{
179 		memcpy(buffer, res, sizeof(struct tm));
180 		res = buffer;
181 	}
182 
183 	pthread_mutex_unlock(&getrtl_mutex);
184 
185 	return res;
186 }
187 #endif  /* defined NETBSD */
188 
189 #ifdef SCO
190 #include <pwd.h>
191 #include <shadow.h>
192 #include <sys/types.h>
193 
194 struct spwd *getspnam_r(const char *name, struct spwd* s, char* buffer, int size )
195 {
196   	struct spwd* res;
197 
198   	pthread_mutex_lock(&getrtl_mutex);
199 
200   	if ( res = getspnam(name) )
201   	{
202 		int nnamp;
203 
204 		nnamp = strlen(res->sp_namp)+1;
205 
206 		if (nnamp+strlen(res->sp_pwdp) < size) {
207     		memcpy(s, res, sizeof(struct spwd));
208 
209         	strcpy(buffer, res->sp_namp);
210       		s->sp_namp = buffer;
211 			buffer += nnamp;
212 
213         	strcpy(buffer, res->sp_pwdp);
214       		s->sp_pwdp = buffer;
215 
216    			res = s;
217 		}
218 		else
219 			res = 0;
220 	}
221 
222   	pthread_mutex_unlock(&getrtl_mutex);
223 
224   	return res;
225 }
226 
227 struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
228 {
229   	struct passwd* res;
230 
231   	pthread_mutex_lock(&getrtl_mutex);
232 
233   	if ( res = getpwnam(name) )
234   	{
235 		int nname, npasswd, nage;
236 		int ncomment, ngecos, ndir;
237 
238 		nname= strlen(res->pw_name)+1;
239 		npasswd= strlen(res->pw_passwd)+1;
240 		nage= strlen(res->pw_age)+1;
241 		ncomment= strlen(res->pw_comment)+1;
242 		ngecos= strlen(res->pw_gecos)+1;
243 		ndir= strlen(res->pw_dir)+1;
244 
245 		if (nname+npasswd+nage+ncomment+ngecos+ndir
246 				+strlen(res->pw_shell) < size)
247 		{
248     		memcpy(s, res, sizeof(struct passwd));
249 
250         	strcpy(buffer, res->pw_name);
251       		s->pw_name = buffer;
252 			buffer += nname;
253 
254         	strcpy(buffer, res->pw_passwd);
255       		s->pw_passwd = buffer;
256 			buffer += npasswd;
257 
258         	strcpy(buffer, res->pw_age);
259       		s->pw_age = buffer;
260 			buffer += nage;
261 
262         	strcpy(buffer, res->pw_comment);
263       		s->pw_comment = buffer;
264 			buffer += ncomment;
265 
266         	strcpy(buffer, res->pw_gecos);
267       		s->pw_gecos = buffer;
268 			buffer += ngecos;
269 
270         	strcpy(buffer, res->pw_dir);
271       		s->pw_dir = buffer;
272 			buffer += ndir;
273 
274         	strcpy(buffer, res->pw_shell);
275       		s->pw_shell = buffer;
276 
277    			res = s;
278 		}
279 		else
280 			res = 0;
281 	}
282 
283 	pthread_mutex_unlock(&getrtl_mutex);
284 
285   	return res;
286 }
287 #endif /* defined SCO */
288 
289 #if !defined(FREEBSD) || (__FreeBSD_version < 601103)
290 
291 extern int h_errno;
292 
293 struct hostent *gethostbyname_r(const char *name, struct hostent *result,
294 								char *buffer, int buflen, int *h_errnop)
295 {
296 	/* buffer layout: 	name\0
297 	 *					array_of_pointer_to_aliases
298 	 *					NULL
299 	 *					alias1\0...aliasn\0
300 	 *                  array_of_pointer_to_addresses
301 	 * 					NULL
302 	 * 					addr1addr2addr3...addrn
303 	 */
304   	struct hostent* res;
305 
306   	pthread_mutex_lock(&getrtl_mutex);
307 
308   	if ( (res = gethostbyname(name)) )
309   	{
310 		int nname, naliases, naddr_list, naliasesdata, n;
311 		char **p, **parray, *data;
312 
313 		/* Check buffer size before copying, we want to leave the
314 		 * buffers unmodified in case something goes wrong.
315 		 *
316 		 * Is this required?
317 		 */
318 
319 		nname= strlen(res->h_name)+1;
320 
321 		naliases = naddr_list = naliasesdata = 0;
322 
323 		for ( p = res->h_aliases; *p != NULL; p++) {
324 			naliases++;
325 			naliasesdata += strlen(*p)+1;
326 		}
327 
328 		for ( p = res->h_addr_list; *p != NULL; p++)
329 			naddr_list++;
330 
331 		if ( nname
332 			 + (naliases+1)*sizeof(char*) + naliasesdata
333 			 + (naddr_list+1)*sizeof(char*) + naddr_list*res->h_length
334 			 <= buflen )
335 		{
336     		memcpy(result, res, sizeof(struct hostent));
337 
338         	strcpy(buffer, res->h_name);
339       		result->h_name = buffer;
340 			buffer += nname;
341 
342 			parray = (char**)buffer;
343 			result->h_aliases = parray;
344 			data = buffer + (naliases+1)*sizeof(char*);
345 			for ( p = res->h_aliases; *p != NULL; p++) {
346 				n = strlen(*p)+1;
347 				*parray++ = data;
348 				memcpy(data, *p, n);
349 				data += n;
350 			}
351 			*parray = NULL;
352 			buffer = data;
353 			parray = (char**)buffer;
354 			result->h_addr_list = parray;
355 			data = buffer + (naddr_list+1)*sizeof(char*);
356 			for ( p = res->h_addr_list; *p != NULL; p++) {
357 				*parray++ = data;
358 				memcpy(data, *p, res->h_length);
359 				data += res->h_length;
360 			}
361 			*parray = NULL;
362 
363    			res = result;
364 		}
365 		else
366 		{
367 			errno = ERANGE;
368 			res = NULL;
369 		}
370 	}
371 	else
372 	{
373 		*h_errnop = h_errno;
374 	}
375 
376 	pthread_mutex_unlock(&getrtl_mutex);
377 
378   	return res;
379 }
380 #endif /* !defined(FREEBSD) || (__FreeBSD_version < 601103) */
381 
382 #if defined(MACOSX)
383 /*
384  * Add support for resolving Mac native alias files (not the same as unix alias files)
385  * returns 0 on success.
386  */
387 int macxp_resolveAlias(char *path, int buflen)
388 {
389   FSRef aFSRef;
390   OSStatus nErr;
391   Boolean bFolder;
392   Boolean bAliased;
393   char *unprocessedPath = path;
394 
395   if ( *unprocessedPath == '/' )
396     unprocessedPath++;
397 
398   int nRet = 0;
399   while ( !nRet && unprocessedPath && *unprocessedPath )
400     {
401       unprocessedPath = strchr( unprocessedPath, '/' );
402       if ( unprocessedPath )
403 	*unprocessedPath = '\0';
404 
405       nErr = noErr;
406       bFolder = FALSE;
407       bAliased = FALSE;
408       if ( FSPathMakeRef( (const UInt8 *)path, &aFSRef, 0 ) == noErr )
409 	{
410 	  nErr = FSResolveAliasFileWithMountFlags( &aFSRef, TRUE, &bFolder, &bAliased, kResolveAliasFileNoUI );
411 	  if ( nErr == nsvErr )
412 	    {
413 	      errno = ENOENT;
414 	      nRet = -1;
415 	    }
416 	  else if ( nErr == noErr && bAliased )
417 	    {
418 	      char tmpPath[ PATH_MAX ];
419 	      if ( FSRefMakePath( &aFSRef, (UInt8 *)tmpPath, PATH_MAX ) == noErr )
420 		{
421 		  int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 );
422 		  if ( nLen < buflen && nLen < PATH_MAX )
423 		    {
424 		      if ( unprocessedPath )
425 			{
426 			  int nTmpPathLen = strlen( tmpPath );
427 			  strcat( tmpPath, "/" );
428 			  strcat( tmpPath, unprocessedPath + 1 );
429 			  strcpy( path, tmpPath);
430 			  unprocessedPath = path + nTmpPathLen;
431 			}
432 		      else if ( !unprocessedPath )
433 			{
434 			  strcpy( path, tmpPath);
435 			}
436 		    }
437 		  else
438 		    {
439 		      errno = ENAMETOOLONG;
440 		      nRet = -1;
441 		    }
442 		}
443 	    }
444 	}
445 
446       if ( unprocessedPath )
447 	*unprocessedPath++ = '/';
448     }
449 
450   return nRet;
451 }
452 
453 #endif  /* defined MACOSX */
454 
455 #endif /* NO_PTHREAD_RTL */
456 
457 #if (defined (LINUX) && (GLIBC >= 2))
458 /* The linux kernel thread implemention, always return the pid of the
459    thread subprocess and not of the main process. So we save the main
460    pid at startup
461 */
462 
463 // Directly from libc.so.6, obviously missing from some unistd.h:
464 extern __pid_t __getpid(void);
465 
466 static pid_t pid = -1;
467 
468 static void savePid(void) __attribute__((constructor));
469 
470 static void savePid(void)
471 {
472 	if (pid == -1)
473 		pid = __getpid();
474 }
475 
476 pid_t getpid(void)
477 {
478 	if (pid == -1)
479 		savePid();
480 
481 	return (pid);
482 }
483 #endif /*  (defined (LINUX) && (GLIBC >= 2)) */
484 
485 #ifdef NO_PTHREAD_SEMAPHORES
486 int sem_init(sem_t* sem, int pshared, unsigned int value)
487 {
488 	pthread_mutex_init(&sem->mutex, PTHREAD_MUTEXATTR_DEFAULT);
489 	pthread_cond_init(&sem->increased, PTHREAD_CONDATTR_DEFAULT);
490 
491 	sem->value = (int)value;
492 	return 0;
493 }
494 
495 int sem_destroy(sem_t* sem)
496 {
497 	pthread_mutex_destroy(&sem->mutex);
498 	pthread_cond_destroy(&sem->increased);
499 	sem->value = 0;
500 	return 0;
501 }
502 
503 int sem_wait(sem_t* sem)
504 {
505 	pthread_mutex_lock(&sem->mutex);
506 
507 	while (sem->value <= 0)
508 	{
509 		pthread_cond_wait(&sem->increased, &sem->mutex);
510 	}
511 
512 	sem->value--;
513 	pthread_mutex_unlock(&sem->mutex);
514 
515 	return 0;
516 }
517 
518 int sem_trywait(sem_t* sem)
519 {
520 	int result = 0;
521 
522 	pthread_mutex_lock(&sem->mutex);
523 
524 	if (sem->value > 0)
525 	{
526 		sem->value--;
527 	}
528 	else
529 	{
530 		errno = EAGAIN;
531 		result = -1;
532 	}
533 
534 	pthread_mutex_unlock(&sem->mutex);
535 
536 	return result;
537 }
538 
539 int sem_post(sem_t* sem)
540 {
541 	pthread_mutex_lock(&sem->mutex);
542 
543 	sem->value++;
544 
545 	pthread_mutex_unlock(&sem->mutex);
546 
547 	pthread_cond_signal(&sem->increased);
548 
549 	return 0;
550 }
551 #endif
552 
553 #if defined(FREEBSD)
554 char *fcvt(double value, int ndigit, int *decpt, int *sign)
555 {
556   static char ret[256];
557   char buf[256],zahl[256],format[256]="%";
558   char *v1,*v2;
559 
560   if (value==0.0) value=1e-30;
561 
562   if (value<0.0) *sign=1; else *sign=0;
563 
564   if (value<1.0)
565   {
566     *decpt=(int)log10(value);
567 	value*=pow(10.0,1-*decpt);
568 	ndigit+=*decpt-1;
569 	if (ndigit<0) ndigit=0;
570   }
571   else
572   {
573     *decpt=(int)log10(value)+1;
574   }
575 
576   sprintf(zahl,"%d",ndigit);
577   strcat(format,zahl);
578   strcat(format,".");
579   strcat(format,zahl);
580   strcat(format,"f");
581 
582   sprintf(buf,format,value);
583 
584   if (ndigit!=0)
585   {
586     v1=strtok(buf,".");
587     v2=strtok(NULL,".");
588 	strcpy(ret,v1);
589     strcat(ret,v2);
590   }
591   else
592   {
593     strcpy(ret,buf);
594   }
595 
596   return(ret);
597 }
598 
599 #endif
600