Add a wrapper for dup2() to our system.c
[kai/samba.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba system utilities
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1998-2002
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
24 /*
25    The idea is that this file will eventually have wrappers around all
26    important system calls in samba. The aims are:
27
28    - to enable easier porting by putting OS dependent stuff in here
29
30    - to allow for hooks into other "pseudo-filesystems"
31
32    - to allow easier integration of things like the japanese extensions
33
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.
37 */
38
39
40
41 /*******************************************************************
42  A wrapper for usleep in case we don't have one.
43 ********************************************************************/
44
45 int sys_usleep(long usecs)
46 {
47 #ifndef HAVE_USLEEP
48         struct timeval tval;
49 #endif
50
51         /*
52          * We need this braindamage as the glibc usleep
53          * is not SPEC1170 complient... grumble... JRA.
54          */
55
56         if(usecs < 0 || usecs > 1000000) {
57                 errno = EINVAL;
58                 return -1;
59         }
60
61 #if HAVE_USLEEP
62         usleep(usecs);
63         return 0;
64 #else /* HAVE_USLEEP */
65         /*
66          * Fake it with select...
67          */
68         tval.tv_sec = 0;
69         tval.tv_usec = usecs/1000;
70         select(0,NULL,NULL,NULL,&tval);
71         return 0;
72 #endif /* HAVE_USLEEP */
73 }
74
75 /*******************************************************************
76 A read wrapper that will deal with EINTR.
77 ********************************************************************/
78
79 ssize_t sys_read(int fd, void *buf, size_t count)
80 {
81         ssize_t ret;
82
83         do {
84                 ret = read(fd, buf, count);
85         } while (ret == -1 && errno == EINTR);
86         return ret;
87 }
88
89 /*******************************************************************
90 A write wrapper that will deal with EINTR.
91 ********************************************************************/
92
93 ssize_t sys_write(int fd, const void *buf, size_t count)
94 {
95         ssize_t ret;
96
97         do {
98                 ret = write(fd, buf, count);
99         } while (ret == -1 && errno == EINTR);
100         return ret;
101 }
102
103 /*******************************************************************
104 A send wrapper that will deal with EINTR.
105 ********************************************************************/
106
107 ssize_t sys_send(int s, const void *msg, size_t len, int flags)
108 {
109         ssize_t ret;
110
111         do {
112                 ret = send(s, msg, len, flags);
113         } while (ret == -1 && errno == EINTR);
114         return ret;
115 }
116
117 /*******************************************************************
118 A sendto wrapper that will deal with EINTR.
119 ********************************************************************/
120
121 ssize_t sys_sendto(int s,  const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
122 {
123         ssize_t ret;
124
125         do {
126                 ret = sendto(s, msg, len, flags, to, tolen);
127         } while (ret == -1 && errno == EINTR);
128         return ret;
129 }
130
131 /*******************************************************************
132 A recvfrom wrapper that will deal with EINTR.
133 ********************************************************************/
134
135 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
136 {
137         ssize_t ret;
138
139         do {
140                 ret = recvfrom(s, buf, len, flags, from, fromlen);
141         } while (ret == -1 && errno == EINTR);
142         return ret;
143 }
144
145 /*******************************************************************
146 A fcntl wrapper that will deal with EINTR.
147 ********************************************************************/
148
149 int sys_fcntl_ptr(int fd, int cmd, void *arg)
150 {
151         int ret;
152
153         do {
154                 ret = fcntl(fd, cmd, arg);
155         } while (ret == -1 && errno == EINTR);
156         return ret;
157 }
158
159 /*******************************************************************
160 A fcntl wrapper that will deal with EINTR.
161 ********************************************************************/
162
163 int sys_fcntl_long(int fd, int cmd, long arg)
164 {
165         int ret;
166
167         do {
168                 ret = fcntl(fd, cmd, arg);
169         } while (ret == -1 && errno == EINTR);
170         return ret;
171 }
172
173 /*******************************************************************
174 A stat() wrapper that will deal with 64 bit filesizes.
175 ********************************************************************/
176
177 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
178 {
179         int ret;
180 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
181         ret = stat64(fname, sbuf);
182 #else
183         ret = stat(fname, sbuf);
184 #endif
185         /* we always want directories to appear zero size */
186         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
187         return ret;
188 }
189
190 /*******************************************************************
191  An fstat() wrapper that will deal with 64 bit filesizes.
192 ********************************************************************/
193
194 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
195 {
196         int ret;
197 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
198         ret = fstat64(fd, sbuf);
199 #else
200         ret = fstat(fd, sbuf);
201 #endif
202         /* we always want directories to appear zero size */
203         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
204         return ret;
205 }
206
207 /*******************************************************************
208  An lstat() wrapper that will deal with 64 bit filesizes.
209 ********************************************************************/
210
211 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
212 {
213         int ret;
214 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
215         ret = lstat64(fname, sbuf);
216 #else
217         ret = lstat(fname, sbuf);
218 #endif
219         /* we always want directories to appear zero size */
220         if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
221         return ret;
222 }
223
224 /*******************************************************************
225  An ftruncate() wrapper that will deal with 64 bit filesizes.
226 ********************************************************************/
227
228 int sys_ftruncate(int fd, SMB_OFF_T offset)
229 {
230 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
231         return ftruncate64(fd, offset);
232 #else
233         return ftruncate(fd, offset);
234 #endif
235 }
236
237 /*******************************************************************
238  An lseek() wrapper that will deal with 64 bit filesizes.
239 ********************************************************************/
240
241 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
242 {
243 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
244         return lseek64(fd, offset, whence);
245 #else
246         return lseek(fd, offset, whence);
247 #endif
248 }
249
250 /*******************************************************************
251  An fseek() wrapper that will deal with 64 bit filesizes.
252 ********************************************************************/
253
254 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
255 {
256 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
257         return fseek64(fp, offset, whence);
258 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
259         return fseeko64(fp, offset, whence);
260 #else
261         return fseek(fp, offset, whence);
262 #endif
263 }
264
265 /*******************************************************************
266  An ftell() wrapper that will deal with 64 bit filesizes.
267 ********************************************************************/
268
269 SMB_OFF_T sys_ftell(FILE *fp)
270 {
271 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
272         return (SMB_OFF_T)ftell64(fp);
273 #elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
274         return (SMB_OFF_T)ftello64(fp);
275 #else
276         return (SMB_OFF_T)ftell(fp);
277 #endif
278 }
279
280 /*******************************************************************
281  A creat() wrapper that will deal with 64 bit filesizes.
282 ********************************************************************/
283
284 int sys_creat(const char *path, mode_t mode)
285 {
286 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
287         return creat64(path, mode);
288 #else
289         /*
290          * If creat64 isn't defined then ensure we call a potential open64.
291          * JRA.
292          */
293         return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
294 #endif
295 }
296
297 /*******************************************************************
298  An open() wrapper that will deal with 64 bit filesizes.
299 ********************************************************************/
300
301 int sys_open(const char *path, int oflag, mode_t mode)
302 {
303 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
304         return open64(path, oflag, mode);
305 #else
306         return open(path, oflag, mode);
307 #endif
308 }
309
310 /*******************************************************************
311  An fopen() wrapper that will deal with 64 bit filesizes.
312 ********************************************************************/
313
314 FILE *sys_fopen(const char *path, const char *type)
315 {
316 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
317         return fopen64(path, type);
318 #else
319         return fopen(path, type);
320 #endif
321 }
322
323 /*******************************************************************
324  A readdir wrapper that will deal with 64 bit filesizes.
325 ********************************************************************/
326
327 SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp)
328 {
329 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
330         return readdir64(dirp);
331 #else
332         return readdir(dirp);
333 #endif
334 }
335
336 /*******************************************************************
337  An mknod() wrapper that will deal with 64 bit filesizes.
338 ********************************************************************/
339
340 int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
341 {
342 #if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
343 #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
344         return mknod64(path, mode, dev);
345 #else
346         return mknod(path, mode, dev);
347 #endif
348 #else
349         /* No mknod system call. */
350         errno = ENOSYS;
351         return -1;
352 #endif
353 }
354
355 /*******************************************************************
356  Wrapper for realpath.
357 ********************************************************************/
358
359 char *sys_realpath(const char *path, char *resolved_path)
360 {
361 #if defined(HAVE_REALPATH)
362         return realpath(path, resolved_path);
363 #else
364         /* As realpath is not a system call we can't return ENOSYS. */
365         errno = EINVAL;
366         return NULL;
367 #endif
368 }
369
370 /*******************************************************************
371 The wait() calls vary between systems
372 ********************************************************************/
373
374 int sys_waitpid(pid_t pid,int *status,int options)
375 {
376 #ifdef HAVE_WAITPID
377         return waitpid(pid,status,options);
378 #else /* HAVE_WAITPID */
379         return wait4(pid, status, options, NULL);
380 #endif /* HAVE_WAITPID */
381 }
382
383 /*******************************************************************
384  System wrapper for getwd
385 ********************************************************************/
386
387 char *sys_getwd(char *s)
388 {
389         char *wd;
390 #ifdef HAVE_GETCWD
391         wd = (char *)getcwd(s, sizeof (pstring));
392 #else
393         wd = (char *)getwd(s);
394 #endif
395         return wd;
396 }
397
398 /*******************************************************************
399 system wrapper for symlink
400 ********************************************************************/
401
402 int sys_symlink(const char *oldpath, const char *newpath)
403 {
404 #ifndef HAVE_SYMLINK
405         errno = ENOSYS;
406         return -1;
407 #else
408         return symlink(oldpath, newpath);
409 #endif
410 }
411
412 /*******************************************************************
413 system wrapper for readlink
414 ********************************************************************/
415
416 int sys_readlink(const char *path, char *buf, size_t bufsiz)
417 {
418 #ifndef HAVE_READLINK
419         errno = ENOSYS;
420         return -1;
421 #else
422         return readlink(path, buf, bufsiz);
423 #endif
424 }
425
426 /*******************************************************************
427 system wrapper for link
428 ********************************************************************/
429
430 int sys_link(const char *oldpath, const char *newpath)
431 {
432 #ifndef HAVE_LINK
433         errno = ENOSYS;
434         return -1;
435 #else
436         return link(oldpath, newpath);
437 #endif
438 }
439
440 /*******************************************************************
441 chown isn't used much but OS/2 doesn't have it
442 ********************************************************************/
443
444 int sys_chown(const char *fname,uid_t uid,gid_t gid)
445 {
446 #ifndef HAVE_CHOWN
447         static int done;
448         if (!done) {
449                 DEBUG(1,("WARNING: no chown!\n"));
450                 done=1;
451         }
452 #else
453         return(chown(fname,uid,gid));
454 #endif
455 }
456
457 /*******************************************************************
458 os/2 also doesn't have chroot
459 ********************************************************************/
460 int sys_chroot(const char *dname)
461 {
462 #ifndef HAVE_CHROOT
463         static int done;
464         if (!done) {
465                 DEBUG(1,("WARNING: no chroot!\n"));
466                 done=1;
467         }
468         errno = ENOSYS;
469         return -1;
470 #else
471         return(chroot(dname));
472 #endif
473 }
474
475 /**************************************************************************
476 A wrapper for gethostbyname() that tries avoids looking up hostnames 
477 in the root domain, which can cause dial-on-demand links to come up for no
478 apparent reason.
479 ****************************************************************************/
480
481 struct hostent *sys_gethostbyname(const char *name)
482 {
483 #ifdef REDUCE_ROOT_DNS_LOOKUPS
484         char query[256], hostname[256];
485         char *domain;
486
487         /* Does this name have any dots in it? If so, make no change */
488
489         if (strchr_m(name, '.'))
490                 return(gethostbyname(name));
491
492         /* Get my hostname, which should have domain name 
493                 attached. If not, just do the gethostname on the
494                 original string. 
495         */
496
497         gethostname(hostname, sizeof(hostname) - 1);
498         hostname[sizeof(hostname) - 1] = 0;
499         if ((domain = strchr_m(hostname, '.')) == NULL)
500                 return(gethostbyname(name));
501
502         /* Attach domain name to query and do modified query.
503                 If names too large, just do gethostname on the
504                 original string.
505         */
506
507         if((strlen(name) + strlen(domain)) >= sizeof(query))
508                 return(gethostbyname(name));
509
510         slprintf(query, sizeof(query)-1, "%s%s", name, domain);
511         return(gethostbyname(query));
512 #else /* REDUCE_ROOT_DNS_LOOKUPS */
513         return(gethostbyname(name));
514 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
515 }
516
517
518 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
519 /**************************************************************************
520  Try and abstract process capabilities (for systems that have them).
521 ****************************************************************************/
522 static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
523 {
524         if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
525                 cap_t cap = cap_get_proc();
526
527                 if (cap == NULL) {
528                         DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
529                                 strerror(errno)));
530                         return False;
531                 }
532
533                 if(enable)
534                         cap->cap_effective |= CAP_NETWORK_MGT;
535                 else
536                         cap->cap_effective &= ~CAP_NETWORK_MGT;
537
538                 if (cap_set_proc(cap) == -1) {
539                         DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
540                                 strerror(errno)));
541                         cap_free(cap);
542                         return False;
543                 }
544
545                 cap_free(cap);
546
547                 DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
548         }
549         return True;
550 }
551
552 /**************************************************************************
553  Try and abstract inherited process capabilities (for systems that have them).
554 ****************************************************************************/
555
556 static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
557 {
558         if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
559                 cap_t cap = cap_get_proc();
560
561                 if (cap == NULL) {
562                         DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
563                                 strerror(errno)));
564                         return False;
565                 }
566
567                 if(enable)
568                         cap->cap_inheritable |= CAP_NETWORK_MGT;
569                 else
570                         cap->cap_inheritable &= ~CAP_NETWORK_MGT;
571
572                 if (cap_set_proc(cap) == -1) {
573                         DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", 
574                                 strerror(errno)));
575                         cap_free(cap);
576                         return False;
577                 }
578
579                 cap_free(cap);
580
581                 DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
582         }
583         return True;
584 }
585 #endif
586
587 /****************************************************************************
588  Gain the oplock capability from the kernel if possible.
589 ****************************************************************************/
590
591 void oplock_set_capability(BOOL this_process, BOOL inherit)
592 {
593 #if HAVE_KERNEL_OPLOCKS_IRIX
594         set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
595         set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
596 #endif
597 }
598
599 /**************************************************************************
600  Wrapper for random().
601 ****************************************************************************/
602
603 long sys_random(void)
604 {
605 #if defined(HAVE_RANDOM)
606         return (long)random();
607 #elif defined(HAVE_RAND)
608         return (long)rand();
609 #else
610         DEBUG(0,("Error - no random function available !\n"));
611         exit(1);
612 #endif
613 }
614
615 /**************************************************************************
616  Wrapper for srandom().
617 ****************************************************************************/
618
619 void sys_srandom(unsigned int seed)
620 {
621 #if defined(HAVE_SRANDOM)
622         srandom(seed);
623 #elif defined(HAVE_SRAND)
624         srand(seed);
625 #else
626         DEBUG(0,("Error - no srandom function available !\n"));
627         exit(1);
628 #endif
629 }
630
631 /**************************************************************************
632  Returns equivalent to NGROUPS_MAX - using sysconf if needed.
633 ****************************************************************************/
634
635 int groups_max(void)
636 {
637 #if defined(SYSCONF_SC_NGROUPS_MAX)
638         int ret = sysconf(_SC_NGROUPS_MAX);
639         return (ret == -1) ? NGROUPS_MAX : ret;
640 #else
641         return NGROUPS_MAX;
642 #endif
643 }
644
645 /**************************************************************************
646  Wrapper for getgroups. Deals with broken (int) case.
647 ****************************************************************************/
648
649 int sys_getgroups(int setlen, gid_t *gidset)
650 {
651 #if !defined(HAVE_BROKEN_GETGROUPS)
652         return getgroups(setlen, gidset);
653 #else
654
655         GID_T gid;
656         GID_T *group_list;
657         int i, ngroups;
658
659         if(setlen == 0) {
660                 return getgroups(setlen, &gid);
661         }
662
663         /*
664          * Broken case. We need to allocate a
665          * GID_T array of size setlen.
666          */
667
668         if(setlen < 0) {
669                 errno = EINVAL; 
670                 return -1;
671         } 
672
673         if (setlen == 0)
674                 setlen = groups_max();
675
676         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
677                 DEBUG(0,("sys_getgroups: Malloc fail.\n"));
678                 return -1;
679         }
680
681         if((ngroups = getgroups(setlen, group_list)) < 0) {
682                 int saved_errno = errno;
683                 SAFE_FREE(group_list);
684                 errno = saved_errno;
685                 return -1;
686         }
687
688         for(i = 0; i < ngroups; i++)
689                 gidset[i] = (gid_t)group_list[i];
690
691         SAFE_FREE(group_list);
692         return ngroups;
693 #endif /* HAVE_BROKEN_GETGROUPS */
694 }
695
696 #ifdef HAVE_SETGROUPS
697
698 /**************************************************************************
699  Wrapper for setgroups. Deals with broken (int) case. Automatically used
700  if we have broken getgroups.
701 ****************************************************************************/
702
703 int sys_setgroups(int setlen, gid_t *gidset)
704 {
705 #if !defined(HAVE_BROKEN_GETGROUPS)
706         return setgroups(setlen, gidset);
707 #else
708
709         GID_T *group_list;
710         int i ; 
711
712         if (setlen == 0)
713                 return 0 ;
714
715         if (setlen < 0 || setlen > groups_max()) {
716                 errno = EINVAL; 
717                 return -1;   
718         }
719
720         /*
721          * Broken case. We need to allocate a
722          * GID_T array of size setlen.
723          */
724
725         if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
726                 DEBUG(0,("sys_setgroups: Malloc fail.\n"));
727                 return -1;    
728         }
729  
730         for(i = 0; i < setlen; i++) 
731                 group_list[i] = (GID_T) gidset[i]; 
732
733         if(setgroups(setlen, group_list) != 0) {
734                 int saved_errno = errno;
735                 SAFE_FREE(group_list);
736                 errno = saved_errno;
737                 return -1;
738         }
739  
740         SAFE_FREE(group_list);
741         return 0 ;
742 #endif /* HAVE_BROKEN_GETGROUPS */
743 }
744
745 #endif /* HAVE_SETGROUPS */
746
747 /**************************************************************************
748  Wrappers for setpwent(), getpwent() and endpwent()
749 ****************************************************************************/
750
751 void sys_setpwent(void)
752 {
753         setpwent();
754 }
755
756 struct passwd *sys_getpwent(void)
757 {
758         return getpwent();
759 }
760
761 void sys_endpwent(void)
762 {
763         endpwent();
764 }
765
766 /**************************************************************************
767  Wrappers for getpwnam(), getpwuid(), getgrnam(), getgrgid()
768 ****************************************************************************/
769
770 struct passwd *sys_getpwnam(const char *name)
771 {
772         return getpwnam(name);
773 }
774
775 struct passwd *sys_getpwuid(uid_t uid)
776 {
777         return getpwuid(uid);
778 }
779
780 struct group *sys_getgrnam(const char *name)
781 {
782         return getgrnam(name);
783 }
784
785 struct group *sys_getgrgid(gid_t gid)
786 {
787         return getgrgid(gid);
788 }
789
790 #if 0 /* NOT CURRENTLY USED - JRA */
791 /**************************************************************************
792  The following are the UNICODE versions of *all* system interface functions
793  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
794  which currently are left as ascii as they are not used other than in name
795  resolution.
796 ****************************************************************************/
797
798 /**************************************************************************
799  Wide stat. Just narrow and call sys_xxx.
800 ****************************************************************************/
801
802 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
803 {
804         pstring fname;
805         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
806 }
807
808 /**************************************************************************
809  Wide lstat. Just narrow and call sys_xxx.
810 ****************************************************************************/
811
812 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
813 {
814         pstring fname;
815         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
816 }
817
818 /**************************************************************************
819  Wide creat. Just narrow and call sys_xxx.
820 ****************************************************************************/
821
822 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
823 {
824         pstring fname;
825         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
826 }
827
828 /**************************************************************************
829  Wide open. Just narrow and call sys_xxx.
830 ****************************************************************************/
831
832 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
833 {
834         pstring fname;
835         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
836 }
837
838 /**************************************************************************
839  Wide fopen. Just narrow and call sys_xxx.
840 ****************************************************************************/
841
842 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
843 {
844         pstring fname;
845         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
846 }
847
848 /**************************************************************************
849  Wide opendir. Just narrow and call sys_xxx.
850 ****************************************************************************/
851
852 DIR *wsys_opendir(const smb_ucs2_t *wfname)
853 {
854         pstring fname;
855         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
856 }
857
858 /**************************************************************************
859  Wide readdir. Return a structure pointer containing a wide filename.
860 ****************************************************************************/
861
862 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
863 {
864         static SMB_STRUCT_WDIRENT retval;
865         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
866
867         if(!dirval)
868                 return NULL;
869
870         /*
871          * The only POSIX defined member of this struct is d_name.
872          */
873
874         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
875
876         return &retval;
877 }
878
879 /**************************************************************************
880  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
881 ****************************************************************************/
882
883 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
884 {
885         pstring fname;
886         char *p = sys_getwd(fname);
887
888         if(!p)
889                 return NULL;
890
891         return unix_to_unicode(s, p, sizeof(wpstring));
892 }
893
894 /**************************************************************************
895  Wide chown. Just narrow and call sys_xxx.
896 ****************************************************************************/
897
898 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
899 {
900         pstring fname;
901         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
902 }
903
904 /**************************************************************************
905  Wide chroot. Just narrow and call sys_xxx.
906 ****************************************************************************/
907
908 int wsys_chroot(const smb_ucs2_t *wfname)
909 {
910         pstring fname;
911         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
912 }
913
914 /**************************************************************************
915  Wide getpwnam. Return a structure pointer containing wide names.
916 ****************************************************************************/
917
918 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
919 {
920         static SMB_STRUCT_WPASSWD retval;
921         fstring name;
922         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
923
924         if(!pwret)
925                 return NULL;
926
927         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
928         retval.pw_passwd = pwret->pw_passwd;
929         retval.pw_uid = pwret->pw_uid;
930         retval.pw_gid = pwret->pw_gid;
931         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
932         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
933         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
934
935         return &retval;
936 }
937
938 /**************************************************************************
939  Wide getpwuid. Return a structure pointer containing wide names.
940 ****************************************************************************/
941
942 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
943 {
944         static SMB_STRUCT_WPASSWD retval;
945         struct passwd *pwret = sys_getpwuid(uid);
946
947         if(!pwret)
948                 return NULL;
949
950         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
951         retval.pw_passwd = pwret->pw_passwd;
952         retval.pw_uid = pwret->pw_uid;
953         retval.pw_gid = pwret->pw_gid;
954         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
955         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
956         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
957
958         return &retval;
959 }
960 #endif /* NOT CURRENTLY USED - JRA */
961
962 /**************************************************************************
963  Extract a command into an arg list. Uses a static pstring for storage.
964  Caller frees returned arg list (which contains pointers into the static pstring).
965 ****************************************************************************/
966
967 static char **extract_args(const char *command)
968 {
969         static pstring trunc_cmd;
970         char *ptr;
971         int argcl;
972         char **argl = NULL;
973         int i;
974
975         pstrcpy(trunc_cmd, command);
976
977         if(!(ptr = strtok(trunc_cmd, " \t"))) {
978                 errno = EINVAL;
979                 return NULL;
980         }
981
982         /*
983          * Count the args.
984          */
985
986         for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
987                 argcl++;
988
989         if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
990                 return NULL;
991
992         /*
993          * Now do the extraction.
994          */
995
996         pstrcpy(trunc_cmd, command);
997
998         ptr = strtok(trunc_cmd, " \t");
999         i = 0;
1000         argl[i++] = ptr;
1001
1002         while((ptr = strtok(NULL, " \t")) != NULL)
1003                 argl[i++] = ptr;
1004
1005         argl[i++] = NULL;
1006         return argl;
1007 }
1008
1009 /**************************************************************************
1010  Wrapper for fork. Ensures that mypid is reset. Used so we can write
1011  a sys_getpid() that only does a system call *once*.
1012 ****************************************************************************/
1013
1014 static pid_t mypid = (pid_t)-1;
1015
1016 pid_t sys_fork(void)
1017 {
1018         pid_t forkret = fork();
1019
1020         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
1021                 mypid = (pid_t) -1;
1022
1023         return forkret;
1024 }
1025
1026 /**************************************************************************
1027  Wrapper for getpid. Ensures we only do a system call *once*.
1028 ****************************************************************************/
1029
1030 pid_t sys_getpid(void)
1031 {
1032         if (mypid == (pid_t)-1)
1033                 mypid = getpid();
1034
1035         return mypid;
1036 }
1037
1038 /**************************************************************************
1039  Wrapper for popen. Safer as it doesn't search a path.
1040  Modified from the glibc sources.
1041  modified by tridge to return a file descriptor. We must kick our FILE* habit
1042 ****************************************************************************/
1043
1044 typedef struct _popen_list
1045 {
1046         int fd;
1047         pid_t child_pid;
1048         struct _popen_list *next;
1049 } popen_list;
1050
1051 static popen_list *popen_chain;
1052
1053 int sys_popen(const char *command)
1054 {
1055         int parent_end, child_end;
1056         int pipe_fds[2];
1057         popen_list *entry = NULL;
1058         char **argl = NULL;
1059
1060         if (pipe(pipe_fds) < 0)
1061                 return -1;
1062
1063         parent_end = pipe_fds[0];
1064         child_end = pipe_fds[1];
1065
1066         if (!*command) {
1067                 errno = EINVAL;
1068                 goto err_exit;
1069         }
1070
1071         if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1072                 goto err_exit;
1073
1074         ZERO_STRUCTP(entry);
1075
1076         /*
1077          * Extract the command and args into a NULL terminated array.
1078          */
1079
1080         if(!(argl = extract_args(command)))
1081                 goto err_exit;
1082
1083         entry->child_pid = sys_fork();
1084
1085         if (entry->child_pid == -1) {
1086                 goto err_exit;
1087         }
1088
1089         if (entry->child_pid == 0) {
1090
1091                 /*
1092                  * Child !
1093                  */
1094
1095                 int child_std_end = STDOUT_FILENO;
1096                 popen_list *p;
1097
1098                 close(parent_end);
1099                 if (child_end != child_std_end) {
1100                         dup2 (child_end, child_std_end);
1101                         close (child_end);
1102                 }
1103
1104                 /*
1105                  * POSIX.2:  "popen() shall ensure that any streams from previous
1106                  * popen() calls that remain open in the parent process are closed
1107                  * in the new child process."
1108                  */
1109
1110                 for (p = popen_chain; p; p = p->next)
1111                         close(p->fd);
1112
1113                 execv(argl[0], argl);
1114                 _exit (127);
1115         }
1116
1117         /*
1118          * Parent.
1119          */
1120
1121         close (child_end);
1122         SAFE_FREE(argl);
1123
1124         /* Link into popen_chain. */
1125         entry->next = popen_chain;
1126         popen_chain = entry;
1127         entry->fd = parent_end;
1128
1129         return entry->fd;
1130
1131 err_exit:
1132
1133         SAFE_FREE(entry);
1134         SAFE_FREE(argl);
1135         close(pipe_fds[0]);
1136         close(pipe_fds[1]);
1137         return -1;
1138 }
1139
1140 /**************************************************************************
1141  Wrapper for pclose. Modified from the glibc sources.
1142 ****************************************************************************/
1143
1144 int sys_pclose(int fd)
1145 {
1146         int wstatus;
1147         popen_list **ptr = &popen_chain;
1148         popen_list *entry = NULL;
1149         pid_t wait_pid;
1150         int status = -1;
1151
1152         /* Unlink from popen_chain. */
1153         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1154                 if ((*ptr)->fd == fd) {
1155                         entry = *ptr;
1156                         *ptr = (*ptr)->next;
1157                         status = 0;
1158                         break;
1159                 }
1160         }
1161
1162         if (status < 0 || close(entry->fd) < 0)
1163                 return -1;
1164
1165         /*
1166          * As Samba is catching and eating child process
1167          * exits we don't really care about the child exit
1168          * code, a -1 with errno = ECHILD will do fine for us.
1169          */
1170
1171         do {
1172                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1173         } while (wait_pid == -1 && errno == EINTR);
1174
1175         SAFE_FREE(entry);
1176
1177         if (wait_pid == -1)
1178                 return -1;
1179         return wstatus;
1180 }
1181
1182 /**************************************************************************
1183  Wrappers for dlopen, dlsym, dlclose.
1184 ****************************************************************************/
1185
1186 void *sys_dlopen(const char *name, int flags)
1187 {
1188 #if defined(HAVE_DLOPEN)
1189         return dlopen(name, flags);
1190 #else
1191         return NULL;
1192 #endif
1193 }
1194
1195 void *sys_dlsym(void *handle, char *symbol)
1196 {
1197 #if defined(HAVE_DLSYM)
1198     return dlsym(handle, symbol);
1199 #else
1200     return NULL;
1201 #endif
1202 }
1203
1204 int sys_dlclose (void *handle)
1205 {
1206 #if defined(HAVE_DLCLOSE)
1207         return dlclose(handle);
1208 #else
1209         return 0;
1210 #endif
1211 }
1212
1213 const char *sys_dlerror(void)
1214 {
1215 #if defined(HAVE_DLERROR)
1216         return dlerror();
1217 #else
1218         return NULL;
1219 #endif
1220 }
1221
1222 int sys_dup2(int oldfd, int newfd) 
1223 {
1224 #if defined(HAVE_DUP2)
1225         return dup2(oldfd, newfd);
1226 #else
1227         errno = ENOSYS;
1228         return -1;
1229 #endif
1230 }
1231
1232 /**************************************************************************
1233  Wrapper for Admin Logs.
1234 ****************************************************************************/
1235
1236 void sys_adminlog(int priority, const char *format_str, ...)
1237 {
1238         va_list ap;
1239         int ret;
1240         char **msgbuf = NULL;
1241
1242         if (!lp_admin_log())
1243                 return;
1244
1245         va_start( ap, format_str );
1246         ret = vasprintf( msgbuf, format_str, ap );
1247         va_end( ap );
1248
1249         if (ret == -1)
1250                 return;
1251
1252 #if defined(HAVE_SYSLOG)
1253         syslog( priority, "%s", *msgbuf );
1254 #else
1255         DEBUG(0,("%s", *msgbuf ));
1256 #endif
1257         SAFE_FREE(*msgbuf);
1258 }