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 The wait() calls vary between systems
259 ********************************************************************/
261 int sys_waitpid(pid_t pid,int *status,int options)
264 return waitpid(pid,status,options);
265 #else /* HAVE_WAITPID */
266 return wait4(pid, status, options, NULL);
267 #endif /* HAVE_WAITPID */
270 /*******************************************************************
271 System wrapper for getwd
272 ********************************************************************/
274 char *sys_getwd(char *s)
278 wd = (char *)getcwd(s, sizeof (pstring));
280 wd = (char *)getwd(s);
285 /*******************************************************************
286 system wrapper for symlink
287 ********************************************************************/
289 int sys_symlink(const char *oldpath, const char *newpath)
295 return symlink(oldpath, newpath);
299 /*******************************************************************
300 system wrapper for readlink
301 ********************************************************************/
303 int sys_readlink(const char *path, char *buf, size_t bufsiz)
305 #ifndef HAVE_READLINK
309 return readlink(path, buf, bufsiz);
313 /*******************************************************************
314 system wrapper for link
315 ********************************************************************/
317 int sys_link(const char *oldpath, const char *newpath)
323 return link(oldpath, newpath);
327 /*******************************************************************
328 chown isn't used much but OS/2 doesn't have it
329 ********************************************************************/
331 int sys_chown(const char *fname,uid_t uid,gid_t gid)
336 DEBUG(1,("WARNING: no chown!\n"));
340 return(chown(fname,uid,gid));
344 /*******************************************************************
345 os/2 also doesn't have chroot
346 ********************************************************************/
347 int sys_chroot(const char *dname)
352 DEBUG(1,("WARNING: no chroot!\n"));
358 return(chroot(dname));
362 /**************************************************************************
363 A wrapper for gethostbyname() that tries avoids looking up hostnames
364 in the root domain, which can cause dial-on-demand links to come up for no
366 ****************************************************************************/
368 struct hostent *sys_gethostbyname(const char *name)
370 #ifdef REDUCE_ROOT_DNS_LOOKUPS
371 char query[256], hostname[256];
374 /* Does this name have any dots in it? If so, make no change */
376 if (strchr_m(name, '.'))
377 return(gethostbyname(name));
379 /* Get my hostname, which should have domain name
380 attached. If not, just do the gethostname on the
384 gethostname(hostname, sizeof(hostname) - 1);
385 hostname[sizeof(hostname) - 1] = 0;
386 if ((domain = strchr_m(hostname, '.')) == NULL)
387 return(gethostbyname(name));
389 /* Attach domain name to query and do modified query.
390 If names too large, just do gethostname on the
394 if((strlen(name) + strlen(domain)) >= sizeof(query))
395 return(gethostbyname(name));
397 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
398 return(gethostbyname(query));
399 #else /* REDUCE_ROOT_DNS_LOOKUPS */
400 return(gethostbyname(name));
401 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
405 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
406 /**************************************************************************
407 Try and abstract process capabilities (for systems that have them).
408 ****************************************************************************/
409 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
411 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
412 cap_t cap = cap_get_proc();
415 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
421 cap->cap_effective |= CAP_NETWORK_MGT;
423 cap->cap_effective &= ~CAP_NETWORK_MGT;
425 if (cap_set_proc(cap) == -1) {
426 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
434 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
439 /**************************************************************************
440 Try and abstract inherited process capabilities (for systems that have them).
441 ****************************************************************************/
443 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
445 if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
446 cap_t cap = cap_get_proc();
449 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
455 cap->cap_inheritable |= CAP_NETWORK_MGT;
457 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
459 if (cap_set_proc(cap) == -1) {
460 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
468 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
474 /****************************************************************************
475 Gain the oplock capability from the kernel if possible.
476 ****************************************************************************/
478 void oplock_set_capability(BOOL this_process, BOOL inherit)
480 #if HAVE_KERNEL_OPLOCKS_IRIX
481 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
482 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
486 /**************************************************************************
487 Wrapper for random().
488 ****************************************************************************/
490 long sys_random(void)
492 #if defined(HAVE_RANDOM)
493 return (long)random();
494 #elif defined(HAVE_RAND)
497 DEBUG(0,("Error - no random function available !\n"));
502 /**************************************************************************
503 Wrapper for srandom().
504 ****************************************************************************/
506 void sys_srandom(unsigned int seed)
508 #if defined(HAVE_SRANDOM)
510 #elif defined(HAVE_SRAND)
513 DEBUG(0,("Error - no srandom function available !\n"));
518 /**************************************************************************
519 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
520 ****************************************************************************/
524 #if defined(SYSCONF_SC_NGROUPS_MAX)
525 int ret = sysconf(_SC_NGROUPS_MAX);
526 return (ret == -1) ? NGROUPS_MAX : ret;
532 /**************************************************************************
533 Wrapper for getgroups. Deals with broken (int) case.
534 ****************************************************************************/
536 int sys_getgroups(int setlen, gid_t *gidset)
538 #if !defined(HAVE_BROKEN_GETGROUPS)
539 return getgroups(setlen, gidset);
547 return getgroups(setlen, &gid);
551 * Broken case. We need to allocate a
552 * GID_T array of size setlen.
561 setlen = groups_max();
563 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
564 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
568 if((ngroups = getgroups(setlen, group_list)) < 0) {
569 int saved_errno = errno;
570 SAFE_FREE(group_list);
575 for(i = 0; i < ngroups; i++)
576 gidset[i] = (gid_t)group_list[i];
578 SAFE_FREE(group_list);
580 #endif /* HAVE_BROKEN_GETGROUPS */
583 #ifdef HAVE_SETGROUPS
585 /**************************************************************************
586 Wrapper for setgroups. Deals with broken (int) case. Automatically used
587 if we have broken getgroups.
588 ****************************************************************************/
590 int sys_setgroups(int setlen, gid_t *gidset)
592 #if !defined(HAVE_BROKEN_GETGROUPS)
593 return setgroups(setlen, gidset);
602 if (setlen < 0 || setlen > groups_max()) {
608 * Broken case. We need to allocate a
609 * GID_T array of size setlen.
612 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
613 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
617 for(i = 0; i < setlen; i++)
618 group_list[i] = (GID_T) gidset[i];
620 if(setgroups(setlen, group_list) != 0) {
621 int saved_errno = errno;
622 SAFE_FREE(group_list);
627 SAFE_FREE(group_list);
629 #endif /* HAVE_BROKEN_GETGROUPS */
632 #endif /* HAVE_SETGROUPS */
635 * We only wrap pw_name and pw_passwd for now as these
636 * are the only potentially modified fields.
639 /**************************************************************************
640 Helper function for getpwnam/getpwuid wrappers.
641 ****************************************************************************/
652 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
653 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
655 static int num_lookups; /* Counter so we don't always use cache. */
656 #ifndef PW_RET_CACHE_MAX_LOOKUPS
657 #define PW_RET_CACHE_MAX_LOOKUPS 100
660 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
662 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
664 fstrcpy(dst->pw_name, pass->pw_name);
665 dst->pass.pw_name = dst->pw_name;
667 fstrcpy(dst->pw_passwd, pass->pw_passwd);
668 dst->pass.pw_passwd = dst->pw_passwd;
670 fstrcpy(dst->pw_gecos, pass->pw_gecos);
671 dst->pass.pw_gecos = dst->pw_gecos;
673 pstrcpy(dst->pw_dir, pass->pw_dir);
674 dst->pass.pw_dir = dst->pw_dir;
676 pstrcpy(dst->pw_shell, pass->pw_shell);
677 dst->pass.pw_shell = dst->pw_shell;
680 static struct passwd *setup_pwret(struct passwd *pass)
683 /* Clear the caches. */
684 memset(&pw_cache, '\0', sizeof(struct saved_pw));
685 memset(&pw_mod, '\0', sizeof(struct saved_pw));
690 copy_pwent( &pw_mod, pass);
692 if (pass != &pw_cache.pass) {
694 /* If it's a cache miss we must also refill the cache. */
696 copy_pwent( &pw_cache, pass);
704 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
710 /**************************************************************************
711 Wrappers for setpwent(), getpwent() and endpwent()
712 ****************************************************************************/
714 void sys_setpwent(void)
716 setup_pwret(NULL); /* Clear cache. */
720 struct passwd *sys_getpwent(void)
722 return setup_pwret(getpwent());
725 void sys_endpwent(void)
727 setup_pwret(NULL); /* Clear cache. */
731 /**************************************************************************
732 Wrapper for getpwnam(). Always returns a static that can be modified.
733 ****************************************************************************/
735 struct passwd *sys_getpwnam(const char *name)
737 if (!name || !name[0])
740 /* check for a cache hit first */
741 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
742 return setup_pwret(&pw_cache.pass);
745 return setup_pwret(getpwnam(name));
748 /**************************************************************************
749 Wrapper for getpwuid(). Always returns a static that can be modified.
750 ****************************************************************************/
752 struct passwd *sys_getpwuid(uid_t uid)
754 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
755 return setup_pwret(&pw_cache.pass);
758 return setup_pwret(getpwuid(uid));
761 #if 0 /* NOT CURRENTLY USED - JRA */
762 /**************************************************************************
763 The following are the UNICODE versions of *all* system interface functions
764 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
765 which currently are left as ascii as they are not used other than in name
767 ****************************************************************************/
769 /**************************************************************************
770 Wide stat. Just narrow and call sys_xxx.
771 ****************************************************************************/
773 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
776 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
779 /**************************************************************************
780 Wide lstat. Just narrow and call sys_xxx.
781 ****************************************************************************/
783 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
786 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
789 /**************************************************************************
790 Wide creat. Just narrow and call sys_xxx.
791 ****************************************************************************/
793 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
796 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
799 /**************************************************************************
800 Wide open. Just narrow and call sys_xxx.
801 ****************************************************************************/
803 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
806 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
809 /**************************************************************************
810 Wide fopen. Just narrow and call sys_xxx.
811 ****************************************************************************/
813 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
816 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
819 /**************************************************************************
820 Wide opendir. Just narrow and call sys_xxx.
821 ****************************************************************************/
823 DIR *wsys_opendir(const smb_ucs2_t *wfname)
826 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
829 /**************************************************************************
830 Wide readdir. Return a structure pointer containing a wide filename.
831 ****************************************************************************/
833 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
835 static SMB_STRUCT_WDIRENT retval;
836 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
842 * The only POSIX defined member of this struct is d_name.
845 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
850 /**************************************************************************
851 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
852 ****************************************************************************/
854 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
857 char *p = sys_getwd(fname);
862 return unix_to_unicode(s, p, sizeof(wpstring));
865 /**************************************************************************
866 Wide chown. Just narrow and call sys_xxx.
867 ****************************************************************************/
869 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
872 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
875 /**************************************************************************
876 Wide chroot. Just narrow and call sys_xxx.
877 ****************************************************************************/
879 int wsys_chroot(const smb_ucs2_t *wfname)
882 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
885 /**************************************************************************
886 Wide getpwnam. Return a structure pointer containing wide names.
887 ****************************************************************************/
889 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
891 static SMB_STRUCT_WPASSWD retval;
893 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
898 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
899 retval.pw_passwd = pwret->pw_passwd;
900 retval.pw_uid = pwret->pw_uid;
901 retval.pw_gid = pwret->pw_gid;
902 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
903 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
904 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
909 /**************************************************************************
910 Wide getpwuid. Return a structure pointer containing wide names.
911 ****************************************************************************/
913 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
915 static SMB_STRUCT_WPASSWD retval;
916 struct passwd *pwret = sys_getpwuid(uid);
921 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
922 retval.pw_passwd = pwret->pw_passwd;
923 retval.pw_uid = pwret->pw_uid;
924 retval.pw_gid = pwret->pw_gid;
925 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
926 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
927 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
931 #endif /* NOT CURRENTLY USED - JRA */
933 /**************************************************************************
934 Extract a command into an arg list. Uses a static pstring for storage.
935 Caller frees returned arg list (which contains pointers into the static pstring).
936 ****************************************************************************/
938 static char **extract_args(const char *command)
940 static pstring trunc_cmd;
946 pstrcpy(trunc_cmd, command);
948 if(!(ptr = strtok(trunc_cmd, " \t"))) {
957 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
960 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
964 * Now do the extraction.
967 pstrcpy(trunc_cmd, command);
969 ptr = strtok(trunc_cmd, " \t");
973 while((ptr = strtok(NULL, " \t")) != NULL)
980 /**************************************************************************
981 Wrapper for fork. Ensures that mypid is reset. Used so we can write
982 a sys_getpid() that only does a system call *once*.
983 ****************************************************************************/
985 static pid_t mypid = (pid_t)-1;
989 pid_t forkret = fork();
991 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
997 /**************************************************************************
998 Wrapper for getpid. Ensures we only do a system call *once*.
999 ****************************************************************************/
1001 pid_t sys_getpid(void)
1003 if (mypid == (pid_t)-1)
1009 /**************************************************************************
1010 Wrapper for popen. Safer as it doesn't search a path.
1011 Modified from the glibc sources.
1012 modified by tridge to return a file descriptor. We must kick our FILE* habit
1013 ****************************************************************************/
1015 typedef struct _popen_list
1019 struct _popen_list *next;
1022 static popen_list *popen_chain;
1024 int sys_popen(const char *command)
1026 int parent_end, child_end;
1028 popen_list *entry = NULL;
1031 if (pipe(pipe_fds) < 0)
1034 parent_end = pipe_fds[0];
1035 child_end = pipe_fds[1];
1042 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1045 ZERO_STRUCTP(entry);
1048 * Extract the command and args into a NULL terminated array.
1051 if(!(argl = extract_args(command)))
1054 entry->child_pid = sys_fork();
1056 if (entry->child_pid == -1) {
1060 if (entry->child_pid == 0) {
1066 int child_std_end = STDOUT_FILENO;
1070 if (child_end != child_std_end) {
1071 dup2 (child_end, child_std_end);
1076 * POSIX.2: "popen() shall ensure that any streams from previous
1077 * popen() calls that remain open in the parent process are closed
1078 * in the new child process."
1081 for (p = popen_chain; p; p = p->next)
1084 execv(argl[0], argl);
1095 /* Link into popen_chain. */
1096 entry->next = popen_chain;
1097 popen_chain = entry;
1098 entry->fd = parent_end;
1111 /**************************************************************************
1112 Wrapper for pclose. Modified from the glibc sources.
1113 ****************************************************************************/
1115 int sys_pclose(int fd)
1118 popen_list **ptr = &popen_chain;
1119 popen_list *entry = NULL;
1123 /* Unlink from popen_chain. */
1124 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1125 if ((*ptr)->fd == fd) {
1127 *ptr = (*ptr)->next;
1133 if (status < 0 || close(entry->fd) < 0)
1137 * As Samba is catching and eating child process
1138 * exits we don't really care about the child exit
1139 * code, a -1 with errno = ECHILD will do fine for us.
1143 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1144 } while (wait_pid == -1 && errno == EINTR);
1153 /**************************************************************************
1154 Wrappers for dlopen, dlsym, dlclose.
1155 ****************************************************************************/
1157 void *sys_dlopen(const char *name, int flags)
1160 return dlopen(name, flags);
1166 void *sys_dlsym(void *handle, char *symbol)
1169 return dlsym(handle, symbol);
1175 int sys_dlclose (void *handle)
1178 return dlclose(handle);
1184 const char *sys_dlerror(void)