static void testMakeArgv(MprTestGroup *gp) { int argc; cchar **argv; // Simple arg parsing argc = mprMakeArgv("app a b", &argv, 0); assert(argc == 3); assert(strcmp(argv[0], "app") == 0); assert(strcmp(argv[1], "a") == 0); assert(strcmp(argv[2], "b") == 0); // Quoted arg parsing argc = mprMakeArgv("app \"a\" b", &argv, 0); assert(argc == 3); assert(strcmp(argv[0], "app") == 0); assert(strcmp(argv[1], "a") == 0); assert(strcmp(argv[2], "b") == 0); // Embedded spaces in quoted args argc = mprMakeArgv("app \"a b\"", &argv, 0); assert(argc == 2); assert(strcmp(argv[0], "app") == 0); assert(strcmp(argv[1], "a b") == 0); // Single quotes argc = mprMakeArgv("app 'a b'", &argv, 0); assert(argc == 2); assert(strcmp(argv[0], "app") == 0); assert(strcmp(argv[1], "a b") == 0); // Backquoting a double quote (need double to get past cc compiler): \"a argc = mprMakeArgv("\\\"a", &argv, 0); assert(argc == 1); assert(strcmp(argv[0], "\"a") == 0); // Backquoting a single quote (need double to get past cc compiler): \'a argc = mprMakeArgv("\\'a", &argv, 0); assert(argc == 1); assert(strcmp(argv[0], "'a") == 0); // Backquoting normal chars preserves the backquote \a argc = mprMakeArgv("\\a", &argv, 0); assert(argc == 1); assert(strcmp(argv[0], "\\a") == 0); // Backquoted path argc = mprMakeArgv("\\a\\b\\c", &argv, 0); assert(argc == 1); assert(strcmp(argv[0], "\\a\\b\\c") == 0); // Backquote at the end (preserved) argc = mprMakeArgv("a\\", &argv, 0); assert(argc == 1); assert(strcmp(argv[0], "a\\") == 0); }
int MprCmd::start(char *cmd, int userFlags) { char **argv; int rc; mprMakeArgv(0, cmd, &argv, 0); rc = start(argv[0], argv, 0, 0, 0, userFlags); mprFree(argv); return rc; }
static void testArgvRegressions(MprTestGroup *gp) { int argc; cchar **argv; // "\bin\sh" "-c" "c:/home/mob/ejs/out/bin/ejs.exe ./args \"a b\" c" argc = mprMakeArgv("\"\\bin\\sh\" \"-c\" \"c:/home/mob/ejs/out/bin/ejs.exe ./args \\\"a b\\\" c\"", &argv, 0); assert(argc == 3); assert(strcmp(argv[0], "\\bin\\sh") == 0); assert(strcmp(argv[1], "-c") == 0); assert(strcmp(argv[2], "c:/home/mob/ejs/out/bin/ejs.exe ./args \"a b\" c") == 0); // "\bin\sh" "-c" "/bin/ejs ./args \"a b\" c" argc = mprMakeArgv("\"\\bin\\sh\" \"-c\" \"/bin/ejs ./args \\\"a b\\\" c\"", &argv, 0); assert(argc == 3); assert(strcmp(argv[0], "\\bin\\sh") == 0); assert(strcmp(argv[1], "-c") == 0); assert(strcmp(argv[2], "/bin/ejs ./args \"a b\" c") == 0); }
/* * Run a simple blocking command. See arg usage below in mprRunCmdV. */ int mprRunCmd(MprCmd *cmd, cchar *command, char **out, char **err, int flags) { char **argv; int argc; if (mprMakeArgv(cmd, NULL, command, &argc, &argv) < 0 || argv == 0) { return 0; } return mprRunCmdV(cmd, argc, argv, out, err, flags); }
MAIN(testMain, int argc, char *argv[]) { Mpr *mpr; MprTestService *ts; MprTestGroup *gp; int rc; mpr = mprCreate(argc, argv, 0); #if VXWORKS || WINCE /* * These platforms pass an arg string in via the argc value. Assumes 32-bit. */ mprMakeArgv(mpr, "testMpr", (char*) argc, &argc, &argv); #endif ts = mprCreateTestService(mpr); if (ts == 0) { mprError(mpr, "Can't create test service"); exit(2); } if (mprParseTestArgs(ts, argc, argv) < 0) { mprFree(mpr); exit(3); } gp = mprAddTestGroup(ts, &master); if (gp == 0) { exit(4); } #if BLD_FEATURE_SSL && (BLD_FEATURE_MATRIXSSL || BLD_FEATURE_OPENSSL) if (!mprLoadSsl(mpr, 0)) { exit(5); } #endif /* * Need a background event thread as we use the main thread to run the tests. */ if (mprStart(mpr, 0)) { mprError(mpr, "Can't start mpr services"); exit(4); } /* * Run the tests and return zero if 100% success */ rc = mprRunTests(ts); mprReportTestResults(ts); return (rc == 0) ? 0 : 6; }
/* Run a simple blocking command. See arg usage below in mprRunCmdV. */ PUBLIC int mprRunCmd(MprCmd *cmd, cchar *command, cchar **envp, cchar *in, char **out, char **err, MprTicks timeout, int flags) { cchar **argv; int argc; if (cmd == 0 && (cmd = mprCreateCmd(0)) == 0) { return MPR_ERR_BAD_STATE; } if ((argc = mprMakeArgv(command, &argv, 0)) < 0 || argv == 0) { return MPR_ERR_BAD_ARGS; } cmd->makeArgv = argv; return mprRunCmdV(cmd, argc, argv, envp, in, out, err, timeout, flags); }
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; }
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *args, int junk2) { char **argv, *argp; int argc, err, nextArg; mpr = mprCreate(0, NULL, MPR_USER_EVENTS_THREAD); app = mprAllocObj(App, manageApp); mprAddRoot(app); mprAddTerminator(terminating); err = 0; app->appInst = inst; app->heartBeatPeriod = HEART_BEAT_PERIOD; setAppDefaults(); mprSetAppName(BLD_PRODUCT "Manager", BLD_NAME "Manager", BLD_VERSION); app->appName = mprGetAppName(); app->appTitle = mprGetAppTitle(mpr); mprSetLogHandler(logHandler); mprSetWinMsgCallback((MprMsgCallback) msgProc); if ((argc = mprMakeArgv(args, &argv, MPR_ARGV_ARGS_ONLY)) < 0) { return FALSE; } for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-' || strcmp(argp, "--") == 0) { break; } if (strcmp(argp, "--args") == 0) { /* Args to pass to service when it starts */ if (nextArg >= argc) { err++; } else { app->serviceArgs = argv[++nextArg]; } } else if (strcmp(argp, "--console") == 0) { /* Allow the service to interact with the console */ app->createConsole++; } else if (strcmp(argp, "--daemon") == 0) { /* Ignored on windows */ } else if (strcmp(argp, "--heartBeat") == 0) { /* Set the heart beat period */ if (nextArg >= argc) { err++; } else { app->heartBeatPeriod = atoi(argv[++nextArg]) * 1000; } } else if (strcmp(argp, "--home") == 0) { /* Change to this directory before starting the service */ if (nextArg >= argc) { err++; } else { app->serviceHome = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--log") == 0) { /* Pass the log directive through to the service */ if (nextArg >= argc) { err++; } else { app->logSpec = sclone(argv[++nextArg]); mprStartLogging(app->logSpec, 0); mprSetCmdlineLogging(1); } } else if (strcmp(argp, "--name") == 0) { if (nextArg >= argc) { err++; } else { app->serviceName = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--program") == 0) { if (nextArg >= argc) { err++; } else { app->serviceProgram = sclone(argv[++nextArg]); } } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) { mprSetLogLevel(1); } else { err++; } if (err) { mprUserError("Bad command line: %s\n" " Usage: %s [options] [program args]\n" " Switches:\n" " --args # Args to pass to service\n" " --console # Display the service console\n" " --heartBeat interval # Heart beat interval period (secs)\n" " --home path # Home directory for service\n" " --log logFile:level # Log directive for service\n" " --name name # Name of the service to manage\n" " --program path # Service program to start\n" " --verbose # Show command feedback\n" " Commands:\n" " disable # Disable the service\n" " enable # Enable the service\n" " start # Start the service\n" " stop # Start the service\n" " run # Run and watch over the service\n", args, app->appName); return -1; } } if (mprStart() < 0) { mprUserError("Can't start MPR for %s", mprGetAppName()); } else { mprStartEventsThread(); if (nextArg >= argc) { return process("run"); } else for (; nextArg < argc; nextArg++) { if (!process(argv[nextArg])) { return FALSE; } } } return TRUE; }
static void runService() { MprTime mark; char **av, *env[3], **argv; int err, i, status, ac, next; app->servicePid = 0; atexit(cleanup); mprLog(1, "%s: Watching over %s", app->appName, app->serviceProgram); if (access(app->serviceProgram, X_OK) < 0) { mprError("start: can't access %s, errno %d", app->serviceProgram, mprGetOsError()); return; } if (writePid(getpid()) < 0) { return; } mark = mprGetTime(); while (!mprIsStopping()) { if (mprGetElapsedTime(mark) > (3600 * 1000)) { mark = mprGetTime(); app->restartCount = 0; app->restartWarned = 0; } if (app->servicePid == 0) { if (app->restartCount >= app->retries) { if (! app->restartWarned) { mprError("Too many restarts for %s, %d in ths last hour", app->serviceProgram, app->restartCount); mprError("Suspending restarts for one hour"); app->restartWarned++; } mprSleep(60 * 1000); continue; } /* Create the child */ app->servicePid = vfork(); if (app->servicePid < 0) { mprError("Can't fork new process to run %s", app->serviceProgram); continue; } else if (app->servicePid == 0) { /* Child */ umask(022); setsid(); mprLog(1, "%s: Change dir to %s", app->appName, app->serviceHome); if (chdir(app->serviceHome) < 0) {} for (i = 3; i < 128; i++) { close(i); } if (app->serviceArgs && *app->serviceArgs) { ac = mprMakeArgv(app->serviceArgs, &av, 0); } else { ac = 0; } argv = mprAlloc(sizeof(char*) * (6 + ac)); env[0] = sjoin("LD_LIBRARY_PATH=", app->serviceHome, NULL); env[1] = sjoin("PATH=", getenv("PATH"), NULL); env[2] = 0; next = 0; argv[next++] = app->serviceProgram; if (app->logSpec) { argv[next++] = "--log"; argv[next++] = (char*) app->logSpec; } for (i = 0; i < ac; i++) { argv[next++] = av[i]; } argv[next++] = 0; mprLog(1, "%s: Running %s", app->appName, app->serviceProgram); for (i = 1; argv[i]; i++) { mprLog(1, "%s: argv[%d] = %s", app->appName, i, argv[i]); } execve(app->serviceProgram, argv, (char**) &env); /* Should not get here */ err = errno; mprError("%s: Can't exec %s, err %d, cwd %s", app->appName, app->serviceProgram, err, app->serviceHome); exit(MPR_ERR_CANT_INITIALIZE); } /* Parent */ mprLog(1, "%s: create child %s at pid %d", app->appName, app->serviceProgram, app->servicePid); app->restartCount++; waitpid(app->servicePid, &status, 0); mprLog(1, "%s: %s has exited with status %d", app->appName, app->serviceProgram, WEXITSTATUS(status)); if (!mprIsStopping()) { mprLog(1, "%s: Restarting %s (%d/%d)...", app->appName, app->serviceProgram, app->restartCount, app->retries); } app->servicePid = 0; } } }
/* * Add a shell parameter then do the regular init */ Mpr *mprCreateEx(int argc, char **argv, MprAllocNotifier cback, void *shell) { MprFileSystem *fs; Mpr *mpr; char *cp; if (cback == 0) { cback = memoryFailure; } mpr = (Mpr*) mprCreateAllocService(cback, (MprDestructor) mprDestructor); if (mpr == 0) { mprAssert(mpr); return 0; } /* * Wince and Vxworks passes an arg via argc, and the program name in argv. NOTE: this will only work on 32-bit systems. */ #if WINCE mprMakeArgv(mpr, (char*) argv, mprToAsc(mpr, (uni*) argc), &argc, &argv); #elif VXWORKS mprMakeArgv(mpr, NULL, (char*) argc, &argc, &argv); #endif mpr->argc = argc; mpr->argv = argv; mpr->name = mprStrdup(mpr, BLD_PRODUCT); mpr->title = mprStrdup(mpr, BLD_NAME); mpr->version = mprStrdup(mpr, BLD_VERSION); mpr->idleCallback = mprServicesAreIdle; if (mprCreateTimeService(mpr) < 0) { goto error; } if ((mpr->osService = mprCreateOsService(mpr)) < 0) { goto error; } /* * See if any of the preceeding allocations failed and mark all blocks allocated so far as required. * They will then be omitted from leak reports. */ if (mprHasAllocError(mpr)) { goto error; } #if BREW mprSetShell(mpr, shell); #endif #if BLD_FEATURE_MULTITHREAD mpr->multiThread = 1; if ((mpr->threadService = mprCreateThreadService(mpr)) == 0) { goto error; } mpr->mutex = mprCreateLock(mpr); mpr->spin = mprCreateSpinLock(mpr); #endif if ((fs = mprCreateFileSystem(mpr, "/")) == 0) { goto error; } mprAddFileSystem(mpr, fs); if ((mpr->moduleService = mprCreateModuleService(mpr)) == 0) { goto error; } if ((mpr->dispatcher = mprCreateDispatcher(mpr)) == 0) { goto error; } #if BLD_FEATURE_CMD if ((mpr->cmdService = mprCreateCmdService(mpr)) == 0) { goto error; } #endif #if BLD_FEATURE_MULTITHREAD if ((mpr->workerService = mprCreateWorkerService(mpr)) == 0) { goto error; } #endif if ((mpr->waitService = mprCreateWaitService(mpr)) == 0) { goto error; } if ((mpr->socketService = mprCreateSocketService(mpr)) == 0) { goto error; } #if BLD_FEATURE_HTTP if ((mpr->httpService = mprCreateHttpService(mpr)) == 0) { goto error; } #endif if (mpr->argv && mpr->argv[0] && *mpr->argv[0]) { mprFree(mpr->name); mpr->name = mprGetPathBase(mpr, mpr->argv[0]); if ((cp = strchr(mpr->name, '.')) != 0) { *cp = '\0'; } } /* * Now catch all memory allocation errors up to this point. Should be none. */ if (mprHasAllocError(mpr)) { goto error; } return mpr; /* * Error return */ error: mprFree(mpr); return 0; }
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *command, int junk2) { char **argv; cchar *documents, *home, *logs, *port, *ssl, *argp, *path, *contents, *revised; cchar *user, *group, *cache, *modules, *bak; int argc, err, nextArg; static void logHandler(int flags, int level, cchar *msg); if (mprCreate(0, NULL, MPR_USER_EVENTS_THREAD) == NULL) { exit(1); } if ((argc = mprMakeArgv(command, &argv, MPR_ARGV_ARGS_ONLY)) < 0) { return FALSE; } mprSetLogHandler(logHandler); #else int main(int argc, char **argv) { cchar *documents, *home, *logs, *port, *ssl, *argp, *path, *contents, *revised; cchar *user, *group, *cache, *modules, *bak; int err, nextArg; if (mprCreate(argc, argv, MPR_USER_EVENTS_THREAD) == NULL) { exit(1); } #endif documents = home = port = ssl = logs = user = group = cache = modules = 0; for (err = 0, nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (smatch(argp, "--documents") && nextArg < argc) { documents = argv[++nextArg]; } else if (smatch(argp, "--home") && nextArg < argc) { home = argv[++nextArg]; } else if (smatch(argp, "--logs") && nextArg < argc) { logs = argv[++nextArg]; } else if (smatch(argp, "--port") && nextArg < argc) { port = argv[++nextArg]; } else if (smatch(argp, "--ssl") && nextArg < argc) { ssl = argv[++nextArg]; } else if (smatch(argp, "--user") && nextArg < argc) { user = argv[++nextArg]; } else if (smatch(argp, "--group") && nextArg < argc) { group = argv[++nextArg]; } else if (smatch(argp, "--cache") && nextArg < argc) { cache = argv[++nextArg]; } else if (smatch(argp, "--modules") && nextArg < argc) { modules = argv[++nextArg]; } else { err++; } } if (nextArg != (argc - 1)) { err++; } if (err) { #if BIT_WIN_LIKE mprUserError("Bad command line:"); #else mprUserError("Bad command line:\n" " Usage: pathConfig [options]\n" " Switches:\n" " --cache dir # Cache dir" " --documents dir # Static documents directory" " --group groupname # Group name" " --home dir # Server home directory" " --logs dir # Log directory" " --modules dir # moduels dir" " --port number # HTTP port number" " --user username # User name"); #endif return 1; } path = argv[nextArg++]; if ((contents = mprReadPathContents(path, NULL)) == 0) { mprUserError("Cannot read %s", path); return 1; } if (port) { contents = replace(contents, "Listen 80", "Listen %s", port); } if (ssl) { contents = replace(contents, "443", ssl); } if (documents) { contents = replace(contents, "DocumentRoot", "DocumentRoot \"%s\"", documents); } if (home) { contents = replace(contents, "ServerRoot", "ServerRoot \"%s\"", home); } if (logs) { contents = replace(contents, "ErrorLog", "ErrorLog \"%s\"", mprJoinPath(logs, "error.log")); contents = replace(contents, "AccessLog", "AccessLog \"%s\"", mprJoinPath(logs, "access.log")); } if (user) { contents = replace(contents, "UserAccount", "UserAccount %s", user); } if (group) { contents = replace(contents, "GroupAccount", "GroupAccount %s", group); } if (cache) { contents = replace(contents, "EspDir cache", "EspDir cache \"%s\"", cache); } if (modules) { contents = replace(contents, "LoadModulePath", "LoadModulePath \"%s\"", modules); } revised = mprGetTempPath(mprGetPathDir(path)); if (mprWritePathContents(revised, contents, -1, 0644) < 0) { mprUserError("Cannot write %s", revised); } bak = sfmt("%s.bak", path); mprDeletePath(bak); if (rename(path, bak) < 0) { mprUserError("Cannot save %s to %s: 0x%x", path, bak, mprGetError()); } mprDeletePath(path); if (rename(revised, path) < 0) { mprUserError("Cannot rename %s to %s: 0x%x", revised, path, mprGetError()); rename(bak, path); } return 0; }
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *args, int junk2) { char **argv, *argp, *serviceArgs, *homeDir; int argc, err, nextArg, installFlag; mpr = mprCreate(0, NULL, NULL); appInst = inst; serviceArgs = 0; err = 0; exiting = 0; installFlag = 0; homeDir = 0; heartBeatPeriod = HEART_BEAT_PERIOD; initService(); mprSetAppName(mpr, BLD_PRODUCT "Angel", BLD_NAME "Angel", BLD_VERSION); appName = mprGetAppName(mpr); appTitle = mprGetAppTitle(mpr); mprSetLogHandler(mpr, logHandler, NULL); /* * Create the window */ if (initWindow() < 0) { mprError(mpr, "Can't initialize application Window"); return FALSE; } /* * Parse command line arguments */ if (mprMakeArgv(mpr, "", args, &argc, &argv) < 0) { return FALSE; } for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-' || strcmp(argp, "--") == 0) { break; } if (strcmp(argp, "--args") == 0) { /* * Args to pass to service when it starts */ if (nextArg >= argc) { err++; } else { serviceArgs = argv[++nextArg]; } } else if (strcmp(argp, "--console") == 0) { /* * Allow the service to interact with the console */ createConsole++; } else if (strcmp(argp, "--daemon") == 0) { /* Ignored on windows */ } else if (strcmp(argp, "--heartBeat") == 0) { /* * Set the heart beat period */ if (nextArg >= argc) { err++; } else { heartBeatPeriod = atoi(argv[++nextArg]) * 1000; } } else if (strcmp(argp, "--home") == 0) { /* * Change to this directory before starting the service */ if (nextArg >= argc) { err++; } else { homeDir = argv[++nextArg]; } } else if (strcmp(argp, "--program") == 0) { if (nextArg >= argc) { err++; } else { serviceProgram = argv[++nextArg]; } } else if (strcmp(argp, "--install") == 0) { installFlag++; } else if (strcmp(argp, "--start") == 0) { /* * Start the angel */ if (startService() < 0) { return FALSE; } mprSleep(mpr, 2000); /* Time for service to really start */ } else if (strcmp(argp, "--stop") == 0) { /* * Stop the angel */ if (removeService(0) < 0) { return FALSE; } } else if (strcmp(argp, "--uninstall") == 0) { /* * Remove the angel */ if (removeService(1) < 0) { return FALSE; } } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) { verbose++; } else { err++; } if (err) { mprUserError(mpr, "Bad command line: %s\n" " Usage: %s [options] [program args]\n" " Switches:\n" " --args # Args to pass to service\n" " --console # Display the service console\n" " --heartBeat interval # Heart beat interval period (secs)\n" " --home path # Home directory for service\n" " --install # Install the service\n" " --program # Service program to start\n" " --start # Start the service\n" " --stop # Stop the service\n" " --uninstall # Uninstall the service", args, appName); return -1; } } if (installFlag) { /* * Install the angel */ if (installService(homeDir, serviceArgs) < 0) { return FALSE; } } if (argc <= 1) { /* * This will block if we are a service and are being started by the * service control manager. While blocked, the svcMain will be called * which becomes the effective main program. */ startDispatcher(serviceMain); } return 0; }
MAIN(benchMain, int argc, char *argv[]) { Mpr *mpr; char *argp; int err, i, nextArg; #if BLD_FEATURE_MULTITHREAD MprThread *tp; #endif mpr = mprCreate(argc, argv, 0); #if VXWORKS || WINCE /* * These platforms pass an arg string in via the argc value. Assumes 32-bit. */ mprMakeArgv(mpr, "http", (char*) argc, &argc, &argv); #endif err = 0; for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--iterations") == 0 || strcmp(argp, "-i") == 0) { if (nextArg >= argc) { err++; } else { iterations = atoi(argv[++nextArg]); } } else if (strcmp(argp, "--workers") == 0 || strcmp(argp, "-w") == 0) { if (nextArg >= argc) { err++; } else { i = atoi(argv[++nextArg]); if (i <= 0 || i > 100) { mprError(mpr, "%s: Bad number of worker threads (0-100)", mprGetAppName(mpr)); exit(2); } workers = i; } } else { err++; } } if (err) { mprPrintf(mpr, "usage: bench [-em] [-i iterations] [-t workers]\n"); mprRawLog(mpr, 0, "usage: %s [options]\n" " --iterations count # Number of iterations to run the test\n" " --workers count # Set maximum worker threads\n", mprGetAppName(mpr)); exit(2); } #if BLD_FEATURE_MULTITHREAD mutex = mprCreateLock(mpr); mprSetMaxWorkers(mpr, workers); #endif mprStart(mpr, 0); #if BLD_FEATURE_MULTITHREAD tp = mprCreateThread(mpr, "bench", (MprThreadProc) doBenchmark, (void*) mpr, MPR_NORMAL_PRIORITY, 0); mprStartThread(tp); while (!testComplete) { mprServiceEvents(mprGetDispatcher(mpr), 250, MPR_SERVICE_EVENTS | MPR_SERVICE_IO); } #else doBenchmark(mpr, NULL); #endif mprPrintf(mpr, "\n\n"); // mprFree(mpr); return 0; }