pyldb: avoid segfault when adding an element with no name
[sfrench/samba-autobuild/.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 /*
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  */
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 */
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
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 ****************************************************************************/
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 ********************************************************************/
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 ****************************************************************************/
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
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
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 **/
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 **/
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)
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
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
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
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
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
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
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
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
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
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 */
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
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
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 convertion.
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
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
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 convertion.
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
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
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
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
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
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 **/
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
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
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
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
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
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
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)
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)
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
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
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
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
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
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
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
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
941 void rep_setproctitle(const char *fmt, ...)
942 {
943 }
944 #endif
945 #ifndef HAVE_SETPROCTITLE_INIT
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
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
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 */