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