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