1diff --git a/configure.ac b/configure.ac
2index 55fcfe6..1e26c93 100644
3--- a/configure.ac
4+++ b/configure.ac
5@@ -51,15 +51,19 @@ AS_CASE([$host_os],
6 AC_SEARCH_LIBS([clock_gettime], [rt], [CLOCK_GETTIME_LIBS="-lrt"])
7 AC_SUBST([CLOCK_GETTIME_LIBS])
8 LIBS="$saved_LIBS"
9+ AM_CONDITIONAL([BUILD_LINK_VERSION_SCRIPT], [1])
10 ],
11 [*-musl*], [
12 # Upstream refuses to define this, we will do it ourselves then.
13 AC_DEFINE([__MUSL__], [1], [Define to 1 if we are building for musl])
14+ AM_CONDITIONAL([BUILD_LINK_VERSION_SCRIPT], [1])
15 ],
16-)
17+ [
18+ AM_CONDITIONAL([BUILD_LINK_VERSION_SCRIPT], [1])
19+ ])
20
21 # Checks for header files.
22-AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h])
23+AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h nlist.h])
24
25 # Checks for typedefs, structures, and compiler characteristics.
26 AC_C_INLINE
27@@ -143,7 +147,8 @@ AC_LINK_IFELSE(
28
29 AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
30 getauxval getentropy getexecname getline \
31- pstat_getproc sysconf])
32+ pstat_getproc sysconf \
33+ strlcpy strlcat strnstr strmode fpurge])
34 AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
35
36 AC_CONFIG_FILES([
37diff --git a/include/bsd/string.h b/include/bsd/string.h
38index f987fee..a1e17ed 100644
39--- a/include/bsd/string.h
40+++ b/include/bsd/string.h
41@@ -41,10 +41,21 @@
42 #include <sys/types.h>
43
44 __BEGIN_DECLS
45+#if !HAVE_STRLCPY
46 size_t strlcpy(char *dst, const char *src, size_t siz);
47+#endif
48+
49+#if !HAVE_STRLCAT
50 size_t strlcat(char *dst, const char *src, size_t siz);
51+#endif
52+
53+#if !HAVE_STRNSTR
54 char *strnstr(const char *str, const char *find, size_t str_len);
55+#endif
56+
57+#if !HAVE_STRMODE
58 void strmode(mode_t mode, char *str);
59+#endif
60
61 #if !defined(__GLIBC__) || \
62 (defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 25) || !defined(_GNU_SOURCE)))
63diff --git a/src/Makefile.am b/src/Makefile.am
64index f3cc0fa..3aaecd4 100644
65--- a/src/Makefile.am
66+++ b/src/Makefile.am
67@@ -56,8 +56,10 @@ libbsd_la_DEPENDENCIES = \
68 libbsd_la_LIBADD = \
69 $(CLOCK_GETTIME_LIBS)
70 libbsd_la_LDFLAGS = \
71- -Wl,--version-script=$(srcdir)/libbsd.map \
72 -version-number $(LIBBSD_ABI)
73+if BUILD_LINK_VERSION_SCRIPT
74+libbsd_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libbsd.map
75+endif
76 libbsd_la_SOURCES = \
77 arc4random.c \
78 arc4random.h \
79diff --git a/src/fpurge.c b/src/fpurge.c
80index 462535a..a8941db 100644
81--- a/src/fpurge.c
82+++ b/src/fpurge.c
83@@ -26,9 +26,10 @@
84
85 #include <errno.h>
86 #include <stdio.h>
87-#include <stdio_ext.h>
88
89 #ifdef HAVE___FPURGE
90+#include <stdio_ext.h>
91+
92 int
93 fpurge(FILE *fp)
94 {
95@@ -41,6 +42,36 @@ fpurge(FILE *fp)
96
97 return 0;
98 }
99+/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin 1.7 */
100+#elif HAVE_FPURGE
101+int
102+fpurge(FILE *fp)
103+{
104+ if (fp == NULL || fileno(fp) < 0) {
105+ errno = EBADF;
106+ return EOF;
107+ }
108+
109+ /* Call the system's fpurge function. */
110+#undef fpurge
111+#if !HAVE_DECL_FPURGE
112+ extern int fpurge (FILE *);
113+#endif
114+ int result = fpurge (fp);
115+/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
116+#if defined(__sferror) || defined(__DragonFly__)
117+ if (result == 0)
118+ /* Correct the invariants that fpurge broke.
119+ <stdio.h> on BSD systems says:
120+ "The following always hold: if _flags & __SRD, _w is 0."
121+ If this invariant is not fulfilled and the stream is read-write but
122+ currently reading, subsequent putc or fputc calls will write directly
123+ into the buffer, although they shouldn't be allowed to. */
124+ if ((fp->_flags & __SRD) != 0)
125+ fp->_w = 0;
126+#endif
127+ return result;
128+}
129 #else
130 #error "Function fpurge() needs to be ported."
131 #endif
132diff --git a/src/funopen.c b/src/funopen.c
133index 1e05c7e..65ba5a8 100644
134--- a/src/funopen.c
135+++ b/src/funopen.c
136@@ -143,6 +143,7 @@ funopen(const void *cookie,
137 * they will not add the needed support to implement it. Just ignore this
138 * interface there, as it has never been provided anyway.
139 */
140+#elif defined(__MACH__)
141 #else
142 #error "Function funopen() needs to be ported or disabled."
143 #endif
144diff --git a/src/hash/sha512.h b/src/hash/sha512.h
145index 4f368a1..7632e25 100644
146--- a/src/hash/sha512.h
147+++ b/src/hash/sha512.h
148@@ -29,7 +29,11 @@
149 #ifndef _SHA512_H_
150 #define _SHA512_H_
151
152+#ifdef __MACH__
153+#include <stdint.h>
154+#else
155 #include <sys/types.h>
156+#endif
157
158 #define SHA512_DIGEST_LENGTH 64
159
160diff --git a/src/hash/sha512c.c b/src/hash/sha512c.c
161index b3c8d5e..602f54e 100644
162--- a/src/hash/sha512c.c
163+++ b/src/hash/sha512c.c
164@@ -25,7 +25,12 @@
165 */
166
167 #include <sys/cdefs.h>
168+
169+#ifdef __MACH__
170+#include <machine/endian.h>
171+#else
172 #include <sys/endian.h>
173+#endif
174 #include <sys/types.h>
175
176 #include <string.h>
177diff --git a/src/local-link.h b/src/local-link.h
178index d518dcf..84694a2 100644
179--- a/src/local-link.h
180+++ b/src/local-link.h
181@@ -27,7 +27,11 @@
182 #ifndef LIBBSD_LOCAL_LINK_H
183 #define LIBBSD_LOCAL_LINK_H
184
185+#ifdef __MACH__
186+#define libbsd_link_warning(symbol, msg)
187+#else
188 #define libbsd_link_warning(symbol, msg) \
189 static const char libbsd_emit_link_warning_##symbol[] \
190 __attribute__((used,section(".gnu.warning." #symbol))) = msg;
191 #endif
192+#endif
193diff --git a/src/nlist.c b/src/nlist.c
194index 0932f59..4502048 100644
195--- a/src/nlist.c
196+++ b/src/nlist.c
197@@ -41,6 +41,7 @@
198 #include <unistd.h>
199 #include <nlist.h>
200
201+#if !HAVE_NLIST_H
202 #include "local-elf.h"
203
204 #define SIZE_T_MAX 0xffffffffU
205@@ -265,3 +266,4 @@ nlist(const char *name, struct nlist *list)
206 (void)close(fd);
207 return (n);
208 }
209+#endif
210diff --git a/src/readpassphrase.c b/src/readpassphrase.c
211index f9f6195..2bc5fb4 100644
212--- a/src/readpassphrase.c
213+++ b/src/readpassphrase.c
214@@ -36,6 +36,14 @@
215 #define TCSASOFT 0
216 #endif
217
218+#ifndef _SIGMAX
219+#define _SIGMAX 64
220+#endif
221+
222+#ifndef _NSIG
223+#define _NSIG (_SIGMAX + 1)
224+#endif
225+
226 static volatile sig_atomic_t signo[_NSIG];
227
228 static void handler(int);
229diff --git a/src/setproctitle.c b/src/setproctitle.c
230index 038ac7d..e9ee09c 100644
231--- a/src/setproctitle.c
232+++ b/src/setproctitle.c
233@@ -32,6 +32,10 @@
234 #include <unistd.h>
235 #include <string.h>
236
237+#ifdef __MACH__
238+extern char **environ;
239+#endif
240+
241 static struct {
242 /* Original value. */
243 const char *arg0;
244@@ -280,16 +284,22 @@ setproctitle_impl(const char *fmt, ...)
245 *++nul = '\0';
246 }
247 }
248+#ifndef __MACH__
249 __asm__(".symver setproctitle_impl,setproctitle@@LIBBSD_0.5");
250+#endif
251
252 /* The original function introduced in 0.2 was a stub, it only got implemented
253 * in 0.5, make the implementation available in the old version as an alias
254 * for code linking against that version, and change the default to use the
255 * new version, so that new code depends on the implemented version. */
256-#ifdef HAVE_TYPEOF
257+#ifdef __MACH__
258+void setproctitle_stub(const char *fmt, ...);
259+#elif HAVE_TYPEOF
260 extern typeof(setproctitle_impl) setproctitle_stub __attribute__((alias("setproctitle_impl")));
261 #else
262 void setproctitle_stub(const char *fmt, ...)
263 __attribute__((alias("setproctitle_impl")));
264 #endif
265+#ifndef __MACH__
266 __asm__(".symver setproctitle_stub,setproctitle@LIBBSD_0.2");
267+#endif
268diff --git a/src/strlcat.c b/src/strlcat.c
269index 14c53a1..5961c17 100644
270--- a/src/strlcat.c
271+++ b/src/strlcat.c
272@@ -26,6 +26,7 @@
273 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
274 * If retval >= dsize, truncation occurred.
275 */
276+#if !HAVE_STRLCAT
277 size_t
278 strlcat(char *dst, const char *src, size_t dsize)
279 {
280@@ -53,3 +54,4 @@ strlcat(char *dst, const char *src, size_t dsize)
281
282 return(dlen + (src - osrc)); /* count does not include NUL */
283 }
284+#endif
285diff --git a/src/strlcpy.c b/src/strlcpy.c
286index e9a7fe4..5137acb 100644
287--- a/src/strlcpy.c
288+++ b/src/strlcpy.c
289@@ -24,6 +24,7 @@
290 * chars will be copied. Always NUL terminates (unless dsize == 0).
291 * Returns strlen(src); if retval >= dsize, truncation occurred.
292 */
293+#if !HAVE_STRLCPY
294 size_t
295 strlcpy(char *dst, const char *src, size_t dsize)
296 {
297@@ -48,3 +49,4 @@ strlcpy(char *dst, const char *src, size_t dsize)
298
299 return(src - osrc - 1); /* count does not include NUL */
300 }
301+#endif
302diff --git a/src/strmode.c b/src/strmode.c
303index e6afde5..da680c9 100644
304--- a/src/strmode.c
305+++ b/src/strmode.c
306@@ -32,6 +32,7 @@
307 #include <sys/stat.h>
308 #include <string.h>
309
310+#if !HAVE_STRMODE
311 void
312 strmode(mode_t mode, char *p)
313 {
314@@ -141,3 +142,4 @@ strmode(mode_t mode, char *p)
315 *p++ = ' '; /* will be a '+' if ACL's implemented */
316 *p = '\0';
317 }
318+#endif
319diff --git a/src/unvis.c b/src/unvis.c
320index 94e3e7a..fba4c66 100644
321--- a/src/unvis.c
322+++ b/src/unvis.c
323@@ -565,11 +565,15 @@ strnunvis_openbsd(char *dst, const char *src, size_t dlen)
324 {
325 return strnunvisx(dst, dlen, src, 0);
326 }
327+#ifndef __MACH__
328 __asm__(".symver strnunvis_openbsd,strnunvis@@LIBBSD_0.2");
329+#endif
330
331 int
332 strnunvis_netbsd(char *dst, size_t dlen, const char *src)
333 {
334 return strnunvisx(dst, dlen, src, 0);
335 }
336+#ifndef __MACH__
337 __asm__(".symver strnunvis_netbsd,strnunvis@LIBBSD_0.9.1");
338+#endif
339diff --git a/src/vis.c b/src/vis.c
340index c2cd2d8..2d84330 100644
341--- a/src/vis.c
342+++ b/src/vis.c
343@@ -723,14 +723,18 @@ strnvis_openbsd(char *mbdst, const char *mbsrc, size_t dlen, int flags)
344 {
345 return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, "", NULL);
346 }
347+#ifndef __MACH__
348 __asm__(".symver strnvis_openbsd,strnvis@@LIBBSD_0.2");
349+#endif
350
351 int
352 strnvis_netbsd(char *mbdst, size_t dlen, const char *mbsrc, int flags)
353 {
354 return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, "", NULL);
355 }
356+#ifndef __MACH__
357 __asm__(".symver strnvis_netbsd,strnvis@LIBBSD_0.9.1");
358+#endif
359
360 int
361 stravis(char **mbdstp, const char *mbsrc, int flags)