2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2002
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 The idea is that this file will eventually have wrappers around all
26 important system calls in samba. The aims are:
28 - to enable easier porting by putting OS dependent stuff in here
30 - to allow for hooks into other "pseudo-filesystems"
32 - to allow easier integration of things like the japanese extensions
34 - to support the philosophy of Samba to expose the features of
35 the OS within the SMB model. In general whatever file/printer/variable
36 expansions/etc make sense to the OS should be acceptable to Samba.
41 /*******************************************************************
42 A wrapper for usleep in case we don't have one.
43 ********************************************************************/
45 int sys_usleep(long usecs)
52 * We need this braindamage as the glibc usleep
53 * is not SPEC1170 complient... grumble... JRA.
56 if(usecs < 0 || usecs > 1000000) {
64 #else /* HAVE_USLEEP */
66 * Fake it with select...
69 tval.tv_usec = usecs/1000;
70 select(0,NULL,NULL,NULL,&tval);
72 #endif /* HAVE_USLEEP */
75 /*******************************************************************
76 A read wrapper that will deal with EINTR.
77 ********************************************************************/
79 ssize_t sys_read(int fd, void *buf, size_t count)
85 ret = read(fd, buf, count);
86 } while (ret == -1 && errno == EINTR);
90 /*******************************************************************
91 A write wrapper that will deal with EINTR.
92 ********************************************************************/
94 ssize_t sys_write(int fd, const void *buf, size_t count)
100 ret = write(fd, buf, count);
101 } while (ret == -1 && errno == EINTR);
105 /*******************************************************************
106 A send wrapper that will deal with EINTR.
107 ********************************************************************/
109 int sys_send(int s, const void *msg, size_t len, int flags)
115 ret = send(s, msg, len, flags);
116 } while (ret == -1 && errno == EINTR);
120 /*******************************************************************
121 A stat() wrapper that will deal with 64 bit filesizes.
122 ********************************************************************/
124 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
127 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
128 ret = stat64(fname, sbuf);
130 ret = stat(fname, sbuf);
132 /* we always want directories to appear zero size */
133 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
137 /*******************************************************************
138 An fstat() wrapper that will deal with 64 bit filesizes.
139 ********************************************************************/
141 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
144 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
145 ret = fstat64(fd, sbuf);
147 ret = fstat(fd, sbuf);
149 /* we always want directories to appear zero size */
150 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
154 /*******************************************************************
155 An lstat() wrapper that will deal with 64 bit filesizes.
156 ********************************************************************/
158 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
161 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
162 ret = lstat64(fname, sbuf);
164 ret = lstat(fname, sbuf);
166 /* we always want directories to appear zero size */
167 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
171 /*******************************************************************
172 An ftruncate() wrapper that will deal with 64 bit filesizes.
173 ********************************************************************/
175 int sys_ftruncate(int fd, SMB_OFF_T offset)
177 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
178 return ftruncate64(fd, offset);
180 return ftruncate(fd, offset);
184 /*******************************************************************
185 An lseek() wrapper that will deal with 64 bit filesizes.
186 ********************************************************************/
188 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
190 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
191 return lseek64(fd, offset, whence);
193 return lseek(fd, offset, whence);
197 /*******************************************************************
198 An fseek() wrapper that will deal with 64 bit filesizes.
199 ********************************************************************/
201 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
203 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
204 return fseek64(fp, offset, whence);
205 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
206 return fseeko64(fp, offset, whence);
208 return fseek(fp, offset, whence);
212 /*******************************************************************
213 An ftell() wrapper that will deal with 64 bit filesizes.
214 ********************************************************************/
216 SMB_OFF_T sys_ftell(FILE *fp)
218 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
219 return (SMB_OFF_T)ftell64(fp);
220 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
221 return (SMB_OFF_T)ftello64(fp);
223 return (SMB_OFF_T)ftell(fp);
227 /*******************************************************************
228 A creat() wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
231 int sys_creat(const char *path, mode_t mode)
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
234 return creat64(path, mode);
237 * If creat64 isn't defined then ensure we call a potential open64.
240 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
244 /*******************************************************************
245 An open() wrapper that will deal with 64 bit filesizes.
246 ********************************************************************/
248 int sys_open(const char *path, int oflag, mode_t mode)
250 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
251 return open64(path, oflag, mode);
253 return open(path, oflag, mode);
257 /*******************************************************************
258 An fopen() wrapper that will deal with 64 bit filesizes.
259 ********************************************************************/
261 FILE *sys_fopen(const char *path, const char *type)
263 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
264 return fopen64(path, type);
266 return fopen(path, type);
270 /*******************************************************************
271 A readdir wrapper that will deal with 64 bit filesizes.
272 ********************************************************************/
274 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
276 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
277 return readdir64(dirp);
279 return readdir(dirp);
283 /*******************************************************************
284 An mknod() wrapper that will deal with 64 bit filesizes.
285 ********************************************************************/
287 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
289 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
290 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
291 return mknod64(path, mode, dev);
293 return mknod(path, mode, dev);
296 /* No mknod system call. */
302 /*******************************************************************
303 Wrapper for realpath.
304 ********************************************************************/
306 char *sys_realpath(const char *path, char *resolved_path)
308 #if defined(HAVE_REALPATH)
309 return realpath(path, resolved_path);
311 /* As realpath is not a system call we can't return ENOSYS. */
317 /*******************************************************************
318 The wait() calls vary between systems
319 ********************************************************************/
321 int sys_waitpid(pid_t pid,int *status,int options)
324 return waitpid(pid,status,options);
325 #else /* HAVE_WAITPID */
326 return wait4(pid, status, options, NULL);
327 #endif /* HAVE_WAITPID */
330 /*******************************************************************
331 System wrapper for getwd
332 ********************************************************************/
334 char *sys_getwd(char *s)
338 wd = (char *)getcwd(s, sizeof (pstring));
340 wd = (char *)getwd(s);
345 /*******************************************************************
346 system wrapper for symlink
347 ********************************************************************/
349 int sys_symlink(const char *oldpath, const char *newpath)
355 return symlink(oldpath, newpath);
359 /*******************************************************************
360 system wrapper for readlink
361 ********************************************************************/
363 int sys_readlink(const char *path, char *buf, size_t bufsiz)
365 #ifndef HAVE_READLINK
369 return readlink(path, buf, bufsiz);
373 /*******************************************************************
374 system wrapper for link
375 ********************************************************************/
377 int sys_link(const char *oldpath, const char *newpath)
383 return link(oldpath, newpath);
387 /*******************************************************************
388 chown isn't used much but OS/2 doesn't have it
389 ********************************************************************/
391 int sys_chown(const char *fname,uid_t uid,gid_t gid)
396 DEBUG(1,("WARNING: no chown!\n"));
400 return(chown(fname,uid,gid));
404 /*******************************************************************
405 os/2 also doesn't have chroot
406 ********************************************************************/
407 int sys_chroot(const char *dname)
412 DEBUG(1,("WARNING: no chroot!\n"));
418 return(chroot(dname));
422 /**************************************************************************
423 A wrapper for gethostbyname() that tries avoids looking up hostnames
424 in the root domain, which can cause dial-on-demand links to come up for no
426 ****************************************************************************/
428 struct hostent *sys_gethostbyname(const char *name)
430 #ifdef REDUCE_ROOT_DNS_LOOKUPS
431 char query[256], hostname[256];
434 /* Does this name have any dots in it? If so, make no change */
436 if (strchr_m(name, '.'))
437 return(gethostbyname(name));
439 /* Get my hostname, which should have domain name
440 attached. If not, just do the gethostname on the
444 gethostname(hostname, sizeof(hostname) - 1);
445 hostname[sizeof(hostname) - 1] = 0;
446 if ((domain = strchr_m(hostname, '.')) == NULL)
447 return(gethostbyname(name));
449 /* Attach domain name to query and do modified query.
450 If names too large, just do gethostname on the
454 if((strlen(name) + strlen(domain)) >= sizeof(query))
455 return(gethostbyname(name));
457 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
458 return(gethostbyname(query));
459 #else /* REDUCE_ROOT_DNS_LOOKUPS */
460 return(gethostbyname(name));
461 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
465 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
466 /**************************************************************************
467 Try and abstract process capabilities (for systems that have them).
468 ****************************************************************************/
469 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
471 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
472 cap_t cap = cap_get_proc();
475 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
481 cap->cap_effective |= CAP_NETWORK_MGT;
483 cap->cap_effective &= ~CAP_NETWORK_MGT;
485 if (cap_set_proc(cap) == -1) {
486 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
494 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
499 /**************************************************************************
500 Try and abstract inherited process capabilities (for systems that have them).
501 ****************************************************************************/
503 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
505 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
506 cap_t cap = cap_get_proc();
509 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
515 cap->cap_inheritable |= CAP_NETWORK_MGT;
517 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
519 if (cap_set_proc(cap) == -1) {
520 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
528 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
534 /****************************************************************************
535 Gain the oplock capability from the kernel if possible.
536 ****************************************************************************/
538 void oplock_set_capability(BOOL this_process, BOOL inherit)
540 #if HAVE_KERNEL_OPLOCKS_IRIX
541 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
542 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
546 /**************************************************************************
547 Wrapper for random().
548 ****************************************************************************/
550 long sys_random(void)
552 #if defined(HAVE_RANDOM)
553 return (long)random();
554 #elif defined(HAVE_RAND)
557 DEBUG(0,("Error - no random function available !\n"));
562 /**************************************************************************
563 Wrapper for srandom().
564 ****************************************************************************/
566 void sys_srandom(unsigned int seed)
568 #if defined(HAVE_SRANDOM)
570 #elif defined(HAVE_SRAND)
573 DEBUG(0,("Error - no srandom function available !\n"));
578 /**************************************************************************
579 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
580 ****************************************************************************/
584 #if defined(SYSCONF_SC_NGROUPS_MAX)
585 int ret = sysconf(_SC_NGROUPS_MAX);
586 return (ret == -1) ? NGROUPS_MAX : ret;
592 /**************************************************************************
593 Wrapper for getgroups. Deals with broken (int) case.
594 ****************************************************************************/
596 int sys_getgroups(int setlen, gid_t *gidset)
598 #if !defined(HAVE_BROKEN_GETGROUPS)
599 return getgroups(setlen, gidset);
607 return getgroups(setlen, &gid);
611 * Broken case. We need to allocate a
612 * GID_T array of size setlen.
621 setlen = groups_max();
623 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
624 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
628 if((ngroups = getgroups(setlen, group_list)) < 0) {
629 int saved_errno = errno;
630 SAFE_FREE(group_list);
635 for(i = 0; i < ngroups; i++)
636 gidset[i] = (gid_t)group_list[i];
638 SAFE_FREE(group_list);
640 #endif /* HAVE_BROKEN_GETGROUPS */
643 #ifdef HAVE_SETGROUPS
645 /**************************************************************************
646 Wrapper for setgroups. Deals with broken (int) case. Automatically used
647 if we have broken getgroups.
648 ****************************************************************************/
650 int sys_setgroups(int setlen, gid_t *gidset)
652 #if !defined(HAVE_BROKEN_GETGROUPS)
653 return setgroups(setlen, gidset);
662 if (setlen < 0 || setlen > groups_max()) {
668 * Broken case. We need to allocate a
669 * GID_T array of size setlen.
672 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
673 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
677 for(i = 0; i < setlen; i++)
678 group_list[i] = (GID_T) gidset[i];
680 if(setgroups(setlen, group_list) != 0) {
681 int saved_errno = errno;
682 SAFE_FREE(group_list);
687 SAFE_FREE(group_list);
689 #endif /* HAVE_BROKEN_GETGROUPS */
692 #endif /* HAVE_SETGROUPS */
695 * We only wrap pw_name and pw_passwd for now as these
696 * are the only potentially modified fields.
699 /**************************************************************************
700 Helper function for getpwnam/getpwuid wrappers.
701 ****************************************************************************/
712 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
713 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
715 static int num_lookups; /* Counter so we don't always use cache. */
716 #ifndef PW_RET_CACHE_MAX_LOOKUPS
717 #define PW_RET_CACHE_MAX_LOOKUPS 100
720 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
722 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
724 fstrcpy(dst->pw_name, pass->pw_name);
725 dst->pass.pw_name = dst->pw_name;
727 fstrcpy(dst->pw_passwd, pass->pw_passwd);
728 dst->pass.pw_passwd = dst->pw_passwd;
730 fstrcpy(dst->pw_gecos, pass->pw_gecos);
731 dst->pass.pw_gecos = dst->pw_gecos;
733 pstrcpy(dst->pw_dir, pass->pw_dir);
734 dst->pass.pw_dir = dst->pw_dir;
736 pstrcpy(dst->pw_shell, pass->pw_shell);
737 dst->pass.pw_shell = dst->pw_shell;
740 static struct passwd *setup_pwret(struct passwd *pass)
743 /* Clear the caches. */
744 memset(&pw_cache, '\0', sizeof(struct saved_pw));
745 memset(&pw_mod, '\0', sizeof(struct saved_pw));
750 copy_pwent( &pw_mod, pass);
752 if (pass != &pw_cache.pass) {
754 /* If it's a cache miss we must also refill the cache. */
756 copy_pwent( &pw_cache, pass);
764 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
770 /**************************************************************************
771 Wrappers for setpwent(), getpwent() and endpwent()
772 ****************************************************************************/
774 void sys_setpwent(void)
776 setup_pwret(NULL); /* Clear cache. */
780 struct passwd *sys_getpwent(void)
782 return setup_pwret(getpwent());
785 void sys_endpwent(void)
787 setup_pwret(NULL); /* Clear cache. */
791 /**************************************************************************
792 Wrapper for getpwnam(). Always returns a static that can be modified.
793 ****************************************************************************/
795 struct passwd *sys_getpwnam(const char *name)
797 if (!name || !name[0])
800 /* check for a cache hit first */
801 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
802 return setup_pwret(&pw_cache.pass);
805 return setup_pwret(getpwnam(name));
808 /**************************************************************************
809 Wrapper for getpwuid(). Always returns a static that can be modified.
810 ****************************************************************************/
812 struct passwd *sys_getpwuid(uid_t uid)
814 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
815 return setup_pwret(&pw_cache.pass);
818 return setup_pwret(getpwuid(uid));
821 #if 0 /* NOT CURRENTLY USED - JRA */
822 /**************************************************************************
823 The following are the UNICODE versions of *all* system interface functions
824 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
825 which currently are left as ascii as they are not used other than in name
827 ****************************************************************************/
829 /**************************************************************************
830 Wide stat. Just narrow and call sys_xxx.
831 ****************************************************************************/
833 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
836 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
839 /**************************************************************************
840 Wide lstat. Just narrow and call sys_xxx.
841 ****************************************************************************/
843 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
846 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
849 /**************************************************************************
850 Wide creat. Just narrow and call sys_xxx.
851 ****************************************************************************/
853 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
856 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
859 /**************************************************************************
860 Wide open. Just narrow and call sys_xxx.
861 ****************************************************************************/
863 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
866 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
869 /**************************************************************************
870 Wide fopen. Just narrow and call sys_xxx.
871 ****************************************************************************/
873 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
876 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
879 /**************************************************************************
880 Wide opendir. Just narrow and call sys_xxx.
881 ****************************************************************************/
883 DIR *wsys_opendir(const smb_ucs2_t *wfname)
886 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
889 /**************************************************************************
890 Wide readdir. Return a structure pointer containing a wide filename.
891 ****************************************************************************/
893 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
895 static SMB_STRUCT_WDIRENT retval;
896 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
902 * The only POSIX defined member of this struct is d_name.
905 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
910 /**************************************************************************
911 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
912 ****************************************************************************/
914 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
917 char *p = sys_getwd(fname);
922 return unix_to_unicode(s, p, sizeof(wpstring));
925 /**************************************************************************
926 Wide chown. Just narrow and call sys_xxx.
927 ****************************************************************************/
929 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
932 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
935 /**************************************************************************
936 Wide chroot. Just narrow and call sys_xxx.
937 ****************************************************************************/
939 int wsys_chroot(const smb_ucs2_t *wfname)
942 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
945 /**************************************************************************
946 Wide getpwnam. Return a structure pointer containing wide names.
947 ****************************************************************************/
949 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
951 static SMB_STRUCT_WPASSWD retval;
953 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
958 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
959 retval.pw_passwd = pwret->pw_passwd;
960 retval.pw_uid = pwret->pw_uid;
961 retval.pw_gid = pwret->pw_gid;
962 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
963 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
964 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
969 /**************************************************************************
970 Wide getpwuid. Return a structure pointer containing wide names.
971 ****************************************************************************/
973 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
975 static SMB_STRUCT_WPASSWD retval;
976 struct passwd *pwret = sys_getpwuid(uid);
981 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
982 retval.pw_passwd = pwret->pw_passwd;
983 retval.pw_uid = pwret->pw_uid;
984 retval.pw_gid = pwret->pw_gid;
985 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
986 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
987 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
991 #endif /* NOT CURRENTLY USED - JRA */
993 /**************************************************************************
994 Extract a command into an arg list. Uses a static pstring for storage.
995 Caller frees returned arg list (which contains pointers into the static pstring).
996 ****************************************************************************/
998 static char **extract_args(const char *command)
1000 static pstring trunc_cmd;
1006 pstrcpy(trunc_cmd, command);
1008 if(!(ptr = strtok(trunc_cmd, " \t"))) {
1017 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
1020 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
1024 * Now do the extraction.
1027 pstrcpy(trunc_cmd, command);
1029 ptr = strtok(trunc_cmd, " \t");
1033 while((ptr = strtok(NULL, " \t")) != NULL)
1040 /**************************************************************************
1041 Wrapper for fork. Ensures that mypid is reset. Used so we can write
1042 a sys_getpid() that only does a system call *once*.
1043 ****************************************************************************/
1045 static pid_t mypid = (pid_t)-1;
1047 pid_t sys_fork(void)
1049 pid_t forkret = fork();
1051 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1057 /**************************************************************************
1058 Wrapper for getpid. Ensures we only do a system call *once*.
1059 ****************************************************************************/
1061 pid_t sys_getpid(void)
1063 if (mypid == (pid_t)-1)
1069 /**************************************************************************
1070 Wrapper for popen. Safer as it doesn't search a path.
1071 Modified from the glibc sources.
1072 modified by tridge to return a file descriptor. We must kick our FILE* habit
1073 ****************************************************************************/
1075 typedef struct _popen_list
1079 struct _popen_list *next;
1082 static popen_list *popen_chain;
1084 int sys_popen(const char *command)
1086 int parent_end, child_end;
1088 popen_list *entry = NULL;
1091 if (pipe(pipe_fds) < 0)
1094 parent_end = pipe_fds[0];
1095 child_end = pipe_fds[1];
1102 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1105 ZERO_STRUCTP(entry);
1108 * Extract the command and args into a NULL terminated array.
1111 if(!(argl = extract_args(command)))
1114 entry->child_pid = sys_fork();
1116 if (entry->child_pid == -1) {
1120 if (entry->child_pid == 0) {
1126 int child_std_end = STDOUT_FILENO;
1130 if (child_end != child_std_end) {
1131 dup2 (child_end, child_std_end);
1136 * POSIX.2: "popen() shall ensure that any streams from previous
1137 * popen() calls that remain open in the parent process are closed
1138 * in the new child process."
1141 for (p = popen_chain; p; p = p->next)
1144 execv(argl[0], argl);
1155 /* Link into popen_chain. */
1156 entry->next = popen_chain;
1157 popen_chain = entry;
1158 entry->fd = parent_end;
1171 /**************************************************************************
1172 Wrapper for pclose. Modified from the glibc sources.
1173 ****************************************************************************/
1175 int sys_pclose(int fd)
1178 popen_list **ptr = &popen_chain;
1179 popen_list *entry = NULL;
1183 /* Unlink from popen_chain. */
1184 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1185 if ((*ptr)->fd == fd) {
1187 *ptr = (*ptr)->next;
1193 if (status < 0 || close(entry->fd) < 0)
1197 * As Samba is catching and eating child process
1198 * exits we don't really care about the child exit
1199 * code, a -1 with errno = ECHILD will do fine for us.
1203 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1204 } while (wait_pid == -1 && errno == EINTR);
1213 /**************************************************************************
1214 Wrappers for dlopen, dlsym, dlclose.
1215 ****************************************************************************/
1217 void *sys_dlopen(const char *name, int flags)
1219 #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
1220 return dlopen(name, flags);
1226 void *sys_dlsym(void *handle, char *symbol)
1228 #if defined(HAVE_LIBDL) || defined(HAVE_DLSYM)
1229 return dlsym(handle, symbol);
1235 int sys_dlclose (void *handle)
1237 #if defined(HAVE_LIBDL) || defined(HAVE_DLCLOSE)
1238 return dlclose(handle);
1244 const char *sys_dlerror(void)
1246 #if defined(HAVE_LIBDL) || defined(HAVE_DLERROR)
1253 /**************************************************************************
1254 Wrapper for Admin Logs.
1255 ****************************************************************************/
1257 void sys_adminlog(int priority, const char *format_str, ...)
1261 char **msgbuf = NULL;
1263 if (!lp_admin_log())
1266 va_start( ap, format_str );
1267 ret = vasprintf( msgbuf, format_str, ap );
1273 #if defined(HAVE_SYSLOG)
1274 syslog( priority, "%s", *msgbuf );
1276 DEBUG(0,("%s", *msgbuf ));