2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1998
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.
24 extern int DEBUGLEVEL;
27 The idea is that this file will eventually have wrappers around all
28 important system calls in samba. The aims are:
30 - to enable easier porting by putting OS dependent stuff in here
32 - to allow for hooks into other "pseudo-filesystems"
34 - to allow easier integration of things like the japanese extensions
36 - to support the philosophy of Samba to expose the features of
37 the OS within the SMB model. In general whatever file/printer/variable
38 expansions/etc make sense to the OS should be acceptable to Samba.
43 /*******************************************************************
44 A wrapper for usleep in case we don't have one.
45 ********************************************************************/
47 int sys_usleep(long usecs)
54 * We need this braindamage as the glibc usleep
55 * is not SPEC1170 complient... grumble... JRA.
58 if(usecs < 0 || usecs > 1000000) {
66 #else /* HAVE_USLEEP */
68 * Fake it with select...
71 tval.tv_usec = usecs/1000;
72 select(0,NULL,NULL,NULL,&tval);
74 #endif /* HAVE_USLEEP */
77 /*******************************************************************
78 A stat() wrapper that will deal with 64 bit filesizes.
79 ********************************************************************/
81 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
84 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
85 ret = stat64(fname, sbuf);
87 ret = stat(fname, sbuf);
89 /* we always want directories to appear zero size */
90 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
94 /*******************************************************************
95 An fstat() wrapper that will deal with 64 bit filesizes.
96 ********************************************************************/
98 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
101 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
102 ret = fstat64(fd, sbuf);
104 ret = fstat(fd, sbuf);
106 /* we always want directories to appear zero size */
107 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
111 /*******************************************************************
112 An lstat() wrapper that will deal with 64 bit filesizes.
113 ********************************************************************/
115 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
118 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
119 ret = lstat64(fname, sbuf);
121 ret = lstat(fname, sbuf);
123 /* we always want directories to appear zero size */
124 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
128 /*******************************************************************
129 An ftruncate() wrapper that will deal with 64 bit filesizes.
130 ********************************************************************/
132 int sys_ftruncate(int fd, SMB_OFF_T offset)
134 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
135 return ftruncate64(fd, offset);
137 return ftruncate(fd, offset);
141 /*******************************************************************
142 An lseek() wrapper that will deal with 64 bit filesizes.
143 ********************************************************************/
145 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
147 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
148 return lseek64(fd, offset, whence);
150 return lseek(fd, offset, whence);
154 /*******************************************************************
155 An fseek() wrapper that will deal with 64 bit filesizes.
156 ********************************************************************/
158 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
160 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
161 return fseek64(fp, offset, whence);
162 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
163 return fseeko64(fp, offset, whence);
165 return fseek(fp, offset, whence);
169 /*******************************************************************
170 An ftell() wrapper that will deal with 64 bit filesizes.
171 ********************************************************************/
173 SMB_OFF_T sys_ftell(FILE *fp)
175 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
176 return (SMB_OFF_T)ftell64(fp);
177 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
178 return (SMB_OFF_T)ftello64(fp);
180 return (SMB_OFF_T)ftell(fp);
184 /*******************************************************************
185 A creat() wrapper that will deal with 64 bit filesizes.
186 ********************************************************************/
188 int sys_creat(const char *path, mode_t mode)
190 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
191 return creat64(path, mode);
194 * If creat64 isn't defined then ensure we call a potential open64.
197 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
201 /*******************************************************************
202 An open() wrapper that will deal with 64 bit filesizes.
203 ********************************************************************/
205 int sys_open(const char *path, int oflag, mode_t mode)
207 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
208 return open64(path, oflag, mode);
210 return open(path, oflag, mode);
214 /*******************************************************************
215 An fopen() wrapper that will deal with 64 bit filesizes.
216 ********************************************************************/
218 FILE *sys_fopen(const char *path, const char *type)
220 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
221 return fopen64(path, type);
223 return fopen(path, type);
227 /*******************************************************************
228 A readdir wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
231 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
234 return readdir64(dirp);
236 return readdir(dirp);
240 /*******************************************************************
241 The wait() calls vary between systems
242 ********************************************************************/
244 int sys_waitpid(pid_t pid,int *status,int options)
247 return waitpid(pid,status,options);
248 #else /* HAVE_WAITPID */
249 return wait4(pid, status, options, NULL);
250 #endif /* HAVE_WAITPID */
253 /*******************************************************************
254 system wrapper for getwd
255 ********************************************************************/
256 char *sys_getwd(char *s)
260 wd = (char *)getcwd(s, sizeof (pstring));
262 wd = (char *)getwd(s);
267 /*******************************************************************
268 chown isn't used much but OS/2 doesn't have it
269 ********************************************************************/
271 int sys_chown(const char *fname,uid_t uid,gid_t gid)
276 DEBUG(1,("WARNING: no chown!\n"));
280 return(chown(fname,uid,gid));
284 /*******************************************************************
285 os/2 also doesn't have chroot
286 ********************************************************************/
287 int sys_chroot(const char *dname)
292 DEBUG(1,("WARNING: no chroot!\n"));
298 return(chroot(dname));
302 /**************************************************************************
303 A wrapper for gethostbyname() that tries avoids looking up hostnames
304 in the root domain, which can cause dial-on-demand links to come up for no
306 ****************************************************************************/
307 struct hostent *sys_gethostbyname(const char *name)
309 #ifdef REDUCE_ROOT_DNS_LOOKUPS
310 char query[256], hostname[256];
313 /* Does this name have any dots in it? If so, make no change */
315 if (strchr(name, '.'))
316 return(gethostbyname(name));
318 /* Get my hostname, which should have domain name
319 attached. If not, just do the gethostname on the
323 gethostname(hostname, sizeof(hostname) - 1);
324 hostname[sizeof(hostname) - 1] = 0;
325 if ((domain = strchr(hostname, '.')) == NULL)
326 return(gethostbyname(name));
328 /* Attach domain name to query and do modified query.
329 If names too large, just do gethostname on the
333 if((strlen(name) + strlen(domain)) >= sizeof(query))
334 return(gethostbyname(name));
336 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
337 return(gethostbyname(query));
338 #else /* REDUCE_ROOT_DNS_LOOKUPS */
339 return(gethostbyname(name));
340 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
344 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
345 /**************************************************************************
346 Try and abstract process capabilities (for systems that have them).
347 ****************************************************************************/
348 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
350 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
352 cap_t cap = cap_get_proc();
355 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
361 cap->cap_effective |= CAP_NETWORK_MGT;
363 cap->cap_effective &= ~CAP_NETWORK_MGT;
365 if (cap_set_proc(cap) == -1) {
366 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
374 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
379 /**************************************************************************
380 Try and abstract inherited process capabilities (for systems that have them).
381 ****************************************************************************/
383 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
385 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
387 cap_t cap = cap_get_proc();
390 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
396 cap->cap_inheritable |= CAP_NETWORK_MGT;
398 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
400 if (cap_set_proc(cap) == -1) {
401 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
409 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
415 /****************************************************************************
416 gain the oplock capability from the kernel if possible
417 ****************************************************************************/
418 void oplock_set_capability(BOOL this_process, BOOL inherit)
420 #if HAVE_KERNEL_OPLOCKS_IRIX
421 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
422 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
426 /**************************************************************************
427 Wrapper for random().
428 ****************************************************************************/
430 long sys_random(void)
432 #if defined(HAVE_RANDOM)
433 return (long)random();
434 #elif defined(HAVE_RAND)
437 DEBUG(0,("Error - no random function available !\n"));
442 /**************************************************************************
443 Wrapper for srandom().
444 ****************************************************************************/
446 void sys_srandom(unsigned int seed)
448 #if defined(HAVE_SRANDOM)
450 #elif defined(HAVE_SRAND)
453 DEBUG(0,("Error - no srandom function available !\n"));
458 /**************************************************************************
459 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
460 ****************************************************************************/
464 #if defined(SYSCONF_SC_NGROUPS_MAX)
465 int ret = sysconf(_SC_NGROUPS_MAX);
466 return (ret == -1) ? NGROUPS_MAX : ret;
472 /**************************************************************************
473 Wrapper for getgroups. Deals with broken (int) case.
474 ****************************************************************************/
476 int sys_getgroups(int setlen, gid_t *gidset)
478 #if !defined(HAVE_BROKEN_GETGROUPS)
479 return getgroups(setlen, gidset);
487 return getgroups(setlen, &gid);
491 * Broken case. We need to allocate a
492 * GID_T array of size setlen.
501 setlen = groups_max();
503 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
504 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
508 if((ngroups = getgroups(setlen, group_list)) < 0) {
509 int saved_errno = errno;
510 free((char *)group_list);
515 for(i = 0; i < ngroups; i++)
516 gidset[i] = (gid_t)group_list[i];
518 free((char *)group_list);
520 #endif /* HAVE_BROKEN_GETGROUPS */
523 #ifdef HAVE_SETGROUPS
525 /**************************************************************************
526 Wrapper for setgroups. Deals with broken (int) case. Automatically used
527 if we have broken getgroups.
528 ****************************************************************************/
530 int sys_setgroups(int setlen, gid_t *gidset)
532 #if !defined(HAVE_BROKEN_GETGROUPS)
533 return setgroups(setlen, gidset);
542 if (setlen < 0 || setlen > groups_max()) {
548 * Broken case. We need to allocate a
549 * GID_T array of size setlen.
552 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
553 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
557 for(i = 0; i < setlen; i++)
558 group_list[i] = (GID_T) gidset[i];
560 if(setgroups(setlen, group_list) != 0) {
561 int saved_errno = errno;
562 free((char *)group_list);
567 free((char *)group_list);
569 #endif /* HAVE_BROKEN_GETGROUPS */
572 #endif /* HAVE_SETGROUPS */
575 * We only wrap pw_name and pw_passwd for now as these
576 * are the only potentially modified fields.
579 /**************************************************************************
580 Helper function for getpwnam/getpwuid wrappers.
581 ****************************************************************************/
589 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
590 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
592 static int num_lookups; /* Counter so we don't always use cache. */
593 #ifndef PW_RET_CACHE_MAX_LOOKUPS
594 #define PW_RET_CACHE_MAX_LOOKUPS 100
597 static struct passwd *setup_pwret(struct passwd *pass)
600 /* Clear the caches. */
601 memset(&pw_cache, '\0', sizeof(struct saved_pw));
602 memset(&pw_mod, '\0', sizeof(struct saved_pw));
607 /* this gets the uid, gid and null pointers */
609 memcpy((char *)&pw_mod.pass, pass, sizeof(struct passwd));
610 fstrcpy(pw_mod.pw_name, pass->pw_name);
611 pw_mod.pass.pw_name = pw_mod.pw_name;
612 fstrcpy(pw_mod.pw_passwd, pass->pw_passwd);
613 pw_mod.pass.pw_passwd = pw_mod.pw_passwd;
616 if (pass != &pw_cache.pass) {
618 /* If it's a cache miss we must also refill the cache. */
620 memcpy((char *)&pw_cache.pass, pass, sizeof(struct passwd));
621 fstrcpy(pw_cache.pw_name, pass->pw_name);
622 pw_cache.pass.pw_name = pw_cache.pw_name;
623 fstrcpy(pw_cache.pw_passwd, pass->pw_passwd);
624 pw_cache.pass.pw_passwd = pw_cache.pw_passwd;
633 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
639 /**************************************************************************
640 Wrappers for setpwent(), getpwent() and endpwent()
641 ****************************************************************************/
643 void sys_setpwent(void)
645 setup_pwret(NULL); /* Clear cache. */
649 struct passwd *sys_getpwent(void)
651 return setup_pwret(getpwent());
654 void sys_endpwent(void)
656 setup_pwret(NULL); /* Clear cache. */
660 /**************************************************************************
661 Wrapper for getpwnam(). Always returns a static that can be modified.
662 ****************************************************************************/
664 struct passwd *sys_getpwnam(const char *name)
666 if (!name || !name[0])
669 /* check for a cache hit first */
670 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
671 DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name));
672 return setup_pwret(&pw_cache.pass);
675 return setup_pwret(getpwnam(name));
678 /**************************************************************************
679 Wrapper for getpwuid(). Always returns a static that can be modified.
680 ****************************************************************************/
682 struct passwd *sys_getpwuid(uid_t uid)
684 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
685 DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid));
686 return setup_pwret(&pw_cache.pass);
689 DEBUG(2,("getpwuid(%d) called\n",uid));
691 return setup_pwret(getpwuid(uid));
694 /**************************************************************************
695 The following are the UNICODE versions of *all* system interface functions
696 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
697 which currently are left as ascii as they are not used other than in name
699 ****************************************************************************/
701 /**************************************************************************
702 Wide stat. Just narrow and call sys_xxx.
703 ****************************************************************************/
705 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
708 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
711 /**************************************************************************
712 Wide lstat. Just narrow and call sys_xxx.
713 ****************************************************************************/
715 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
718 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
721 /**************************************************************************
722 Wide creat. Just narrow and call sys_xxx.
723 ****************************************************************************/
725 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
728 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
731 /**************************************************************************
732 Wide open. Just narrow and call sys_xxx.
733 ****************************************************************************/
735 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
738 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
741 /**************************************************************************
742 Wide fopen. Just narrow and call sys_xxx.
743 ****************************************************************************/
745 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
748 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
751 /**************************************************************************
752 Wide opendir. Just narrow and call sys_xxx.
753 ****************************************************************************/
755 DIR *wsys_opendir(const smb_ucs2_t *wfname)
758 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
761 /**************************************************************************
762 Wide readdir. Return a structure pointer containing a wide filename.
763 ****************************************************************************/
765 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
767 static SMB_STRUCT_WDIRENT retval;
768 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
774 * The only POSIX defined member of this struct is d_name.
777 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
782 /**************************************************************************
783 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
784 ****************************************************************************/
786 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
789 char *p = sys_getwd(fname);
794 return unix_to_unicode(s, p, sizeof(wpstring));
797 /**************************************************************************
798 Wide chown. Just narrow and call sys_xxx.
799 ****************************************************************************/
801 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
804 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
807 /**************************************************************************
808 Wide chroot. Just narrow and call sys_xxx.
809 ****************************************************************************/
811 int wsys_chroot(const smb_ucs2_t *wfname)
814 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
817 /**************************************************************************
818 Wide getpwnam. Return a structure pointer containing wide names.
819 ****************************************************************************/
821 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
823 static SMB_STRUCT_WPASSWD retval;
825 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
830 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
831 retval.pw_passwd = pwret->pw_passwd;
832 retval.pw_uid = pwret->pw_uid;
833 retval.pw_gid = pwret->pw_gid;
834 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
835 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
836 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
841 /**************************************************************************
842 Wide getpwuid. Return a structure pointer containing wide names.
843 ****************************************************************************/
845 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
847 static SMB_STRUCT_WPASSWD retval;
848 struct passwd *pwret = sys_getpwuid(uid);
853 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
854 retval.pw_passwd = pwret->pw_passwd;
855 retval.pw_uid = pwret->pw_uid;
856 retval.pw_gid = pwret->pw_gid;
857 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
858 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
859 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
864 /**************************************************************************
865 Extract a command into an arg list. Uses a static pstring for storage.
866 Caller frees returned arg list (which contains pointers into the static pstring).
867 ****************************************************************************/
869 static char **extract_args(const char *command)
871 static pstring trunc_cmd;
877 pstrcpy(trunc_cmd, command);
879 if(!(ptr = strtok(trunc_cmd, " \t"))) {
888 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
891 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
895 * Now do the extraction.
898 pstrcpy(trunc_cmd, command);
900 ptr = strtok(trunc_cmd, " \t");
904 while((ptr = strtok(NULL, " \t")) != NULL)
911 /**************************************************************************
912 Wrapper for fork. Ensures that mypid is reset. Used so we can write
913 a sys_getpid() that only does a system call *once*.
914 ****************************************************************************/
916 static pid_t mypid = (pid_t)-1;
920 pid_t forkret = fork();
922 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
928 /**************************************************************************
929 Wrapper for getpid. Ensures we only do a system call *once*.
930 ****************************************************************************/
932 pid_t sys_getpid(void)
934 if (mypid == (pid_t)-1)
940 /**************************************************************************
941 Wrapper for popen. Safer as it doesn't search a path.
942 Modified from the glibc sources.
943 modified by tridge to return a file descriptor. We must kick our FILE* habit
944 ****************************************************************************/
946 typedef struct _popen_list
950 struct _popen_list *next;
953 static popen_list *popen_chain;
955 int sys_popen(const char *command)
957 int parent_end, child_end;
959 popen_list *entry = NULL;
962 if (pipe(pipe_fds) < 0)
965 parent_end = pipe_fds[0];
966 child_end = pipe_fds[1];
973 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
979 * Extract the command and args into a NULL terminated array.
982 if(!(argl = extract_args(command)))
985 entry->child_pid = sys_fork();
987 if (entry->child_pid == -1) {
991 if (entry->child_pid == 0) {
997 int child_std_end = STDOUT_FILENO;
1001 if (child_end != child_std_end) {
1002 dup2 (child_end, child_std_end);
1007 * POSIX.2: "popen() shall ensure that any streams from previous
1008 * popen() calls that remain open in the parent process are closed
1009 * in the new child process."
1012 for (p = popen_chain; p; p = p->next)
1015 execv(argl[0], argl);
1026 /* Link into popen_chain. */
1027 entry->next = popen_chain;
1028 popen_chain = entry;
1029 entry->fd = parent_end;
1036 free((char *)entry);
1044 /**************************************************************************
1045 Wrapper for pclose. Modified from the glibc sources.
1046 ****************************************************************************/
1047 int sys_pclose(int fd)
1050 popen_list **ptr = &popen_chain;
1051 popen_list *entry = NULL;
1055 /* Unlink from popen_chain. */
1056 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1057 if ((*ptr)->fd == fd) {
1059 *ptr = (*ptr)->next;
1065 if (status < 0 || close(entry->fd) < 0)
1069 * As Samba is catching and eating child process
1070 * exits we don't really care about the child exit
1071 * code, a -1 with errno = ECHILD will do fine for us.
1075 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1076 } while (wait_pid == -1 && errno == EINTR);
1078 free((char *)entry);
1085 /**************************************************************************
1086 Wrappers for dlopen, dlsym, dlclose.
1087 ****************************************************************************/
1089 void *sys_dlopen(const char *name, int flags)
1092 return dlopen(name, flags);
1098 void *sys_dlsym(void *handle, char *symbol)
1101 return dlsym(handle, symbol);
1107 int sys_dlclose (void *handle)
1110 return dlclose(handle);