xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/sys_compat.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: sys_compat.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	sys_compat 3
6 /* SUMMARY
7 /*	compatibility routines
8 /* SYNOPSIS
9 /*	#include <sys_defs.h>
10 /*
11 /*	void	closefrom(int lowfd)
12 /*	int	lowfd;
13 /*
14 /*	const char *strerror(err)
15 /*	int	err;
16 /*
17 /*	int	setenv(name, value, clobber)
18 /*	const char *name;
19 /*	const char *value;
20 /*	int	clobber;
21 /*
22 /*	int	seteuid(euid)
23 /*	uid_t	euid;
24 /*
25 /*	int	setegid(egid)
26 /*	gid_t	euid;
27 /*
28 /*	int	mkfifo(path, mode)
29 /*	char	*path;
30 /*	int	mode;
31 /*
32 /*	int	waitpid(pid, statusp, options)
33 /*	int	pid;
34 /*	WAIT_STATUS_T *statusp;
35 /*	int	options;
36 /*
37 /*	int	setsid()
38 /*
39 /*	void	dup2_pass_on_exec(int oldd, int newd)
40 /*
41 /*	char	*inet_ntop(af, src, dst, size)
42 /*	int	af;
43 /*	const void *src;
44 /*	char	*dst;
45 /*	size_t	size;
46 /*
47 /*	int	inet_pton(af, src, dst)
48 /*	int	af;
49 /*	const char *src;
50 /*	void	*dst;
51 /* DESCRIPTION
52 /*	These routines are compiled for platforms that lack the functionality
53 /*	or that have broken versions that we prefer to stay away from.
54 /* LICENSE
55 /* .ad
56 /* .fi
57 /*	The Secure Mailer license must be distributed with this software.
58 /* AUTHOR(S)
59 /*	Wietse Venema
60 /*	IBM T.J. Watson Research
61 /*	P.O. Box 704
62 /*	Yorktown Heights, NY 10598, USA
63 /*--*/
64 
65 /* System library. */
66 
67 #include "sys_defs.h"
68 
69  /*
70   * ANSI strerror() emulation
71   */
72 #ifdef MISSING_STRERROR
73 
74 extern int errno;
75 extern char *sys_errlist[];
76 extern int sys_nerr;
77 
78 #include <vstring.h>
79 
80 /* strerror - print text corresponding to error */
81 
82 const char *strerror(int err)
83 {
84     static VSTRING *buf;
85 
86     if (err < 0 || err >= sys_nerr) {
87 	if (buf == 0)
88 	    buf = vstring_alloc(10);
89 	vstring_sprintf(buf, "Unknown error %d", err);
90 	return (vstring_str(buf));
91     } else {
92 	return (sys_errlist[errno]);
93     }
94 }
95 
96 #endif
97 
98  /*
99   * setenv() emulation on top of putenv().
100   */
101 #ifdef MISSING_SETENV
102 
103 #include <stdio.h>
104 #include <string.h>
105 #include <stdlib.h>
106 
107 /* setenv - update or insert environment (name,value) pair */
108 
109 int     setenv(const char *name, const char *value, int clobber)
110 {
111     char   *cp;
112 
113     if (clobber == 0 && getenv(name) != 0)
114 	return (0);
115     if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0)
116 	return (1);
117     sprintf(cp, "%s=%s", name, value);
118     return (putenv(cp));
119 }
120 
121 #endif
122 
123  /*
124   * seteuid() and setegid() emulation, the HP-UX way
125   */
126 #ifdef MISSING_SETEUID
127 #ifdef HAVE_SETRESUID
128 #include <unistd.h>
129 
130 int     seteuid(uid_t euid)
131 {
132     return setresuid(-1, euid, -1);
133 }
134 
135 #else
136 #error MISSING_SETEUID
137 #endif
138 
139 #endif
140 
141 #ifdef MISSING_SETEGID
142 #ifdef HAVE_SETRESGID
143 #include <unistd.h>
144 
145 int     setegid(gid_t egid)
146 {
147     return setresgid(-1, egid, -1);
148 }
149 
150 #else
151 #error MISSING_SETEGID
152 #endif
153 
154 #endif
155 
156  /*
157   * mkfifo() emulation - requires superuser privileges
158   */
159 #ifdef MISSING_MKFIFO
160 
161 #include <sys/stat.h>
162 
163 int     mkfifo(char *path, int mode)
164 {
165     return mknod(path, (mode & ~_S_IFMT) | _S_IFIFO, 0);
166 }
167 
168 #endif
169 
170  /*
171   * waitpid() emulation on top of Berkeley UNIX wait4()
172   */
173 #ifdef MISSING_WAITPID
174 #ifdef HAS_WAIT4
175 
176 #include <sys/wait.h>
177 #include <errno.h>
178 
179 int     waitpid(int pid, WAIT_STATUS_T *status, int options)
180 {
181     if (pid == -1)
182 	pid = 0;
183     return wait4(pid, status, options, (struct rusage *) 0);
184 }
185 
186 #else
187 #error MISSING_WAITPID
188 #endif
189 
190 #endif
191 
192  /*
193   * setsid() emulation, the Berkeley UNIX way
194   */
195 #ifdef MISSING_SETSID
196 
197 #include <sys/ioctl.h>
198 #include <unistd.h>
199 #include <fcntl.h>
200 #include <errno.h>
201 
202 #ifdef TIOCNOTTY
203 
204 #include <msg.h>
205 
206 int     setsid(void)
207 {
208     int     p = getpid();
209     int     fd;
210 
211     if (setpgrp(p, p))
212 	return -1;
213 
214     fd = open("/dev/tty", O_RDONLY, 0);
215     if (fd >= 0 || errno != ENXIO) {
216 	if (fd < 0) {
217 	    msg_warn("open /dev/tty: %m");
218 	    return -1;
219 	}
220 	if (ioctl(fd, TIOCNOTTY, 0)) {
221 	    msg_warn("ioctl TIOCNOTTY: %m");
222 	    return -1;
223 	}
224 	close(fd);
225     }
226     return 0;
227 }
228 
229 #else
230 #error MISSING_SETSID
231 #endif
232 
233 #endif
234 
235  /*
236   * dup2_pass_on_exec() - dup2() and clear close-on-exec flag on the result
237   */
238 #ifdef DUP2_DUPS_CLOSE_ON_EXEC
239 
240 #include "iostuff.h"
241 
242 int     dup2_pass_on_exec(int oldd, int newd)
243 {
244     int     res;
245 
246     if ((res = dup2(oldd, newd)) >= 0)
247 	close_on_exec(newd, PASS_ON_EXEC);
248 
249     return res;
250 }
251 
252 #endif
253 
254 #ifndef HAS_CLOSEFROM
255 
256 #include <unistd.h>
257 #include <errno.h>
258 #include <iostuff.h>
259 
260 /* closefrom() - closes all file descriptors from the given one up */
261 
262 int     closefrom(int lowfd)
263 {
264     int     fd_limit = open_limit(0);
265     int     fd;
266 
267     /*
268      * lowfrom does not have an easy to determine upper limit. A process may
269      * have files open that were inherited from a parent process with a less
270      * restrictive resource limit.
271      */
272     if (lowfd < 0) {
273 	errno = EBADF;
274 	return (-1);
275     }
276     if (fd_limit > 500)
277 	fd_limit = 500;
278     for (fd = lowfd; fd < fd_limit; fd++)
279 	(void) close(fd);
280 
281     return (0);
282 }
283 
284 #endif
285 
286 #ifdef MISSING_INET_NTOP
287 
288 #include <sys/types.h>
289 #include <sys/socket.h>
290 #include <netinet/in.h>
291 #include <arpa/inet.h>
292 #include <stdio.h>
293 #include <string.h>
294 #include <errno.h>
295 
296 /* inet_ntop - convert binary address to printable address */
297 
298 const char *inet_ntop(int af, const void *src, char *dst, size_t size)
299 {
300     const unsigned char *addr;
301     char    buffer[sizeof("255.255.255.255")];
302     int     len;
303 
304     if (af != AF_INET) {
305 	errno = EAFNOSUPPORT;
306 	return (0);
307     }
308     addr = (const unsigned char *) src;
309 #if (CHAR_BIT > 8)
310     sprintf(buffer, "%d.%d.%d.%d", addr[0] & 0xff,
311 	    addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff);
312 #else
313     sprintf(buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
314 #endif
315     if ((len = strlen(buffer)) >= size) {
316 	errno = ENOSPC;
317 	return (0);
318     } else {
319 	memcpy(dst, buffer, len + 1);
320 	return (dst);
321     }
322 }
323 
324 #endif
325 
326 #ifdef MISSING_INET_PTON
327 
328 #include <sys/types.h>
329 #include <sys/socket.h>
330 #include <netinet/in.h>
331 #include <arpa/inet.h>
332 #include <string.h>
333 #include <errno.h>
334 
335 #ifndef INADDR_NONE
336 #define INADDR_NONE 0xffffffff
337 #endif
338 
339 /* inet_pton - convert printable address to binary address */
340 
341 int     inet_pton(int af, const char *src, void *dst)
342 {
343     struct in_addr addr;
344 
345     /*
346      * inet_addr() accepts a wider range of input formats than inet_pton();
347      * the former accepts 1-, 2-, or 3-part dotted addresses, while the
348      * latter requires dotted quad form.
349      */
350     if (af != AF_INET) {
351 	errno = EAFNOSUPPORT;
352 	return (-1);
353     } else if ((addr.s_addr = inet_addr(src)) == INADDR_NONE
354 	       && strcmp(src, "255.255.255.255") != 0) {
355 	return (0);
356     } else {
357 	memcpy(dst, (char *) &addr, sizeof(addr));
358 	return (1);
359     }
360 }
361 
362 #endif
363