logo

utils-std

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

pwd.c (2159B)


  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 _POSIX_C_SOURCE 200809L
  5. #include <limits.h> // PATH_MAX
  6. #include <stdbool.h>
  7. #include <stdio.h> // puts, perror, printf
  8. #include <stdlib.h> // getenv
  9. #include <sys/stat.h>
  10. #include <unistd.h> // getcwd
  11. const char *argv0 = "pwd";
  12. enum pwd
  13. {
  14. PWD_L = 0,
  15. PWD_P = 1,
  16. };
  17. static void
  18. usage(void)
  19. {
  20. fputs("Usage: pwd [-L|-P]\n", stderr);
  21. }
  22. static bool
  23. is_absolute(char *path)
  24. {
  25. if(!path) return false;
  26. if(path[0] != '/') return false;
  27. size_t dotlen = 0;
  28. for(size_t i = 1; path[i] != '\0'; i++)
  29. {
  30. switch(path[i])
  31. {
  32. case '.':
  33. dotlen++;
  34. break;
  35. case '/':
  36. if(dotlen == 1 || dotlen == 2) return false;
  37. dotlen = 0;
  38. break;
  39. default:
  40. dotlen = 0;
  41. break;
  42. }
  43. }
  44. return true;
  45. }
  46. static bool
  47. is_pwd(char *path)
  48. {
  49. if(!is_absolute(path)) return false;
  50. struct stat path_status;
  51. if(stat(path, &path_status) < 0) return false;
  52. struct stat dot_status;
  53. if(stat(".", &dot_status) < 0) return false;
  54. if(path_status.st_dev != dot_status.st_dev) return false;
  55. if(path_status.st_ino != dot_status.st_ino) return false;
  56. return true;
  57. }
  58. int
  59. main(int argc, char *argv[])
  60. {
  61. enum pwd mode = PWD_L;
  62. int c = -1;
  63. while((c = getopt(argc, argv, ":LP")) != -1)
  64. {
  65. switch(c)
  66. {
  67. case 'L':
  68. mode = PWD_L;
  69. break;
  70. case 'P':
  71. mode = PWD_P;
  72. break;
  73. case ':':
  74. fprintf(stderr, "%s: error: Missing operand for option '-%c'\n", argv0, optopt);
  75. usage();
  76. return 1;
  77. case '?':
  78. fprintf(stderr, "%s: error: Unrecognised option '-%c'\n", argv0, optopt);
  79. usage();
  80. return 1;
  81. }
  82. }
  83. argc -= optind;
  84. argv += optind;
  85. if(argc != 0)
  86. {
  87. usage();
  88. return 1;
  89. }
  90. if(mode == PWD_L)
  91. {
  92. char *pwd = getenv("PWD");
  93. if(is_pwd(pwd))
  94. {
  95. if(puts(pwd) < 0)
  96. {
  97. perror("pwd: error: puts");
  98. return 1;
  99. }
  100. return 0;
  101. }
  102. }
  103. char pwd[PATH_MAX] = "";
  104. if(getcwd(pwd, sizeof(pwd)) == NULL)
  105. {
  106. perror("pwd: error: getcwd");
  107. return 1;
  108. }
  109. if(puts(pwd) < 0)
  110. {
  111. perror("pwd: error: puts");
  112. return 1;
  113. }
  114. return 0;
  115. }