xref: /trunk/main/sal/osl/unx/system.c (revision 78190a370f7d7129fed9a7e70ca122eaae71ce1d)
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
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 
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 
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 
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 
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 
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 
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  */
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 
467 static void savePid(void)
468 {
469     if (pid == -1)
470         pid = __getpid();
471 }
472 
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
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 
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 
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 
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 
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)
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