1 /* $NetBSD: sys_compat.c,v 1.3 2020/03/18 19:05:22 christos 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 unsetenv(name) 23 /* const char *name; 24 /* 25 /* int seteuid(euid) 26 /* uid_t euid; 27 /* 28 /* int setegid(egid) 29 /* gid_t euid; 30 /* 31 /* int mkfifo(path, mode) 32 /* char *path; 33 /* int mode; 34 /* 35 /* int waitpid(pid, statusp, options) 36 /* int pid; 37 /* WAIT_STATUS_T *statusp; 38 /* int options; 39 /* 40 /* int setsid() 41 /* 42 /* void dup2_pass_on_exec(int oldd, int newd) 43 /* 44 /* char *inet_ntop(af, src, dst, size) 45 /* int af; 46 /* const void *src; 47 /* char *dst; 48 /* SOCKADDR_SIZE size; 49 /* 50 /* int inet_pton(af, src, dst) 51 /* int af; 52 /* const char *src; 53 /* void *dst; 54 /* DESCRIPTION 55 /* These routines are compiled for platforms that lack the functionality 56 /* or that have broken versions that we prefer to stay away from. 57 /* LICENSE 58 /* .ad 59 /* .fi 60 /* The Secure Mailer license must be distributed with this software. 61 /* AUTHOR(S) 62 /* Wietse Venema 63 /* IBM T.J. Watson Research 64 /* P.O. Box 704 65 /* Yorktown Heights, NY 10598, USA 66 /* 67 /* Wietse Venema 68 /* Google, Inc. 69 /* 111 8th Avenue 70 /* New York, NY 10011, USA 71 /*--*/ 72 73 /* System library. */ 74 75 #include "sys_defs.h" 76 77 /* 78 * ANSI strerror() emulation 79 */ 80 #ifdef MISSING_STRERROR 81 82 extern int errno; 83 extern char *sys_errlist[]; 84 extern int sys_nerr; 85 86 #include <vstring.h> 87 88 /* strerror - print text corresponding to error */ 89 90 const char *strerror(int err) 91 { 92 static VSTRING *buf; 93 94 if (err < 0 || err >= sys_nerr) { 95 if (buf == 0) 96 buf = vstring_alloc(10); 97 vstring_sprintf(buf, "Unknown error %d", err); 98 return (vstring_str(buf)); 99 } else { 100 return (sys_errlist[errno]); 101 } 102 } 103 104 #endif 105 106 /* 107 * setenv() emulation on top of putenv(). 108 */ 109 #ifdef MISSING_SETENV 110 111 #include <stdio.h> 112 #include <string.h> 113 #include <stdlib.h> 114 115 /* setenv - update or insert environment (name,value) pair */ 116 117 int setenv(const char *name, const char *value, int clobber) 118 { 119 char *cp; 120 121 if (clobber == 0 && getenv(name) != 0) 122 return (0); 123 if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) 124 return (1); 125 sprintf(cp, "%s=%s", name, value); 126 return (putenv(cp)); 127 } 128 129 /* unsetenv - remove all instances of the name */ 130 131 int unsetenv(const char *name) 132 { 133 extern char **environ; 134 ssize_t name_len = strlen(name); 135 char **src_pp; 136 char **dst_pp; 137 138 for (dst_pp = src_pp = environ; *src_pp; src_pp++, dst_pp++) { 139 if (strncmp(*src_pp, name, name_len) == 0 140 && *(*src_pp + name_len) == '=') { 141 dst_pp--; 142 } else if (dst_pp != src_pp) { 143 *dst_pp = *src_pp; 144 } 145 } 146 *dst_pp = 0; 147 return (0); 148 } 149 150 #endif 151 152 /* 153 * seteuid() and setegid() emulation, the HP-UX way 154 */ 155 #ifdef MISSING_SETEUID 156 #ifdef HAVE_SETRESUID 157 #include <unistd.h> 158 159 int seteuid(uid_t euid) 160 { 161 return setresuid(-1, euid, -1); 162 } 163 164 #else 165 #error MISSING_SETEUID 166 #endif 167 168 #endif 169 170 #ifdef MISSING_SETEGID 171 #ifdef HAVE_SETRESGID 172 #include <unistd.h> 173 174 int setegid(gid_t egid) 175 { 176 return setresgid(-1, egid, -1); 177 } 178 179 #else 180 #error MISSING_SETEGID 181 #endif 182 183 #endif 184 185 /* 186 * mkfifo() emulation - requires superuser privileges 187 */ 188 #ifdef MISSING_MKFIFO 189 190 #include <sys/stat.h> 191 192 int mkfifo(char *path, int mode) 193 { 194 return mknod(path, (mode & ~_S_IFMT) | _S_IFIFO, 0); 195 } 196 197 #endif 198 199 /* 200 * waitpid() emulation on top of Berkeley UNIX wait4() 201 */ 202 #ifdef MISSING_WAITPID 203 #ifdef HAS_WAIT4 204 205 #include <sys/wait.h> 206 #include <errno.h> 207 208 int waitpid(int pid, WAIT_STATUS_T *status, int options) 209 { 210 if (pid == -1) 211 pid = 0; 212 return wait4(pid, status, options, (struct rusage *) 0); 213 } 214 215 #else 216 #error MISSING_WAITPID 217 #endif 218 219 #endif 220 221 /* 222 * setsid() emulation, the Berkeley UNIX way 223 */ 224 #ifdef MISSING_SETSID 225 226 #include <sys/ioctl.h> 227 #include <unistd.h> 228 #include <fcntl.h> 229 #include <errno.h> 230 231 #ifdef TIOCNOTTY 232 233 #include <msg.h> 234 235 int setsid(void) 236 { 237 int p = getpid(); 238 int fd; 239 240 if (setpgrp(p, p)) 241 return -1; 242 243 fd = open("/dev/tty", O_RDONLY, 0); 244 if (fd >= 0 || errno != ENXIO) { 245 if (fd < 0) { 246 msg_warn("open /dev/tty: %m"); 247 return -1; 248 } 249 if (ioctl(fd, TIOCNOTTY, 0)) { 250 msg_warn("ioctl TIOCNOTTY: %m"); 251 return -1; 252 } 253 close(fd); 254 } 255 return 0; 256 } 257 258 #else 259 #error MISSING_SETSID 260 #endif 261 262 #endif 263 264 /* 265 * dup2_pass_on_exec() - dup2() and clear close-on-exec flag on the result 266 */ 267 #ifdef DUP2_DUPS_CLOSE_ON_EXEC 268 269 #include "iostuff.h" 270 271 int dup2_pass_on_exec(int oldd, int newd) 272 { 273 int res; 274 275 if ((res = dup2(oldd, newd)) >= 0) 276 close_on_exec(newd, PASS_ON_EXEC); 277 278 return res; 279 } 280 281 #endif 282 283 #ifndef HAS_CLOSEFROM 284 285 #include <unistd.h> 286 #include <errno.h> 287 #include <iostuff.h> 288 289 /* closefrom() - closes all file descriptors from the given one up */ 290 291 int closefrom(int lowfd) 292 { 293 int fd_limit = open_limit(0); 294 int fd; 295 296 /* 297 * lowfrom does not have an easy to determine upper limit. A process may 298 * have files open that were inherited from a parent process with a less 299 * restrictive resource limit. 300 */ 301 if (lowfd < 0) { 302 errno = EBADF; 303 return (-1); 304 } 305 if (fd_limit > 500) 306 fd_limit = 500; 307 for (fd = lowfd; fd < fd_limit; fd++) 308 (void) close(fd); 309 310 return (0); 311 } 312 313 #endif 314 315 #ifdef MISSING_INET_NTOP 316 317 #include <sys/types.h> 318 #include <sys/socket.h> 319 #include <netinet/in.h> 320 #include <arpa/inet.h> 321 #include <stdio.h> 322 #include <string.h> 323 #include <errno.h> 324 325 /* inet_ntop - convert binary address to printable address */ 326 327 const char *inet_ntop(int af, const void *src, char *dst, SOCKADDR_SIZE size) 328 { 329 const unsigned char *addr; 330 char buffer[sizeof("255.255.255.255")]; 331 int len; 332 333 if (af != AF_INET) { 334 errno = EAFNOSUPPORT; 335 return (0); 336 } 337 addr = (const unsigned char *) src; 338 #if (CHAR_BIT > 8) 339 sprintf(buffer, "%d.%d.%d.%d", addr[0] & 0xff, 340 addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff); 341 #else 342 sprintf(buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 343 #endif 344 if ((len = strlen(buffer)) >= size) { 345 errno = ENOSPC; 346 return (0); 347 } else { 348 memcpy(dst, buffer, len + 1); 349 return (dst); 350 } 351 } 352 353 #endif 354 355 #ifdef MISSING_INET_PTON 356 357 #include <sys/types.h> 358 #include <sys/socket.h> 359 #include <netinet/in.h> 360 #include <arpa/inet.h> 361 #include <string.h> 362 #include <errno.h> 363 364 #ifndef INADDR_NONE 365 #define INADDR_NONE 0xffffffff 366 #endif 367 368 /* inet_pton - convert printable address to binary address */ 369 370 int inet_pton(int af, const char *src, void *dst) 371 { 372 struct in_addr addr; 373 374 /* 375 * inet_addr() accepts a wider range of input formats than inet_pton(); 376 * the former accepts 1-, 2-, or 3-part dotted addresses, while the 377 * latter requires dotted quad form. 378 */ 379 if (af != AF_INET) { 380 errno = EAFNOSUPPORT; 381 return (-1); 382 } else if ((addr.s_addr = inet_addr(src)) == INADDR_NONE 383 && strcmp(src, "255.255.255.255") != 0) { 384 return (0); 385 } else { 386 memcpy(dst, (void *) &addr, sizeof(addr)); 387 return (1); 388 } 389 } 390 391 #endif 392