c6a4259417714133e9a8babf1e4bcf3ac76eb5ad
[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;
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[NGROUPS_MAX];
167         int    i,j;
168         struct group *g;
169         char   *gr;
170         
171         setgrent();
172         grouplst[0] = id;
173         i = 1;
174         while (i < NGROUPS_MAX && 
175                ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
176                 if (g->gr_gid == id)
177                         continue;
178                 j = 0;
179                 gr = g->gr_mem[0];
180                 while (gr && (*gr != (char)NULL)) {
181                         if (strcmp(name,gr) == 0) {
182                                 grouplst[i] = g->gr_gid;
183                                 i++;
184                                 gr = (char *)NULL;
185                                 break;
186                         }
187                         gr = g->gr_mem[++j];
188                 }
189         }
190         endgrent();
191         return(setgroups(i,grouplst));
192 #endif /* HAVE_SETGROUPS */
193 }
194 #endif /* HAVE_INITGROUPS */
195
196
197 #if (defined(SecureWare) && defined(SCO))
198 /* This is needed due to needing the nap() function but we don't want
199    to include the Xenix libraries since that will break other things...
200    BTW: system call # 0x0c28 is the same as calling nap() */
201  long nap(long milliseconds) {
202          return syscall(0x0c28, milliseconds);
203  }
204 #endif
205
206
207 #ifndef HAVE_MEMMOVE
208 /*******************************************************************
209 safely copies memory, ensuring no overlap problems.
210 this is only used if the machine does not have it's own memmove().
211 this is not the fastest algorithm in town, but it will do for our
212 needs.
213 ********************************************************************/
214  void *memmove(void *dest,const void *src,int size)
215 {
216         unsigned long d,s;
217         int i;
218         if (dest==src || !size) return(dest);
219
220         d = (unsigned long)dest;
221         s = (unsigned long)src;
222
223         if ((d >= (s+size)) || (s >= (d+size))) {
224                 /* no overlap */
225                 memcpy(dest,src,size);
226                 return(dest);
227         }
228
229         if (d < s) {
230                 /* we can forward copy */
231                 if (s-d >= sizeof(int) && 
232                     !(s%sizeof(int)) && 
233                     !(d%sizeof(int)) && 
234                     !(size%sizeof(int))) {
235                         /* do it all as words */
236                         int *idest = (int *)dest;
237                         int *isrc = (int *)src;
238                         size /= sizeof(int);
239                         for (i=0;i<size;i++) idest[i] = isrc[i];
240                 } else {
241                         /* simplest */
242                         char *cdest = (char *)dest;
243                         char *csrc = (char *)src;
244                         for (i=0;i<size;i++) cdest[i] = csrc[i];
245                 }
246         } else {
247                 /* must backward copy */
248                 if (d-s >= sizeof(int) && 
249                     !(s%sizeof(int)) && 
250                     !(d%sizeof(int)) && 
251                     !(size%sizeof(int))) {
252                         /* do it all as words */
253                         int *idest = (int *)dest;
254                         int *isrc = (int *)src;
255                         size /= sizeof(int);
256                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
257                 } else {
258                         /* simplest */
259                         char *cdest = (char *)dest;
260                         char *csrc = (char *)src;
261                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
262                 }      
263         }
264         return(dest);
265 }
266 #endif /* HAVE_MEMMOVE */
267
268 #ifndef HAVE_STRDUP
269 /****************************************************************************
270 duplicate a string
271 ****************************************************************************/
272  char *strdup(const char *s)
273 {
274         size_t len;
275         char *ret;
276
277         if (!s) return(NULL);
278
279         len = strlen(s)+1;
280         ret = (char *)malloc(len);
281         if (!ret) return(NULL);
282         memcpy(ret,s,len);
283         return(ret);
284 }
285 #endif /* HAVE_STRDUP */
286
287 #ifdef REPLACE_INET_NTOA
288 char *rep_inet_ntoa(struct in_addr ip)
289 {
290         unsigned char *p = (unsigned char *)&ip.s_addr;
291         static char buf[18];
292 #if WORDS_BIGENDIAN
293         slprintf(buf, 17, "%d.%d.%d.%d", 
294                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
295 #else /* WORDS_BIGENDIAN */
296         slprintf(buf, 17, "%d.%d.%d.%d", 
297                  (int)p[3], (int)p[2], (int)p[1], (int)p[0]);
298 #endif /* WORDS_BIGENDIAN */
299         return buf;
300 }
301 #endif /* REPLACE_INET_NTOA */
302
303 #ifndef HAVE_STRTOUL
304 #ifndef ULONG_MAX
305 #define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
306 #endif
307
308 /*
309  * Convert a string to an unsigned long integer.
310  * Taken from libg++ - libiberty code.
311  *
312  * Ignores `locale' stuff.  Assumes that the upper and lower case
313  * alphabets and digits are each contiguous.
314  */
315  unsigned long strtoul(const char *nptr, char **endptr, int base)
316 {
317         const char *s = nptr;
318         unsigned long acc;
319         int c;
320         unsigned long cutoff;
321         int neg = 0, any, cutlim;
322
323         /*
324          * See strtol for comments as to the logic used.
325          */
326         do {
327                 c = *s++;
328         } while (isspace(c));
329         if (c == '-') {
330                 neg = 1;
331                 c = *s++;
332         } else if (c == '+')
333                 c = *s++;
334         if ((base == 0 || base == 16) &&
335             c == '0' && (*s == 'x' || *s == 'X')) {
336                 c = s[1];
337                 s += 2;
338                 base = 16;
339         }
340         if (base == 0)
341                 base = c == '0' ? 8 : 10;
342         cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
343         cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
344         for (acc = 0, any = 0;; c = *s++) {
345                 if (isdigit(c))
346                         c -= '0';
347                 else if (isalpha(c))
348                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
349                 else
350                         break;
351                 if (c >= base)
352                         break;
353                 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
354                         any = -1;
355                 else {
356                         any = 1;
357                         acc *= base;
358                         acc += c;
359                 }
360         }
361         if (any < 0) {
362                 acc = ULONG_MAX;
363                 errno = ERANGE;
364         } else if (neg)
365                 acc = -acc;
366         if (endptr != 0)
367                 *endptr = (char *) (any ? s - 1 : nptr);
368         return (acc);
369 }
370 #endif /* HAVE_STRTOUL */