logo

utils-std

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

basename.c (2240B)


  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(void)
  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. for(int c = -1; (c = getopt(argc, argv, ":as:z")) != -1;)
  42. {
  43. switch(c)
  44. {
  45. case 'a':
  46. opt_a = true;
  47. break;
  48. case 's':
  49. opt_a = true;
  50. suffix = optarg;
  51. break;
  52. case 'z':
  53. delim = '\0';
  54. break;
  55. case ':':
  56. fprintf(stderr, "%s: error: Missing operand for option '-%c'\n", argv0, optopt);
  57. usage();
  58. return 1;
  59. case '?':
  60. fprintf(stderr, "%s: error: Unrecognised option '-%c'\n", argv0, optopt);
  61. usage();
  62. return 1;
  63. }
  64. }
  65. argc -= optind;
  66. argv += optind;
  67. if(!opt_a || argc == 0)
  68. {
  69. int ret = 0;
  70. switch(argc)
  71. {
  72. case 0:
  73. ret = printf(".%c", delim);
  74. break;
  75. case 1:
  76. ret = printf("%s%c", basename(argv[0]), delim);
  77. break;
  78. case 2:
  79. ret = printf("%s%c", suffix_basename(argv[0], argv[1]), delim);
  80. break;
  81. default:
  82. usage();
  83. return 1;
  84. }
  85. if(ret < 0)
  86. {
  87. perror("basename: error: Failed to print result");
  88. return 1;
  89. }
  90. return 0;
  91. }
  92. for(int argi = 0; argi < argc; argi++)
  93. {
  94. char *res = NULL;
  95. if(suffix != NULL)
  96. res = suffix_basename(argv[argi], suffix);
  97. else
  98. res = basename(argv[argi]);
  99. if(printf("%s%c", res, delim) < 0)
  100. {
  101. perror("basename: error: Failed to print result");
  102. return 1;
  103. }
  104. }
  105. return 0;
  106. }