From f55eeb1da8ad4582500acb3a0c04ae70a52fa770 Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Thu, 19 Apr 2018 22:19:10 -0400 Subject: [PATCH] Eliminate MAX_CONFIGS limit using a dynamic array The number of configs is now unlimited. But there is a limit of 2^16 menu items which permits only about 2^12 configs to be displayed in the menu. A warning is shown if the number of configs exceeds this value. For a responsive menu keep the number of configs under ~1000. Signed-off-by: Selva Nair --- configure.ac | 6 ------ main.c | 2 +- openvpn_config.c | 23 +++++++++++++++++++---- options.c | 18 +++++++++++------- options.h | 10 +++++++--- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 9a2ba75..d893802 100644 --- a/configure.ac +++ b/configure.ac @@ -49,12 +49,6 @@ AC_ARG_ENABLE( [enable_password_change="yes"] ) -AC_ARG_VAR([MAX_CONFIGS], [specify the maximum number of configs @<:@default=50@:>@]) -if test -z "$MAX_CONFIGS"; then - MAX_CONFIGS=50 -fi -AC_DEFINE_UNQUOTED([MAX_CONFIGS], [$MAX_CONFIGS], [Maximum number of config files supported.]) - case "$host" in *-mingw*) CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN" diff --git a/main.c b/main.c index f8ec7e3..ff91b4f 100644 --- a/main.c +++ b/main.c @@ -80,7 +80,7 @@ VerifyAutoConnections() { int i; - for (i = 0; i < MAX_CONFIGS && o.auto_connect[i] != 0; i++) + for (i = 0; i < o.num_auto_connect; i++) { if (GetConnByName(o.auto_connect[i]) == NULL) { diff --git a/openvpn_config.c b/openvpn_config.c index e5b7d00..e1a4728 100644 --- a/openvpn_config.c +++ b/openvpn_config.c @@ -112,7 +112,7 @@ AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir) #endif /* Check if connection should be autostarted */ - for (i = 0; i < MAX_CONFIGS && o.auto_connect[i]; ++i) + for (i = 0; i < o.num_auto_connect; ++i) { if (_tcsicmp(c->config_file, o.auto_connect[i]) == 0 || _tcsicmp(c->config_name, o.auto_connect[i]) == 0) @@ -265,10 +265,17 @@ BuildFileList0(const TCHAR *config_dir, int recurse_depth, config_group_t *group /* Loop over each config file in config dir */ do { - if (o.num_configs >= MAX_CONFIGS) + if (!o.conn || o.num_configs == o.max_configs) { - ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, MAX_CONFIGS); - break; + o.max_configs += 50; + void *tmp = realloc(o.conn, sizeof(*o.conn)*o.max_configs); + if (!tmp) + { + o.max_configs -= 50; + FindClose(find_handle); + ErrorExit(1, L"Out of memory while scanning configs"); + } + o.conn = tmp; } match_t match_type = match(&find_obj, o.ext_string); @@ -360,6 +367,14 @@ BuildFileList() if (o.num_configs == 0 && issue_warnings) ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir); + /* More than MAX_CONFIGS are ignored in the menu listing */ + if (o.num_configs > MAX_CONFIGS) + { + if (issue_warnings) + ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, o.num_configs); + o.num_configs = MAX_CONFIGS; /* menus don't work with more -- ignore the rest */ + } + ActivateConfigGroups(); issue_warnings = false; diff --git a/options.c b/options.c index 3dc5496..f9e4caf 100644 --- a/options.c +++ b/options.c @@ -97,18 +97,22 @@ add_option(options_t *options, int i, TCHAR **p) else if (streq(p[0], _T("connect")) && p[1]) { ++i; - static int auto_connect_nr = 0; - if (auto_connect_nr == MAX_CONFIGS) + if (!options->auto_connect || options->num_auto_connect == options->max_auto_connect) { - /* Too many configs */ - ShowLocalizedMsg(IDS_ERR_MANY_CONFIGS, MAX_CONFIGS); - exit(1); + options->max_auto_connect += 10; + void *tmp = realloc(options->auto_connect, sizeof(wchar_t *)*options->max_auto_connect); + if (!tmp) + { + options->max_auto_connect -= 10; + ErrorExit(1, L"Out of memory while parsing command line"); + } + options->auto_connect = tmp; } - options->auto_connect[auto_connect_nr++] = p[1]; + options->auto_connect[options->num_auto_connect++] = p[1]; /* Treat the first connect option to also mean --command connect profile. * This gets used if we are not the first instance. */ - if (auto_connect_nr == 1) + if (options->num_auto_connect == 1) { options->action = WM_OVPN_START; options->action_arg = p[1]; diff --git a/options.h b/options.h index 43b78a2..3970334 100644 --- a/options.h +++ b/options.h @@ -41,7 +41,8 @@ typedef struct connection connection_t; * including the option name itself. */ #define MAX_PARMS 5 /* Max number of parameters per option */ - +/* Menu ids are constructed as 12 bits for config number, 4 bits for action */ +#define MAX_CONFIGS (1<<12) typedef enum { service_noaccess = -1, @@ -155,13 +156,16 @@ struct connection { /* All options used within OpenVPN GUI */ typedef struct { /* Array of configs to autostart */ - const TCHAR *auto_connect[MAX_CONFIGS]; + const TCHAR **auto_connect; /* Connection parameters */ - connection_t conn[MAX_CONFIGS]; /* Connection structure */ + connection_t *conn; /* Array of connection structure */ config_group_t *groups; /* Array of nodes defining the config groups tree */ int num_configs; /* Number of configs */ + int num_auto_connect; /* Number of auto-connect configs */ int num_groups; /* Number of config groups */ + int max_configs; /* Current capacity of conn array */ + int max_auto_connect; /* Current capacity of auto_connect array */ int max_groups; /* Current capacity of groups array */ service_state_t service_state; /* State of the OpenVPN Service */