/* * Process the requests */ static void processing() { if (chunkSize) { mprAddItem(headers, mprCreateKeyPair(headers, "X-Appweb-Chunk-Size", chunkSize)); } #if BLD_FEATURE_MULTITHREAD { MprThread *tp; int j; activeLoadThreads = loadThreads; for (j = 0; j < loadThreads; j++) { char name[64]; mprSprintf(name, sizeof(name), "http.%d", j); tp = mprCreateThread(mpr, name, threadMain, mpr, MPR_NORMAL_PRIORITY, 0); mprStartThread(tp); } } #else threadMain(mpr, NULL); #endif }
int MprLogToFile::setLogSpec(char *path, int size) { struct stat sbuf; char bak[MPR_MAX_FNAME]; if (logFd >= 0) { close(logFd); } maxSize = size * 1024 * 1024; // Convert to bytes logFileName = mprStrdup(path); if (strcmp(logFileName, "stdout") == 0) { logFd = MPR_STDOUT; } else { if (stat(logFileName, &sbuf) >= 0) { mprSprintf(bak, sizeof(bak), "%s.old", logFileName); if (access(bak, R_OK) == 0) { unlink(bak); } rename(logFileName, bak); #if VXWORKS // // VxWorks FTP file system does not succeed with renames // if (access(logFileName, R_OK) == 0) { unlink(logFileName); } #endif } logFd = open(logFileName, O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0666); if (logFd < 0) { return MPR_ERR_CANT_OPEN; } } return 0; }
static pid_t readPid() { Mpr *mpr; char pidPath[MPR_MAX_FNAME]; pid_t pid; int fd; mpr = mprGetMpr(); mprSprintf(pidPath, MPR_MAX_FNAME, "%s/.%s_pid.log", mpr->getInstallDir(), mpr->getAppName()); if ((fd = open(pidPath, O_RDONLY, 0666)) < 0) { mprLog(MPR_DEBUG, "Could not read a pid from %s\n", pidPath); return -1; } if (read(fd, &pid, sizeof(pid)) != sizeof(pid)) { mprLog(MPR_DEBUG, "Read from file %s failed\n", pidPath); close(fd); return -1; } close(fd); return pid; }
/* 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; }
int maWriteGroupFile(MaServer *server, MaAuth *auth, char *path) { MprHash *hp; MprFile *file; MaGroup *gp; char buf[MPR_MAX_STRING], *tempFile, *name; int next; tempFile = mprGetTempPath(server, NULL); if ((file = mprOpen(auth, tempFile, O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0444)) == 0) { mprError(server, "Can't open %s", tempFile); mprFree(tempFile); return MPR_ERR_CANT_OPEN; } mprFree(tempFile); hp = mprGetNextHash(auth->groups, 0); while (hp) { gp = (MaGroup*) hp->data; mprSprintf(buf, sizeof(buf), "%d: %x: %s: ", gp->enabled, gp->acl, gp->name); mprWrite(file, buf, (int) strlen(buf)); for (next = 0; (name = mprGetNextItem(gp->users, &next)) != 0; ) { mprWrite(file, name, (int) strlen(name)); } mprWrite(file, "\n", 1); hp = mprGetNextHash(auth->groups, hp); } mprFree(file); unlink(path); if (rename(tempFile, path) < 0) { mprError(server, "Can't create new %s", path); return MPR_ERR_CANT_WRITE; } return 0; }
static int configureViaApi() { MaHostAddress *address; MaHost *host; MprList *listens; MaListen *lp; MprHashTable *hostAddresses; MaDir *dir; MaAlias *ap; MaLocation *loc; char *cp, *docRootPath; char addrBuf[MPR_MAX_IP_ADDR_PORT], pathBuf[MPR_MAX_FNAME]; int port; mprLog(MPR_CONFIG, "Configuration via Command Line\n"); #if BLD_FEATURE_ROMFS mprLog(MPR_CONFIG, "Server Root \"%s\" in ROM\n", serverRoot); docRootPath = mprStrdup(docRoot); #else // // Set the document root. Is relative to the server root unless an absolute path is used. // #if WIN if (*docRoot != '/' && docRoot[1] != ':' && docRoot[2] != '/') #elif WINCE if (*docRoot != '\\' && docRoot != '/') #else if (*docRoot != '/') #endif { if (*docRoot) { mprAllocSprintf(&docRootPath, MPR_MAX_FNAME, "%s/%s", serverRoot, docRoot); } else { docRootPath = mprStrdup(serverRoot); } } else { docRootPath = mprStrdup(docRoot); } #endif // BLD_FEATURE_ROMFS mprLog(MPR_CONFIG, "Document Root \"%s\"\n", docRootPath); // // Setup the listening addresses. If only a port is specified, listen on // all interfaces. If only the IP address is specified without a port, // then default to port 80. IF autoScan is on, scan for a free port // starting from the base address. // listens = server->getListens(); port = MA_SERVER_DEFAULT_PORT_NUM; if ((cp = strchr(ipAddr, ':')) != 0) { *cp++ = '\0'; port = atoi(cp); if (port <= 0 || port > 65535) { mprError(MPR_L, MPR_USER, "Bad listen port number %d", port); return MPR_ERR_BAD_SYNTAX; } if (autoScan) { port = findFreePort(ipAddr, port); } listens->insert(new MaListen(ipAddr, port, 0)); } else { if (isdigit((uchar) *ipAddr) && strchr(ipAddr, '.') == 0) { port = atoi(ipAddr); if (port <= 0 || port > 65535) { mprError(MPR_L, MPR_USER, "Bad listen port number %d", port); return MPR_ERR_BAD_SYNTAX; } if (autoScan) { port = findFreePort("", port); } listens->insert(new MaListen("", port)); } else { if (autoScan) { port = findFreePort(ipAddr, MA_SERVER_DEFAULT_PORT_NUM); } listens->insert(new MaListen(ipAddr, port)); } } mprFree(ipAddr); ipAddr = 0; host = server->newHost(docRootPath); if (host == 0) { return MPR_ERR_CANT_OPEN; } // // Add the default server listening addresses to the HostAddress hash. // FUTURE -- this should be moved into newHost // hostAddresses = server->getHostAddresses(); lp = (MaListen*) listens->getFirst(); while (lp) { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", lp->getIpAddr(), lp->getPort()); address = (MaHostAddress*) hostAddresses->lookup(addrBuf); if (address == 0) { address = new MaHostAddress(addrBuf); hostAddresses->insert(address); } mprLog(MPR_CONFIG, "Listening for HTTP on %s\n", addrBuf); address->insertVhost(new MaVhost(host)); lp = (MaListen*) listens->getNext(lp); mprFree(ipAddr); ipAddr = mprStrdup(addrBuf); } // // Setup a module search path that works for production and developement. // #if BLD_FEATURE_DLL char searchPath[MPR_MAX_FNAME]; mprSprintf(searchPath, sizeof(searchPath), "./lib ../lib ../lib/modules ../../lib ../../lib/modules %s/lib", BLD_PREFIX); host->setModuleDirs(searchPath); #endif // // Load all possible modules // #if BLD_FEATURE_AUTH_MODULE // // Handler must be added first to authorize all requests. // if (server->loadModule("auth") == 0) { host->addHandler("authHandler", ""); } #endif #if BLD_FEATURE_UPLOAD_MODULE // // Must be after auth and before ESP, EGI. // if (server->loadModule("upload") == 0) { host->addHandler("uploadHandler", ""); } #endif #if BLD_FEATURE_CGI_MODULE if (server->loadModule("cgi") == 0) { host->addHandler("cgiHandler", ".cgi .cgi-nph .bat .cmd .pl .py"); } #endif #if BLD_FEATURE_EGI_MODULE if (server->loadModule("egi") == 0) { host->addHandler("egiHandler", ".egi"); } #endif #if BLD_FEATURE_ESP_MODULE if (server->loadModule("esp") == 0) { host->addHandler("espHandler", ".esp .asp"); } #endif #if BLD_FEATURE_C_API_MODULE server->loadModule("capi"); #endif #if BLD_FEATURE_GACOMPAT_MODULE server->loadModule("compat"); #endif #if BLD_FEATURE_SSL_MODULE server->loadModule("ssl"); #endif // // Only load one of matrixSsl / openssl // #if BLD_FEATURE_OPENSSL_MODULE server->loadModule("openSsl"); #elif BLD_FEATURE_MATRIXSSL_MODULE server->loadModule("matrixSsl"); #endif #if BLD_FEATURE_PHP5_MODULE if (server->loadModule("php5") == 0) { host->addHandler("php5Handler", ".php"); } #endif #if BLD_FEATURE_COPY_MODULE // // Handler must be added last to be the catch all // if (server->loadModule("copy") == 0) { host->addHandler("copyHandler", ""); } #endif // // Create the top level directory // dir = new MaDir(host); dir->setPath(docRootPath); host->insertDir(dir); // // Add cgi-bin // mprSprintf(pathBuf, sizeof(pathBuf), "%s/cgi-bin", serverRoot); ap = new MaAlias("/cgi-bin/", pathBuf); mprLog(4, "ScriptAlias \"/cgi-bin/\":\n\t\t\t\"%s\"\n", pathBuf); host->insertAlias(ap); loc = new MaLocation(dir->getAuth()); loc->setPrefix("/cgi-bin/"); loc->setHandler("cgiHandler"); host->insertLocation(loc); mprFree(docRootPath); return 0; }
static int locateServerRoot(char *path) { #if BLD_FEATURE_CONFIG_PARSE && !BLD_FEATURE_ROMFS if (serverRoot == 0) { MprFileInfo info; char searchPath[MPR_MAX_FNAME * 8], pathBuf[MPR_MAX_FNAME]; char cwd[MPR_MAX_FNAME]; char *tok, *searchBuf; // // No explicit server root switch was supplied so search for // "mime.types" in the search path: // . // .. // ../productName // ../../productName // For windows, we also do: // modDir (where the exe was loaded from) // modDir/.. // modDir/../productName // modDir/../../productName // For all: // BLD_PREFIX // #if WIN || WINCE char modDir[MPR_MAX_FNAME], modPath[MPR_MAX_FNAME]; char module[MPR_MAX_FNAME]; // // Initially change directory to where the exe lives // GetModuleFileName(0, module, sizeof(module)); mprGetDirName(modDir, sizeof(modDir), module); mprGetFullPathName(modPath, sizeof(modPath), modDir); #if WIN /* NOTE: use tabs not spaces between items */ mprSprintf(searchPath, sizeof(searchPath), ". .. ../%s ../../%s " "%s %s/.. %s/../%s %s/../../%s %s", BLD_PRODUCT, BLD_PRODUCT, modPath, modPath, modPath, BLD_PRODUCT, modPath, BLD_PRODUCT, BLD_PREFIX); #else /* NOTE: use tabs not spaces between items */ mprSprintf(searchPath, sizeof(searchPath), "%s %s ../%s ../../%s " "%s/.. %s/../%s", MPR_STORAGE, modPath, BLD_PRODUCT, BLD_PRODUCT, modPath, modPath, modPath); #endif #else mprSprintf(searchPath, sizeof(searchPath), ". .. ../%s ../../%s %s", BLD_PRODUCT, BLD_PRODUCT, BLD_PREFIX); #endif getcwd(cwd, sizeof(cwd) - 1); mprLog(3, "Root search path %s, cwd %s\n", searchPath, cwd); searchBuf = mprStrdup(searchPath); path = mprStrTok(searchBuf, "\t", &tok); while (path) { mprSprintf(pathBuf, sizeof(pathBuf), "%s/mime.types", path); mprLog(4, "Searching for %s\n", pathBuf); if (fileSystem->stat(pathBuf, &info) == 0) { break; } path = mprStrTok(0, "\t", &tok); } if (path == 0) { mprError(MPR_L, MPR_USER, "Can't find suitable server root directory\n" "Using search path %s, and current directory %s\n" "Ensure you have adequate permissions to access the required " "directories.\n", searchPath, cwd); mprFree(searchBuf); return MPR_ERR_CANT_ACCESS; } server->setServerRoot(path); mprFree(searchBuf); } else { // // Must program the server up for the server root. It will convert this // path to an absolute path which we reassign to our notion of // serverRoot. // server->setServerRoot(path); } serverRoot = server->getServerRoot(); #endif #if !BLD_FEATURE_ROMFS chdir(serverRoot); #endif return 0; }
static int realMain(MprCmdLine *cmdLine) { MaHttp *http; char portNumBuf[MPR_MAX_IP_PORT]; char *argp, *logSpec; int c, errflg, kill, poolThreads, outputVersion; mprSetMemHandler(memoryFailure); mprCreateMemHeap(0, 16 * 1024, MAXINT); program = mprGetBaseName(cmdLine->getArgv()[0]); poolThreads = -1; kill = errflg = 0; logSpec = 0; outputVersion = 0; autoScan = 1; background = 0; serverRoot = 0; docRoot = "web"; #if !WIN && !WINCE && !VXWORKS if (getuid()) { ipAddr = mprStrdup("4000"); } else { mprSprintf(portNumBuf, sizeof(portNumBuf), "%d", MA_SERVER_DEFAULT_PORT_NUM); ipAddr = mprStrdup(portNumBuf); } #else mprSprintf(portNumBuf, sizeof(portNumBuf), "%d", MA_SERVER_DEFAULT_PORT_NUM); ipAddr = mprStrdup(portNumBuf); #endif while ((c = cmdLine->next(&argp)) != EOF) { switch(c) { case 'A': autoScan = 0; break; case 'a': mprFree(ipAddr); ipAddr = mprStrdup(argp); break; case 'b': background++; break; case 'c': /* Ignored */ break; case 'D': mprSetDebugMode(1); break; case 'd': docRoot = argp; break; case 'f': #if BLD_FEATURE_CONFIG_PARSE configFile = argp; autoScan = 0; #else errflg++; #endif break; case 'k': kill++; logSpec = 0; break; case 'l': logSpec = (*argp) ? argp : 0; break; case 'm': mprRequestMemStats(1); break; case 'r': serverRoot = argp; break; case 't': poolThreads = atoi(argp); break; // // FUTURE -- just for test. Will be removed // case 'w': writeFile = argp; break; case 'v': outputVersion++; break; #if WIN && BLD_FEATURE_RUN_AS_SERVICE case 'i': serviceOp = MPR_INSTALL_SERVICE; if (strcmp(argp, "none") == 0) { serviceCmdLine = ""; } else if (strcmp(argp, "default") == 0) { serviceCmdLine = "-b -c -f " BLD_PRODUCT ".conf"; } else { serviceCmdLine = argp; } break; case 'g': serviceOp = MPR_GO_SERVICE; break; case 's': serviceOp = MPR_STOP_SERVICE; break; case 'u': serviceOp = MPR_UNINSTALL_SERVICE; break; #endif default: errflg++; break; } } if (errflg) { printUsage(program); return MPR_ERR_BAD_SYNTAX; } mp = new Mpr(program); mp->setAppName(BLD_PRODUCT); mp->setAppTitle(BLD_NAME); mp->setHeadless(isService || background); #if BLD_HOST_UNIX || VXWORKS initSignals(); #endif if (kill) { mp->killMpr(); delete mp; exit(0); } if (outputVersion) { printVersion(); delete mp; exit(0); } // // Create the top level HTTP service and default HTTP server // http = new MaHttp(); server = new MaServer(http, "default"); setupFileSystem(); setLogging(logSpec); // // Confirm the location of the server root // if (locateServerRoot(serverRoot) < 0) { mprError(MPR_L, MPR_USER, "Can't start server, exiting."); exit(2); } if (securityChecks(cmdLine->getArgv()[0]) < 0) { exit(3); } #if WIN #if BLD_FEATURE_RUN_AS_SERVICE if (serviceOp) { windowsServiceOps(); delete mp; return 0; } #endif if (windowsInit() < 0) { delete mp; return MPR_ERR_CANT_INITIALIZE; } #endif // // Start the MPR. This starts Timer, Socket and Pool services // if (mp->start(MPR_KILLABLE) < 0) { mprError(MPR_L, MPR_USER, "Can't start MPR for %s", mp->getAppTitle()); delete mp; return MPR_ERR_CANT_INITIALIZE; } // // Load the statically linked modules // maLoadStaticModules(); if (setupServer(http, poolThreads) < 0) { mprError(MPR_L, MPR_USER, "Can't configure the server, exiting."); exit(6); } #if BLD_FEATURE_CONFIG_SAVE if (writeFile) { server->saveConfig(writeFile); mprLog(0, "Configuration saved to %s\nExiting ...\n", writeFile); exit(0); } #endif if (http->start() < 0) { mprError(MPR_L, MPR_USER, "Can't start server, exiting."); exit(7); } else { #if LINUX && BLD_FEATURE_RUN_AS_SERVICE if (background && mp->makeDaemon(1) < 0) { mprError(MPR_L, MPR_USER, "Could not run in the background"); } else #endif { #if BLD_FEATURE_MULTITHREAD mprLog(MPR_CONFIG, "HTTP services are ready with %d pool threads\n", http->getLimits()->maxThreads); #else mprLog(MPR_CONFIG, "HTTP services are ready (single-threaded).\n"); #endif } mp->setHeadless(1); eventLoop(); mprLog(MPR_WARN, "Stopping HTTP services.\n"); http->stop(); } #if WIN if (trayIcon > 0) { closeTrayIcon(); } if (trayTimer) { trayTimer->stop(MPR_TIMEOUT_STOP); trayTimer->dispose(); trayTimer = 0; } #endif mprLog(MPR_WARN, "Stopping MPR services.\n"); mp->stop(0); maUnloadStaticModules(); delete server; delete http; delete mp; mprFree(ipAddr); #if BLD_FEATURE_ROMFS delete romFileSystem; #endif #if BLD_FEATURE_LOG mprLog(MPR_WARN, "Closing log.\n"); if (logger) { delete logger; } #if WIN if (dialog) { delete dialog; } #endif #endif return 0; }
int MprTestSession::setupTests(MprTestResult *result, Mpr *mpr, int argc, char *argv[], char *switches) { char switchBuf[80]; char *programName, *argp; int errflg, c, i, l; #if BLD_FEATURE_LOG char *logSpec; #endif this->mpr = mpr; programName = mprGetBaseName(argv[0]); errflg = 0; #if BLD_FEATURE_LOG logSpec = "stdout:1"; logger = new MprLogToFile(); #endif switchBuf[0] = '\0'; mprStrcat(switchBuf, sizeof(switchBuf), 0, "cDeg:i:l:n:msT:t:v?", switches, (void*) 0); MprCmdLine cmdLine(argc, argv, switchBuf); while ((c = cmdLine.next(&argp)) != EOF) { switch(c) { case 'c': result->setContinueOnFailures(1); break; case 'D': mprSetDebugMode(1); result->setDebugOnFailures(1); break; case 'e': needEventsThread = 1; break; case 'g': testGroups->parse(argp); break; case 'i': iterations = atoi(argp); break; case 'l': #if BLD_FEATURE_LOG logSpec = argp; #endif break; case 'n': l = atoi(argp); if (l == 0) { sessionLevel = MPR_BASIC; } else if (l == 1) { sessionLevel = MPR_THOROUGH; } else { sessionLevel = MPR_DEDICATED; } break; case 'm': mprRequestMemStats(1); break; case 's': result->setSingleStep(1); break; case 't': i = atoi(argp); if (i <= 0 || i > 100) { mprFprintf(MPR_STDERR, "%s: Bad number of threads (0-100)\n", programName); exit(2); } #if BLD_FEATURE_MULTITHREAD numThreads = i; #endif break; case 'T': #if BLD_FEATURE_MULTITHREAD poolThreads = atoi(argp); #endif break; case 'v': verbose++; break; default: // // Ignore args we don't understand // break; case '?': errflg++; break; } } if (errflg) { mprFprintf(MPR_STDERR, "usage: %s [-cDemsv] [-g groups] [-i iterations] " "[-l logSpec] [-n testLevel] [-T poolThreads] [-t threads]\n", programName); exit(2); } #if !BLD_FEATURE_MULTITHREAD needEventsThread = 0; #endif #if BLD_FEATURE_LOG mpr->addListener(logger); mpr->setLogSpec(logSpec); #endif initSignals(); this->argc = argc; this->argv = argv; this->firstArg = cmdLine.firstArg(); #if BLD_FEATURE_MULTITHREAD mpr->setMaxPoolThreads(poolThreads); #endif if (mpr->start(needEventsThread ? MPR_SERVICE_THREAD : 0) < 0) { return MPR_ERR_CANT_INITIALIZE; } result->adjustThreadCount(numThreads); result->setVerbosity(verbose); if (result->getListenerCount() == 0) { result->addListener(new MprTestListener("__default__")); } if (verbose) { mprFprintf(MPR_STDOUT, "Testing: iterations %d, threads %d, pool %d, service thread %d\n", iterations, numThreads, poolThreads, needEventsThread); } // // Use current session object for the main thread // sessions = (MprTestSession**) mprMalloc(sizeof(MprTestSession*) * numThreads); sessions[0] = this; if (sessions[0]->initializeClasses(result) < 0) { exit(3); } #if BLD_FEATURE_MULTITHREAD // // Now clone this session object for all other threads // for (i = 1; i < numThreads; i++) { char tName[64]; sessions[i] = this->newSession(); sessions[i]->setResult(result); sessions[i]->cloneSettings(this); mprSprintf(tName, sizeof(tName), "test.%d", i); } #endif return 0; }
EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri, MprVar *variables) { EspRequest *ep; MprVar *global; #if BLD_FEATURE_LEGACY_API MprVar *np; char keyBuf[ESP_MAX_HEADER]; int i; #endif mprAssert(variables); ep = (EspRequest*)mprMalloc(sizeof(EspRequest)); if (ep == 0) { return 0; } memset(ep, 0, sizeof(EspRequest)); ep->requestHandle = webServerRequestHandle; ep->esp = esp; ep->uri = mprStrdup(uri); ep->docPath = 0; ep->variables = variables; /* * The handle passed to ejsOpenEngine is passed to every C function * called by JavaScript. */ ep->eid = ejsOpenEngine((EjsHandle) ep, (EjsHandle) webServerRequestHandle); if (ep->eid < 0) { mprFree(ep); return 0; } /* * All these copies and SetProperties will only copy references * They will increments the object ref counts. */ mprCopyVar(&variables[ESP_GLOBAL_OBJ], ejsGetGlobalObject(ep->eid), MPR_SHALLOW_COPY); mprCopyVar(&variables[ESP_LOCAL_OBJ], ejsGetLocalObject(ep->eid), MPR_SHALLOW_COPY); global = &variables[ESP_GLOBAL_OBJ]; mprCreateProperty(global, "application", &variables[ESP_APPLICATION_OBJ]); mprCreateProperty(global, "cookies", &variables[ESP_COOKIES_OBJ]); mprCreateProperty(global, "files", &variables[ESP_FILES_OBJ]); mprCreateProperty(global, "form", &variables[ESP_FORM_OBJ]); mprCreateProperty(global, "headers", &variables[ESP_HEADERS_OBJ]); mprCreateProperty(global, "request", &variables[ESP_REQUEST_OBJ]); // // FUTURE -- could server be shared across all requests for a given host // and be made read-only. // mprCreateProperty(global, "server", &variables[ESP_SERVER_OBJ]); #if BLD_FEATURE_SESSION mprCreateProperty(global, "session", &variables[ESP_SESSION_OBJ]); #endif #if BLD_FEATURE_LEGACY_API /* * DEPRECATED: 2.0 * Define variables as globals. headers[] are prefixed with "HTTP_". * NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar * does if legacy_api is defined. So variables pre-defined by MaRequest * must be copied here into globals[]. * * NOTE: if a variable is in session[] and in form[], the form[] will * override being later in the variables[] list. Use mprSetProperty * instead of mprCreateProperty to cover for this case. */ for (i = 0; i < ESP_OBJ_MAX; i++) { if (i == ESP_GLOBAL_OBJ || i == ESP_LOCAL_OBJ) { continue; } if (variables[i].type != MPR_TYPE_OBJECT) { continue; } np = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA); while (np) { if (i == ESP_HEADERS_OBJ) { mprSprintf(keyBuf, sizeof(keyBuf) - 1, "HTTP_%s", np->name); mprSetProperty(global, keyBuf, np); } else { mprSetProperty(global, np->name, np); } np = mprGetNextProperty(&variables[i], np, MPR_ENUM_DATA); } } #endif return ep; }
static void angel() { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; MprTime mark; ulong status; char *dir, *homeDir, *serviceArgs; char key[MPR_MAX_FNAME], path[MPR_MAX_FNAME], cmd[MPR_MAX_FNAME]; int createFlags, restartWarned; servicePid = 0; createFlags = 0; restartWarned = 0; #if USEFUL_FOR_DEBUG DebugBreak(); #endif /* * Read the service home directory and args. Default to the current dir if none specified. */ homeDir = 0; serviceArgs = 0; mprSprintf(key, sizeof(key), "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\%s", serviceName); mprReadRegistry(mpr, &homeDir, MPR_MAX_FNAME, key, "HomeDir"); mprReadRegistry(mpr, &serviceArgs, MPR_MAX_FNAME, key, "Args"); /* * Expect to find the service executable in the same directory as this angel program. */ if (serviceProgram == 0) { GetModuleFileName(0, path, sizeof(path)); dir = mprGetPathDir(mpr, path); mprSprintf(path, sizeof(path), "\"%s\\%s.exe\"", dir, BLD_PRODUCT); mprFree(dir); } else { mprSprintf(path, sizeof(path), "\"%s\"", serviceProgram); } if (serviceArgs && *serviceArgs) { mprSprintf(cmd, sizeof(cmd), "%s %s", path, serviceArgs); } else { mprSprintf(cmd, sizeof(cmd), "%s", path); } if (createConsole) { createFlags |= CREATE_NEW_CONSOLE; } mark = mprGetTime(mpr); while (! exiting) { if (mprGetElapsedTime(mpr, mark) > (3600 * 1000)) { mark = mprGetTime(mpr); restartCount = 0; restartWarned = 0; } if (servicePid == 0 && !serviceStopped) { if (restartCount >= RESTART_MAX) { if (! restartWarned) { mprError(mpr, "Too many restarts for %s, %d in ths last hour", appTitle, restartCount); restartWarned++; } /* * This is not a real heart-beat. We are only waiting till the service process exits. */ WaitForSingleObject(heartBeatEvent, heartBeatPeriod); continue; } memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); /* * Launch the process */ if (! CreateProcess(0, cmd, 0, 0, FALSE, createFlags, 0, homeDir, &startInfo, &procInfo)) { mprError(mpr, "Can't create process: %s, %d", cmd, mprGetOsError()); } else { servicePid = (int) procInfo.hProcess; } restartCount++; } WaitForSingleObject(heartBeatEvent, heartBeatPeriod); if (servicePid) { if (GetExitCodeProcess((HANDLE) servicePid, (ulong*) &status)) { if (status != STILL_ACTIVE) { CloseHandle((HANDLE) servicePid); servicePid = 0; } } else { CloseHandle((HANDLE) servicePid); servicePid = 0; } } if (verbose) { mprPrintf(mpr, "%s has exited with status %d\n", serviceProgram, status); mprPrintf(mpr, "%s will be restarted in 10 seconds\n", serviceProgram); } } mprFree(homeDir); mprFree(serviceArgs); }
int MprSocket::write(char *buf, int bufsize) { #if BLD_FEATURE_IPV6 struct addrinfo hints, *res; struct sockaddr_storage server6; char port_string[MPR_MAX_IP_PORT]; int rc; #endif struct sockaddr_in server; struct sockaddr *sa; MprSocklen addrlen; int sofar, errCode, len, written; mprAssert(buf); mprAssert(bufsize >= 0); mprAssert((flags & MPR_SOCKET_CLOSED) == 0); addrlen = 0; sa = 0; lock(); if (flags & (MPR_SOCKET_BROADCAST | MPR_SOCKET_DATAGRAM)) { #if BLD_FEATURE_IPV6 if (ipv6) { memset((char *) &hints, '\0', sizeof(hints)); memset((char *) &server, '\0', sizeof(struct sockaddr_storage)); mprSprintf(port_string, sizeof(port_string), "%d", port); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; if (strcmp(ipAddr, "") == 0) { // Note that IPv6 does not support broadcast, there is no // 255.255.255.255 equiv. Multicast can be used over a specific // link, but the user must provide that address plus %scope_id. unlock(); return -1; } rc = getaddrinfo(ipAddr, port_string, &hints, &res); if (rc) { unlock(); return -1; } else { memcpy(&server, res->ai_addr, res->ai_addrlen); addrlen = res->ai_addrlen; freeaddrinfo(res); } sa = (struct sockaddr*) &server6; } else #endif { memset((char*) &server, '\0', sizeof(struct sockaddr_in)); addrlen = sizeof(struct sockaddr_in); server.sin_family = AF_INET; server.sin_port = htons((short) (port & 0xFFFF)); if (strcmp(ipAddr, "") != 0) { server.sin_addr.s_addr = inet_addr(ipAddr); } else { server.sin_addr.s_addr = INADDR_ANY; } sa = (struct sockaddr*) &server; } } if (flags & MPR_SOCKET_EOF) { sofar = bufsize; } else { errCode = 0; len = bufsize; sofar = 0; while (len > 0) { if ((flags & MPR_SOCKET_BROADCAST) || (flags & MPR_SOCKET_DATAGRAM)) { written = sendto(sock, &buf[sofar], len, MSG_NOSIGNAL, sa, addrlen); } else { written = send(sock, &buf[sofar], len, MSG_NOSIGNAL); } if (written < 0) { errCode = getError(); if (errCode == EINTR) { mprLog(8, log, "%d: write: EINTR\n", sock); continue; } else if (errCode == EAGAIN || errCode == EWOULDBLOCK) { mprLog(8, log, "%d: write: EAGAIN returning %d\n", sock, sofar); unlock(); return sofar; } mprLog(8, log, "%d: write: error %d\n", sock, -errCode); unlock(); return -errCode; } len -= written; sofar += written; } } mprLog(8, log, "%d: write: %d bytes, ask %d, flags %x\n", sock, sofar, bufsize, flags); unlock(); return sofar; }
int main(int argc, char *argv[]) { double elapsed; char *programName, *argp, *logSpec; int c, errflg, start; #if BLD_FEATURE_LOG MprLogToFile *logger; #endif #if BLD_FEATURE_MULTITHREAD MprThread *threadp; #endif programName = mprGetBaseName(argv[0]); method = "GET"; fileList = cmpDir = writeDir = 0; verbose = continueOnErrors = outputHeader = errflg = 0; poolThreads = 4; // Need at least one to run efficiently httpVersion = 1; // HTTP/1.1 success = 1; trace = 0; host = "localhost"; logSpec = "stdout:1"; postData = 0; postLen = 0; retries = MPR_HTTP_CLIENT_RETRIES; iterations = HTTP_DEFAULT_ITERATIONS; loadThreads = HTTP_DEFAULT_LOAD_THREADS; timeout = MPR_HTTP_CLIENT_TIMEOUT; #if BLD_FEATURE_MULTITHREAD mutex = new MprMutex(); #endif // // FUTURE: switch to GNU style --args with a better usage message // MprCmdLine cmdLine(argc, argv, "bC:cDd:f:Hh:i:l:M:mqo:r:st:T:vV:w:"); while ((c = cmdLine.next(&argp)) != EOF) { switch(c) { case 'b': benchmark++; break; case 'c': continueOnErrors++; break; case 'C': cmpDir = argp; break; case 'd': postData = argp; postLen = strlen(postData); break; case 'D': mprSetDebugMode(1); break; case 'f': fileList = argp; break; case 'h': host = argp; break; case 'H': outputHeader++; break; case 'i': iterations = atoi(argp); break; case 'l': logSpec = argp; break; case 'm': mprRequestMemStats(1); break; case 'M': method = argp; break; case 'o': timeout = atoi(argp); break; case 'q': quietMode++; break; case 'r': retries = atoi(argp); break; case 's': singleStep++; break; case 't': loadThreads = atoi(argp); break; case 'T': poolThreads = atoi(argp); break; case 'v': verbose++; trace++; break; case 'V': httpVersion = atoi(argp); break; case 'w': writeDir = argp; break; default: errflg++; break; } } if (writeDir && (loadThreads > 1)) { errflg++; } if (errflg) { mprFprintf(MPR_STDERR, "usage: %s [-bcHMmqsTv] [-C cmpDir] [-d postData] [-f fileList]\n" " [-i iterations] [-l logSpec] [-M method] [-o timeout]\n" " [-h host] [-r retries] [-t threads] [-T poolThreads]\n" " [-V httpVersion] [-w writeDir] [urls...]\n", programName); exit(2); } saveArgc = argc - cmdLine.firstArg(); saveArgv = &argv[cmdLine.firstArg()]; mpr = new Mpr(programName); #if BLD_FEATURE_LOG tMod = new MprLogModule("httpClient"); logger = new MprLogToFile(); mpr->addListener(logger); if (mpr->setLogSpec(logSpec) < 0) { mprFprintf(MPR_STDERR, "Can't open log file %s\n", logSpec); exit(2); } #endif // // Alternatively, set the configuration manually // mpr->setAppTitle("Embedthis HTTP Client"); #if BLD_FEATURE_MULTITHREAD mpr->setMaxPoolThreads(poolThreads); #endif // // Start the Timer, Socket and Pool services // if (mpr->start(MPR_SERVICE_THREAD) < 0) { mprError(MPR_L, MPR_USER, "Can't start MPR for %s", mpr->getAppTitle()); delete mpr; exit(2); } // // Create extra test threads to run the tests as required. We use // the main thread also (so start with j==1) // start = mprGetTime(0); #if BLD_FEATURE_MULTITHREAD activeLoadThreads = loadThreads; for (int j = 1; j < loadThreads; j++) { char name[64]; mprSprintf(name, sizeof(name), "t.%d", j - 1); threadp = new MprThread(doTests, MPR_NORMAL_PRIORITY, (void*) j, name); threadp->start(); } #endif doTests(0, 0); // // Wait for all the threads to complete (simple but effective). Keep // servicing events as we wind down. // while (activeLoadThreads > 1) { mprSleep(100); } if (benchmark && success) { elapsed = (mprGetTime(0) - start); if (fetchCount == 0) { elapsed = 0; fetchCount = 1; } mprPrintf("\tThreads %d, Pool Threads %d \t%13.2f\t%12.2f\t%6d\n", loadThreads, poolThreads, elapsed * 1000.0 / fetchCount, elapsed / 1000.0, fetchCount); mprPrintf("\nTime elapsed: %13.4f sec\n", elapsed / 1000.0); mprPrintf("Time per request: %13.4f sec\n", elapsed / 1000.0 / fetchCount); mprPrintf("Requests per second: %13.4f\n", fetchCount * 1.0 / (elapsed / 1000.0)); } if (! quietMode) { mprPrintf("\n"); } mpr->stop(0); #if BLD_FEATURE_MULTITHREAD delete mutex; #endif #if BLD_FEATURE_LOG delete tMod; #endif delete mpr; #if BLD_FEATURE_LOG delete logger; #endif mprMemClose(); return (success) ? 0 : 255; }
int MprSocket::openServer(char *addr, int portNum, MprSocketAcceptProc acceptFn, void *data, int initialFlags) { #if BLD_FEATURE_IPV6 struct addrinfo hints, *res; struct sockaddr_storage sockAddr6; char portNumString[MPR_MAX_IP_PORT]; char addrBuf[MPR_MAX_IP_ADDR]; char *bindName; #endif struct sockaddr_in sockAddr; struct sockaddr *sa; struct hostent *hostent; MprSocklen addrlen; int datagram, rc; mprAssert(addr); if (addr == 0 || *addr == '\0') { mprLog(6, log, "openServer: *:%d, flags %x\n", portNum, initialFlags); } else { mprLog(6, log, "openServer: %s:%d, flags %x\n", addr, portNum, initialFlags); } #if BLD_FEATURE_IPV6 if (addr[0] == '[') { ipv6 = 1; mprStrcpy(addrBuf, sizeof(addrBuf), &addr[1]); mprAssert(addrBuf[strlen(addrBuf) - 1] == ']'); addrBuf[strlen(addrBuf) - 1] = '\0'; addr = addrBuf; } if (ipv6) { memset((char *) &hints, '\0', sizeof(hints)); memset((char *) &sockAddr6, '\0', sizeof(struct sockaddr_storage)); mprSprintf(portNumString, sizeof(portNumString), "%d", portNum); hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_INET6; if (strcmp(addr, "") != 0) { bindName = addr; } else { bindName = NULL; hints.ai_flags |= AI_PASSIVE; /* Bind to 0.0.0.0 and :: */ /* Sets to IN6ADDR_ANY_INIT */ } rc = getaddrinfo(bindName, portNumString, &hints, &res); if (rc) { return MPR_ERR_CANT_OPEN; } sa = (struct sockaddr*) &sockAddr6; memcpy(sa, res->ai_addr, res->ai_addrlen); addrlen = res->ai_addrlen; freeaddrinfo(res); } else #endif { /* * TODO could we use getaddrinfo in all cases. ie. merge with IPV6 code */ memset((char *) &sockAddr, '\0', sizeof(struct sockaddr_in)); addrlen = sizeof(struct sockaddr_in); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons((short) (portNum & 0xFFFF)); if (strcmp(addr, "") != 0) { sockAddr.sin_addr.s_addr = inet_addr(addr); if (sockAddr.sin_addr.s_addr == INADDR_NONE) { hostent = mprGetHostByName(addr); if (hostent != 0) { memcpy((char*) &sockAddr.sin_addr, (char*) hostent->h_addr_list[0], (size_t) hostent->h_length); mprFreeGetHostByName(hostent); } else { return MPR_ERR_NOT_FOUND; } } } else { sockAddr.sin_addr.s_addr = INADDR_ANY; } sa = (struct sockaddr*) &sockAddr; } lock(); port = portNum; acceptCallback = acceptFn; acceptData = data; flags = (initialFlags & (MPR_SOCKET_BROADCAST | MPR_SOCKET_DATAGRAM | MPR_SOCKET_BLOCK | MPR_SOCKET_LISTENER | MPR_SOCKET_NOREUSE | MPR_SOCKET_NODELAY)); ipAddr = mprStrdup(addr); datagram = flags & MPR_SOCKET_DATAGRAM; // // Create the O/S socket // sock = socket(sa->sa_family, datagram ? SOCK_DGRAM: SOCK_STREAM, 0); if (sock < 0) { unlock(); return MPR_ERR_CANT_OPEN; } #if !WIN && !WINCE && !VXWORKS fcntl(sock, F_SETFD, FD_CLOEXEC); // Children won't inherit this fd #endif #if CYGWIN || LINUX || MACOSX || VXWORKS || FREEBSD if (!(flags & MPR_SOCKET_NOREUSE)) { rc = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &rc, sizeof(rc)); } #endif rc = bind(sock, sa, addrlen); // rc = bind(sock, res->ai_addr, res->ai_addrlen); if (rc < 0) { int err = errno; err = err; ::closesocket(sock); sock = -1; unlock(); return MPR_ERR_CANT_OPEN; } if (! datagram) { flags |= MPR_SOCKET_LISTENER; if (listen(sock, SOMAXCONN) < 0) { ::closesocket(sock); sock = -1; unlock(); return MPR_ERR_CANT_OPEN; } handler = new MprSelectHandler(sock, MPR_SOCKET_READABLE, (MprSelectProc) acceptProcWrapper, (void*) this, handlerPriority); } handlerMask |= MPR_SOCKET_READABLE; //TODO - what about WINCE? #if WIN // // Delay setting reuse until now so that we can be assured that we // have exclusive use of the port. // if (!(flags & MPR_SOCKET_NOREUSE)) { rc = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &rc, sizeof(rc)); } #endif setBlockingMode((bool) (flags & MPR_SOCKET_BLOCK)); // // TCP/IP stacks have the No delay option (nagle algorithm) on by default. // if (flags & MPR_SOCKET_NODELAY) { setNoDelay(1); } unlock(); return sock; }
int MprSocket::openClient(char *addr, int portNum, int initialFlags) { #if BLD_FEATURE_IPV6 struct addrinfo hints, *res; struct sockaddr_storage remoteAddr6; char portNum_string[MPR_MAX_IP_PORT]; char addrBuf[MPR_MAX_IP_ADDR]; #endif struct sockaddr_in remoteAddr; struct hostent *hostent; struct sockaddr *sa; MprSocklen addrlen; int broadcast, datagram, rc, err; mprLog(6, log, "openClient: %s:%d, flags %x\n", addr, portNum, initialFlags); #if BLD_FEATURE_IPV6 if (addr[0] == '[') { ipv6 = 1; mprStrcpy(addrBuf, sizeof(addr), &addr[1]); mprAssert(addrBuf[strlen(addrBuf) - 2] == ']'); addrBuf[strlen(addrBuf) - 2] = '\0'; addr = addrBuf; } else { ipv6 = 0; } if (ipv6) { memset((char*) &hints, '\0', sizeof(hints)); memset((char*) &remoteAddr6, '\0', sizeof(struct sockaddr_storage)); mprSprintf(portNum_string, sizeof(portNum_string), "%d", portNum); hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo(addr, portNum_string, &hints, &res); if (rc) { /* no need to unlock yet */ return MPR_ERR_CANT_OPEN; } sa = (struct sockaddr*) &remoteAddr6; memcpy(sa, res->ai_addr, res->ai_addrlen); addrlen = res->ai_addrlen; freeaddrinfo(res); } else #endif { memset((char *) &remoteAddr, '\0', sizeof(struct sockaddr_in)); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons((short) (portNum & 0xFFFF)); sa = (struct sockaddr*) &remoteAddr; addrlen = sizeof(remoteAddr); } lock(); port = portNum; flags = (initialFlags & (MPR_SOCKET_BROADCAST | MPR_SOCKET_DATAGRAM | MPR_SOCKET_BLOCK | MPR_SOCKET_LISTENER | MPR_SOCKET_NOREUSE | MPR_SOCKET_NODELAY)); // Save copy of the address ipAddr = mprStrdup(addr); #if BLD_FEATURE_IPV6 if (!ipv6) { // Nothing here } else #endif { remoteAddr.sin_addr.s_addr = inet_addr(ipAddr); if (remoteAddr.sin_addr.s_addr == INADDR_NONE) { hostent = mprGetHostByName(ipAddr); if (hostent != 0) { memcpy((char*) &remoteAddr.sin_addr, (char*) hostent->h_addr_list[0], (size_t) hostent->h_length); mprFreeGetHostByName(hostent); } else { unlock(); return MPR_ERR_NOT_FOUND; } } } broadcast = flags & MPR_SOCKET_BROADCAST; if (broadcast) { flags |= MPR_SOCKET_DATAGRAM; } datagram = flags & MPR_SOCKET_DATAGRAM; // // Create the O/S socket // sock = socket(sa->sa_family, datagram ? SOCK_DGRAM: SOCK_STREAM, 0); if (sock < 0) { err = getError(); unlock(); return -err; } #if !WIN && !WINCE && !VXWORKS fcntl(sock, F_SETFD, FD_CLOEXEC); // Children won't inherit this fd #endif if (broadcast) { int flag = 1; if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &flag, sizeof(flag)) < 0) { err = getError(); ::closesocket(sock); sock = -1; unlock(); return -err; } } if (!datagram) { flags |= MPR_SOCKET_CONNECTING; rc = connect(sock, sa, addrlen); if (rc < 0) { err = getError(); ::closesocket(sock); sock = -1; unlock(); #if UNUSED // // If the listen backlog is too high, ECONNREFUSED is returned // if (err == EADDRINUSE || err == ECONNREFUSED) { return MPR_ERR_BUSY; } #endif return -err; } } setBlockingMode((bool) (flags & MPR_SOCKET_BLOCK)); // // TCP/IP stacks have the No delay option (nagle algorithm) on by default. // if (flags & MPR_SOCKET_NODELAY) { setNoDelay(1); } unlock(); return sock; }
static void outputLine(MaQueue *q, MprDirEntry *ep, cchar *path, int nameSize) { MprPath info; Dir *dir; MprTime when; MaHost *host; char *newPath, sizeBuf[16], timeBuf[48], *icon; struct tm tm; bool isDir; int len; cchar *ext, *mimeType; char *dirSuffix; char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; dir = q->stage->stageData; if (ep->size >= (1024*1024*1024)) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024 * 1024 * 1024, "G"); } else if (ep->size >= (1024*1024)) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024 * 1024, "M"); } else if (ep->size >= 1024) { fmtNum(sizeBuf, sizeof(sizeBuf), (int) ep->size, 1024, "K"); } else { mprSprintf(sizeBuf, sizeof(sizeBuf), "%6d", (int) ep->size); } newPath = mprJoinPath(q, path, ep->name); if (mprGetPathInfo(q, newPath, &info) < 0) { when = mprGetTime(q); isDir = 0; } else { isDir = info.isDir ? 1 : 0; when = (MprTime) info.mtime * MPR_TICKS_PER_SEC; } mprFree(newPath); if (isDir) { icon = "folder"; dirSuffix = "/"; } else { host = q->conn->host; ext = mprGetPathExtension(q, ep->name); if ((mimeType = maLookupMimeType(host, ext)) != 0) { if (strcmp(ext, "es") == 0 || strcmp(ext, "ejs") == 0 || strcmp(ext, "php") == 0) { icon = "text"; } else if (strstr(mimeType, "text") != 0) { icon = "text"; } else { icon = "compressed"; } } else { icon = "compressed"; } dirSuffix = ""; } mprDecodeLocalTime(q, &tm, when); mprSprintf(timeBuf, sizeof(timeBuf), "%02d-%3s-%4d %02d:%02d", tm.tm_mday, months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour, tm.tm_min); len = (int) strlen(ep->name) + (int) strlen(dirSuffix); if (dir->fancyIndexing == 2) { maWrite(q, "<tr><td valign=\"top\">"); maWrite(q, "<img src=\"/icons/%s.gif\" alt=\"[ ]\", /></td>", icon); maWrite(q, "<td><a href=\"%s%s\">%s%s</a></td>", ep->name, dirSuffix, ep->name, dirSuffix); maWrite(q, "<td>%s</td><td>%s</td></tr>\r\n", timeBuf, sizeBuf); } else if (dir->fancyIndexing == 1) { maWrite(q, "<img src=\"/icons/%s.gif\" alt=\"[ ]\", /> ", icon); maWrite(q, "<a href=\"%s%s\">%s%s</a>%-*s %17s %4s\r\n", ep->name, dirSuffix, ep->name, dirSuffix, nameSize - len, "", timeBuf, sizeBuf); } else { maWrite(q, "<li><a href=\"%s%s\"> %s%s</a></li>\r\n", ep->name, dirSuffix, ep->name, dirSuffix); } }
/* * Sanitize args. Convert "/" to "\" and converting '\r' and '\n' to spaces, quote all args and put the program as argv[0]. */ static int sanitizeArgs(MprCmd *cmd, int argc, char **argv, char **env) { #if VXWORKS cmd->argv = argv; cmd->argc = argc; cmd->env = 0; #endif #if BLD_UNIX_LIKE char *cp; int index, i, hasPath, hasLibPath; cmd->argv = argv; cmd->argc = argc; cmd->env = 0; if (env) { for (i = 0; env && env[i]; i++) { mprLog(cmd, 6, "cmd: env[%d]: %s", i, env[i]); } if ((cmd->env = mprAlloc(cmd, (i + 3) * (int) sizeof(char*))) == NULL) { return MPR_ERR_NO_MEMORY; } hasPath = hasLibPath = 0; for (index = i = 0; env && env[i]; i++) { mprLog(cmd, 6, "cmd: env[%d]: %s", i, env[i]); if (strncmp(env[i], "PATH=", 5) == 0) { hasPath++; } else if (strncmp(env[i], LD_LIBRARY_PATH "=", 16) == 0) { hasLibPath++; } cmd->env[index++] = env[i]; } /* * Add PATH and LD_LIBRARY_PATH */ if (!hasPath && (cp = getenv("PATH")) != 0) { cmd->env[index++] = mprAsprintf(cmd, -1, "PATH=%s", cp); } if (!hasLibPath && (cp = getenv(LD_LIBRARY_PATH)) != 0) { cmd->env[index++] = mprAsprintf(cmd, -1, "%s=%s", LD_LIBRARY_PATH, cp); } cmd->env[index++] = '\0'; for (i = 0; i < argc; i++) { mprLog(cmd, 4, "cmd: arg[%d]: %s", i, argv[i]); } for (i = 0; cmd->env[i]; i++) { mprLog(cmd, 4, "cmd: env[%d]: %s", i, cmd->env[i]); } } #endif #if BLD_WIN_LIKE char *program, *SYSTEMROOT, **ep, **ap, *destp, *cp, *progBuf, *localArgv[2], *saveArg0, *PATH, *endp; int i, len, hasPath, hasSystemRoot; mprAssert(argc > 0 && argv[0] != NULL); cmd->argv = argv; cmd->argc = argc; program = argv[0]; progBuf = mprAlloc(cmd, (int) strlen(program) * 2 + 1); strcpy(progBuf, program); program = progBuf; for (cp = program; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } else if (*cp == '\r' || *cp == '\n') { *cp = ' '; } } if (*program == '\"') { if ((cp = strrchr(++program, '"')) != 0) { *cp = '\0'; } } if (argv == 0) { argv = localArgv; argv[1] = 0; saveArg0 = program; } else { saveArg0 = argv[0]; } /* * Set argv[0] to the program name while creating the command line. Restore later */ argv[0] = program; /* * Determine the command line length and arg count */ argc = 0; for (len = 0, ap = argv; *ap; ap++) { len += (int) strlen(*ap) + 1 + 2; /* Space and possible quotes */ argc++; } cmd->command = (char*) mprAlloc(cmd, len + 1); cmd->command[len] = '\0'; /* * Add quotes to all args that have spaces in them including "program" */ destp = cmd->command; for (ap = &argv[0]; *ap; ) { cp = *ap; if ((strchr(cp, ' ') != 0) && cp[0] != '\"') { *destp++ = '\"'; strcpy(destp, cp); destp += strlen(cp); *destp++ = '\"'; } else { strcpy(destp, cp); destp += strlen(cp); } if (*++ap) { *destp++ = ' '; } } *destp = '\0'; argv[0] = saveArg0; for (i = 0; i < argc; i++) { mprLog(cmd, 4, "cmd: arg[%d]: %s", i, argv[i]); } /* * Now work on the environment. Windows has a block of null separated strings with a trailing null. */ cmd->env = 0; if (env) { for (hasSystemRoot = hasPath = len = 0, ep = env; ep && *ep; ep++) { len += (int) strlen(*ep) + 1; if (strncmp(*ep, "PATH=", 5) == 0) { hasPath++; } else if (strncmp(*ep, "SYSTEMROOT=", 11) == 0) { hasSystemRoot++; } } if (!hasSystemRoot && (SYSTEMROOT = getenv("SYSTEMROOT")) != 0) { len += 11 + (int) strlen(SYSTEMROOT) + 1; } if (!hasPath && (PATH = getenv("PATH")) != 0) { len += 5 + (int) strlen(PATH) + 1; } len += 2; /* Windows requires 2 nulls for the block end */ destp = (char*) mprAlloc(cmd, len); endp = &destp[len]; cmd->env = (char**) destp; for (ep = env; ep && *ep; ep++) { mprLog(cmd, 4, "cmd: env[%d]: %s", i, *ep); strcpy(destp, *ep); mprLog(cmd, 7, "cmd: Set env variable: %s", destp); destp += strlen(*ep) + 1; } if (!hasSystemRoot) { mprSprintf(destp, endp - destp - 1, "SYSTEMROOT=%s", SYSTEMROOT); destp += 12 + strlen(SYSTEMROOT); } if (!hasPath) { mprSprintf(destp, endp - destp - 1, "PATH=%s", PATH); destp += 6 + strlen(PATH); } *destp++ = '\0'; *destp++ = '\0'; /* Windows requires two nulls */ mprAssert(destp <= endp); #if TEST for (cp = (char*) cmd->env; *cp; cp++) { print("ENV %s\n", cp); cp += strlen(cp); } #endif } #endif /* BLD_WIN_LIKE */ return 0; }
/* Build the command arguments. NOTE: argv is untrusted input. */ static void buildArgs(MaConn *conn, MprCmd *cmd, int *argcp, char ***argvp) { MaRequest *req; MaResponse *resp; char *fileName, **argv, status[8], *indexQuery, *cp, *tok; cchar *actionProgram; int argc, argind, len; req = conn->request; resp = conn->response; fileName = resp->filename; mprAssert(fileName); actionProgram = 0; argind = 0; argc = *argcp; if (resp->extension) { actionProgram = maGetMimeActionProgram(req->host, resp->extension); if (actionProgram != 0) { argc++; } } /* This is an Apache compatible hack for PHP 5.3 */ mprItoa(status, sizeof(status), MPR_HTTP_CODE_MOVED_TEMPORARILY, 10); mprAddHash(req->headers, "REDIRECT_STATUS", mprStrdup(req, status)); /* Count the args for ISINDEX queries. Only valid if there is not a "=" in the query. If this is so, then we must not have these args in the query env also? */ indexQuery = req->parsedUri->query; if (indexQuery && !strchr(indexQuery, '=')) { argc++; for (cp = indexQuery; *cp; cp++) { if (*cp == '+') { argc++; } } } else { indexQuery = 0; } #if BLD_WIN_LIKE || VXWORKS { char *bangScript, *cmdBuf, *program, *cmdScript; /* On windows we attempt to find an executable matching the fileName. We look for *.exe, *.bat and also do unix style processing "#!/program" */ findExecutable(conn, &program, &cmdScript, &bangScript, fileName); mprAssert(program); if (cmdScript) { /* Cmd/Batch script (.bat | .cmd) Convert the command to the form where there are 4 elements in argv that cmd.exe can interpret. argv[0] = cmd.exe argv[1] = /Q argv[2] = /C argv[3] = ""script" args ..." */ argc = 4; len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); argv[argind++] = program; /* Duped in findExecutable */ argv[argind++] = mprStrdup(cmd, "/Q"); argv[argind++] = mprStrdup(cmd, "/C"); len = (int) strlen(cmdScript) + 2 + 1; cmdBuf = (char*) mprAlloc(cmd, len); mprSprintf(cmdBuf, len, "\"%s\"", cmdScript); argv[argind++] = cmdBuf; mprSetCmdDir(cmd, cmdScript); mprFree(cmdScript); /* program will get freed when argv[] gets freed */ } else if (bangScript) { /* Script used "#!/program". NOTE: this may be overridden by a mime Action directive. */ argc++; /* Adding bangScript arg */ len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); argv[argind++] = program; /* Will get freed when argv[] is freed */ argv[argind++] = bangScript; /* Will get freed when argv[] is freed */ mprSetCmdDir(cmd, bangScript); } else { /* Either unknown extension or .exe (.out) program. */ len = (argc + 1) * sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); if (actionProgram) { argv[argind++] = mprStrdup(cmd, actionProgram); } argv[argind++] = program; } } #else len = (argc + 1) * (int) sizeof(char*); argv = (char**) mprAlloc(cmd, len); memset(argv, 0, len); if (actionProgram) { argv[argind++] = mprStrdup(cmd, actionProgram); } argv[argind++] = mprStrdup(cmd, fileName); #endif /* ISINDEX queries. Only valid if there is not a "=" in the query. If this is so, then we must not have these args in the query env also? */ if (indexQuery) { indexQuery = mprStrdup(cmd, indexQuery); cp = mprStrTok(indexQuery, "+", &tok); while (cp) { argv[argind++] = mprEscapeCmd(resp, mprUrlDecode(resp, cp), 0); cp = mprStrTok(NULL, "+", &tok); } } mprAssert(argind <= argc); argv[argind] = 0; *argcp = argc; *argvp = argv; }
/* * Create the host addresses for a host. Called for hosts or for NameVirtualHost directives (host == 0). */ int maCreateHostAddresses(MaServer *server, MaHost *host, cchar *configValue) { MaListen *listen; MaHostAddress *address; char *ipAddrPort, *ipAddr, *value, *tok; char addrBuf[MPR_MAX_IP_ADDR_PORT]; int next, port; address = 0; value = mprStrdup(server, configValue); ipAddrPort = mprStrTok(value, " \t", &tok); while (ipAddrPort) { if (mprStrcmpAnyCase(ipAddrPort, "_default_") == 0) { mprAssert(0); ipAddrPort = "*:*"; } if (mprParseIp(server, ipAddrPort, &ipAddr, &port, -1) < 0) { mprError(server, "Can't parse ipAddr %s", ipAddrPort); continue; } mprAssert(ipAddr && *ipAddr); if (ipAddr[0] == '*') { ipAddr = mprStrdup(server, ""); } /* * For each listening endpiont, */ for (next = 0; (listen = mprGetNextItem(server->listens, &next)) != 0; ) { if (port > 0 && port != listen->port) { continue; } if (listen->ipAddr[0] != '\0' && ipAddr[0] != '\0' && strcmp(ipAddr, listen->ipAddr) != 0) { continue; } /* * Find the matching host address or create a new one */ if ((address = maLookupHostAddress(server, listen->ipAddr, listen->port)) == 0) { address = maCreateHostAddress(server, listen->ipAddr, listen->port); mprAddItem(server->hostAddresses, address); } /* * If a host is specified */ if (host == 0) { maSetNamedVirtualHostAddress(address); } else { maInsertVirtualHost(address, host); if (listen->ipAddr[0] != '\0') { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", listen->ipAddr, listen->port); } else { mprSprintf(addrBuf, sizeof(addrBuf), "%s:%d", ipAddr, listen->port); } maSetHostName(host, addrBuf); } } mprFree(ipAddr); ipAddrPort = mprStrTok(0, " \t", &tok); } if (host) { if (address == 0) { mprError(server, "No valid IP address for host %s", host->name); mprFree(value); return MPR_ERR_CANT_INITIALIZE; } if (maIsNamedVirtualHostAddress(address)) { maSetNamedVirtualHost(host); } } mprFree(value); return 0; }
static int fetch(MaClient *client, char *method, char *url, char *data, int len) { struct stat sbuf; FILE *fp; MaUrl *parsedUrl; char *header, *content, *diffBuf, *msg; char path[MPR_MAX_PATH], dir[MPR_MAX_PATH], urlBuf[MPR_HTTP_MAX_URL]; char tmp[MPR_MAX_PATH]; int i, code, rc, contentLen, mark, elapsed, c; fp = 0; lock(); fetchCount++; unlock(); if (url == 0) { return MPR_ERR_BAD_ARGS; } if (*url == '/') { mprSprintf(urlBuf, sizeof(urlBuf), "http://127.0.0.1%s", url); url = urlBuf; } else if ((strstr(url, "http://")) == 0) { mprSprintf(urlBuf, sizeof(urlBuf), "http://%s", url); url = urlBuf; } mprLog(MPR_DEBUG, tMod, "fetch: %s %s\n", method, url); mark = mprGetTime(0); if (mprStrCmpAnyCase(method, "GET") == 0) { rc = client->getRequest(url); } else if (mprStrCmpAnyCase(method, "HEAD") == 0) { rc = client->headRequest(url); } else if (mprStrCmpAnyCase(method, "OPTIONS") == 0) { rc = client->optionsRequest(url); } else if (mprStrCmpAnyCase(method, "POST") == 0) { rc = client->postRequest(url, data, len); } else if (mprStrCmpAnyCase(method, "TRACE") == 0) { rc = client->traceRequest(url); } if (rc < 0) { return MPR_ERR_CANT_OPEN; } code = client->getResponseCode(); content = client->getResponseContent(&contentLen); header = client->getResponseHeader(); msg = client->getResponseMessage(); elapsed = mprGetTime(0) - mark; if (code == 200 || code == 302) { mprLog(6, tMod, "Response code %d, content len %d, header: \n%s\n", code, contentLen, header); } else { mprLog(2, tMod, "Response code %d, content len %d, header: \n%s\n%s", code, contentLen, header, content); mprError(MPR_L, MPR_USER, "Can't retrieve \"%s\" (%d), %s", url, code, msg); return MPR_ERR_CANT_READ; } if (cmpDir) { client->getParsedUrl(&parsedUrl); mprSprintf(path, sizeof(path), "%s%s", cmpDir, parsedUrl->uri); if (path[strlen(path) - 1] == '/') { path[strlen(path) - 1] = '\0'; } if (stat(path, &sbuf) < 0) { mprError(MPR_L, MPR_USER, "Can't access %s", path); return MPR_ERR_CANT_ACCESS; } if (sbuf.st_mode & S_IFDIR) { strcpy(tmp, path); mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp); } if (stat(path, &sbuf) < 0) { mprError(MPR_L, MPR_USER, "Can't access %s", path); return MPR_ERR_CANT_ACCESS; } if ((int) sbuf.st_size != contentLen) { mprError(MPR_L, MPR_USER, "Failed comparison for %s" "ContentLen %d, size %d\n", url, contentLen, sbuf.st_size); return MPR_ERR_CANT_ACCESS; } if ((fp = fopen(path, "r" MPR_BINARY)) == 0) { mprError(MPR_L, MPR_USER, "Can't open %s", path); return MPR_ERR_CANT_OPEN; } diffBuf = (char*) mprMalloc(contentLen); if ((int) fread(diffBuf, 1, contentLen, fp) != contentLen) { mprError(MPR_L, MPR_USER, "Can't read content from %s", path); return MPR_ERR_CANT_READ; } for (i = 0; i < contentLen; i++) { if (diffBuf[i] != content[i]) { mprError(MPR_L, MPR_USER, "Failed comparison for %s" "At byte %d: %x vs %x\n", i, (uchar) diffBuf[i], (uchar) content[i]); return MPR_ERR_GENERAL; } } fclose(fp); mprFree(diffBuf); } if (writeDir) { client->getParsedUrl(&parsedUrl); mprSprintf(path, sizeof(path), "%s%s", writeDir, parsedUrl->uri); if (path[strlen(path) - 1] == '/') { path[strlen(path) - 1] = '\0'; } mprGetDirName(dir, sizeof(dir), path); mprMakeDir(dir); if (stat(path, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) { strcpy(tmp, path); mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp); } if ((fp = fopen(path, "w" MPR_BINARY)) == 0) { mprError(MPR_L, MPR_USER, "Can't open %s", path); return MPR_ERR_CANT_OPEN; } if (outputHeader) { if (fputs(header, fp) != EOF) { mprError(MPR_L, MPR_USER, "Can't write header to %s", path); return MPR_ERR_CANT_WRITE; } fputc('\n', fp); } if ((int) fwrite(content, 1, contentLen, fp) != contentLen) { mprError(MPR_L, MPR_USER, "Can't write content to %s", path); return MPR_ERR_CANT_WRITE; } fclose(fp); } lock(); if (trace) { if (strstr(url, "http://") != 0) { url += 7; } if ((fetchCount % 100) == 1) { if (fetchCount == 1 || (fetchCount % 2500) == 1) { if (fetchCount > 1) { mprPrintf("\n"); } mprPrintf( " Count Fd Thread Op Code Bytes Time Url\n"); } mprPrintf("%8d %4d %7s %4s %5d %7d %5.2f %s\n", fetchCount - 1, client->getFd(), #if BLD_FEATURE_MULTITHREAD mprGetCurrentThreadName(), #else "", #endif method, code, contentLen, elapsed / 1000.0, url); } } if (outputHeader) { mprPrintf("%s\n", header); } if (!quietMode) { for (i = 0; i < contentLen; i++) { if (!isprint((uchar) content[i]) && content[i] != '\n' && content[i] != '\r' && content[i] != '\t') { break; } } if (contentLen > 0) { if (i != contentLen && 0) { mprPrintf("Content has non-printable data\n"); } else { // mprPrintf("Length of content %d\n", contentLen); for (i = 0; i < contentLen; i++) { c = (uchar) content[i]; if (isprint((uchar) c) || isspace((uchar) c)) { putchar(content[i]); } else { mprPrintf("0x%x", c); } } fflush(stdout); } } } unlock(); if (singleStep) { mprPrintf("Pause: "); read(0, (char*) &rc, 1); } return 0; }
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; }
int MaHost::mapToStorage(MaRequest *rq, char *path, int pathLen, char *uri, int flags) { MaAlias *ap; MaDir *dir; char urlBuf[MPR_HTTP_MAX_URL]; char *base, *aliasName, *prefix; int len, redirectCode, prefixLen; mprAssert(path); mprAssert(pathLen > 0); *path = '\0'; lock(); // // FUTURE - Could optimize by having a hash lookup for alias prefixes. // ap = (MaAlias*) aliases.getFirst(); while (ap) { aliasName = ap->getName(); prefix = ap->getPrefix(); prefixLen = ap->getPrefixLen(); // // Note that for Aliases with redirects, the aliasName is a URL and // not a document path. // if (strncmp(prefix, uri, prefixLen) == 0) { redirectCode = ap->getRedirectCode(); if (redirectCode) { if (flags & MPR_HTTP_REDIRECT) { rq->redirect(redirectCode, aliasName); rq->flushOutput(MPR_HTTP_FOREGROUND_FLUSH, MPR_HTTP_FINISH_REQUEST); } else { mprStrcpy(path, pathLen, aliasName); } unlock(); return 0; } base = &uri[prefixLen]; while (*base == '/') { base++; } if (aliasName[strlen(aliasName) - 1] == '/') { len = mprSprintf(path, pathLen, "%s%s", aliasName, base); } else if (*base) { len = mprSprintf(path, pathLen, "%s/%s", aliasName, base); } else { len = mprStrcpy(path, pathLen, aliasName); } dir = 0; if (*base != '\0') { // // There was some extra URI past the matching alias prefix // portion // #if WIN // // Windows will ignore trailing "." and " ". We must reject // here as the URL probably won't match due to the trailing // character and the copyHandler will return the unprocessed // content to the user. Bad. // int lastc = base[strlen(base) - 1]; if (lastc == '.' || lastc == ' ') { unlock(); return MPR_ERR_CANT_ACCESS; } #endif unlock(); return 0; } else { if (*prefix == '\0') { prefix = "/"; } // // The URL matched the alias exactly so we change the URI // to match the prefix as we may have changed the extension // mprStrcpy(urlBuf, sizeof(urlBuf), prefix); MaUrl *url = rq->getUrl(); if (strcmp(urlBuf, url->uri) != 0) { if (url->query && *url->query) { mprStrcat(urlBuf, sizeof(urlBuf), "?", url->query, (void*) 0); } if (flags & MPR_HTTP_REMATCH) { rq->setUri(urlBuf); rq->parseUri(); } } } if (flags & MPR_HTTP_REMATCH) { rq->deleteHandlers(); } unlock(); return 0; } ap = (MaAlias*) aliases.getNext(ap); } unlock(); return MPR_ERR_NOT_FOUND; }
static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) { EspParse parse; char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME]; char *incBuf, *incText; int state, tid, len, rc, maxScriptSize, incSize; mprAssert(ep); mprAssert(jsBuf); mprAssert(input); rc = 0; len = 0; state = ESP_STATE_BEGIN; if (errMsg) { *errMsg = 0; } memset(&parse, 0, sizeof(parse)); parse.token = (char*) mprMalloc(ESP_TOK_INCR); if (parse.token == 0) { return MPR_ERR_CANT_ALLOCATE; } parse.token[0] = '\0'; parse.tokLen = ESP_TOK_INCR; parse.endp = &parse.token[parse.tokLen - 1]; parse.tokp = parse.token; parse.inBuf = input; parse.inp = parse.inBuf; maxScriptSize = esp->maxScriptSize; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && len >= 0) { switch (tid) { default: case ESP_TOK_ERR: mprFree(parse.token); return MPR_ERR_BAD_SYNTAX; case ESP_TOK_LITERAL: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"", parse.token, "\");\n", (void*) 0); break; case ESP_TOK_ATAT: /* * Trick to get undefined variables to evaluate to "". * Catenate with "" to cause toString to run. */ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); break; case ESP_TOK_EQUALS: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); state = ESP_STATE_IN_ESP_TAG; break; case ESP_TOK_START_ESP: state = ESP_STATE_IN_ESP_TAG; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && tid != ESP_TOK_END_ESP && len >= 0) { len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, parse.token, (void*) 0); tid = getEspToken(state, &parse); } state = ESP_STATE_BEGIN; break; case ESP_TOK_END_ESP: state = ESP_STATE_BEGIN; break; case ESP_TOK_INCLUDE: if (parse.token[0] == '/') { mprStrcpy(incPath, sizeof(incPath), parse.token); } else { mprGetDirName(dir, sizeof(dir), ep->uri); mprSprintf(incPath, sizeof(incPath), "%s/%s", dir, parse.token); } if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), incPath, 0) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't find include file: %s", path); rc = MPR_ERR_CANT_OPEN; break; } if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't read include file: %s", path); rc = MPR_ERR_CANT_READ; break; } incText[incSize] = '\0'; /* * Recurse and process the include script */ incBuf = 0; if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) { mprFree(incText); mprFree(parse.token); return rc; } len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, (void*) 0); mprFree(incText); mprFree(incBuf); state = ESP_STATE_IN_ESP_TAG; break; } tid = getEspToken(state, &parse); } mprFree(parse.token); if (len < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Script token is too big in %s.\nConfigured maximum is %d.", path, maxScriptSize); return MPR_ERR_WONT_FIT; } return rc; }
int MaClient::sendCore(char *method, char *requestUrl, char *postData, int postLen) { char abuf[MPR_HTTP_MAX_PASS * 2], encDetails[MPR_HTTP_MAX_PASS * 2]; char *host; int port, len, rc, nbytes; mprAssert(requestUrl && *requestUrl); lock(); reset(); mprLog(3, tMod, "sendCore: %s %s\n", method, requestUrl); this->method = mprStrdup(method); timestamp = mprGetTime(0); if (timeoutPeriod < 0) { timeoutPeriod = MPR_HTTP_CLIENT_TIMEOUT; } if (timeoutPeriod > 0) { if (!mprGetDebugMode()) { timer = new MprTimer(MPR_HTTP_TIMER_PERIOD, timeoutWrapper, (void *) this); } } if (*requestUrl == '/') { url.parse(requestUrl); host = (proxyHost) ? proxyHost : defaultHost; port = (proxyHost) ? proxyPort : defaultPort; } else { url.parse(requestUrl); host = (proxyHost) ? proxyHost : url.host; port = (proxyHost) ? proxyPort : url.port; } if (sock) { if (port != currentPort || strcmp(host, currentHost) != 0) { // // This request is for a different host or port. Must close socket. // sock->close(0); sock->dispose(); sock = 0; } } if (sock == 0) { sock = new MprSocket(); mprLog(3, tMod, "Opening new socket on: %s:%d\n", host, port); rc = sock->openClient(host, port, MPR_SOCKET_NODELAY); if (rc < 0) { mprLog(MPR_ERROR, tMod, "Can't open socket on %s:%d, %d\n", host, port, rc); unlock(); sock->dispose(); sock = 0; return rc; } sock->setBufSize(-1, MPR_HTTP_CLIENT_BUFSIZE); currentHost = mprStrdup(host); currentPort = port; } else { mprLog(3, tMod, "Reusing Keep-Alive socket on: %s:%d\n", host, port); } // // Remove this flush when pipelining is supported // inBuf->flush(); fd = sock->getFd(); if (proxyHost && *proxyHost) { if (url.query && *url.query) { outBuf->putFmt("%s http://%s:%d%s?%s HTTP/1.1\r\n", method, proxyHost, proxyPort, url.uri, url.query); } else { outBuf->putFmt("%s http://%s:%d%s HTTP/1.1\r\n", method, proxyHost, proxyPort, url.uri); } } else { if (url.query && *url.query) { outBuf->putFmt("%s %s?%s HTTP/1.1\r\n", method, url.uri, url.query); } else { outBuf->putFmt("%s %s HTTP/1.1\r\n", method, url.uri); } } if (serverAuthType) { if (strcmp(serverAuthType, "basic") == 0) { mprSprintf(abuf, sizeof(abuf), "%s:%s", user, password); maEncode64(encDetails, sizeof(encDetails), abuf); outBuf->putFmt("Authorization: %s %s\r\n", serverAuthType, encDetails); #if BLD_FEATURE_DIGEST } else if (strcmp(serverAuthType, "digest") == 0) { char a1Buf[256], a2Buf[256], digestBuf[256]; char *ha1, *ha2, *digest, *qop; authNc++; if (secret == 0) { if (createSecret() < 0) { mprLog(MPR_ERROR, tMod, "Can't create secret\n"); return MPR_ERR_CANT_INITIALIZE; } } mprFree(authCnonce); maCalcNonce(&authCnonce, secret, 0, realm); mprSprintf(a1Buf, sizeof(a1Buf), "%s:%s:%s", user, realm, password); ha1 = maMD5(a1Buf); mprSprintf(a2Buf, sizeof(a2Buf), "%s:%s", method, url.uri); ha2 = maMD5(a2Buf); qop = (serverQop) ? serverQop : (char*) ""; if (mprStrCmpAnyCase(serverQop, "auth") == 0) { mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%08x:%s:%s:%s", ha1, serverNonce, authNc, authCnonce, serverQop, ha2); } else if (mprStrCmpAnyCase(serverQop, "auth-int") == 0) { mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%08x:%s:%s:%s", ha1, serverNonce, authNc, authCnonce, serverQop, ha2); } else { qop = ""; mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%s", ha1, serverNonce, ha2); } mprFree(ha1); mprFree(ha2); digest = maMD5(digestBuf); if (*qop == '\0') { outBuf->putFmt("Authorization: Digest " "username=\"%s\", realm=\"%s\", nonce=\"%s\", " "uri=\"%s\", response=\"%s\"\r\n", user, realm, serverNonce, url.uri, digest); } else if (strcmp(qop, "auth") == 0) { outBuf->putFmt("Authorization: Digest " "username=\"%s\", realm=\"%s\", domain=\"%s\", " "algorithm=\"MD5\", qop=\"%s\", cnonce=\"%s\", " "nc=\"%08x\", nonce=\"%s\", opaque=\"%s\", " "stale=\"FALSE\", uri=\"%s\", response=\"%s\"\r\n", user, realm, serverDomain, serverQop, authCnonce, authNc, serverNonce, serverOpaque, url.uri, digest); } else if (strcmp(qop, "auth-int") == 0) { ; } mprFree(digest); #endif // BLD_FEATURE_HTTP_DIGEST } } outBuf->putFmt("Host: %s\r\n", host); outBuf->putFmt("User-Agent: %s\r\n", MPR_HTTP_CLIENT_NAME); if (userFlags & MPR_HTTP_KEEP_ALIVE) { outBuf->putFmt("Connection: Keep-Alive\r\n"); } else { outBuf->putFmt("Connection: close\r\n"); } if (postLen > 0) { outBuf->putFmt("Content-Length: %d\r\n", postLen); } if (postData) { outBuf->putFmt("Content-Type: application/x-www-form-urlencoded\r\n"); } if (userHeaders) { outBuf->put(userHeaders); } outBuf->put("\r\n"); outBuf->addNull(); // // Flush to the socket with any post data. Writes can fail because the // server prematurely closes a keep-alive connection. // len = outBuf->getLength(); if ((rc = sock->write(outBuf->getStart(), len)) != len) { flags |= MPR_HTTP_TERMINATED; unlock(); mprLog(MPR_ERROR, tMod, "Can't write to socket on %s:%d, %d\n", host, port, rc); return rc; } #if BLD_DEBUG mprLog(3, MPR_RAW, tMod, "Request >>>>\n%s\n", outBuf->getStart()); #endif if (postData) { sock->setBlockingMode(1); for (len = 0; len < postLen; ) { nbytes = postLen - len; rc = sock->write(&postData[len], nbytes); #if BLD_DEBUG mprLog(3, MPR_RAW, tMod, "POST DATA %s\n", &postData[len]); #endif if (rc < 0) { unlock(); mprLog(MPR_ERROR, tMod, "Can't write post data to socket on %s:%d, %d\n", host, port, rc); flags |= MPR_HTTP_TERMINATED; sock->dispose(); sock = 0; return rc; } len += rc; } sock->setBlockingMode(0); } sock->setCallback(readEventWrapper, (void*) this, 0, MPR_READABLE); // // If no callback, then we must block // if (callback == 0) { unlock(); while (state != MPR_HTTP_CLIENT_DONE) { // // If multithreaded and the events thread is not yet running, // we still want to work. // #if BLD_FEATURE_MULTITHREAD if (mprGetMpr()->isRunningEventsThread() && mprGetMpr()->poolService->getMaxPoolThreads() > 0) { completeCond->waitForCond(250); } else #endif mprGetMpr()->serviceEvents(1, 100); } } else { unlock(); } return 0; }
static void doTests(void *data, void *threadp) #endif { MprBuf post; FILE *fp; MaClient *client; char urlBuf[4096], urlBuf2[4096]; char postBuf[4096]; char *cp, *operation, *url, *tok; int rc, j, line; fp = 0; client = new MaClient(); client->setTimeout(timeout); client->setRetries(retries); if (httpVersion == 0) { client->setKeepAlive(0); } post.setBuf(MPR_HTTP_CLIENT_BUFSIZE, MPR_HTTP_MAX_BODY); while (!mpr->isExiting() && success) { lock(); if (fetchCount >= iterations) { unlock(); break; } unlock(); rc = 0; for (j = 0; j < saveArgc; j++) { url = saveArgv[j]; if (*url == '/') { mprSprintf(urlBuf2, sizeof(urlBuf2), "%s%s", host, url); url = urlBuf2; } rc = fetch(client, method, url, postData, postLen); if (rc < 0 && !continueOnErrors) { success = 0; goto commonExit; } } if (fileList == 0) { continue; } fp = fopen(fileList, "rt"); if (fp == 0) { mprError(MPR_L, MPR_USER, "Can't open %s", fileList); goto commonExit; } line = 0; while (fgets(urlBuf, sizeof(urlBuf), fp) != NULL && !mpr->isExiting()) { lock(); if (fetchCount >= iterations) { unlock(); break; } unlock(); if ((cp = strchr(urlBuf, '\n')) != 0) { *cp = '\0'; } operation = mprStrTok(urlBuf, " \t\n", &tok); url = mprStrTok(0, " \t\n", &tok); if (*url == '/') { mprSprintf(urlBuf2, sizeof(urlBuf2), "%s%s", host, url); url = urlBuf2; } if (strcmp(operation, "GET") == 0) { rc = fetch(client, operation, url, postData, postLen); } else if (strcmp(operation, "HEAD") == 0) { rc = fetch(client, operation, url, postData, postLen); } else if (strcmp(operation, "POST") == 0) { while (fgets(postBuf, sizeof(postBuf), fp) != NULL) { if (postBuf[0] != '\t') { break; } if (strlen(postBuf) == 1) { break; } post.put((uchar*) &postBuf[1], strlen(postBuf) - 2); post.addNull(); if (post.getLength() >= (MPR_HTTP_MAX_BODY - 1)) { mprError(MPR_L, MPR_USER, "Bad post data on line %d", line); if (!continueOnErrors) { success = 0; fclose(fp); fp = 0; goto commonExit; } } } if (post.getLength() > 0) { rc = fetch(client, operation, url, post.getStart(), post.getLength()); } else { rc = fetch(client, operation, url, postBuf, postLen); } post.flush(); } else { rc = -1; mprError(MPR_L, MPR_USER, "Bad operation on line %d", line); } if (rc < 0 && !continueOnErrors) { success = 0; fclose(fp); fp = 0; goto commonExit; } } fclose(fp); fp = 0; } commonExit: #if BLD_FEATURE_MULTITHREAD if (threadp) { lock(); activeLoadThreads--; unlock(); } #endif delete client; }
int MprLogService::setLogSpec(char *fileSpec) { MprLogModule *mp; MprLogListener *lp; char namBuf[MPR_MAX_FNAME]; char *spec, *cp, *sizeStr; int maxSize; mprAssert(!logging); #if BLD_FEATURE_MULTITHREAD if (mutex == 0) { mutex = new MprMutex(); } #endif lock(); logging = 1; if (fileSpec == NULL || *fileSpec == '\0') { fileSpec = "trace.txt"; } logSpec = mprStrdup(fileSpec); spec = mprStrdup(fileSpec); for (cp = spec; *cp; cp++) { if (*cp == ':' && isdigit(cp[1])) { break; } } maxSize = MPR_MAX_LOG_SIZE; if (*cp) { *cp++ = '\0'; moduleSpecs = strchr(cp, ','); sizeStr = strchr(cp, '.'); if (sizeStr != 0) { *sizeStr++ = '\0'; maxSize = atoi(sizeStr); // Size in MB } // // Set all modules to the default trace level and then examine // the modules spec to override specified modules // defaultLevel = atoi(cp); if (defaultLevel < 0) { defaultLevel = 0; } mp = (MprLogModule*) moduleList.getFirst(); while (mp) { mp->setLevel(defaultLevel); mp = (MprLogModule*) moduleList.getNext(mp); } if (moduleSpecs) { moduleSpecs++; mp = (MprLogModule*) moduleList.getFirst(); while (mp) { mprSprintf(namBuf, sizeof(namBuf), "%s:", mp->getName()); if ((cp = strstr(moduleSpecs, namBuf)) != 0) { if ((cp = strchr(cp, ':')) != 0) { mp->setLevel(atoi(++cp)); } } mp = (MprLogModule*) moduleList.getNext(mp); } } } if (spec != 0 && *spec != '\0') { lp = (MprLogListener*) listeners.getFirst(); while (lp) { if (lp->setLogSpec(spec, maxSize) < 0) { mprFree(spec); unlock(); return MPR_ERR_CANT_OPEN; } lp = (MprLogListener*) listeners.getNext(lp); } } mprFree(spec); unlock(); return 0; }
void Mpr::writeToOsLog(char *message, int flags) { HKEY hkey; void *event; long errorType; char buf[MPR_MAX_STRING], msg[MPR_MAX_STRING]; char logName[MPR_MAX_STRING]; char *lines[9]; char *cp, *value; int type; ulong exists; static int once = 0; mprStrcpy(buf, sizeof(buf), message); cp = &buf[strlen(buf) - 1]; while (*cp == '\n' && cp > buf) { *cp-- = '\0'; } if (flags & MPR_INFO) { type = EVENTLOG_INFORMATION_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s information: ", Mpr::getAppName()); } else if (flags == MPR_WARN) { type = EVENTLOG_WARNING_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s warning: ", Mpr::getAppName()); } else { type = EVENTLOG_ERROR_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s error: %d", Mpr::getAppName(), GetLastError()); } lines[0] = msg; lines[1] = buf; lines[2] = lines[3] = lines[4] = lines[5] = 0; lines[6] = lines[7] = lines[8] = 0; if (once == 0) { // Initialize the registry once = 1; mprSprintf(logName, sizeof(logName), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", Mpr::getAppName()); hkey = 0; if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, logName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, &exists) == ERROR_SUCCESS) { value = "%SystemRoot%\\System32\\netmsg.dll"; if (RegSetValueEx(hkey, "EventMessageFile", 0, REG_EXPAND_SZ, (uchar*) value, strlen(value) + 1) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } errorType = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if (RegSetValueEx(hkey, "TypesSupported", 0, REG_DWORD, (uchar*) &errorType, sizeof(DWORD)) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } RegCloseKey(hkey); } } event = RegisterEventSource(0, Mpr::getAppName()); if (event) { // // 3299 is the event number for the generic message in netmsg.dll. // "%1 %2 %3 %4 %5 %6 %7 %8 %9" -- thanks Apache for the tip // ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, sizeof(lines) / sizeof(char*), 0, (LPCSTR*) lines, 0); DeregisterEventSource(event); } }
void MprLogService::error(char *file, int line, int flags, char *fmt, va_list args) { static int recurseGate = 0; Mpr *mpr; char msg[MPR_MAX_LOG_STRING], buf[MPR_MAX_LOG_STRING]; mpr = mprGetMpr(); // // Errors post close // #if BLD_FEATURE_MULTITHREAD if (mutex == 0) { return; } #endif lock(); if (recurseGate > 0) { unlock(); return; } recurseGate++; mprVsprintf(msg, sizeof(msg), fmt, args); if (flags & MPR_TRAP) { mprSprintf(buf, sizeof(buf), "Assertion %s, failed (%s:%d)\n", msg, file, line); output(defaultModule, flags, MPR_ERROR, buf); // // Break to the debugger // breakpoint(file, line); } else if (flags & MPR_LOG) { // // Write to both the O/S log and to the trace log // mprSprintf(buf, sizeof(buf), "Error: %s\n", msg); output(defaultModule, flags, MPR_ERROR, buf); if (mpr) { mpr->writeToOsLog(buf, flags | MPR_INFO); } } else if (flags & MPR_USER) { mprSprintf(buf, sizeof(buf), "Error: %s\n", msg); output(defaultModule, flags, MPR_ERROR, buf); if (mpr) { mpr->writeToOsLog(buf, flags | MPR_WARN); } } else if (flags & MPR_ALERT) { // FUTURE -- TBD } else { mprAssert(0); } recurseGate--; unlock(); }
static long msgProc(HWND hwnd, uint msg, uint wp, long lp) { char buf[MPR_MAX_FNAME]; switch (msg) { case WM_DESTROY: case WM_QUIT: mprSignalExit(mpr); break; case APPWEB_MONITOR_MESSAGE: return monitorEvent(hwnd, wp, lp); case WM_COMMAND: switch (LOWORD(wp)) { case MA_MENU_STATUS: break; case MA_MENU_DOC: runBrowser("/doc/index.html"); break; case MA_MENU_MANAGE: runBrowser("/index.html"); break; case MA_MENU_START: startService(); break; case MA_MENU_STOP: stopService(); break; case MA_MENU_ABOUT: /* * Single-threaded users beware. This blocks !! */ mprSprintf(buf, sizeof(buf), "%s %s-%s", BLD_NAME, BLD_VERSION, BLD_NUMBER); MessageBoxEx(NULL, buf, mprGetAppTitle(mpr), MB_OK, 0); break; case MA_MENU_EXIT: /* * FUTURE * * h = CreateDialog(appInst, MAKEINTRESOURCE(IDD_EXIT), appHwnd, dialogProc); * ShowWindow(h, SW_SHOW); */ PostMessage(hwnd, WM_QUIT, 0, 0L); break; default: return DefWindowProc(hwnd, msg, wp, lp); } break; default: return DefWindowProc(hwnd, msg, wp, lp); } return 0; }
int main(int argc, char *argv[]) { char *password, *passFile, *userName; char *encodedPassword, *argp, *realm; char passBuf[MPR_HTTP_MAX_PASS], buf[MPR_HTTP_MAX_PASS * 2]; int c, errflg, create, nextArg; bool enable; programName = mprGetBaseName(argv[0]); userName = 0; create = errflg = 0; password = 0; enable = 1; #if BLD_FEATURE_LOG MprLogService *ls = new MprLogService(); ls->addListener(new MprLogToFile()); ls->setLogSpec("stdout:0"); #endif MprCmdLine cmdLine(argc, argv, "cdep:"); while ((c = cmdLine.next(&argp)) != EOF) { switch(c) { case 'c': create++; break; case 'e': enable = 1; break; case 'd': enable = 0; break; case 'p': password = argp; break; default: errflg++; break; } } nextArg = cmdLine.firstArg(); if ((nextArg + 3) > argc) { errflg++; } if (errflg) { printUsage(argv[0]); exit(2); } passFile = argv[nextArg++]; realm = argv[nextArg++]; userName = argv[nextArg++]; if (!create) { if (readPassFile(passFile) < 0) { exit(2); } if (access(passFile, R_OK) != 0) { mprError(MPR_L, MPR_USER, "Can't find %s\n", passFile); exit(3); } if (access(passFile, W_OK) < 0) { mprError(MPR_L, MPR_USER, "Can't write to %s\n", passFile); exit(4); } } else { if (access(passFile, R_OK) == 0) { mprError(MPR_L, MPR_USER, "Can't create %s, already exists\n", passFile); exit(5); } } if (password == 0) { password = getPassword(passBuf, sizeof(passBuf)); if (password == 0) { exit(1); } } mprSprintf(buf, sizeof(buf), "%s:%s:%s", userName, realm, password); encodedPassword = maMD5(buf); addUser(userName, realm, encodedPassword, enable); if (updatePassFile(passFile) < 0) { exit(6); } mprFree(encodedPassword); return 0; }