00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <stdlib.h>
00013 #include <unistd.h>
00014 #include <stdio.h>
00015 #include <u/libu.h>
00016 #include <klone/klone.h>
00017 #include <klone/server.h>
00018 #include <klone/os.h>
00019 #include <klone/context.h>
00020 #include <klone/utils.h>
00021 #include <klone/version.h>
00022 #include "main.h"
00023
00024 int facility = LOG_LOCAL0;
00025
00026 static context_t c;
00027 context_t *ctx = &c;
00028
00029 #ifdef OS_WIN
00030
00031 enum { SS_NAME_BUFSZ = 64, SS_DESC_BUFSZ = 256 };
00032 static char ss_name[SS_NAME_BUFSZ] = "kloned";
00033 static char ss_desc[SS_DESC_BUFSZ] = "kloned daemon";
00034
00035 int InstallService();
00036 int RemoveService();
00037 #endif
00038
00039 static void usage()
00040 {
00041 static const char *us =
00042 "Usage: kloned OPTIONS ARGUMENTS \n"
00043 "Version: %s - Copyright (c) 2005, 2006 KoanLogic s.r.l. - All rights reserved. \n"
00044 "\n"
00045 " -d turn on debugging \n"
00046 " -f file load an external config file \n"
00047 " -F run in foreground \n"
00048 " -h display this help \n"
00049 #ifdef OS_WIN
00050 " -i install KLone Windows service \n"
00051 " -u remove KLone Windows service \n"
00052 #endif
00053 " -V print KLone version and exit \n"
00054 "\n";
00055
00056 fprintf(stderr, us, klone_version());
00057
00058 exit(1);
00059 }
00060
00061 static int parse_opt(int argc, char **argv)
00062 {
00063 int ret;
00064 #ifdef OS_WIN
00065 #define CMDLINE_FORMAT "hVFdiuf:"
00066 #else
00067 #define CMDLINE_FORMAT "hVFdf:"
00068 #endif
00069
00070
00071 ctx->daemon++;
00072
00073 while((ret = getopt(argc, argv, CMDLINE_FORMAT)) != -1)
00074 {
00075 switch(ret)
00076 {
00077 case 'f':
00078 ctx->ext_config = u_strdup(optarg);
00079 dbg_err_if(ctx->ext_config == NULL);
00080 dbg("ext config: %s", ctx->ext_config);
00081 break;
00082
00083 case 'd':
00084 ctx->debug++;
00085 break;
00086
00087 case 'F':
00088 ctx->daemon = 0;
00089 break;
00090
00091 case 'V':
00092 u_print_version_and_exit();
00093 break;
00094
00095 #ifdef OS_WIN
00096 case 'i':
00097 ctx->serv_op = SERV_INSTALL;
00098 break;
00099
00100 case 'u':
00101 ctx->serv_op = SERV_REMOVE;
00102 break;
00103
00104 #endif
00105
00106 default:
00107 case 'h':
00108 usage();
00109 }
00110 }
00111
00112 ctx->narg = argc - optind;
00113 ctx->arg = argv + optind;
00114
00115 return 0;
00116 err:
00117 return ~0;
00118 }
00119
00120 #if defined(OS_WIN)
00121
00122
00123
00124 int InstallService(void)
00125 {
00126 SC_HANDLE hSCM, hService;
00127 char szModulePathname[_MAX_PATH];
00128 SERVICE_DESCRIPTION sd = { ss_desc };
00129 int rc;
00130
00131
00132 hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
00133
00134 dbg_err_if(hSCM == NULL);
00135
00136 dbg_err_if(GetModuleFileName(GetModuleHandle(NULL), szModulePathname,
00137 _MAX_PATH) == 0 );
00138
00139
00140 hService = CreateService(hSCM, ss_name, ss_name,
00141 SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS,
00142 SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,
00143 szModulePathname, NULL, NULL, NULL, NULL, NULL);
00144
00145 dbg_err_if(hService == NULL);
00146
00147 rc = ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd);
00148
00149 dbg_err_if(rc == 0);
00150
00151
00152 MessageBox(NULL, "Service installation succeded", ss_name, MB_OK);
00153
00154 return 0;
00155 err:
00156
00157 warn_strerror(GetLastError());
00158 MessageBox(NULL, "Service installation error", ss_name, MB_OK);
00159 return ~0;
00160 }
00161
00162
00163 int RemoveService(void)
00164 {
00165 SC_HANDLE hSCM, hService;
00166 int rc;
00167
00168 hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
00169
00170 dbg_err_if(hSCM == NULL);
00171
00172
00173 hService = OpenService(hSCM, ss_name, DELETE);
00174
00175 dbg_err_if(hService == NULL);
00176
00177
00178 rc = DeleteService(hService);
00179
00180 dbg_err_if(rc == 0);
00181
00182
00183 MessageBox(NULL, "Uninstall secceded", ss_name, MB_OK);
00184 return 0;
00185 err:
00186
00187 warn_strerror(GetLastError());
00188 MessageBox(NULL, "Uninstall failed", ss_name, MB_OK);
00189 return ~0;
00190 }
00191
00192
00193 DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType,
00194 LPVOID lpEventData, LPVOID lpContext)
00195 {
00196 enum { DENY_ACTION = 0xff };
00197
00198 switch(dwControl)
00199 {
00200 case SERVICE_CONTROL_INTERROGATE:
00201 dbg("SERVICE_CONTROL_INTERROGATE" );
00202 SetServiceStatus(ctx->hServiceStatus, &ctx->status);
00203 return NO_ERROR;
00204
00205 case SERVICE_CONTROL_STOP:
00206 dbg("SERVICE_CONTROL_STOP");
00207
00208 if(ctx->status.dwCurrentState == SERVICE_STOPPED)
00209 return NO_ERROR;
00210
00211
00212 ctx->status.dwCheckPoint = 1;
00213 ctx->status.dwWaitHint = 2000;
00214 ctx->status.dwCurrentState = SERVICE_STOP_PENDING;
00215 SetServiceStatus(ctx->hServiceStatus, &ctx->status);
00216
00217 server_stop(ctx->server);
00218 return NO_ERROR;
00219
00220 case SERVICE_CONTROL_PAUSE:
00221 dbg("SERVICE_CONTROL_PAUSE");
00222 break;
00223
00224 case SERVICE_CONTROL_CONTINUE:
00225 dbg("SERVICE_CONTROL_CONTINUE");
00226 break;
00227
00228 case SERVICE_CONTROL_SHUTDOWN:
00229 dbg("SERVICE_CONTROL_SHUTDOWN");
00230 break;
00231
00232 case SERVICE_CONTROL_PARAMCHANGE:
00233 dbg("SERVICE_CONTROL_PARAMCHANGE");
00234 break;
00235
00236 default:
00237 dbg("SERVICE_CONTROL_UNKNOWN!!!!");
00238 }
00239 if(dwControl > 127 && dwControl < 255)
00240 {
00241
00242 dbg("SERVICE_CONTROL_USER_DEFINED");
00243 }
00244
00245 return ERROR_CALL_NOT_IMPLEMENTED;
00246 }
00247
00248
00249
00250 void WINAPI ServiceMain(DWORD argc, PTSTR *argv)
00251 {
00252 SERVICE_STATUS *pSt = &ctx->status;
00253
00254
00255 ctx->hServiceStatus = RegisterServiceCtrlHandlerEx(ss_name, HandlerEx, ctx);
00256 dbg_err_if( ctx->hServiceStatus == 0 );
00257
00258
00259 ZeroMemory(pSt, sizeof(SERVICE_STATUS));
00260
00261 pSt->dwServiceType = SERVICE_WIN32_OWN_PROCESS;
00262
00263 pSt->dwControlsAccepted = SERVICE_ACCEPT_STOP;
00264
00265 pSt->dwWin32ExitCode = NO_ERROR;
00266
00267 pSt->dwServiceSpecificExitCode = 0;
00268
00269 pSt->dwCurrentState = SERVICE_START_PENDING;
00270
00271 pSt->dwCheckPoint = 1;
00272
00273 pSt->dwWaitHint = 1000;
00274
00275 dbg_err_if(SetServiceStatus(ctx->hServiceStatus, pSt) == 0);
00276
00277 dbg_err_if(parse_opt(argc, argv));
00278
00279
00280 dbg_err_if(app_init());
00281
00282
00283
00284
00285
00286 dbg("SERVICE_RUNNING");
00287 ctx->status.dwCurrentState = SERVICE_RUNNING;
00288 ctx->status.dwCheckPoint = ctx->status.dwWaitHint = 0;
00289 dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));
00290
00291
00292 app_run();
00293
00294
00295 ctx->status.dwCurrentState = SERVICE_STOPPED;
00296 dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));
00297
00298 return;
00299
00300 err:
00301 warn_strerror(GetLastError());
00302
00303
00304 ctx->status.dwCurrentState = SERVICE_STOPPED;
00305 dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));
00306 }
00307
00308 int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
00309 LPSTR lpCmdLine, int nCmdShow)
00310 {
00311 SERVICE_TABLE_ENTRY ServiceTable[] =
00312 {
00313 { ss_name, ServiceMain },
00314 { NULL, NULL }
00315 };
00316 int rc = 0;
00317 const char *name, *desc;
00318
00319 memset(ctx, 0, sizeof(context_t));
00320
00321
00322
00323 dbg_err_if(parse_opt(__argc, __argv));
00324
00325 if(ctx->serv_op)
00326 {
00327
00328 dbg_err_if(app_init());
00329
00330
00331 name = u_config_get_subkey_value(ctx->config, "daemon.name");
00332 if(name)
00333 strncpy(ss_name, name, SS_NAME_BUFSZ);
00334
00335 desc = u_config_get_subkey_value(ctx->config, "daemon.description");
00336 if(desc)
00337 strncpy(ss_desc, desc, SS_DESC_BUFSZ);
00338
00339 if(ctx->serv_op == SERV_INSTALL)
00340 dbg_err_if(InstallService());
00341 else
00342 dbg_err_if(RemoveService());
00343 } else if(ctx->daemon) {
00344 dbg("Starting in service mode...");
00345
00346
00347 if(!StartServiceCtrlDispatcher(ServiceTable))
00348 warn_strerror(GetLastError());
00349 } else {
00350
00351 dbg_err_if(app_init());
00352
00353 rc = app_run();
00354 }
00355
00356 dbg_err_if(app_term());
00357
00358
00359
00360 if(ctx->debug)
00361 return rc;
00362
00363
00364
00365
00366
00367 _exit(rc);
00368 err:
00369 app_term();
00370
00371 if(ctx->debug)
00372 return rc;
00373 _exit(EXIT_FAILURE);
00374 }
00375
00376 #elif defined(OS_UNIX)
00377
00378 int main(int argc, char **argv)
00379 {
00380 int rc = 0;
00381
00382 memset(ctx, 0, sizeof(context_t));
00383
00384
00385 dbg_err_if(parse_opt(argc, argv));
00386
00387 if(getenv("GATEWAY_INTERFACE"))
00388 ctx->cgi = 1;
00389
00390
00391 dbg_err_if(app_init());
00392
00393
00394 if(ctx->daemon && !ctx->cgi)
00395 con_err_ifm(daemon(0, 0), "daemon error");
00396
00397
00398 rc = app_run();
00399
00400 dbg_err_if(app_term());
00401
00402
00403
00404 if(ctx->debug)
00405 return rc;
00406
00407
00408
00409
00410
00411 _exit(rc);
00412 err:
00413 app_term();
00414 if(ctx->debug)
00415 return ~0;
00416 _exit(EXIT_FAILURE);
00417 }
00418
00419 #else
00420 #error unsupported platform
00421 #endif
00422