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.
42 /*******************************************************************
43 this replaces the normal select() system call
44 return if some data has arrived on one of the file descriptors
46 ********************************************************************/
48 static int pollfd(int fd)
54 #elif defined(TCRDCHK)
55 (void)ioctl(fd, TCRDCHK, &r);
57 (void)ioctl(fd, FIONREAD, &r);
63 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
74 for (i=0;i<maxfd;i++) {
75 if (FD_ISSET(i,fds) && pollfd(i)>0) {
82 memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
86 if (tval && tval->tv_sec < counter) return(0);
92 #else /* !NO_SELECT */
93 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
96 struct pollfd pfd[256];
103 for( i = 0; i < maxfd; i++) {
104 if(FD_ISSET(i,fds)) {
105 struct pollfd *pfdp = &pfd[maxpoll++];
107 pfdp->events = POLLIN;
112 timeout = (tval != NULL) ? (tval->tv_sec * 1000) + (tval->tv_usec/1000) :
116 pollrtn = poll( &pfd[0], maxpoll, timeout);
117 } while (pollrtn<0 && errno == EINTR);
121 for( i = 0; i < maxpoll; i++)
122 if( pfd[i].revents & POLLIN )
123 FD_SET(pfd[i].fd,fds);
132 if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
134 selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
135 } while (selrtn<0 && errno == EINTR);
139 #endif /* USE_POLL */
140 #endif /* NO_SELECT */
142 /*******************************************************************
143 A wrapper for usleep in case we don't have one.
144 ********************************************************************/
146 int sys_usleep(long usecs)
153 * We need this braindamage as the glibc usleep
154 * is not SPEC1170 complient... grumble... JRA.
157 if(usecs < 0 || usecs > 1000000) {
165 #else /* HAVE_USLEEP */
167 * Fake it with select...
170 tval.tv_usec = usecs/1000;
171 select(0,NULL,NULL,NULL,&tval);
173 #endif /* HAVE_USLEEP */
176 /*******************************************************************
177 A stat() wrapper that will deal with 64 bit filesizes.
178 ********************************************************************/
180 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
183 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
184 ret = stat64(fname, sbuf);
186 ret = stat(fname, sbuf);
188 /* we always want directories to appear zero size */
189 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
193 /*******************************************************************
194 An fstat() wrapper that will deal with 64 bit filesizes.
195 ********************************************************************/
197 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
200 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
201 ret = fstat64(fd, sbuf);
203 ret = fstat(fd, sbuf);
205 /* we always want directories to appear zero size */
206 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
210 /*******************************************************************
211 An lstat() wrapper that will deal with 64 bit filesizes.
212 ********************************************************************/
214 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
217 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
218 ret = lstat64(fname, sbuf);
220 ret = lstat(fname, sbuf);
222 /* we always want directories to appear zero size */
223 if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
227 /*******************************************************************
228 An ftruncate() wrapper that will deal with 64 bit filesizes.
229 ********************************************************************/
231 int sys_ftruncate(int fd, SMB_OFF_T offset)
233 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
234 return ftruncate64(fd, offset);
236 return ftruncate(fd, offset);
240 /*******************************************************************
241 An lseek() wrapper that will deal with 64 bit filesizes.
242 ********************************************************************/
244 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
246 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
247 return lseek64(fd, offset, whence);
249 return lseek(fd, offset, whence);
253 /*******************************************************************
254 An fseek() wrapper that will deal with 64 bit filesizes.
255 ********************************************************************/
257 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
259 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
260 return fseek64(fp, offset, whence);
261 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
262 return fseeko64(fp, offset, whence);
264 return fseek(fp, offset, whence);
268 /*******************************************************************
269 An ftell() wrapper that will deal with 64 bit filesizes.
270 ********************************************************************/
272 SMB_OFF_T sys_ftell(FILE *fp)
274 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
275 return (SMB_OFF_T)ftell64(fp);
276 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
277 return (SMB_OFF_T)ftello64(fp);
279 return (SMB_OFF_T)ftell(fp);
283 /*******************************************************************
284 A creat() wrapper that will deal with 64 bit filesizes.
285 ********************************************************************/
287 int sys_creat(const char *path, mode_t mode)
289 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
290 return creat64(path, mode);
293 * If creat64 isn't defined then ensure we call a potential open64.
296 return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
300 /*******************************************************************
301 An open() wrapper that will deal with 64 bit filesizes.
302 ********************************************************************/
304 int sys_open(const char *path, int oflag, mode_t mode)
306 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
307 return open64(path, oflag, mode);
309 return open(path, oflag, mode);
313 /*******************************************************************
314 An fopen() wrapper that will deal with 64 bit filesizes.
315 ********************************************************************/
317 FILE *sys_fopen(const char *path, const char *type)
319 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
320 return fopen64(path, type);
322 return fopen(path, type);
326 #if defined(HAVE_MMAP)
328 /*******************************************************************
329 An mmap() wrapper that will deal with 64 bit filesizes.
330 ********************************************************************/
332 void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
334 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
335 return mmap64(addr, len, prot, flags, fd, offset);
337 return mmap(addr, len, prot, flags, fd, offset);
341 #endif /* HAVE_MMAP */
343 /*******************************************************************
344 A readdir wrapper that will deal with 64 bit filesizes.
345 ********************************************************************/
347 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
349 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
350 return readdir64(dirp);
352 return readdir(dirp);
356 /*******************************************************************
357 The wait() calls vary between systems
358 ********************************************************************/
360 int sys_waitpid(pid_t pid,int *status,int options)
363 return waitpid(pid,status,options);
364 #else /* HAVE_WAITPID */
365 return wait4(pid, status, options, NULL);
366 #endif /* HAVE_WAITPID */
369 /*******************************************************************
370 system wrapper for getwd
371 ********************************************************************/
372 char *sys_getwd(char *s)
376 wd = (char *)getcwd(s, sizeof (pstring));
378 wd = (char *)getwd(s);
383 /*******************************************************************
384 chown isn't used much but OS/2 doesn't have it
385 ********************************************************************/
387 int sys_chown(const char *fname,uid_t uid,gid_t gid)
392 DEBUG(1,("WARNING: no chown!\n"));
396 return(chown(fname,uid,gid));
400 /*******************************************************************
401 os/2 also doesn't have chroot
402 ********************************************************************/
403 int sys_chroot(const char *dname)
408 DEBUG(1,("WARNING: no chroot!\n"));
412 return(chroot(dname));
416 /**************************************************************************
417 A wrapper for gethostbyname() that tries avoids looking up hostnames
418 in the root domain, which can cause dial-on-demand links to come up for no
420 ****************************************************************************/
421 struct hostent *sys_gethostbyname(const char *name)
423 #ifdef REDUCE_ROOT_DNS_LOOKUPS
424 char query[256], hostname[256];
427 /* Does this name have any dots in it? If so, make no change */
429 if (strchr(name, '.'))
430 return(gethostbyname(name));
432 /* Get my hostname, which should have domain name
433 attached. If not, just do the gethostname on the
437 gethostname(hostname, sizeof(hostname) - 1);
438 hostname[sizeof(hostname) - 1] = 0;
439 if ((domain = strchr(hostname, '.')) == NULL)
440 return(gethostbyname(name));
442 /* Attach domain name to query and do modified query.
443 If names too large, just do gethostname on the
447 if((strlen(name) + strlen(domain)) >= sizeof(query))
448 return(gethostbyname(name));
450 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
451 return(gethostbyname(query));
452 #else /* REDUCE_ROOT_DNS_LOOKUPS */
453 return(gethostbyname(name));
454 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
458 /**************************************************************************
459 Try and abstract process capabilities (for systems that have them).
460 ****************************************************************************/
462 BOOL set_process_capability( uint32 cap_flag, BOOL enable )
464 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
465 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
467 cap_t cap = cap_get_proc();
470 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
476 cap->cap_effective |= CAP_NETWORK_MGT;
478 cap->cap_effective &= ~CAP_NETWORK_MGT;
480 if (cap_set_proc(cap) == -1) {
481 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
489 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
495 /**************************************************************************
496 Try and abstract inherited process capabilities (for systems that have them).
497 ****************************************************************************/
499 BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
501 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
502 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
504 cap_t cap = cap_get_proc();
507 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
513 cap->cap_inheritable |= CAP_NETWORK_MGT;
515 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
517 if (cap_set_proc(cap) == -1) {
518 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
526 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
532 /**************************************************************************
533 Wrapper for random().
534 ****************************************************************************/
536 long sys_random(void)
538 #if defined(HAVE_RANDOM)
539 return (long)random();
540 #elif defined(HAVE_RAND)
543 DEBUG(0,("Error - no random function available !\n"));
548 /**************************************************************************
549 Wrapper for srandom().
550 ****************************************************************************/
552 void sys_srandom(unsigned int seed)
554 #if defined(HAVE_SRANDOM)
556 #elif defined(HAVE_SRAND)
559 DEBUG(0,("Error - no srandom function available !\n"));
564 /**************************************************************************
565 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
566 ****************************************************************************/
570 #if defined(SYSCONF_SC_NGROUPS_MAX)
571 int ret = sysconf(_SC_NGROUPS_MAX);
572 return (ret == -1) ? NGROUPS_MAX : ret;
578 /**************************************************************************
579 Wrapper for getgroups. Deals with broken (int) case.
580 ****************************************************************************/
582 int sys_getgroups(int setlen, gid_t *gidset)
584 #if !defined(HAVE_BROKEN_GETGROUPS)
585 return getgroups(setlen, gidset);
593 return getgroups(setlen, &gid);
597 * Broken case. We need to allocate a
598 * GID_T array of size setlen.
607 setlen = groups_max();
609 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
610 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
614 if((ngroups = getgroups(setlen, group_list)) < 0) {
615 int saved_errno = errno;
616 free((char *)group_list);
621 for(i = 0; i < ngroups; i++)
622 gidset[i] = (gid_t)group_list[i];
624 free((char *)group_list);
626 #endif /* HAVE_BROKEN_GETGROUPS */
629 #ifdef HAVE_SETGROUPS
631 /**************************************************************************
632 Wrapper for setgroups. Deals with broken (int) case. Automatically used
633 if we have broken getgroups.
634 ****************************************************************************/
636 int sys_setgroups(int setlen, gid_t *gidset)
638 #if !defined(HAVE_BROKEN_GETGROUPS)
639 return setgroups(setlen, gidset);
648 if (setlen < 0 || setlen > groups_max()) {
654 * Broken case. We need to allocate a
655 * GID_T array of size setlen.
658 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
659 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
663 for(i = 0; i < setlen; i++)
664 group_list[i] = (GID_T) gidset[i];
666 if(setgroups(setlen, group_list) != 0) {
667 int saved_errno = errno;
668 free((char *)group_list);
673 free((char *)group_list);
675 #endif /* HAVE_BROKEN_GETGROUPS */
678 #endif /* HAVE_SETGROUPS */
681 * We only wrap pw_name and pw_passwd for now as these
682 * are the only potentially modified fields.
685 /**************************************************************************
686 Helper function for getpwnam/getpwuid wrappers.
687 ****************************************************************************/
689 static struct passwd *setup_pwret(struct passwd *pass)
691 static pstring pw_name;
692 static pstring pw_passwd;
693 static struct passwd pw_ret;
700 memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
704 pw_ret.pw_name = pw_name;
705 pstrcpy(pw_ret.pw_name, pass->pw_name);
710 pw_ret.pw_passwd = pw_passwd;
711 pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
717 /**************************************************************************
718 Wrapper for getpwnam(). Always returns a static that can be modified.
719 ****************************************************************************/
721 struct passwd *sys_getpwnam(const char *name)
723 return setup_pwret(getpwnam(name));
726 /**************************************************************************
727 Wrapper for getpwuid(). Always returns a static that can be modified.
728 ****************************************************************************/
730 struct passwd *sys_getpwuid(uid_t uid)
732 return setup_pwret(getpwuid(uid));
735 /**************************************************************************
736 The following are the UNICODE versions of *all* system interface functions
737 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
738 which currently are left as ascii as they are not used other than in name
740 ****************************************************************************/
742 /**************************************************************************
743 Wide stat. Just narrow and call sys_xxx.
744 ****************************************************************************/
746 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
749 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
752 /**************************************************************************
753 Wide lstat. Just narrow and call sys_xxx.
754 ****************************************************************************/
756 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
759 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
762 /**************************************************************************
763 Wide creat. Just narrow and call sys_xxx.
764 ****************************************************************************/
766 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
769 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
772 /**************************************************************************
773 Wide open. Just narrow and call sys_xxx.
774 ****************************************************************************/
776 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
779 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
782 /**************************************************************************
783 Wide fopen. Just narrow and call sys_xxx.
784 ****************************************************************************/
786 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
789 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
792 /**************************************************************************
793 Wide opendir. Just narrow and call sys_xxx.
794 ****************************************************************************/
796 DIR *wsys_opendir(const smb_ucs2_t *wfname)
799 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
802 /**************************************************************************
803 Wide readdir. Return a structure pointer containing a wide filename.
804 ****************************************************************************/
806 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
808 static SMB_STRUCT_WDIRENT retval;
809 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
815 * The only POSIX defined member of this struct is d_name.
818 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
823 /**************************************************************************
824 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
825 ****************************************************************************/
827 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
830 char *p = sys_getwd(fname);
835 return unix_to_unicode(s, p, sizeof(wpstring));
838 /**************************************************************************
839 Wide chown. Just narrow and call sys_xxx.
840 ****************************************************************************/
842 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
845 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
848 /**************************************************************************
849 Wide chroot. Just narrow and call sys_xxx.
850 ****************************************************************************/
852 int wsys_chroot(const smb_ucs2_t *wfname)
855 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
858 /**************************************************************************
859 Wide getpwnam. Return a structure pointer containing wide names.
860 ****************************************************************************/
862 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
864 static SMB_STRUCT_WPASSWD retval;
866 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
871 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
872 retval.pw_passwd = pwret->pw_passwd;
873 retval.pw_uid = pwret->pw_uid;
874 retval.pw_gid = pwret->pw_gid;
875 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
876 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
877 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
882 /**************************************************************************
883 Wide getpwuid. Return a structure pointer containing wide names.
884 ****************************************************************************/
886 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
888 static SMB_STRUCT_WPASSWD retval;
889 struct passwd *pwret = sys_getpwuid(uid);
894 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
895 retval.pw_passwd = pwret->pw_passwd;
896 retval.pw_uid = pwret->pw_uid;
897 retval.pw_gid = pwret->pw_gid;
898 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
899 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
900 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
905 /**************************************************************************
906 Extract a command into an arg list. Uses a static pstring for storage.
907 Caller frees returned arg list (which contains pointers into the static pstring).
908 ****************************************************************************/
910 static char **extract_args(const char *command)
912 static pstring trunc_cmd;
918 pstrcpy(trunc_cmd, command);
920 if(!(ptr = strtok(trunc_cmd, " \t"))) {
929 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
932 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
936 * Now do the extraction.
939 pstrcpy(trunc_cmd, command);
941 ptr = strtok(trunc_cmd, " \t");
945 while((ptr = strtok(NULL, " \t")) != NULL)
952 /**************************************************************************
953 Wrapper for popen. Safer as it doesn't search a path.
954 Modified from the glibc sources.
955 ****************************************************************************/
957 typedef struct _popen_list
961 struct _popen_list *next;
964 static popen_list *popen_chain;
966 FILE *sys_popen(const char *command, const char *mode)
968 int parent_end, child_end;
970 popen_list *entry = NULL;
973 if (pipe(pipe_fds) < 0)
976 if (mode[0] == 'r' && mode[1] == '\0') {
977 parent_end = pipe_fds[0];
978 child_end = pipe_fds[1];
979 } else if (mode[0] == 'w' && mode[1] == '\0') {
980 parent_end = pipe_fds[1];
981 child_end = pipe_fds[0];
992 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
996 * Extract the command and args into a NULL terminated array.
999 if(!(argl = extract_args(command)))
1002 entry->child_pid = fork();
1004 if (entry->child_pid == -1) {
1013 if (entry->child_pid == 0) {
1019 int child_std_end = (mode[0] == 'r') ? STDOUT_FILENO : STDIN_FILENO;
1023 if (child_end != child_std_end) {
1024 dup2 (child_end, child_std_end);
1029 * POSIX.2: "popen() shall ensure that any streams from previous
1030 * popen() calls that remain open in the parent process are closed
1031 * in the new child process."
1034 for (p = popen_chain; p; p = p->next)
1035 close(fileno(p->fp));
1037 execv(argl[0], argl);
1049 * Create the FILE * representing this fd.
1051 entry->fp = fdopen(parent_end, mode);
1053 /* Link into popen_chain. */
1054 entry->next = popen_chain;
1055 popen_chain = entry;
1062 free((char *)entry);
1070 /**************************************************************************
1071 Wrapper for pclose. Modified from the glibc sources.
1072 ****************************************************************************/
1074 int sys_pclose( FILE *fp)
1077 popen_list **ptr = &popen_chain;
1078 popen_list *entry = NULL;
1082 /* Unlink from popen_chain. */
1083 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1084 if ((*ptr)->fp == fp) {
1086 *ptr = (*ptr)->next;
1092 if (status < 0 || close(fileno(entry->fp)) < 0)
1096 * As Samba is catching and eating child process
1097 * exits we don't really care about the child exit
1098 * code, a -1 with errno = ECHILD will do fine for us.
1102 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1103 } while (wait_pid == -1 && errno == EINTR);
1105 free((char *)entry);