# HG changeset patch # User David Demelier # Date 1643965003 -3600 # Node ID 323d6d34ec1bfa945dd21301559ecae611d78426 # Parent cbc5dfb0b0295e932bb5a10f501cf7cd3bdde17c irccdctl: remove ketopt, closes #2530 diff -r cbc5dfb0b029 -r 323d6d34ec1b CMakeLists.txt --- a/CMakeLists.txt Thu Feb 03 13:16:56 2022 +0100 +++ b/CMakeLists.txt Fri Feb 04 09:56:43 2022 +0100 @@ -82,7 +82,6 @@ endif () add_subdirectory(extern/libutlist) -add_subdirectory(extern/libketopt) add_subdirectory(lib) add_subdirectory(irccd) diff -r cbc5dfb0b029 -r 323d6d34ec1b extern/libketopt/CMakeLists.txt --- a/extern/libketopt/CMakeLists.txt Thu Feb 03 13:16:56 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# -# CMakeLists.txt -- CMake build system for irccd -# -# Copyright (c) 2013-2022 David Demelier -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -project(libirccd-ketopt) - -add_library(libirccd-ketopt INTERFACE ${libirccd-ketopt_SOURCE_DIR}/ketopt.h) -target_include_directories(libirccd-ketopt INTERFACE $) -set_target_properties(libirccd-ketopt PROPERTIES FOLDER extern) diff -r cbc5dfb0b029 -r 323d6d34ec1b extern/libketopt/ketopt.h --- a/extern/libketopt/ketopt.h Thu Feb 03 13:16:56 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -#ifndef KETOPT_H -#define KETOPT_H - -#include /* for strchr() and strncmp() */ - -#define ko_no_argument 0 -#define ko_required_argument 1 -#define ko_optional_argument 2 - -typedef struct { - int ind; /* equivalent to optind */ - int opt; /* equivalent to optopt */ - char *arg; /* equivalent to optarg */ - int longidx; /* index of a long option; or -1 if short */ - /* private variables not intended for external uses */ - int i, pos, n_args; -} ketopt_t; - -typedef struct { - char *name; - int has_arg; - int val; -} ko_longopt_t; - -static ketopt_t KETOPT_INIT = { 0, 0, 0, -1, 0, 0, 0 }; - -static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */ -{ - int k; - char *p = argv[j]; - for (k = 0; k < n; ++k) - argv[j - k] = argv[j - k - 1]; - argv[j - k] = p; -} - -/** - * Parse command-line options and arguments - * - * This fuction has a similar interface to GNU's getopt_long(). Each call - * parses one option and returns the option name. s->arg points to the option - * argument if present. The function returns -1 when all command-line arguments - * are parsed. In this case, s->ind is the index of the first non-option - * argument. - * - * @param s status; shall be initialized to KETOPT_INIT on the first call - * @param argc length of argv[] - * @param argv list of command-line arguments; argv[0] is ignored - * @param permute non-zero to move options ahead of non-option arguments - * @param ostr option string - * @param longopts long options - * - * @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if - * argv[] is fully processed; '?' for an unknown option or an ambiguous - * long option; ':' if an option argument is missing - */ -static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts) -{ - int opt = -1, i0, j; - if (permute) { - while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0')) - ++s->i, ++s->n_args; - } - s->arg = 0, s->longidx = -1, i0 = s->i; - if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') { - s->ind = s->i - s->n_args; - return -1; - } - if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */ - if (argv[s->i][2] == '\0') { /* a bare "--" */ - ketopt_permute(argv, s->i, s->n_args); - ++s->i, s->ind = s->i - s->n_args; - return -1; - } - s->opt = 0, opt = '?', s->pos = -1; - if (longopts) { /* parse long options */ - int k, n_exact = 0, n_partial = 0; - const ko_longopt_t *o = 0, *o_exact = 0, *o_partial = 0; - for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */ - for (k = 0; longopts[k].name != 0; ++k) - if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) { - if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k]; - else ++n_partial, o_partial = &longopts[k]; - } - if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?'; - o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0; - if (o) { - s->opt = opt = o->val, s->longidx = o - longopts; - if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1]; - if (o->has_arg == 1 && argv[s->i][j] == '\0') { - if (s->i < argc - 1) s->arg = argv[++s->i]; - else opt = ':'; /* missing option argument */ - } - } - } - } else { /* a short option */ - const char *p; - if (s->pos == 0) s->pos = 1; - opt = s->opt = argv[s->i][s->pos++]; - p = strchr((char*)ostr, opt); - if (p == 0) { - opt = '?'; /* unknown option */ - } else if (p[1] == ':') { - if (argv[s->i][s->pos] == 0) { - if (s->i < argc - 1) s->arg = argv[++s->i]; - else opt = ':'; /* missing option argument */ - } else s->arg = &argv[s->i][s->pos]; - s->pos = -1; - } - } - if (s->pos < 0 || argv[s->i][s->pos] == 0) { - ++s->i, s->pos = 0; - if (s->n_args > 0) /* permute */ - for (j = i0; j < s->i; ++j) - ketopt_permute(argv, j, s->n_args); - } - s->ind = s->i - s->n_args; - return opt; -} - -#endif diff -r cbc5dfb0b029 -r 323d6d34ec1b irccdctl/CMakeLists.txt --- a/irccdctl/CMakeLists.txt Thu Feb 03 13:16:56 2022 +0100 +++ b/irccdctl/CMakeLists.txt Fri Feb 04 09:56:43 2022 +0100 @@ -19,6 +19,6 @@ project(irccdctl) add_executable(irccdctl ${irccdctl_SOURCE_DIR}/irccdctl.c) -target_link_libraries(irccdctl libirccd libirccd-ketopt) +target_link_libraries(irccdctl libirccd) source_group(TREE ${irccdctl_SOURCE_DIR} FILES ${irccdctl_SOURCE_DIR}/irccdctl.c) install(TARGETS irccdctl DESTINATION ${CMAKE_INSTALL_BINDIR}) diff -r cbc5dfb0b029 -r 323d6d34ec1b irccdctl/irccdctl.c --- a/irccdctl/irccdctl.c Thu Feb 03 13:16:56 2022 +0100 +++ b/irccdctl/irccdctl.c Fri Feb 04 09:56:43 2022 +0100 @@ -30,8 +30,6 @@ #include #include -#include - #include #include @@ -359,6 +357,9 @@ char *line, *p, name[16]; size_t num = 0; + --argc; + ++argv; + if (argc == 3) { req("%s %s %s %s", cmd, argv[0], argv[1], argv[2]); ok(); @@ -410,7 +411,8 @@ static void cmd_hook_add(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("HOOK-ADD %s %s", argv[0], argv[1]); ok(); @@ -428,7 +430,8 @@ static void cmd_hook_remove(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("HOOK-REMOVE %s", argv[0]); ok(); @@ -452,7 +455,8 @@ static void cmd_plugin_info(int argc, char **argv) { - (void)argc; + --argc; + ++argv; const char *response; @@ -480,7 +484,8 @@ static void cmd_plugin_load(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("PLUGIN-LOAD %s", argv[0]); ok(); @@ -495,6 +500,9 @@ static void cmd_plugin_reload(int argc, char **argv) { + --argc; + ++argv; + if (argc == 1) req("PLUGIN-RELOAD %s", argv[0]); else @@ -512,6 +520,9 @@ static void cmd_plugin_unload(int argc, char **argv) { + --argc; + ++argv; + if (argc == 1) req("PLUGIN-UNLOAD %s", argv[0]); else @@ -523,19 +534,19 @@ static void cmd_rule_add(int argc, char **argv) { - ketopt_t ko = KETOPT_INIT; FILE *fp; char out[IRC_BUF_LEN]; + int ch; if (!(fp = fmemopen(out, sizeof (out) - 1, "w"))) irc_util_die("abort: fmemopen: %s\n", strerror(errno)); /* TODO: invalid option. */ - for (int ch; (ch = ketopt(&ko, argc, argv, 0, "c:e:i:o:p:s:", NULL)) != -1; ) - fprintf(fp, "%c=%s ", ch, ko.arg); + while ((ch = getopt(argc, argv, "c:e:i:o:p:s:")) != -1) + fprintf(fp, "%c=%s ", ch, optarg); - argc -= ko.ind; - argv += ko.ind; + argc -= optind; + argv += optind; if (argc < 1) irc_util_die("abort: missing accept or drop rule action\n"); @@ -553,23 +564,23 @@ static void cmd_rule_edit(int argc, char **argv) { - ketopt_t ko = KETOPT_INIT; FILE *fp; char out[IRC_BUF_LEN]; + int ch; if (!(fp = fmemopen(out, sizeof (out) - 1, "w"))) irc_util_die("abort: fmemopen: %s\n", strerror(errno)); /* TODO: invalid option. */ - for (int ch; (ch = ketopt(&ko, argc, argv, 0, "a:C:c:E:e:O:o:P:p:S:s:", NULL)) != -1; ) { + while ((ch = getopt(argc, argv, "a:C:c:E:e:O:o:P:p:S:s:")) != -1) { if (ch == 'a') - fprintf(fp, "a=%s ", ko.arg); + fprintf(fp, "a=%s ", optarg); else - fprintf(fp, "%c%c%s ", tolower(ch), isupper(ch) ? '-' : '+', ko.arg); + fprintf(fp, "%c%c%s ", tolower(ch), isupper(ch) ? '-' : '+', optarg); } - argc -= ko.ind; - argv += ko.ind; + argc -= optind; + argv += optind; if (argc < 1) irc_util_die("abort: missing rule index\n"); @@ -623,7 +634,8 @@ static void cmd_rule_move(int argc, char **argv) { - (void)argc; + --argc; + ++argv; long long from, to; @@ -639,7 +651,8 @@ static void cmd_rule_remove(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("RULE-REMOVE %s", argv[0]); ok(); @@ -648,37 +661,36 @@ static void cmd_server_connect(int argc, char **argv) { - ketopt_t ko = KETOPT_INIT; - int ssl = 0; + int ssl = 0, ch; const char *nickname = "irccd", *username = "irccd", *realname = "IRC Client Daemon", *port = "6667"; - for (int ch; (ch = ketopt(&ko, argc, argv, 0, "sn:r:u:p:", NULL)) != -1; ) { + while ((ch = getopt(argc, argv, "sn:r:u:p:")) != -1) { switch (ch) { case 's': ssl = 1; break; case 'n': - nickname = ko.arg; + nickname = optarg; break; case 'r': - realname = ko.arg; + realname = optarg; break; case 'u': - username = ko.arg; + username = optarg; break; case 'p': - port = ko.arg; + port = optarg; break; default: break; } } - argc -= ko.ind; - argv += ko.ind; + argc -= optind; + argv += optind; if (argc < 2) irc_util_die("abort: missing id and/or host\n"); @@ -691,6 +703,9 @@ static void cmd_server_disconnect(int argc, char **argv) { + --argc; + ++argv; + if (argc == 1) req("SERVER-DISCONNECT %s", argv[0]); else @@ -710,7 +725,8 @@ static void cmd_server_info(int argc, char **argv) { - (void)argc; + --argc; + ++argv; char *list; const char *args[16] = {0}; @@ -743,6 +759,9 @@ static void cmd_server_join(int argc, char **argv) { + --argc; + ++argv; + if (argc >= 3) req("SERVER-JOIN %s %s %s", argv[0], argv[1], argv[2]); else @@ -763,7 +782,8 @@ static void cmd_server_message(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("SERVER-MESSAGE %s %s %s", argv[0], argv[1], argv[2]); ok(); @@ -772,7 +792,8 @@ static void cmd_server_me(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("SERVER-ME %s %s %s", argv[0], argv[1], argv[2]); ok(); @@ -781,6 +802,9 @@ static void cmd_server_mode(int argc, char **argv) { + --argc; + ++argv; + req("SERVER-MODE %s %s %s%c%s", argv[0], argv[1], argv[2], argc >= 4 ? ' ' : '\0', argc >= 4 ? argv[3] : ""); @@ -790,7 +814,8 @@ static void cmd_server_nick(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("SERVER-NICK %s %s", argv[0], argv[1]); ok(); @@ -799,7 +824,8 @@ static void cmd_server_notice(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("SERVER-NOTICE %s %s %s", argv[0], argv[1], argv[2]); ok(); @@ -808,7 +834,8 @@ static void cmd_server_part(int argc, char **argv) { - (void)argc; + --argc; + ++argv; /* Let's advertise irccd a bit. */ req("SERVER-PART %s %s %s", argv[0], argv[1], @@ -819,6 +846,9 @@ static void cmd_server_reconnect(int argc, char **argv) { + --argc; + ++argv; + if (argc == 1) req("SERVER-RECONNECT %s", argv[0]); else @@ -830,7 +860,8 @@ static void cmd_server_topic(int argc, char **argv) { - (void)argc; + --argc; + ++argv; req("SERVER-TOPIC %s %s %s", argv[0], argv[1], argv[2]); ok(); @@ -915,11 +946,7 @@ if (!(c = find_cmd(argv[0]))) irc_util_die("abort: command not found\n"); - - --argc; - ++argv; - - if ((c->minargs != -1 && argc < c->minargs) || (c->minargs != -1 && argc > c->maxargs)) + if ((c->minargs != -1 && argc - 1 < c->minargs) || (c->minargs != -1 && argc - 1 > c->maxargs)) irc_util_die("abort: invalid number of arguments\n"); c->exec(argc, argv); @@ -973,15 +1000,14 @@ int main(int argc, char **argv) { - ketopt_t ko = KETOPT_INIT; + int ch; - --argc; - ++argv; + putenv("POSIXLY_CORRECT=1"); - for (int ch; (ch = ketopt(&ko, argc, argv, 0, "s:v", NULL)) != -1; ) { + while ((ch = getopt(argc, argv, "s:v")) != -1) { switch (ch) { case 's': - irc_util_strlcpy(sockaddr.sun_path, ko.arg, sizeof (sockaddr.sun_path)); + irc_util_strlcpy(sockaddr.sun_path, optarg, sizeof (sockaddr.sun_path)); break; case 'v': verbose = 1; @@ -992,8 +1018,11 @@ } } - argc -= ko.ind; - argv += ko.ind; + argc -= optind; + argv += optind; + + /* Reset options for subcommands. */ + optind = 1; if (argc < 1) usage();