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