/* If ME_CONFIG_FILE is defined, use that as the base name for appweb.conf. Otherwise, use "programName.conf". Search order is: "."/BASE ME_SERVER_ROOT/BASE EXE/../BASE EXE/../appweb.conf */ static int findAppwebConf() { char *base, *filename; if (ME_CONFIG_FILE) { base = sclone(ME_CONFIG_FILE); } else { base = mprJoinPathExt(mprGetAppName(), ".conf"); } #if !ME_ROM filename = base; if (!mprPathExists(filename, R_OK)) { filename = mprJoinPath(app->home, base); if (!mprPathExists(filename, R_OK)) { filename = mprJoinPath(mprGetPathParent(mprGetAppDir()), base); if (!mprPathExists(filename, R_OK)) { filename = mprJoinPath(mprGetPathParent(mprGetAppDir()), "appweb.conf"); if (!mprPathExists(filename, R_OK)) { mprError("Cannot find config file %s", base); return MPR_ERR_CANT_OPEN; } } } } #endif app->configFile = filename; return 0; }
/* function WebSocket(uri: Uri, protocols = null, options) options = { certificate: Path, verify: Boolean, } */ static EjsWebSocket *wsConstructor(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv) { EjsAny *certificate; bool verify; assert(ejsIsPot(ejs, ws)); ejsLoadHttpService(ejs); ws->ejs = ejs; verify = 0; ws->uri = httpUriToString(((EjsUri*) argv[0])->uri, 0); if (argc >= 2) { if (ejsIs(ejs, argv[1], Array)) { ws->protocols = sclone((ejsToString(ejs, argv[1]))->value); } else if (ejsIs(ejs, argv[1], String)) { ws->protocols = sclone(((EjsString*) argv[1])->value); } else { ws->protocols = sclone("chat"); } } else { ws->protocols = sclone("chat"); } if (*ws->protocols == '\0') { ejsThrowArgError(ejs, "Bad protocol"); return 0; } if (argc >= 3) { ws->frames = ejsGetPropertyByName(ejs, argv[2], EN("frames")) == ESV(true); verify = ejsGetPropertyByName(ejs, argv[2], EN("verify")) == ESV(true); if ((certificate = ejsGetPropertyByName(ejs, argv[2], EN("certificate"))) != 0) { ws->certFile = ejsToMulti(ejs, argv[0]); } } if ((ws->conn = httpCreateConn(MPR->httpService, NULL, ejs->dispatcher)) == 0) { ejsThrowMemoryError(ejs); return 0; } httpSetAsync(ws->conn, 1); httpPrepClientConn(ws->conn, 0); httpSetConnNotifier(ws->conn, webSocketNotify); httpSetWebSocketProtocols(ws->conn, ws->protocols); httpSetConnContext(ws->conn, ws); if (sstarts(ws->uri, "wss")) { ws->ssl = mprCreateSsl(0); mprVerifySslIssuer(ws->ssl, verify); mprVerifySslPeer(ws->ssl, verify); #if FUTURE if (!hp->caFile) { //MOB - Some define for this. hp->caFile = mprJoinPath(mprGetAppDir(), "http-ca.crt"); } mprSetSslCaFile(hp->ssl, hp->caFile); mprSetSslCaFile(hp->ssl, mprJoinPath(mprGetAppDir(), "http-ca.crt")); #endif } startWebSocketRequest(ejs, ws); return ws; }
static char *getOutDir(cchar *name) { #if DEBUG_IDE return mprGetAppDir(); #else return mprNormalizePath(sfmt("%s/../%s", mprGetAppDir(), name)); #endif }
PUBLIC int maSetPlatform(cchar *platformPath) { MaAppweb *appweb; MprDirEntry *dp; cchar *platform, *dir, *junk, *appwebExe; int next, i, notrace; appweb = MPR->appwebService; notrace = !platformPath; if (!platformPath) { platformPath = appweb->localPlatform; } appweb->platform = appweb->platformDir = 0; platform = mprGetPathBase(platformPath); if (mprPathExists(platformPath, X_OK) && mprIsPathDir(platformPath)) { appweb->platform = platform; appweb->platformDir = sclone(platformPath); } else if (smatch(platform, appweb->localPlatform)) { /* If running inside an appweb source tree, locate the platform directory */ appwebExe = mprJoinPath(mprGetAppDir(), "appweb" BIT_EXE); if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = mprGetPathParent(mprGetAppDir()); } else { /* Check installed appweb */ appwebExe = BIT_VAPP_PREFIX "/bin/appweb" BIT_EXE; if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = sclone(BIT_VAPP_PREFIX); } } } /* Last chance. Search up the tree for a similar platform directory. This permits specifying a partial platform like "vxworks" without architecture and profile. */ if (!appweb->platformDir) { dir = mprGetCurrentPath(); for (i = 0; !mprSamePath(dir, "/") && i < 64; i++) { for (ITERATE_ITEMS(mprGetPathFiles(dir, 0), dp, next)) { if (dp->isDir && sstarts(mprGetPathBase(dp->name), platform)) { appweb->platform = mprGetPathBase(dp->name); appweb->platformDir = mprJoinPath(dir, dp->name); break; } } dir = mprGetPathParent(dir); } }
void mprSetModuleSearchPath(char *searchPath) { MprModuleService *ms; ms = MPR->moduleService; if (searchPath == 0) { ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), MPR_SEARCH_SEP, BIT_BIN_PREFIX, NULL); } else { ms->searchPath = sclone(searchPath); } }
PUBLIC void mprSetModuleSearchPath(char *searchPath) { MprModuleService *ms; ms = MPR->moduleService; if (searchPath == 0) { #ifdef ME_VAPP_PREFIX ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), MPR_SEARCH_SEP, ME_VAPP_PREFIX "/bin", NULL); #else ms->searchPath = sjoin(mprGetAppDir(), MPR_SEARCH_SEP, mprGetAppDir(), NULL); #endif } else { ms->searchPath = sclone(searchPath); } }
/* * Write the port so the monitor can manage */ static int writePort(MaHost *host) { char *cp, numBuf[16], *path; int fd, port, len; path = mprJoinPath(host, mprGetAppDir(host), "../.port.log"); if ((fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) { mprError(host, "Could not create port file %s\n", path); return MPR_ERR_CANT_CREATE; } cp = host->ipAddrPort; if ((cp = strchr(host->ipAddrPort, ':')) != 0) { port = atoi(++cp); } else { port = 80; } mprItoa(numBuf, sizeof(numBuf), port, 10); len = (int) strlen(numBuf); numBuf[len++] = '\n'; if (write(fd, numBuf, len) != len) { mprError(host, "Write to file %s failed\n", path); return MPR_ERR_CANT_WRITE; } close(fd); return 0; }
/* Write the port so the monitor can manage */ static int writePort(MaServer *server) { HttpEndpoint *endpoint; char numBuf[16], *path; int fd, len; if ((endpoint = mprGetFirstItem(server->http->endpoints)) == 0) { mprLog("error appweb", 0, "No configured endpoints"); return MPR_ERR_CANT_ACCESS; } // FUTURE - should really go to a ME_LOG_DIR (then fix uninstall.sh) path = mprJoinPath(mprGetAppDir(), "../.port.log"); if ((fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) { mprLog("error appweb", 0, "Could not create port file %s", path); return MPR_ERR_CANT_CREATE; } fmt(numBuf, sizeof(numBuf), "%d", endpoint->port); len = (int) strlen(numBuf); numBuf[len++] = '\n'; if (write(fd, numBuf, len) != len) { mprLog("error appweb", 0, "Write to file %s failed", path); return MPR_ERR_CANT_WRITE; } close(fd); return 0; }
/* Security checks. Make sure we are staring with a safe environment */ static int checkEnvironment(cchar *program) { #if BIT_UNIX_LIKE app->pathVar = sjoin("PATH=", getenv("PATH"), ":", mprGetAppDir(), NULL); putenv(app->pathVar); #endif return 0; }
static void setAppDefaults() { app->appName = mprGetAppName(); app->serviceProgram = sjoin(mprGetAppDir(), "/", BLD_PRODUCT, ".exe", NULL); app->serviceName = sclone(BLD_COMPANY "-" BLD_PRODUCT); app->serviceHome = mprGetNativePath(SERVICE_HOME); app->serviceTitle = sclone(BLD_NAME); app->serviceStopped = 0; }
static void initService() { // TOOD - serviceName should come from the command line program serviceName = BLD_COMPANY "-" BLD_PRODUCT; serviceTitle = BLD_NAME; serviceStopped = 0; serviceProgram = mprStrcat(mpr, -1, mprGetAppDir(mpr), "/", BLD_PRODUCT, ".exe", NULL); }
static int findConfig() { char *base, *filename; base = sclone("http.json"); filename = base; if (!mprPathExists(filename, R_OK)) { filename = mprJoinPath(mprGetPathParent(mprGetAppDir()), base); if (!mprPathExists(filename, R_OK)) { filename = mprJoinPath(mprGetPathParent(mprGetAppDir()), base); if (!mprPathExists(filename, R_OK)) { mprError("Cannot find config file %s", base); return MPR_ERR_CANT_OPEN; } } } app->configFile = filename; return 0; }
/* Security checks. Make sure we are staring with a safe environment */ static int checkEnvironment(cchar *program) { #if ME_UNIX_LIKE char *home; home = mprGetCurrentPath(); if (unixSecurityChecks(program, home) < 0) { return -1; } app->pathVar = sjoin("PATH=", getenv("PATH"), ":", mprGetAppDir(), NULL); putenv(app->pathVar); #endif return 0; }
/* * Security checks. Make sure we are staring with a safe environment */ int checkEnvironment(Mpr *mpr, cchar *program, cchar *home) { #if BLD_UNIX_LIKE char *path; /* * Ensure the binaries directory is in the path. Used by ejs to run ejsweb from /usr/local/bin */ path = mprStrcat(mpr, -1, "PATH=", getenv("PATH"), ":", mprGetAppDir(mpr), NULL); putenv(path); #endif #if BLD_UNIX_LIKE if (unixSecurityChecks(mpr, program, home) < 0) { return -1; } #endif return 0; }
/* Get local port used by Appweb */ static int getAppwebPort() { char *path, portBuf[32]; int fd; path = mprJoinPath(mprGetAppDir(), "../.port.log"); if ((fd = open(path, O_RDONLY, 0666)) < 0) { mprError("Could not read port file %s", path); return -1; } if (read(fd, portBuf, sizeof(portBuf)) < 0) { mprError("Read from port file %s failed", path); close(fd); return 80; } close(fd); return atoi(portBuf); }
static int findConfigFile() { cchar *userPath; userPath = app->configFile; if (app->configFile == 0) { app->configFile = mprJoinPathExt(mprGetAppName(), ".conf"); } if (!mprPathExists(app->configFile, R_OK)) { if (!userPath) { app->configFile = mprJoinPath(app->home, "appweb.conf"); if (!mprPathExists(app->configFile, R_OK)) { app->configFile = mprJoinPath(mprGetAppDir(), sfmt("../%s/%s.conf", BLD_LIB_NAME, mprGetAppName())); } } if (!mprPathExists(app->configFile, R_OK)) { mprError("Can't open config file %s", app->configFile); return MPR_ERR_CANT_OPEN; } } return 0; }
static int findAppwebConf() { cchar *userPath; userPath = app->configFile; if (!app->configFile || *app->configFile == '\0') { app->configFile = mprJoinPathExt(mprGetAppName(), ".conf"); } #if !BIT_ROM if (!mprPathExists(app->configFile, R_OK)) { if (!userPath) { app->configFile = mprJoinPath(app->home, "appweb.conf"); if (!mprPathExists(app->configFile, R_OK)) { app->configFile = mprJoinPath(mprGetAppDir(), sfmt("%s.conf", mprGetAppName())); } } if (!mprPathExists(app->configFile, R_OK)) { mprError("Cannot open config file %s", app->configFile); return MPR_ERR_CANT_OPEN; } } #endif return 0; }
/* Write the port so the monitor can manage */ static int writePort(MaServer *server) { HttpHost *host; char numBuf[16], *path; int fd, len; host = mprGetFirstItem(server->http->hosts); // TODO - should really go to a BLD_LOG_DIR path = mprJoinPath(mprGetAppDir(), "../.port.log"); if ((fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) { mprError("Could not create port file %s", path); return MPR_ERR_CANT_CREATE; } mprSprintf(numBuf, sizeof(numBuf), "%d", host->port); len = (int) strlen(numBuf); numBuf[len++] = '\n'; if (write(fd, numBuf, len) != len) { mprError("Write to file %s failed", path); return MPR_ERR_CANT_WRITE; } close(fd); return 0; }
APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *command, int junk2) { char *argv[MPR_MAX_ARGC], *argp; int argc, err, nextArg, manage, stop; argc = mprParseArgs(command, &argv[1], MPR_MAX_ARGC - 1) + 1; if (mprCreate(argc, argv, MPR_USER_EVENTS_THREAD | MPR_NO_WINDOW) == NULL) { exit(1); } if ((app = mprAllocObj(App, manageApp)) == NULL) { exit(2); } mprAddRoot(app); err = 0; stop = 0; manage = 0; app->appInst = inst; app->serviceName = sclone(BIT_COMPANY "-" BIT_PRODUCT); app->serviceTitle = sclone(BIT_TITLE); app->serviceWindowName = sclone(BIT_PRODUCT "Angel"); app->serviceWindowTitle = sclone(BIT_TITLE "Angel"); mprSetAppName(BIT_PRODUCT "Monitor", BIT_TITLE " Monitor", BIT_VERSION); mprSetLogHandler(logHandler); chdir(mprGetAppDir()); /* Parse command line arguments */ for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--manage") == 0) { manage++; } else if (strcmp(argp, "--stop") == 0) { stop++; } else { err++; } if (err) { mprUserError("Bad command line: %s\n" " Usage: %s [options]\n" " Switches:\n" " --manage # Launch browser to manage", " --stop # Stop a running monitor", command, mprGetAppName()); return -1; } } if (stop) { stopMonitor(); return 0; } if (findInstance()) { mprUserError("Application %s is already active.", mprGetAppTitle()); return MPR_ERR_BUSY; } if (mprInitWindow() < 0) { mprUserError("Can't initialize application Window"); return MPR_ERR_CANT_INITIALIZE; } app->appHwnd = mprGetHwnd(); mprSetWinMsgCallback(msgProc); if (app->taskBarIcon > 0) { ShowWindow(app->appHwnd, SW_MINIMIZE); UpdateWindow(app->appHwnd); } if (manage) { /* Launch the browser */ runBrowser("/index.html"); } else { if (openMonitorIcon() < 0) { mprUserError("Can't open %s tray", mprGetAppName()); } else { eventLoop(); closeMonitorIcon(); } } return 0; }
/* * Get the directory containing the application's executable file. * * static function get exeDir(): Path */ static EjsVar *exeDir(Ejs *ejs, EjsObject *unused, int argc, EjsVar **argv) { return (EjsVar*) ejsCreatePath(ejs, mprGetAppDir(ejs)); }
/* Tokens: ARCH Build architecture (x86_64) CC Compiler (cc) DEBUG Debug compilation options (-g, -Zi -Od) INC Include directory out/inc LIB Library directory (out/lib, xcode/VS: out/bin) LIBS Libraries required to link with ESP OBJ Name of compiled source (out/lib/view-MD5.o) OUT Output module (view_MD5.dylib) SHLIB Host Shared library (.lib, .so) SHOBJ Host Shared Object (.dll, .so) SRC Source code for view or controller (already templated) TMP Temp directory VS Visual Studio directory WINSDK Windows SDK directory */ char *espExpandCommand(cchar *command, cchar *source, cchar *module) { MprBuf *buf; MaAppweb *appweb; cchar *cp, *out; char *tmp; #if BLD_WIN_LIKE cchar *path; path = 0; #endif if (command == 0) { return 0; } out = mprTrimPathExt(module); buf = mprCreateBuf(-1, -1); appweb = MPR->appwebService; for (cp = command; *cp; ) { if (*cp == '$') { if (matchToken(&cp, "${ARCH}")) { /* Build architecture */ mprPutStringToBuf(buf, appweb->hostArch); #if BLD_WIN_LIKE } else if (matchToken(&cp, "${WINSDK}")) { path = mprReadRegistry("HKLM\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", "CurrentInstallFolder"); path = strim(path, "\\", MPR_TRIM_END); mprPutStringToBuf(buf, path); } else if (matchToken(&cp, "${VS}")) { path = mprGetPathParent(mprGetPathParent(getenv("VS100COMNTOOLS"))); mprPutStringToBuf(buf, mprGetPortablePath(path)); #endif } else if (matchToken(&cp, "${CC}")) { /* Compiler */ #if BLD_WIN_LIKE // MOB - what about cross compilation path = mprJoinPath(mprGetPathParent(mprGetPathParent(getenv("VS100COMNTOOLS"))), "VC/bin/cl.exe"); mprPutStringToBuf(buf, mprGetPortablePath(path)); #else mprPutStringToBuf(buf, BLD_CC); #endif } else if (matchToken(&cp, "${DEBUG}")) { mprPutStringToBuf(buf, ESP_DEBUG); } else if (matchToken(&cp, "${INC}")) { /* Include directory (out/inc) */ mprPutStringToBuf(buf, mprResolvePath(mprGetAppDir(), "inc")); } else if (matchToken(&cp, "${LIB}")) { /* Library directory. IDE's use bin dir */ mprPutStringToBuf(buf, getOutDir(BLD_LIB_NAME)); } else if (matchToken(&cp, "${LIBS}")) { /* Required libraries to link. These may have nested ${TOKENS} */ mprPutStringToBuf(buf, espExpandCommand(ESP_LIBS, source, module)); } else if (matchToken(&cp, "${OBJ}")) { /* Output object with extension (.o) */ mprPutStringToBuf(buf, mprJoinPathExt(out, BLD_OBJ)); } else if (matchToken(&cp, "${OUT}")) { /* Output modules */ mprPutStringToBuf(buf, out); } else if (matchToken(&cp, "${SHLIB}")) { /* .lib */ mprPutStringToBuf(buf, appweb->hostOs); } else if (matchToken(&cp, "${SHOBJ}")) { /* .dll */ #ifdef BLD_HOST_SHOBJ // MOB - need this for bit mprPutStringToBuf(buf, BLD_HOST_SHOBJ); #else mprPutStringToBuf(buf, BLD_SHOBJ); #endif } else if (matchToken(&cp, "${SRC}")) { /* View (already parsed into C code) or controller source */ mprPutStringToBuf(buf, source); } else if (matchToken(&cp, "${TMP}")) { #if BLD_WIN_LIKE if ((tmp = getenv("TMP")) == 0) { tmp = getenv("TEMP"); } #else tmp = getenv("TMPDIR"); #endif mprPutStringToBuf(buf, tmp ? tmp : "."); #ifdef WIND_BASE } else if (matchToken(&cp, "${WIND_BASE}")) { mprPutStringToBuf(buf, WIND_BASE); #endif #ifdef WIND_HOME } else if (matchToken(&cp, "${WIND_HOME}")) { mprPutStringToBuf(buf, WIND_HOME); #endif #ifdef WIND_HOST_TYPE } else if (matchToken(&cp, "${WIND_HOST_TYPE}")) { mprPutStringToBuf(buf, WIND_HOST_TYPE); #endif #ifdef WIND_PLATFORM } else if (matchToken(&cp, "${WIND_PLATFORM}")) { mprPutStringToBuf(buf, WIND_PLATFORM); #endif #ifdef WIND_GNU_PATH } else if (matchToken(&cp, "${WIND_GNU_PATH}")) { mprPutStringToBuf(buf, WIND_GNU_PATH); #endif } else { mprPutCharToBuf(buf, *cp++); } } else { mprPutCharToBuf(buf, *cp++); } } mprAddNullToBuf(buf); return sclone(mprGetBufStart(buf)); }
MAIN(ejsMain, int argc, char **argv, char **envp) { Mpr *mpr; Ejs *ejs; EcCompiler *ec; char *argp, *searchPath, *path, *homeDir; int nextArg, err, flags; /* Initialize Multithreaded Portable Runtime (MPR) */ mpr = mprCreate(argc, argv, 0); app = mprAllocObj(App, manageApp); mprAddRoot(app); mprAddStandardSignals(); if (mprStart(mpr) < 0) { mprError("Cannot start mpr services"); return EJS_ERR; } err = 0; searchPath = 0; argc = mpr->argc; argv = (char**) mpr->argv; for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (smatch(argp, "--chdir") || smatch(argp, "--home") || smatch(argp, "-C")) { if (nextArg >= argc) { err++; } else { homeDir = argv[++nextArg]; if (chdir((char*) homeDir) < 0) { mprError("Cannot change directory to %s", homeDir); } } } else if (smatch(argp, "--debugger") || smatch(argp, "-D")) { mprSetDebugMode(1); } else if (smatch(argp, "--log")) { if (nextArg >= argc) { err++; } else { mprStartLogging(argv[++nextArg], 0); mprSetCmdlineLogging(1); } } else if (smatch(argp, "--name")) { /* Just ignore. Used to tag commands with a unique command line */ nextArg++; } else if (smatch(argp, "--search") || smatch(argp, "--searchpath")) { if (nextArg >= argc) { err++; } else { searchPath = argv[++nextArg]; } } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) { mprStartLogging("stderr:1", 0); mprSetCmdlineLogging(1); } else if (smatch(argp, "--version") || smatch(argp, "-V")) { mprPrintf("%s-%s\n", BIT_VERSION, BIT_BUILD_NUMBER); return 0; } else { /* Ignore */ } } path = mprJoinPath(mprGetAppDir(), mprGetPathBase(argv[0])); path = mprReplacePathExt(path, ".es"); mprAddRoot(path); argv[0] = path; if ((ejs = ejsCreateVM(argc, (cchar **) &argv[0], 0)) == 0) { return MPR_ERR_MEMORY; } app->ejs = ejs; if (ejsLoadModules(ejs, searchPath, NULL) < 0) { return MPR_ERR_CANT_READ; } mprLog(2, "Load script \"%s\"", path); flags = EC_FLAGS_BIND | EC_FLAGS_DEBUG | EC_FLAGS_NO_OUT | EC_FLAGS_THROW; if ((ec = ecCreateCompiler(ejs, flags)) == 0) { return MPR_ERR_MEMORY; } mprAddRoot(ec); ecSetOptimizeLevel(ec, 9); ecSetWarnLevel(ec, 1); if (ecCompile(ec, 1, (char**) &path) < 0) { if (flags & EC_FLAGS_THROW) { ejsThrowSyntaxError(ejs, "%s", ec->errorMsg ? ec->errorMsg : "Cannot parse script"); ejsReportError(ejs, "Error in script"); } err = MPR_ERR; } else { mprRemoveRoot(ec); if (ejsRunProgram(ejs, NULL, NULL) < 0) { ejsReportError(ejs, "Error in script"); err = MPR_ERR; } } if (!err) { err = mpr->exitStatus; } app->ejs = 0; mprTerminate(MPR_EXIT_DEFAULT, err); ejsDestroyVM(ejs); mprDestroy(MPR_EXIT_DEFAULT); return err; }
static bool installService() { SC_HANDLE svc, mgr; char cmd[MPR_MAX_FNAME], key[MPR_MAX_FNAME]; int serviceType; mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (! mgr) { mprUserError("Can't open service manager"); return 0; } /* Install this app as a service */ svc = OpenService(mgr, app->serviceName, SERVICE_ALL_ACCESS); if (svc == NULL) { serviceType = SERVICE_WIN32_OWN_PROCESS; if (app->createConsole) { serviceType |= SERVICE_INTERACTIVE_PROCESS; } GetModuleFileName(0, cmd, sizeof(cmd)); svc = CreateService(mgr, app->serviceName, app->serviceTitle, SERVICE_ALL_ACCESS, serviceType, SERVICE_DISABLED, SERVICE_ERROR_NORMAL, cmd, NULL, NULL, "", NULL, NULL); if (! svc) { mprUserError("Can't create service: 0x%x == %d", GetLastError(), GetLastError()); CloseServiceHandle(mgr); return 0; } } CloseServiceHandle(svc); CloseServiceHandle(mgr); /* Write a service description */ mprSprintf(key, sizeof(key), "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\" "Services\\%s", app->serviceName); if (mprWriteRegistry(key, "Description", SERVICE_DESCRIPTION) < 0) { return 0; } /* Write the home directory */ if (app->serviceHome == 0) { app->serviceHome = mprGetPathParent(mprGetAppDir()); } if (mprWriteRegistry(key, "HomeDir", app->serviceHome) < 0) { return 0; } /* Write the service args */ if (app->serviceArgs && *app->serviceArgs) { if (mprWriteRegistry(key, "Args", app->serviceArgs) < 0) { return 0; } } return 1; }
static void run() { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; MprTime mark; ulong status; char *path, *cmd, *key; int createFlags; createFlags = 0; #if USEFUL_FOR_DEBUG /* This is useful to debug manager as a windows service. */ DebugBreak(); #endif /* Read the service home directory and args. Default to the current dir if none specified. */ key = sfmt("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\%s", app->serviceName); app->serviceHome = mprReadRegistry(key, "HomeDir"); app->serviceArgs = mprReadRegistry(key, "Args"); /* Expect to find the service executable in the same directory as this manager program. */ if (app->serviceProgram == 0) { path = sfmt("\"%s\\%s.exe\"", mprGetAppDir(), BLD_PRODUCT); } else { path = sfmt("\"%s\"", app->serviceProgram); } if (app->serviceArgs && *app->serviceArgs) { cmd = sfmt("%s %s", path, app->serviceArgs); } else { cmd = path; } if (app->createConsole) { createFlags |= CREATE_NEW_CONSOLE; } mark = mprGetTime(); while (! app->exiting) { if (mprGetElapsedTime(mark) > (3600 * 1000)) { mark = mprGetTime(); app->restartCount = 0; app->restartWarned = 0; } if (app->servicePid == 0 && !app->serviceStopped) { if (app->restartCount >= RESTART_MAX) { if (! app->restartWarned) { mprError("Too many restarts for %s, %d in ths last hour", app->appTitle, app->restartCount); app->restartWarned++; } /* This is not a real heart-beat. We are only waiting till the service process exits. */ WaitForSingleObject(app->heartBeatEvent, app->heartBeatPeriod); continue; } memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); /* Launch the process */ if (! CreateProcess(0, cmd, 0, 0, FALSE, createFlags, 0, app->serviceHome, &startInfo, &procInfo)) { mprError("Can't create process: %s, %d", cmd, mprGetOsError()); } else { app->servicePid = (int) procInfo.hProcess; } app->restartCount++; } WaitForSingleObject(app->heartBeatEvent, app->heartBeatPeriod); if (app->servicePid) { if (GetExitCodeProcess((HANDLE) app->servicePid, (ulong*) &status)) { if (status != STILL_ACTIVE) { CloseHandle((HANDLE) app->servicePid); app->servicePid = 0; } } else { CloseHandle((HANDLE) app->servicePid); app->servicePid = 0; } } mprLog(1, "%s has exited with status %d", app->serviceProgram, status); mprLog(1, "%s will be restarted in 10 seconds", app->serviceProgram); } }
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *args, int junk2) { char **argv, *argp; int argc, err, nextArg, manage, stop; mpr = mprCreate(0, NULL, NULL); err = 0; manage = 0; appInst = inst; stop = 0; serviceName = BLD_COMPANY "-" BLD_PRODUCT; serviceTitle = BLD_NAME; serviceWindowName = BLD_PRODUCT "Angel"; serviceWindowTitle = BLD_NAME "Angel"; mprSetAppName(mpr, BLD_PRODUCT "Monitor", BLD_NAME " Monitor", BLD_VERSION); appName = mprGetAppName(mpr); appTitle = mprGetAppTitle(mpr); mprSetLogHandler(mpr, logHandler, NULL); chdir(mprGetAppDir(mpr)); /* * Parse command line arguments */ if (mprMakeArgv(mpr, "", args, &argc, &argv) < 0) { return FALSE; } for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--manage") == 0) { manage++; } else if (strcmp(argp, "--stop") == 0) { stop++; } else { err++; } if (err) { mprUserError(mpr, "Bad command line: %s\n" " Usage: %s [options]\n" " Switches:\n" " --manage # Launch browser to manage", " --stop # Stop a running monitor", args, appName); return -1; } } if (stop) { stopMonitor(); return 0; } if (findInstance(mpr)) { mprUserError(mpr, "Application %s is already active.", mprGetAppTitle(mpr)); return MPR_ERR_BUSY; } /* * Create the window */ if (initWindow(mpr) < 0) { mprUserError(mpr, "Can't initialize application Window"); return MPR_ERR_CANT_INITIALIZE; } if (manage) { /* * Launch the browser */ runBrowser("/index.html"); } else { if (openMonitorIcon() < 0) { mprUserError(mpr, "Can't open %s tray", appName); } else { eventLoop(); closeMonitorIcon(); } } // mprFree(mpr); return 0; }
/* Get the directory containing the application's executable file. static function get exeDir(): Path */ static EjsPath *app_exeDir(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { return ejsCreatePathFromAsc(ejs, mprGetAppDir()); }
APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *command, int junk2) { char *argv[ME_MAX_ARGC], *argp; int argc, err, nextArg, manage, stop; argv[0] = ME_NAME "Monitor"; argc = mprParseArgs(command, &argv[1], ME_MAX_ARGC - 1) + 1; if (mprCreate(argc, argv, MPR_USER_EVENTS_THREAD | MPR_NO_WINDOW) == NULL) { exit(1); } if ((app = mprAllocObj(App, manageApp)) == NULL) { exit(2); } mprAddRoot(app); err = 0; stop = 0; manage = 0; app->appInst = inst; app->company = sclone(ME_COMPANY); app->serviceName = sclone(ME_NAME); mprSetLogHandler(logHandler); chdir(mprGetAppDir()); /* Parse command line arguments */ for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--manage") == 0) { manage++; } else if (strcmp(argp, "--stop") == 0) { stop++; } else { err++; } if (err) { mprError("appweb monitor", "Bad command line: %s\n" " Usage: %s [options]\n" " Switches:\n" " --manage # Launch browser to manage", " --stop # Stop a running monitor", command, mprGetAppName()); return -1; } } if (stop) { stopMonitor(); return 0; } if (findInstance()) { mprError("appweb monitor", "Application %s is already active.", mprGetAppTitle()); return MPR_ERR_BUSY; } app->hwnd = mprSetWindowsThread(0); mprSetWinMsgCallback(msgProc); if (app->taskBarIcon > 0) { ShowWindow(app->hwnd, SW_MINIMIZE); UpdateWindow(app->hwnd); } if (manage) { /* Launch the browser */ runBrowser("/index.html"); } else { if (openMonitorIcon() < 0) { mprError("appweb monitor", "Cannot open %s tray", mprGetAppName()); } else { mprServiceEvents(-1, 0); closeMonitorIcon(); } } mprDestroy(); return 0; }