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