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