1 /* xwrap.c - wrappers around existing library functions. 2 * 3 * Functions with the x prefix are wrappers that either succeed or kill the 4 * program with an error message, but never return failure. They usually have 5 * the same arguments and return value as the function they wrap. 6 * 7 * Copyright 2006 Rob Landley <rob (at) landley.net> 8 */ 9 10 #include "toys.h" 11 12 // strcpy and strncat with size checking. Size is the total space in "dest", 13 // including null terminator. Exit if there's not enough space for the string 14 // (including space for the null terminator), because silently truncating is 15 // still broken behavior. (And leaving the string unterminated is INSANE.) 16 void xstrncpy(char *dest, char *src, size_t size) 17 { 18 if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size); 19 strcpy(dest, src); 20 } 21 22 void xstrncat(char *dest, char *src, size_t size) 23 { 24 long len = strlen(dest); 25 26 if (len+strlen(src)+1 > size) 27 error_exit("'%s%s' > %ld bytes", dest, src, (long)size); 28 strcpy(dest+len, src); 29 } 30 31 void xexit(void) 32 { 33 if (toys.rebound) longjmp(*toys.rebound, 1); 34 if (fflush(NULL) || ferror(stdout)) 35 if (!toys.exitval) perror_msg("write"); 36 37 exit(toys.exitval); 38 } 39 40 // Die unless we can allocate memory. 41 void *xmalloc(size_t size) 42 { 43 void *ret = malloc(size); 44 if (!ret) error_exit("xmalloc(%ld)", (long)size); 45 46 return ret; 47 } 48 49 // Die unless we can allocate prezeroed memory. 50 void *xzalloc(size_t size) 51 { 52 void *ret = xmalloc(size); 53 memset(ret, 0, size); 54 return ret; 55 } 56 57 // Die unless we can change the size of an existing allocation, possibly 58 // moving it. (Notice different arguments from libc function.) 59 void *xrealloc(void *ptr, size_t size) 60 { 61 ptr = realloc(ptr, size); 62 if (!ptr) error_exit("xrealloc"); 63 64 return ptr; 65 } 66 67 // Die unless we can allocate a copy of this many bytes of string. 68 char *xstrndup(char *s, size_t n) 69 { 70 char *ret = strndup(s, ++n); 71 72 if (!ret) error_exit("xstrndup"); 73 ret[--n] = 0; 74 75 return ret; 76 } 77 78 // Die unless we can allocate a copy of this string. 79 char *xstrdup(char *s) 80 { 81 return xstrndup(s, strlen(s)); 82 } 83 84 void *xmemdup(void *s, long len) 85 { 86 void *ret = xmalloc(len); 87 memcpy(ret, s, len); 88 89 return ret; 90 } 91 92 // Die unless we can allocate enough space to sprintf() into. 93 char *xmprintf(char *format, ...) 94 { 95 va_list va, va2; 96 int len; 97 char *ret; 98 99 va_start(va, format); 100 va_copy(va2, va); 101 102 // How long is it? 103 len = vsnprintf(0, 0, format, va); 104 len++; 105 va_end(va); 106 107 // Allocate and do the sprintf() 108 ret = xmalloc(len); 109 vsnprintf(ret, len, format, va2); 110 va_end(va2); 111 112 return ret; 113 } 114 115 void xprintf(char *format, ...) 116 { 117 va_list va; 118 va_start(va, format); 119 120 vprintf(format, va); 121 va_end(va); 122 if (fflush(stdout) || ferror(stdout)) perror_exit("write"); 123 } 124 125 void xputs(char *s) 126 { 127 if (EOF == puts(s) || fflush(stdout) || ferror(stdout)) perror_exit("write"); 128 } 129 130 void xputc(char c) 131 { 132 if (EOF == fputc(c, stdout) || fflush(stdout) || ferror(stdout)) 133 perror_exit("write"); 134 } 135 136 void xflush(void) 137 { 138 if (fflush(stdout) || ferror(stdout)) perror_exit("write");; 139 } 140 141 // This is called through the XVFORK macro because parent/child of vfork 142 // share a stack, so child returning from a function would stomp the return 143 // address parent would need. Solution: make vfork() an argument so processes 144 // diverge before function gets called. 145 pid_t xvforkwrap(pid_t pid) 146 { 147 if (pid == -1) perror_exit("vfork"); 148 149 // Signal to xexec() and friends that we vforked so can't recurse 150 toys.stacktop = 0; 151 152 return pid; 153 } 154 155 // Die unless we can exec argv[] (or run builtin command). Note that anything 156 // with a path isn't a builtin, so /bin/sh won't match the builtin sh. 157 void xexec(char **argv) 158 { 159 // Only recurse to builtin when we have multiplexer and !vfork context. 160 if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE && toys.stacktop) toy_exec(argv); 161 execvp(argv[0], argv); 162 163 perror_msg("exec %s", argv[0]); 164 toys.exitval = 127; 165 if (!CFG_TOYBOX_FORK) _exit(toys.exitval); 166 xexit(); 167 } 168 169 // Spawn child process, capturing stdin/stdout. 170 // argv[]: command to exec. If null, child re-runs original program with 171 // toys.stacktop zeroed. 172 // pipes[2]: stdin, stdout of new process, only allocated if zero on way in, 173 // pass NULL to skip pipe allocation entirely. 174 // return: pid of child process 175 pid_t xpopen_both(char **argv, int *pipes) 176 { 177 int cestnepasun[4], pid; 178 179 // Make the pipes? Note this won't set either pipe to 0 because if fds are 180 // allocated in order and if fd0 was free it would go to cestnepasun[0] 181 if (pipes) { 182 for (pid = 0; pid < 2; pid++) { 183 if (pipes[pid] != 0) continue; 184 if (pipe(cestnepasun+(2*pid))) perror_exit("pipe"); 185 pipes[pid] = cestnepasun[pid+1]; 186 } 187 } 188 189 // Child process. 190 if (!(pid = CFG_TOYBOX_FORK ? xfork() : XVFORK())) { 191 // Dance of the stdin/stdout redirection. 192 if (pipes) { 193 // if we had no stdin/out, pipe handles could overlap, so test for it 194 // and free up potentially overlapping pipe handles before reuse 195 if (pipes[1] != -1) close(cestnepasun[2]); 196 if (pipes[0] != -1) { 197 close(cestnepasun[1]); 198 if (cestnepasun[0]) { 199 dup2(cestnepasun[0], 0); 200 close(cestnepasun[0]); 201 } 202 } 203 if (pipes[1] != -1) { 204 dup2(cestnepasun[3], 1); 205 dup2(cestnepasun[3], 2); 206 if (cestnepasun[3] > 2 || !cestnepasun[3]) close(cestnepasun[3]); 207 } 208 } 209 if (argv) xexec(argv); 210 211 // In fork() case, force recursion because we know it's us. 212 if (CFG_TOYBOX_FORK) { 213 toy_init(toys.which, toys.argv); 214 toys.stacktop = 0; 215 toys.which->toy_main(); 216 xexit(); 217 // In vfork() case, exec /proc/self/exe with high bit of first letter set 218 // to tell main() we reentered. 219 } else { 220 char *s = "/proc/self/exe"; 221 222 // We did a nommu-friendly vfork but must exec to continue. 223 // setting high bit of argv[0][0] to let new process know 224 **toys.argv |= 0x80; 225 execv(s, toys.argv); 226 perror_msg_raw(s); 227 228 _exit(127); 229 } 230 } 231 232 // Parent process 233 if (!CFG_TOYBOX_FORK) **toys.argv &= 0x7f; 234 if (pipes) { 235 if (pipes[0] != -1) close(cestnepasun[0]); 236 if (pipes[1] != -1) close(cestnepasun[3]); 237 } 238 239 return pid; 240 } 241 242 // Wait for child process to exit, then return adjusted exit code. 243 int xwaitpid(pid_t pid) 244 { 245 int status; 246 247 while (-1 == waitpid(pid, &status, 0) && errno == EINTR); 248 249 return WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127; 250 } 251 252 int xpclose_both(pid_t pid, int *pipes) 253 { 254 if (pipes) { 255 close(pipes[0]); 256 close(pipes[1]); 257 } 258 259 return xwaitpid(pid); 260 } 261 262 // Wrapper to xpopen with a pipe for just one of stdin/stdout 263 pid_t xpopen(char **argv, int *pipe, int stdout) 264 { 265 int pipes[2], pid; 266 267 pipes[!stdout] = -1; 268 pipes[!!stdout] = 0; 269 pid = xpopen_both(argv, pipes); 270 *pipe = pid ? pipes[!!stdout] : -1; 271 272 return pid; 273 } 274 275 int xpclose(pid_t pid, int pipe) 276 { 277 close(pipe); 278 279 return xpclose_both(pid, 0); 280 } 281 282 // Call xpopen and wait for it to finish, keeping existing stdin/stdout. 283 int xrun(char **argv) 284 { 285 return xpclose_both(xpopen_both(argv, 0), 0); 286 } 287 288 void xaccess(char *path, int flags) 289 { 290 if (access(path, flags)) perror_exit("Can't access '%s'", path); 291 } 292 293 // Die unless we can delete a file. (File must exist to be deleted.) 294 void xunlink(char *path) 295 { 296 if (unlink(path)) perror_exit("unlink '%s'", path); 297 } 298 299 // Die unless we can open/create a file, returning file descriptor. 300 int xcreate(char *path, int flags, int mode) 301 { 302 int fd = open(path, flags^O_CLOEXEC, mode); 303 if (fd == -1) perror_exit_raw(path); 304 return fd; 305 } 306 307 // Die unless we can open a file, returning file descriptor. 308 int xopen(char *path, int flags) 309 { 310 return xcreate(path, flags, 0); 311 } 312 313 void xpipe(int *pp) 314 { 315 if (pipe(pp)) perror_exit("xpipe"); 316 } 317 318 void xclose(int fd) 319 { 320 if (close(fd)) perror_exit("xclose"); 321 } 322 323 int xdup(int fd) 324 { 325 if (fd != -1) { 326 fd = dup(fd); 327 if (fd == -1) perror_exit("xdup"); 328 } 329 return fd; 330 } 331 332 FILE *xfdopen(int fd, char *mode) 333 { 334 FILE *f = fdopen(fd, mode); 335 336 if (!f) perror_exit("xfdopen"); 337 338 return f; 339 } 340 341 // Die unless we can open/create a file, returning FILE *. 342 FILE *xfopen(char *path, char *mode) 343 { 344 FILE *f = fopen(path, mode); 345 if (!f) perror_exit("No file %s", path); 346 return f; 347 } 348 349 // Die if there's an error other than EOF. 350 size_t xread(int fd, void *buf, size_t len) 351 { 352 ssize_t ret = read(fd, buf, len); 353 if (ret < 0) perror_exit("xread"); 354 355 return ret; 356 } 357 358 void xreadall(int fd, void *buf, size_t len) 359 { 360 if (len != readall(fd, buf, len)) perror_exit("xreadall"); 361 } 362 363 // There's no xwriteall(), just xwrite(). When we read, there may or may not 364 // be more data waiting. When we write, there is data and it had better go 365 // somewhere. 366 367 void xwrite(int fd, void *buf, size_t len) 368 { 369 if (len != writeall(fd, buf, len)) perror_exit("xwrite"); 370 } 371 372 // Die if lseek fails, probably due to being called on a pipe. 373 374 off_t xlseek(int fd, off_t offset, int whence) 375 { 376 offset = lseek(fd, offset, whence); 377 if (offset<0) perror_exit("lseek"); 378 379 return offset; 380 } 381 382 char *xgetcwd(void) 383 { 384 char *buf = getcwd(NULL, 0); 385 if (!buf) perror_exit("xgetcwd"); 386 387 return buf; 388 } 389 390 void xstat(char *path, struct stat *st) 391 { 392 if(stat(path, st)) perror_exit("Can't stat %s", path); 393 } 394 395 // Cannonicalize path, even to file with one or more missing components at end. 396 // if exact, require last path component to exist 397 char *xabspath(char *path, int exact) 398 { 399 struct string_list *todo, *done = 0; 400 int try = 9999, dirfd = open("/", 0);; 401 char buf[4096], *ret; 402 403 // If this isn't an absolute path, start with cwd. 404 if (*path != '/') { 405 char *temp = xgetcwd(); 406 407 splitpath(path, splitpath(temp, &todo)); 408 free(temp); 409 } else splitpath(path, &todo); 410 411 // Iterate through path components 412 while (todo) { 413 struct string_list *new = llist_pop(&todo), **tail; 414 ssize_t len; 415 416 if (!try--) { 417 errno = ELOOP; 418 goto error; 419 } 420 421 // Removable path componenents. 422 if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { 423 int x = new->str[1]; 424 425 free(new); 426 if (x) { 427 if (done) free(llist_pop(&done)); 428 len = 0; 429 } else continue; 430 431 // Is this a symlink? 432 } else len=readlinkat(dirfd, new->str, buf, 4096); 433 434 if (len>4095) goto error; 435 if (len<1) { 436 int fd; 437 char *s = ".."; 438 439 // For .. just move dirfd 440 if (len) { 441 // Not a symlink: add to linked list, move dirfd, fail if error 442 if ((exact || todo) && errno != EINVAL) goto error; 443 new->next = done; 444 done = new; 445 if (errno == EINVAL && !todo) break; 446 s = new->str; 447 } 448 fd = openat(dirfd, s, 0); 449 if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; 450 close(dirfd); 451 dirfd = fd; 452 continue; 453 } 454 455 // If this symlink is to an absolute path, discard existing resolved path 456 buf[len] = 0; 457 if (*buf == '/') { 458 llist_traverse(done, free); 459 done=0; 460 close(dirfd); 461 dirfd = open("/", 0); 462 } 463 free(new); 464 465 // prepend components of new path. Note symlink to "/" will leave new NULL 466 tail = splitpath(buf, &new); 467 468 // symlink to "/" will return null and leave tail alone 469 if (new) { 470 *tail = todo; 471 todo = new; 472 } 473 } 474 close(dirfd); 475 476 // At this point done has the path, in reverse order. Reverse list while 477 // calculating buffer length. 478 479 try = 2; 480 while (done) { 481 struct string_list *temp = llist_pop(&done);; 482 483 if (todo) try++; 484 try += strlen(temp->str); 485 temp->next = todo; 486 todo = temp; 487 } 488 489 // Assemble return buffer 490 491 ret = xmalloc(try); 492 *ret = '/'; 493 ret [try = 1] = 0; 494 while (todo) { 495 if (try>1) ret[try++] = '/'; 496 try = stpcpy(ret+try, todo->str) - ret; 497 free(llist_pop(&todo)); 498 } 499 500 return ret; 501 502 error: 503 close(dirfd); 504 llist_traverse(todo, free); 505 llist_traverse(done, free); 506 507 return NULL; 508 } 509 510 void xchdir(char *path) 511 { 512 if (chdir(path)) error_exit("chdir '%s'", path); 513 } 514 515 void xchroot(char *path) 516 { 517 if (chroot(path)) error_exit("chroot '%s'", path); 518 xchdir("/"); 519 } 520 521 struct passwd *xgetpwuid(uid_t uid) 522 { 523 struct passwd *pwd = getpwuid(uid); 524 if (!pwd) error_exit("bad uid %ld", (long)uid); 525 return pwd; 526 } 527 528 struct group *xgetgrgid(gid_t gid) 529 { 530 struct group *group = getgrgid(gid); 531 532 if (!group) perror_exit("gid %ld", (long)gid); 533 return group; 534 } 535 536 struct passwd *xgetpwnamid(char *user) 537 { 538 struct passwd *up = getpwnam(user); 539 uid_t uid; 540 541 if (!up) { 542 char *s = 0; 543 544 uid = estrtol(user, &s, 10); 545 if (!errno && s && !*s) up = getpwuid(uid); 546 } 547 if (!up) perror_exit("user '%s'", user); 548 549 return up; 550 } 551 552 struct group *xgetgrnamid(char *group) 553 { 554 struct group *gr = getgrnam(group); 555 gid_t gid; 556 557 if (!gr) { 558 char *s = 0; 559 560 gid = estrtol(group, &s, 10); 561 if (!errno && s && !*s) gr = getgrgid(gid); 562 } 563 if (!gr) perror_exit("group '%s'", group); 564 565 return gr; 566 } 567 568 struct passwd *xgetpwnam(char *name) 569 { 570 struct passwd *up = getpwnam(name); 571 572 if (!up) perror_exit("user '%s'", name); 573 return up; 574 } 575 576 struct group *xgetgrnam(char *name) 577 { 578 struct group *gr = getgrnam(name); 579 580 if (!gr) perror_exit("group '%s'", name); 581 return gr; 582 } 583 584 // setuid() can fail (for example, too many processes belonging to that user), 585 // which opens a security hole if the process continues as the original user. 586 587 void xsetuser(struct passwd *pwd) 588 { 589 if (initgroups(pwd->pw_name, pwd->pw_gid) || setgid(pwd->pw_uid) 590 || setuid(pwd->pw_uid)) perror_exit("xsetuser '%s'", pwd->pw_name); 591 } 592 593 // This can return null (meaning file not found). It just won't return null 594 // for memory allocation reasons. 595 char *xreadlink(char *name) 596 { 597 int len, size = 0; 598 char *buf = 0; 599 600 // Grow by 64 byte chunks until it's big enough. 601 for(;;) { 602 size +=64; 603 buf = xrealloc(buf, size); 604 len = readlink(name, buf, size); 605 606 if (len<0) { 607 free(buf); 608 return 0; 609 } 610 if (len<size) { 611 buf[len]=0; 612 return buf; 613 } 614 } 615 } 616 617 char *xreadfile(char *name, char *buf, off_t len) 618 { 619 if (!(buf = readfile(name, buf, len))) perror_exit("Bad '%s'", name); 620 621 return buf; 622 } 623 624 int xioctl(int fd, int request, void *data) 625 { 626 int rc; 627 628 errno = 0; 629 rc = ioctl(fd, request, data); 630 if (rc == -1 && errno) perror_exit("ioctl %x", request); 631 632 return rc; 633 } 634 635 // Open a /var/run/NAME.pid file, dying if we can't write it or if it currently 636 // exists and is this executable. 637 void xpidfile(char *name) 638 { 639 char pidfile[256], spid[32]; 640 int i, fd; 641 pid_t pid; 642 643 sprintf(pidfile, "/var/run/%s.pid", name); 644 // Try three times to open the sucker. 645 for (i=0; i<3; i++) { 646 fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); 647 if (fd != -1) break; 648 649 // If it already existed, read it. Loop for race condition. 650 fd = open(pidfile, O_RDONLY); 651 if (fd == -1) continue; 652 653 // Is the old program still there? 654 spid[xread(fd, spid, sizeof(spid)-1)] = 0; 655 close(fd); 656 pid = atoi(spid); 657 if (pid < 1 || (kill(pid, 0) && errno == ESRCH)) unlink(pidfile); 658 659 // An else with more sanity checking might be nice here. 660 } 661 662 if (i == 3) error_exit("xpidfile %s", name); 663 664 xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); 665 close(fd); 666 } 667 668 // Copy the rest of in to out and close both files. 669 670 void xsendfile(int in, int out) 671 { 672 long len; 673 674 if (in<0) return; 675 for (;;) { 676 len = xread(in, libbuf, sizeof(libbuf)); 677 if (len<1) break; 678 xwrite(out, libbuf, len); 679 } 680 } 681 682 // parse fractional seconds with optional s/m/h/d suffix 683 long xparsetime(char *arg, long units, long *fraction) 684 { 685 double d; 686 long l; 687 688 if (CFG_TOYBOX_FLOAT) d = strtod(arg, &arg); 689 else l = strtoul(arg, &arg, 10); 690 691 // Parse suffix 692 if (*arg) { 693 int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); 694 695 if (i == -1) error_exit("Unknown suffix '%c'", *arg); 696 if (CFG_TOYBOX_FLOAT) d *= ismhd[i]; 697 else l *= ismhd[i]; 698 } 699 700 if (CFG_TOYBOX_FLOAT) { 701 l = (long)d; 702 if (fraction) *fraction = units*(d-l); 703 } else if (fraction) *fraction = 0; 704 705 return l; 706 } 707 708 // Compile a regular expression into a regex_t 709 void xregcomp(regex_t *preg, char *regex, int cflags) 710 { 711 int rc = regcomp(preg, regex, cflags); 712 713 if (rc) { 714 regerror(rc, preg, libbuf, sizeof(libbuf)); 715 error_exit("xregcomp: %s", libbuf); 716 } 717 } 718 719 char *xtzset(char *new) 720 { 721 char *old = getenv("TZ"); 722 723 if (old) old = xstrdup(old); 724 if (new ? setenv("TZ", new, 1) : unsetenv("TZ")) perror_exit("setenv"); 725 tzset(); 726 727 return old; 728 } 729 730 // Set a signal handler 731 void xsignal(int signal, void *handler) 732 { 733 struct sigaction *sa = (void *)libbuf; 734 735 memset(sa, 0, sizeof(struct sigaction)); 736 sa->sa_handler = handler; 737 738 if (sigaction(signal, sa, 0)) perror_exit("xsignal %d", signal); 739 } 740