r15356: Remove unused 'flags' argument from socket_send() and friends.
[bbaumbach/samba-autobuild/.git] / source4 / lib / replace / 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 #include "system/filesys.h"
26 #include "system/iconv.h"
27
28  void replace_dummy(void);
29  void replace_dummy(void) {}
30
31 #ifndef HAVE_FTRUNCATE
32  /*******************************************************************
33 ftruncate for operating systems that don't have it
34 ********************************************************************/
35  int ftruncate(int f,off_t l)
36 {
37 #ifdef HAVE_CHSIZE
38       return chsize(f,l);
39 #else
40       struct  flock   fl;
41
42       fl.l_whence = 0;
43       fl.l_len = 0;
44       fl.l_start = l;
45       fl.l_type = F_WRLCK;
46       return fcntl(f, F_FREESP, &fl);
47 #endif
48 }
49 #endif /* HAVE_FTRUNCATE */
50
51
52 #ifndef HAVE_STRLCPY
53 /* like strncpy but does not 0 fill the buffer and always null 
54    terminates. bufsize is the size of the destination buffer */
55  size_t strlcpy(char *d, const char *s, size_t bufsize)
56 {
57         size_t len = strlen(s);
58         size_t ret = len;
59         if (bufsize <= 0) return 0;
60         if (len >= bufsize) len = bufsize-1;
61         memcpy(d, s, len);
62         d[len] = 0;
63         return ret;
64 }
65 #endif
66
67 #ifndef HAVE_STRLCAT
68 /* like strncat but does not 0 fill the buffer and always null 
69    terminates. bufsize is the length of the buffer, which should
70    be one more than the maximum resulting string length */
71  size_t strlcat(char *d, const char *s, size_t bufsize)
72 {
73         size_t len1 = strlen(d);
74         size_t len2 = strlen(s);
75         size_t ret = len1 + len2;
76
77         if (len1+len2 >= bufsize) {
78                 len2 = bufsize - (len1+1);
79         }
80         if (len2 > 0) {
81                 memcpy(d+len1, s, len2);
82                 d[len1+len2] = 0;
83         }
84         return ret;
85 }
86 #endif
87
88 #ifndef HAVE_MKTIME
89 /*******************************************************************
90 a mktime() replacement for those who don't have it - contributed by 
91 C.A. Lademann <cal@zls.com>
92 Corrections by richard.kettlewell@kewill.com
93 ********************************************************************/
94
95 #define  MINUTE  60
96 #define  HOUR    60*MINUTE
97 #define  DAY             24*HOUR
98 #define  YEAR    365*DAY
99  time_t mktime(struct tm *t)
100 {
101   struct tm       *u;
102   time_t  epoch = 0;
103   int n;
104   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
105   y, m, i;
106
107   if(t->tm_year < 70)
108     return((time_t)-1);
109
110   n = t->tm_year + 1900 - 1;
111   epoch = (t->tm_year - 70) * YEAR + 
112     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
113
114   y = t->tm_year + 1900;
115   m = 0;
116
117   for(i = 0; i < t->tm_mon; i++) {
118     epoch += mon [m] * DAY;
119     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
120       epoch += DAY;
121     
122     if(++m > 11) {
123       m = 0;
124       y++;
125     }
126   }
127
128   epoch += (t->tm_mday - 1) * DAY;
129   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
130   
131   if((u = localtime(&epoch)) != NULL) {
132     t->tm_sec = u->tm_sec;
133     t->tm_min = u->tm_min;
134     t->tm_hour = u->tm_hour;
135     t->tm_mday = u->tm_mday;
136     t->tm_mon = u->tm_mon;
137     t->tm_year = u->tm_year;
138     t->tm_wday = u->tm_wday;
139     t->tm_yday = u->tm_yday;
140     t->tm_isdst = u->tm_isdst;
141   }
142
143   return(epoch);
144 }
145 #endif /* !HAVE_MKTIME */
146
147
148
149 #ifndef HAVE_RENAME
150 /* Rename a file. (from libiberty in GNU binutils)  */
151  int rename(const char *zfrom, const char *zto)
152 {
153   if (link (zfrom, zto) < 0)
154     {
155       if (errno != EEXIST)
156         return -1;
157       if (unlink (zto) < 0
158           || link (zfrom, zto) < 0)
159         return -1;
160     }
161   return unlink (zfrom);
162 }
163 #endif /* HAVE_RENAME */
164
165
166 #ifndef HAVE_INNETGR
167 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
168 /*
169  * Search for a match in a netgroup. This replaces it on broken systems.
170  */
171  int innetgr(const char *group,const char *host,const char *user,const char *dom)
172 {
173         char *hst, *usr, *dm;
174   
175         setnetgrent(group);
176         while (getnetgrent(&hst, &usr, &dm)) {
177                 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
178                     ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
179                     ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
180                         endnetgrent();
181                         return (1);
182                 }
183         }
184         endnetgrent();
185         return (0);
186 }
187 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
188 #endif /* HAVE_INNETGR */
189
190
191
192 #ifndef HAVE_INITGROUPS
193 /****************************************************************************
194  some systems don't have an initgroups call 
195 ****************************************************************************/
196  int initgroups(char *name, gid_t id)
197 {
198 #ifndef HAVE_SETGROUPS
199         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
200         errno = ENOSYS;
201         return -1;
202 #else /* HAVE_SETGROUPS */
203         gid_t *grouplst = NULL;
204         int max_gr = groups_max();
205         int ret;
206         int    i,j;
207         struct group *g;
208         char   *gr;
209         
210         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
211                 errno = ENOMEM;
212                 return -1;
213         }
214
215         grouplst[0] = id;
216         i = 1;
217         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
218                 if (g->gr_gid == id)
219                         continue;
220                 j = 0;
221                 gr = g->gr_mem[0];
222                 while (gr && (*gr != (char)NULL)) {
223                         if (strcmp(name,gr) == 0) {
224                                 grouplst[i] = g->gr_gid;
225                                 i++;
226                                 gr = (char *)NULL;
227                                 break;
228                         }
229                         gr = g->gr_mem[++j];
230                 }
231         }
232         endgrent();
233         ret = setgroups(i, grouplst);
234         free(grouplst);
235         return ret;
236 #endif /* HAVE_SETGROUPS */
237 }
238 #endif /* HAVE_INITGROUPS */
239
240
241 #if (defined(SecureWare) && defined(SCO))
242 /* This is needed due to needing the nap() function but we don't want
243    to include the Xenix libraries since that will break other things...
244    BTW: system call # 0x0c28 is the same as calling nap() */
245  long nap(long milliseconds) {
246          return syscall(0x0c28, milliseconds);
247  }
248 #endif
249
250
251 #ifndef HAVE_MEMMOVE
252 /*******************************************************************
253 safely copies memory, ensuring no overlap problems.
254 this is only used if the machine does not have it's own memmove().
255 this is not the fastest algorithm in town, but it will do for our
256 needs.
257 ********************************************************************/
258  void *memmove(void *dest,const void *src,int size)
259 {
260         unsigned long d,s;
261         int i;
262         if (dest==src || !size) return(dest);
263
264         d = (unsigned long)dest;
265         s = (unsigned long)src;
266
267         if ((d >= (s+size)) || (s >= (d+size))) {
268                 /* no overlap */
269                 memcpy(dest,src,size);
270                 return(dest);
271         }
272
273         if (d < s) {
274                 /* we can forward copy */
275                 if (s-d >= sizeof(int) && 
276                     !(s%sizeof(int)) && 
277                     !(d%sizeof(int)) && 
278                     !(size%sizeof(int))) {
279                         /* do it all as words */
280                         int *idest = (int *)dest;
281                         int *isrc = (int *)src;
282                         size /= sizeof(int);
283                         for (i=0;i<size;i++) idest[i] = isrc[i];
284                 } else {
285                         /* simplest */
286                         char *cdest = (char *)dest;
287                         char *csrc = (char *)src;
288                         for (i=0;i<size;i++) cdest[i] = csrc[i];
289                 }
290         } else {
291                 /* must backward copy */
292                 if (d-s >= sizeof(int) && 
293                     !(s%sizeof(int)) && 
294                     !(d%sizeof(int)) && 
295                     !(size%sizeof(int))) {
296                         /* do it all as words */
297                         int *idest = (int *)dest;
298                         int *isrc = (int *)src;
299                         size /= sizeof(int);
300                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
301                 } else {
302                         /* simplest */
303                         char *cdest = (char *)dest;
304                         char *csrc = (char *)src;
305                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
306                 }      
307         }
308         return(dest);
309 }
310 #endif /* HAVE_MEMMOVE */
311
312 #ifndef HAVE_STRDUP
313 /****************************************************************************
314 duplicate a string
315 ****************************************************************************/
316  char *strdup(const char *s)
317 {
318         size_t len;
319         char *ret;
320
321         if (!s) return(NULL);
322
323         len = strlen(s)+1;
324         ret = (char *)malloc(len);
325         if (!ret) return(NULL);
326         memcpy(ret,s,len);
327         return(ret);
328 }
329 #endif /* HAVE_STRDUP */
330
331 #ifndef WITH_PTHREADS
332 /* REWRITE: not thread safe */
333 #ifdef REPLACE_INET_NTOA
334  char *rep_inet_ntoa(struct in_addr ip)
335 {
336         uint8_t *p = (uint8_t *)&ip.s_addr;
337         static char buf[18];
338         slprintf(buf, 17, "%d.%d.%d.%d", 
339                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
340         return buf;
341 }
342 #endif /* REPLACE_INET_NTOA */
343 #endif
344
345 #ifndef HAVE_SETLINEBUF
346  int setlinebuf(FILE *stream)
347 {
348         return setvbuf(stream, (char *)NULL, _IOLBF, 0);
349 }
350 #endif /* HAVE_SETLINEBUF */
351
352 #ifndef HAVE_VSYSLOG
353 #ifdef HAVE_SYSLOG
354  void vsyslog (int facility_priority, char *format, va_list arglist)
355 {
356         char *msg = NULL;
357         vasprintf(&msg, format, arglist);
358         if (!msg)
359                 return;
360         syslog(facility_priority, "%s", msg);
361         free(msg);
362 }
363 #endif /* HAVE_SYSLOG */
364 #endif /* HAVE_VSYSLOG */
365
366
367 #ifndef HAVE_TIMEGM
368 /*
369   yes, I know this looks insane, but its really needed. The function in the 
370   Linux timegm() manpage does not work on solaris.
371 */
372  time_t timegm(struct tm *tm) 
373 {
374         time_t t = mktime(tm);
375         t -= mktime(gmtime(&t)) - (int)mktime(localtime(&t));
376         return t;
377 }
378 #endif
379
380 #ifndef HAVE_SETENV
381  int setenv(const char *name, const char *value, int overwrite) 
382 {
383         char *p = NULL;
384         int ret = -1;
385
386         asprintf(&p, "%s=%s", name, value);
387
388         if (overwrite || getenv(name)) {
389                 if (p) ret = putenv(p);
390         } else {
391                 ret = 0;
392         }
393
394         return ret;     
395 }
396 #endif
397
398
399 #ifndef HAVE_STRTOULL
400  unsigned long long int strtoull(const char *str, char **endptr, int base)
401 {
402 #ifdef HAVE_STRTOUQ
403         return strtouq(str, endptr, base);
404 #elif defined(HAVE___STRTOULL) 
405         return __strtoull(str, endptr, base);
406 #else
407 # error "You need a strtoull function"
408 #endif
409 }
410 #endif
411
412 #ifndef HAVE_STRTOLL
413  long long int strtoll(const char *str, char **endptr, int base)
414 {
415 #ifdef HAVE_STRTOQ
416         return strtoq(str, endptr, base);
417 #elif defined(HAVE___STRTOLL) 
418         return __strtoll(str, endptr, base);
419 #else
420 # error "You need a strtoll function"
421 #endif
422 }
423 #endif
424
425
426 #ifndef HAVE_STRNDUP
427 /**
428  Some platforms don't have strndup.
429 **/
430  char *strndup(const char *s, size_t n)
431 {
432         char *ret;
433         
434         n = strnlen(s, n);
435         ret = malloc(n+1);
436         if (!ret)
437                 return NULL;
438         memcpy(ret, s, n);
439         ret[n] = 0;
440
441         return ret;
442 }
443 #endif
444
445 #ifndef HAVE_STRNLEN
446 /**
447  Some platforms don't have strnlen
448 **/
449  size_t strnlen(const char *s, size_t n)
450 {
451         int i;
452         for (i=0; s[i] && i<n; i++)
453                 /* noop */ ;
454         return i;
455 }
456 #endif
457
458 #ifndef HAVE_WAITPID
459 int waitpid(pid_t pid,int *status,int options)
460 {
461   return wait4(pid, status, options, NULL);
462 }
463 #endif
464
465 #ifndef HAVE_SETEUID
466  int seteuid(uid_t euid)
467 {
468 #ifdef HAVE_SETRESUID
469         return setresuid(-1, euid, -1);
470 #else
471 #  error "You need a seteuid function"
472 #endif
473 }
474 #endif
475
476 #ifndef HAVE_SETEGID
477  int setegid(gid_t egid)
478 {
479 #ifdef HAVE_SETRESGID
480         return setresgid(-1, egid, -1);
481 #else
482 #  error "You need a setegid function"
483 #endif
484 }
485 #endif
486
487 /*******************************************************************
488 os/2 also doesn't have chroot
489 ********************************************************************/
490 #ifndef HAVE_CHROOT
491 int chroot(const char *dname)
492 {
493         errno = ENOSYS;
494         return -1;
495 }
496 #endif
497
498 /*****************************************************************
499  Possibly replace mkstemp if it is broken.
500 *****************************************************************/  
501
502 #ifndef HAVE_SECURE_MKSTEMP
503 int rep_mkstemp(char *template)
504 {
505         /* have a reasonable go at emulating it. Hope that
506            the system mktemp() isn't completly hopeless */
507         char *p = mktemp(template);
508         if (!p)
509                 return -1;
510         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
511 }
512 #endif
513
514 #ifndef HAVE_PREAD
515 static ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
516 {
517         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
518                 return -1;
519         }
520         return read(__fd, __buf, __nbytes);
521 }
522 #endif
523
524 #ifndef HAVE_PWRITE
525 static ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
526 {
527         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
528                 return -1;
529         }
530         return write(__fd, __buf, __nbytes);
531 }
532 #endif
533
534 #ifndef HAVE_STRCASESTR
535 char *strcasestr(const char *haystack, const char *needle)
536 {
537         const char *s;
538         size_t nlen = strlen(needle);
539         for (s=haystack;*s;s++) {
540                 if (toupper(*needle) == toupper(*s) &&
541                     strncasecmp(s, needle, nlen) == 0) {
542                         return discard_const_p(char, s);
543                 }
544         }
545         return NULL;
546 }
547 #endif