don't close high fd's in smbrun when using insure (prevents closing
[kai/samba.git] / source3 / lib / replace.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    replacement routines for broken systems
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  void replace_dummy(void);
27  void replace_dummy(void) {}
28
29
30 #ifndef HAVE_FTRUNCATE
31  /*******************************************************************
32 ftruncate for operating systems that don't have it
33 ********************************************************************/
34  int ftruncate(int f,SMB_OFF_T l)
35 {
36       struct  flock   fl;
37
38       fl.l_whence = 0;
39       fl.l_len = 0;
40       fl.l_start = l;
41       fl.l_type = F_WRLCK;
42       return fcntl(f, F_FREESP, &fl);
43 }
44 #endif /* HAVE_FTRUNCATE */
45
46
47 #ifndef HAVE_MKTIME
48 /*******************************************************************
49 a mktime() replacement for those who don't have it - contributed by 
50 C.A. Lademann <cal@zls.com>
51 Corrections by richard.kettlewell@kewill.com
52 ********************************************************************/
53
54 #define  MINUTE  60
55 #define  HOUR    60*MINUTE
56 #define  DAY             24*HOUR
57 #define  YEAR    365*DAY
58  time_t mktime(struct tm *t)
59 {
60   struct tm       *u;
61   time_t  epoch = 0;
62   int n;
63   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
64   y, m, i;
65
66   if(t->tm_year < 70)
67     return((time_t)-1);
68
69   n = t->tm_year + 1900 - 1;
70   epoch = (t->tm_year - 70) * YEAR + 
71     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
72
73   y = t->tm_year + 1900;
74   m = 0;
75
76   for(i = 0; i < t->tm_mon; i++) {
77     epoch += mon [m] * DAY;
78     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
79       epoch += DAY;
80     
81     if(++m > 11) {
82       m = 0;
83       y++;
84     }
85   }
86
87   epoch += (t->tm_mday - 1) * DAY;
88   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
89   
90   if((u = localtime(&epoch)) != NULL) {
91     t->tm_sec = u->tm_sec;
92     t->tm_min = u->tm_min;
93     t->tm_hour = u->tm_hour;
94     t->tm_mday = u->tm_mday;
95     t->tm_mon = u->tm_mon;
96     t->tm_year = u->tm_year;
97     t->tm_wday = u->tm_wday;
98     t->tm_yday = u->tm_yday;
99     t->tm_isdst = u->tm_isdst;
100   }
101
102   return(epoch);
103 }
104 #endif /* !HAVE_MKTIME */
105
106
107
108 #ifndef HAVE_RENAME
109 /* Rename a file. (from libiberty in GNU binutils)  */
110  int rename(const char *zfrom, const char *zto)
111 {
112   if (link (zfrom, zto) < 0)
113     {
114       if (errno != EEXIST)
115         return -1;
116       if (unlink (zto) < 0
117           || link (zfrom, zto) < 0)
118         return -1;
119     }
120   return unlink (zfrom);
121 }
122 #endif /* HAVE_RENAME */
123
124
125 #ifndef HAVE_INNETGR
126 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
127 /*
128  * Search for a match in a netgroup. This replaces it on broken systems.
129  */
130  int innetgr(char *group,char *host,char *user,char *dom)
131 {
132         char *hst, *usr, *dm;
133   
134         setnetgrent(group);
135         while (getnetgrent(&hst, &usr, &dm)) {
136                 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
137                     ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
138                     ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
139                         endnetgrent();
140                         return (1);
141                 }
142         }
143         endnetgrent();
144         return (0);
145 }
146 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
147 #endif /* HAVE_INNETGR */
148
149
150
151 #ifndef HAVE_INITGROUPS
152 /****************************************************************************
153  some systems don't have an initgroups call 
154 ****************************************************************************/
155  int initgroups(char *name,gid_t id)
156 {
157 #ifndef HAVE_SETGROUPS
158         static int done;
159         if (!done) {
160                 DEBUG(1,("WARNING: running without setgroups\n"));
161                 done=1;
162         }
163         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
164         return(0);
165 #else /* HAVE_SETGROUPS */
166         gid_t *grouplst = NULL;
167         int max_gr = groups_max();
168         int ret;
169         int    i,j;
170         struct group *g;
171         char   *gr;
172         
173         if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) {
174                 DEBUG(0,("initgroups: malloc fail !\n");
175                 return -1;
176         }
177
178         grouplst[0] = id;
179         i = 1;
180         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
181                 if (g->gr_gid == id)
182                         continue;
183                 j = 0;
184                 gr = g->gr_mem[0];
185                 while (gr && (*gr != (char)NULL)) {
186                         if (strcmp(name,gr) == 0) {
187                                 grouplst[i] = g->gr_gid;
188                                 i++;
189                                 gr = (char *)NULL;
190                                 break;
191                         }
192                         gr = g->gr_mem[++j];
193                 }
194         }
195         endgrent();
196         ret = sys_setgroups(i,grouplst);
197         free((char *)grouplst);
198         return ret;
199 #endif /* HAVE_SETGROUPS */
200 }
201 #endif /* HAVE_INITGROUPS */
202
203
204 #if (defined(SecureWare) && defined(SCO))
205 /* This is needed due to needing the nap() function but we don't want
206    to include the Xenix libraries since that will break other things...
207    BTW: system call # 0x0c28 is the same as calling nap() */
208  long nap(long milliseconds) {
209          return syscall(0x0c28, milliseconds);
210  }
211 #endif
212
213
214 #ifndef HAVE_MEMMOVE
215 /*******************************************************************
216 safely copies memory, ensuring no overlap problems.
217 this is only used if the machine does not have it's own memmove().
218 this is not the fastest algorithm in town, but it will do for our
219 needs.
220 ********************************************************************/
221  void *memmove(void *dest,const void *src,int size)
222 {
223         unsigned long d,s;
224         int i;
225         if (dest==src || !size) return(dest);
226
227         d = (unsigned long)dest;
228         s = (unsigned long)src;
229
230         if ((d >= (s+size)) || (s >= (d+size))) {
231                 /* no overlap */
232                 memcpy(dest,src,size);
233                 return(dest);
234         }
235
236         if (d < s) {
237                 /* we can forward copy */
238                 if (s-d >= sizeof(int) && 
239                     !(s%sizeof(int)) && 
240                     !(d%sizeof(int)) && 
241                     !(size%sizeof(int))) {
242                         /* do it all as words */
243                         int *idest = (int *)dest;
244                         int *isrc = (int *)src;
245                         size /= sizeof(int);
246                         for (i=0;i<size;i++) idest[i] = isrc[i];
247                 } else {
248                         /* simplest */
249                         char *cdest = (char *)dest;
250                         char *csrc = (char *)src;
251                         for (i=0;i<size;i++) cdest[i] = csrc[i];
252                 }
253         } else {
254                 /* must backward copy */
255                 if (d-s >= sizeof(int) && 
256                     !(s%sizeof(int)) && 
257                     !(d%sizeof(int)) && 
258                     !(size%sizeof(int))) {
259                         /* do it all as words */
260                         int *idest = (int *)dest;
261                         int *isrc = (int *)src;
262                         size /= sizeof(int);
263                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
264                 } else {
265                         /* simplest */
266                         char *cdest = (char *)dest;
267                         char *csrc = (char *)src;
268                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
269                 }      
270         }
271         return(dest);
272 }
273 #endif /* HAVE_MEMMOVE */
274
275 #ifndef HAVE_STRDUP
276 /****************************************************************************
277 duplicate a string
278 ****************************************************************************/
279  char *strdup(const char *s)
280 {
281         size_t len;
282         char *ret;
283
284         if (!s) return(NULL);
285
286         len = strlen(s)+1;
287         ret = (char *)malloc(len);
288         if (!ret) return(NULL);
289         memcpy(ret,s,len);
290         return(ret);
291 }
292 #endif /* HAVE_STRDUP */
293
294 #ifdef REPLACE_INET_NTOA
295 char *rep_inet_ntoa(struct in_addr ip)
296 {
297         unsigned char *p = (unsigned char *)&ip.s_addr;
298         static char buf[18];
299 #if WORDS_BIGENDIAN
300         slprintf(buf, 17, "%d.%d.%d.%d", 
301                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
302 #else /* WORDS_BIGENDIAN */
303         slprintf(buf, 17, "%d.%d.%d.%d", 
304                  (int)p[3], (int)p[2], (int)p[1], (int)p[0]);
305 #endif /* WORDS_BIGENDIAN */
306         return buf;
307 }
308 #endif /* REPLACE_INET_NTOA */
309
310 #ifndef HAVE_STRTOUL
311 #ifndef ULONG_MAX
312 #define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
313 #endif
314
315 /*
316  * Convert a string to an unsigned long integer.
317  * Taken from libg++ - libiberty code.
318  *
319  * Ignores `locale' stuff.  Assumes that the upper and lower case
320  * alphabets and digits are each contiguous.
321  */
322  unsigned long strtoul(const char *nptr, char **endptr, int base)
323 {
324         const char *s = nptr;
325         unsigned long acc;
326         int c;
327         unsigned long cutoff;
328         int neg = 0, any, cutlim;
329
330         /*
331          * See strtol for comments as to the logic used.
332          */
333         do {
334                 c = *s++;
335         } while (isspace(c));
336         if (c == '-') {
337                 neg = 1;
338                 c = *s++;
339         } else if (c == '+')
340                 c = *s++;
341         if ((base == 0 || base == 16) &&
342             c == '0' && (*s == 'x' || *s == 'X')) {
343                 c = s[1];
344                 s += 2;
345                 base = 16;
346         }
347         if (base == 0)
348                 base = c == '0' ? 8 : 10;
349         cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
350         cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
351         for (acc = 0, any = 0;; c = *s++) {
352                 if (isdigit(c))
353                         c -= '0';
354                 else if (isalpha(c))
355                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
356                 else
357                         break;
358                 if (c >= base)
359                         break;
360                 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
361                         any = -1;
362                 else {
363                         any = 1;
364                         acc *= base;
365                         acc += c;
366                 }
367         }
368         if (any < 0) {
369                 acc = ULONG_MAX;
370                 errno = ERANGE;
371         } else if (neg)
372                 acc = -acc;
373         if (endptr != 0)
374                 *endptr = (char *) (any ? s - 1 : nptr);
375         return (acc);
376 }
377 #endif /* HAVE_STRTOUL */