added jeremy's sys_getpwnam() and sys_getpwuid() routines from 2_0 tree.
[nivanova/samba-autobuild/.git] / source3 / lib / system.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba system utilities
5    Copyright (C) Andrew Tridgell 1992-1998
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 extern int DEBUGLEVEL;
25
26 /*
27    The idea is that this file will eventually have wrappers around all
28    important system calls in samba. The aims are:
29
30    - to enable easier porting by putting OS dependent stuff in here
31
32    - to allow for hooks into other "pseudo-filesystems"
33
34    - to allow easier integration of things like the japanese extensions
35
36    - to support the philosophy of Samba to expose the features of
37      the OS within the SMB model. In general whatever file/printer/variable
38      expansions/etc make sense to the OS should be acceptable to Samba.
39 */
40
41
42 /*******************************************************************
43 this replaces the normal select() system call
44 return if some data has arrived on one of the file descriptors
45 return -1 means error
46 ********************************************************************/
47 #ifndef HAVE_SELECT
48 static int pollfd(int fd)
49 {
50   int     r=0;
51
52 #ifdef HAS_RDCHK
53   r = rdchk(fd);
54 #elif defined(TCRDCHK)
55   (void)ioctl(fd, TCRDCHK, &r);
56 #else
57   (void)ioctl(fd, FIONREAD, &r);
58 #endif
59
60   return(r);
61 }
62
63 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
64 {
65   fd_set fds2;
66   int counter=0;
67   int found=0;
68
69   FD_ZERO(&fds2);
70
71   while (1) 
72   {
73     int i;
74     for (i=0;i<maxfd;i++) {
75       if (FD_ISSET(i,fds) && pollfd(i)>0) {
76         found++;
77         FD_SET(i,&fds2);
78       }
79     }
80
81     if (found) {
82       memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
83       return(found);
84     }
85       
86     if (tval && tval->tv_sec < counter) return(0);
87       sleep(1);
88       counter++;
89   }
90 }
91
92 #else /* !NO_SELECT */
93 int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
94 {
95 #ifdef USE_POLL
96   struct pollfd pfd[256];
97   int i;
98   int maxpoll;
99   int timeout;
100   int pollrtn;
101
102   maxpoll = 0;
103   for( i = 0; i < maxfd; i++) {
104     if(FD_ISSET(i,fds)) {
105       struct pollfd *pfdp = &pfd[maxpoll++];
106       pfdp->fd = i;
107       pfdp->events = POLLIN;
108       pfdp->revents = 0;
109     }
110   }
111
112   timeout = (tval != NULL) ? (tval->tv_sec * 1000) + (tval->tv_usec/1000) :
113                 -1;
114   errno = 0;
115   do {
116     pollrtn = poll( &pfd[0], maxpoll, timeout);
117   } while (pollrtn<0 && errno == EINTR);
118
119   FD_ZERO(fds);
120
121   for( i = 0; i < maxpoll; i++)
122     if( pfd[i].revents & POLLIN )
123       FD_SET(pfd[i].fd,fds);
124
125   return pollrtn;
126 #else /* USE_POLL */
127
128   struct timeval t2;
129   int selrtn;
130
131   do {
132     if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
133     errno = 0;
134     selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
135   } while (selrtn<0 && errno == EINTR);
136
137   return(selrtn);
138 }
139 #endif /* USE_POLL */
140 #endif /* NO_SELECT */
141
142 /*******************************************************************
143 A stat() wrapper that will deal with 64 bit filesizes.
144 ********************************************************************/
145
146 int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
147 {
148 #if defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
149   return stat64(fname, sbuf);
150 #else
151   return stat(fname, sbuf);
152 #endif
153 }
154
155 /*******************************************************************
156  An fstat() wrapper that will deal with 64 bit filesizes.
157 ********************************************************************/
158
159 int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
160 {
161 #if defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
162   return fstat64(fd, sbuf);
163 #else
164   return fstat(fd, sbuf);
165 #endif
166 }
167
168 /*******************************************************************
169  An lstat() wrapper that will deal with 64 bit filesizes.
170 ********************************************************************/
171
172 int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
173 {
174 #if defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
175   return lstat64(fname, sbuf);
176 #else
177   return lstat(fname, sbuf);
178 #endif
179 }
180
181 /*******************************************************************
182  An ftruncate() wrapper that will deal with 64 bit filesizes.
183 ********************************************************************/
184
185 int sys_ftruncate(int fd, SMB_OFF_T offset)
186 {
187 #if defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
188   return ftruncate64(fd, offset);
189 #else
190   return ftruncate(fd, offset);
191 #endif
192 }
193
194 /*******************************************************************
195  An lseek() wrapper that will deal with 64 bit filesizes.
196 ********************************************************************/
197
198 SMB_OFF_T sys_lseek(int fd, SMB_OFF_T offset, int whence)
199 {
200 #if defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
201   return lseek64(fd, offset, whence);
202 #else
203   return lseek(fd, offset, whence);
204 #endif
205 }
206
207 /*******************************************************************
208  An fseek() wrapper that will deal with 64 bit filesizes.
209 ********************************************************************/
210
211 int sys_fseek(FILE *fp, SMB_OFF_T offset, int whence)
212 {
213 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
214   return fseek64(fp, offset, whence);
215 #else
216   return fseek(fp, offset, whence);
217 #endif
218 }
219
220 /*******************************************************************
221  An ftell() wrapper that will deal with 64 bit filesizes.
222 ********************************************************************/
223
224 SMB_OFF_T sys_ftell(FILE *fp)
225 {
226 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
227   return (SMB_OFF_T)ftell64(fp);
228 #else
229   return (SMB_OFF_T)ftell(fp);
230 #endif
231 }
232
233 /*******************************************************************
234  A creat() wrapper that will deal with 64 bit filesizes.
235 ********************************************************************/
236
237 int sys_creat(const char *path, mode_t mode)
238 {
239 #if defined(HAVE_CREAT64)
240   return creat64(path, mode);
241 #else
242   /*
243    * If creat64 isn't defined then ensure we call a potential open64.
244    * JRA.
245    */
246   return sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
247 #endif
248 }
249
250 /*******************************************************************
251  An open() wrapper that will deal with 64 bit filesizes.
252 ********************************************************************/
253
254 int sys_open(const char *path, int oflag, mode_t mode)
255 {
256 #if defined(HAVE_OPEN64)
257   return open64(path, oflag, mode);
258 #else
259   return open(path, oflag, mode);
260 #endif
261 }
262
263 /*******************************************************************
264  An fopen() wrapper that will deal with 64 bit filesizes.
265 ********************************************************************/
266
267 FILE *sys_fopen(const char *path, const char *type)
268 {
269 #if defined(HAVE_FOPEN64)
270   return fopen64(path, type);
271 #else
272   return fopen(path, type);
273 #endif
274 }
275
276 /*******************************************************************
277  An mmap() wrapper that will deal with 64 bit filesizes.
278 ********************************************************************/
279
280 void *sys_mmap(void *addr, size_t len, int prot, int flags, int fd, SMB_OFF_T offset)
281 {
282 #if defined(LARGE_SMB_OFF_T) && defined(HAVE_MMAP64)
283   return mmap64(addr, len, prot, flags, fd, offset);
284 #else
285   return mmap(addr, len, prot, flags, fd, offset);
286 #endif
287 }
288
289 /*******************************************************************
290 The wait() calls vary between systems
291 ********************************************************************/
292
293 int sys_waitpid(pid_t pid,int *status,int options)
294 {
295 #ifdef HAVE_WAITPID
296   return waitpid(pid,status,options);
297 #else /* HAVE_WAITPID */
298   return wait4(pid, status, options, NULL);
299 #endif /* HAVE_WAITPID */
300 }
301
302 /*******************************************************************
303 system wrapper for getwd
304 ********************************************************************/
305 char *sys_getwd(char *s)
306 {
307         char *wd;
308 #ifdef HAVE_GETCWD
309         wd = (char *)getcwd(s, sizeof (pstring));
310 #else
311         wd = (char *)getwd(s);
312 #endif
313         return wd;
314 }
315
316 /*******************************************************************
317 chown isn't used much but OS/2 doesn't have it
318 ********************************************************************/
319 int sys_chown(const char *fname,uid_t uid,gid_t gid)
320 {
321 #ifndef HAVE_CHOWN
322         static int done;
323         if (!done) {
324                 DEBUG(1,("WARNING: no chown!\n"));
325                 done=1;
326         }
327 #else
328         return(chown(fname,uid,gid));
329 #endif
330 }
331
332 /*******************************************************************
333 os/2 also doesn't have chroot
334 ********************************************************************/
335 int sys_chroot(const char *dname)
336 {
337 #ifndef HAVE_CHROOT
338         static int done;
339         if (!done) {
340                 DEBUG(1,("WARNING: no chroot!\n"));
341                 done=1;
342         }
343 #else
344         return(chroot(dname));
345 #endif
346 }
347
348 /**************************************************************************
349 A wrapper for gethostbyname() that tries avoids looking up hostnames 
350 in the root domain, which can cause dial-on-demand links to come up for no
351 apparent reason.
352 ****************************************************************************/
353 struct hostent *sys_gethostbyname(const char *name)
354 {
355 #ifdef REDUCE_ROOT_DNS_LOOKUPS
356   char query[256], hostname[256];
357   char *domain;
358
359   /* Does this name have any dots in it? If so, make no change */
360
361   if (strchr(name, '.'))
362     return(gethostbyname(name));
363
364   /* Get my hostname, which should have domain name 
365      attached. If not, just do the gethostname on the
366      original string. 
367   */
368
369   gethostname(hostname, sizeof(hostname) - 1);
370   hostname[sizeof(hostname) - 1] = 0;
371   if ((domain = strchr(hostname, '.')) == NULL)
372     return(gethostbyname(name));
373
374   /* Attach domain name to query and do modified query.
375      If names too large, just do gethostname on the
376      original string.
377   */
378
379   if((strlen(name) + strlen(domain)) >= sizeof(query))
380     return(gethostbyname(name));
381
382   slprintf(query, sizeof(query)-1, "%s%s", name, domain);
383   return(gethostbyname(query));
384 #else /* REDUCE_ROOT_DNS_LOOKUPS */
385   return(gethostbyname(name));
386 #endif /* REDUCE_ROOT_DNS_LOOKUPS */
387 }
388
389
390 /**************************************************************************
391  Try and abstract process capabilities (for systems that have them).
392 ****************************************************************************/
393
394 BOOL set_process_capability( uint32 cap_flag, BOOL enable )
395 {
396 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
397   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
398   {
399     cap_t cap = cap_get_proc();
400
401     if (cap == NULL) {
402       DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
403             strerror(errno)));
404       return False;
405     }
406
407     if(enable)
408       cap->cap_effective |= CAP_NETWORK_MGT;
409     else
410       cap->cap_effective &= ~CAP_NETWORK_MGT;
411
412     if (cap_set_proc(cap) == -1) {
413       DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
414             strerror(errno)));
415       return False;
416     }
417
418     DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
419   }
420 #endif
421   return True;
422 }
423
424 /**************************************************************************
425  Try and abstract inherited process capabilities (for systems that have them).
426 ****************************************************************************/
427
428 BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
429 {
430 #if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
431   if(cap_flag == KERNEL_OPLOCK_CAPABILITY)
432   {
433     cap_t cap = cap_get_proc();
434
435     if (cap == NULL) {
436       DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
437             strerror(errno)));
438       return False;
439     }
440
441     if(enable)
442       cap->cap_inheritable |= CAP_NETWORK_MGT;
443     else
444       cap->cap_inheritable &= ~CAP_NETWORK_MGT;
445
446     if (cap_set_proc(cap) == -1) {
447       DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", 
448             strerror(errno)));
449       return False;
450     }
451
452     DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
453   }
454 #endif
455   return True;
456 }
457
458 /**************************************************************************
459  Wrapper for random().
460 ****************************************************************************/
461
462 long sys_random(void)
463 {
464 #if defined(HAVE_RANDOM)
465   return (long)random();
466 #elif defined(HAVE_RAND)
467   return (long)rand();
468 #else
469   DEBUG(0,("Error - no random function available !\n"));
470   exit(1);
471 #endif
472 }
473
474 /**************************************************************************
475  Wrapper for srandom().
476 ****************************************************************************/
477
478 void sys_srandom(unsigned int seed)
479 {
480 #if defined(HAVE_SRANDOM)
481   srandom(seed);
482 #elif defined(HAVE_SRAND)
483   srand(seed);
484 #else
485   DEBUG(0,("Error - no srandom function available !\n"));
486   exit(1);
487 #endif
488 }
489
490 /**************************************************************************
491  Wrapper for getgroups. Deals with broken (int) case.
492 ****************************************************************************/
493
494 int sys_getgroups(int setlen, gid_t *gidset)
495 {
496 #if !defined(HAVE_BROKEN_GETGROUPS)
497   return getgroups(setlen, gidset);
498 #else
499
500   GID_T gid;
501   GID_T *group_list;
502   int i, ngroups;
503
504   if(setlen == 0) {
505     return getgroups(setlen, &gid);
506   }
507
508   /*
509    * Broken case. We need to allocate a
510    * GID_T array of size setlen.
511    */
512
513   if(setlen < 0) {
514     errno = EINVAL; 
515     return -1;
516   } 
517
518   if (setlen == 0) setlen = 1;
519
520   if((group_list = (GID_T *)malloc(setlen * sizeof(GID_T))) == NULL) {
521     DEBUG(0,("sys_getgroups: Malloc fail.\n"));
522     return -1;
523   }
524
525   if((ngroups = getgroups(setlen, group_list)) < 0) {
526     int saved_errno = errno;
527     free((char *)group_list);
528     errno = saved_errno;
529     return -1;
530   }
531
532   for(i = 0; i < ngroups; i++)
533     gidset[i] = (gid_t)group_list[i];
534
535   free((char *)group_list);
536   return ngroups;
537 #endif /* HAVE_BROKEN_GETGROUPS */
538 }
539
540 /*
541  * We only wrap pw_name and pw_passwd for now as these
542  * are the only potentially modified fields.
543  */
544
545 /**************************************************************************
546  Helper function for getpwnam/getpwuid wrappers.
547 ****************************************************************************/
548
549 static struct passwd *setup_pwret(struct passwd *pass)
550 {
551         static pstring pw_name;
552         static pstring pw_passwd;
553         static struct passwd pw_ret;
554
555         if (pass == NULL)
556         {
557                 return NULL;
558         }
559
560         memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
561
562         if (pass->pw_name)
563         {
564                 pw_name[0] = '\0';
565                 pw_ret.pw_name = pw_name;
566                 pstrcpy(pw_ret.pw_name, pass->pw_name);
567         }
568
569         if (pass->pw_passwd)
570         {
571                 pw_passwd[0] = '\0';
572                 pw_ret.pw_passwd = pw_passwd;
573                 pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
574         }
575
576         return &pw_ret;
577 }
578
579 /**************************************************************************
580  Wrapper for getpwnam(). Always returns a static that can be modified.
581 ****************************************************************************/
582
583 struct passwd *sys_getpwnam(const char *name)
584 {
585         return setup_pwret(getpwnam(name));
586 }
587
588 /**************************************************************************
589  Wrapper for getpwuid(). Always returns a static that can be modified.
590 ****************************************************************************/
591
592 struct passwd *sys_getpwuid(uid_t uid)
593 {
594         return setup_pwret(getpwuid(uid));
595 }