1/*
2Copyright 1996, 1998  The Open Group
3
4Permission to use, copy, modify, distribute, and sell this software and its
5documentation for any purpose is hereby granted without fee, provided that
6the above copyright notice appear in all copies and that both that
7copyright notice and this permission notice appear in supporting
8documentation.
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
16OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of The Open Group shall not be
21used in advertising or otherwise to promote the sale, use or other dealings
22in this Software without prior written authorization from The Open Group.
23*/
24
25/*
26 * Various and sundry Thread-Safe functions used by X11, Motif, and CDE.
27 *
28 * Use this file in MT-safe code where you would have included
29 *	<dirent.h>	for readdir()
30 *	<grp.h>		for getgrgid() or getgrnam()
31 *	<netdb.h>	for gethostbyname(), gethostbyaddr(), or getservbyname()
32 *	<pwd.h>		for getpwnam() or getpwuid()
33 *	<string.h>	for strtok()
34 *	<time.h>	for asctime(), ctime(), localtime(), or gmtime()
35 *	<unistd.h>	for getlogin() or ttyname()
36 * or their thread-safe analogs.
37 *
38 * If you are on a platform that defines XTHREADS but does not have
39 * MT-safe system API (e.g. UnixWare) you must define _Xos_processLock
40 * and _Xos_processUnlock macros before including this header.
41 *
42 * For convenience XOS_USE_XLIB_LOCKING or XOS_USE_XT_LOCKING may be defined
43 * to obtain either Xlib-only or Xt-based versions of these macros.  These
44 * macros won't result in truly thread-safe calls, but they are better than
45 * nothing.  If you do not want locking in this situation define
46 * XOS_USE_NO_LOCKING.
47 *
48 * NOTE: On systems lacking appropriate _r functions Gethostbyname(),
49 *	Gethostbyaddr(), and Getservbyname() do NOT copy the host or
50 *	protocol lists!
51 *
52 * NOTE: On systems lacking appropriate _r functions Getgrgid() and
53 *	Getgrnam() do NOT copy the list of group members!
54 *
55 * This header is nominally intended to simplify porting X11, Motif, and
56 * CDE; it may be useful to other people too.  The structure below is
57 * complicated, mostly because P1003.1c (the IEEE POSIX Threads spec)
58 * went through lots of drafts, and some vendors shipped systems based
59 * on draft API that were changed later.  Unfortunately POSIX did not
60 * provide a feature-test macro for distinguishing each of the drafts.
61 */
62
63/*
64 * This header has several parts.  Search for "Effective prototypes"
65 * to locate the beginning of a section.
66 */
67
68/* This header can be included multiple times with different defines! */
69#ifndef _XOS_R_H_
70# define _XOS_R_H_
71
72# include <X11/Xos.h>
73# include <X11/Xfuncs.h>
74
75# ifndef X_NOT_POSIX
76#  ifdef _POSIX_SOURCE
77#   include <limits.h>
78#  else
79#   define _POSIX_SOURCE
80#   include <limits.h>
81#   undef _POSIX_SOURCE
82#  endif
83#  ifndef LINE_MAX
84#   define X_LINE_MAX 2048
85#  else
86#   define X_LINE_MAX LINE_MAX
87#  endif
88# endif
89#endif /* _XOS_R_H */
90
91#ifndef WIN32
92
93#ifdef __cplusplus
94extern "C" {
95#endif
96
97# if defined(XOS_USE_XLIB_LOCKING)
98#  ifndef XAllocIDs /* Xlibint.h does not have multiple include protection */
99typedef struct _LockInfoRec *LockInfoPtr;
100extern LockInfoPtr _Xglobal_lock;
101#  endif
102#  ifndef _Xos_isThreadInitialized
103#   define _Xos_isThreadInitialized	(_Xglobal_lock)
104#  endif
105#  if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
106#   ifndef XAllocIDs /* Xlibint.h does not have multiple include protection */
107#    include <X11/Xfuncproto.h>	/* for NeedFunctionPrototypes */
108extern void (*_XLockMutex_fn)(
109#    if NeedFunctionPrototypes
110    LockInfoPtr	/* lock */, char * /* file */, int /* line */
111#    endif
112);
113extern void (*_XUnlockMutex_fn)(
114#    if NeedFunctionPrototypes
115    LockInfoPtr	/* lock */, char * /* file */, int /* line */
116#    endif
117);
118#   endif
119#   ifndef _Xos_processLock
120#    define _Xos_processLock	\
121  (_XLockMutex_fn ? (*_XLockMutex_fn)(_Xglobal_lock,__FILE__,__LINE__) : 0)
122#   endif
123#   ifndef _Xos_processUnlock
124#    define _Xos_processUnlock	\
125  (_XUnlockMutex_fn ? (*_XUnlockMutex_fn)(_Xglobal_lock,__FILE__,__LINE__) : 0)
126#   endif
127#  else
128#   ifndef XAllocIDs /* Xlibint.h does not have multiple include protection */
129#    include <X11/Xfuncproto.h>	/* for NeedFunctionPrototypes */
130extern void (*_XLockMutex_fn)(
131#    if NeedFunctionPrototypes
132    LockInfoPtr	/* lock */
133#    endif
134);
135extern void (*_XUnlockMutex_fn)(
136#    if NeedFunctionPrototypes
137    LockInfoPtr	/* lock */
138#    endif
139);
140#   endif
141#   ifndef _Xos_processLock
142#    define _Xos_processLock	\
143  (_XLockMutex_fn ? ((*_XLockMutex_fn)(_Xglobal_lock), 0) : 0)
144#   endif
145#   ifndef _Xos_processUnlock
146#    define _Xos_processUnlock	\
147  (_XUnlockMutex_fn ? ((*_XUnlockMutex_fn)(_Xglobal_lock), 0) : 0)
148#   endif
149#  endif
150# elif defined(XOS_USE_XT_LOCKING)
151#  ifndef _XtThreadsI_h
152extern void (*_XtProcessLock)(void);
153#  endif
154#  ifndef _XtintrinsicP_h
155#   include <X11/Xfuncproto.h>	/* for NeedFunctionPrototypes */
156extern void XtProcessLock(
157#   if NeedFunctionPrototypes
158    void
159#   endif
160);
161extern void XtProcessUnlock(
162#   if NeedFunctionPrototypes
163    void
164#   endif
165);
166#  endif
167#  ifndef _Xos_isThreadInitialized
168#   define _Xos_isThreadInitialized	_XtProcessLock
169#  endif
170#  ifndef _Xos_processLock
171#   define _Xos_processLock		XtProcessLock()
172#  endif
173#  ifndef _Xos_processUnlock
174#   define _Xos_processUnlock		XtProcessUnlock()
175#  endif
176# elif defined(XOS_USE_NO_LOCKING)
177#  ifndef _Xos_isThreadInitialized
178#   define _Xos_isThreadInitialized	0
179#  endif
180#  ifndef _Xos_processLock
181#   define _Xos_processLock		0
182#  endif
183#  ifndef _Xos_processUnlock
184#   define _Xos_processUnlock		0
185#  endif
186# endif
187
188#endif /* !defined WIN32 */
189
190/*
191 * Solaris defines the POSIX thread-safe feature test macro, but
192 * uses the older SVR4 thread-safe functions unless the POSIX ones
193 * are specifically requested.  Fix the feature test macro.
194 */
195#if defined(__sun) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \
196	(_POSIX_C_SOURCE - 0 < 199506L) && !defined(_POSIX_PTHREAD_SEMANTICS)
197# undef _POSIX_THREAD_SAFE_FUNCTIONS
198#endif
199
200/***** <pwd.h> wrappers *****/
201
202/*
203 * Effective prototypes for <pwd.h> wrappers:
204 *
205 * #define X_INCLUDE_PWD_H
206 * #define XOS_USE_..._LOCKING
207 * #include <X11/Xos_r.h>
208 *
209 * typedef ... _Xgetpwparams;
210 *
211 * struct passwd* _XGetpwnam(const char *name, _Xgetpwparams);
212 * struct passwd* _XGetpwuid(uid_t uid, _Xgetpwparams);
213 */
214
215#if defined(X_INCLUDE_PWD_H) && !defined(_XOS_INCLUDED_PWD_H)
216# include <pwd.h>
217# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_PWDAPI)
218#  define XOS_USE_MTSAFE_PWDAPI 1
219# endif
220#endif
221
222#undef X_NEEDS_PWPARAMS
223#if !defined(X_INCLUDE_PWD_H) || defined(_XOS_INCLUDED_PWD_H)
224/* Do nothing */
225
226#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
227/* Use regular, unsafe API. */
228# if defined(X_NOT_POSIX) && !defined(__i386__) && !defined(SYSV)
229extern struct passwd *getpwuid(), *getpwnam();
230# endif
231typedef int _Xgetpwparams;	/* dummy */
232# define _XGetpwuid(u,p)	getpwuid((u))
233# define _XGetpwnam(u,p)	getpwnam((u))
234
235#elif !defined(XOS_USE_MTSAFE_PWDAPI) || defined(XNO_MTSAFE_PWDAPI)
236/* UnixWare 2.0, or other systems with thread support but no _r API. */
237# define X_NEEDS_PWPARAMS
238typedef struct {
239  struct passwd pws;
240  char   pwbuf[1024];
241  struct passwd* pwp;
242  size_t len;
243} _Xgetpwparams;
244
245/*
246 * NetBSD and FreeBSD, at least, are missing several of the unixware passwd
247 * fields.
248 */
249
250#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
251    defined(__APPLE__) || defined(__DragonFly__)
252static __inline__ void _Xpw_copyPasswd(_Xgetpwparams p)
253{
254   memcpy(&(p).pws, (p).pwp, sizeof(struct passwd));
255
256   (p).pws.pw_name = (p).pwbuf;
257   (p).len = strlen((p).pwp->pw_name);
258   strcpy((p).pws.pw_name, (p).pwp->pw_name);
259
260   (p).pws.pw_passwd = (p).pws.pw_name + (p).len + 1;
261   (p).len = strlen((p).pwp->pw_passwd);
262   strcpy((p).pws.pw_passwd,(p).pwp->pw_passwd);
263
264   (p).pws.pw_class = (p).pws.pw_passwd + (p).len + 1;
265   (p).len = strlen((p).pwp->pw_class);
266   strcpy((p).pws.pw_class, (p).pwp->pw_class);
267
268   (p).pws.pw_gecos = (p).pws.pw_class + (p).len + 1;
269   (p).len = strlen((p).pwp->pw_gecos);
270   strcpy((p).pws.pw_gecos, (p).pwp->pw_gecos);
271
272   (p).pws.pw_dir = (p).pws.pw_gecos + (p).len + 1;
273   (p).len = strlen((p).pwp->pw_dir);
274   strcpy((p).pws.pw_dir, (p).pwp->pw_dir);
275
276   (p).pws.pw_shell = (p).pws.pw_dir + (p).len + 1;
277   (p).len = strlen((p).pwp->pw_shell);
278   strcpy((p).pws.pw_shell, (p).pwp->pw_shell);
279
280   (p).pwp = &(p).pws;
281}
282
283#else
284# define _Xpw_copyPasswd(p) \
285   (memcpy(&(p).pws, (p).pwp, sizeof(struct passwd)), \
286    ((p).pws.pw_name = (p).pwbuf), \
287    ((p).len = strlen((p).pwp->pw_name)), \
288    strcpy((p).pws.pw_name, (p).pwp->pw_name), \
289    ((p).pws.pw_passwd = (p).pws.pw_name + (p).len + 1), \
290    ((p).len = strlen((p).pwp->pw_passwd)), \
291    strcpy((p).pws.pw_passwd,(p).pwp->pw_passwd), \
292    ((p).pws.pw_age = (p).pws.pw_passwd + (p).len + 1), \
293    ((p).len = strlen((p).pwp->pw_age)), \
294    strcpy((p).pws.pw_age, (p).pwp->pw_age), \
295    ((p).pws.pw_comment = (p).pws.pw_age + (p).len + 1), \
296    ((p).len = strlen((p).pwp->pw_comment)), \
297    strcpy((p).pws.pw_comment, (p).pwp->pw_comment), \
298    ((p).pws.pw_gecos = (p).pws.pw_comment + (p).len + 1), \
299    ((p).len = strlen((p).pwp->pw_gecos)), \
300    strcpy((p).pws.pw_gecos, (p).pwp->pw_gecos), \
301    ((p).pws.pw_dir = (p).pws.pw_comment + (p).len + 1), \
302    ((p).len = strlen((p).pwp->pw_dir)), \
303    strcpy((p).pws.pw_dir, (p).pwp->pw_dir), \
304    ((p).pws.pw_shell = (p).pws.pw_dir + (p).len + 1), \
305    ((p).len = strlen((p).pwp->pw_shell)), \
306    strcpy((p).pws.pw_shell, (p).pwp->pw_shell), \
307    ((p).pwp = &(p).pws), \
308    0 )
309#endif
310# define _XGetpwuid(u,p) \
311( (_Xos_processLock), \
312  (((p).pwp = getpwuid((u))) ? _Xpw_copyPasswd(p), 0 : 0), \
313  (_Xos_processUnlock), \
314  (p).pwp )
315# define _XGetpwnam(u,p) \
316( (_Xos_processLock), \
317  (((p).pwp = getpwnam((u))) ? _Xpw_copyPasswd(p), 0 : 0), \
318  (_Xos_processUnlock), \
319  (p).pwp )
320
321#elif !defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(__APPLE__)
322# define X_NEEDS_PWPARAMS
323typedef struct {
324  struct passwd pws;
325  char pwbuf[X_LINE_MAX];
326} _Xgetpwparams;
327# if defined(_POSIX_REENTRANT_FUNCTIONS) || !defined(SVR4)
328#   define _XGetpwuid(u,p) \
329((getpwuid_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf)) == -1) ? NULL : &(p).pws)
330#   define _XGetpwnam(u,p) \
331((getpwnam_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf)) == -1) ? NULL : &(p).pws)
332# else /* SVR4 */
333#  define _XGetpwuid(u,p) \
334((getpwuid_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf)) == NULL) ? NULL : &(p).pws)
335#  define _XGetpwnam(u,p) \
336((getpwnam_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf)) == NULL) ? NULL : &(p).pws)
337# endif /* SVR4 */
338
339#else /* _POSIX_THREAD_SAFE_FUNCTIONS */
340# define X_NEEDS_PWPARAMS
341typedef struct {
342  struct passwd pws;
343  char pwbuf[X_LINE_MAX];
344  struct passwd* pwp;
345} _Xgetpwparams;
346typedef int _Xgetpwret;
347# define _XGetpwuid(u,p) \
348((getpwuid_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf),&(p).pwp) == 0) ? \
349 (p).pwp : NULL)
350# define _XGetpwnam(u,p) \
351((getpwnam_r((u),&(p).pws,(p).pwbuf,sizeof((p).pwbuf),&(p).pwp) == 0) ? \
352 (p).pwp : NULL)
353#endif /* X_INCLUDE_PWD_H */
354
355#if defined(X_INCLUDE_PWD_H) && !defined(_XOS_INCLUDED_PWD_H)
356# define _XOS_INCLUDED_PWD_H
357#endif
358
359
360/***** <netdb.h> wrappers *****/
361
362/*
363 * Effective prototypes for <netdb.h> wrappers:
364 *
365 * NOTE: On systems lacking the appropriate _r functions Gethostbyname(),
366 *	Gethostbyaddr(), and Getservbyname() do NOT copy the host or
367 *	protocol lists!
368 *
369 * #define X_INCLUDE_NETDB_H
370 * #define XOS_USE_..._LOCKING
371 * #include <X11/Xos_r.h>
372 *
373 * typedef ... _Xgethostbynameparams;
374 * typedef ... _Xgetservbynameparams;
375 *
376 * struct hostent* _XGethostbyname(const char* name,_Xgethostbynameparams);
377 * struct hostent* _XGethostbyaddr(const char* addr, int len, int type,
378 *				   _Xgethostbynameparams);
379 * struct servent* _XGetservbyname(const char* name, const char* proto,
380 *				 _Xgetservbynameparams);
381 */
382
383#undef XTHREADS_NEEDS_BYNAMEPARAMS
384#if defined(X_INCLUDE_NETDB_H) && !defined(_XOS_INCLUDED_NETDB_H) \
385    && !defined(WIN32)
386# include <netdb.h>
387# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_NETDBAPI)
388#  define XOS_USE_MTSAFE_NETDBAPI 1
389# endif
390#endif
391
392#if !defined(X_INCLUDE_NETDB_H) || defined(_XOS_INCLUDED_NETDB_H)
393/* Do nothing. */
394
395#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
396/* Use regular, unsafe API. */
397typedef int _Xgethostbynameparams; /* dummy */
398typedef int _Xgetservbynameparams; /* dummy */
399# define _XGethostbyname(h,hp)		gethostbyname((h))
400# define _XGethostbyaddr(a,al,t,hp)	gethostbyaddr((a),(al),(t))
401# define _XGetservbyname(s,p,sp)	getservbyname((s),(p))
402
403#elif !defined(XOS_USE_MTSAFE_NETDBAPI) || defined(XNO_MTSAFE_NETDBAPI)
404/* WARNING:  The h_addr_list and s_aliases values are *not* copied! */
405
406#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
407#include <sys/param.h>
408#endif
409
410typedef struct {
411  struct hostent hent;
412  char           h_name[MAXHOSTNAMELEN];
413  struct hostent *hptr;
414} _Xgethostbynameparams;
415typedef struct {
416  struct servent sent;
417  char           s_name[255];
418  char		 s_proto[255];
419  struct servent *sptr;
420} _Xgetservbynameparams;
421
422# define XTHREADS_NEEDS_BYNAMEPARAMS
423
424# define _Xg_copyHostent(hp) \
425   (memcpy(&(hp).hent, (hp).hptr, sizeof(struct hostent)), \
426    strcpy((hp).h_name, (hp).hptr->h_name), \
427    ((hp).hent.h_name = (hp).h_name), \
428    ((hp).hptr = &(hp).hent), \
429     0 )
430# define _Xg_copyServent(sp) \
431   (memcpy(&(sp).sent, (sp).sptr, sizeof(struct servent)), \
432    strcpy((sp).s_name, (sp).sptr->s_name), \
433    ((sp).sent.s_name = (sp).s_name), \
434    strcpy((sp).s_proto, (sp).sptr->s_proto), \
435    ((sp).sent.s_proto = (sp).s_proto), \
436    ((sp).sptr = &(sp).sent), \
437    0 )
438# define _XGethostbyname(h,hp) \
439   ((_Xos_processLock), \
440    (((hp).hptr = gethostbyname((h))) ? _Xg_copyHostent(hp) : 0), \
441    (_Xos_processUnlock), \
442    (hp).hptr )
443# define _XGethostbyaddr(a,al,t,hp) \
444   ((_Xos_processLock), \
445    (((hp).hptr = gethostbyaddr((a),(al),(t))) ? _Xg_copyHostent(hp) : 0), \
446    (_Xos_processUnlock), \
447    (hp).hptr )
448# define _XGetservbyname(s,p,sp) \
449   ((_Xos_processLock), \
450    (((sp).sptr = getservbyname((s),(p))) ? _Xg_copyServent(sp) : 0), \
451    (_Xos_processUnlock), \
452    (sp).sptr )
453
454#elif defined(XUSE_NETDB_R_API)
455/*
456 * POSIX does not specify _r equivalents for <netdb.h> API, but some
457 * vendors provide them anyway.  Use them only when explicitly asked.
458 */
459# ifdef _POSIX_REENTRANT_FUNCTIONS
460#  ifndef _POSIX_THREAD_SAFE_FUNCTIONS
461#  endif
462# endif
463# ifdef _POSIX_THREAD_SAFE_FUNCTIONS
464#  define X_POSIX_THREAD_SAFE_FUNCTIONS 1
465# endif
466
467# define XTHREADS_NEEDS_BYNAMEPARAMS
468
469# ifndef X_POSIX_THREAD_SAFE_FUNCTIONS
470typedef struct {
471    struct hostent      hent;
472    char                hbuf[X_LINE_MAX];
473    int                 herr;
474} _Xgethostbynameparams;
475typedef struct {
476    struct servent      sent;
477    char                sbuf[X_LINE_MAX];
478} _Xgetservbynameparams;
479#  define _XGethostbyname(h,hp) \
480  gethostbyname_r((h),&(hp).hent,(hp).hbuf,sizeof((hp).hbuf),&(hp).herr)
481#  define _XGethostbyaddr(a,al,t,hp) \
482  gethostbyaddr_r((a),(al),(t),&(hp).hent,(hp).hbuf,sizeof((hp).hbuf),&(hp).herr)
483#  define _XGetservbyname(s,p,sp) \
484  getservbyname_r((s),(p),&(sp).sent,(sp).sbuf,sizeof((sp).sbuf))
485# else
486typedef struct {
487  struct hostent      hent;
488  struct hostent_data hdata;
489} _Xgethostbynameparams;
490typedef struct {
491  struct servent      sent;
492  struct servent_data sdata;
493} _Xgetservbynameparams;
494#  define _XGethostbyname(h,hp) \
495  (bzero((char*)&(hp).hdata,sizeof((hp).hdata)),	\
496   ((gethostbyname_r((h),&(hp).hent,&(hp).hdata) == -1) ? NULL : &(hp).hent))
497#  define _XGethostbyaddr(a,al,t,hp) \
498  (bzero((char*)&(hp).hdata,sizeof((hp).hdata)),	\
499   ((gethostbyaddr_r((a),(al),(t),&(hp).hent,&(hp).hdata) == -1) ? NULL : &(hp).hent))
500#  define _XGetservbyname(s,p,sp) \
501  (bzero((char*)&(sp).sdata,sizeof((sp).sdata)),	\
502   ((getservbyname_r((s),(p),&(sp).sent,&(sp).sdata) == -1) ? NULL : &(sp).sent) )
503# endif
504# ifdef X_POSIX_THREAD_SAFE_FUNCTIONS
505#  undef X_POSIX_THREAD_SAFE_FUNCTIONS
506# endif
507
508#else
509/* The regular API is assumed to be MT-safe under POSIX. */
510typedef int _Xgethostbynameparams; /* dummy */
511typedef int _Xgetservbynameparams; /* dummy */
512# define _XGethostbyname(h,hp)		gethostbyname((h))
513# define _XGethostbyaddr(a,al,t,hp)	gethostbyaddr((a),(al),(t))
514# define _XGetservbyname(s,p,sp)	getservbyname((s),(p))
515#endif /* X_INCLUDE_NETDB_H */
516
517#if defined(X_INCLUDE_NETDB_H) && !defined(_XOS_INCLUDED_NETDB_H)
518# define _XOS_INCLUDED_NETDB_H
519#endif
520
521
522/***** <dirent.h> wrappers *****/
523
524/*
525 * Effective prototypes for <dirent.h> wrappers:
526 *
527 * #define X_INCLUDE_DIRENT_H
528 * #define XOS_USE_..._LOCKING
529 * #include <X11/Xos_r.h>
530 *
531 * typedef ... _Xreaddirparams;
532 *
533 * struct dirent *_XReaddir(DIR *dir_pointer, _Xreaddirparams);
534 */
535
536#if defined(X_INCLUDE_DIRENT_H) && !defined(_XOS_INCLUDED_DIRENT_H)
537# include <sys/types.h>
538# if !defined(X_NOT_POSIX) || defined(SYSV)
539#  include <dirent.h>
540# else
541#  include <sys/dir.h>
542#  ifndef dirent
543#   define dirent direct
544#  endif
545# endif
546# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_DIRENTAPI)
547#  define XOS_USE_MTSAFE_DIRENTAPI 1
548# endif
549#endif
550
551#if !defined(X_INCLUDE_DIRENT_H) || defined(_XOS_INCLUDED_DIRENT_H)
552/* Do nothing. */
553
554#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
555/* Use regular, unsafe API. */
556typedef int _Xreaddirparams;	/* dummy */
557# define _XReaddir(d,p)	readdir(d)
558
559#elif !defined(XOS_USE_MTSAFE_DIRENTAPI) || defined(XNO_MTSAFE_DIRENTAPI)
560/* Systems with thread support but no _r API. */
561typedef struct {
562  struct dirent *result;
563  struct dirent dir_entry;
564# ifdef _POSIX_PATH_MAX
565  char buf[_POSIX_PATH_MAX];
566# elif defined(NAME_MAX)
567  char buf[NAME_MAX];
568# else
569  char buf[255];
570# endif
571} _Xreaddirparams;
572
573# define _XReaddir(d,p)	\
574 ( (_Xos_processLock),						 \
575   (((p).result = readdir((d))) ?				 \
576    (memcpy(&((p).dir_entry), (p).result, (p).result->d_reclen), \
577     ((p).result = &(p).dir_entry), 0) :			 \
578    0),								 \
579   (_Xos_processUnlock),					 \
580   (p).result )
581
582#else
583typedef struct {
584  struct dirent *result;
585  struct dirent dir_entry;
586# ifdef _POSIX_PATH_MAX
587  char buf[_POSIX_PATH_MAX];
588# elif defined(NAME_MAX)
589  char buf[NAME_MAX];
590# else
591  char buf[255];
592# endif
593} _Xreaddirparams;
594
595# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(__APPLE__)
596/* POSIX final API, returns (int)0 on success. */
597#  define _XReaddir(d,p)						\
598    (readdir_r((d), &((p).dir_entry), &((p).result)) ? NULL : (p).result)
599# elif defined(_POSIX_REENTRANT_FUNCTIONS)
600/* POSIX draft API, returns (int)0 on success. */
601#  define _XReaddir(d,p)	\
602    (readdir_r((d),&((p).dir_entry)) ? NULL : &((p).dir_entry))
603# elif defined(SVR4)
604/* Pre-POSIX API, returns non-NULL on success. */
605#  define _XReaddir(d,p)	(readdir_r((d), &(p).dir_entry))
606# else
607/* We have no idea what is going on.  Fake it all using process locks. */
608#  define _XReaddir(d,p)	\
609    ( (_Xos_processLock),						\
610      (((p).result = readdir((d))) ?					\
611       (memcpy(&((p).dir_entry), (p).result, (p).result->d_reclen),	\
612	((p).result = &(p).dir_entry), 0) :				\
613       0),								\
614      (_Xos_processUnlock),						\
615      (p).result )
616# endif
617#endif /* X_INCLUDE_DIRENT_H */
618
619#if defined(X_INCLUDE_DIRENT_H) && !defined(_XOS_INCLUDED_DIRENT_H)
620# define _XOS_INCLUDED_DIRENT_H
621#endif
622
623
624/***** <unistd.h> wrappers *****/
625
626/*
627 * Effective prototypes for <unistd.h> wrappers:
628 *
629 * #define X_INCLUDE_UNISTD_H
630 * #define XOS_USE_..._LOCKING
631 * #include <X11/Xos_r.h>
632 *
633 * typedef ... _Xgetloginparams;
634 * typedef ... _Xttynameparams;
635 *
636 * char *_XGetlogin(_Xgetloginparams);
637 * char *_XTtyname(int, _Xttynameparams);
638 */
639
640#if defined(X_INCLUDE_UNISTD_H) && !defined(_XOS_INCLUDED_UNISTD_H)
641/* <unistd.h> already included by <X11/Xos.h> */
642# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_UNISTDAPI)
643#  define XOS_USE_MTSAFE_UNISTDAPI 1
644# endif
645#endif
646
647#if !defined(X_INCLUDE_UNISTD_H) || defined(_XOS_INCLUDED_UNISTD_H)
648/* Do nothing. */
649
650#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
651/* Use regular, unsafe API. */
652typedef int _Xgetloginparams;	/* dummy */
653typedef int _Xttynameparams;	/* dummy */
654# define _XGetlogin(p)	getlogin()
655# define _XTtyname(f)	ttyname((f))
656
657#elif !defined(XOS_USE_MTSAFE_UNISTDAPI) || defined(XNO_MTSAFE_UNISTDAPI)
658/* Systems with thread support but no _r API. */
659typedef struct {
660  char *result;
661# if defined(MAXLOGNAME)
662  char buf[MAXLOGNAME];
663# elif defined(LOGIN_NAME_MAX)
664  char buf[LOGIN_NAME_MAX];
665# else
666  char buf[64];
667# endif
668} _Xgetloginparams;
669typedef struct {
670  char *result;
671# ifdef TTY_NAME_MAX
672  char buf[TTY_NAME_MAX];
673# elif defined(_POSIX_TTY_NAME_MAX)
674  char buf[_POSIX_TTY_NAME_MAX];
675# elif defined(_POSIX_PATH_MAX)
676  char buf[_POSIX_PATH_MAX];
677# else
678  char buf[256];
679# endif
680} _Xttynameparams;
681
682# define _XGetlogin(p) \
683 ( (_Xos_processLock), \
684   (((p).result = getlogin()) ? \
685    (strncpy((p).buf, (p).result, sizeof((p).buf)), \
686     ((p).buf[sizeof((p).buf)-1] = '\0'), \
687     ((p).result = (p).buf), 0) : 0), \
688   (_Xos_processUnlock), \
689   (p).result )
690#define _XTtyname(f,p) \
691 ( (_Xos_processLock), \
692   (((p).result = ttyname(f)) ? \
693    (strncpy((p).buf, (p).result, sizeof((p).buf)), \
694     ((p).buf[sizeof((p).buf)-1] = '\0'), \
695     ((p).result = (p).buf), 0) : 0), \
696   (_Xos_processUnlock), \
697   (p).result )
698
699#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_REENTRANT_FUNCTIONS)
700/* POSIX API.
701 *
702 * extern int getlogin_r(char *, size_t);
703 * extern int ttyname_r(int, char *, size_t);
704 */
705typedef struct {
706# if defined(MAXLOGNAME)
707  char buf[MAXLOGNAME];
708# elif defined(LOGIN_NAME_MAX)
709  char buf[LOGIN_NAME_MAX];
710# else
711  char buf[64];
712# endif
713} _Xgetloginparams;
714typedef struct {
715# ifdef TTY_NAME_MAX
716  char buf[TTY_NAME_MAX];
717# elif defined(_POSIX_TTY_NAME_MAX)
718  char buf[_POSIX_TTY_NAME_MAX];
719# elif defined(_POSIX_PATH_MAX)
720  char buf[_POSIX_PATH_MAX];
721# else
722  char buf[256];
723# endif
724} _Xttynameparams;
725
726# define _XGetlogin(p)	(getlogin_r((p).buf, sizeof((p).buf)) ? NULL : (p).buf)
727# define _XTtyname(f,p)	\
728	(ttyname_r((f), (p).buf, sizeof((p).buf)) ? NULL : (p).buf)
729
730#else
731/* Pre-POSIX API.
732 *
733 * extern char *getlogin_r(char *, size_t);
734 * extern char *ttyname_r(int, char *, size_t);
735 */
736typedef struct {
737# if defined(MAXLOGNAME)
738  char buf[MAXLOGNAME];
739# elif defined(LOGIN_NAME_MAX)
740  char buf[LOGIN_NAME_MAX];
741# else
742  char buf[64];
743# endif
744} _Xgetloginparams;
745typedef struct {
746# ifdef TTY_NAME_MAX
747  char buf[TTY_NAME_MAX];
748# elif defined(_POSIX_TTY_NAME_MAX)
749  char buf[_POSIX_TTY_NAME_MAX];
750# elif defined(_POSIX_PATH_MAX)
751  char buf[_POSIX_PATH_MAX];
752# else
753  char buf[256];
754# endif
755} _Xttynameparams;
756
757# define _XGetlogin(p)	getlogin_r((p).buf, sizeof((p).buf))
758# define _XTtyname(f,p)	ttyname_r((f), (p).buf, sizeof((p).buf))
759#endif /* X_INCLUDE_UNISTD_H */
760
761#if defined(X_INCLUDE_UNISTD_H) && !defined(_XOS_INCLUDED_UNISTD_H)
762# define _XOS_INCLUDED_UNISTD_H
763#endif
764
765
766/***** <string.h> wrappers *****/
767
768/*
769 * Effective prototypes for <string.h> wrappers:
770 *
771 * #define X_INCLUDE_STRING_H
772 * #define XOS_USE_..._LOCKING
773 * #include <X11/Xos_r.h>
774 *
775 * typedef ... _Xstrtokparams;
776 *
777 * char *_XStrtok(char *, const char*, _Xstrtokparams);
778 */
779
780#if defined(X_INCLUDE_STRING_H) && !defined(_XOS_INCLUDED_STRING_H)
781/* <string.h> has already been included by <X11/Xos.h> */
782# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_STRINGAPI)
783#  define XOS_USE_MTSAFE_STRINGAPI 1
784# endif
785#endif
786
787#if !defined(X_INCLUDE_STRING_H) || defined(_XOS_INCLUDED_STRING_H)
788/* Do nothing. */
789
790#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
791/* Use regular, unsafe API. */
792typedef int _Xstrtokparams;	/* dummy */
793# define _XStrtok(s1,s2,p) \
794 ( p = 0, (void)p, strtok((s1),(s2)) )
795
796#elif !defined(XOS_USE_MTSAFE_STRINGAPI) || defined(XNO_MTSAFE_STRINGAPI)
797/* Systems with thread support but no _r API. */
798typedef char *_Xstrtokparams;
799# define _XStrtok(s1,s2,p) \
800 ( (_Xos_processLock), \
801   ((p) = strtok((s1),(s2))), \
802   (_Xos_processUnlock), \
803   (p) )
804
805#else
806/* POSIX or pre-POSIX API. */
807typedef char * _Xstrtokparams;
808# define _XStrtok(s1,s2,p)	strtok_r((s1),(s2),&(p))
809#endif /* X_INCLUDE_STRING_H */
810
811
812/***** <time.h> wrappers *****/
813
814/*
815 * Effective prototypes for <time.h> wrappers:
816 *
817 * #define X_INCLUDE_TIME_H
818 * #define XOS_USE_..._LOCKING
819 * #include <X11/Xos_r.h>
820 *
821 * typedef ... _Xatimeparams;
822 * typedef ... _Xctimeparams;
823 * typedef ... _Xgtimeparams;
824 * typedef ... _Xltimeparams;
825 *
826 * char *_XAsctime(const struct tm *, _Xatimeparams);
827 * char *_XCtime(const time_t *, _Xctimeparams);
828 * struct tm *_XGmtime(const time_t *, _Xgtimeparams);
829 * struct tm *_XLocaltime(const time_t *, _Xltimeparams);
830 */
831
832#if defined(X_INCLUDE_TIME_H) && !defined(_XOS_INCLUDED_TIME_H)
833# include <time.h>
834# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_TIMEAPI)
835#  define XOS_USE_MTSAFE_TIMEAPI 1
836# endif
837#endif
838
839#if !defined(X_INCLUDE_TIME_H) || defined(_XOS_INCLUDED_TIME_H)
840/* Do nothing. */
841
842#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
843/* Use regular, unsafe API. */
844typedef int _Xatimeparams;	/* dummy */
845# define _XAsctime(t,p)		asctime((t))
846typedef int _Xctimeparams;	/* dummy */
847# define _XCtime(t,p)		ctime((t))
848typedef int _Xgtimeparams;	/* dummy */
849# define _XGmtime(t,p)		gmtime((t))
850typedef int _Xltimeparams;	/* dummy */
851# define _XLocaltime(t,p)	localtime((t))
852
853#elif !defined(XOS_USE_MTSAFE_TIMEAPI) || defined(XNO_MTSAFE_TIMEAPI)
854/* Systems with thread support but no _r API. */
855typedef struct {
856# ifdef TIMELEN
857  char buf[TIMELEN];
858# else
859  char buf[26];
860# endif
861  char *result;
862} _Xctimeparams, _Xatimeparams;
863typedef struct {
864  struct tm buf;
865  struct tm *result;
866} _Xgtimeparams, _Xltimeparams;
867# define _XAsctime(t,p) \
868 ( (_Xos_processLock), \
869   (((p).result = asctime((t))) ? \
870    (strncpy((p).buf, (p).result, sizeof((p).buf)), (p).result = &(p).buf) : \
871    0), \
872   (_Xos_processUnlock), \
873   (p).result )
874# define _XCtime(t,p) \
875 ( (_Xos_processLock), \
876   (((p).result = ctime((t))) ? \
877    (strncpy((p).buf, (p).result, sizeof((p).buf)), (p).result = &(p).buf) : \
878    0), \
879   (_Xos_processUnlock), \
880   (p).result )
881# define _XGmtime(t,p) \
882 ( (_Xos_processLock), \
883   (((p).result = gmtime(t)) ? \
884    (memcpy(&(p).buf, (p).result, sizeof((p).buf)), (p).result = &(p).buf) : \
885    0), \
886   (_Xos_processUnlock), \
887   (p).result )
888# define _XLocaltime(t,p) \
889 ( (_Xos_processLock), \
890   (((p).result = localtime(t)) ? \
891    (memcpy(&(p).buf, (p).result, sizeof((p).buf)), (p).result = &(p).buf) : \
892    0), \
893   (_Xos_processUnlock), \
894   (p).result )
895
896#elif !defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&  defined(hpV4)
897/* Returns (int)0 on success.
898 *
899 * extern int asctime_r(const struct tm *timeptr, char *buffer, int buflen);
900 * extern int ctime_r(const time_t *timer, char *buffer, int buflen);
901 * extern int gmtime_r(const time_t *timer, struct tm *result);
902 * extern int localtime_r(const time_t *timer, struct tm *result);
903 */
904# ifdef TIMELEN
905typedef char _Xatimeparams[TIMELEN];
906typedef char _Xctimeparams[TIMELEN];
907# else
908typedef char _Xatimeparams[26];
909typedef char _Xctimeparams[26];
910# endif
911typedef struct tm _Xgtimeparams;
912typedef struct tm _Xltimeparams;
913# define _XAsctime(t,p)		(asctime_r((t),(p),sizeof((p))) ? NULL : (p))
914# define _XCtime(t,p)		(ctime_r((t),(p),sizeof((p))) ? NULL : (p))
915# define _XGmtime(t,p)		(gmtime_r((t),&(p)) ? NULL : &(p))
916# define _XLocaltime(t,p)	(localtime_r((t),&(p)) ? NULL : &(p))
917
918#elif !defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(__sun)
919/* Returns NULL on failure.  Solaris 2.5
920 *
921 * extern char *asctime_r(const struct tm *tm,char *buf, int buflen);
922 * extern char *ctime_r(const time_t *clock, char *buf, int buflen);
923 * extern struct tm *gmtime_r(const time_t *clock, struct tm *res);
924 * extern struct tm *localtime_r(const time_t *clock, struct tm *res);
925 */
926# ifdef TIMELEN
927typedef char _Xatimeparams[TIMELEN];
928typedef char _Xctimeparams[TIMELEN];
929# else
930typedef char _Xatimeparams[26];
931typedef char _Xctimeparams[26];
932# endif
933typedef struct tm _Xgtimeparams;
934typedef struct tm _Xltimeparams;
935# define _XAsctime(t,p)		asctime_r((t),(p),sizeof((p)))
936# define _XCtime(t,p)		ctime_r((t),(p),sizeof((p)))
937# define _XGmtime(t,p)		gmtime_r((t),&(p))
938# define _XLocaltime(t,p)	localtime_r((t),&(p))
939
940#else /* defined(_POSIX_THREAD_SAFE_FUNCTIONS) */
941/* POSIX final API.
942 * extern char *asctime_r(const struct tm *timeptr, char *buffer);
943 * extern char *ctime_r(const time_t *timer, char *buffer);
944 * extern struct tm *gmtime_r(const time_t *timer, struct tm *result);
945 * extern struct tm *localtime_r(const time_t *timer, struct tm *result);
946 */
947# ifdef TIMELEN
948typedef char _Xatimeparams[TIMELEN];
949typedef char _Xctimeparams[TIMELEN];
950# else
951typedef char _Xatimeparams[26];
952typedef char _Xctimeparams[26];
953# endif
954typedef struct tm _Xgtimeparams;
955typedef struct tm _Xltimeparams;
956# define _XAsctime(t,p)		asctime_r((t),(p))
957# define _XCtime(t,p)		ctime_r((t),(p))
958# define _XGmtime(t,p)		gmtime_r((t),&(p))
959# define _XLocaltime(t,p)	localtime_r((t),&(p))
960#endif /* X_INCLUDE_TIME_H */
961
962#if defined(X_INCLUDE_TIME_H) && !defined(_XOS_INCLUDED_TIME_H)
963# define _XOS_INCLUDED_TIME_H
964#endif
965
966
967/***** <grp.h> wrappers *****/
968
969/*
970 * Effective prototypes for <grp.h> wrappers:
971 *
972 * NOTE: On systems lacking appropriate _r functions Getgrgid() and
973 *	Getgrnam() do NOT copy the list of group members!
974 *
975 * Remember that fgetgrent(), setgrent(), getgrent(), and endgrent()
976 * are not included in POSIX.
977 *
978 * #define X_INCLUDE_GRP_H
979 * #define XOS_USE_..._LOCKING
980 * #include <X11/Xos_r.h>
981 *
982 * typedef ... _Xgetgrparams;
983 *
984 * struct group *_XGetgrgid(gid_t, _Xgetgrparams);
985 * struct group *_XGetgrnam(const char *, _Xgetgrparams);
986 */
987
988#if defined(X_INCLUDE_GRP_H) && !defined(_XOS_INCLUDED_GRP_H)
989# include <grp.h>
990# if defined(XUSE_MTSAFE_API) || defined(XUSE_MTSAFE_GRPAPI)
991#  define XOS_USE_MTSAFE_GRPAPI 1
992# endif
993#endif
994
995#if !defined(X_INCLUDE_GRP_H) || defined(_XOS_INCLUDED_GRP_H)
996/* Do nothing. */
997
998#elif !defined(XTHREADS) && !defined(X_FORCE_USE_MTSAFE_API)
999/* Use regular, unsafe API. */
1000typedef int _Xgetgrparams;	/* dummy */
1001#define _XGetgrgid(g,p)	getgrgid((g))
1002#define _XGetgrnam(n,p)	getgrnam((n))
1003
1004#elif !defined(XOS_USE_MTSAFE_GRPAPI) || defined(XNO_MTSAFE_GRPAPI)
1005/* Systems with thread support but no _r API.  UnixWare 2.0. */
1006typedef struct {
1007  struct group grp;
1008  char buf[X_LINE_MAX];	/* Should be sysconf(_SC_GETGR_R_SIZE_MAX)? */
1009  struct group *pgrp;
1010  size_t len;
1011} _Xgetgrparams;
1012#ifdef SVR4
1013/* Copy the gr_passwd field too. */
1014# define _Xgrp_copyGroup(p) \
1015 ( memcpy(&(p).grp, (p).pgrp, sizeof(struct group)), \
1016   ((p).grp.gr_name = (p).buf), \
1017   ((p).len = strlen((p).pgrp->gr_name)), \
1018   strcpy((p).grp.gr_name, (p).pgrp->gr_name), \
1019   ((p).grp.gr_passwd = (p).grp.gr_name + (p).len + 1), \
1020   ((p).pgrp = &(p).grp), \
1021   0 )
1022#else
1023# define _Xgrp_copyGroup(p) \
1024 ( memcpy(&(p).grp, (p).pgrp, sizeof(struct group)), \
1025   ((p).grp.gr_name = (p).buf), \
1026   strcpy((p).grp.gr_name, (p).pgrp->gr_name), \
1027   ((p).pgrp = &(p).grp), \
1028   0 )
1029#endif
1030#define _XGetgrgid(g,p) \
1031 ( (_Xos_processLock), \
1032   (((p).pgrp = getgrgid((g))) ? _Xgrp_copyGroup(p) : 0), \
1033   (_Xos_processUnlock), \
1034   (p).pgrp )
1035#define _XGetgrnam(n,p) \
1036 ( (_Xos_processLock), \
1037   (((p).pgrp = getgrnam((n))) ? _Xgrp_copyGroup(p) : 0), \
1038   (_Xos_processUnlock), \
1039   (p).pgrp )
1040
1041#elif !defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(__sun)
1042/* Non-POSIX API.  Solaris.
1043 *
1044 * extern struct group *getgrgid_r(gid_t, struct group *, char *, int);
1045 * extern struct group *getgrnam_r(const char *, struct group *, char *, int);
1046 */
1047typedef struct {
1048  struct group grp;
1049  char buf[X_LINE_MAX];	/* Should be sysconf(_SC_GETGR_R_SIZE_MAX)? */
1050} _Xgetgrparams;
1051#define _XGetgrgid(g,p)	getgrgid_r((g), &(p).grp, (p).buf, sizeof((p).buf))
1052#define _XGetgrnam(n,p)	getgrnam_r((n), &(p).grp, (p).buf, sizeof((p).buf))
1053
1054#elif !defined(_POSIX_THREAD_SAFE_FUNCTIONS)
1055/* Non-POSIX API.
1056 * extern int getgrgid_r(gid_t, struct group *, char *, int);
1057 * extern int getgrnam_r(const char *, struct group *, char *, int);
1058 */
1059typedef struct {
1060  struct group grp;
1061  char buf[X_LINE_MAX];	/* Should be sysconf(_SC_GETGR_R_SIZE_MAX)? */
1062} _Xgetgrparams;
1063#define _XGetgrgid(g,p)	\
1064 ((getgrgid_r((g), &(p).grp, (p).buf, sizeof((p).buf)) ? NULL : &(p).grp))
1065#define _XGetgrnam(n,p)	\
1066 ((getgrnam_r((n), &(p).grp, (p).buf, sizeof((p).buf)) ? NULL : &(p).grp))
1067
1068#else
1069/* POSIX final API.
1070 *
1071 * int getgrgid_r(gid_t, struct group *, char *, size_t, struct group **);
1072 * int getgrnam_r(const char *, struct group *, char *, size_t, struct group **);
1073 */
1074typedef struct {
1075  struct group grp;
1076  char buf[X_LINE_MAX];	/* Should be sysconf(_SC_GETGR_R_SIZE_MAX)? */
1077  struct group *result;
1078} _Xgetgrparams;
1079
1080#define _XGetgrgid(g,p)	\
1081 ((getgrgid_r((g), &(p).grp, (p).buf, sizeof((p).buf), &(p).result) ? \
1082   NULL : (p).result))
1083#define _XGetgrnam(n,p)	\
1084 ((getgrnam_r((n), &(p).grp, (p).buf, sizeof((p).buf), &(p).result) ? \
1085   NULL : (p).result))
1086#endif
1087
1088#if defined(X_INCLUDE_GRP_H) && !defined(_XOS_INCLUDED_GRP_H)
1089# define _XOS_INCLUDED_GRP_H
1090#endif
1091
1092
1093#ifdef __cplusplus
1094}  /* Close scope of 'extern "C"' declaration which encloses file. */
1095#endif
1096