-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWinAGC.c
169 lines (151 loc) · 6.12 KB
/
WinAGC.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
Copyright 2005,2009 Ronald S. Burkey <[email protected]>
This file is part of yaAGC.
yaAGC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
yaAGC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with yaAGC; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
In addition, as a special exception, Ronald S. Burkey gives permission to
link the code of this program with the Orbiter SDK library (or with
modified versions of the Orbiter SDK library that use the same license as
the Orbiter SDK library), and distribute linked combinations including
the two. You must obey the GNU General Public License in all respects for
all of the code used other than the Orbiter SDK library. If you modify
this file, you may extend this exception to your version of the file,
but you are not obligated to do so. If you do not wish to do so, delete
this exception statement from your version.
Filename: WinAGC.c
Purpose: This is a process manager for Virtual AGC in Win32.
It allows an orderly shutdown of all Virtual AGC processes
after you exit from any one process. (In other words
exiting yaDSKY can shutdown yaAGC as well, and vice versa.)
I was able to accomplish this perfectly well in Linux just
with shell scripts, but Win32 is so crippled that I had
to write an exe file to do it. (Windows XP Pro contains
programs TASKLIST and TASKKILL that allow appropriate scripts
to be written, but Windows XP Home, and probably every other
earlier version of Windows does not.)
Compiler: GNU gcc.
Contact: Ron Burkey <[email protected]>
Reference: http://www.ibiblio.org/apollo/index.html
Mods: 07/12/05 RSB Created. Note: Right now, there's a
problem with this program in that if
you run yaAGC under it, it essentially
uses up all available CPU time. (Whereas
if you run yaAGC from a command line
or a batch file, it takes an immeasurably
small amount of CPU time.)
03/08/09 RSB Tried a workaround for the 100% CPU time
mentioned above. Increased the max command-line
length from 128 to 256.
04/25/09 RSB Allow the startup delay to be changed from
the command line, and changed the default to
0 (was hard-coded at 30 seconds)
08/02/09 RSB The arbitrary limit I placed on command-line
length was too arbitrary, and is easily
exceeded when command-line debugging is performed.
Increased it from 256 to 2048, which should be
tremendous overkill.
This program expects to receive a list of command-lines for processes,
separated by \n and/or \r, on the standard input. It ignores white lines
and lines that begin with '#'.
For example, if the file test.txt contained
yaAGC --core=Luminary131.bin --cfg=LM.ini
start yaDSKY --cfg=LM.ini --test-downlink
then
WinAGC <test.txt
would execute the two commands shown, as separate processes, closing them
both down when either one of them terminated.
*/
#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_PROCESSES 20
#define MAX_LENGTH 2048
static char CommandLines[MAX_PROCESSES][MAX_LENGTH + 1];
STARTUPINFO si[MAX_PROCESSES];
PROCESS_INFORMATION pi[MAX_PROCESSES];
static int NumProcesses;
static int StartupDelay = 0;
static char s[MAX_LENGTH + 1];
int
main (int argc, char *argv[])
{
int i, j;
char *ss;
// Read the command-line options.
for (i = 1; i < argc; i++)
if (1 == sscanf (argv[i], "--startup-delay=%d", &j))
StartupDelay = j;
// Read the input file.
for (NumProcesses = 0;
NumProcesses < MAX_PROCESSES && NULL != fgets (s, MAX_LENGTH, stdin); )
{
for (ss = s; isspace (*ss); ss++);
if (*ss == '#' || *ss == '\n' || *ss == '\r' || *ss == 0)
continue;
strcpy (CommandLines[NumProcesses], ss);
for (ss = CommandLines[NumProcesses]; *ss; ss++)
if (*ss == '\r' || *ss == '\n')
*ss = 0;
NumProcesses++;
}
// Create all processes.
printf ("\n");
for (i = 0; i < NumProcesses; i++)
{
printf ("Creating process %d: \"%s\"\n", i, CommandLines[i]);
if (!CreateProcess(NULL, // No module name (use command line).
CommandLines[i], // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si[i], // Pointer to STARTUPINFO structure.
&pi[i] )) // Pointer to PROCESS_INFORMATION structure.
{
printf ("CreateProcess failed.\n");
NumProcesses = i;
goto Done;
}
Sleep (500);
}
// Wait for any one of them to exit.
if (StartupDelay > 0)
Sleep (StartupDelay);
printf ("Scanning for process exits.\n");
while (1)
{
for (i = 0; i < NumProcesses; i++)
{
// Wait 10 ms. for process to end.
if (WAIT_TIMEOUT != WaitForSingleObject (pi[i].hProcess, 100))
{
printf ("Process #%d exited.\n", i);
goto Done; // Not timeout, so must be exit or error!
}
}
Sleep (500);
}
// Now terminate all of them!
Done:
Sleep (5000);
for (i = 0; i < NumProcesses; i++)
{
printf ("Stopping process #%d\n", i);
TerminateProcess (pi[i].hProcess, 0);
CloseHandle (pi[i].hProcess);
CloseHandle (pi[i].hThread);
}
return (0);
}