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