IRC bouncer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* Copyright (C) 2019 C. McEnroe <june@causal.agency>
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. #include <err.h>
  17. #include <getopt.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "bounce.h"
  22. #define WS "\t "
  23. static const char *path;
  24. static FILE *file;
  25. static size_t num;
  26. static char *line;
  27. static size_t cap;
  28. static int clean(int opt) {
  29. if (file) fclose(file);
  30. free(line);
  31. line = NULL;
  32. cap = 0;
  33. return opt;
  34. }
  35. int getopt_config(
  36. int argc, char *const *argv,
  37. const char *optstring, const struct option *longopts, int *longindex
  38. ) {
  39. static int opt;
  40. if (opt >= 0) {
  41. opt = getopt_long(argc, argv, optstring, longopts, longindex);
  42. }
  43. if (opt >= 0) return opt;
  44. for (;;) {
  45. if (!file) {
  46. if (optind < argc) {
  47. num = 0;
  48. path = argv[optind++];
  49. file = fopen(path, "r");
  50. if (!file) {
  51. warn("%s", path);
  52. return clean('?');
  53. }
  54. } else {
  55. return clean(-1);
  56. }
  57. }
  58. for (;;) {
  59. ssize_t llen = getline(&line, &cap, file);
  60. if (ferror(file)) {
  61. warn("%s", path);
  62. return clean('?');
  63. }
  64. if (llen <= 0) break;
  65. if (line[llen - 1] == '\n') line[llen - 1] = '\0';
  66. num++;
  67. char *name = line + strspn(line, WS);
  68. size_t len = strcspn(name, WS "=");
  69. if (!name[0] || name[0] == '#') continue;
  70. const struct option *option;
  71. for (option = longopts; option->name; ++option) {
  72. if (strlen(option->name) != len) continue;
  73. if (!strncmp(option->name, name, len)) break;
  74. }
  75. if (!option->name) {
  76. warnx(
  77. "%s:%zu: unrecognized option `%.*s'",
  78. path, num, (int)len, name
  79. );
  80. return clean('?');
  81. }
  82. char *equal = &name[len] + strspn(&name[len], WS);
  83. if (*equal && *equal != '=') {
  84. warnx(
  85. "%s:%zu: option `%s' missing equals sign",
  86. path, num, option->name
  87. );
  88. return clean('?');
  89. }
  90. if (option->has_arg == no_argument && *equal) {
  91. warnx(
  92. "%s:%zu: option `%s' doesn't allow an argument",
  93. path, num, option->name
  94. );
  95. return clean('?');
  96. }
  97. if (option->has_arg == required_argument && !*equal) {
  98. warnx(
  99. "%s:%zu: option `%s' requires an argument",
  100. path, num, option->name
  101. );
  102. return clean(':');
  103. }
  104. optarg = NULL;
  105. if (*equal) {
  106. char *arg = &equal[1] + strspn(&equal[1], WS);
  107. optarg = strdup(arg);
  108. if (!optarg) {
  109. warn("getopt_config");
  110. return clean('?');
  111. }
  112. }
  113. if (longindex) *longindex = option - longopts;
  114. if (option->flag) {
  115. *option->flag = option->val;
  116. return 0;
  117. } else {
  118. return option->val;
  119. }
  120. }
  121. fclose(file);
  122. file = NULL;
  123. }
  124. }