1/*++
2/* NAME
3/*	sys_compat 3
4/* SUMMARY
5/*	compatibility routines
6/* SYNOPSIS
7/*	#include <sys_defs.h>
8/*
9/*	void	closefrom(int lowfd)
10/*	int	lowfd;
11/*
12/*	const char *strerror(err)
13/*	int	err;
14/*
15/*	int	setenv(name, value, clobber)
16/*	const char *name;
17/*	const char *value;
18/*	int	clobber;
19/*
20/*	int	seteuid(euid)
21/*	uid_t	euid;
22/*
23/*	int	setegid(egid)
24/*	gid_t	euid;
25/*
26/*	int	mkfifo(path, mode)
27/*	char	*path;
28/*	int	mode;
29/*
30/*	int	waitpid(pid, statusp, options)
31/*	int	pid;
32/*	WAIT_STATUS_T *statusp;
33/*	int	options;
34/*
35/*	int	setsid()
36/*
37/*	void	dup2_pass_on_exec(int oldd, int newd)
38/*
39/*	char	*inet_ntop(af, src, dst, size)
40/*	int	af;
41/*	const void *src;
42/*	char	*dst;
43/*	size_t	size;
44/*
45/*	int	inet_pton(af, src, dst)
46/*	int	af;
47/*	const char *src;
48/*	void	*dst;
49/* DESCRIPTION
50/*	These routines are compiled for platforms that lack the functionality
51/*	or that have broken versions that we prefer to stay away from.
52/* LICENSE
53/* .ad
54/* .fi
55/*	The Secure Mailer license must be distributed with this software.
56/* AUTHOR(S)
57/*	Wietse Venema
58/*	IBM T.J. Watson Research
59/*	P.O. Box 704
60/*	Yorktown Heights, NY 10598, USA
61/*--*/
62
63/* System library. */
64
65#include "sys_defs.h"
66
67 /*
68  * ANSI strerror() emulation
69  */
70#ifdef MISSING_STRERROR
71
72extern int errno;
73extern char *sys_errlist[];
74extern int sys_nerr;
75
76#include <vstring.h>
77
78/* strerror - print text corresponding to error */
79
80const char *strerror(int err)
81{
82    static VSTRING *buf;
83
84    if (err < 0 || err >= sys_nerr) {
85	if (buf == 0)
86	    buf = vstring_alloc(10);
87	vstring_sprintf(buf, "Unknown error %d", err);
88	return (vstring_str(buf));
89    } else {
90	return (sys_errlist[errno]);
91    }
92}
93
94#endif
95
96 /*
97  * setenv() emulation on top of putenv().
98  */
99#ifdef MISSING_SETENV
100
101#include <stdio.h>
102#include <string.h>
103#include <stdlib.h>
104
105/* setenv - update or insert environment (name,value) pair */
106
107int     setenv(const char *name, const char *value, int clobber)
108{
109    size_t size; /* APPLE */
110    char   *cp;
111
112    if (clobber == 0 && getenv(name) != 0)
113	return (0);
114    size = strlen(name) + strlen(value) + 2; /* APPLE */
115    if ((cp = malloc(size)) == 0) /* APPLE */
116	return (1);
117    snprintf(cp, size, "%s=%s", name, value); /* APPLE */
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
130int     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
145int     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
163int     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
179int     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
206int     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
242int     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
262int     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
298const 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    snprintf(buffer, sizeof buffer, "%d.%d.%d.%d", addr[0] & 0xff,
311	    addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff);  /* APPLE */
312#else
313    snprintf(buffer, sizeof buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);  /* APPLE */
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
341int     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