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