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    char   *cp;
110
111    if (clobber == 0 && getenv(name) != 0)
112	return (0);
113    if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0)
114	return (1);
115    sprintf(cp, "%s=%s", name, value);
116    return (putenv(cp));
117}
118
119#endif
120
121 /*
122  * seteuid() and setegid() emulation, the HP-UX way
123  */
124#ifdef MISSING_SETEUID
125#ifdef HAVE_SETRESUID
126#include <unistd.h>
127
128int     seteuid(uid_t euid)
129{
130    return setresuid(-1, euid, -1);
131}
132
133#else
134#error MISSING_SETEUID
135#endif
136
137#endif
138
139#ifdef MISSING_SETEGID
140#ifdef HAVE_SETRESGID
141#include <unistd.h>
142
143int     setegid(gid_t egid)
144{
145    return setresgid(-1, egid, -1);
146}
147
148#else
149#error MISSING_SETEGID
150#endif
151
152#endif
153
154 /*
155  * mkfifo() emulation - requires superuser privileges
156  */
157#ifdef MISSING_MKFIFO
158
159#include <sys/stat.h>
160
161int     mkfifo(char *path, int mode)
162{
163    return mknod(path, (mode & ~_S_IFMT) | _S_IFIFO, 0);
164}
165
166#endif
167
168 /*
169  * waitpid() emulation on top of Berkeley UNIX wait4()
170  */
171#ifdef MISSING_WAITPID
172#ifdef HAS_WAIT4
173
174#include <sys/wait.h>
175#include <errno.h>
176
177int     waitpid(int pid, WAIT_STATUS_T *status, int options)
178{
179    if (pid == -1)
180	pid = 0;
181    return wait4(pid, status, options, (struct rusage *) 0);
182}
183
184#else
185#error MISSING_WAITPID
186#endif
187
188#endif
189
190 /*
191  * setsid() emulation, the Berkeley UNIX way
192  */
193#ifdef MISSING_SETSID
194
195#include <sys/ioctl.h>
196#include <unistd.h>
197#include <fcntl.h>
198#include <errno.h>
199
200#ifdef TIOCNOTTY
201
202#include <msg.h>
203
204int     setsid(void)
205{
206    int     p = getpid();
207    int     fd;
208
209    if (setpgrp(p, p))
210	return -1;
211
212    fd = open("/dev/tty", O_RDONLY, 0);
213    if (fd >= 0 || errno != ENXIO) {
214	if (fd < 0) {
215	    msg_warn("open /dev/tty: %m");
216	    return -1;
217	}
218	if (ioctl(fd, TIOCNOTTY, 0)) {
219	    msg_warn("ioctl TIOCNOTTY: %m");
220	    return -1;
221	}
222	close(fd);
223    }
224    return 0;
225}
226
227#else
228#error MISSING_SETSID
229#endif
230
231#endif
232
233 /*
234  * dup2_pass_on_exec() - dup2() and clear close-on-exec flag on the result
235  */
236#ifdef DUP2_DUPS_CLOSE_ON_EXEC
237
238#include "iostuff.h"
239
240int     dup2_pass_on_exec(int oldd, int newd)
241{
242    int     res;
243
244    if ((res = dup2(oldd, newd)) >= 0)
245	close_on_exec(newd, PASS_ON_EXEC);
246
247    return res;
248}
249
250#endif
251
252#ifndef HAS_CLOSEFROM
253
254#include <unistd.h>
255#include <errno.h>
256#include <iostuff.h>
257
258/* closefrom() - closes all file descriptors from the given one up */
259
260int     closefrom(int lowfd)
261{
262    int     fd_limit = open_limit(0);
263    int     fd;
264
265    /*
266     * lowfrom does not have an easy to determine upper limit. A process may
267     * have files open that were inherited from a parent process with a less
268     * restrictive resource limit.
269     */
270    if (lowfd < 0) {
271	errno = EBADF;
272	return (-1);
273    }
274    if (fd_limit > 500)
275	fd_limit = 500;
276    for (fd = lowfd; fd < fd_limit; fd++)
277	(void) close(fd);
278
279    return (0);
280}
281
282#endif
283
284#ifdef MISSING_INET_NTOP
285
286#include <sys/types.h>
287#include <sys/socket.h>
288#include <netinet/in.h>
289#include <arpa/inet.h>
290#include <stdio.h>
291#include <string.h>
292#include <errno.h>
293
294/* inet_ntop - convert binary address to printable address */
295
296const char *inet_ntop(int af, const void *src, char *dst, size_t size)
297{
298    const unsigned char *addr;
299    char    buffer[sizeof("255.255.255.255")];
300    int     len;
301
302    if (af != AF_INET) {
303	errno = EAFNOSUPPORT;
304	return (0);
305    }
306    addr = (const unsigned char *) src;
307#if (CHAR_BIT > 8)
308    sprintf(buffer, "%d.%d.%d.%d", addr[0] & 0xff,
309	    addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff);
310#else
311    sprintf(buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
312#endif
313    if ((len = strlen(buffer)) >= size) {
314	errno = ENOSPC;
315	return (0);
316    } else {
317	memcpy(dst, buffer, len + 1);
318	return (dst);
319    }
320}
321
322#endif
323
324#ifdef MISSING_INET_PTON
325
326#include <sys/types.h>
327#include <sys/socket.h>
328#include <netinet/in.h>
329#include <arpa/inet.h>
330#include <string.h>
331#include <errno.h>
332
333#ifndef INADDR_NONE
334#define INADDR_NONE 0xffffffff
335#endif
336
337/* inet_pton - convert printable address to binary address */
338
339int     inet_pton(int af, const char *src, void *dst)
340{
341    struct in_addr addr;
342
343    /*
344     * inet_addr() accepts a wider range of input formats than inet_pton();
345     * the former accepts 1-, 2-, or 3-part dotted addresses, while the
346     * latter requires dotted quad form.
347     */
348    if (af != AF_INET) {
349	errno = EAFNOSUPPORT;
350	return (-1);
351    } else if ((addr.s_addr = inet_addr(src)) == INADDR_NONE
352	       && strcmp(src, "255.255.255.255") != 0) {
353	return (0);
354    } else {
355	memcpy(dst, (char *) &addr, sizeof(addr));
356	return (1);
357    }
358}
359
360#endif
361