summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/io/parameters.c')
-rw-r--r--src/io/parameters.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/io/parameters.c b/src/io/parameters.c
new file mode 100644
index 0000000..0f7d05c
--- /dev/null
+++ b/src/io/parameters.c
@@ -0,0 +1,354 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "../pervasive.h"
+
+#include "error.h"
+
+#include "parameters.h"
+
+static void load_default_parameters
+(
+ struct ZoO_parameters param [const restrict static 1]
+)
+{
+ param->data_filename = ZoO_DEFAULT_DATA_FILENAME;
+
+ param->irc_server_addr = ZoO_DEFAULT_IRC_SERVER_ADDR;
+ param->irc_server_port = ZoO_DEFAULT_IRC_SERVER_PORT;
+ param->irc_server_channel = ZoO_DEFAULT_IRC_SERVER_CHANNEL;
+ param->irc_username = ZoO_DEFAULT_IRC_USERNAME;
+ param->irc_realname = ZoO_DEFAULT_IRC_REALNAME;
+
+ param->reply_rate = ZoO_DEFAULT_REPLY_RATE;
+
+ param->aliases_count = 0;
+ param->aliases = NULL;
+}
+
+static void print_help (const char exec [const restrict static 1])
+{
+ printf
+ (
+ "Usage: %s [option_1 option_2 ...] NICKNAME [ALIAS_1 ALIAS_2 ...] \n"
+ "NICKNAME is used as the IRC nickname value.\n"
+ "If NICKNAME or any ALIAS is found in an event, the program will reply.\n"
+ "\nAvailable options:\n"
+ " [--data-filename | -df] FILENAME\n"
+ " Learn content from FILENAME before connecting.\n"
+ " Default: %s.\n"
+ " [--irc-server-addr | -isa] IRC_SERVER_ADDR\n"
+ " Connect to this server address.\n"
+ " Default: %s.\n"
+ " [--irc-server-port | -isp] IRC_SERVER_PORT\n"
+ " Connect to this server port.\n"
+ " Default: %s.\n"
+ " [--irc-server-channel | -isc] IRC_SERVER_CHANNEL\n"
+ " Connect to this server's channel.\n"
+ " Default: %s.\n"
+ " [--irc-username | -iu] USERNAME\n"
+ " Connect using this as 'username' (shown in WHOIS).\n"
+ " Default: %s.\n"
+ " [--irc-realname | -ir] REALNAME\n"
+ " Connect using this as 'realname' (shown in WHOIS).\n"
+ " Default: %s.\n"
+ " [--reply-rate | -rr] REPLY_RATE\n"
+ " Chance to reply to an event (integer, range [0, 100]).\n"
+ " Default: %d.\n",
+ exec,
+ ZoO_DEFAULT_DATA_FILENAME,
+ ZoO_DEFAULT_IRC_SERVER_ADDR,
+ ZoO_DEFAULT_IRC_SERVER_PORT,
+ ZoO_DEFAULT_IRC_SERVER_CHANNEL,
+ ZoO_DEFAULT_IRC_USERNAME,
+ ZoO_DEFAULT_IRC_REALNAME,
+ ZoO_DEFAULT_REPLY_RATE
+ );
+}
+
+static int parse_string_arg
+(
+ const char * restrict dest [const restrict static 1],
+ int const i,
+ const char * restrict argv [const restrict static 1],
+ int const argc
+)
+{
+ if (i == argc)
+ {
+ ZoO_FATAL
+ (
+ "Missing value for parameter '%s'.",
+ /* Safe: i > 1 */
+ argv[i - 1]
+ );
+
+ return -1;
+ }
+
+ *dest = argv[i];
+
+ return 0;
+}
+
+static int parse_integer_arg
+(
+ int dest [const restrict static 1],
+ int const i,
+ const char * argv [const restrict static 1],
+ int const argc,
+ int const min_val,
+ int const max_val
+)
+{
+ long int result;
+ char * endptr;
+ const int old_errno = errno;
+
+ if (i == argc)
+ {
+ ZoO_FATAL
+ (
+ "Missing value for parameter '%s'.",
+ /* Safe: i > 1 */
+ argv[i - 1]
+ );
+
+ return -1;
+ }
+
+ errno = 0;
+
+ result = strtol(argv[i], &endptr, 10);
+
+ if
+ (
+ (errno != 0)
+ || ((*endptr) == '\n')
+ || (result < min_val)
+ || (result > max_val)
+ )
+ {
+ ZoO_FATAL
+ (
+ "Invalid or missing value for parameter '%s', accepted range is "
+ "[%d, %d] (integer).",
+ /* Safe: i > 1 */
+ argv[i - 1],
+ min_val,
+ max_val
+ );
+
+ errno = old_errno;
+
+ return -1;
+ }
+
+ *dest = (int) result;
+
+ errno = old_errno;
+
+ return 0;
+}
+
+int ZoO_parameters_initialize
+(
+ struct ZoO_parameters param [const restrict static 1],
+ int const argc,
+ const char * argv [const restrict static argc]
+)
+{
+ int i;
+
+ load_default_parameters(param);
+
+ for (i = 1; i < argc; ++i)
+ {
+ if
+ (
+ (strcmp(argv[i], "--data-filename") == 0)
+ || (strcmp(argv[i], "-df") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->data_filename),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--irc-server-addr") == 0)
+ || (strcmp(argv[i], "-isa") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->irc_server_addr),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--irc-server-port") == 0)
+ || (strcmp(argv[i], "-isp") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->irc_server_port),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--irc-server-channel") == 0)
+ || (strcmp(argv[i], "-isc") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->irc_server_channel),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--irc-username") == 0)
+ || (strcmp(argv[i], "-iu") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->irc_username),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--irc-realname") == 0)
+ || (strcmp(argv[i], "-in") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_string_arg
+ (
+ &(param->irc_realname),
+ i,
+ argv,
+ argc
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--reply-rate") == 0)
+ || (strcmp(argv[i], "-rr") == 0)
+ )
+ {
+ i += 1;
+
+ if
+ (
+ parse_integer_arg
+ (
+ &(param->reply_rate),
+ i,
+ argv,
+ argc,
+ 0,
+ 100
+ ) < 0
+ )
+ {
+ return -1;
+ }
+ }
+ else if
+ (
+ (strcmp(argv[i], "--help") == 0)
+ || (strcmp(argv[i], "-h") == 0)
+ )
+ {
+ print_help(argv[0]);
+
+ return 0;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (i == argc)
+ {
+ ZoO_S_FATAL("Missing argument: NICKNAME");
+
+ print_help(argv[0]);
+
+ return -1;
+ }
+
+ param->aliases_count = (argc - i);
+ param->aliases = (argv + i);
+
+ return 1;
+}