Home | History | Annotate | Download | only in X11
      1 /*
      2 Copyright 1996, 1998  The Open Group
      3 
      4 Permission to use, copy, modify, distribute, and sell this software and its
      5 documentation for any purpose is hereby granted without fee, provided that
      6 the above copyright notice appear in all copies and that both that
      7 copyright notice and this permission notice appear in supporting
      8 documentation.
      9 
     10 The above copyright notice and this permission notice shall be included in
     11 all copies or substantial portions of the Software.
     12 
     13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     19 
     20 Except as contained in this notice, the name of The Open Group shall not be
     21 used in advertising or otherwise to promote the sale, use or other dealings
     22 in 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
     94 extern "C" {
     95 #endif
     96 
     97 # if defined(XOS_USE_XLIB_LOCKING)
     98 #  ifndef XAllocIDs /* Xlibint.h does not have multiple include protection */
     99 typedef struct _LockInfoRec *LockInfoPtr;
    100 extern 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 */
    108 extern void (*_XLockMutex_fn)(
    109 #    if NeedFunctionPrototypes
    110     LockInfoPtr	/* lock */, char * /* file */, int /* line */
    111 #    endif
    112 );
    113 extern 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 */
    130 extern void (*_XLockMutex_fn)(
    131 #    if NeedFunctionPrototypes
    132     LockInfoPtr	/* lock */
    133 #    endif
    134 );
    135 extern 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
    152 extern void (*_XtProcessLock)(void);
    153 #  endif
    154 #  ifndef _XtintrinsicP_h
    155 #   include <X11/Xfuncproto.h>	/* for NeedFunctionPrototypes */
    156 extern void XtProcessLock(
    157 #   if NeedFunctionPrototypes
    158     void
    159 #   endif
    160 );
    161 extern 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)
    229 extern struct passwd *getpwuid(), *getpwnam();
    230 # endif
    231 typedef 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
    238 typedef 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__)
    252 static __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
    323 typedef 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
    341 typedef struct {
    342   struct passwd pws;
    343   char pwbuf[X_LINE_MAX];
    344   struct passwd* pwp;
    345 } _Xgetpwparams;
    346 typedef 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. */
    397 typedef int _Xgethostbynameparams; /* dummy */
    398 typedef 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 
    410 typedef struct {
    411   struct hostent hent;
    412   char           h_name[MAXHOSTNAMELEN];
    413   struct hostent *hptr;
    414 } _Xgethostbynameparams;
    415 typedef 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
    470 typedef struct {
    471     struct hostent      hent;
    472     char                hbuf[X_LINE_MAX];
    473     int                 herr;
    474 } _Xgethostbynameparams;
    475 typedef 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
    486 typedef struct {
    487   struct hostent      hent;
    488   struct hostent_data hdata;
    489 } _Xgethostbynameparams;
    490 typedef 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. */
    510 typedef int _Xgethostbynameparams; /* dummy */
    511 typedef 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. */
    556 typedef 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. */
    561 typedef 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
    583 typedef 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. */
    652 typedef int _Xgetloginparams;	/* dummy */
    653 typedef 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. */
    659 typedef 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;
    669 typedef 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  */
    705 typedef 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;
    714 typedef 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  */
    736 typedef 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;
    745 typedef 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. */
    792 typedef 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. */
    798 typedef 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. */
    807 typedef 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. */
    844 typedef int _Xatimeparams;	/* dummy */
    845 # define _XAsctime(t,p)		asctime((t))
    846 typedef int _Xctimeparams;	/* dummy */
    847 # define _XCtime(t,p)		ctime((t))
    848 typedef int _Xgtimeparams;	/* dummy */
    849 # define _XGmtime(t,p)		gmtime((t))
    850 typedef 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. */
    855 typedef struct {
    856 # ifdef TIMELEN
    857   char buf[TIMELEN];
    858 # else
    859   char buf[26];
    860 # endif
    861   char *result;
    862 } _Xctimeparams, _Xatimeparams;
    863 typedef 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
    905 typedef char _Xatimeparams[TIMELEN];
    906 typedef char _Xctimeparams[TIMELEN];
    907 # else
    908 typedef char _Xatimeparams[26];
    909 typedef char _Xctimeparams[26];
    910 # endif
    911 typedef struct tm _Xgtimeparams;
    912 typedef 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
    927 typedef char _Xatimeparams[TIMELEN];
    928 typedef char _Xctimeparams[TIMELEN];
    929 # else
    930 typedef char _Xatimeparams[26];
    931 typedef char _Xctimeparams[26];
    932 # endif
    933 typedef struct tm _Xgtimeparams;
    934 typedef 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
    948 typedef char _Xatimeparams[TIMELEN];
    949 typedef char _Xctimeparams[TIMELEN];
    950 # else
    951 typedef char _Xatimeparams[26];
    952 typedef char _Xctimeparams[26];
    953 # endif
    954 typedef struct tm _Xgtimeparams;
    955 typedef 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. */
   1000 typedef 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. */
   1006 typedef 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  */
   1047 typedef 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  */
   1059 typedef 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  */
   1074 typedef 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