2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
33 #include "winbacula.h"
34 #include "winservice.h"
38 extern int BaculaMain(int argc, char *argv[]);
39 extern void terminate_dird(int sig);
41 extern BOOL ReportStatus(DWORD state, DWORD exitcode, DWORD waithint);
42 extern void d_msg(const char *, int, int, const char *, ...);
45 HINSTANCE hAppInstance;
46 const char *szAppName = "Bacula-dir";
48 bool opt_debug = false;
50 /* Imported variables */
51 extern DWORD g_servicethread;
53 #define MAX_COMMAND_ARGS 100
54 static char *command_args[MAX_COMMAND_ARGS] = {"bacula-dir", NULL};
55 static int num_command_args = 1;
56 static pid_t main_pid;
57 static pthread_t main_tid;
60 * WinMain parses the command line and either calls the main App
61 * routine or, under NT, the main service routine.
63 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
64 PSTR CmdLine, int iCmdShow)
66 char *szCmdLine = CmdLine;
67 char *wordPtr, *tempPtr;
70 /* Save the application instance and main thread id */
71 hAppInstance = hInstance;
72 mainthreadId = GetCurrentThreadId();
75 main_tid = pthread_self();
78 * Funny things happen with the command line if the
79 * execution comes from c:/Program Files/bacula/bacula.exe
80 * We get a command line like: Files/bacula/bacula.exe" options
81 * I.e. someone stops scanning command line on a space, not
82 * realizing that the filename is quoted!!!!!!!!!!
83 * So if first character is not a double quote and
84 * the last character before first space is a double
85 * quote, we throw away the junk.
89 while (*wordPtr && *wordPtr != ' ')
91 if (wordPtr > szCmdLine) /* backup to char before space */
93 /* if first character is not a quote and last is, junk it */
94 if (*szCmdLine != '"' && *wordPtr == '"') {
95 szCmdLine = wordPtr + 1;
98 /* Build Unix style argc *argv[] */
100 /* Don't NULL command_args[0] !!! */
101 for (i=1;i<MAX_COMMAND_ARGS;i++)
102 command_args[i] = NULL;
104 char *pszArgs = bstrdup(szCmdLine);
107 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
109 if (*wordPtr == '\"') {
112 } else if (*wordPtr == '/') {
113 /* Skip Windows options */
114 while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
116 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
120 while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
123 while (*tempPtr && *tempPtr != '\"')
127 while (*tempPtr && *tempPtr != ' ')
132 command_args[num_command_args++] = wordPtr;
134 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
136 if (*wordPtr == '\"') {
144 * Now process Windows command line options
146 for (i = 0; i < (int)strlen(szCmdLine); i++) {
147 if (szCmdLine[i] <= ' ') {
151 if (szCmdLine[i] != '/') {
155 /* Now check for command-line arguments */
157 /* /debug install quietly -- no prompts */
158 if (strnicmp(&szCmdLine[i], BaculaOptDebug, sizeof(BaculaOptDebug) - 1) == 0) {
160 i += sizeof(BaculaOptDebug) - 1;
164 /* /service start service */
165 if (strnicmp(&szCmdLine[i], BaculaRunService, sizeof(BaculaRunService) - 1) == 0) {
166 /* Run Bacula as a service */
167 return bacService::BaculaServiceMain();
169 /* /run (this is the default if no command line arguments) */
170 if (strnicmp(&szCmdLine[i], BaculaRunAsUserApp, sizeof(BaculaRunAsUserApp) - 1) == 0) {
171 /* Bacula is being run as a user-level program */
172 return BaculaAppMain();
175 if (strnicmp(&szCmdLine[i], BaculaInstallService, sizeof(BaculaInstallService) - 1) == 0) {
176 /* Install Bacula as a service */
177 return bacService::InstallService(&szCmdLine[i + sizeof(BaculaInstallService) - 1]);
180 if (strnicmp(&szCmdLine[i], BaculaRemoveService, sizeof(BaculaRemoveService) - 1) == 0) {
181 /* Remove the Bacula service */
182 return bacService::RemoveService();
186 if (strnicmp(&szCmdLine[i], BaculaKillRunningCopy, sizeof(BaculaKillRunningCopy) - 1) == 0) {
187 /* Kill running copy of Bacula */
188 return bacService::KillRunningCopy() ? 0 : 1;
192 if (strnicmp(&szCmdLine[i], BaculaShowHelp, sizeof(BaculaShowHelp) - 1) == 0) {
193 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK|MB_ICONINFORMATION);
197 MessageBox(NULL, szCmdLine, _("Bad Command Line Options"), MB_OK);
199 /* Show the usage dialog */
200 MessageBox(NULL, BaculaUsageText, _("Bacula Usage"), MB_OK | MB_ICONINFORMATION);
204 return BaculaAppMain();
209 * Called as a thread from BaculaAppMain()
210 * Here we handle the Windows messages
212 //DWORD WINAPI Main_Msg_Loop(LPVOID lpwThreadParam)
213 void *Main_Msg_Loop(LPVOID lpwThreadParam)
215 DWORD old_servicethread = g_servicethread;
217 pthread_detach(pthread_self());
219 /* Since we are the only thread with a message loop
220 * mark ourselves as the service thread so that
221 * we can receive all the window events.
223 g_servicethread = GetCurrentThreadId();
225 /* Now enter the Windows message handling loop until told to quit! */
227 while (GetMessage(&msg, NULL, 0,0) ) {
228 TranslateMessage(&msg);
229 DispatchMessage(&msg);
232 if (old_servicethread != 0) { /* started as NT service */
233 /* Mark that we're no longer running */
236 /* Tell the service manager that we've stopped. */
237 ReportStatus(SERVICE_STOPPED, g_error, 0);
239 /* Tell main program to go away */
242 /* Should not get here */
243 pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
245 kill(main_pid, SIGTERM); /* ask main thread to terminate */
251 * This is the main routine for Bacula when running as an application
252 * (under Windows 95 or Windows NT)
253 * Under NT, Bacula can also run as a service. The BaculaServerMain routine,
254 * defined in the bacService header, is used instead when running as a service.
258 /* DWORD dwThreadID; */
260 DWORD dwCharsWritten;
266 /* If no arguments were given then just run */
267 if (p_AttachConsole == NULL || !p_AttachConsole(ATTACH_PARENT_PROCESS)) {
272 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), "\r\n", 2, &dwCharsWritten, NULL);
274 /* Set this process to be the last application to be shut down. */
275 if (p_SetProcessShutdownParameters) {
276 p_SetProcessShutdownParameters(0x100, 0);
279 /* Create a thread to handle the Windows messages */
280 pthread_create(&tid, NULL, Main_Msg_Loop, (void *)0);
282 /* Call the "real" Bacula */
283 BaculaMain(num_command_args, command_args);