logo

utils-std

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

pwd.c (2157B)


  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. for(int c = -1; (c = getopt(argc, argv, ":LP")) != -1;)
  63. {
  64. switch(c)
  65. {
  66. case 'L':
  67. mode = PWD_L;
  68. break;
  69. case 'P':
  70. mode = PWD_P;
  71. break;
  72. case ':':
  73. fprintf(stderr, "%s: error: Missing operand for option '-%c'\n", argv0, optopt);
  74. usage();
  75. return 1;
  76. case '?':
  77. fprintf(stderr, "%s: error: Unrecognised option '-%c'\n", argv0, optopt);
  78. usage();
  79. return 1;
  80. }
  81. }
  82. argc -= optind;
  83. argv += optind;
  84. if(argc != 0)
  85. {
  86. usage();
  87. return 1;
  88. }
  89. if(mode == PWD_L)
  90. {
  91. char *pwd = getenv("PWD");
  92. if(is_pwd(pwd))
  93. {
  94. if(puts(pwd) < 0)
  95. {
  96. perror("pwd: error: puts");
  97. return 1;
  98. }
  99. return 0;
  100. }
  101. }
  102. char pwd[PATH_MAX] = "";
  103. if(getcwd(pwd, sizeof(pwd)) == NULL)
  104. {
  105. perror("pwd: error: getcwd");
  106. return 1;
  107. }
  108. if(puts(pwd) < 0)
  109. {
  110. perror("pwd: error: puts");
  111. return 1;
  112. }
  113. return 0;
  114. }