Skip to content

Commit 6787306

Browse files
committed
Support sending multiple actions to a running instance
Currently we support only one --command action arg type of option. Extend it to allow multiple such commands in one invocation. Trac OpenVPN#498 Signed-off-by: Selva Nair <[email protected]>
1 parent 79f5cb9 commit 6787306

File tree

3 files changed

+91
-56
lines changed

3 files changed

+91
-56
lines changed

main.c

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ VerifyAutoConnections()
100100
* to the running instance and return success or error.
101101
*/
102102
static int
103-
NotifyRunningInstance()
103+
NotifyRunningInstance(int action_type, wchar_t *action_arg)
104104
{
105105
/* Check if a previous instance has a window initialized
106106
* Even if we are not the first instance this may return null
@@ -110,22 +110,16 @@ NotifyRunningInstance()
110110
int exit_code = 0;
111111
if (hwnd_master)
112112
{
113-
/* GUI up and running -- send a message if any action is pecified,
114-
else show the balloon */
113+
/* GUI up and running -- send a message for the specified action */
115114
COPYDATASTRUCT config_data = {0};
116115
int timeout = 30*1000; /* 30 seconds */
117-
if (!o.action)
116+
config_data.dwData = action_type;
117+
if (action_arg)
118118
{
119-
o.action = WM_OVPN_NOTIFY;
120-
o.action_arg = LoadLocalizedString(IDS_NFO_CLICK_HERE_TO_START);
119+
config_data.cbData = (wcslen(action_arg)+1)*sizeof(action_arg[0]);
120+
config_data.lpData = (void *) action_arg;
121121
}
122-
config_data.dwData = o.action;
123-
if (o.action_arg)
124-
{
125-
config_data.cbData = (wcslen(o.action_arg)+1)*sizeof(o.action_arg[0]);
126-
config_data.lpData = (void *) o.action_arg;
127-
}
128-
PrintDebug(L"Instance 2: called with action %d : %ls", o.action, o.action_arg);
122+
PrintDebug(L"Instance 2: called with action %d : %ls", action_type, action_arg);
129123
if (!SendMessageTimeout (hwnd_master, WM_COPYDATA, 0,
130124
(LPARAM) &config_data, 0, timeout, NULL))
131125
{
@@ -245,23 +239,40 @@ int WINAPI _tWinMain (HINSTANCE hThisInstance,
245239

246240
if (!first_instance)
247241
{
248-
int res = NotifyRunningInstance();
249-
exit(res);
250-
}
251-
else if (o.action == WM_OVPN_START)
252-
{
253-
PrintDebug(L"Instance 1: Called with --command connect xxx. Treating it as --connect xxx");
254-
}
255-
else if (o.action == WM_OVPN_IMPORT)
256-
{
257-
; /* pass -- import is handled after Window initialization */
242+
int exit_code = 0;
243+
struct action *a = o.action_list.head;
244+
if (!a) /* no actions -- send a balloon notification */
245+
{
246+
exit_code = NotifyRunningInstance(WM_OVPN_NOTIFY,
247+
LoadLocalizedString(IDS_NFO_CLICK_HERE_TO_START));
248+
}
249+
else while (a)
250+
{
251+
int res = NotifyRunningInstance(a->type, a->arg);
252+
exit_code = res > exit_code ? res : exit_code;
253+
a = a->next;
254+
}
255+
exit(exit_code);
258256
}
259-
else if (o.action)
257+
else
260258
{
261-
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Called with --command when no previous instance available");
262-
exit(OVPN_EXITCODE_ERROR);
259+
for (struct action *a = o.action_list.head; a; a = a->next)
260+
{
261+
if (a->type == WM_OVPN_START)
262+
{
263+
PrintDebug(L"Instance 1: Called with --command connect xxx. Treating it as --connect xxx");
264+
}
265+
else if (a->type == WM_OVPN_IMPORT)
266+
{
267+
; /* pass -- import is handled after Window initialization */
268+
}
269+
else
270+
{
271+
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Called with --command when no previous instance available (action type = %d arg = %s", a->type, a->arg ? a->arg : L"");
272+
exit(OVPN_EXITCODE_ERROR);
273+
}
274+
}
263275
}
264-
265276
if (!CheckVersion()) {
266277
exit(1);
267278
}
@@ -528,9 +539,12 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
528539
CheckServiceStatus(); // Check if service is running or not
529540

530541
/* if '--import' was specified, do it now */
531-
if (o.action == WM_OVPN_IMPORT && o.action_arg)
542+
for (struct action *a = o.action_list.head; a ; a = a->next)
532543
{
533-
ImportConfigFile(o.action_arg, true); /* prompt user */
544+
if (a->type == WM_OVPN_IMPORT && a->arg)
545+
{
546+
ImportConfigFile(a->arg, true); /* prompt user */
547+
}
534548
}
535549

536550
if (!AutoStartConnections()) {

options.c

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <shlobj.h>
3737
#include <shlwapi.h>
3838
#include <combaseapi.h>
39+
#include <assert.h>
3940

4041
#include "options.h"
4142
#include "main.h"
@@ -81,9 +82,32 @@ ExpandOptions (void)
8182
ExpandString (o.install_path, _countof(o.install_path));
8283
}
8384

85+
static void
86+
add_action(struct action_list *al, DWORD type, wchar_t *arg)
87+
{
88+
struct action *a = calloc(sizeof(*a), 1);
89+
if (!a)
90+
{
91+
ErrorExit(1, L"Out of memory while parsing command line");
92+
}
93+
a->type = type;
94+
a->arg = arg;
95+
if (!al->head) /* first entry */
96+
{
97+
al->head = a;
98+
}
99+
else
100+
{
101+
assert(al->tail);
102+
al->tail->next = a;
103+
}
104+
al->tail = a;
105+
}
106+
84107
static int
85108
add_option(options_t *options, int i, TCHAR **p)
86109
{
110+
struct action_list *al = &options->action_list;
87111
if (streq(p[0], _T("help")))
88112
{
89113
TCHAR caption[200];
@@ -112,23 +136,18 @@ add_option(options_t *options, int i, TCHAR **p)
112136
options->auto_connect = tmp;
113137
}
114138
options->auto_connect[options->num_auto_connect++] = p[1];
115-
/* Treat the first connect option to also mean --command connect profile.
139+
/* Treat connect option to also mean --command connect profile.
116140
* This gets used if we are not the first instance.
117141
*/
118-
if (options->num_auto_connect == 1)
119-
{
120-
options->action = WM_OVPN_START;
121-
options->action_arg = p[1];
122-
}
142+
add_action(al, WM_OVPN_START, p[1]);
123143
}
124144
else if (streq(p[0], L"import") && p[1])
125145
{
126146
++i;
127147
/* This is interpreted directly or as a command depending
128148
* on we are the first instance or not. So, set as an action.
129149
*/
130-
options->action = WM_OVPN_IMPORT;
131-
options->action_arg = p[1];
150+
add_action(al, WM_OVPN_IMPORT, p[1]);
132151
}
133152
else if (streq(p[0], _T("exe_path")) && p[1])
134153
{
@@ -248,52 +267,44 @@ add_option(options_t *options, int i, TCHAR **p)
248267
if (streq(p[1], _T("connect")) && p[2])
249268
{
250269
/* Treat this as "--connect profile" in case this is the first instance */
251-
add_option(options, i, &p[1]);
252-
++i;
253-
options->action = WM_OVPN_START;
254-
options->action_arg = p[2];
270+
i = add_option(options, i, &p[1]);
255271
}
256272
else if (streq(p[1], _T("disconnect")) && p[2])
257273
{
258274
++i;
259-
options->action = WM_OVPN_STOP;
260-
options->action_arg = p[2];
275+
add_action(al, WM_OVPN_STOP, p[2]);
261276
}
262277
else if (streq(p[1], _T("reconnect")) && p[2])
263278
{
264279
++i;
265-
options->action = WM_OVPN_RESTART;
266-
options->action_arg = p[2];
280+
add_action(al, WM_OVPN_RESTART, p[2]);
267281
}
268282
else if (streq(p[1], _T("status")) && p[2])
269283
{
270284
++i;
271-
options->action = WM_OVPN_SHOWSTATUS;
272-
options->action_arg = p[2];
285+
add_action(al, WM_OVPN_SHOWSTATUS, p[2]);
273286
}
274287
else if (streq(p[1], L"import") && p[2])
275288
{
276289
++i;
277-
options->action = WM_OVPN_IMPORT;
278-
options->action_arg = p[2];
290+
add_action(al, WM_OVPN_IMPORT, p[2]);
279291
}
280292
else if (streq(p[1], _T("silent_connection")))
281293
{
282294
++i;
283-
options->action = WM_OVPN_SILENT;
284-
options->action_arg = p[2] ? p[2] : _T("1");
295+
add_action(al, WM_OVPN_SILENT, p[2] ? p[2] : L"1");
285296
}
286297
else if (streq(p[1], _T("disconnect_all")))
287298
{
288-
options->action = WM_OVPN_STOPALL;
299+
add_action(al, WM_OVPN_STOPALL, NULL);
289300
}
290301
else if (streq(p[1], _T("exit")))
291302
{
292-
options->action = WM_OVPN_EXIT;
303+
add_action(al, WM_OVPN_EXIT, NULL);
293304
}
294305
else if (streq(p[1], _T("rescan")))
295306
{
296-
options->action = WM_OVPN_RESCAN;
307+
add_action(al, WM_OVPN_RESCAN, NULL);
297308
}
298309
else
299310
{

options.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ struct connection {
158158
struct echo_msg echo_msg; /* Message echo-ed from server or client config and related data */
159159
};
160160

161+
/* Command actions to be send to running instance */
162+
struct action {
163+
int type;
164+
wchar_t *arg;
165+
struct action *next;
166+
};
167+
168+
struct action_list {
169+
struct action *head, *tail;
170+
};
171+
161172
/* All options used within OpenVPN GUI */
162173
typedef struct {
163174
/* Array of configs to autostart */
@@ -223,8 +234,7 @@ typedef struct {
223234
unsigned int dpi_scale;
224235
COLORREF clr_warning;
225236
COLORREF clr_error;
226-
int action; /* action to send to a running instance */
227-
TCHAR *action_arg;
237+
struct action_list action_list; /* list of actions to send to a running instance */
228238
HANDLE session_semaphore;
229239
HANDLE event_log;
230240
} options_t;

0 commit comments

Comments
 (0)