1 /*
2    Unix SMB/CIFS implementation.
3    replacement routines for broken systems
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jelmer Vernooij 2005-2008
6    Copyright (C) Matthieu Patou  2010
7 
8      ** NOTE! The following LGPL license applies to the replace
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11 
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16 
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21 
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25 
26 #include "replace.h"
27 
28 #include "system/filesys.h"
29 #include "system/time.h"
30 #include "system/network.h"
31 #include "system/passwd.h"
32 #include "system/syslog.h"
33 #include "system/locale.h"
34 #include "system/wait.h"
35 
36 #ifdef _WIN32
37 #define mkdir(d,m) _mkdir(d)
38 #endif
39 
40 void replace_dummy(void);
replace_dummy(void)41 void replace_dummy(void) {}
42 
43 #ifndef HAVE_FTRUNCATE
44  /*******************************************************************
45 ftruncate for operating systems that don't have it
46 ********************************************************************/
rep_ftruncate(int f,off_t l)47 int rep_ftruncate(int f, off_t l)
48 {
49 #ifdef HAVE_CHSIZE
50       return chsize(f,l);
51 #elif defined(F_FREESP)
52       struct  flock   fl;
53 
54       fl.l_whence = 0;
55       fl.l_len = 0;
56       fl.l_start = l;
57       fl.l_type = F_WRLCK;
58       return fcntl(f, F_FREESP, &fl);
59 #else
60 #error "you must have a ftruncate function"
61 #endif
62 }
63 #endif /* HAVE_FTRUNCATE */
64 
65 
66 #ifndef HAVE_STRLCPY
67 /*
68  * Like strncpy but does not 0 fill the buffer and always null
69  * terminates. bufsize is the size of the destination buffer.
70  * Returns the length of s.
71  */
rep_strlcpy(char * d,const char * s,size_t bufsize)72 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
73 {
74 	size_t len = strlen(s);
75 	size_t ret = len;
76 
77 	if (bufsize <= 0) {
78 		return 0;
79 	}
80 	if (len >= bufsize) {
81 		len = bufsize - 1;
82 	}
83 	memcpy(d, s, len);
84 	d[len] = 0;
85 	return ret;
86 }
87 #endif
88 
89 #ifndef HAVE_STRLCAT
90 /* like strncat but does not 0 fill the buffer and always null
91    terminates. bufsize is the length of the buffer, which should
92    be one more than the maximum resulting string length */
rep_strlcat(char * d,const char * s,size_t bufsize)93 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
94 {
95 	size_t len1 = strnlen(d, bufsize);
96 	size_t len2 = strlen(s);
97 	size_t ret = len1 + len2;
98 
99 	if (len1+len2 >= bufsize) {
100 		if (bufsize < (len1+1)) {
101 			return ret;
102 		}
103 		len2 = bufsize - (len1+1);
104 	}
105 	if (len2 > 0) {
106 		memcpy(d+len1, s, len2);
107 		d[len1+len2] = 0;
108 	}
109 	return ret;
110 }
111 #endif
112 
113 #ifndef HAVE_MKTIME
114 /*******************************************************************
115 a mktime() replacement for those who don't have it - contributed by
116 C.A. Lademann <cal@zls.com>
117 Corrections by richard.kettlewell@kewill.com
118 ********************************************************************/
119 
120 #define  MINUTE  60
121 #define  HOUR    60*MINUTE
122 #define  DAY             24*HOUR
123 #define  YEAR    365*DAY
rep_mktime(struct tm * t)124 time_t rep_mktime(struct tm *t)
125 {
126   struct tm       *u;
127   time_t  epoch = 0;
128   int n;
129   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
130   y, m, i;
131 
132   if(t->tm_year < 70)
133     return((time_t)-1);
134 
135   n = t->tm_year + 1900 - 1;
136   epoch = (t->tm_year - 70) * YEAR +
137     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
138 
139   y = t->tm_year + 1900;
140   m = 0;
141 
142   for(i = 0; i < t->tm_mon; i++) {
143     epoch += mon [m] * DAY;
144     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
145       epoch += DAY;
146 
147     if(++m > 11) {
148       m = 0;
149       y++;
150     }
151   }
152 
153   epoch += (t->tm_mday - 1) * DAY;
154   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
155 
156   if((u = localtime(&epoch)) != NULL) {
157     t->tm_sec = u->tm_sec;
158     t->tm_min = u->tm_min;
159     t->tm_hour = u->tm_hour;
160     t->tm_mday = u->tm_mday;
161     t->tm_mon = u->tm_mon;
162     t->tm_year = u->tm_year;
163     t->tm_wday = u->tm_wday;
164     t->tm_yday = u->tm_yday;
165     t->tm_isdst = u->tm_isdst;
166   }
167 
168   return(epoch);
169 }
170 #endif /* !HAVE_MKTIME */
171 
172 
173 #ifndef HAVE_INITGROUPS
174 /****************************************************************************
175  some systems don't have an initgroups call
176 ****************************************************************************/
rep_initgroups(char * name,gid_t id)177 int rep_initgroups(char *name, gid_t id)
178 {
179 #ifndef HAVE_SETGROUPS
180 	/* yikes! no SETGROUPS or INITGROUPS? how can this work? */
181 	errno = ENOSYS;
182 	return -1;
183 #else /* HAVE_SETGROUPS */
184 
185 #include <grp.h>
186 
187 	gid_t *grouplst = NULL;
188 	int max_gr = NGROUPS_MAX;
189 	int ret;
190 	int    i,j;
191 	struct group *g;
192 	char   *gr;
193 
194 	if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
195 		errno = ENOMEM;
196 		return -1;
197 	}
198 
199 	grouplst[0] = id;
200 	i = 1;
201 	while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
202 		if (g->gr_gid == id)
203 			continue;
204 		j = 0;
205 		gr = g->gr_mem[0];
206 		while (gr && (*gr != (char)NULL)) {
207 			if (strcmp(name,gr) == 0) {
208 				grouplst[i] = g->gr_gid;
209 				i++;
210 				gr = (char *)NULL;
211 				break;
212 			}
213 			gr = g->gr_mem[++j];
214 		}
215 	}
216 	endgrent();
217 	ret = setgroups(i, grouplst);
218 	free(grouplst);
219 	return ret;
220 #endif /* HAVE_SETGROUPS */
221 }
222 #endif /* HAVE_INITGROUPS */
223 
224 
225 #ifndef HAVE_MEMMOVE
226 /*******************************************************************
227 safely copies memory, ensuring no overlap problems.
228 this is only used if the machine does not have its own memmove().
229 this is not the fastest algorithm in town, but it will do for our
230 needs.
231 ********************************************************************/
rep_memmove(void * dest,const void * src,int size)232 void *rep_memmove(void *dest,const void *src,int size)
233 {
234 	unsigned long d,s;
235 	int i;
236 	if (dest==src || !size) return(dest);
237 
238 	d = (unsigned long)dest;
239 	s = (unsigned long)src;
240 
241 	if ((d >= (s+size)) || (s >= (d+size))) {
242 		/* no overlap */
243 		memcpy(dest,src,size);
244 		return(dest);
245 	}
246 
247 	if (d < s) {
248 		/* we can forward copy */
249 		if (s-d >= sizeof(int) &&
250 		    !(s%sizeof(int)) &&
251 		    !(d%sizeof(int)) &&
252 		    !(size%sizeof(int))) {
253 			/* do it all as words */
254 			int *idest = (int *)dest;
255 			int *isrc = (int *)src;
256 			size /= sizeof(int);
257 			for (i=0;i<size;i++) idest[i] = isrc[i];
258 		} else {
259 			/* simplest */
260 			char *cdest = (char *)dest;
261 			char *csrc = (char *)src;
262 			for (i=0;i<size;i++) cdest[i] = csrc[i];
263 		}
264 	} else {
265 		/* must backward copy */
266 		if (d-s >= sizeof(int) &&
267 		    !(s%sizeof(int)) &&
268 		    !(d%sizeof(int)) &&
269 		    !(size%sizeof(int))) {
270 			/* do it all as words */
271 			int *idest = (int *)dest;
272 			int *isrc = (int *)src;
273 			size /= sizeof(int);
274 			for (i=size-1;i>=0;i--) idest[i] = isrc[i];
275 		} else {
276 			/* simplest */
277 			char *cdest = (char *)dest;
278 			char *csrc = (char *)src;
279 			for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
280 		}
281 	}
282 	return(dest);
283 }
284 #endif /* HAVE_MEMMOVE */
285 
286 #ifndef HAVE_STRDUP
287 /****************************************************************************
288 duplicate a string
289 ****************************************************************************/
rep_strdup(const char * s)290 char *rep_strdup(const char *s)
291 {
292 	size_t len;
293 	char *ret;
294 
295 	if (!s) return(NULL);
296 
297 	len = strlen(s)+1;
298 	ret = (char *)malloc(len);
299 	if (!ret) return(NULL);
300 	memcpy(ret,s,len);
301 	return(ret);
302 }
303 #endif /* HAVE_STRDUP */
304 
305 #ifndef HAVE_SETLINEBUF
rep_setlinebuf(FILE * stream)306 void rep_setlinebuf(FILE *stream)
307 {
308 	setvbuf(stream, (char *)NULL, _IOLBF, 0);
309 }
310 #endif /* HAVE_SETLINEBUF */
311 
312 #ifndef HAVE_VSYSLOG
313 #ifdef HAVE_SYSLOG
rep_vsyslog(int facility_priority,const char * format,va_list arglist)314 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
315 {
316 	char *msg = NULL;
317 	vasprintf(&msg, format, arglist);
318 	if (!msg)
319 		return;
320 	syslog(facility_priority, "%s", msg);
321 	free(msg);
322 }
323 #endif /* HAVE_SYSLOG */
324 #endif /* HAVE_VSYSLOG */
325 
326 #ifndef HAVE_STRNLEN
327 /**
328  Some platforms don't have strnlen
329 **/
rep_strnlen(const char * s,size_t max)330  size_t rep_strnlen(const char *s, size_t max)
331 {
332         size_t len;
333 
334         for (len = 0; len < max; len++) {
335                 if (s[len] == '\0') {
336                         break;
337                 }
338         }
339         return len;
340 }
341 #endif
342 
343 #ifndef HAVE_STRNDUP
344 /**
345  Some platforms don't have strndup.
346 **/
rep_strndup(const char * s,size_t n)347 char *rep_strndup(const char *s, size_t n)
348 {
349 	char *ret;
350 
351 	n = strnlen(s, n);
352 	ret = malloc(n+1);
353 	if (!ret)
354 		return NULL;
355 	memcpy(ret, s, n);
356 	ret[n] = 0;
357 
358 	return ret;
359 }
360 #endif
361 
362 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
rep_waitpid(pid_t pid,int * status,int options)363 int rep_waitpid(pid_t pid,int *status,int options)
364 {
365   return wait4(pid, status, options, NULL);
366 }
367 #endif
368 
369 #ifndef HAVE_SETEUID
rep_seteuid(uid_t euid)370 int rep_seteuid(uid_t euid)
371 {
372 #ifdef HAVE_SETRESUID
373 	return setresuid(-1, euid, -1);
374 #else
375 	errno = ENOSYS;
376 	return -1;
377 #endif
378 }
379 #endif
380 
381 #ifndef HAVE_SETEGID
rep_setegid(gid_t egid)382 int rep_setegid(gid_t egid)
383 {
384 #ifdef HAVE_SETRESGID
385 	return setresgid(-1, egid, -1);
386 #else
387 	errno = ENOSYS;
388 	return -1;
389 #endif
390 }
391 #endif
392 
393 /*******************************************************************
394 os/2 also doesn't have chroot
395 ********************************************************************/
396 #ifndef HAVE_CHROOT
rep_chroot(const char * dname)397 int rep_chroot(const char *dname)
398 {
399 	errno = ENOSYS;
400 	return -1;
401 }
402 #endif
403 
404 /*****************************************************************
405  Possibly replace mkstemp if it is broken.
406 *****************************************************************/
407 
408 #ifndef HAVE_SECURE_MKSTEMP
rep_mkstemp(char * template)409 int rep_mkstemp(char *template)
410 {
411 	/* have a reasonable go at emulating it. Hope that
412 	   the system mktemp() isn't completely hopeless */
413 	mktemp(template);
414 	if (template[0] == 0)
415 		return -1;
416 	return open(template, O_CREAT|O_EXCL|O_RDWR, 0600);
417 }
418 #endif
419 
420 #ifndef HAVE_MKDTEMP
rep_mkdtemp(char * template)421 char *rep_mkdtemp(char *template)
422 {
423 	char *dname;
424 
425 	if ((dname = mktemp(template))) {
426 		if (mkdir(dname, 0700) >= 0) {
427 			return dname;
428 		}
429 	}
430 
431 	return NULL;
432 }
433 #endif
434 
435 /*****************************************************************
436  Watch out: this is not thread safe.
437 *****************************************************************/
438 
439 #ifndef HAVE_PREAD
rep_pread(int __fd,void * __buf,size_t __nbytes,off_t __offset)440 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
441 {
442 	if (lseek(__fd, __offset, SEEK_SET) != __offset) {
443 		return -1;
444 	}
445 	return read(__fd, __buf, __nbytes);
446 }
447 #endif
448 
449 /*****************************************************************
450  Watch out: this is not thread safe.
451 *****************************************************************/
452 
453 #ifndef HAVE_PWRITE
rep_pwrite(int __fd,const void * __buf,size_t __nbytes,off_t __offset)454 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
455 {
456 	if (lseek(__fd, __offset, SEEK_SET) != __offset) {
457 		return -1;
458 	}
459 	return write(__fd, __buf, __nbytes);
460 }
461 #endif
462 
463 #ifndef HAVE_STRCASESTR
rep_strcasestr(const char * haystack,const char * needle)464 char *rep_strcasestr(const char *haystack, const char *needle)
465 {
466 	const char *s;
467 	size_t nlen = strlen(needle);
468 	for (s=haystack;*s;s++) {
469 		if (toupper(*needle) == toupper(*s) &&
470 		    strncasecmp(s, needle, nlen) == 0) {
471 			return (char *)((uintptr_t)s);
472 		}
473 	}
474 	return NULL;
475 }
476 #endif
477 
478 #ifndef HAVE_STRSEP
rep_strsep(char ** pps,const char * delim)479 char *rep_strsep(char **pps, const char *delim)
480 {
481 	char *ret = *pps;
482 	char *p = *pps;
483 
484 	if (p == NULL) {
485 		return NULL;
486 	}
487 	p += strcspn(p, delim);
488 	if (*p == '\0') {
489 		*pps = NULL;
490 	} else {
491 		*p = '\0';
492 		*pps = p + 1;
493 	}
494 	return ret;
495 }
496 #endif
497 
498 #ifndef HAVE_STRTOK_R
499 /* based on GLIBC version, copyright Free Software Foundation */
rep_strtok_r(char * s,const char * delim,char ** save_ptr)500 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
501 {
502 	char *token;
503 
504 	if (s == NULL) s = *save_ptr;
505 
506 	s += strspn(s, delim);
507 	if (*s == '\0') {
508 		*save_ptr = s;
509 		return NULL;
510 	}
511 
512 	token = s;
513 	s = strpbrk(token, delim);
514 	if (s == NULL) {
515 		*save_ptr = token + strlen(token);
516 	} else {
517 		*s = '\0';
518 		*save_ptr = s + 1;
519 	}
520 
521 	return token;
522 }
523 #endif
524 
525 
526 #ifndef HAVE_STRTOLL
rep_strtoll(const char * str,char ** endptr,int base)527 long long int rep_strtoll(const char *str, char **endptr, int base)
528 {
529 #ifdef HAVE_STRTOQ
530 	return strtoq(str, endptr, base);
531 #elif defined(HAVE___STRTOLL)
532 	return __strtoll(str, endptr, base);
533 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
534 	return (long long int) strtol(str, endptr, base);
535 #else
536 # error "You need a strtoll function"
537 #endif
538 }
539 #else
540 #ifdef HAVE_BSD_STRTOLL
541 #undef strtoll
rep_strtoll(const char * str,char ** endptr,int base)542 long long int rep_strtoll(const char *str, char **endptr, int base)
543 {
544 	int saved_errno = errno;
545 	long long int nb = strtoll(str, endptr, base);
546 	/* With glibc EINVAL is only returned if base is not ok */
547 	if (errno == EINVAL) {
548 		if (base == 0 || (base >1 && base <37)) {
549 			/* Base was ok so it's because we were not
550 			 * able to make the conversion.
551 			 * Let's reset errno.
552 			 */
553 			errno = saved_errno;
554 		}
555 	}
556 	return nb;
557 }
558 #endif /* HAVE_BSD_STRTOLL */
559 #endif /* HAVE_STRTOLL */
560 
561 
562 #ifndef HAVE_STRTOULL
rep_strtoull(const char * str,char ** endptr,int base)563 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
564 {
565 #ifdef HAVE_STRTOUQ
566 	return strtouq(str, endptr, base);
567 #elif defined(HAVE___STRTOULL)
568 	return __strtoull(str, endptr, base);
569 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
570 	return (unsigned long long int) strtoul(str, endptr, base);
571 #else
572 # error "You need a strtoull function"
573 #endif
574 }
575 #else
576 #ifdef HAVE_BSD_STRTOLL
577 #undef strtoull
rep_strtoull(const char * str,char ** endptr,int base)578 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
579 {
580 	int saved_errno = errno;
581 	unsigned long long int nb = strtoull(str, endptr, base);
582 	/* With glibc EINVAL is only returned if base is not ok */
583 	if (errno == EINVAL) {
584 		if (base == 0 || (base >1 && base <37)) {
585 			/* Base was ok so it's because we were not
586 			 * able to make the conversion.
587 			 * Let's reset errno.
588 			 */
589 			errno = saved_errno;
590 		}
591 	}
592 	return nb;
593 }
594 #endif /* HAVE_BSD_STRTOLL */
595 #endif /* HAVE_STRTOULL */
596 
597 #ifndef HAVE_SETENV
rep_setenv(const char * name,const char * value,int overwrite)598 int rep_setenv(const char *name, const char *value, int overwrite)
599 {
600 	char *p;
601 	size_t l1, l2;
602 	int ret;
603 
604 	if (!overwrite && getenv(name)) {
605 		return 0;
606 	}
607 
608 	l1 = strlen(name);
609 	l2 = strlen(value);
610 
611 	p = malloc(l1+l2+2);
612 	if (p == NULL) {
613 		return -1;
614 	}
615 	memcpy(p, name, l1);
616 	p[l1] = '=';
617 	memcpy(p+l1+1, value, l2);
618 	p[l1+l2+1] = 0;
619 
620 	ret = putenv(p);
621 	if (ret != 0) {
622 		free(p);
623 	}
624 
625 	return ret;
626 }
627 #endif
628 
629 #ifndef HAVE_UNSETENV
rep_unsetenv(const char * name)630 int rep_unsetenv(const char *name)
631 {
632 	extern char **environ;
633 	size_t len = strlen(name);
634 	size_t i, count;
635 
636 	if (environ == NULL || getenv(name) == NULL) {
637 		return 0;
638 	}
639 
640 	for (i=0;environ[i];i++) /* noop */ ;
641 
642 	count=i;
643 
644 	for (i=0;i<count;) {
645 		if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
646 			/* note: we do _not_ free the old variable here. It is unsafe to
647 			   do so, as the pointer may not have come from malloc */
648 			memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
649 			count--;
650 		} else {
651 			i++;
652 		}
653 	}
654 
655 	return 0;
656 }
657 #endif
658 
659 #ifndef HAVE_UTIME
rep_utime(const char * filename,const struct utimbuf * buf)660 int rep_utime(const char *filename, const struct utimbuf *buf)
661 {
662 	errno = ENOSYS;
663 	return -1;
664 }
665 #endif
666 
667 #ifndef HAVE_UTIMES
rep_utimes(const char * filename,const struct timeval tv[2])668 int rep_utimes(const char *filename, const struct timeval tv[2])
669 {
670 	struct utimbuf u;
671 
672 	u.actime = tv[0].tv_sec;
673 	if (tv[0].tv_usec > 500000) {
674 		u.actime += 1;
675 	}
676 
677 	u.modtime = tv[1].tv_sec;
678 	if (tv[1].tv_usec > 500000) {
679 		u.modtime += 1;
680 	}
681 
682 	return utime(filename, &u);
683 }
684 #endif
685 
686 #ifndef HAVE_DUP2
rep_dup2(int oldfd,int newfd)687 int rep_dup2(int oldfd, int newfd)
688 {
689 	errno = ENOSYS;
690 	return -1;
691 }
692 #endif
693 
694 #ifndef HAVE_CHOWN
695 /**
696 chown isn't used much but OS/2 doesn't have it
697 **/
rep_chown(const char * fname,uid_t uid,gid_t gid)698 int rep_chown(const char *fname, uid_t uid, gid_t gid)
699 {
700 	errno = ENOSYS;
701 	return -1;
702 }
703 #endif
704 
705 #ifndef HAVE_LINK
rep_link(const char * oldpath,const char * newpath)706 int rep_link(const char *oldpath, const char *newpath)
707 {
708 	errno = ENOSYS;
709 	return -1;
710 }
711 #endif
712 
713 #ifndef HAVE_READLINK
rep_readlink(const char * path,char * buf,size_t bufsiz)714 int rep_readlink(const char *path, char *buf, size_t bufsiz)
715 {
716 	errno = ENOSYS;
717 	return -1;
718 }
719 #endif
720 
721 #ifndef HAVE_SYMLINK
rep_symlink(const char * oldpath,const char * newpath)722 int rep_symlink(const char *oldpath, const char *newpath)
723 {
724 	errno = ENOSYS;
725 	return -1;
726 }
727 #endif
728 
729 #ifndef HAVE_LCHOWN
rep_lchown(const char * fname,uid_t uid,gid_t gid)730 int rep_lchown(const char *fname,uid_t uid,gid_t gid)
731 {
732 	errno = ENOSYS;
733 	return -1;
734 }
735 #endif
736 
737 #ifndef HAVE_REALPATH
rep_realpath(const char * path,char * resolved_path)738 char *rep_realpath(const char *path, char *resolved_path)
739 {
740 	/* As realpath is not a system call we can't return ENOSYS. */
741 	errno = EINVAL;
742 	return NULL;
743 }
744 #endif
745 
746 
747 #ifndef HAVE_MEMMEM
rep_memmem(const void * haystack,size_t haystacklen,const void * needle,size_t needlelen)748 void *rep_memmem(const void *haystack, size_t haystacklen,
749 		 const void *needle, size_t needlelen)
750 {
751 	if (needlelen == 0) {
752 		return discard_const(haystack);
753 	}
754 	while (haystacklen >= needlelen) {
755 		char *p = (char *)memchr(haystack, *(const char *)needle,
756 					 haystacklen-(needlelen-1));
757 		if (!p) return NULL;
758 		if (memcmp(p, needle, needlelen) == 0) {
759 			return p;
760 		}
761 		haystack = p+1;
762 		haystacklen -= (p - (const char *)haystack) + 1;
763 	}
764 	return NULL;
765 }
766 #endif
767 
768 #if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
rep_vdprintf(int fd,const char * format,va_list ap)769 int rep_vdprintf(int fd, const char *format, va_list ap)
770 {
771 	char *s = NULL;
772 	int ret;
773 
774 	vasprintf(&s, format, ap);
775 	if (s == NULL) {
776 		errno = ENOMEM;
777 		return -1;
778 	}
779 	ret = write(fd, s, strlen(s));
780 	free(s);
781 	return ret;
782 }
783 #endif
784 
785 #if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
rep_dprintf(int fd,const char * format,...)786 int rep_dprintf(int fd, const char *format, ...)
787 {
788 	int ret;
789 	va_list ap;
790 
791 	va_start(ap, format);
792 	ret = vdprintf(fd, format, ap);
793 	va_end(ap);
794 
795 	return ret;
796 }
797 #endif
798 
799 #ifndef HAVE_GET_CURRENT_DIR_NAME
rep_get_current_dir_name(void)800 char *rep_get_current_dir_name(void)
801 {
802 	char buf[PATH_MAX+1];
803 	char *p;
804 	p = getcwd(buf, sizeof(buf));
805 	if (p == NULL) {
806 		return NULL;
807 	}
808 	return strdup(p);
809 }
810 #endif
811 
812 #ifndef HAVE_STRERROR_R
rep_strerror_r(int errnum,char * buf,size_t buflen)813 int rep_strerror_r(int errnum, char *buf, size_t buflen)
814 {
815 	char *s = strerror(errnum);
816 	if (strlen(s)+1 > buflen) {
817 		errno = ERANGE;
818 		return -1;
819 	}
820 	strncpy(buf, s, buflen);
821 	return 0;
822 }
823 #elif (!defined(STRERROR_R_XSI_NOT_GNU))
824 #undef strerror_r
rep_strerror_r(int errnum,char * buf,size_t buflen)825 int rep_strerror_r(int errnum, char *buf, size_t buflen)
826 {
827 	char *s = strerror_r(errnum, buf, buflen);
828 	if (s == NULL) {
829 		/* Shouldn't happen, should always get a string */
830 		return EINVAL;
831 	}
832 	if (s != buf) {
833 		strlcpy(buf, s, buflen);
834 		if (strlen(s) > buflen - 1) {
835 			return ERANGE;
836 		}
837 	}
838 	return 0;
839 
840 }
841 #endif
842 
843 #ifndef HAVE_CLOCK_GETTIME
rep_clock_gettime(clockid_t clk_id,struct timespec * tp)844 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
845 {
846 	struct timeval tval;
847 	switch (clk_id) {
848 		case 0: /* CLOCK_REALTIME :*/
849 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
850 			gettimeofday(&tval,NULL);
851 #else
852 			gettimeofday(&tval);
853 #endif
854 			tp->tv_sec = tval.tv_sec;
855 			tp->tv_nsec = tval.tv_usec * 1000;
856 			break;
857 		default:
858 			errno = EINVAL;
859 			return -1;
860 	}
861 	return 0;
862 }
863 #endif
864 
865 #ifndef HAVE_MEMALIGN
rep_memalign(size_t align,size_t size)866 void *rep_memalign( size_t align, size_t size )
867 {
868 #if defined(HAVE_POSIX_MEMALIGN)
869 	void *p = NULL;
870 	int ret = posix_memalign( &p, align, size );
871 	if ( ret == 0 )
872 		return p;
873 
874 	return NULL;
875 #else
876 	/* On *BSD systems memaligns doesn't exist, but memory will
877 	 * be aligned on allocations of > pagesize. */
878 #if defined(SYSCONF_SC_PAGESIZE)
879 	size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
880 #elif defined(HAVE_GETPAGESIZE)
881 	size_t pagesize = (size_t)getpagesize();
882 #else
883 	size_t pagesize = (size_t)-1;
884 #endif
885 	if (pagesize == (size_t)-1) {
886 		errno = ENOSYS;
887 		return NULL;
888 	}
889 	if (size < pagesize) {
890 		size = pagesize;
891 	}
892 	return malloc(size);
893 #endif
894 }
895 #endif
896 
897 #ifndef HAVE_GETPEEREID
rep_getpeereid(int s,uid_t * uid,gid_t * gid)898 int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
899 {
900 #if defined(HAVE_PEERCRED)
901 	struct ucred cred;
902 	socklen_t cred_len = sizeof(struct ucred);
903 	int ret;
904 
905 #undef getsockopt
906 	ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
907 	if (ret != 0) {
908 		return -1;
909 	}
910 
911 	if (cred_len != sizeof(struct ucred)) {
912 		errno = EINVAL;
913 		return -1;
914 	}
915 
916 	*uid = cred.uid;
917 	*gid = cred.gid;
918 	return 0;
919 #else
920 	errno = ENOSYS;
921 	return -1;
922 #endif
923 }
924 #endif
925 
926 #ifndef HAVE_USLEEP
rep_usleep(useconds_t sec)927 int rep_usleep(useconds_t sec)
928 {
929 	struct timeval tval;
930 	/*
931 	 * Fake it with select...
932 	 */
933 	tval.tv_sec = 0;
934 	tval.tv_usec = usecs/1000;
935 	select(0,NULL,NULL,NULL,&tval);
936 	return 0;
937 }
938 #endif /* HAVE_USLEEP */
939 
940 #ifndef HAVE_SETPROCTITLE
rep_setproctitle(const char * fmt,...)941 void rep_setproctitle(const char *fmt, ...)
942 {
943 }
944 #endif
945 #ifndef HAVE_SETPROCTITLE_INIT
rep_setproctitle_init(int argc,char * argv[],char * envp[])946 void rep_setproctitle_init(int argc, char *argv[], char *envp[])
947 {
948 }
949 #endif
950 
951 #ifndef HAVE_MEMSET_S
952 # ifndef RSIZE_MAX
953 #  define RSIZE_MAX (SIZE_MAX >> 1)
954 # endif
955 
rep_memset_s(void * dest,size_t destsz,int ch,size_t count)956 int rep_memset_s(void *dest, size_t destsz, int ch, size_t count)
957 {
958 	if (dest == NULL) {
959 		return EINVAL;
960 	}
961 
962 	if (destsz > RSIZE_MAX ||
963 	    count > RSIZE_MAX ||
964 	    count > destsz) {
965 		return ERANGE;
966 	}
967 
968 #if defined(HAVE_MEMSET_EXPLICIT)
969 	memset_explicit(dest, destsz, ch, count);
970 #else /* HAVE_MEMSET_EXPLICIT */
971 	memset(dest, ch, count);
972 # if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
973 	/* See http://llvm.org/bugs/show_bug.cgi?id=15495 */
974 	__asm__ volatile("" : : "g"(dest) : "memory");
975 # endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
976 #endif /* HAVE_MEMSET_EXPLICIT */
977 
978 	return 0;
979 }
980 #endif /* HAVE_MEMSET_S */
981 
982 #ifndef HAVE_GETPROGNAME
983 # ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
984 # define PROGNAME_SIZE 32
985 static char rep_progname[PROGNAME_SIZE];
986 # endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
987 
rep_getprogname(void)988 const char *rep_getprogname(void)
989 {
990 #ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
991 	return program_invocation_short_name;
992 #else /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
993 	FILE *fp = NULL;
994 	char cmdline[4096] = {0};
995 	char *p = NULL;
996 	pid_t pid;
997 	size_t nread;
998 	int len;
999 	int rc;
1000 
1001 	if (rep_progname[0] != '\0') {
1002 		return rep_progname;
1003 	}
1004 
1005 	len = snprintf(rep_progname, sizeof(rep_progname), "%s", "<unknown>");
1006 	if (len <= 0) {
1007 		return NULL;
1008 	}
1009 
1010 	pid = getpid();
1011 	if (pid <= 1 || pid == (pid_t)-1) {
1012 		return NULL;
1013 	}
1014 
1015 	len = snprintf(cmdline,
1016 		       sizeof(cmdline),
1017 		       "/proc/%u/cmdline",
1018 		       (unsigned int)pid);
1019 	if (len <= 0 || len == sizeof(cmdline)) {
1020 		return NULL;
1021 	}
1022 
1023 	fp = fopen(cmdline, "r");
1024 	if (fp == NULL) {
1025 		return NULL;
1026 	}
1027 
1028 	nread = fread(cmdline, 1, sizeof(cmdline) - 1, fp);
1029 
1030 	rc = fclose(fp);
1031 	if (rc != 0) {
1032 		return NULL;
1033 	}
1034 
1035 	if (nread == 0) {
1036 		return NULL;
1037 	}
1038 
1039 	cmdline[nread] = '\0';
1040 
1041 	p = strrchr(cmdline, '/');
1042 	if (p != NULL) {
1043 		p++;
1044 	} else {
1045 		p = cmdline;
1046 	}
1047 
1048 	len = strlen(p);
1049 	if (len > PROGNAME_SIZE) {
1050 		p[PROGNAME_SIZE - 1] = '\0';
1051 	}
1052 
1053 	(void)snprintf(rep_progname, sizeof(rep_progname), "%s", p);
1054 
1055 	return rep_progname;
1056 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
1057 }
1058 #endif /* HAVE_GETPROGNAME */
1059