GNUnet  0.10.x
gnunet-timeout-w32.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010 GNUnet e.V.
4 
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.
9 
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.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
27 #include <windows.h>
28 #include <sys/types.h>
29 #include <stdio.h>
30 
31 int
32 main (int argc, char *argv[])
33 {
34  int i;
35  DWORD wait_result;
36  wchar_t *commandline;
37  wchar_t **wargv;
38  wchar_t *arg;
39  unsigned int cmdlen;
40  STARTUPINFOW start;
41  PROCESS_INFORMATION proc;
42 
43  wchar_t wpath[MAX_PATH + 1];
44 
45  wchar_t *pathbuf;
46  DWORD pathbuf_len, alloc_len;
47  wchar_t *ptr;
48  wchar_t *non_const_filename;
49  wchar_t *wcmd;
50  int wargc;
51  int timeout = 0;
52  ssize_t wrote;
53 
54  HANDLE job;
55 
56  if (argc < 3)
57  {
58  printf
59  ("arg 1: timeout in sec., arg 2: executable, arg<n> arguments\n");
60  exit (1);
61  }
62 
63  timeout = atoi (argv[1]);
64 
65  if (timeout == 0)
66  timeout = 600;
67 
68  commandline = GetCommandLineW ();
69  if (commandline == NULL)
70  {
71  printf ("Failed to get commandline: %lu\n", GetLastError ());
72  exit (2);
73  }
74 
75  wargv = CommandLineToArgvW (commandline, &wargc);
76  if (wargv == NULL || wargc <= 1)
77  {
78  printf ("Failed to get parse commandline: %lu\n", GetLastError ());
79  exit (3);
80  }
81 
82  job = CreateJobObject (NULL, NULL);
83  if (job == NULL)
84  {
85  printf ("Failed to create a job: %lu\n", GetLastError ());
86  exit (4);
87  }
88 
89  pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0);
90 
91  alloc_len = pathbuf_len + 1;
92 
93  pathbuf = malloc (alloc_len * sizeof (wchar_t));
94 
95  ptr = pathbuf;
96 
97  alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len);
98 
99  cmdlen = wcslen (wargv[2]);
100  if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0)
101  {
102  non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5));
103  swprintf (non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]);
104  }
105  else
106  {
107  non_const_filename = wcsdup (wargv[2]);
108  }
109 
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),
115  wpath, NULL))
116  {
117  printf ("Failed to get find executable: %lu\n", GetLastError ());
118  exit (5);
119  }
120  free (pathbuf);
121  free (non_const_filename);
122 
123  cmdlen = wcslen (wpath) + 4;
124  i = 3;
125  while (NULL != (arg = wargv[i++]))
126  cmdlen += wcslen (arg) + 4;
127 
128  wcmd = malloc (sizeof (wchar_t) * (cmdlen + 1));
129  wrote = 0;
130  i = 2;
131  while (NULL != (arg = wargv[i++]))
132  {
133  /* This is to escape trailing slash */
134  wchar_t arg_lastchar = arg[wcslen (arg) - 1];
135  if (wrote == 0)
136  {
137  wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath,
138  arg_lastchar == L'\\' ? L"\\" : L"");
139  }
140  else
141  {
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" ");
145  else
146  wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg,
147  arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
148  }
149  }
150 
151  LocalFree (wargv);
152 
153  memset (&start, 0, sizeof (start));
154  start.cb = sizeof (start);
155 
156  if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
157  NULL, NULL, &start, &proc))
158  {
159  wprintf (L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError ());
160  exit (6);
161  }
162 
163  AssignProcessToJobObject (job, proc.hProcess);
164 
165  ResumeThread (proc.hThread);
166  CloseHandle (proc.hThread);
167 
168  free (wcmd);
169 
170  wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000);
171  if (wait_result == WAIT_OBJECT_0)
172  {
173  DWORD status;
174  wait_result = GetExitCodeProcess (proc.hProcess, &status);
175  CloseHandle (proc.hProcess);
176  if (wait_result != 0)
177  {
178  printf ("Test process exited with result %lu\n", status);
179  TerminateJobObject (job, status);
180  exit (status);
181  }
182  printf ("Test process exited (failed to obtain exit status)\n");
183  TerminateJobObject (job, 0);
184  exit (0);
185  }
186  printf ("Child processes were killed after timeout of %u seconds\n",
187  timeout);
188  TerminateJobObject (job, 1);
189  CloseHandle (proc.hProcess);
190  exit (1);
191 }
192 
193 /* end of timeout_watchdog_w32.c */
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
uint16_t status
See PRISM_STATUS_*-constants.
static struct GNUNET_SCHEDULER_Task * job
Task for main job.
Definition: gnunet-cadet.c:137
int main(int argc, char *argv[])