if we are adding a new sambaAccount, make sure that we add a
[Samba.git] / source / lib / system.c
bloba449600b21f42b7bd2434e35cc45b799c4f500ff
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba system utilities
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Jeremy Allison 1998-2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
26 The idea is that this file will eventually have wrappers around all
27 important system calls in samba. The aims are:
29 - to enable easier porting by putting OS dependent stuff in here
31 - to allow for hooks into other "pseudo-filesystems"
33 - to allow easier integration of things like the japanese extensions
35 - to support the philosophy of Samba to expose the features of
36 the OS within the SMB model. In general whatever file/printer/variable
37 expansions/etc make sense to the OS should be acceptable to Samba.
42 /*******************************************************************
43 A wrapper for usleep in case we don't have one.
44 ********************************************************************/
46 int sys_usleep(long usecs)
48 #ifndef HAVE_USLEEP
49 struct timeval tval;
50 #endif
53 * We need this braindamage as the glibc usleep
54 * is not SPEC1170 complient... grumble... JRA.
57 if(usecs < 0 || usecs > 1000000) {
58 errno = EINVAL;
59 return -1;
62 #if HAVE_USLEEP
63 usleep(usecs);
64 return 0;
65 #else /* HAVE_USLEEP */
67 * Fake it with select...
69 tval.tv_sec = 0;
70 tval.tv_usec = usecs/1000;
71 select(0,NULL,NULL,NULL,&tval);
72 return 0;
73 #endif /* HAVE_USLEEP */
76 /*******************************************************************
77 A read wrapper that will deal with EINTR.
78 ********************************************************************/
80 ssize_t sys_read(int fd, void *buf, size_t count)
82 ssize_t ret;
84 do {
85 ret = read(fd, buf, count);
86 } while (ret == -1 && errno == EINTR);
87 return ret;
90 /*******************************************************************
91 A write wrapper that will deal with EINTR.
92 ********************************************************************/
94 ssize_t sys_write(int fd, const void *buf, size_t count)
96 ssize_t ret;
98 do {
99 ret = write(fd, buf, count);
100 } while (ret == -1 && errno == EINTR);
101 return ret;
104 /*******************************************************************
105 A send wrapper that will deal with EINTR.
106 ********************************************************************/
108 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
110 ssize_t ret;
112 do {
113 ret = send(s, msg, len, flags);
114 } while (ret == -1 && errno == EINTR);
115 return ret;
118 /*******************************************************************
119 A sendto wrapper that will deal with EINTR.
120 ********************************************************************/
122 ssize_t sys_sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
124 ssize_t ret;
126 do {
127 ret = sendto(s, msg, len, flags, to, tolen);
128 } while (ret == -1 && errno == EINTR);
129 return ret;
132 /*******************************************************************
133 A recvfrom wrapper that will deal with EINTR.
134 ********************************************************************/
136 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
138 ssize_t ret;
140 do {
141 ret = recvfrom(s, buf, len, flags, from, fromlen);
142 } while (ret == -1 && errno == EINTR);
143 return ret;
146 /*******************************************************************
147 A fcntl wrapper that will deal with EINTR.
148 ********************************************************************/
150 int sys_fcntl_ptr(int fd, int cmd, void *arg)
152 int ret;
154 do {
155 ret = fcntl(fd, cmd, arg);
156 } while (ret == -1 && errno == EINTR);
157 return ret;
160 /*******************************************************************
161 A fcntl wrapper that will deal with EINTR.
162 ********************************************************************/
164 int sys_fcntl_long(int fd, int cmd, long arg)
166 int ret;
168 do {
169 ret = fcntl(fd, cmd, arg);
170 } while (ret == -1 && errno == EINTR);
171 return ret;
174 /*******************************************************************
175 A stat() wrapper that will deal with 64 bit filesizes.
176 ********************************************************************/
178 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
180 int ret;
181 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
182 ret = stat64(fname, sbuf);
183 #else
184 ret = stat(fname, sbuf);
185 #endif
186 /* we always want directories to appear zero size */
187 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
188 return ret;
191 /*******************************************************************
192 An fstat() wrapper that will deal with 64 bit filesizes.
193 ********************************************************************/
195 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
197 int ret;
198 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
199 ret = fstat64(fd, sbuf);
200 #else
201 ret = fstat(fd, sbuf);
202 #endif
203 /* we always want directories to appear zero size */
204 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
205 return ret;
208 /*******************************************************************
209 An lstat() wrapper that will deal with 64 bit filesizes.
210 ********************************************************************/
212 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
214 int ret;
215 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
216 ret = lstat64(fname, sbuf);
217 #else
218 ret = lstat(fname, sbuf);
219 #endif
220 /* we always want directories to appear zero size */
221 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
222 return ret;
225 /*******************************************************************
226 An ftruncate() wrapper that will deal with 64 bit filesizes.
227 ********************************************************************/
229 int sys_ftruncate(int fd, SMB_OFF_T offset)
231 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
232 return ftruncate64(fd, offset);
233 #else
234 return ftruncate(fd, offset);
235 #endif
238 /*******************************************************************
239 An lseek() wrapper that will deal with 64 bit filesizes.
240 ********************************************************************/
242 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
244 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
245 return lseek64(fd, offset, whence);
246 #else
247 return lseek(fd, offset, whence);
248 #endif
251 /*******************************************************************
252 An fseek() wrapper that will deal with 64 bit filesizes.
253 ********************************************************************/
255 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
257 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
258 return fseek64(fp, offset, whence);
259 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
260 return fseeko64(fp, offset, whence);
261 #else
262 return fseek(fp, offset, whence);
263 #endif
266 /*******************************************************************
267 An ftell() wrapper that will deal with 64 bit filesizes.
268 ********************************************************************/
270 SMB_OFF_T sys_ftell(FILE *fp)
272 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
273 return (SMB_OFF_T)ftell64(fp);
274 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
275 return (SMB_OFF_T)ftello64(fp);
276 #else
277 return (SMB_OFF_T)ftell(fp);
278 #endif
281 /*******************************************************************
282 A creat() wrapper that will deal with 64 bit filesizes.
283 ********************************************************************/
285 int sys_creat(const char *path, mode_t mode)
287 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
288 return creat64(path, mode);
289 #else
291 * If creat64 isn't defined then ensure we call a potential open64.
292 * JRA.
294 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
295 #endif
298 /*******************************************************************
299 An open() wrapper that will deal with 64 bit filesizes.
300 ********************************************************************/
302 int sys_open(const char *path, int oflag, mode_t mode)
304 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
305 return open64(path, oflag, mode);
306 #else
307 return open(path, oflag, mode);
308 #endif
311 /*******************************************************************
312 An fopen() wrapper that will deal with 64 bit filesizes.
313 ********************************************************************/
315 FILE *sys_fopen(const char *path, const char *type)
317 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
318 return fopen64(path, type);
319 #else
320 return fopen(path, type);
321 #endif
324 /*******************************************************************
325 A readdir wrapper that will deal with 64 bit filesizes.
326 ********************************************************************/
328 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
330 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
331 return readdir64(dirp);
332 #else
333 return readdir(dirp);
334 #endif
337 /*******************************************************************
338 An mknod() wrapper that will deal with 64 bit filesizes.
339 ********************************************************************/
341 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
343 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
344 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
345 return mknod64(path, mode, dev);
346 #else
347 return mknod(path, mode, dev);
348 #endif
349 #else
350 /* No mknod system call. */
351 errno = ENOSYS;
352 return -1;
353 #endif
356 /*******************************************************************
357 Wrapper for realpath.
358 ********************************************************************/
360 char *sys_realpath(const char *path, char *resolved_path)
362 #if defined(HAVE_REALPATH)
363 return realpath(path, resolved_path);
364 #else
365 /* As realpath is not a system call we can't return ENOSYS. */
366 errno = EINVAL;
367 return NULL;
368 #endif
371 /*******************************************************************
372 The wait() calls vary between systems
373 ********************************************************************/
375 int sys_waitpid(pid_t pid,int *status,int options)
377 #ifdef HAVE_WAITPID
378 return waitpid(pid,status,options);
379 #else /* HAVE_WAITPID */
380 return wait4(pid, status, options, NULL);
381 #endif /* HAVE_WAITPID */
384 /*******************************************************************
385 System wrapper for getwd
386 ********************************************************************/
388 char *sys_getwd(char *s)
390 char *wd;
391 #ifdef HAVE_GETCWD
392 wd = (char *)getcwd(s, sizeof (pstring));
393 #else
394 wd = (char *)getwd(s);
395 #endif
396 return wd;
399 /*******************************************************************
400 system wrapper for symlink
401 ********************************************************************/
403 int sys_symlink(const char *oldpath, const char *newpath)
405 #ifndef HAVE_SYMLINK
406 errno = ENOSYS;
407 return -1;
408 #else
409 return symlink(oldpath, newpath);
410 #endif
413 /*******************************************************************
414 system wrapper for readlink
415 ********************************************************************/
417 int sys_readlink(const char *path, char *buf, size_t bufsiz)
419 #ifndef HAVE_READLINK
420 errno = ENOSYS;
421 return -1;
422 #else
423 return readlink(path, buf, bufsiz);
424 #endif
427 /*******************************************************************
428 system wrapper for link
429 ********************************************************************/
431 int sys_link(const char *oldpath, const char *newpath)
433 #ifndef HAVE_LINK
434 errno = ENOSYS;
435 return -1;
436 #else
437 return link(oldpath, newpath);
438 #endif
441 /*******************************************************************
442 chown isn't used much but OS/2 doesn't have it
443 ********************************************************************/
445 int sys_chown(const char *fname,uid_t uid,gid_t gid)
447 #ifndef HAVE_CHOWN
448 static int done;
449 if (!done) {
450 DEBUG(1,("WARNING: no chown!\n"));
451 done=1;
453 #else
454 return(chown(fname,uid,gid));
455 #endif
458 /*******************************************************************
459 os/2 also doesn't have chroot
460 ********************************************************************/
461 int sys_chroot(const char *dname)
463 #ifndef HAVE_CHROOT
464 static int done;
465 if (!done) {
466 DEBUG(1,("WARNING: no chroot!\n"));
467 done=1;
469 errno = ENOSYS;
470 return -1;
471 #else
472 return(chroot(dname));
473 #endif
476 /**************************************************************************
477 A wrapper for gethostbyname() that tries avoids looking up hostnames
478 in the root domain, which can cause dial-on-demand links to come up for no
479 apparent reason.
480 ****************************************************************************/
482 struct hostent *sys_gethostbyname(const char *name)
484 #ifdef REDUCE_ROOT_DNS_LOOKUPS
485 char query[256], hostname[256];
486 char *domain;
488 /* Does this name have any dots in it? If so, make no change */
490 if (strchr(name, '.'))
491 return(gethostbyname(name));
493 /* Get my hostname, which should have domain name
494 attached. If not, just do the gethostname on the
495 original string.
498 gethostname(hostname, sizeof(hostname) - 1);
499 hostname[sizeof(hostname) - 1] = 0;
500 if ((domain = strchr(hostname, '.')) == NULL)
501 return(gethostbyname(name));
503 /* Attach domain name to query and do modified query.
504 If names too large, just do gethostname on the
505 original string.
508 if((strlen(name) + strlen(domain)) >= sizeof(query))
509 return(gethostbyname(name));
511 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
512 return(gethostbyname(query));
513 #else /* REDUCE_ROOT_DNS_LOOKUPS */
514 return(gethostbyname(name));
515 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
519 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
520 /**************************************************************************
521 Try and abstract process capabilities (for systems that have them).
522 ****************************************************************************/
523 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
525 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
526 cap_t cap = cap_get_proc();
528 if (cap == NULL) {
529 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
530 strerror(errno)));
531 return False;
534 if(enable)
535 cap->cap_effective |= CAP_NETWORK_MGT;
536 else
537 cap->cap_effective &= ~CAP_NETWORK_MGT;
539 if (cap_set_proc(cap) == -1) {
540 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
541 strerror(errno)));
542 cap_free(cap);
543 return False;
546 cap_free(cap);
548 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
550 return True;
553 /**************************************************************************
554 Try and abstract inherited process capabilities (for systems that have them).
555 ****************************************************************************/
557 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
559 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
560 cap_t cap = cap_get_proc();
562 if (cap == NULL) {
563 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
564 strerror(errno)));
565 return False;
568 if(enable)
569 cap->cap_inheritable |= CAP_NETWORK_MGT;
570 else
571 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
573 if (cap_set_proc(cap) == -1) {
574 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
575 strerror(errno)));
576 cap_free(cap);
577 return False;
580 cap_free(cap);
582 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
584 return True;
586 #endif
588 /****************************************************************************
589 Gain the oplock capability from the kernel if possible.
590 ****************************************************************************/
592 void oplock_set_capability(BOOL this_process, BOOL inherit)
594 #if HAVE_KERNEL_OPLOCKS_IRIX
595 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
596 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
597 #endif
600 /**************************************************************************
601 Wrapper for random().
602 ****************************************************************************/
604 long sys_random(void)
606 #if defined(HAVE_RANDOM)
607 return (long)random();
608 #elif defined(HAVE_RAND)
609 return (long)rand();
610 #else
611 DEBUG(0,("Error - no random function available !\n"));
612 exit(1);
613 #endif
616 /**************************************************************************
617 Wrapper for srandom().
618 ****************************************************************************/
620 void sys_srandom(unsigned int seed)
622 #if defined(HAVE_SRANDOM)
623 srandom(seed);
624 #elif defined(HAVE_SRAND)
625 srand(seed);
626 #else
627 DEBUG(0,("Error - no srandom function available !\n"));
628 exit(1);
629 #endif
632 /**************************************************************************
633 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
634 ****************************************************************************/
636 int groups_max(void)
638 #if defined(SYSCONF_SC_NGROUPS_MAX)
639 int ret = sysconf(_SC_NGROUPS_MAX);
640 return (ret == -1) ? NGROUPS_MAX : ret;
641 #else
642 return NGROUPS_MAX;
643 #endif
646 /**************************************************************************
647 Wrapper for getgroups. Deals with broken (int) case.
648 ****************************************************************************/
650 int sys_getgroups(int setlen, gid_t *gidset)
652 #if !defined(HAVE_BROKEN_GETGROUPS)
653 return getgroups(setlen, gidset);
654 #else
656 GID_T gid;
657 GID_T *group_list;
658 int i, ngroups;
660 if(setlen == 0) {
661 return getgroups(setlen, &gid);
665 * Broken case. We need to allocate a
666 * GID_T array of size setlen.
669 if(setlen < 0) {
670 errno = EINVAL;
671 return -1;
674 if (setlen == 0)
675 setlen = groups_max();
677 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
678 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
679 return -1;
682 if((ngroups = getgroups(setlen, group_list)) < 0) {
683 int saved_errno = errno;
684 SAFE_FREE(group_list);
685 errno = saved_errno;
686 return -1;
689 for(i = 0; i < ngroups; i++)
690 gidset[i] = (gid_t)group_list[i];
692 SAFE_FREE(group_list);
693 return ngroups;
694 #endif /* HAVE_BROKEN_GETGROUPS */
697 #ifdef HAVE_SETGROUPS
699 /**************************************************************************
700 Wrapper for setgroups. Deals with broken (int) case. Automatically used
701 if we have broken getgroups.
702 ****************************************************************************/
704 int sys_setgroups(int setlen, gid_t *gidset)
706 #if !defined(HAVE_BROKEN_GETGROUPS)
707 return setgroups(setlen, gidset);
708 #else
710 GID_T *group_list;
711 int i ;
713 if (setlen == 0)
714 return 0 ;
716 if (setlen < 0 || setlen > groups_max()) {
717 errno = EINVAL;
718 return -1;
722 * Broken case. We need to allocate a
723 * GID_T array of size setlen.
726 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
727 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
728 return -1;
731 for(i = 0; i < setlen; i++)
732 group_list[i] = (GID_T) gidset[i];
734 if(setgroups(setlen, group_list) != 0) {
735 int saved_errno = errno;
736 SAFE_FREE(group_list);
737 errno = saved_errno;
738 return -1;
741 SAFE_FREE(group_list);
742 return 0 ;
743 #endif /* HAVE_BROKEN_GETGROUPS */
746 #endif /* HAVE_SETGROUPS */
749 * We only wrap pw_name and pw_passwd for now as these
750 * are the only potentially modified fields.
753 /**************************************************************************
754 Helper function for getpwnam/getpwuid wrappers.
755 ****************************************************************************/
757 struct saved_pw {
758 fstring pw_name;
759 fstring pw_passwd;
760 fstring pw_gecos;
761 pstring pw_dir;
762 pstring pw_shell;
763 struct passwd pass;
766 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
767 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
769 static int num_lookups; /* Counter so we don't always use cache. */
770 #ifndef PW_RET_CACHE_MAX_LOOKUPS
771 #define PW_RET_CACHE_MAX_LOOKUPS 100
772 #endif
774 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
776 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
778 fstrcpy(dst->pw_name, pass->pw_name);
779 dst->pass.pw_name = dst->pw_name;
781 fstrcpy(dst->pw_passwd, pass->pw_passwd);
782 dst->pass.pw_passwd = dst->pw_passwd;
784 fstrcpy(dst->pw_gecos, pass->pw_gecos);
785 dst->pass.pw_gecos = dst->pw_gecos;
787 pstrcpy(dst->pw_dir, pass->pw_dir);
788 dst->pass.pw_dir = dst->pw_dir;
790 pstrcpy(dst->pw_shell, pass->pw_shell);
791 dst->pass.pw_shell = dst->pw_shell;
794 static struct passwd *setup_pwret(struct passwd *pass)
796 if (pass == NULL) {
797 /* Clear the caches. */
798 memset(&pw_cache, '\0', sizeof(struct saved_pw));
799 memset(&pw_mod, '\0', sizeof(struct saved_pw));
800 num_lookups = 0;
801 return NULL;
804 copy_pwent( &pw_mod, pass);
806 if (pass != &pw_cache.pass) {
808 /* If it's a cache miss we must also refill the cache. */
810 copy_pwent( &pw_cache, pass);
811 num_lookups = 1;
813 } else {
815 /* Cache hit. */
817 num_lookups++;
818 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
821 return &pw_mod.pass;
824 /**************************************************************************
825 Wrappers for setpwent(), getpwent() and endpwent()
826 ****************************************************************************/
828 void sys_setpwent(void)
830 setup_pwret(NULL); /* Clear cache. */
831 setpwent();
834 struct passwd *sys_getpwent(void)
836 return setup_pwret(getpwent());
839 void sys_endpwent(void)
841 setup_pwret(NULL); /* Clear cache. */
842 endpwent();
845 /**************************************************************************
846 Wrapper for getpwnam(). Always returns a static that can be modified.
847 ****************************************************************************/
849 struct passwd *sys_getpwnam(const char *name)
851 if (!name || !name[0])
852 return NULL;
854 /* check for a cache hit first */
855 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
856 return setup_pwret(&pw_cache.pass);
859 return setup_pwret(getpwnam(name));
862 /**************************************************************************
863 Wrapper for getpwuid(). Always returns a static that can be modified.
864 ****************************************************************************/
866 struct passwd *sys_getpwuid(uid_t uid)
868 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
869 return setup_pwret(&pw_cache.pass);
872 return setup_pwret(getpwuid(uid));
875 #if 0 /* NOT CURRENTLY USED - JRA */
876 /**************************************************************************
877 The following are the UNICODE versions of *all* system interface functions
878 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
879 which currently are left as ascii as they are not used other than in name
880 resolution.
881 ****************************************************************************/
883 /**************************************************************************
884 Wide stat. Just narrow and call sys_xxx.
885 ****************************************************************************/
887 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
889 pstring fname;
890 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
893 /**************************************************************************
894 Wide lstat. Just narrow and call sys_xxx.
895 ****************************************************************************/
897 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
899 pstring fname;
900 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
903 /**************************************************************************
904 Wide creat. Just narrow and call sys_xxx.
905 ****************************************************************************/
907 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
909 pstring fname;
910 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
913 /**************************************************************************
914 Wide open. Just narrow and call sys_xxx.
915 ****************************************************************************/
917 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
919 pstring fname;
920 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
923 /**************************************************************************
924 Wide fopen. Just narrow and call sys_xxx.
925 ****************************************************************************/
927 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
929 pstring fname;
930 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
933 /**************************************************************************
934 Wide opendir. Just narrow and call sys_xxx.
935 ****************************************************************************/
937 DIR *wsys_opendir(const smb_ucs2_t *wfname)
939 pstring fname;
940 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
943 /**************************************************************************
944 Wide readdir. Return a structure pointer containing a wide filename.
945 ****************************************************************************/
947 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
949 static SMB_STRUCT_WDIRENT retval;
950 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
952 if(!dirval)
953 return NULL;
956 * The only POSIX defined member of this struct is d_name.
959 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
961 return &retval;
964 /**************************************************************************
965 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
966 ****************************************************************************/
968 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
970 pstring fname;
971 char *p = sys_getwd(fname);
973 if(!p)
974 return NULL;
976 return unix_to_unicode(s, p, sizeof(wpstring));
979 /**************************************************************************
980 Wide chown. Just narrow and call sys_xxx.
981 ****************************************************************************/
983 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
985 pstring fname;
986 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
989 /**************************************************************************
990 Wide chroot. Just narrow and call sys_xxx.
991 ****************************************************************************/
993 int wsys_chroot(const smb_ucs2_t *wfname)
995 pstring fname;
996 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
999 /**************************************************************************
1000 Wide getpwnam. Return a structure pointer containing wide names.
1001 ****************************************************************************/
1003 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
1005 static SMB_STRUCT_WPASSWD retval;
1006 fstring name;
1007 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
1009 if(!pwret)
1010 return NULL;
1012 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1013 retval.pw_passwd = pwret->pw_passwd;
1014 retval.pw_uid = pwret->pw_uid;
1015 retval.pw_gid = pwret->pw_gid;
1016 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1017 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1018 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1020 return &retval;
1023 /**************************************************************************
1024 Wide getpwuid. Return a structure pointer containing wide names.
1025 ****************************************************************************/
1027 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
1029 static SMB_STRUCT_WPASSWD retval;
1030 struct passwd *pwret = sys_getpwuid(uid);
1032 if(!pwret)
1033 return NULL;
1035 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
1036 retval.pw_passwd = pwret->pw_passwd;
1037 retval.pw_uid = pwret->pw_uid;
1038 retval.pw_gid = pwret->pw_gid;
1039 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
1040 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
1041 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
1043 return &retval;
1045 #endif /* NOT CURRENTLY USED - JRA */
1047 /**************************************************************************
1048 Extract a command into an arg list. Uses a static pstring for storage.
1049 Caller frees returned arg list (which contains pointers into the static pstring).
1050 ****************************************************************************/
1052 static char **extract_args(const char *command)
1054 static pstring trunc_cmd;
1055 char *ptr;
1056 int argcl;
1057 char **argl = NULL;
1058 int i;
1060 pstrcpy(trunc_cmd, command);
1062 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1063 errno = EINVAL;
1064 return NULL;
1068 * Count the args.
1071 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1072 argcl++;
1074 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
1075 return NULL;
1078 * Now do the extraction.
1081 pstrcpy(trunc_cmd, command);
1083 ptr = strtok(trunc_cmd, " \t");
1084 i = 0;
1085 argl[i++] = ptr;
1087 while((ptr = strtok(NULL, " \t")) != NULL)
1088 argl[i++] = ptr;
1090 argl[i++] = NULL;
1091 return argl;
1094 /**************************************************************************
1095 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1096 a sys_getpid() that only does a system call *once*.
1097 ****************************************************************************/
1099 static pid_t mypid = (pid_t)-1;
1101 pid_t sys_fork(void)
1103 pid_t forkret = fork();
1105 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1106 mypid = (pid_t) -1;
1108 return forkret;
1111 /**************************************************************************
1112 Wrapper for getpid. Ensures we only do a system call *once*.
1113 ****************************************************************************/
1115 pid_t sys_getpid(void)
1117 if (mypid == (pid_t)-1)
1118 mypid = getpid();
1120 return mypid;
1123 /**************************************************************************
1124 Wrapper for popen. Safer as it doesn't search a path.
1125 Modified from the glibc sources.
1126 modified by tridge to return a file descriptor. We must kick our FILE* habit
1127 ****************************************************************************/
1129 typedef struct _popen_list
1131 int fd;
1132 pid_t child_pid;
1133 struct _popen_list *next;
1134 } popen_list;
1136 static popen_list *popen_chain;
1138 int sys_popen(const char *command)
1140 int parent_end, child_end;
1141 int pipe_fds[2];
1142 popen_list *entry = NULL;
1143 char **argl = NULL;
1145 if (pipe(pipe_fds) < 0)
1146 return -1;
1148 parent_end = pipe_fds[0];
1149 child_end = pipe_fds[1];
1151 if (!*command) {
1152 errno = EINVAL;
1153 goto err_exit;
1156 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1157 goto err_exit;
1159 ZERO_STRUCTP(entry);
1162 * Extract the command and args into a NULL terminated array.
1165 if(!(argl = extract_args(command)))
1166 goto err_exit;
1168 entry->child_pid = sys_fork();
1170 if (entry->child_pid == -1) {
1171 goto err_exit;
1174 if (entry->child_pid == 0) {
1177 * Child !
1180 int child_std_end = STDOUT_FILENO;
1181 popen_list *p;
1183 close(parent_end);
1184 if (child_end != child_std_end) {
1185 dup2 (child_end, child_std_end);
1186 close (child_end);
1190 * POSIX.2: "popen() shall ensure that any streams from previous
1191 * popen() calls that remain open in the parent process are closed
1192 * in the new child process."
1195 for (p = popen_chain; p; p = p->next)
1196 close(p->fd);
1198 execv(argl[0], argl);
1199 _exit (127);
1203 * Parent.
1206 close (child_end);
1207 SAFE_FREE(argl);
1209 /* Link into popen_chain. */
1210 entry->next = popen_chain;
1211 popen_chain = entry;
1212 entry->fd = parent_end;
1214 return entry->fd;
1216 err_exit:
1218 SAFE_FREE(entry);
1219 SAFE_FREE(argl);
1220 close(pipe_fds[0]);
1221 close(pipe_fds[1]);
1222 return -1;
1225 /**************************************************************************
1226 Wrapper for pclose. Modified from the glibc sources.
1227 ****************************************************************************/
1229 int sys_pclose(int fd)
1231 int wstatus;
1232 popen_list **ptr = &popen_chain;
1233 popen_list *entry = NULL;
1234 pid_t wait_pid;
1235 int status = -1;
1237 /* Unlink from popen_chain. */
1238 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1239 if ((*ptr)->fd == fd) {
1240 entry = *ptr;
1241 *ptr = (*ptr)->next;
1242 status = 0;
1243 break;
1247 if (status < 0 || close(entry->fd) < 0)
1248 return -1;
1251 * As Samba is catching and eating child process
1252 * exits we don't really care about the child exit
1253 * code, a -1 with errno = ECHILD will do fine for us.
1256 do {
1257 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1258 } while (wait_pid == -1 && errno == EINTR);
1260 SAFE_FREE(entry);
1262 if (wait_pid == -1)
1263 return -1;
1264 return wstatus;
1267 /**************************************************************************
1268 Wrappers for dlopen, dlsym, dlclose.
1269 ****************************************************************************/
1271 void *sys_dlopen(const char *name, int flags)
1273 #if defined(HAVE_DLOPEN)
1274 return dlopen(name, flags);
1275 #else
1276 return NULL;
1277 #endif
1280 void *sys_dlsym(void *handle, char *symbol)
1282 #if defined(HAVE_DLSYM)
1283 return dlsym(handle, symbol);
1284 #else
1285 return NULL;
1286 #endif
1289 int sys_dlclose (void *handle)
1291 #if defined(HAVE_DLCLOSE)
1292 return dlclose(handle);
1293 #else
1294 return 0;
1295 #endif
1298 const char *sys_dlerror(void)
1300 #if defined(HAVE_DLERROR)
1301 return dlerror();
1302 #else
1303 return NULL;
1304 #endif
1307 /**************************************************************************
1308 Wrapper for Admin Logs.
1309 ****************************************************************************/
1311 void sys_adminlog(int priority, const char *format_str, ...)
1313 va_list ap;
1314 int ret;
1315 char **msgbuf = NULL;
1317 if (!lp_admin_log())
1318 return;
1320 va_start( ap, format_str );
1321 ret = vasprintf( msgbuf, format_str, ap );
1322 va_end( ap );
1324 if (ret == -1)
1325 return;
1327 #if defined(HAVE_SYSLOG)
1328 syslog( priority, "%s", *msgbuf );
1329 #else
1330 DEBUG(0,("%s", *msgbuf ));
1331 #endif
1332 SAFE_FREE(*msgbuf);