replace: Avoid DEBUG(), which is not available in libreplace.
[amitay/samba.git] / lib / replace / replace.c
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);
41 void replace_dummy(void) {}
42
43 #ifndef HAVE_FTRUNCATE
44  /*******************************************************************
45 ftruncate for operating systems that don't have it
46 ********************************************************************/
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 /* like strncpy but does not 0 fill the buffer and always null 
68    terminates. bufsize is the size of the destination buffer */
69 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
70 {
71         size_t len = strlen(s);
72         size_t ret = len;
73         if (bufsize <= 0) return 0;
74         if (len >= bufsize) len = bufsize-1;
75         memcpy(d, s, len);
76         d[len] = 0;
77         return ret;
78 }
79 #endif
80
81 #ifndef HAVE_STRLCAT
82 /* like strncat but does not 0 fill the buffer and always null 
83    terminates. bufsize is the length of the buffer, which should
84    be one more than the maximum resulting string length */
85 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
86 {
87         size_t len1 = strlen(d);
88         size_t len2 = strlen(s);
89         size_t ret = len1 + len2;
90
91         if (len1+len2 >= bufsize) {
92                 if (bufsize < (len1+1)) {
93                         return ret;
94                 }
95                 len2 = bufsize - (len1+1);
96         }
97         if (len2 > 0) {
98                 memcpy(d+len1, s, len2);
99                 d[len1+len2] = 0;
100         }
101         return ret;
102 }
103 #endif
104
105 #ifndef HAVE_MKTIME
106 /*******************************************************************
107 a mktime() replacement for those who don't have it - contributed by 
108 C.A. Lademann <cal@zls.com>
109 Corrections by richard.kettlewell@kewill.com
110 ********************************************************************/
111
112 #define  MINUTE  60
113 #define  HOUR    60*MINUTE
114 #define  DAY             24*HOUR
115 #define  YEAR    365*DAY
116 time_t rep_mktime(struct tm *t)
117 {
118   struct tm       *u;
119   time_t  epoch = 0;
120   int n;
121   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
122   y, m, i;
123
124   if(t->tm_year < 70)
125     return((time_t)-1);
126
127   n = t->tm_year + 1900 - 1;
128   epoch = (t->tm_year - 70) * YEAR + 
129     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
130
131   y = t->tm_year + 1900;
132   m = 0;
133
134   for(i = 0; i < t->tm_mon; i++) {
135     epoch += mon [m] * DAY;
136     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
137       epoch += DAY;
138     
139     if(++m > 11) {
140       m = 0;
141       y++;
142     }
143   }
144
145   epoch += (t->tm_mday - 1) * DAY;
146   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
147   
148   if((u = localtime(&epoch)) != NULL) {
149     t->tm_sec = u->tm_sec;
150     t->tm_min = u->tm_min;
151     t->tm_hour = u->tm_hour;
152     t->tm_mday = u->tm_mday;
153     t->tm_mon = u->tm_mon;
154     t->tm_year = u->tm_year;
155     t->tm_wday = u->tm_wday;
156     t->tm_yday = u->tm_yday;
157     t->tm_isdst = u->tm_isdst;
158   }
159
160   return(epoch);
161 }
162 #endif /* !HAVE_MKTIME */
163
164
165 #ifndef HAVE_INITGROUPS
166 /****************************************************************************
167  some systems don't have an initgroups call 
168 ****************************************************************************/
169 int rep_initgroups(char *name, gid_t id)
170 {
171 #ifndef HAVE_SETGROUPS
172         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
173         errno = ENOSYS;
174         return -1;
175 #else /* HAVE_SETGROUPS */
176
177 #include <grp.h>
178
179         gid_t *grouplst = NULL;
180         int max_gr = NGROUPS_MAX;
181         int ret;
182         int    i,j;
183         struct group *g;
184         char   *gr;
185         
186         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
187                 errno = ENOMEM;
188                 return -1;
189         }
190
191         grouplst[0] = id;
192         i = 1;
193         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
194                 if (g->gr_gid == id)
195                         continue;
196                 j = 0;
197                 gr = g->gr_mem[0];
198                 while (gr && (*gr != (char)NULL)) {
199                         if (strcmp(name,gr) == 0) {
200                                 grouplst[i] = g->gr_gid;
201                                 i++;
202                                 gr = (char *)NULL;
203                                 break;
204                         }
205                         gr = g->gr_mem[++j];
206                 }
207         }
208         endgrent();
209         ret = setgroups(i, grouplst);
210         free(grouplst);
211         return ret;
212 #endif /* HAVE_SETGROUPS */
213 }
214 #endif /* HAVE_INITGROUPS */
215
216
217 #if (defined(SecureWare) && defined(SCO))
218 /* This is needed due to needing the nap() function but we don't want
219    to include the Xenix libraries since that will break other things...
220    BTW: system call # 0x0c28 is the same as calling nap() */
221 long nap(long milliseconds) {
222          return syscall(0x0c28, milliseconds);
223  }
224 #endif
225
226
227 #ifndef HAVE_MEMMOVE
228 /*******************************************************************
229 safely copies memory, ensuring no overlap problems.
230 this is only used if the machine does not have its own memmove().
231 this is not the fastest algorithm in town, but it will do for our
232 needs.
233 ********************************************************************/
234 void *rep_memmove(void *dest,const void *src,int size)
235 {
236         unsigned long d,s;
237         int i;
238         if (dest==src || !size) return(dest);
239
240         d = (unsigned long)dest;
241         s = (unsigned long)src;
242
243         if ((d >= (s+size)) || (s >= (d+size))) {
244                 /* no overlap */
245                 memcpy(dest,src,size);
246                 return(dest);
247         }
248
249         if (d < s) {
250                 /* we can forward copy */
251                 if (s-d >= sizeof(int) && 
252                     !(s%sizeof(int)) && 
253                     !(d%sizeof(int)) && 
254                     !(size%sizeof(int))) {
255                         /* do it all as words */
256                         int *idest = (int *)dest;
257                         int *isrc = (int *)src;
258                         size /= sizeof(int);
259                         for (i=0;i<size;i++) idest[i] = isrc[i];
260                 } else {
261                         /* simplest */
262                         char *cdest = (char *)dest;
263                         char *csrc = (char *)src;
264                         for (i=0;i<size;i++) cdest[i] = csrc[i];
265                 }
266         } else {
267                 /* must backward copy */
268                 if (d-s >= sizeof(int) && 
269                     !(s%sizeof(int)) && 
270                     !(d%sizeof(int)) && 
271                     !(size%sizeof(int))) {
272                         /* do it all as words */
273                         int *idest = (int *)dest;
274                         int *isrc = (int *)src;
275                         size /= sizeof(int);
276                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
277                 } else {
278                         /* simplest */
279                         char *cdest = (char *)dest;
280                         char *csrc = (char *)src;
281                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
282                 }      
283         }
284         return(dest);
285 }
286 #endif /* HAVE_MEMMOVE */
287
288 #ifndef HAVE_STRDUP
289 /****************************************************************************
290 duplicate a string
291 ****************************************************************************/
292 char *rep_strdup(const char *s)
293 {
294         size_t len;
295         char *ret;
296
297         if (!s) return(NULL);
298
299         len = strlen(s)+1;
300         ret = (char *)malloc(len);
301         if (!ret) return(NULL);
302         memcpy(ret,s,len);
303         return(ret);
304 }
305 #endif /* HAVE_STRDUP */
306
307 #ifndef HAVE_SETLINEBUF
308 void rep_setlinebuf(FILE *stream)
309 {
310         setvbuf(stream, (char *)NULL, _IOLBF, 0);
311 }
312 #endif /* HAVE_SETLINEBUF */
313
314 #ifndef HAVE_VSYSLOG
315 #ifdef HAVE_SYSLOG
316 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
317 {
318         char *msg = NULL;
319         vasprintf(&msg, format, arglist);
320         if (!msg)
321                 return;
322         syslog(facility_priority, "%s", msg);
323         free(msg);
324 }
325 #endif /* HAVE_SYSLOG */
326 #endif /* HAVE_VSYSLOG */
327
328 #ifndef HAVE_STRNLEN
329 /**
330  Some platforms don't have strnlen
331 **/
332  size_t rep_strnlen(const char *s, size_t max)
333 {
334         size_t len;
335   
336         for (len = 0; len < max; len++) {
337                 if (s[len] == '\0') {
338                         break;
339                 }
340         }
341         return len;  
342 }
343 #endif
344   
345 #ifndef HAVE_STRNDUP
346 /**
347  Some platforms don't have strndup.
348 **/
349 char *rep_strndup(const char *s, size_t n)
350 {
351         char *ret;
352         
353         n = strnlen(s, n);
354         ret = malloc(n+1);
355         if (!ret)
356                 return NULL;
357         memcpy(ret, s, n);
358         ret[n] = 0;
359
360         return ret;
361 }
362 #endif
363
364 #if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
365 int rep_waitpid(pid_t pid,int *status,int options)
366 {
367   return wait4(pid, status, options, NULL);
368 }
369 #endif
370
371 #ifndef HAVE_SETEUID
372 int rep_seteuid(uid_t euid)
373 {
374 #ifdef HAVE_SETRESUID
375         return setresuid(-1, euid, -1);
376 #else
377         errno = ENOSYS;
378         return -1;
379 #endif
380 }
381 #endif
382
383 #ifndef HAVE_SETEGID
384 int rep_setegid(gid_t egid)
385 {
386 #ifdef HAVE_SETRESGID
387         return setresgid(-1, egid, -1);
388 #else
389         errno = ENOSYS;
390         return -1;
391 #endif
392 }
393 #endif
394
395 /*******************************************************************
396 os/2 also doesn't have chroot
397 ********************************************************************/
398 #ifndef HAVE_CHROOT
399 int rep_chroot(const char *dname)
400 {
401         errno = ENOSYS;
402         return -1;
403 }
404 #endif
405
406 /*****************************************************************
407  Possibly replace mkstemp if it is broken.
408 *****************************************************************/  
409
410 #ifndef HAVE_SECURE_MKSTEMP
411 int rep_mkstemp(char *template)
412 {
413         /* have a reasonable go at emulating it. Hope that
414            the system mktemp() isn't completely hopeless */
415         char *p = mktemp(template);
416         if (!p)
417                 return -1;
418         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
419 }
420 #endif
421
422 #ifndef HAVE_MKDTEMP
423 char *rep_mkdtemp(char *template)
424 {
425         char *dname;
426         
427         if ((dname = mktemp(template))) {
428                 if (mkdir(dname, 0700) >= 0) {
429                         return dname;
430                 }
431         }
432
433         return NULL;
434 }
435 #endif
436
437 /*****************************************************************
438  Watch out: this is not thread safe.
439 *****************************************************************/
440
441 #ifndef HAVE_PREAD
442 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
443 {
444         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
445                 return -1;
446         }
447         return read(__fd, __buf, __nbytes);
448 }
449 #endif
450
451 /*****************************************************************
452  Watch out: this is not thread safe.
453 *****************************************************************/
454
455 #ifndef HAVE_PWRITE
456 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
457 {
458         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
459                 return -1;
460         }
461         return write(__fd, __buf, __nbytes);
462 }
463 #endif
464
465 #ifndef HAVE_STRCASESTR
466 char *rep_strcasestr(const char *haystack, const char *needle)
467 {
468         const char *s;
469         size_t nlen = strlen(needle);
470         for (s=haystack;*s;s++) {
471                 if (toupper(*needle) == toupper(*s) &&
472                     strncasecmp(s, needle, nlen) == 0) {
473                         return (char *)((uintptr_t)s);
474                 }
475         }
476         return NULL;
477 }
478 #endif
479
480 #ifndef HAVE_STRTOK_R
481 /* based on GLIBC version, copyright Free Software Foundation */
482 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
483 {
484         char *token;
485
486         if (s == NULL) s = *save_ptr;
487
488         s += strspn(s, delim);
489         if (*s == '\0') {
490                 *save_ptr = s;
491                 return NULL;
492         }
493
494         token = s;
495         s = strpbrk(token, delim);
496         if (s == NULL) {
497                 *save_ptr = token + strlen(token);
498         } else {
499                 *s = '\0';
500                 *save_ptr = s + 1;
501         }
502
503         return token;
504 }
505 #endif
506
507
508 #ifndef HAVE_STRTOLL
509 long long int rep_strtoll(const char *str, char **endptr, int base)
510 {
511 #ifdef HAVE_STRTOQ
512         return strtoq(str, endptr, base);
513 #elif defined(HAVE___STRTOLL) 
514         return __strtoll(str, endptr, base);
515 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
516         return (long long int) strtol(str, endptr, base);
517 #else
518 # error "You need a strtoll function"
519 #endif
520 }
521 #else
522 #ifdef HAVE_BSD_STRTOLL
523 #ifdef HAVE_STRTOQ
524 long long int rep_strtoll(const char *str, char **endptr, int base)
525 {
526         long long int nb = strtoq(str, endptr, base);
527         /* In linux EINVAL is only returned if base is not ok */
528         if (errno == EINVAL) {
529                 if (base == 0 || (base >1 && base <37)) {
530                         /* Base was ok so it's because we were not
531                          * able to make the convertion.
532                          * Let's reset errno.
533                          */
534                         errno = 0;
535                 }
536         }
537         return nb;
538 }
539 #else
540 #error "You need the strtoq function"
541 #endif /* HAVE_STRTOQ */
542 #endif /* HAVE_BSD_STRTOLL */
543 #endif /* HAVE_STRTOLL */
544
545
546 #ifndef HAVE_STRTOULL
547 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
548 {
549 #ifdef HAVE_STRTOUQ
550         return strtouq(str, endptr, base);
551 #elif defined(HAVE___STRTOULL) 
552         return __strtoull(str, endptr, base);
553 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
554         return (unsigned long long int) strtoul(str, endptr, base);
555 #else
556 # error "You need a strtoull function"
557 #endif
558 }
559 #else
560 #ifdef HAVE_BSD_STRTOLL
561 #ifdef HAVE_STRTOUQ
562 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
563 {
564         unsigned long long int nb = strtouq(str, endptr, base);
565         /* In linux EINVAL is only returned if base is not ok */
566         if (errno == EINVAL) {
567                 if (base == 0 || (base >1 && base <37)) {
568                         /* Base was ok so it's because we were not
569                          * able to make the convertion.
570                          * Let's reset errno.
571                          */
572                         errno = 0;
573                 }
574         }
575         return nb;
576 }
577 #else
578 #error "You need the strtouq function"
579 #endif /* HAVE_STRTOUQ */
580 #endif /* HAVE_BSD_STRTOLL */
581 #endif /* HAVE_STRTOULL */
582
583 #ifndef HAVE_SETENV
584 int rep_setenv(const char *name, const char *value, int overwrite) 
585 {
586         char *p;
587         size_t l1, l2;
588         int ret;
589
590         if (!overwrite && getenv(name)) {
591                 return 0;
592         }
593
594         l1 = strlen(name);
595         l2 = strlen(value);
596
597         p = malloc(l1+l2+2);
598         if (p == NULL) {
599                 return -1;
600         }
601         memcpy(p, name, l1);
602         p[l1] = '=';
603         memcpy(p+l1+1, value, l2);
604         p[l1+l2+1] = 0;
605
606         ret = putenv(p);
607         if (ret != 0) {
608                 free(p);
609         }
610
611         return ret;
612 }
613 #endif
614
615 #ifndef HAVE_UNSETENV
616 int rep_unsetenv(const char *name)
617 {
618         extern char **environ;
619         size_t len = strlen(name);
620         size_t i, count;
621
622         if (environ == NULL || getenv(name) == NULL) {
623                 return 0;
624         }
625
626         for (i=0;environ[i];i++) /* noop */ ;
627
628         count=i;
629         
630         for (i=0;i<count;) {
631                 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
632                         /* note: we do _not_ free the old variable here. It is unsafe to 
633                            do so, as the pointer may not have come from malloc */
634                         memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *));
635                         count--;
636                 } else {
637                         i++;
638                 }
639         }
640
641         return 0;
642 }
643 #endif
644
645 #ifndef HAVE_UTIME
646 int rep_utime(const char *filename, const struct utimbuf *buf)
647 {
648         errno = ENOSYS;
649         return -1;
650 }
651 #endif
652
653 #ifndef HAVE_UTIMES
654 int rep_utimes(const char *filename, const struct timeval tv[2])
655 {
656         struct utimbuf u;
657
658         u.actime = tv[0].tv_sec;
659         if (tv[0].tv_usec > 500000) {
660                 u.actime += 1;
661         }
662
663         u.modtime = tv[1].tv_sec;
664         if (tv[1].tv_usec > 500000) {
665                 u.modtime += 1;
666         }
667
668         return utime(filename, &u);
669 }
670 #endif
671
672 #ifndef HAVE_DUP2
673 int rep_dup2(int oldfd, int newfd) 
674 {
675         errno = ENOSYS;
676         return -1;
677 }
678 #endif
679
680 #ifndef HAVE_CHOWN
681 /**
682 chown isn't used much but OS/2 doesn't have it
683 **/
684 int rep_chown(const char *fname, uid_t uid, gid_t gid)
685 {
686         errno = ENOSYS;
687         return -1;
688 }
689 #endif
690
691 #ifndef HAVE_LINK
692 int rep_link(const char *oldpath, const char *newpath)
693 {
694         errno = ENOSYS;
695         return -1;
696 }
697 #endif
698
699 #ifndef HAVE_READLINK
700 int rep_readlink(const char *path, char *buf, size_t bufsiz)
701 {
702         errno = ENOSYS;
703         return -1;
704 }
705 #endif
706
707 #ifndef HAVE_SYMLINK
708 int rep_symlink(const char *oldpath, const char *newpath)
709 {
710         errno = ENOSYS;
711         return -1;
712 }
713 #endif
714
715 #ifndef HAVE_LCHOWN
716 int rep_lchown(const char *fname,uid_t uid,gid_t gid)
717 {
718         errno = ENOSYS;
719         return -1;
720 }
721 #endif
722
723 #ifndef HAVE_REALPATH
724 char *rep_realpath(const char *path, char *resolved_path)
725 {
726         /* As realpath is not a system call we can't return ENOSYS. */
727         errno = EINVAL;
728         return NULL;
729 }
730 #endif
731
732
733 #ifndef HAVE_MEMMEM
734 void *rep_memmem(const void *haystack, size_t haystacklen,
735                  const void *needle, size_t needlelen)
736 {
737         if (needlelen == 0) {
738                 return discard_const(haystack);
739         }
740         while (haystacklen >= needlelen) {
741                 char *p = (char *)memchr(haystack, *(const char *)needle,
742                                          haystacklen-(needlelen-1));
743                 if (!p) return NULL;
744                 if (memcmp(p, needle, needlelen) == 0) {
745                         return p;
746                 }
747                 haystack = p+1;
748                 haystacklen -= (p - (const char *)haystack) + 1;
749         }
750         return NULL;
751 }
752 #endif
753
754 #ifndef HAVE_VDPRINTF
755 int rep_vdprintf(int fd, const char *format, va_list ap)
756 {
757         char *s = NULL;
758         int ret;
759
760         vasprintf(&s, format, ap);
761         if (s == NULL) {
762                 errno = ENOMEM;
763                 return -1;
764         }
765         ret = write(fd, s, strlen(s));
766         free(s);
767         return ret;
768 }
769 #endif
770
771 #ifndef HAVE_DPRINTF
772 int rep_dprintf(int fd, const char *format, ...)
773 {
774         int ret;
775         va_list ap;
776
777         va_start(ap, format);
778         ret = vdprintf(fd, format, ap);
779         va_end(ap);
780
781         return ret;
782 }
783 #endif
784
785 #ifndef HAVE_GET_CURRENT_DIR_NAME
786 char *rep_get_current_dir_name(void)
787 {
788         char buf[PATH_MAX+1];
789         char *p;
790         p = getcwd(buf, sizeof(buf));
791         if (p == NULL) {
792                 return NULL;
793         }
794         return strdup(p);
795 }
796 #endif
797
798 #if !defined(HAVE_STRERROR_R) || !defined(STRERROR_R_PROTO_COMPATIBLE)
799 int rep_strerror_r(int errnum, char *buf, size_t buflen)
800 {
801         char *s = strerror(errnum);
802         if (strlen(s)+1 > buflen) {
803                 errno = ERANGE;
804                 return -1;
805         }
806         strncpy(buf, s, buflen);
807         return 0;
808 }
809 #endif
810
811 #ifndef HAVE_CLOCK_GETTIME
812 int rep_clock_gettime(clockid_t clk_id, struct timespec *tp)
813 {
814         struct timeval tval;
815         switch (clk_id) {
816                 case 0: /* CLOCK_REALTIME :*/
817 #ifdef HAVE_GETTIMEOFDAY_TZ
818                         gettimeofday(&tval,NULL);
819 #else
820                         gettimeofday(&tval);
821 #endif
822                         tp->tv_sec = tval.tv_sec;
823                         tp->tv_nsec = tval.tv_usec * 1000;
824                         break;
825                 default:
826                         errno = EINVAL;
827                         return -1;
828         }
829         return 0;
830 }
831 #endif
832
833 #ifndef HAVE_MEMALIGN
834 void *rep_memalign( size_t align, size_t size )
835 {
836 #if defined(HAVE_POSIX_MEMALIGN)
837         void *p = NULL;
838         int ret = posix_memalign( &p, align, size );
839         if ( ret == 0 )
840                 return p;
841
842         return NULL;
843 #else
844         /* On *BSD systems memaligns doesn't exist, but memory will
845          * be aligned on allocations of > pagesize. */
846 #if defined(SYSCONF_SC_PAGESIZE)
847         size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
848 #elif defined(HAVE_GETPAGESIZE)
849         size_t pagesize = (size_t)getpagesize();
850 #else
851         size_t pagesize = (size_t)-1;
852 #endif
853         if (pagesize == (size_t)-1) {
854                 errno = ENOSYS;
855                 return NULL;
856         }
857         if (size < pagesize) {
858                 size = pagesize;
859         }
860         return malloc(size);
861 #endif
862 }
863 #endif
864
865 #ifndef HAVE_GETPEEREID
866 int rep_getpeereid(int s, uid_t *uid, gid_t *gid)
867 {
868 #if defined(HAVE_PEERCRED)
869         struct ucred cred;
870         socklen_t cred_len = sizeof(struct ucred);
871         int ret;
872
873 #undef getsockopt
874         ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len);
875         if (ret != 0) {
876                 return -1;
877         }
878
879         if (cred_len != sizeof(struct ucred)) {
880                 errno = EINVAL;
881                 return -1;
882         }
883
884         *uid = cred.uid;
885         *gid = cred.gid;
886         return 0;
887 #else
888         errno = ENOSYS;
889         return -1;
890 #endif
891 }
892 #endif
893
894 #ifndef HAVE_USLEEP
895 int rep_usleep(useconds_t sec)
896 {
897         struct timeval tval;
898         /*
899          * Fake it with select...
900          */
901         tval.tv_sec = 0;
902         tval.tv_usec = usecs/1000;
903         select(0,NULL,NULL,NULL,&tval);
904         return 0;
905 }
906 #endif /* HAVE_USLEEP */