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 system wrapper for symlink
269 ********************************************************************/
271 int sys_symlink(const char *oldpath, const char *newpath)
277 return symlink(oldpath, newpath);
281 /*******************************************************************
282 system wrapper for readlink
283 ********************************************************************/
285 int sys_readlink(const char *path, char *buf, size_t bufsiz)
287 #ifndef HAVE_READLINK
291 return readlink(path, buf, bufsiz);
295 /*******************************************************************
296 chown isn't used much but OS/2 doesn't have it
297 ********************************************************************/
299 int sys_chown(const char *fname,uid_t uid,gid_t gid)
304 DEBUG(1,("WARNING: no chown!\n"));
308 return(chown(fname,uid,gid));
312 /*******************************************************************
313 os/2 also doesn't have chroot
314 ********************************************************************/
315 int sys_chroot(const char *dname)
320 DEBUG(1,("WARNING: no chroot!\n"));
326 return(chroot(dname));
330 /**************************************************************************
331 A wrapper for gethostbyname() that tries avoids looking up hostnames
332 in the root domain, which can cause dial-on-demand links to come up for no
334 ****************************************************************************/
335 struct hostent *sys_gethostbyname(const char *name)
337 #ifdef REDUCE_ROOT_DNS_LOOKUPS
338 char query[256], hostname[256];
341 /* Does this name have any dots in it? If so, make no change */
343 if (strchr(name, '.'))
344 return(gethostbyname(name));
346 /* Get my hostname, which should have domain name
347 attached. If not, just do the gethostname on the
351 gethostname(hostname, sizeof(hostname) - 1);
352 hostname[sizeof(hostname) - 1] = 0;
353 if ((domain = strchr(hostname, '.')) == NULL)
354 return(gethostbyname(name));
356 /* Attach domain name to query and do modified query.
357 If names too large, just do gethostname on the
361 if((strlen(name) + strlen(domain)) >= sizeof(query))
362 return(gethostbyname(name));
364 slprintf(query, sizeof(query)-1, "%s%s", name, domain);
365 return(gethostbyname(query));
366 #else /* REDUCE_ROOT_DNS_LOOKUPS */
367 return(gethostbyname(name));
368 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
372 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
373 /**************************************************************************
374 Try and abstract process capabilities (for systems that have them).
375 ****************************************************************************/
376 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
378 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
380 cap_t cap = cap_get_proc();
383 DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
389 cap->cap_effective |= CAP_NETWORK_MGT;
391 cap->cap_effective &= ~CAP_NETWORK_MGT;
393 if (cap_set_proc(cap) == -1) {
394 DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
402 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
407 /**************************************************************************
408 Try and abstract inherited process capabilities (for systems that have them).
409 ****************************************************************************/
411 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
413 if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
415 cap_t cap = cap_get_proc();
418 DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
424 cap->cap_inheritable |= CAP_NETWORK_MGT;
426 cap->cap_inheritable &= ~CAP_NETWORK_MGT;
428 if (cap_set_proc(cap) == -1) {
429 DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
437 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
443 /****************************************************************************
444 gain the oplock capability from the kernel if possible
445 ****************************************************************************/
446 void oplock_set_capability(BOOL this_process, BOOL inherit)
448 #if HAVE_KERNEL_OPLOCKS_IRIX
449 set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
450 set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
454 /**************************************************************************
455 Wrapper for random().
456 ****************************************************************************/
458 long sys_random(void)
460 #if defined(HAVE_RANDOM)
461 return (long)random();
462 #elif defined(HAVE_RAND)
465 DEBUG(0,("Error - no random function available !\n"));
470 /**************************************************************************
471 Wrapper for srandom().
472 ****************************************************************************/
474 void sys_srandom(unsigned int seed)
476 #if defined(HAVE_SRANDOM)
478 #elif defined(HAVE_SRAND)
481 DEBUG(0,("Error - no srandom function available !\n"));
486 /**************************************************************************
487 Returns equivalent to NGROUPS_MAX - using sysconf if needed.
488 ****************************************************************************/
492 #if defined(SYSCONF_SC_NGROUPS_MAX)
493 int ret = sysconf(_SC_NGROUPS_MAX);
494 return (ret == -1) ? NGROUPS_MAX : ret;
500 /**************************************************************************
501 Wrapper for getgroups. Deals with broken (int) case.
502 ****************************************************************************/
504 int sys_getgroups(int setlen, gid_t *gidset)
506 #if !defined(HAVE_BROKEN_GETGROUPS)
507 return getgroups(setlen, gidset);
515 return getgroups(setlen, &gid);
519 * Broken case. We need to allocate a
520 * GID_T array of size setlen.
529 setlen = groups_max();
531 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
532 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
536 if((ngroups = getgroups(setlen, group_list)) < 0) {
537 int saved_errno = errno;
538 free((char *)group_list);
543 for(i = 0; i < ngroups; i++)
544 gidset[i] = (gid_t)group_list[i];
546 free((char *)group_list);
548 #endif /* HAVE_BROKEN_GETGROUPS */
551 #ifdef HAVE_SETGROUPS
553 /**************************************************************************
554 Wrapper for setgroups. Deals with broken (int) case. Automatically used
555 if we have broken getgroups.
556 ****************************************************************************/
558 int sys_setgroups(int setlen, gid_t *gidset)
560 #if !defined(HAVE_BROKEN_GETGROUPS)
561 return setgroups(setlen, gidset);
570 if (setlen < 0 || setlen > groups_max()) {
576 * Broken case. We need to allocate a
577 * GID_T array of size setlen.
580 if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
581 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
585 for(i = 0; i < setlen; i++)
586 group_list[i] = (GID_T) gidset[i];
588 if(setgroups(setlen, group_list) != 0) {
589 int saved_errno = errno;
590 free((char *)group_list);
595 free((char *)group_list);
597 #endif /* HAVE_BROKEN_GETGROUPS */
600 #endif /* HAVE_SETGROUPS */
603 * We only wrap pw_name and pw_passwd for now as these
604 * are the only potentially modified fields.
607 /**************************************************************************
608 Helper function for getpwnam/getpwuid wrappers.
609 ****************************************************************************/
620 static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
621 static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
623 static int num_lookups; /* Counter so we don't always use cache. */
624 #ifndef PW_RET_CACHE_MAX_LOOKUPS
625 #define PW_RET_CACHE_MAX_LOOKUPS 100
628 static void copy_pwent(struct saved_pw *dst, struct passwd *pass)
630 memcpy((char *)&dst->pass, pass, sizeof(struct passwd));
632 fstrcpy(dst->pw_name, pass->pw_name);
633 dst->pass.pw_name = dst->pw_name;
635 fstrcpy(dst->pw_passwd, pass->pw_passwd);
636 dst->pass.pw_passwd = dst->pw_passwd;
638 fstrcpy(dst->pw_gecos, pass->pw_gecos);
639 dst->pass.pw_gecos = dst->pw_gecos;
641 pstrcpy(dst->pw_dir, pass->pw_dir);
642 dst->pass.pw_dir = dst->pw_dir;
644 pstrcpy(dst->pw_shell, pass->pw_shell);
645 dst->pass.pw_shell = dst->pw_shell;
648 static struct passwd *setup_pwret(struct passwd *pass)
651 /* Clear the caches. */
652 memset(&pw_cache, '\0', sizeof(struct saved_pw));
653 memset(&pw_mod, '\0', sizeof(struct saved_pw));
658 copy_pwent( &pw_mod, pass);
660 if (pass != &pw_cache.pass) {
662 /* If it's a cache miss we must also refill the cache. */
664 copy_pwent( &pw_cache, pass);
672 num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
678 /**************************************************************************
679 Wrappers for setpwent(), getpwent() and endpwent()
680 ****************************************************************************/
682 void sys_setpwent(void)
684 setup_pwret(NULL); /* Clear cache. */
688 struct passwd *sys_getpwent(void)
690 return setup_pwret(getpwent());
693 void sys_endpwent(void)
695 setup_pwret(NULL); /* Clear cache. */
699 /**************************************************************************
700 Wrapper for getpwnam(). Always returns a static that can be modified.
701 ****************************************************************************/
703 struct passwd *sys_getpwnam(const char *name)
705 if (!name || !name[0])
708 /* check for a cache hit first */
709 if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
710 return setup_pwret(&pw_cache.pass);
713 return setup_pwret(getpwnam(name));
716 /**************************************************************************
717 Wrapper for getpwuid(). Always returns a static that can be modified.
718 ****************************************************************************/
720 struct passwd *sys_getpwuid(uid_t uid)
722 if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
723 return setup_pwret(&pw_cache.pass);
726 return setup_pwret(getpwuid(uid));
729 /**************************************************************************
730 The following are the UNICODE versions of *all* system interface functions
731 called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
732 which currently are left as ascii as they are not used other than in name
734 ****************************************************************************/
736 /**************************************************************************
737 Wide stat. Just narrow and call sys_xxx.
738 ****************************************************************************/
740 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
743 return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
746 /**************************************************************************
747 Wide lstat. Just narrow and call sys_xxx.
748 ****************************************************************************/
750 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
753 return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
756 /**************************************************************************
757 Wide creat. Just narrow and call sys_xxx.
758 ****************************************************************************/
760 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
763 return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
766 /**************************************************************************
767 Wide open. Just narrow and call sys_xxx.
768 ****************************************************************************/
770 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
773 return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
776 /**************************************************************************
777 Wide fopen. Just narrow and call sys_xxx.
778 ****************************************************************************/
780 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
783 return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
786 /**************************************************************************
787 Wide opendir. Just narrow and call sys_xxx.
788 ****************************************************************************/
790 DIR *wsys_opendir(const smb_ucs2_t *wfname)
793 return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
796 /**************************************************************************
797 Wide readdir. Return a structure pointer containing a wide filename.
798 ****************************************************************************/
800 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
802 static SMB_STRUCT_WDIRENT retval;
803 SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
809 * The only POSIX defined member of this struct is d_name.
812 unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
817 /**************************************************************************
818 Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
819 ****************************************************************************/
821 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
824 char *p = sys_getwd(fname);
829 return unix_to_unicode(s, p, sizeof(wpstring));
832 /**************************************************************************
833 Wide chown. Just narrow and call sys_xxx.
834 ****************************************************************************/
836 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
839 return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
842 /**************************************************************************
843 Wide chroot. Just narrow and call sys_xxx.
844 ****************************************************************************/
846 int wsys_chroot(const smb_ucs2_t *wfname)
849 return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
852 /**************************************************************************
853 Wide getpwnam. Return a structure pointer containing wide names.
854 ****************************************************************************/
856 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
858 static SMB_STRUCT_WPASSWD retval;
860 struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
865 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
866 retval.pw_passwd = pwret->pw_passwd;
867 retval.pw_uid = pwret->pw_uid;
868 retval.pw_gid = pwret->pw_gid;
869 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
870 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
871 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
876 /**************************************************************************
877 Wide getpwuid. Return a structure pointer containing wide names.
878 ****************************************************************************/
880 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
882 static SMB_STRUCT_WPASSWD retval;
883 struct passwd *pwret = sys_getpwuid(uid);
888 unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
889 retval.pw_passwd = pwret->pw_passwd;
890 retval.pw_uid = pwret->pw_uid;
891 retval.pw_gid = pwret->pw_gid;
892 unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
893 unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
894 unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
899 /**************************************************************************
900 Extract a command into an arg list. Uses a static pstring for storage.
901 Caller frees returned arg list (which contains pointers into the static pstring).
902 ****************************************************************************/
904 static char **extract_args(const char *command)
906 static pstring trunc_cmd;
912 pstrcpy(trunc_cmd, command);
914 if(!(ptr = strtok(trunc_cmd, " \t"))) {
923 for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
926 if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
930 * Now do the extraction.
933 pstrcpy(trunc_cmd, command);
935 ptr = strtok(trunc_cmd, " \t");
939 while((ptr = strtok(NULL, " \t")) != NULL)
946 /**************************************************************************
947 Wrapper for fork. Ensures that mypid is reset. Used so we can write
948 a sys_getpid() that only does a system call *once*.
949 ****************************************************************************/
951 static pid_t mypid = (pid_t)-1;
955 pid_t forkret = fork();
957 if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
963 /**************************************************************************
964 Wrapper for getpid. Ensures we only do a system call *once*.
965 ****************************************************************************/
967 pid_t sys_getpid(void)
969 if (mypid == (pid_t)-1)
975 /**************************************************************************
976 Wrapper for popen. Safer as it doesn't search a path.
977 Modified from the glibc sources.
978 modified by tridge to return a file descriptor. We must kick our FILE* habit
979 ****************************************************************************/
981 typedef struct _popen_list
985 struct _popen_list *next;
988 static popen_list *popen_chain;
990 int sys_popen(const char *command)
992 int parent_end, child_end;
994 popen_list *entry = NULL;
997 if (pipe(pipe_fds) < 0)
1000 parent_end = pipe_fds[0];
1001 child_end = pipe_fds[1];
1008 if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1011 ZERO_STRUCTP(entry);
1014 * Extract the command and args into a NULL terminated array.
1017 if(!(argl = extract_args(command)))
1020 entry->child_pid = sys_fork();
1022 if (entry->child_pid == -1) {
1026 if (entry->child_pid == 0) {
1032 int child_std_end = STDOUT_FILENO;
1036 if (child_end != child_std_end) {
1037 dup2 (child_end, child_std_end);
1042 * POSIX.2: "popen() shall ensure that any streams from previous
1043 * popen() calls that remain open in the parent process are closed
1044 * in the new child process."
1047 for (p = popen_chain; p; p = p->next)
1050 execv(argl[0], argl);
1061 /* Link into popen_chain. */
1062 entry->next = popen_chain;
1063 popen_chain = entry;
1064 entry->fd = parent_end;
1071 free((char *)entry);
1079 /**************************************************************************
1080 Wrapper for pclose. Modified from the glibc sources.
1081 ****************************************************************************/
1082 int sys_pclose(int fd)
1085 popen_list **ptr = &popen_chain;
1086 popen_list *entry = NULL;
1090 /* Unlink from popen_chain. */
1091 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1092 if ((*ptr)->fd == fd) {
1094 *ptr = (*ptr)->next;
1100 if (status < 0 || close(entry->fd) < 0)
1104 * As Samba is catching and eating child process
1105 * exits we don't really care about the child exit
1106 * code, a -1 with errno = ECHILD will do fine for us.
1110 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1111 } while (wait_pid == -1 && errno == EINTR);
1113 free((char *)entry);
1120 /**************************************************************************
1121 Wrappers for dlopen, dlsym, dlclose.
1122 ****************************************************************************/
1124 void *sys_dlopen(const char *name, int flags)
1127 return dlopen(name, flags);
1133 void *sys_dlsym(void *handle, char *symbol)
1136 return dlsym(handle, symbol);
1142 int sys_dlclose (void *handle)
1145 return dlclose(handle);