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