logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git

chroot.c (1449B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _DEFAULT_SOURCE // chroot isn't POSIX
  5. #include <assert.h> // assert
  6. #include <errno.h> // errno
  7. #include <limits.h> // PATH_MAX
  8. #include <stdbool.h> // false
  9. #include <stdio.h> // fprintf, perror
  10. #include <stdlib.h> // getenv
  11. #include <string.h> // strlen
  12. #include <unistd.h> // chroot, execl, execv
  13. int
  14. main(int argc, char *argv[])
  15. {
  16. if(argc < 2)
  17. {
  18. fprintf(stderr, "chroot: error: Needs arguments\n");
  19. fprintf(stderr, "Usage: chroot <newroot> [command [args ...]]\n");
  20. return 125;
  21. }
  22. if(chroot(argv[1]) < 0)
  23. {
  24. perror("chroot: error: Failed to chroot");
  25. return 125;
  26. }
  27. if(chdir("/") < 0)
  28. {
  29. perror("chroot: error: Failed to change directory");
  30. return 125;
  31. }
  32. int ret = 0;
  33. errno = 0;
  34. if(argc == 2)
  35. {
  36. const char *shell = getenv("SHELL");
  37. if(shell == NULL) shell = "/bin/sh";
  38. if(strnlen(shell, PATH_MAX) >= PATH_MAX)
  39. {
  40. fprintf(stderr,
  41. "chroot: warning: $SHELL is longer than {PATH_MAX}(= %d), using '/bin/sh'\n",
  42. PATH_MAX);
  43. shell = "/bin/sh";
  44. }
  45. ret = execlp(shell, shell, "-i", (char *)0);
  46. }
  47. else
  48. {
  49. argv += 2;
  50. ret = execvp(argv[0], argv);
  51. }
  52. if(ret != 0)
  53. {
  54. perror("chroot: error: Execution failed");
  55. if(errno == ENOENT) return 127;
  56. return 126;
  57. }
  58. assert(false);
  59. }