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