3bf0994621c99270da143ffa652c497938b4689a
[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 #if 0 /* NOT CURRENTLY USED - JRA */
767 /**************************************************************************
768  The following are the UNICODE versions of *all* system interface functions
769  called within Samba. Ok, ok, the exceptions are the gethostbyXX calls,
770  which currently are left as ascii as they are not used other than in name
771  resolution.
772 ****************************************************************************/
773
774 /**************************************************************************
775  Wide stat. Just narrow and call sys_xxx.
776 ****************************************************************************/
777
778 int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
779 {
780         pstring fname;
781         return sys_stat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
782 }
783
784 /**************************************************************************
785  Wide lstat. Just narrow and call sys_xxx.
786 ****************************************************************************/
787
788 int wsys_lstat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf)
789 {
790         pstring fname;
791         return sys_lstat(unicode_to_unix(fname,wfname,sizeof(fname)), sbuf);
792 }
793
794 /**************************************************************************
795  Wide creat. Just narrow and call sys_xxx.
796 ****************************************************************************/
797
798 int wsys_creat(const smb_ucs2_t *wfname, mode_t mode)
799 {
800         pstring fname;
801         return sys_creat(unicode_to_unix(fname,wfname,sizeof(fname)), mode);
802 }
803
804 /**************************************************************************
805  Wide open. Just narrow and call sys_xxx.
806 ****************************************************************************/
807
808 int wsys_open(const smb_ucs2_t *wfname, int oflag, mode_t mode)
809 {
810         pstring fname;
811         return sys_open(unicode_to_unix(fname,wfname,sizeof(fname)), oflag, mode);
812 }
813
814 /**************************************************************************
815  Wide fopen. Just narrow and call sys_xxx.
816 ****************************************************************************/
817
818 FILE *wsys_fopen(const smb_ucs2_t *wfname, const char *type)
819 {
820         pstring fname;
821         return sys_fopen(unicode_to_unix(fname,wfname,sizeof(fname)), type);
822 }
823
824 /**************************************************************************
825  Wide opendir. Just narrow and call sys_xxx.
826 ****************************************************************************/
827
828 DIR *wsys_opendir(const smb_ucs2_t *wfname)
829 {
830         pstring fname;
831         return opendir(unicode_to_unix(fname,wfname,sizeof(fname)));
832 }
833
834 /**************************************************************************
835  Wide readdir. Return a structure pointer containing a wide filename.
836 ****************************************************************************/
837
838 SMB_STRUCT_WDIRENT *wsys_readdir(DIR *dirp)
839 {
840         static SMB_STRUCT_WDIRENT retval;
841         SMB_STRUCT_DIRENT *dirval = sys_readdir(dirp);
842
843         if(!dirval)
844                 return NULL;
845
846         /*
847          * The only POSIX defined member of this struct is d_name.
848          */
849
850         unix_to_unicode(retval.d_name,dirval->d_name,sizeof(retval.d_name));
851
852         return &retval;
853 }
854
855 /**************************************************************************
856  Wide getwd. Call sys_xxx and widen. Assumes s points to a wpstring.
857 ****************************************************************************/
858
859 smb_ucs2_t *wsys_getwd(smb_ucs2_t *s)
860 {
861         pstring fname;
862         char *p = sys_getwd(fname);
863
864         if(!p)
865                 return NULL;
866
867         return unix_to_unicode(s, p, sizeof(wpstring));
868 }
869
870 /**************************************************************************
871  Wide chown. Just narrow and call sys_xxx.
872 ****************************************************************************/
873
874 int wsys_chown(const smb_ucs2_t *wfname, uid_t uid, gid_t gid)
875 {
876         pstring fname;
877         return chown(unicode_to_unix(fname,wfname,sizeof(fname)), uid, gid);
878 }
879
880 /**************************************************************************
881  Wide chroot. Just narrow and call sys_xxx.
882 ****************************************************************************/
883
884 int wsys_chroot(const smb_ucs2_t *wfname)
885 {
886         pstring fname;
887         return chroot(unicode_to_unix(fname,wfname,sizeof(fname)));
888 }
889
890 /**************************************************************************
891  Wide getpwnam. Return a structure pointer containing wide names.
892 ****************************************************************************/
893
894 SMB_STRUCT_WPASSWD *wsys_getpwnam(const smb_ucs2_t *wname)
895 {
896         static SMB_STRUCT_WPASSWD retval;
897         fstring name;
898         struct passwd *pwret = sys_getpwnam(unicode_to_unix(name,wname,sizeof(name)));
899
900         if(!pwret)
901                 return NULL;
902
903         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
904         retval.pw_passwd = pwret->pw_passwd;
905         retval.pw_uid = pwret->pw_uid;
906         retval.pw_gid = pwret->pw_gid;
907         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
908         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
909         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
910
911         return &retval;
912 }
913
914 /**************************************************************************
915  Wide getpwuid. Return a structure pointer containing wide names.
916 ****************************************************************************/
917
918 SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid)
919 {
920         static SMB_STRUCT_WPASSWD retval;
921         struct passwd *pwret = sys_getpwuid(uid);
922
923         if(!pwret)
924                 return NULL;
925
926         unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name));
927         retval.pw_passwd = pwret->pw_passwd;
928         retval.pw_uid = pwret->pw_uid;
929         retval.pw_gid = pwret->pw_gid;
930         unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos));
931         unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir));
932         unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell));
933
934         return &retval;
935 }
936 #endif /* NOT CURRENTLY USED - JRA */
937
938 /**************************************************************************
939  Extract a command into an arg list. Uses a static pstring for storage.
940  Caller frees returned arg list (which contains pointers into the static pstring).
941 ****************************************************************************/
942
943 static char **extract_args(const char *command)
944 {
945         static pstring trunc_cmd;
946         char *ptr;
947         int argcl;
948         char **argl = NULL;
949         int i;
950
951         pstrcpy(trunc_cmd, command);
952
953         if(!(ptr = strtok(trunc_cmd, " \t"))) {
954                 errno = EINVAL;
955                 return NULL;
956         }
957
958         /*
959          * Count the args.
960          */
961
962         for( argcl = 1; ptr; ptr = strtok(NULL, " \t"))
963                 argcl++;
964
965         if((argl = (char **)malloc((argcl + 1) * sizeof(char *))) == NULL)
966                 return NULL;
967
968         /*
969          * Now do the extraction.
970          */
971
972         pstrcpy(trunc_cmd, command);
973
974         ptr = strtok(trunc_cmd, " \t");
975         i = 0;
976         argl[i++] = ptr;
977
978         while((ptr = strtok(NULL, " \t")) != NULL)
979                 argl[i++] = ptr;
980
981         argl[i++] = NULL;
982         return argl;
983 }
984
985 /**************************************************************************
986  Wrapper for fork. Ensures that mypid is reset. Used so we can write
987  a sys_getpid() that only does a system call *once*.
988 ****************************************************************************/
989
990 static pid_t mypid = (pid_t)-1;
991
992 pid_t sys_fork(void)
993 {
994         pid_t forkret = fork();
995
996         if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
997                 mypid = (pid_t) -1;
998
999         return forkret;
1000 }
1001
1002 /**************************************************************************
1003  Wrapper for getpid. Ensures we only do a system call *once*.
1004 ****************************************************************************/
1005
1006 pid_t sys_getpid(void)
1007 {
1008         if (mypid == (pid_t)-1)
1009                 mypid = getpid();
1010
1011         return mypid;
1012 }
1013
1014 /**************************************************************************
1015  Wrapper for popen. Safer as it doesn't search a path.
1016  Modified from the glibc sources.
1017  modified by tridge to return a file descriptor. We must kick our FILE* habit
1018 ****************************************************************************/
1019
1020 typedef struct _popen_list
1021 {
1022         int fd;
1023         pid_t child_pid;
1024         struct _popen_list *next;
1025 } popen_list;
1026
1027 static popen_list *popen_chain;
1028
1029 int sys_popen(const char *command)
1030 {
1031         int parent_end, child_end;
1032         int pipe_fds[2];
1033         popen_list *entry = NULL;
1034         char **argl = NULL;
1035
1036         if (pipe(pipe_fds) < 0)
1037                 return -1;
1038
1039         parent_end = pipe_fds[0];
1040         child_end = pipe_fds[1];
1041
1042         if (!*command) {
1043                 errno = EINVAL;
1044                 goto err_exit;
1045         }
1046
1047         if((entry = (popen_list *)malloc(sizeof(popen_list))) == NULL)
1048                 goto err_exit;
1049
1050         ZERO_STRUCTP(entry);
1051
1052         /*
1053          * Extract the command and args into a NULL terminated array.
1054          */
1055
1056         if(!(argl = extract_args(command)))
1057                 goto err_exit;
1058
1059         entry->child_pid = sys_fork();
1060
1061         if (entry->child_pid == -1) {
1062                 goto err_exit;
1063         }
1064
1065         if (entry->child_pid == 0) {
1066
1067                 /*
1068                  * Child !
1069                  */
1070
1071                 int child_std_end = STDOUT_FILENO;
1072                 popen_list *p;
1073
1074                 close(parent_end);
1075                 if (child_end != child_std_end) {
1076                         dup2 (child_end, child_std_end);
1077                         close (child_end);
1078                 }
1079
1080                 /*
1081                  * POSIX.2:  "popen() shall ensure that any streams from previous
1082                  * popen() calls that remain open in the parent process are closed
1083                  * in the new child process."
1084                  */
1085
1086                 for (p = popen_chain; p; p = p->next)
1087                         close(p->fd);
1088
1089                 execv(argl[0], argl);
1090                 _exit (127);
1091         }
1092
1093         /*
1094          * Parent.
1095          */
1096
1097         close (child_end);
1098         SAFE_FREE(argl);
1099
1100         /* Link into popen_chain. */
1101         entry->next = popen_chain;
1102         popen_chain = entry;
1103         entry->fd = parent_end;
1104
1105         return entry->fd;
1106
1107 err_exit:
1108
1109         SAFE_FREE(entry);
1110         SAFE_FREE(argl);
1111         close(pipe_fds[0]);
1112         close(pipe_fds[1]);
1113         return -1;
1114 }
1115
1116 /**************************************************************************
1117  Wrapper for pclose. Modified from the glibc sources.
1118 ****************************************************************************/
1119
1120 int sys_pclose(int fd)
1121 {
1122         int wstatus;
1123         popen_list **ptr = &popen_chain;
1124         popen_list *entry = NULL;
1125         pid_t wait_pid;
1126         int status = -1;
1127
1128         /* Unlink from popen_chain. */
1129         for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
1130                 if ((*ptr)->fd == fd) {
1131                         entry = *ptr;
1132                         *ptr = (*ptr)->next;
1133                         status = 0;
1134                         break;
1135                 }
1136         }
1137
1138         if (status < 0 || close(entry->fd) < 0)
1139                 return -1;
1140
1141         /*
1142          * As Samba is catching and eating child process
1143          * exits we don't really care about the child exit
1144          * code, a -1 with errno = ECHILD will do fine for us.
1145          */
1146
1147         do {
1148                 wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0);
1149         } while (wait_pid == -1 && errno == EINTR);
1150
1151         SAFE_FREE(entry);
1152
1153         if (wait_pid == -1)
1154                 return -1;
1155         return wstatus;
1156 }
1157
1158 /**************************************************************************
1159  Wrappers for dlopen, dlsym, dlclose.
1160 ****************************************************************************/
1161
1162 void *sys_dlopen(const char *name, int flags)
1163 {
1164 #if defined(HAVE_DLOPEN)
1165         return dlopen(name, flags);
1166 #else
1167         return NULL;
1168 #endif
1169 }
1170
1171 void *sys_dlsym(void *handle, char *symbol)
1172 {
1173 #if defined(HAVE_DLSYM)
1174     return dlsym(handle, symbol);
1175 #else
1176     return NULL;
1177 #endif
1178 }
1179
1180 int sys_dlclose (void *handle)
1181 {
1182 #if defined(HAVE_DLCLOSE)
1183         return dlclose(handle);
1184 #else
1185         return 0;
1186 #endif
1187 }
1188
1189 const char *sys_dlerror(void)
1190 {
1191 #if defined(HAVE_DLERROR)
1192         return dlerror();
1193 #else
1194         return NULL;
1195 #endif
1196 }
1197
1198 /**************************************************************************
1199  Wrapper for Admin Logs.
1200 ****************************************************************************/
1201
1202 void sys_adminlog(int priority, const char *format_str, ...)
1203 {
1204         va_list ap;
1205         int ret;
1206         char **msgbuf = NULL;
1207
1208         if (!lp_admin_log())
1209                 return;
1210
1211         va_start( ap, format_str );
1212         ret = vasprintf( msgbuf, format_str, ap );
1213         va_end( ap );
1214
1215         if (ret == -1)
1216                 return;
1217
1218 #if defined(HAVE_SYSLOG)
1219         syslog( priority, "%s", *msgbuf );
1220 #else
1221         DEBUG(0,("%s", *msgbuf ));
1222 #endif
1223         SAFE_FREE(*msgbuf);
1224 }