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