changeset 1148:323d6d34ec1b

irccdctl: remove ketopt, closes #2530
author David Demelier <markand@malikania.fr>
date Fri, 04 Feb 2022 09:56:43 +0100
parents cbc5dfb0b029
children 4c9d2d5d126f
files CMakeLists.txt extern/libketopt/CMakeLists.txt extern/libketopt/ketopt.h irccdctl/CMakeLists.txt irccdctl/irccdctl.c
diffstat 5 files changed, 77 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- 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)
--- 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 <markand@malikania.fr>
-#
-# 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 $<BUILD_INTERFACE:${libirccd-ketopt_SOURCE_DIR}>)
-set_target_properties(libirccd-ketopt PROPERTIES FOLDER extern)
--- 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 <string.h> /* 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
--- 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})
--- 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 <string.h>
 #include <unistd.h>
 
-#include <ketopt.h>
-
 #include <irccd/limits.h>
 #include <irccd/util.h>
 
@@ -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();