1diff --git c/configure.ac w/configure.ac
2index 09cb310..30c0e2a 100644
3--- c/configure.ac
4+++ w/configure.ac
5@@ -110,7 +110,7 @@ AS_CASE([$host_os],
6 AM_CONDITIONAL([OS_WINDOWS], [test "x$is_windows" = "xyes"])
7
8 # Checks for header files.
9-AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h pwd.h grp.h])
10+AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h pwd.h grp.h nlist.h])
11
12 # Checks for typedefs, structures, and compiler characteristics.
13 AC_C_INLINE
14@@ -210,7 +210,8 @@ AC_LINK_IFELSE(
15
16 AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
17 getauxval getentropy getexecname getline \
18- pstat_getproc sysconf])
19+ pstat_getproc sysconf \
20+ strlcpy strlcat strnstr strmode fpurge])
21 AM_CONDITIONAL([HAVE_GETENTROPY], [test "x$ac_cv_func_getentropy" = "xtrue"])
22
23 AC_SUBST([LIBBSD_LIBS])
24diff --git c/include/bsd/string.h w/include/bsd/string.h
25index f987fee..a1e17ed 100644
26--- c/include/bsd/string.h
27+++ w/include/bsd/string.h
28@@ -41,10 +41,21 @@
29 #include <sys/types.h>
30
31 __BEGIN_DECLS
32+#if !HAVE_STRLCPY
33 size_t strlcpy(char *dst, const char *src, size_t siz);
34+#endif
35+
36+#if !HAVE_STRLCAT
37 size_t strlcat(char *dst, const char *src, size_t siz);
38+#endif
39+
40+#if !HAVE_STRNSTR
41 char *strnstr(const char *str, const char *find, size_t str_len);
42+#endif
43+
44+#if !HAVE_STRMODE
45 void strmode(mode_t mode, char *str);
46+#endif
47
48 #if !defined(__GLIBC__) || \
49 (defined(__GLIBC__) && (!__GLIBC_PREREQ(2, 25) || !defined(_GNU_SOURCE)))
50diff --git c/src/fpurge.c w/src/fpurge.c
51index 462535a..a8941db 100644
52--- c/src/fpurge.c
53+++ w/src/fpurge.c
54@@ -26,9 +26,10 @@
55
56 #include <errno.h>
57 #include <stdio.h>
58-#include <stdio_ext.h>
59
60 #ifdef HAVE___FPURGE
61+#include <stdio_ext.h>
62+
63 int
64 fpurge(FILE *fp)
65 {
66@@ -41,6 +42,36 @@ fpurge(FILE *fp)
67
68 return 0;
69 }
70+/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin 1.7 */
71+#elif HAVE_FPURGE
72+int
73+fpurge(FILE *fp)
74+{
75+ if (fp == NULL || fileno(fp) < 0) {
76+ errno = EBADF;
77+ return EOF;
78+ }
79+
80+ /* Call the system's fpurge function. */
81+#undef fpurge
82+#if !HAVE_DECL_FPURGE
83+ extern int fpurge (FILE *);
84+#endif
85+ int result = fpurge (fp);
86+/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
87+#if defined(__sferror) || defined(__DragonFly__)
88+ if (result == 0)
89+ /* Correct the invariants that fpurge broke.
90+ <stdio.h> on BSD systems says:
91+ "The following always hold: if _flags & __SRD, _w is 0."
92+ If this invariant is not fulfilled and the stream is read-write but
93+ currently reading, subsequent putc or fputc calls will write directly
94+ into the buffer, although they shouldn't be allowed to. */
95+ if ((fp->_flags & __SRD) != 0)
96+ fp->_w = 0;
97+#endif
98+ return result;
99+}
100 #else
101 #error "Function fpurge() needs to be ported."
102 #endif
103diff --git c/src/funopen.c w/src/funopen.c
104index 1e6f43a..3a3af6a 100644
105--- c/src/funopen.c
106+++ w/src/funopen.c
107@@ -143,6 +143,7 @@ funopen(const void *cookie,
108 * they will not add the needed support to implement it. Just ignore this
109 * interface there, as it has never been provided anyway.
110 */
111+#elif defined(__MACH__)
112 #else
113 #error "Function funopen() needs to be ported or disabled."
114 #endif
115diff --git c/src/local-link.h w/src/local-link.h
116index 0d4351a..fc520af 100644
117--- c/src/local-link.h
118+++ w/src/local-link.h
119@@ -27,6 +27,11 @@
120 #ifndef LIBBSD_LOCAL_LINK_H
121 #define LIBBSD_LOCAL_LINK_H
122
123+#ifdef __MACH__
124+#define libbsd_link_warning(symbol, msg)
125+#define libbsd_symver_default(alias, symbol, version)
126+#define libbsd_symver_variant(alias, symbol, version)
127+#else
128 #define libbsd_link_warning(symbol, msg) \
129 static const char libbsd_emit_link_warning_##symbol[] \
130 __attribute__((__used__,__section__(".gnu.warning." #symbol))) = msg;
131@@ -45,3 +50,4 @@
132 #endif
133
134 #endif
135+#endif
136diff --git c/src/nlist.c w/src/nlist.c
137index d22fa19..f41333f 100644
138--- c/src/nlist.c
139+++ w/src/nlist.c
140@@ -41,6 +41,7 @@
141 #include <unistd.h>
142 #include <nlist.h>
143
144+#if !HAVE_NLIST_H
145 #include "local-elf.h"
146
147 #ifndef SIZE_T_MAX
148@@ -282,3 +283,4 @@ nlist(const char *name, struct nlist *list)
149 (void)close(fd);
150 return (n);
151 }
152+#endif
153diff --git c/src/readpassphrase.c w/src/readpassphrase.c
154index f9f6195..2bc5fb4 100644
155--- c/src/readpassphrase.c
156+++ w/src/readpassphrase.c
157@@ -36,6 +36,14 @@
158 #define TCSASOFT 0
159 #endif
160
161+#ifndef _SIGMAX
162+#define _SIGMAX 64
163+#endif
164+
165+#ifndef _NSIG
166+#define _NSIG (_SIGMAX + 1)
167+#endif
168+
169 static volatile sig_atomic_t signo[_NSIG];
170
171 static void handler(int);
172diff --git c/src/setproctitle.c w/src/setproctitle.c
173index ff32aa3..51ed833 100644
174--- c/src/setproctitle.c
175+++ w/src/setproctitle.c
176@@ -33,6 +33,10 @@
177 #include <string.h>
178 #include "local-link.h"
179
180+#ifdef __MACH__
181+extern char **environ;
182+#endif
183+
184 static struct {
185 /* Original value. */
186 const char *arg0;
187@@ -287,7 +291,8 @@ libbsd_symver_default(setproctitle, setproctitle_impl, LIBBSD_0.5);
188 * in 0.5, make the implementation available in the old version as an alias
189 * for code linking against that version, and change the default to use the
190 * new version, so that new code depends on the implemented version. */
191-#ifdef HAVE_TYPEOF
192+#ifdef __MACH__
193+#elif defined(HAVE_TYPEOF)
194 extern __typeof__(setproctitle_impl)
195 setproctitle_stub
196 __attribute__((__alias__("setproctitle_impl")));
197diff --git c/src/strlcat.c w/src/strlcat.c
198index 14c53a1..5961c17 100644
199--- c/src/strlcat.c
200+++ w/src/strlcat.c
201@@ -26,6 +26,7 @@
202 * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
203 * If retval >= dsize, truncation occurred.
204 */
205+#if !HAVE_STRLCAT
206 size_t
207 strlcat(char *dst, const char *src, size_t dsize)
208 {
209@@ -53,3 +54,4 @@ strlcat(char *dst, const char *src, size_t dsize)
210
211 return(dlen + (src - osrc)); /* count does not include NUL */
212 }
213+#endif
214diff --git c/src/strlcpy.c w/src/strlcpy.c
215index e9a7fe4..5137acb 100644
216--- c/src/strlcpy.c
217+++ w/src/strlcpy.c
218@@ -24,6 +24,7 @@
219 * chars will be copied. Always NUL terminates (unless dsize == 0).
220 * Returns strlen(src); if retval >= dsize, truncation occurred.
221 */
222+#if !HAVE_STRLCPY
223 size_t
224 strlcpy(char *dst, const char *src, size_t dsize)
225 {
226@@ -48,3 +49,4 @@ strlcpy(char *dst, const char *src, size_t dsize)
227
228 return(src - osrc - 1); /* count does not include NUL */
229 }
230+#endif
231diff --git c/src/strmode.c w/src/strmode.c
232index e6afde5..da680c9 100644
233--- c/src/strmode.c
234+++ w/src/strmode.c
235@@ -32,6 +32,7 @@
236 #include <sys/stat.h>
237 #include <string.h>
238
239+#if !HAVE_STRMODE
240 void
241 strmode(mode_t mode, char *p)
242 {
243@@ -141,3 +142,4 @@ strmode(mode_t mode, char *p)
244 *p++ = ' '; /* will be a '+' if ACL's implemented */
245 *p = '\0';
246 }
247+#endif