xref: /AOO41X/main/sal/osl/unx/system.c (revision 647f063d49501903f1667b75f5634541fc603283)
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 = 0;
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 = 0;
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 = 0;
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