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