2 This file is part of GNUnet
3 Copyright (C) 2010 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file src/util/gnunet-timeout-w32.c
23 * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period
28 #include <sys/types.h>
32 main (int argc, char *argv[])
41 PROCESS_INFORMATION proc;
43 wchar_t wpath[MAX_PATH + 1];
46 DWORD pathbuf_len, alloc_len;
48 wchar_t *non_const_filename;
59 ("arg 1: timeout in sec., arg 2: executable, arg<n> arguments\n");
63 timeout = atoi (argv[1]);
68 commandline = GetCommandLineW ();
69 if (commandline == NULL)
71 printf ("Failed to get commandline: %lu\n", GetLastError ());
75 wargv = CommandLineToArgvW (commandline, &wargc);
76 if (wargv == NULL || wargc <= 1)
78 printf ("Failed to get parse commandline: %lu\n", GetLastError ());
82 job = CreateJobObject (NULL, NULL);
85 printf ("Failed to create a job: %lu\n", GetLastError ());
89 pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0);
91 alloc_len = pathbuf_len + 1;
93 pathbuf = malloc (alloc_len * sizeof (wchar_t));
97 alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len);
99 cmdlen = wcslen (wargv[2]);
100 if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0)
102 non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5));
103 swprintf (non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]);
107 non_const_filename = wcsdup (wargv[2]);
110 /* Check that this is the full path. If it isn't, search. */
111 if (non_const_filename[1] == L':')
112 swprintf (wpath, sizeof (wpath) / sizeof (wchar_t), L"%S", non_const_filename);
113 else if (!SearchPathW
114 (pathbuf, non_const_filename, NULL, sizeof (wpath) / sizeof (wchar_t),
117 printf ("Failed to get find executable: %lu\n", GetLastError ());
121 free (non_const_filename);
123 cmdlen = wcslen (wpath) + 4;
125 while (NULL != (arg = wargv[i++]))
126 cmdlen += wcslen (arg) + 4;
128 wcmd = malloc (sizeof (wchar_t) * (cmdlen + 1));
131 while (NULL != (arg = wargv[i++]))
133 /* This is to escape trailing slash */
134 wchar_t arg_lastchar = arg[wcslen (arg) - 1];
137 wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath,
138 arg_lastchar == L'\\' ? L"\\" : L"");
142 if (wcschr (arg, L' ') != NULL)
143 wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg,
144 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
146 wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg,
147 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
153 memset (&start, 0, sizeof (start));
154 start.cb = sizeof (start);
156 if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
157 NULL, NULL, &start, &proc))
159 wprintf (L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError ());
163 AssignProcessToJobObject (job, proc.hProcess);
165 ResumeThread (proc.hThread);
166 CloseHandle (proc.hThread);
170 wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000);
171 if (wait_result == WAIT_OBJECT_0)
174 wait_result = GetExitCodeProcess (proc.hProcess, &status);
175 CloseHandle (proc.hProcess);
176 if (wait_result != 0)
178 printf ("Test process exited with result %lu\n", status);
179 TerminateJobObject (job, status);
182 printf ("Test process exited (failed to obtain exit status)\n");
183 TerminateJobObject (job, 0);
186 printf ("Child processes were killed after timeout of %u seconds\n",
188 TerminateJobObject (job, 1);
189 CloseHandle (proc.hProcess);
193 /* end of timeout_watchdog_w32.c */