2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (C) 1989 by NeXT, Inc.
30 #include <mach/mach.h>
34 #include <rpc/types.h>
37 #include <netinet/in.h>
38 #include <sys/param.h>
42 #include "_lu_types.h"
45 #include "lu_overrides.h"
47 static pthread_mutex_t _group_lock
= PTHREAD_MUTEX_INITIALIZER
;
54 free_group_data(struct group
*g
)
58 if (g
== NULL
) return;
60 if (g
->gr_name
!= NULL
) free(g
->gr_name
);
61 if (g
->gr_passwd
!= NULL
) free(g
->gr_passwd
);
66 while (*mem
!= NULL
) free(*mem
++);
72 free_group(struct group
*g
)
74 if (g
== NULL
) return;
80 free_lu_thread_info_group(void *x
)
82 struct lu_thread_info
*tdata
;
84 if (x
== NULL
) return;
86 tdata
= (struct lu_thread_info
*)x
;
88 if (tdata
->lu_entry
!= NULL
)
90 free_group((struct group
*)tdata
->lu_entry
);
91 tdata
->lu_entry
= NULL
;
94 _lu_data_free_vm_xdr(tdata
);
100 extract_group(XDR
*xdr
)
102 int i
, j
, nkeys
, nvals
, status
;
106 if (xdr
== NULL
) return NULL
;
108 if (!xdr_int(xdr
, &nkeys
)) return NULL
;
110 g
= (struct group
*)calloc(1, sizeof(struct group
));
113 for (i
= 0; i
< nkeys
; i
++)
119 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
134 if ((g
->gr_name
== NULL
) && (!strcmp("name", key
)))
136 g
->gr_name
= vals
[0];
139 else if ((g
->gr_passwd
== NULL
) && (!strcmp("passwd", key
)))
141 g
->gr_passwd
= vals
[0];
144 else if ((g
->gr_gid
== -2) && (!strcmp("gid", key
)))
146 g
->gr_gid
= atoi(vals
[0]);
148 else if ((g
->gr_mem
== NULL
) && (!strcmp("users", key
)))
158 for (; j
< nvals
; j
++) free(vals
[j
]);
163 if (g
->gr_name
== NULL
) g
->gr_name
= strdup("");
164 if (g
->gr_passwd
== NULL
) g
->gr_passwd
= strdup("");
165 if (g
->gr_mem
== NULL
) g
->gr_mem
= (char **)calloc(1, sizeof(char *));
170 static struct group
*
171 copy_group(struct group
*in
)
176 if (in
== NULL
) return NULL
;
178 g
= (struct group
*)calloc(1, sizeof(struct group
));
180 g
->gr_name
= LU_COPY_STRING(in
->gr_name
);
181 g
->gr_passwd
= LU_COPY_STRING(in
->gr_passwd
);
182 g
->gr_gid
= in
->gr_gid
;
185 if (in
->gr_mem
!= NULL
)
187 for (len
= 0; in
->gr_mem
[len
] != NULL
; len
++);
190 g
->gr_mem
= (char **)calloc(len
+ 1, sizeof(char *));
191 for (i
= 0; i
< len
; i
++)
193 g
->gr_mem
[i
] = strdup(in
->gr_mem
[i
]);
200 copy_group_r(struct group
*in
, struct group
*out
, char *buffer
, int buflen
)
206 if (in
== NULL
) return -1;
207 if (out
== NULL
) return -1;
209 if (buffer
== NULL
) buflen
= 0;
211 /* Calculate size of input */
213 if (in
->gr_name
!= NULL
) hsize
+= strlen(in
->gr_name
);
214 if (in
->gr_passwd
!= NULL
) hsize
+= strlen(in
->gr_passwd
);
216 /* NULL pointer at end of list */
217 hsize
+= sizeof(char *);
220 if (in
->gr_mem
!= NULL
)
222 for (len
= 0; in
->gr_mem
[len
] != NULL
; len
++)
224 hsize
+= sizeof(char *);
225 hsize
+= strlen(in
->gr_mem
[len
]);
229 /* Check buffer space */
230 if (hsize
> buflen
) return -1;
232 /* Copy result into caller's struct group, using buffer for memory */
236 if (in
->gr_name
!= NULL
)
239 hsize
= strlen(in
->gr_name
) + 1;
240 memmove(bp
, in
->gr_name
, hsize
);
244 out
->gr_passwd
= NULL
;
245 if (in
->gr_passwd
!= NULL
)
248 hsize
= strlen(in
->gr_passwd
) + 1;
249 memmove(bp
, in
->gr_passwd
, hsize
);
253 out
->gr_gid
= in
->gr_gid
;
256 ap
= bp
+ ((len
+ 1) * sizeof(char *));
258 if (in
->gr_mem
!= NULL
)
260 out
->gr_mem
= (char **)bp
;
261 for (i
= 0; i
< len
; i
++)
263 addr
= (unsigned long)ap
;
264 memmove(bp
, &addr
, sizeof(unsigned long));
265 bp
+= sizeof(unsigned long);
267 hsize
= strlen(in
->gr_mem
[i
]) + 1;
268 memmove(ap
, in
->gr_mem
[i
], hsize
);
273 memset(bp
, 0, sizeof(unsigned long));
280 recycle_group(struct lu_thread_info
*tdata
, struct group
*in
)
284 if (tdata
== NULL
) return;
285 g
= (struct group
*)tdata
->lu_entry
;
290 tdata
->lu_entry
= NULL
;
293 if (tdata
->lu_entry
== NULL
)
295 tdata
->lu_entry
= in
;
301 g
->gr_name
= in
->gr_name
;
302 g
->gr_passwd
= in
->gr_passwd
;
303 g
->gr_gid
= in
->gr_gid
;
304 g
->gr_mem
= in
->gr_mem
;
309 static struct group
*
313 unsigned int datalen
;
315 static int proc
= -1;
321 if (_lookup_link(_lu_port
, "getgrgid", &proc
) != KERN_SUCCESS
)
331 if (_lookup_all(_lu_port
, proc
, (unit
*)&gid
, 1, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
336 datalen
*= BYTES_PER_XDR_UNIT
;
337 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
339 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
342 if (!xdr_int(&inxdr
, &count
))
345 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
352 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
356 g
= extract_group(&inxdr
);
358 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
363 static struct group
*
364 lu_getgrnam(const char *name
)
367 unsigned int datalen
;
368 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
371 static int proc
= -1;
377 if (_lookup_link(_lu_port
, "getgrnam", &proc
) != KERN_SUCCESS
)
383 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
385 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
387 xdr_destroy(&outxdr
);
394 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
, xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
399 xdr_destroy(&outxdr
);
401 datalen
*= BYTES_PER_XDR_UNIT
;
402 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
404 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
407 if (!xdr_int(&inxdr
, &count
))
410 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
417 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
421 g
= extract_group(&inxdr
);
423 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
429 lu_initgroups(const char *name
, int basegid
)
431 unsigned int datalen
;
434 static int proc
= -1;
436 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
446 if (_lookup_link(_lu_port
, "initgroups", &proc
) != KERN_SUCCESS
)
452 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
453 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
455 xdr_destroy(&outxdr
);
462 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
,
463 xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
)
466 xdr_destroy(&outxdr
);
470 xdr_destroy(&outxdr
);
472 datalen
*= BYTES_PER_XDR_UNIT
;
473 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
475 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
477 if (!xdr_int(&inxdr
, &count
))
480 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
484 if (count
> NGROUPS
) count
= NGROUPS
;
488 for (i
= 0; i
< count
; i
++)
490 if (!xdr_int(&inxdr
, &a_group
)) break;
492 for (j
= 0; j
< ngroups
; j
++)
494 if (groups
[j
] == a_group
) break;
496 if (j
>= ngroups
) groups
[ngroups
++] = a_group
;
500 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
502 return setgroups(ngroups
, groups
);
508 struct lu_thread_info
*tdata
;
510 tdata
= _lu_data_create_key(_lu_data_key_group
, free_lu_thread_info_group
);
511 _lu_data_free_vm_xdr(tdata
);
521 static struct group
*
525 static int proc
= -1;
526 struct lu_thread_info
*tdata
;
528 tdata
= _lu_data_create_key(_lu_data_key_group
, free_lu_thread_info_group
);
531 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
532 _lu_data_set_key(_lu_data_key_group
, tdata
);
535 if (tdata
->lu_vm
== NULL
)
539 if (_lookup_link(_lu_port
, "getgrent", &proc
) != KERN_SUCCESS
)
546 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
552 /* mig stubs measure size in words (4 bytes) */
553 tdata
->lu_vm_length
*= 4;
555 if (tdata
->lu_xdr
!= NULL
)
557 xdr_destroy(tdata
->lu_xdr
);
560 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
562 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
563 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
570 if (tdata
->lu_vm_cursor
== 0)
576 g
= extract_group(tdata
->lu_xdr
);
583 tdata
->lu_vm_cursor
--;
588 static struct group
*
589 getgr_internal(const char *name
, gid_t gid
, int source
)
591 struct group
*res
= NULL
;
598 res
= lu_getgrnam(name
);
601 res
= lu_getgrgid(gid
);
611 pthread_mutex_lock(&_group_lock
);
615 res
= copy_group(_old_getgrnam(name
));
618 res
= copy_group(_old_getgrgid(gid
));
621 res
= copy_group(_old_getgrent());
625 pthread_mutex_unlock(&_group_lock
);
631 static struct group
*
632 getgr(const char *name
, gid_t gid
, int source
)
634 struct group
*res
= NULL
;
635 struct lu_thread_info
*tdata
;
637 tdata
= _lu_data_create_key(_lu_data_key_group
, free_lu_thread_info_group
);
640 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
641 _lu_data_set_key(_lu_data_key_group
, tdata
);
644 res
= getgr_internal(name
, gid
, source
);
646 recycle_group(tdata
, res
);
647 return (struct group
*)tdata
->lu_entry
;
651 getgr_r(const char *name
, gid_t gid
, int source
, struct group
*grp
, char *buffer
, size_t bufsize
, struct group
**result
)
653 struct group
*res
= NULL
;
659 res
= getgr_internal(name
, gid
, source
);
660 if (res
== NULL
) return -1;
662 status
= copy_group_r(res
, grp
, buffer
, bufsize
);
676 initgroups(const char *name
, int basegid
)
680 if (name
== NULL
) return -1;
684 if ((res
= lu_initgroups(name
, basegid
)))
686 res
= _old_initgroups(name
, basegid
);
691 res
= _old_initgroups(name
, basegid
);
698 getgrnam(const char *name
)
700 return getgr(name
, -2, GR_GET_NAME
);
706 return getgr(NULL
, gid
, GR_GET_GID
);
712 return getgr(NULL
, -2, GR_GET_ENT
);
718 if (_lu_running()) lu_setgrent();
719 else _old_setgrent();
726 if (_lu_running()) lu_endgrent();
727 else _old_endgrent();
731 getgrnam_r(const char *name
, struct group
*grp
, char *buffer
, size_t bufsize
, struct group
**result
)
733 return getgr_r(name
, -2, GR_GET_NAME
, grp
, buffer
, bufsize
, result
);
737 getgrgid_r(gid_t gid
, struct group
*grp
, char *buffer
, size_t bufsize
, struct group
**result
)
739 return getgr_r(NULL
, gid
, GR_GET_GID
, grp
, buffer
, bufsize
, result
);