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