libreplace: replace inet_ntoa() when it is missing
[Samba.git] / source / lib / replace / replace.c
blobc16bded9633a825d229cf0cfd01db967ef576d1c
1 /*
2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
6 ** NOTE! The following LGPL license applies to the replace
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "replace.h"
26 #include "system/filesys.h"
27 #include "system/time.h"
28 #include "system/passwd.h"
29 #include "system/syslog.h"
30 #include "system/network.h"
31 #include "system/locale.h"
32 #include "system/wait.h"
34 void replace_dummy(void);
35 void replace_dummy(void) {}
37 #ifndef HAVE_FTRUNCATE
38 /*******************************************************************
39 ftruncate for operating systems that don't have it
40 ********************************************************************/
41 int rep_ftruncate(int f, off_t l)
43 #ifdef HAVE_CHSIZE
44 return chsize(f,l);
45 #elif defined(F_FREESP)
46 struct flock fl;
48 fl.l_whence = 0;
49 fl.l_len = 0;
50 fl.l_start = l;
51 fl.l_type = F_WRLCK;
52 return fcntl(f, F_FREESP, &fl);
53 #else
54 #error "you must have a ftruncate function"
55 #endif
57 #endif /* HAVE_FTRUNCATE */
60 #ifndef HAVE_STRLCPY
61 /* like strncpy but does not 0 fill the buffer and always null
62 terminates. bufsize is the size of the destination buffer */
63 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
65 size_t len = strlen(s);
66 size_t ret = len;
67 if (bufsize <= 0) return 0;
68 if (len >= bufsize) len = bufsize-1;
69 memcpy(d, s, len);
70 d[len] = 0;
71 return ret;
73 #endif
75 #ifndef HAVE_STRLCAT
76 /* like strncat but does not 0 fill the buffer and always null
77 terminates. bufsize is the length of the buffer, which should
78 be one more than the maximum resulting string length */
79 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
81 size_t len1 = strlen(d);
82 size_t len2 = strlen(s);
83 size_t ret = len1 + len2;
85 if (len1+len2 >= bufsize) {
86 len2 = bufsize - (len1+1);
88 if (len2 > 0) {
89 memcpy(d+len1, s, len2);
90 d[len1+len2] = 0;
92 return ret;
94 #endif
96 #ifndef HAVE_MKTIME
97 /*******************************************************************
98 a mktime() replacement for those who don't have it - contributed by
99 C.A. Lademann <cal@zls.com>
100 Corrections by richard.kettlewell@kewill.com
101 ********************************************************************/
103 #define MINUTE 60
104 #define HOUR 60*MINUTE
105 #define DAY 24*HOUR
106 #define YEAR 365*DAY
107 time_t rep_mktime(struct tm *t)
109 struct tm *u;
110 time_t epoch = 0;
111 int n;
112 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
113 y, m, i;
115 if(t->tm_year < 70)
116 return((time_t)-1);
118 n = t->tm_year + 1900 - 1;
119 epoch = (t->tm_year - 70) * YEAR +
120 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
122 y = t->tm_year + 1900;
123 m = 0;
125 for(i = 0; i < t->tm_mon; i++) {
126 epoch += mon [m] * DAY;
127 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
128 epoch += DAY;
130 if(++m > 11) {
131 m = 0;
132 y++;
136 epoch += (t->tm_mday - 1) * DAY;
137 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
139 if((u = localtime(&epoch)) != NULL) {
140 t->tm_sec = u->tm_sec;
141 t->tm_min = u->tm_min;
142 t->tm_hour = u->tm_hour;
143 t->tm_mday = u->tm_mday;
144 t->tm_mon = u->tm_mon;
145 t->tm_year = u->tm_year;
146 t->tm_wday = u->tm_wday;
147 t->tm_yday = u->tm_yday;
148 t->tm_isdst = u->tm_isdst;
151 return(epoch);
153 #endif /* !HAVE_MKTIME */
156 #ifndef HAVE_INITGROUPS
157 /****************************************************************************
158 some systems don't have an initgroups call
159 ****************************************************************************/
160 int rep_initgroups(char *name, gid_t id)
162 #ifndef HAVE_SETGROUPS
163 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
164 errno = ENOSYS;
165 return -1;
166 #else /* HAVE_SETGROUPS */
168 #include <grp.h>
170 gid_t *grouplst = NULL;
171 int max_gr = 32;
172 int ret;
173 int i,j;
174 struct group *g;
175 char *gr;
177 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
178 errno = ENOMEM;
179 return -1;
182 grouplst[0] = id;
183 i = 1;
184 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
185 if (g->gr_gid == id)
186 continue;
187 j = 0;
188 gr = g->gr_mem[0];
189 while (gr && (*gr != (char)NULL)) {
190 if (strcmp(name,gr) == 0) {
191 grouplst[i] = g->gr_gid;
192 i++;
193 gr = (char *)NULL;
194 break;
196 gr = g->gr_mem[++j];
199 endgrent();
200 ret = setgroups(i, grouplst);
201 free(grouplst);
202 return ret;
203 #endif /* HAVE_SETGROUPS */
205 #endif /* HAVE_INITGROUPS */
208 #if (defined(SecureWare) && defined(SCO))
209 /* This is needed due to needing the nap() function but we don't want
210 to include the Xenix libraries since that will break other things...
211 BTW: system call # 0x0c28 is the same as calling nap() */
212 long nap(long milliseconds) {
213 return syscall(0x0c28, milliseconds);
215 #endif
218 #ifndef HAVE_MEMMOVE
219 /*******************************************************************
220 safely copies memory, ensuring no overlap problems.
221 this is only used if the machine does not have its own memmove().
222 this is not the fastest algorithm in town, but it will do for our
223 needs.
224 ********************************************************************/
225 void *rep_memmove(void *dest,const void *src,int size)
227 unsigned long d,s;
228 int i;
229 if (dest==src || !size) return(dest);
231 d = (unsigned long)dest;
232 s = (unsigned long)src;
234 if ((d >= (s+size)) || (s >= (d+size))) {
235 /* no overlap */
236 memcpy(dest,src,size);
237 return(dest);
240 if (d < s) {
241 /* we can forward copy */
242 if (s-d >= sizeof(int) &&
243 !(s%sizeof(int)) &&
244 !(d%sizeof(int)) &&
245 !(size%sizeof(int))) {
246 /* do it all as words */
247 int *idest = (int *)dest;
248 int *isrc = (int *)src;
249 size /= sizeof(int);
250 for (i=0;i<size;i++) idest[i] = isrc[i];
251 } else {
252 /* simplest */
253 char *cdest = (char *)dest;
254 char *csrc = (char *)src;
255 for (i=0;i<size;i++) cdest[i] = csrc[i];
257 } else {
258 /* must backward copy */
259 if (d-s >= sizeof(int) &&
260 !(s%sizeof(int)) &&
261 !(d%sizeof(int)) &&
262 !(size%sizeof(int))) {
263 /* do it all as words */
264 int *idest = (int *)dest;
265 int *isrc = (int *)src;
266 size /= sizeof(int);
267 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
268 } else {
269 /* simplest */
270 char *cdest = (char *)dest;
271 char *csrc = (char *)src;
272 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
275 return(dest);
277 #endif /* HAVE_MEMMOVE */
279 #ifndef HAVE_STRDUP
280 /****************************************************************************
281 duplicate a string
282 ****************************************************************************/
283 char *rep_strdup(const char *s)
285 size_t len;
286 char *ret;
288 if (!s) return(NULL);
290 len = strlen(s)+1;
291 ret = (char *)malloc(len);
292 if (!ret) return(NULL);
293 memcpy(ret,s,len);
294 return(ret);
296 #endif /* HAVE_STRDUP */
298 #ifndef HAVE_SETLINEBUF
299 void rep_setlinebuf(FILE *stream)
301 setvbuf(stream, (char *)NULL, _IOLBF, 0);
303 #endif /* HAVE_SETLINEBUF */
305 #ifndef HAVE_VSYSLOG
306 #ifdef HAVE_SYSLOG
307 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
309 char *msg = NULL;
310 vasprintf(&msg, format, arglist);
311 if (!msg)
312 return;
313 syslog(facility_priority, "%s", msg);
314 free(msg);
316 #endif /* HAVE_SYSLOG */
317 #endif /* HAVE_VSYSLOG */
319 #ifndef HAVE_STRNLEN
321 Some platforms don't have strnlen
323 size_t rep_strnlen(const char *s, size_t max)
325 size_t len;
327 for (len = 0; len < max; len++) {
328 if (s[len] == '\0') {
329 break;
332 return len;
334 #endif
336 #ifndef HAVE_STRNDUP
338 Some platforms don't have strndup.
340 char *rep_strndup(const char *s, size_t n)
342 char *ret;
344 n = strnlen(s, n);
345 ret = malloc(n+1);
346 if (!ret)
347 return NULL;
348 memcpy(ret, s, n);
349 ret[n] = 0;
351 return ret;
353 #endif
355 #ifndef HAVE_WAITPID
356 int rep_waitpid(pid_t pid,int *status,int options)
358 return wait4(pid, status, options, NULL);
360 #endif
362 #ifndef HAVE_SETEUID
363 int rep_seteuid(uid_t euid)
365 #ifdef HAVE_SETRESUID
366 return setresuid(-1, euid, -1);
367 #else
368 # error "You need a seteuid function"
369 #endif
371 #endif
373 #ifndef HAVE_SETEGID
374 int rep_setegid(gid_t egid)
376 #ifdef HAVE_SETRESGID
377 return setresgid(-1, egid, -1);
378 #else
379 # error "You need a setegid function"
380 #endif
382 #endif
384 /*******************************************************************
385 os/2 also doesn't have chroot
386 ********************************************************************/
387 #ifndef HAVE_CHROOT
388 int rep_chroot(const char *dname)
390 errno = ENOSYS;
391 return -1;
393 #endif
395 /*****************************************************************
396 Possibly replace mkstemp if it is broken.
397 *****************************************************************/
399 #ifndef HAVE_SECURE_MKSTEMP
400 int rep_mkstemp(char *template)
402 /* have a reasonable go at emulating it. Hope that
403 the system mktemp() isn't completly hopeless */
404 char *p = mktemp(template);
405 if (!p)
406 return -1;
407 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
409 #endif
411 #ifndef HAVE_MKDTEMP
412 char *rep_mkdtemp(char *template)
414 char *dname;
416 if ((dname = mktemp(template))) {
417 if (mkdir(dname, 0700) >= 0) {
418 return dname;
422 return NULL;
424 #endif
426 /*****************************************************************
427 Watch out: this is not thread safe.
428 *****************************************************************/
430 #ifndef HAVE_PREAD
431 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
433 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
434 return -1;
436 return read(__fd, __buf, __nbytes);
438 #endif
440 /*****************************************************************
441 Watch out: this is not thread safe.
442 *****************************************************************/
444 #ifndef HAVE_PWRITE
445 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
447 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
448 return -1;
450 return write(__fd, __buf, __nbytes);
452 #endif
454 #ifndef HAVE_STRCASESTR
455 char *rep_strcasestr(const char *haystack, const char *needle)
457 const char *s;
458 size_t nlen = strlen(needle);
459 for (s=haystack;*s;s++) {
460 if (toupper(*needle) == toupper(*s) &&
461 strncasecmp(s, needle, nlen) == 0) {
462 return (char *)((intptr_t)s);
465 return NULL;
467 #endif
469 #ifndef HAVE_STRTOK_R
470 /* based on GLIBC version, copyright Free Software Foundation */
471 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
473 char *token;
475 if (s == NULL) s = *save_ptr;
477 s += strspn(s, delim);
478 if (*s == '\0') {
479 *save_ptr = s;
480 return NULL;
483 token = s;
484 s = strpbrk(token, delim);
485 if (s == NULL) {
486 *save_ptr = token + strlen(token);
487 } else {
488 *s = '\0';
489 *save_ptr = s + 1;
492 return token;
494 #endif
496 #ifndef HAVE_STRTOLL
497 long long int rep_strtoll(const char *str, char **endptr, int base)
499 #ifdef HAVE_STRTOQ
500 return strtoq(str, endptr, base);
501 #elif defined(HAVE___STRTOLL)
502 return __strtoll(str, endptr, base);
503 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
504 return (long long int) strtol(str, endptr, base);
505 #else
506 # error "You need a strtoll function"
507 #endif
509 #endif
512 #ifndef HAVE_STRTOULL
513 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
515 #ifdef HAVE_STRTOUQ
516 return strtouq(str, endptr, base);
517 #elif defined(HAVE___STRTOULL)
518 return __strtoull(str, endptr, base);
519 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
520 return (unsigned long long int) strtoul(str, endptr, base);
521 #else
522 # error "You need a strtoull function"
523 #endif
525 #endif
527 #ifndef HAVE_SETENV
528 int rep_setenv(const char *name, const char *value, int overwrite)
530 char *p;
531 size_t l1, l2;
532 int ret;
534 if (!overwrite && getenv(name)) {
535 return 0;
538 l1 = strlen(name);
539 l2 = strlen(value);
541 p = malloc(l1+l2+2);
542 if (p == NULL) {
543 return -1;
545 memcpy(p, name, l1);
546 p[l1] = '=';
547 memcpy(p+l1+1, value, l2);
548 p[l1+l2+1] = 0;
550 ret = putenv(p);
551 if (ret != 0) {
552 free(p);
555 return ret;
557 #endif
559 #ifndef HAVE_UNSETENV
560 int rep_unsetenv(const char *name)
562 extern char **environ;
563 size_t len = strlen(name);
564 size_t i, count;
566 if (environ == NULL || getenv(name) == NULL) {
567 return 0;
570 for (i=0;environ[i];i++) /* noop */ ;
572 count=i;
574 for (i=0;i<count;) {
575 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
576 /* note: we do _not_ free the old variable here. It is unsafe to
577 do so, as the pointer may not have come from malloc */
578 memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
579 count--;
580 } else {
581 i++;
585 return 0;
587 #endif
589 #ifndef HAVE_SOCKETPAIR
590 int rep_socketpair(int d, int type, int protocol, int sv[2])
592 if (d != AF_UNIX) {
593 errno = EAFNOSUPPORT;
594 return -1;
597 if (protocol != 0) {
598 errno = EPROTONOSUPPORT;
599 return -1;
602 if (type != SOCK_STREAM) {
603 errno = EOPNOTSUPP;
604 return -1;
607 return pipe(sv);
609 #endif