logo

utils-std

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

basename.c (2238B)


  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 <libgen.h> // basename
  6. #include <stdbool.h>
  7. #include <stdio.h> // puts, perror
  8. #include <string.h> // strlen, strncmp
  9. #include <unistd.h> // getopt
  10. const char *argv0 = "basename";
  11. #ifdef __GNUC__
  12. #define _NonNull __attribute__((nonnull))
  13. #else
  14. #define _NonNull
  15. #endif
  16. _NonNull static char *
  17. suffix_basename(char *name, char *suffix)
  18. {
  19. char *string = basename(name);
  20. size_t suflen = strlen(suffix);
  21. size_t len = strlen(string);
  22. if(suflen < len && strcmp(&string[len - suflen], suffix) == 0)
  23. {
  24. string[len - suflen] = '\0';
  25. }
  26. return string;
  27. }
  28. static void
  29. usage()
  30. {
  31. fputs("Usage: basename [-z] [path] [suffix]\n"
  32. " basename [-az] [-s suffix] [path...]\n",
  33. stderr);
  34. }
  35. int
  36. main(int argc, char *argv[])
  37. {
  38. bool opt_a = false;
  39. char *suffix = NULL;
  40. char delim = '\n';
  41. int c = -1;
  42. while((c = getopt(argc, argv, ":as:z")) != -1)
  43. {
  44. switch(c)
  45. {
  46. case 'a':
  47. opt_a = true;
  48. break;
  49. case 's':
  50. opt_a = true;
  51. suffix = optarg;
  52. break;
  53. case 'z':
  54. delim = '\0';
  55. break;
  56. case ':':
  57. fprintf(stderr, "%s: error: Missing operand for option '-%c'\n", argv0, optopt);
  58. usage();
  59. return 1;
  60. case '?':
  61. fprintf(stderr, "%s: error: Unrecognised option '-%c'\n", argv0, optopt);
  62. usage();
  63. return 1;
  64. }
  65. }
  66. argc -= optind;
  67. argv += optind;
  68. if(!opt_a || argc == 0)
  69. {
  70. int ret = 0;
  71. switch(argc)
  72. {
  73. case 0:
  74. ret = printf(".%c", delim);
  75. break;
  76. case 1:
  77. ret = printf("%s%c", basename(argv[0]), delim);
  78. break;
  79. case 2:
  80. ret = printf("%s%c", suffix_basename(argv[0], argv[1]), delim);
  81. break;
  82. default:
  83. usage();
  84. return 1;
  85. }
  86. if(ret < 0)
  87. {
  88. perror("basename: error: Failed to print result");
  89. return 1;
  90. }
  91. return 0;
  92. }
  93. for(int argi = 0; argi < argc; argi++)
  94. {
  95. char *res = NULL;
  96. if(suffix != NULL)
  97. res = suffix_basename(argv[argi], suffix);
  98. else
  99. res = basename(argv[argi]);
  100. if(printf("%s%c", res, delim) < 0)
  101. {
  102. perror("basename: error: Failed to print result");
  103. return 1;
  104. }
  105. }
  106. return 0;
  107. }