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 stat() wrapper that will deal with 64 bit filesizes.
77 ********************************************************************/
79 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
82 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
83 ret = stat64(fname, sbuf);
85 ret = stat(fname, sbuf);
87 /* we always want directories to appear zero size */
88 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
92 /*******************************************************************
93 An fstat() wrapper that will deal with 64 bit filesizes.
94 ********************************************************************/
96 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
99 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
100 ret = fstat64(fd, sbuf);
102 ret = fstat(fd, sbuf);
104 /* we always want directories to appear zero size */
105 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
109 /*******************************************************************
110 An lstat() wrapper that will deal with 64 bit filesizes.
111 ********************************************************************/
113 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
116 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
117 ret = lstat64(fname, sbuf);
119 ret = lstat(fname, sbuf);
121 /* we always want directories to appear zero size */
122 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
126 /*******************************************************************
127 An ftruncate() wrapper that will deal with 64 bit filesizes.
128 ********************************************************************/
130 int sys_ftruncate(int fd, SMB_OFF_T offset)
132 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
133 return ftruncate64(fd, offset);
135 return ftruncate(fd, offset);
139 /*******************************************************************
140 An lseek() wrapper that will deal with 64 bit filesizes.
141 ********************************************************************/
143 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
145 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
146 return lseek64(fd, offset, whence);
148 return lseek(fd, offset, whence);
152 /*******************************************************************
153 An fseek() wrapper that will deal with 64 bit filesizes.
154 ********************************************************************/
156 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
158 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
159 return fseek64(fp, offset, whence);
160 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
161 return fseeko64(fp, offset, whence);
163 return fseek(fp, offset, whence);
167 /*******************************************************************
168 An ftell() wrapper that will deal with 64 bit filesizes.
169 ********************************************************************/
171 SMB_OFF_T sys_ftell(FILE *fp)
173 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
174 return (SMB_OFF_T)ftell64(fp);
175 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
176 return (SMB_OFF_T)ftello64(fp);
178 return (SMB_OFF_T)ftell(fp);
182 /*******************************************************************
183 A creat() wrapper that will deal with 64 bit filesizes.
184 ********************************************************************/
186 int sys_creat(const char *path, mode_t mode)
188 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
189 return creat64(path, mode);
192 * If creat64 isn't defined then ensure we call a potential open64.
195 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
199 /*******************************************************************
200 An open() wrapper that will deal with 64 bit filesizes.
201 ********************************************************************/
203 int sys_open(const char *path, int oflag, mode_t mode)
205 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
206 return open64(path, oflag, mode);
208 return open(path, oflag, mode);
212 /*******************************************************************
213 An fopen() wrapper that will deal with 64 bit filesizes.
214 ********************************************************************/
216 FILE *sys_fopen(const char *path, const char *type)
218 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
219 return fopen64(path, type);
221 return fopen(path, type);
225 /*******************************************************************
226 A readdir wrapper that will deal with 64 bit filesizes.
227 ********************************************************************/
229 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
231 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
232 return readdir64(dirp);
234 return readdir(dirp);
238 /*******************************************************************
239 An mknod() wrapper that will deal with 64 bit filesizes.
240 ********************************************************************/
242 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
244 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
245 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
246 return mknod64(path, mode, dev);
248 return mknod(path, mode, dev);
251 /* No mknod system call. */
257 /*******************************************************************
258 Wrapper for realpath.
259 ********************************************************************/
261 char *sys_realpath(const char *path, char *resolved_path)
263 #if defined(HAVE_REALPATH)
264 return realpath(path, resolved_path);
266 /* As realpath is not a system call we can't return ENOSYS. */
272 /*******************************************************************
273 The wait() calls vary between systems
274 ********************************************************************/
276 int sys_waitpid(pid_t pid,int *status,int options)
279 return waitpid(pid,status,options);
280 #else /* HAVE_WAITPID */
281 return wait4(pid, status, options, NULL);
282 #endif /* HAVE_WAITPID */
285 /*******************************************************************
286 System wrapper for getwd
287 ********************************************************************/
289 char *sys_getwd(char *s)
293 wd = (char *)getcwd(s, sizeof (pstring));
295 wd = (char *)getwd(s);
300 /*******************************************************************
301 system wrapper for symlink
302 ********************************************************************/
304 int sys_symlink(const char *oldpath, const char *newpath)
310 return symlink(oldpath, newpath);
314 /*******************************************************************
315 system wrapper for readlink
316 ********************************************************************/
318 int sys_readlink(const char *path, char *buf, size_t bufsiz)
320 #ifndef HAVE_READLINK
324 return readlink(path, buf, bufsiz);
328 /*******************************************************************
329 system wrapper for link
330 ********************************************************************/
332 int sys_link(const char *oldpath, const char *newpath)
338 return link(oldpath, newpath);
342 /*******************************************************************
343 chown isn't used much but OS/2 doesn't have it
344 ********************************************************************/
346 int sys_chown(const char *fname,uid_t uid,gid_t gid)
351 DEBUG(1,("WARNING: no chown!\n"));
355 return(chown(fname,uid,gid));
359 /*******************************************************************
360 os/2 also doesn't have chroot
361 ********************************************************************/
362 int sys_chroot(const char *dname)
367 DEBUG(1,("WARNING: no chroot!\n"));
373 return(chroot(dname));
377 /**************************************************************************
378 A wrapper for gethostbyname() that tries avoids looking up hostnames
379 in the root domain, which can cause dial-on-demand links to come up for no
381 ****************************************************************************/
383 struct hostent *sys_gethostbyname(const char *name)
385 #ifdef REDUCE_ROOT_DNS_LOOKUPS
386 char query[256], hostname[256];
389 /* Does this name have any dots in it? If so, make no change */
391 if (strchr_m(name, '.'))
392 return(gethostbyname(name));
394 /* Get my hostname, which should have domain name
395 attached. If not, just do the gethostname on the
399 gethostname(hostname, sizeof(hostname) - 1);
400 hostname[sizeof(hostname) - 1] = 0;
401 if ((domain = strchr_m(hostname, '.')) == NULL)
402 return(gethostbyname(name));
404 /* Attach domain name to query and do modified query.
405 If names too large, just do gethostname on the
409 if((strlen(name) + strlen(domain)) >= sizeof(query))
410 return(gethostbyname(name));
412 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
413 return(gethostbyname(query));
414 #else /* REDUCE_ROOT_DNS_LOOKUPS */
415 return(gethostbyname(name));
416 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
420 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
421 /**************************************************************************
422 Try and abstract process capabilities (for systems that have them).
423 ****************************************************************************/
424 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
426 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
427 cap_t cap = cap_get_proc();
430 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
436 cap->cap_effective |= CAP_NETWORK_MGT;
438 cap->cap_effective &= ~CAP_NETWORK_MGT;
440 if (cap_set_proc(cap) == -1) {
441 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
449 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
454 /**************************************************************************
455 Try and abstract inherited process capabilities (for systems that have them).
456 ****************************************************************************/
458 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
460 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
461 cap_t cap = cap_get_proc();
464 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
470 cap->cap_inheritable |= CAP_NETWORK_MGT;
472 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
474 if (cap_set_proc(cap) == -1) {
475 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
483 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
489 /****************************************************************************
490 Gain the oplock capability from the kernel if possible.
491 ****************************************************************************/
493 void oplock_set_capability(BOOL this_process, BOOL inherit)
495 #if HAVE_KERNEL_OPLOCKS_IRIX
496 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
497 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
501 /**************************************************************************
502 Wrapper for random().
503 ****************************************************************************/
505 long sys_random(void)
507 #if defined(HAVE_RANDOM)
508 return (long)random();
509 #elif defined(HAVE_RAND)
512 DEBUG(0,("Error - no random function available !\n"));
517 /**************************************************************************
518 Wrapper for srandom().
519 ****************************************************************************/
521 void sys_srandom(unsigned int seed)
523 #if defined(HAVE_SRANDOM)
525 #elif defined(HAVE_SRAND)
528 DEBUG(0,("Error - no srandom function available !\n"));
533 /**************************************************************************
534 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
535 ****************************************************************************/
539 #if defined(SYSCONF_SC_NGROUPS_MAX)
540 int ret = sysconf(_SC_NGROUPS_MAX);
541 return (ret == -1) ? NGROUPS_MAX : ret;
547 /**************************************************************************
548 Wrapper for getgroups. Deals with broken (int) case.
549 ****************************************************************************/
551 int sys_getgroups(int setlen, gid_t *gidset)
553 #if !defined(HAVE_BROKEN_GETGROUPS)
554 return getgroups(setlen, gidset);
562 return getgroups(setlen, &gid);
566 * Broken case. We need to allocate a
567 * GID_T array of size setlen.
576 setlen = groups_max();
578 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
579 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
583 if((ngroups = getgroups(setlen, group_list)) < 0) {
584 int saved_errno = errno;
585 SAFE_FREE(group_list);
590 for(i = 0; i < ngroups; i++)
591 gidset[i] = (gid_t)group_list[i];
593 SAFE_FREE(group_list);
595 #endif /* HAVE_BROKEN_GETGROUPS */
598 #ifdef HAVE_SETGROUPS
600 /**************************************************************************
601 Wrapper for setgroups. Deals with broken (int) case. Automatically used
602 if we have broken getgroups.
603 ****************************************************************************/
605 int sys_setgroups(int setlen, gid_t *gidset)
607 #if !defined(HAVE_BROKEN_GETGROUPS)
608 return setgroups(setlen, gidset);
617 if (setlen < 0 || setlen > groups_max()) {
623 * Broken case. We need to allocate a
624 * GID_T array of size setlen.
627 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
628 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
632 for(i = 0; i < setlen; i++)
633 group_list[i] = (GID_T) gidset[i];
635 if(setgroups(setlen, group_list) != 0) {
636 int saved_errno = errno;
637 SAFE_FREE(group_list);
642 SAFE_FREE(group_list);
644 #endif /* HAVE_BROKEN_GETGROUPS */
647 #endif /* HAVE_SETGROUPS */
650 * We only wrap pw_name and pw_passwd for now as these
651 * are the only potentially modified fields.
654 /**************************************************************************
655 Helper function for getpwnam/getpwuid wrappers.
656 ****************************************************************************/
667 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
668 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
670 static int num_lookups; /* Counter so we don't always use cache. */
671 #ifndef PW_RET_CACHE_MAX_LOOKUPS
672 #define PW_RET_CACHE_MAX_LOOKUPS 100
675 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
677 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
679 fstrcpy(dst->pw_name, pass->pw_name);
680 dst->pass.pw_name = dst->pw_name;
682 fstrcpy(dst->pw_passwd, pass->pw_passwd);
683 dst->pass.pw_passwd = dst->pw_passwd;
685 fstrcpy(dst->pw_gecos, pass->pw_gecos);
686 dst->pass.pw_gecos = dst->pw_gecos;
688 pstrcpy(dst->pw_dir, pass->pw_dir);
689 dst->pass.pw_dir = dst->pw_dir;
691 pstrcpy(dst->pw_shell, pass->pw_shell);
692 dst->pass.pw_shell = dst->pw_shell;
695 static struct passwd *setup_pwret(struct passwd *pass)
698 /* Clear the caches. */
699 memset(&pw_cache, '\0', sizeof(struct saved_pw));
700 memset(&pw_mod, '\0', sizeof(struct saved_pw));
705 copy_pwent( &pw_mod, pass);
707 if (pass != &pw_cache.pass) {
709 /* If it's a cache miss we must also refill the cache. */
711 copy_pwent( &pw_cache, pass);
719 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
725 /**************************************************************************
726 Wrappers for setpwent(), getpwent() and endpwent()
727 ****************************************************************************/
729 void sys_setpwent(void)
731 setup_pwret(NULL); /* Clear cache. */
735 struct passwd *sys_getpwent(void)
737 return setup_pwret(getpwent());
740 void sys_endpwent(void)
742 setup_pwret(NULL); /* Clear cache. */
746 /**************************************************************************
747 Wrapper for getpwnam(). Always returns a static that can be modified.
748 ****************************************************************************/
750 struct passwd *sys_getpwnam(const char *name)
752 if (!name || !name[0])
755 /* check for a cache hit first */
756 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
757 return setup_pwret(&pw_cache.pass);
760 return setup_pwret(getpwnam(name));
763 /**************************************************************************
764 Wrapper for getpwuid(). Always returns a static that can be modified.
765 ****************************************************************************/
767 struct passwd *sys_getpwuid(uid_t uid)
769 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
770 return setup_pwret(&pw_cache.pass);
773 return setup_pwret(getpwuid(uid));
776 #if 0 /* NOT CURRENTLY USED - JRA */
777 /**************************************************************************
778 The following are the UNICODE versions of *all* system interface functions
779 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
780 which currently are left as ascii as they are not used other than in name
782 ****************************************************************************/
784 /**************************************************************************
785 Wide stat. Just narrow and call sys_xxx.
786 ****************************************************************************/
788 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
791 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
794 /**************************************************************************
795 Wide lstat. Just narrow and call sys_xxx.
796 ****************************************************************************/
798 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
801 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
804 /**************************************************************************
805 Wide creat. Just narrow and call sys_xxx.
806 ****************************************************************************/
808 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
811 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
814 /**************************************************************************
815 Wide open. Just narrow and call sys_xxx.
816 ****************************************************************************/
818 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
821 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
824 /**************************************************************************
825 Wide fopen. Just narrow and call sys_xxx.
826 ****************************************************************************/
828 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
831 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
834 /**************************************************************************
835 Wide opendir. Just narrow and call sys_xxx.
836 ****************************************************************************/
838 DIR *wsys_opendir(const smb_ucs2_t *wfname)
841 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
844 /**************************************************************************
845 Wide readdir. Return a structure pointer containing a wide filename.
846 ****************************************************************************/
848 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
850 static SMB_STRUCT_WDIRENT retval;
851 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
857 * The only POSIX defined member of this struct is d_name.
860 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
865 /**************************************************************************
866 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
867 ****************************************************************************/
869 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
872 char *p = sys_getwd(fname);
877 return unix_to_unicode(s, p, sizeof(wpstring));
880 /**************************************************************************
881 Wide chown. Just narrow and call sys_xxx.
882 ****************************************************************************/
884 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
887 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
890 /**************************************************************************
891 Wide chroot. Just narrow and call sys_xxx.
892 ****************************************************************************/
894 int wsys_chroot(const smb_ucs2_t *wfname)
897 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
900 /**************************************************************************
901 Wide getpwnam. Return a structure pointer containing wide names.
902 ****************************************************************************/
904 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
906 static SMB_STRUCT_WPASSWD retval;
908 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
913 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
914 retval.pw_passwd = pwret->pw_passwd;
915 retval.pw_uid = pwret->pw_uid;
916 retval.pw_gid = pwret->pw_gid;
917 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
918 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
919 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
924 /**************************************************************************
925 Wide getpwuid. Return a structure pointer containing wide names.
926 ****************************************************************************/
928 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
930 static SMB_STRUCT_WPASSWD retval;
931 struct passwd *pwret = sys_getpwuid(uid);
936 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
937 retval.pw_passwd = pwret->pw_passwd;
938 retval.pw_uid = pwret->pw_uid;
939 retval.pw_gid = pwret->pw_gid;
940 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
941 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
942 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
946 #endif /* NOT CURRENTLY USED - JRA */
948 /**************************************************************************
949 Extract a command into an arg list. Uses a static pstring for storage.
950 Caller frees returned arg list (which contains pointers into the static pstring).
951 ****************************************************************************/
953 static char **extract_args(const char *command)
955 static pstring trunc_cmd;
961 pstrcpy(trunc_cmd, command);
963 if(!(ptr = strtok(trunc_cmd, " \t"))) {
972 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
975 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
979 * Now do the extraction.
982 pstrcpy(trunc_cmd, command);
984 ptr = strtok(trunc_cmd, " \t");
988 while((ptr = strtok(NULL, " \t")) != NULL)
995 /**************************************************************************
996 Wrapper for fork. Ensures that mypid is reset. Used so we can write
997 a sys_getpid() that only does a system call *once*.
998 ****************************************************************************/
1000 static pid_t mypid = (pid_t)-1;
1002 pid_t sys_fork(void)
1004 pid_t forkret = fork();
1006 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1012 /**************************************************************************
1013 Wrapper for getpid. Ensures we only do a system call *once*.
1014 ****************************************************************************/
1016 pid_t sys_getpid(void)
1018 if (mypid == (pid_t)-1)
1024 /**************************************************************************
1025 Wrapper for popen. Safer as it doesn't search a path.
1026 Modified from the glibc sources.
1027 modified by tridge to return a file descriptor. We must kick our FILE* habit
1028 ****************************************************************************/
1030 typedef struct _popen_list
1034 struct _popen_list *next;
1037 static popen_list *popen_chain;
1039 int sys_popen(const char *command)
1041 int parent_end, child_end;
1043 popen_list *entry = NULL;
1046 if (pipe(pipe_fds) < 0)
1049 parent_end = pipe_fds[0];
1050 child_end = pipe_fds[1];
1057 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1060 ZERO_STRUCTP(entry);
1063 * Extract the command and args into a NULL terminated array.
1066 if(!(argl = extract_args(command)))
1069 entry->child_pid = sys_fork();
1071 if (entry->child_pid == -1) {
1075 if (entry->child_pid == 0) {
1081 int child_std_end = STDOUT_FILENO;
1085 if (child_end != child_std_end) {
1086 dup2 (child_end, child_std_end);
1091 * POSIX.2: "popen() shall ensure that any streams from previous
1092 * popen() calls that remain open in the parent process are closed
1093 * in the new child process."
1096 for (p = popen_chain; p; p = p->next)
1099 execv(argl[0], argl);
1110 /* Link into popen_chain. */
1111 entry->next = popen_chain;
1112 popen_chain = entry;
1113 entry->fd = parent_end;
1126 /**************************************************************************
1127 Wrapper for pclose. Modified from the glibc sources.
1128 ****************************************************************************/
1130 int sys_pclose(int fd)
1133 popen_list **ptr = &popen_chain;
1134 popen_list *entry = NULL;
1138 /* Unlink from popen_chain. */
1139 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1140 if ((*ptr)->fd == fd) {
1142 *ptr = (*ptr)->next;
1148 if (status < 0 || close(entry->fd) < 0)
1152 * As Samba is catching and eating child process
1153 * exits we don't really care about the child exit
1154 * code, a -1 with errno = ECHILD will do fine for us.
1158 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1159 } while (wait_pid == -1 && errno == EINTR);
1168 /**************************************************************************
1169 Wrappers for dlopen, dlsym, dlclose.
1170 ****************************************************************************/
1172 void *sys_dlopen(const char *name, int flags)
1174 #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN)
1175 return dlopen(name, flags);
1181 void *sys_dlsym(void *handle, char *symbol)
1183 #if defined(HAVE_LIBDL) || defined(HAVE_DLSYM)
1184 return dlsym(handle, symbol);
1190 int sys_dlclose (void *handle)
1192 #if defined(HAVE_LIBDL) || defined(HAVE_DLCLOSE)
1193 return dlclose(handle);
1199 const char *sys_dlerror(void)
1201 #if defined(HAVE_LIBDL) || defined(HAVE_DLERROR)
1208 /**************************************************************************
1209 Wrapper for Admin Logs.
1210 ****************************************************************************/
1212 void sys_adminlog(int priority, const char *format_str, ...)
1216 char **msgbuf = NULL;
1218 if (!lp_admin_log())
1221 va_start( ap, format_str );
1222 ret = vasprintf( msgbuf, format_str, ap );
1228 #if defined(HAVE_SYSLOG)
1229 syslog( priority, "%s", *msgbuf );
1231 DEBUG(0,("%s", *msgbuf ));