r7165: Fix pidl tests
[sfrench/samba-autobuild/.git] / source / lib / replace.c
1 /* 
2    Unix SMB/CIFS implementation.
3    replacement routines for broken systems
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "system/wait.h"
23 #include "system/time.h"
24 #include "system/network.h"
25
26  void replace_dummy(void);
27  void replace_dummy(void) {}
28
29 #ifndef HAVE_FTRUNCATE
30  /*******************************************************************
31 ftruncate for operating systems that don't have it
32 ********************************************************************/
33  int ftruncate(int f,off_t l)
34 {
35 #ifdef HAVE_CHSIZE
36       return chsize(f,l);
37 #else
38       struct  flock   fl;
39
40       fl.l_whence = 0;
41       fl.l_len = 0;
42       fl.l_start = l;
43       fl.l_type = F_WRLCK;
44       return fcntl(f, F_FREESP, &fl);
45 #endif
46 }
47 #endif /* HAVE_FTRUNCATE */
48
49
50 #ifndef HAVE_STRLCPY
51 /* like strncpy but does not 0 fill the buffer and always null 
52    terminates. bufsize is the size of the destination buffer */
53  size_t strlcpy(char *d, const char *s, size_t bufsize)
54 {
55         size_t len = strlen(s);
56         size_t ret = len;
57         if (bufsize <= 0) return 0;
58         if (len >= bufsize) len = bufsize-1;
59         memcpy(d, s, len);
60         d[len] = 0;
61         return ret;
62 }
63 #endif
64
65 #ifndef HAVE_STRLCAT
66 /* like strncat but does not 0 fill the buffer and always null 
67    terminates. bufsize is the length of the buffer, which should
68    be one more than the maximum resulting string length */
69  size_t strlcat(char *d, const char *s, size_t bufsize)
70 {
71         size_t len1 = strlen(d);
72         size_t len2 = strlen(s);
73         size_t ret = len1 + len2;
74
75         if (len1+len2 >= bufsize) {
76                 len2 = bufsize - (len1+1);
77         }
78         if (len2 > 0) {
79                 memcpy(d+len1, s, len2);
80                 d[len1+len2] = 0;
81         }
82         return ret;
83 }
84 #endif
85
86 #ifndef HAVE_MKTIME
87 /*******************************************************************
88 a mktime() replacement for those who don't have it - contributed by 
89 C.A. Lademann <cal@zls.com>
90 Corrections by richard.kettlewell@kewill.com
91 ********************************************************************/
92
93 #define  MINUTE  60
94 #define  HOUR    60*MINUTE
95 #define  DAY             24*HOUR
96 #define  YEAR    365*DAY
97  time_t mktime(struct tm *t)
98 {
99   struct tm       *u;
100   time_t  epoch = 0;
101   int n;
102   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
103   y, m, i;
104
105   if(t->tm_year < 70)
106     return((time_t)-1);
107
108   n = t->tm_year + 1900 - 1;
109   epoch = (t->tm_year - 70) * YEAR + 
110     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
111
112   y = t->tm_year + 1900;
113   m = 0;
114
115   for(i = 0; i < t->tm_mon; i++) {
116     epoch += mon [m] * DAY;
117     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
118       epoch += DAY;
119     
120     if(++m > 11) {
121       m = 0;
122       y++;
123     }
124   }
125
126   epoch += (t->tm_mday - 1) * DAY;
127   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
128   
129   if((u = localtime(&epoch)) != NULL) {
130     t->tm_sec = u->tm_sec;
131     t->tm_min = u->tm_min;
132     t->tm_hour = u->tm_hour;
133     t->tm_mday = u->tm_mday;
134     t->tm_mon = u->tm_mon;
135     t->tm_year = u->tm_year;
136     t->tm_wday = u->tm_wday;
137     t->tm_yday = u->tm_yday;
138     t->tm_isdst = u->tm_isdst;
139   }
140
141   return(epoch);
142 }
143 #endif /* !HAVE_MKTIME */
144
145
146
147 #ifndef HAVE_RENAME
148 /* Rename a file. (from libiberty in GNU binutils)  */
149  int rename(const char *zfrom, const char *zto)
150 {
151   if (link (zfrom, zto) < 0)
152     {
153       if (errno != EEXIST)
154         return -1;
155       if (unlink (zto) < 0
156           || link (zfrom, zto) < 0)
157         return -1;
158     }
159   return unlink (zfrom);
160 }
161 #endif /* HAVE_RENAME */
162
163
164 #ifndef HAVE_INNETGR
165 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
166 /*
167  * Search for a match in a netgroup. This replaces it on broken systems.
168  */
169  int innetgr(const char *group,const char *host,const char *user,const char *dom)
170 {
171         char *hst, *usr, *dm;
172   
173         setnetgrent(group);
174         while (getnetgrent(&hst, &usr, &dm)) {
175                 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
176                     ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
177                     ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
178                         endnetgrent();
179                         return (1);
180                 }
181         }
182         endnetgrent();
183         return (0);
184 }
185 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
186 #endif /* HAVE_INNETGR */
187
188
189
190 #ifndef HAVE_INITGROUPS
191 /****************************************************************************
192  some systems don't have an initgroups call 
193 ****************************************************************************/
194  int initgroups(char *name,gid_t id)
195 {
196 #ifndef HAVE_SETGROUPS
197         static int done;
198         if (!done) {
199                 DEBUG(1,("WARNING: running without setgroups\n"));
200                 done=1;
201         }
202         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
203         return(0);
204 #else /* HAVE_SETGROUPS */
205         gid_t *grouplst = NULL;
206         int max_gr = groups_max();
207         int ret;
208         int    i,j;
209         struct group *g;
210         char   *gr;
211         
212         if((grouplst = malloc_array_p(gid_t, max_gr)) == NULL) {
213                 DEBUG(0,("initgroups: malloc fail !\n"));
214                 return -1;
215         }
216
217         grouplst[0] = id;
218         i = 1;
219         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
220                 if (g->gr_gid == id)
221                         continue;
222                 j = 0;
223                 gr = g->gr_mem[0];
224                 while (gr && (*gr != (char)NULL)) {
225                         if (strcmp(name,gr) == 0) {
226                                 grouplst[i] = g->gr_gid;
227                                 i++;
228                                 gr = (char *)NULL;
229                                 break;
230                         }
231                         gr = g->gr_mem[++j];
232                 }
233         }
234         endgrent();
235         ret = sys_setgroups(i,grouplst);
236         SAFE_FREE(grouplst);
237         return ret;
238 #endif /* HAVE_SETGROUPS */
239 }
240 #endif /* HAVE_INITGROUPS */
241
242
243 #if (defined(SecureWare) && defined(SCO))
244 /* This is needed due to needing the nap() function but we don't want
245    to include the Xenix libraries since that will break other things...
246    BTW: system call # 0x0c28 is the same as calling nap() */
247  long nap(long milliseconds) {
248          return syscall(0x0c28, milliseconds);
249  }
250 #endif
251
252
253 #ifndef HAVE_MEMMOVE
254 /*******************************************************************
255 safely copies memory, ensuring no overlap problems.
256 this is only used if the machine does not have it's own memmove().
257 this is not the fastest algorithm in town, but it will do for our
258 needs.
259 ********************************************************************/
260  void *memmove(void *dest,const void *src,int size)
261 {
262         unsigned long d,s;
263         int i;
264         if (dest==src || !size) return(dest);
265
266         d = (unsigned long)dest;
267         s = (unsigned long)src;
268
269         if ((d >= (s+size)) || (s >= (d+size))) {
270                 /* no overlap */
271                 memcpy(dest,src,size);
272                 return(dest);
273         }
274
275         if (d < s) {
276                 /* we can forward copy */
277                 if (s-d >= sizeof(int) && 
278                     !(s%sizeof(int)) && 
279                     !(d%sizeof(int)) && 
280                     !(size%sizeof(int))) {
281                         /* do it all as words */
282                         int *idest = (int *)dest;
283                         int *isrc = (int *)src;
284                         size /= sizeof(int);
285                         for (i=0;i<size;i++) idest[i] = isrc[i];
286                 } else {
287                         /* simplest */
288                         char *cdest = (char *)dest;
289                         char *csrc = (char *)src;
290                         for (i=0;i<size;i++) cdest[i] = csrc[i];
291                 }
292         } else {
293                 /* must backward copy */
294                 if (d-s >= sizeof(int) && 
295                     !(s%sizeof(int)) && 
296                     !(d%sizeof(int)) && 
297                     !(size%sizeof(int))) {
298                         /* do it all as words */
299                         int *idest = (int *)dest;
300                         int *isrc = (int *)src;
301                         size /= sizeof(int);
302                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
303                 } else {
304                         /* simplest */
305                         char *cdest = (char *)dest;
306                         char *csrc = (char *)src;
307                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
308                 }      
309         }
310         return(dest);
311 }
312 #endif /* HAVE_MEMMOVE */
313
314 #ifndef HAVE_STRDUP
315 /****************************************************************************
316 duplicate a string
317 ****************************************************************************/
318  char *strdup(const char *s)
319 {
320         size_t len;
321         char *ret;
322
323         if (!s) return(NULL);
324
325         len = strlen(s)+1;
326         ret = (char *)malloc(len);
327         if (!ret) return(NULL);
328         memcpy(ret,s,len);
329         return(ret);
330 }
331 #endif /* HAVE_STRDUP */
332
333 #ifndef WITH_PTHREADS
334 /* REWRITE: not thread safe */
335 #ifdef REPLACE_INET_NTOA
336  char *rep_inet_ntoa(struct in_addr ip)
337 {
338         uint8_t *p = (uint8_t *)&ip.s_addr;
339         static char buf[18];
340         slprintf(buf, 17, "%d.%d.%d.%d", 
341                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
342         return buf;
343 }
344 #endif /* REPLACE_INET_NTOA */
345 #endif
346
347 #ifndef HAVE_STRTOUL
348 #ifndef ULONG_MAX
349 #define ULONG_MAX       ((unsigned long)(~0L))          /* 0xFFFFFFFF */
350 #endif
351
352 /*
353  * Convert a string to an unsigned long integer.
354  * Taken from libg++ - libiberty code.
355  *
356  * Ignores `locale' stuff.  Assumes that the upper and lower case
357  * alphabets and digits are each contiguous.
358  */
359  unsigned long strtoul(const char *nptr, char **endptr, int base)
360 {
361         const char *s = nptr;
362         unsigned long acc;
363         int c;
364         unsigned long cutoff;
365         int neg = 0, any, cutlim;
366
367         /*
368          * See strtol for comments as to the logic used.
369          */
370         do {
371                 c = *s++;
372         } while (isspace(c));
373         if (c == '-') {
374                 neg = 1;
375                 c = *s++;
376         } else if (c == '+')
377                 c = *s++;
378         if ((base == 0 || base == 16) &&
379             c == '0' && (*s == 'x' || *s == 'X')) {
380                 c = s[1];
381                 s += 2;
382                 base = 16;
383         }
384         if (base == 0)
385                 base = c == '0' ? 8 : 10;
386         cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
387         cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
388         for (acc = 0, any = 0;; c = *s++) {
389                 if (isdigit(c))
390                         c -= '0';
391                 else if (isalpha(c))
392                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
393                 else
394                         break;
395                 if (c >= base)
396                         break;
397                 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
398                         any = -1;
399                 else {
400                         any = 1;
401                         acc *= base;
402                         acc += c;
403                 }
404         }
405         if (any < 0) {
406                 acc = ULONG_MAX;
407                 errno = ERANGE;
408         } else if (neg)
409                 acc = -acc;
410         if (endptr != 0)
411                 *endptr = (char *) (any ? s - 1 : nptr);
412         return (acc);
413 }
414 #endif /* HAVE_STRTOUL */
415
416 #ifndef HAVE_SETLINEBUF
417  int setlinebuf(FILE *stream)
418 {
419         return setvbuf(stream, (char *)NULL, _IOLBF, 0);
420 }
421 #endif /* HAVE_SETLINEBUF */
422
423 #ifndef HAVE_VSYSLOG
424 #ifdef HAVE_SYSLOG
425  void vsyslog (int facility_priority, char *format, va_list arglist)
426 {
427         char *msg = NULL;
428         vasprintf(&msg, format, arglist);
429         if (!msg)
430                 return;
431         syslog(facility_priority, "%s", msg);
432         SAFE_FREE(msg);
433 }
434 #endif /* HAVE_SYSLOG */
435 #endif /* HAVE_VSYSLOG */
436
437 /*******************************************************************
438 yield the difference between *A and *B, in seconds, ignoring leap seconds
439 ********************************************************************/
440 static int tm_diff(struct tm *a, struct tm *b)
441 {
442         int ay = a->tm_year + (1900 - 1);
443         int by = b->tm_year + (1900 - 1);
444         int intervening_leap_days =
445                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
446         int years = ay - by;
447         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
448         int hours = 24*days + (a->tm_hour - b->tm_hour);
449         int minutes = 60*hours + (a->tm_min - b->tm_min);
450         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
451
452         return seconds;
453 }
454
455 /*******************************************************************
456   return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
457   ******************************************************************/
458 int get_time_zone(time_t t)
459 {
460         struct tm *tm = gmtime(&t);
461         struct tm tm_utc;
462         if (!tm)
463                 return 0;
464         tm_utc = *tm;
465         tm = localtime(&t);
466         if (!tm)
467                 return 0;
468         return tm_diff(&tm_utc,tm);
469 }
470
471 #ifndef HAVE_TIMEGM
472 /*
473   yes, I know this looks insane, but its really needed. The function in the 
474   Linux timegm() manpage does not work on solaris.
475 */
476  time_t timegm(struct tm *tm) 
477 {
478         struct tm tm2, tm3;
479         time_t t;
480
481         tm2 = *tm;
482
483         t = mktime(&tm2);
484         tm3 = *localtime(&t);
485         tm2 = *tm;
486         tm2.tm_isdst = tm3.tm_isdst;
487         t = mktime(&tm2);
488         t -= get_time_zone(t);
489
490         return t;
491 }
492 #endif
493
494 #ifndef HAVE_SETENV
495  int setenv(const char *name, const char *value, int overwrite) 
496 {
497         char *p = NULL;
498         int ret = -1;
499
500         asprintf(&p, "%s=%s", name, value);
501
502         if (overwrite || getenv(name)) {
503                 if (p) ret = putenv(p);
504         } else {
505                 ret = 0;
506         }
507
508         return ret;     
509 }
510 #endif
511
512
513 #ifndef HAVE_STRTOULL
514  unsigned long long int strtoull(const char *str, char **endptr, int base)
515 {
516 #ifdef HAVE_STRTOUQ
517         return strtouq(str, endptr, base);
518 #else
519 #error "system must support 64 bit integer read from strings"
520 #endif
521 }
522 #endif
523
524
525 #ifndef HAVE_STRNDUP
526 /**
527  Some platforms don't have strndup.
528 **/
529  char *strndup(const char *s, size_t n)
530 {
531         char *ret;
532         
533         n = strnlen(s, n);
534         ret = malloc(n+1);
535         if (!ret)
536                 return NULL;
537         memcpy(ret, s, n);
538         ret[n] = 0;
539
540         return ret;
541 }
542 #endif
543
544 #ifndef HAVE_STRNLEN
545 /**
546  Some platforms don't have strnlen
547 **/
548  size_t strnlen(const char *s, size_t n)
549 {
550         int i;
551         for (i=0; s[i] && i<n; i++)
552                 /* noop */ ;
553         return i;
554 }
555 #endif
556
557 int sys_waitpid(pid_t pid,int *status,int options)
558 {
559 #ifdef HAVE_WAITPID
560   return waitpid(pid,status,options);
561 #else /* USE_WAITPID */
562   return wait4(pid, status, options, NULL);
563 #endif /* USE_WAITPID */
564 }