static char *getModuleEntry(EspRoute *eroute, cchar *kind, cchar *source, cchar *cacheName) { char *cp, *entry; if (smatch(kind, "view")) { entry = sfmt("esp_%s", cacheName); } else if (smatch(kind, "app")) { if (eroute->combine) { entry = sfmt("esp_%s_%s_combine", kind, eroute->appName); } else { entry = sfmt("esp_%s_%s", kind, eroute->appName); } } else { /* Controller */ if (eroute->appName) { entry = sfmt("esp_%s_%s_%s", kind, eroute->appName, mprTrimPathExt(mprGetPathBase(source))); } else { entry = sfmt("esp_%s_%s", kind, mprTrimPathExt(mprGetPathBase(source))); } } for (cp = entry; *cp; cp++) { if (!isalnum((uchar) *cp) && *cp != '_') { *cp = '_'; } } return entry; }
PUBLIC int maSetPlatform(cchar *platformPath) { MaAppweb *appweb; MprDirEntry *dp; cchar *platform, *dir, *junk, *appwebExe; int next, i, notrace; appweb = MPR->appwebService; notrace = !platformPath; if (!platformPath) { platformPath = appweb->localPlatform; } appweb->platform = appweb->platformDir = 0; platform = mprGetPathBase(platformPath); if (mprPathExists(platformPath, X_OK) && mprIsPathDir(platformPath)) { appweb->platform = platform; appweb->platformDir = sclone(platformPath); } else if (smatch(platform, appweb->localPlatform)) { /* If running inside an appweb source tree, locate the platform directory */ appwebExe = mprJoinPath(mprGetAppDir(), "appweb" BIT_EXE); if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = mprGetPathParent(mprGetAppDir()); } else { /* Check installed appweb */ appwebExe = BIT_VAPP_PREFIX "/bin/appweb" BIT_EXE; if (mprPathExists(appwebExe, R_OK)) { appweb->platform = appweb->localPlatform; appweb->platformDir = sclone(BIT_VAPP_PREFIX); } } } /* Last chance. Search up the tree for a similar platform directory. This permits specifying a partial platform like "vxworks" without architecture and profile. */ if (!appweb->platformDir) { dir = mprGetCurrentPath(); for (i = 0; !mprSamePath(dir, "/") && i < 64; i++) { for (ITERATE_ITEMS(mprGetPathFiles(dir, 0), dp, next)) { if (dp->isDir && sstarts(mprGetPathBase(dp->name), platform)) { appweb->platform = mprGetPathBase(dp->name); appweb->platformDir = mprJoinPath(dir, dp->name); break; } } dir = mprGetPathParent(dir); } }
int mprSetAppName(MprCtx ctx, cchar *name, cchar *title, cchar *version) { Mpr *mpr; char *cp; mpr = mprGetMpr(ctx); if (name) { mprFree(mpr->name); if ((mpr->name = (char*) mprGetPathBase(mpr, name)) == 0) { return MPR_ERR_CANT_ALLOCATE; } if ((cp = strrchr(mpr->name, '.')) != 0) { *cp = '\0'; } } if (title) { mprFree(mpr->title); if ((mpr->title = mprStrdup(ctx, title)) == 0) { return MPR_ERR_CANT_ALLOCATE; } } if (version) { mprFree(mpr->version); if ((mpr->version = mprStrdup(ctx, version)) == 0) { return MPR_ERR_CANT_ALLOCATE; } } return 0; }
/* Write upload data. This routine blocks. If you need non-blocking ... cut and paste. */ ssize httpWriteUploadData(HttpConn *conn, MprList *fileData, MprList *formData) { char *path, *pair, *key, *value, *name; ssize rc; int next; rc = 0; if (formData) { for (rc = next = 0; rc >= 0 && (pair = mprGetNextItem(formData, &next)) != 0; ) { key = stok(sclone(pair), "=", &value); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"%s\";\r\n", conn->boundary, key); rc += httpWrite(conn->writeq, "Content-Type: application/x-www-form-urlencoded\r\n\r\n%s\r\n", value); } } if (fileData) { for (rc = next = 0; rc >= 0 && (path = mprGetNextItem(fileData, &next)) != 0; ) { name = mprGetPathBase(path); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"file%d\"; filename=\"%s\"\r\n", conn->boundary, next - 1, name); rc += httpWrite(conn->writeq, "Content-Type: %s\r\n\r\n", mprLookupMime(MPR->mimeTypes, path)); rc += blockingFileCopy(conn, path); rc += httpWrite(conn->writeq, "\r\n"); } } rc += httpWrite(conn->writeq, "%s--\r\n--", conn->boundary); httpFinalize(conn); return rc; }
PUBLIC void espScript(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; cchar *indent, *newline, *path; EspScript *sp; EspRoute *eroute; bool minified; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri) { espRender(conn, "<script src='%s' type='text/javascript'></script>", httpUri(conn, uri)); } else { minified = smatch(httpGetOption(options, "minified", 0), "true"); indent = ""; for (sp = defaultScripts; sp->name; sp++) { if (sp->option && !smatch(httpGetOption(options, sp->option, "false"), "true")) { continue; } if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<!-- [if lt IE 9]>\n", indent); } path = sjoin("~/", mprGetPathBase(eroute->clientDir), sp->name, minified ? ".min.js" : ".js", NULL); uri = httpUri(conn, path); newline = sp[1].name ? "\r\n" : ""; espRender(conn, "%s<script src='%s' type='text/javascript'></script>%s", indent, uri, newline); if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<![endif]-->\n", indent); } indent = " "; } } }
static MprList *expandWild(Ejs *ejs, int argc, char **argv) { MprList *list; EjsArray *files; EjsPath *path, *dir; cchar *arg; int i, j; if ((list = mprCreateList(-1, 0)) == 0) { return 0; } for (i = 0; i < argc; i++) { if (schr(argv[i], '*')) { arg = mprNormalizePath(argv[i]); dir = ejsCreatePathFromAsc(ejs, mprGetPathDir(arg)); path = ejsCreatePathFromAsc(ejs, mprGetPathBase(arg)); if ((files = ejsGetPathFiles(ejs, dir, 1, (EjsObj**) (void*) &path)) == 0) { ejsClearException(ejs); mprAddItem(list, sclone(argv[i])); } else { for (j = 0; j < files->length; j++) { mprAddItem(list, ((EjsPath*) files->data[j])->value); } } } else { mprAddItem(list, sclone(argv[i])); } } return list; }
static int processThread(HttpConn *conn, MprEvent *event) { ThreadData *td; cchar *path; char *url; int next; td = mprGetCurrentThread()->data; httpFollowRedirects(conn, !app->nofollow); httpSetTimeout(conn, app->timeout, app->timeout); if (strcmp(app->protocol, "HTTP/1.0") == 0) { httpSetKeepAliveCount(conn, 0); httpSetProtocol(conn, "HTTP/1.0"); } if (app->username) { if (app->password == 0 && !strchr(app->username, ':')) { app->password = getPassword(); } httpSetCredentials(conn, app->username, app->password); } while (!mprShouldDenyNewRequests(conn) && (app->success || app->continueOnErrors)) { if (app->singleStep) waitForUser(); if (app->files && !app->upload) { for (next = 0; (path = mprGetNextItem(app->files, &next)) != 0; ) { /* If URL ends with "/", assume it is a directory on the target and append each file name */ if (app->target[strlen(app->target) - 1] == '/') { url = mprJoinPath(app->target, mprGetPathBase(path)); } else { url = app->target; } app->requestFiles = mprCreateList(-1, MPR_LIST_STATIC_VALUES); mprAddItem(app->requestFiles, path); td->url = url = resolveUrl(conn, url); if (app->verbose) { mprPrintf("putting: %s to %s\n", path, url); } if (doRequest(conn, url, app->requestFiles) < 0) { app->success = 0; break; } } } else { td->url = url = resolveUrl(conn, app->target); if (doRequest(conn, url, app->files) < 0) { app->success = 0; break; } } if (iterationsComplete()) { break; } } httpDestroyConn(conn); finishThread((MprThread*) event->data); return -1; }
/* Start the command to run (stdIn and stdOut are named from the client's perspective) */ PUBLIC int startProcess(MprCmd *cmd) { MprCmdTaskFn entryFn; MprModule *mp; char *entryPoint, *program, *pair; int pri, next; mprLog("info mpr cmd", 4, "Program %s", cmd->program); entryPoint = 0; if (cmd->env) { for (ITERATE_ITEMS(cmd->env, pair, next)) { if (sncmp(pair, "entryPoint=", 11) == 0) { entryPoint = sclone(&pair[11]); } } } program = mprGetPathBase(cmd->program); if (entryPoint == 0) { program = mprTrimPathExt(program); entryPoint = program; } #if ME_CPU_ARCH == MPR_CPU_IX86 || ME_CPU_ARCH == MPR_CPU_IX64 || ME_CPU_ARCH == MPR_CPU_SH /* A leading underscore is required on some architectures */ entryPoint = sjoin("_", entryPoint, NULL); #endif if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { if ((mp = mprCreateModule(cmd->program, cmd->program, NULL, NULL)) == 0) { mprLog("error mpr cmd", 0, "Cannot create module"); return MPR_ERR_CANT_CREATE; } if (mprLoadModule(mp) < 0) { mprLog("error mpr cmd", 0, "Cannot load DLL %s, errno %d", program, mprGetOsError()); return MPR_ERR_CANT_READ; } if (mprFindVxSym(sysSymTbl, entryPoint, (char**) (void*) &entryFn) < 0) { mprLog("error mpr cmd", 0, "Cannot find symbol %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_ACCESS; } } taskPriorityGet(taskIdSelf(), &pri); cmd->pid = taskSpawn(entryPoint, pri, VX_FP_TASK | VX_PRIVATE_ENV, ME_STACK_SIZE, (FUNCPTR) cmdTaskEntry, (int) cmd->program, (int) entryFn, (int) cmd, 0, 0, 0, 0, 0, 0, 0); if (cmd->pid < 0) { mprLog("error mpr cmd", 0, "Cannot create task %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_CREATE; } if (semTake(cmd->startCond, MPR_TIMEOUT_START_TASK) != OK) { mprLog("error mpr cmd", 0, "Child %s did not initialize, errno %d", cmd->program, mprGetOsError()); return MPR_ERR_CANT_CREATE; } semDelete(cmd->startCond); cmd->startCond = 0; return 0; }
PUBLIC int mprLoadNativeModule(MprModule *mp) { MprModuleEntry fn; MprPath info; char *at; void *handle; assert(mp); /* Search the image incase the module has been statically linked */ #ifdef RTLD_DEFAULT handle = RTLD_DEFAULT; #else #ifdef RTLD_MAIN_ONLY handle = RTLD_MAIN_ONLY; #else handle = 0; #endif #endif if (!mp->entry || !dlsym(handle, mp->entry)) { if ((at = mprSearchForModule(mp->path)) == 0) { mprError("Cannot find module \"%s\", cwd: \"%s\", search path \"%s\"", mp->path, mprGetCurrentPath(), mprGetModuleSearchPath()); return MPR_ERR_CANT_ACCESS; } mp->path = at; mprGetPathInfo(mp->path, &info); mp->modified = info.mtime; mprLog(2, "Loading native module %s", mprGetPathBase(mp->path)); if ((handle = dlopen(mp->path, RTLD_LAZY | RTLD_GLOBAL)) == 0) { mprError("Cannot load module %s\nReason: \"%s\"", mp->path, dlerror()); return MPR_ERR_CANT_OPEN; } mp->handle = handle; } else if (mp->entry) { mprLog(2, "Activating native module %s", mp->name); } if (mp->entry) { if ((fn = (MprModuleEntry) dlsym(handle, mp->entry)) != 0) { if ((fn)(mp->moduleData, mp) < 0) { mprError("Initialization for module %s failed", mp->name); dlclose(handle); return MPR_ERR_CANT_INITIALIZE; } } else { mprError("Cannot load module %s\nReason: can't find function \"%s\"", mp->path, mp->entry); dlclose(handle); return MPR_ERR_CANT_READ; } } return 0; }
PUBLIC int mprLoadNativeModule(MprModule *mp) { MprModuleEntry fn; void *handle; assert(mp); if ((handle = (HANDLE) MPR->appInstance) == 0) { handle = GetModuleHandle(NULL); } if (!handle || !mp->entry || !GetProcAddress(handle, mp->entry)) { #if ME_STATIC mprLog("error mpr", 0, "Cannot load module %s, product built static", mp->name); return MPR_ERR_BAD_STATE; #else MprPath info; char *at, *baseName; if ((at = mprSearchForModule(mp->path)) == 0) { mprLog("error mpr", 0, "Cannot find module \"%s\", cwd=\"%s\", search=\"%s\"", mp->path, mprGetCurrentPath(), mprGetModuleSearchPath()); return MPR_ERR_CANT_ACCESS; } mp->path = at; mprGetPathInfo(mp->path, &info); mp->modified = info.mtime; baseName = mprGetPathBase(mp->path); mprLog("info mpr", 4, "Loading native module %s", baseName); if ((handle = LoadLibrary(wide(mp->path))) == 0) { mprLog("error mpr", 0, "Cannot load module %s, errno=\"%d\"", mp->path, mprGetOsError()); return MPR_ERR_CANT_READ; } mp->handle = handle; #endif /* !ME_STATIC */ } else if (mp->entry) { mprLog("info mpr", 4, "Activating native module %s", mp->name); } if (mp->entry) { if ((fn = (MprModuleEntry) GetProcAddress((HINSTANCE) handle, mp->entry)) == 0) { mprLog("error mpr", 0, "Cannot load module %s, cannot find function \"%s\"", mp->name, mp->entry); FreeLibrary((HINSTANCE) handle); return MPR_ERR_CANT_ACCESS; } if ((fn)(mp->moduleData, mp) < 0) { mprLog("error mpr", 0, "Initialization for module %s failed", mp->name); FreeLibrary((HINSTANCE) handle); return MPR_ERR_CANT_INITIALIZE; } } return 0; }
PUBLIC void espIcon(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; EspRoute *eroute; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri == 0) { /* Suppress favicon */ uri = "data:image/x-icon;,"; } else if (*uri == 0) { uri = sjoin("~/", mprGetPathBase(eroute->clientDir), "/images/favicon.ico", NULL); } espRender(conn, "<link href='%s' rel='shortcut icon'%s />", httpUri(conn, uri), map(conn, options)); }
MprModule *mprLoadModule(MprCtx ctx, cchar *moduleName, cchar *initFunction) { MprModule *mp; MprModuleEntry fn; char *module; char *path, *name; void *handle; mprAssert(moduleName && *moduleName); mp = 0; name = path = 0; module = mprGetNormalizedPath(ctx, moduleName); if (mprSearchForModule(ctx, module, &path) < 0) { mprError(ctx, "Can't find module \"%s\" in search path \"%s\"", moduleName, mprGetModuleSearchPath(ctx)); } else { name = mprGetPathBase(ctx, module); mprLog(ctx, MPR_INFO, "Loading module %s from %s", name, path); if ((handle = GetModuleHandle(name)) == 0 && (handle = LoadLibrary(path)) == 0) { mprError(ctx, "Can't load module %s\nReason: \"%d\"\n", path, mprGetOsError()); } else if (initFunction) { if ((fn = (MprModuleEntry) GetProcAddress((HINSTANCE) handle, initFunction)) != 0) { if ((mp = (fn)(ctx, path)) == 0) { mprError(ctx, "Initialization for module %s failed", name); FreeLibrary((HINSTANCE) handle); } else { mp->handle = handle; } } else { mprError(ctx, "Can't load module %s\nReason: can't find function \"%s\"\n", name, initFunction); FreeLibrary((HINSTANCE) handle); } } } mprFree(name); mprFree(path); mprFree(module); return mp; }
static void testAbsPath(MprTestGroup *gp) { char *path; #if MANUAL_TESTING path = mprNormalizePath("/"); path = mprNormalizePath("C:/"); path = mprNormalizePath("C:/abc"); path = mprNormalizePath(""); path = mprNormalizePath("c:abc"); path = mprNormalizePath("abc"); path = mprGetAbsPath("/"); path = mprGetAbsPath("C:/"); path = mprGetAbsPath("C:/abc"); path = mprGetAbsPath(""); path = mprGetAbsPath("c:abc"); path = mprGetAbsPath("abc"); #endif path = mprGetAbsPath(""); assert(mprIsPathAbs(path)); path = mprGetAbsPath("/"); assert(mprIsPathAbs(path)); path = mprGetAbsPath("../../../../../../../../../../.."); assert(mprIsPathAbs(path)); assert(mprIsPathAbs(mprGetAbsPath("Makefile"))); /* Manually check incase mprIsAbs gets it wrong */ path = mprGetAbsPath("Makefile"); assert(path && *path); assert(mprIsPathAbs(path)); #if BIT_WIN_LIKE assert(isalpha(path[0])); assert(path[1] == ':' && path[2] == '\\'); #elif BIT_UNIX_LIKE assert(path[0] == '/' && path[1] != '/'); #endif assert(strcmp(mprGetPathBase(path), "Makefile") == 0); }
static int lstOpen(EjsMod *mp, char *moduleFilename, EjsModuleHdr *hdr) { char *path, *name, *ext; mprAssert(mp); name = mprGetPathBase(moduleFilename); if ((ext = strstr(name, EJS_MODULE_EXT)) != 0) { *ext = '\0'; } path = sjoin(name, EJS_LISTING_EXT, NULL); path = mprJoinPath(mp->outputDir, path); if ((mp->file = mprOpenFile(path, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0664)) == 0) { mprError("Can't create %s", path); return EJS_ERR; } mprEnableFileBuffering(mp->file, 0, 0); mprFprintf(mp->file, "#\n# %s -- Module Listing for %s\n#\n", path, moduleFilename); return 0; }
/* Write upload data. This routine blocks. If you need non-blocking ... cut and paste. */ PUBLIC ssize httpWriteUploadData(HttpConn *conn, MprList *fileData, MprList *formData) { char *path, *pair, *key, *value, *name; cchar *type; ssize rc; int next; rc = 0; if (formData) { for (rc = next = 0; rc >= 0 && (pair = mprGetNextItem(formData, &next)) != 0; ) { key = ssplit(sclone(pair), "=", &value); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"%s\";\r\n", conn->boundary, key); rc += httpWrite(conn->writeq, "Content-Type: application/x-www-form-urlencoded\r\n\r\n%s\r\n", value); } } if (fileData) { for (rc = next = 0; rc >= 0 && (path = mprGetNextItem(fileData, &next)) != 0; ) { if (!mprPathExists(path, R_OK)) { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open %s", path); return MPR_ERR_CANT_OPEN; } name = mprGetPathBase(path); rc += httpWrite(conn->writeq, "%s\r\nContent-Disposition: form-data; name=\"file%d\"; filename=\"%s\"\r\n", conn->boundary, next - 1, name); if ((type = mprLookupMime(MPR->mimeTypes, path)) != 0) { rc += httpWrite(conn->writeq, "Content-Type: %s\r\n", mprLookupMime(MPR->mimeTypes, path)); } httpWrite(conn->writeq, "\r\n"); if (blockingFileCopy(conn, path) < 0) { return MPR_ERR_CANT_WRITE; } rc += httpWrite(conn->writeq, "\r\n"); } } rc += httpWrite(conn->writeq, "%s--\r\n--", conn->boundary); return rc; }
PUBLIC void espStylesheet(HttpConn *conn, cchar *uri, cchar *optionString) { EspRoute *eroute; MprHash *options; cchar *indent, *newline; char **up; bool less; eroute = conn->rx->route->eroute; if (uri) { espRender(conn, "<link rel='stylesheet' type='text/css' href='%s' />", httpUri(conn, uri)); } else { indent = ""; options = httpGetOptions(optionString); less = smatch(httpGetOption(options, "type", "css"), "less"); up = less ? defaultLess : defaultCss; for (; *up; up++) { uri = httpUri(conn, sjoin("~/", mprGetPathBase(eroute->clientDir), *up, NULL)); newline = up[1] ? "\r\n" : ""; espRender(conn, "%s<link rel='stylesheet%s' type='text/css' href='%s' />%s", indent, less ? "/less" : "", uri, newline); indent = " "; } } }
/* Start the command to run (stdIn and stdOut are named from the client's perspective) */ int startProcess(MprCmd *cmd) { MprCmdTaskFn entryFn; SYM_TYPE symType; char *entryPoint, *program; int i, pri; mprLog(cmd, 4, "cmd: start %s", cmd->program); entryPoint = 0; if (cmd->env) { for (i = 0; cmd->env[i]; i++) { if (strncmp(cmd->env[i], "entryPoint=", 11) == 0) { entryPoint = mprStrdup(cmd, cmd->env[i]); } } } program = mprGetPathBase(cmd, cmd->program); if (entryPoint == 0) { program = mprTrimPathExtension(cmd, program); #if BLD_HOST_CPU_ARCH == MPR_CPU_IX86 || BLD_HOST_CPU_ARCH == MPR_CPU_IX64 entryPoint = mprStrcat(cmd, -1, "_", program, "Main", NULL); #else entryPoint = mprStrcat(cmd, -1, program, "Main", NULL); #endif } if (symFindByName(sysSymTbl, entryPoint, (char**) &entryFn, &symType) < 0) { if (mprLoadModule(cmd, cmd->program, NULL) == 0) { mprError(cmd, "start: can't load DLL %s, errno %d", program, mprGetOsError()); return MPR_ERR_CANT_READ; } if (symFindByName(sysSymTbl, entryPoint, (char**) &entryFn, &symType) < 0) { mprError(cmd, "start: can't find symbol %s, errno %d", entryPoint, mprGetOsError()); return MPR_ERR_CANT_ACCESS; } } taskPriorityGet(taskIdSelf(), &pri); /* * Pass the server output file to become the client stdin. */ cmd->pid = taskSpawn(entryPoint, pri, VX_FP_TASK, MPR_DEFAULT_STACK, (FUNCPTR) cmdTaskEntry, (int) cmd->program, (int) entryFn, (int) cmd, 0, 0, 0, 0, 0, 0, 0); if (cmd->pid < 0) { mprError(cmd, "start: can't create task %s, errno %d", entryPoint, mprGetOsError()); mprFree(entryPoint); return MPR_ERR_CANT_CREATE; } mprLog(cmd, 7, "cmd, child taskId %d", cmd->pid); mprFree(entryPoint); if (semTake(cmd->startCond, MPR_TIMEOUT_START_TASK) != OK) { mprError(cmd, "start: child %s did not initialize, errno %d", cmd->program, mprGetOsError()); return MPR_ERR_CANT_CREATE; } semDelete(cmd->startCond); cmd->startCond = 0; return 0; }
static void processThread(MprCtx ctx) { MprHttp *http; MprList *files; cchar *path; char *url; int next; http = mprCreateHttp(ctx); mprSetHttpTimeout(http, timeout); mprSetHttpFollowRedirects(http, !nofollow); if (chunkSize) { mprSetHttpChunked(http, 1); } if (httpVersion == 0) { mprSetHttpKeepAlive(http, 0); mprSetHttpProtocol(http, "HTTP/1.0"); } if (username) { if (password == 0 && !strchr(username, ':')) { password = getPassword(http); } mprSetHttpCredentials(http, username, password); } while (!mprIsExiting(http) && (success || continueOnErrors)) { if (singleStep) waitForUser(http); if (fileData && !upload) { for (next = 0; (path = mprGetNextItem(fileData, &next)) != 0; ) { if (target[strlen(target) - 1] == '/') { url = mprJoinPath(http, target, mprGetPathBase(http, path)); } else { url = target; } files = mprCreateList(http); mprAddItem(files, path); url = resolveUrl(http, url); if (verbose) { mprPrintf(http, "putting: %s to %s\n", path, url); } if (doRequest(http, url, formData, files) < 0) { success = 0; mprFree(files); mprFree(url); break; } mprFree(files); mprFree(url); } } else { url = resolveUrl(http, target); if (doRequest(http, url, formData, fileData) < 0) { success = 0; mprFree(url); break; } } if (iterationsComplete(http)) break; } mprFree(http); }
/* Compile a view or controller cacheName MD5 cache name (not a full path) source ESP source file name module Module file name */ bool espCompile(HttpConn *conn, cchar *source, cchar *module, cchar *cacheName, int isView) { MprFile *fp; HttpRx *rx; HttpRoute *route; EspRoute *eroute; cchar *csource; char *layout, *script, *page, *err; ssize len; rx = conn->rx; route = rx->route; eroute = route->eroute; layout = 0; if (isView) { if ((page = mprReadPathContents(source, &len)) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't read %s", source); return 0; } /* Use layouts iff there is a source defined on the route. Only MVC/controllers based apps do this. */ if (eroute->layoutsDir) { #if UNUSED layout = mprSamePath(eroute->layoutsDir, route->dir) ? 0 : mprJoinPath(eroute->layoutsDir, "default.esp"); #else layout = mprJoinPath(eroute->layoutsDir, "default.esp"); #endif } if ((script = espBuildScript(route, page, source, cacheName, layout, &err)) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't build %s, error %s", source, err); return 0; } csource = mprJoinPathExt(mprTrimPathExt(module), ".c"); if ((fp = mprOpenFile(csource, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0664)) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't open compiled script file %s", csource); return 0; } len = slen(script); if (mprWriteFile(fp, script, len) != len) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't write compiled script file %s", csource); mprCloseFile(fp); return 0; } mprCloseFile(fp); } else { csource = source; } mprMakeDir(eroute->cacheDir, 0775, -1, -1, 1); /* WARNING: GC yield here */ if (runCommand(conn, eroute->compile, csource, module) < 0) { return 0; } if (eroute->link) { /* WARNING: GC yield here */ if (runCommand(conn, eroute->link, csource, module) < 0) { return 0; } #if !(BLD_DEBUG && MACOSX) /* MAC needs the object for debug information */ mprDeletePath(mprJoinPathExt(mprTrimPathExt(module), BLD_OBJ)); #endif } #if BLD_WIN_LIKE { /* Windows leaves intermediate object in the current directory */ cchar *obj; obj = mprReplacePathExt(mprGetPathBase(csource), BLD_OBJ); if (mprPathExists(obj, F_OK)) { mprDeletePath(obj); } } #endif if (!eroute->keepSource && isView) { mprDeletePath(csource); } return 1; }
PUBLIC int espEmail(HttpConn *conn, cchar *to, cchar *from, cchar *subject, MprTime date, cchar *mime, cchar *message, MprList *files) { MprList *lines; MprCmd *cmd; cchar *body, *boundary, *contents, *encoded, *file; char *out, *err; ssize length; int i, next, status; if (!from || !*from) { from = "anonymous"; } if (!subject || !*subject) { subject = "Mail message"; } if (!mime || !*mime) { mime = "text/plain"; } if (!date) { date = mprGetTime(); } boundary = sjoin("esp.mail=", mprGetMD5("BOUNDARY"), NULL); lines = mprCreateList(0, 0); mprAddItem(lines, sfmt("To: %s", to)); mprAddItem(lines, sfmt("From: %s", from)); mprAddItem(lines, sfmt("Date: %s", mprFormatLocalTime(0, date))); mprAddItem(lines, sfmt("Subject: %s", subject)); mprAddItem(lines, "MIME-Version: 1.0"); mprAddItem(lines, sfmt("Content-Type: multipart/mixed; boundary=%s", boundary)); mprAddItem(lines, ""); boundary = sjoin("--", boundary, NULL); mprAddItem(lines, boundary); mprAddItem(lines, sfmt("Content-Type: %s", mime)); mprAddItem(lines, ""); mprAddItem(lines, ""); mprAddItem(lines, message); for (ITERATE_ITEMS(files, file, next)) { mprAddItem(lines, boundary); if ((mime = mprLookupMime(NULL, file)) == 0) { mime = "application/octet-stream"; } mprAddItem(lines, "Content-Transfer-Encoding: base64"); mprAddItem(lines, sfmt("Content-Disposition: inline; filename=\"%s\"", mprGetPathBase(file))); mprAddItem(lines, sfmt("Content-Type: %s; name=\"%s\"", mime, mprGetPathBase(file))); mprAddItem(lines, ""); contents = mprReadPathContents(file, &length); encoded = mprEncode64Block(contents, length); for (i = 0; i < length; i += 76) { mprAddItem(lines, snclone(&encoded[i], i + 76)); } } mprAddItem(lines, sfmt("%s--", boundary)); body = mprListToString(lines, "\n"); httpTraceContent(conn, "esp.email", "context", body, slen(body), 0); cmd = mprCreateCmd(conn->dispatcher); if (mprRunCmd(cmd, "sendmail -t", NULL, body, &out, &err, -1, 0) < 0) { mprDestroyCmd(cmd); return MPR_ERR_CANT_OPEN; } if (mprWaitForCmd(cmd, ME_ESP_EMAIL_TIMEOUT) < 0) { httpTrace(conn, "esp.email.error", "error", "msg=\"Timeout waiting for command to complete\", timeout=%d, command=\"%s\"", ME_ESP_EMAIL_TIMEOUT, cmd->argv[0]); mprDestroyCmd(cmd); return MPR_ERR_CANT_COMPLETE; } if ((status = mprGetCmdExitStatus(cmd)) != 0) { httpTrace(conn, "esp.email.error", "error", "msg=\"Sendmail failed\", status=%d, error=\"%s\"", status, err); mprDestroyCmd(cmd); return MPR_ERR_CANT_WRITE; } mprDestroyCmd(cmd); return 0; }
/* Start the CGI command program. This commences the CGI gateway program. This will be called after content for form and upload requests (or if "RunHandler" before specified), otherwise it runs before receiving content data. */ static void startCgi(HttpQueue *q) { HttpRx *rx; HttpTx *tx; HttpRoute *route; HttpConn *conn; MprCmd *cmd; Cgi *cgi; cchar *baseName, **argv, *fileName, **envv; ssize varCount; int argc, count; argv = 0; argc = 0; cgi = q->queueData; conn = q->conn; rx = conn->rx; route = rx->route; tx = conn->tx; /* The command uses the conn dispatcher. This serializes all I/O for both the connection and the CGI gateway. */ if ((cmd = mprCreateCmd(conn->dispatcher)) == 0) { return; } cgi->cmd = cmd; if (conn->http->forkCallback) { cmd->forkCallback = conn->http->forkCallback; cmd->forkData = conn->http->forkData; } argc = 1; /* argv[0] == programName */ buildArgs(conn, cmd, &argc, &argv); fileName = argv[0]; baseName = mprGetPathBase(fileName); /* nph prefix means non-parsed-header. Don't parse the CGI output for a CGI header */ if (strncmp(baseName, "nph-", 4) == 0 || (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0)) { /* Pretend we've seen the header for Non-parsed Header CGI programs */ cgi->seenHeader = 1; tx->flags |= HTTP_TX_USE_OWN_HEADERS; } /* Build environment variables */ varCount = mprGetHashLength(rx->headers) + mprGetHashLength(rx->svars) + mprGetJsonLength(rx->params); if ((envv = mprAlloc((varCount + 1) * sizeof(char*))) != 0) { count = copyParams(conn, envv, 0, rx->params, route->envPrefix); count = copyVars(conn, envv, count, rx->svars, ""); count = copyVars(conn, envv, count, rx->headers, "HTTP_"); assert(count <= varCount); } #if !VXWORKS /* This will be ignored on VxWorks because there is only one global current directory for all tasks */ mprSetCmdDir(cmd, mprGetPathDir(fileName)); #endif mprSetCmdCallback(cmd, cgiCallback, cgi); if (mprStartCmd(cmd, argc, argv, envv, MPR_CMD_IN | MPR_CMD_OUT | MPR_CMD_ERR) < 0) { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot run CGI process: %s, URI %s", fileName, rx->uri); return; } #if ME_WIN_LIKE mprCreateEvent(conn->dispatcher, "cgi-win", 10, waitForCgi, cgi, MPR_EVENT_CONTINUOUS); #endif }
/* Per-thread execution. Called for main thread and helper threads. */ static void threadMain(void *data, MprThread *tp) { ThreadData *td; HttpConn *conn; cchar *path; char *url; int next, count; td = tp->data; /* Create and start a dispatcher. This ensures that all activity on the connection in this thread will be serialized with respect to all I/O events and httpProtocol work. This also ensures that I/O events will be handled by this thread from httpWait. */ td->dispatcher = mprCreateDispatcher(tp->name, 0); mprStartDispatcher(td->dispatcher); td->conn = conn = httpCreateConn(NULL, td->dispatcher); httpFollowRedirects(conn, !app->nofollow); httpSetTimeout(conn, app->timeout, app->timeout); if (strcmp(app->protocol, "HTTP/1.0") == 0) { httpSetKeepAliveCount(conn, 0); httpSetProtocol(conn, "HTTP/1.0"); } if (app->iterations == 1) { conn->limits->keepAliveMax = 0; } if (app->username) { if (app->password == 0 && !strchr(app->username, ':')) { app->password = getPassword(); } httpSetCredentials(conn, app->username, app->password, app->authType); } for (count = 0; count < app->iterations; count++) { if (mprShouldDenyNewRequests(conn)) { break; } if (!app->success && !app->continueOnErrors) { break; } if (app->singleStep) waitForUser(); if (app->files && !app->upload) { for (next = 0; (path = mprGetNextItem(app->files, &next)) != 0; ) { /* If URL ends with "/", assume it is a directory on the target and append each file name */ if (app->target[strlen(app->target) - 1] == '/') { url = mprJoinPath(app->target, mprGetPathBase(path)); } else { url = app->target; } app->requestFiles = mprCreateList(-1, MPR_LIST_STATIC_VALUES | MPR_LIST_STABLE); mprAddItem(app->requestFiles, path); td->url = url = resolveUrl(conn, url); if (app->verbose) { mprPrintf("putting: %s to %s\n", path, url); } if (doRequest(conn, url, app->requestFiles) < 0) { app->success = 0; break; } } } else { td->url = url = resolveUrl(conn, app->target); if (doRequest(conn, url, app->files) < 0) { app->success = 0; break; } } if (app->verbose > 1) { mprPrintf("."); } } httpDestroyConn(conn); mprDestroyDispatcher(conn->dispatcher); finishThread(tp); }
MAIN(ejsMain, int argc, char **argv, char **envp) { Mpr *mpr; Ejs *ejs; EcCompiler *ec; char *argp, *searchPath, *path, *homeDir; int nextArg, err, flags; /* Initialize Multithreaded Portable Runtime (MPR) */ mpr = mprCreate(argc, argv, 0); app = mprAllocObj(App, manageApp); mprAddRoot(app); mprAddStandardSignals(); if (mprStart(mpr) < 0) { mprError("Cannot start mpr services"); return EJS_ERR; } err = 0; searchPath = 0; argc = mpr->argc; argv = (char**) mpr->argv; for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (smatch(argp, "--chdir") || smatch(argp, "--home") || smatch(argp, "-C")) { if (nextArg >= argc) { err++; } else { homeDir = argv[++nextArg]; if (chdir((char*) homeDir) < 0) { mprError("Cannot change directory to %s", homeDir); } } } else if (smatch(argp, "--debugger") || smatch(argp, "-D")) { mprSetDebugMode(1); } else if (smatch(argp, "--log")) { if (nextArg >= argc) { err++; } else { mprStartLogging(argv[++nextArg], 0); mprSetCmdlineLogging(1); } } else if (smatch(argp, "--name")) { /* Just ignore. Used to tag commands with a unique command line */ nextArg++; } else if (smatch(argp, "--search") || smatch(argp, "--searchpath")) { if (nextArg >= argc) { err++; } else { searchPath = argv[++nextArg]; } } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) { mprStartLogging("stderr:1", 0); mprSetCmdlineLogging(1); } else if (smatch(argp, "--version") || smatch(argp, "-V")) { mprPrintf("%s-%s\n", BIT_VERSION, BIT_BUILD_NUMBER); return 0; } else { /* Ignore */ } } path = mprJoinPath(mprGetAppDir(), mprGetPathBase(argv[0])); path = mprReplacePathExt(path, ".es"); mprAddRoot(path); argv[0] = path; if ((ejs = ejsCreateVM(argc, (cchar **) &argv[0], 0)) == 0) { return MPR_ERR_MEMORY; } app->ejs = ejs; if (ejsLoadModules(ejs, searchPath, NULL) < 0) { return MPR_ERR_CANT_READ; } mprLog(2, "Load script \"%s\"", path); flags = EC_FLAGS_BIND | EC_FLAGS_DEBUG | EC_FLAGS_NO_OUT | EC_FLAGS_THROW; if ((ec = ecCreateCompiler(ejs, flags)) == 0) { return MPR_ERR_MEMORY; } mprAddRoot(ec); ecSetOptimizeLevel(ec, 9); ecSetWarnLevel(ec, 1); if (ecCompile(ec, 1, (char**) &path) < 0) { if (flags & EC_FLAGS_THROW) { ejsThrowSyntaxError(ejs, "%s", ec->errorMsg ? ec->errorMsg : "Cannot parse script"); ejsReportError(ejs, "Error in script"); } err = MPR_ERR; } else { mprRemoveRoot(ec); if (ejsRunProgram(ejs, NULL, NULL) < 0) { ejsReportError(ejs, "Error in script"); err = MPR_ERR; } } if (!err) { err = mpr->exitStatus; } app->ejs = 0; mprTerminate(MPR_EXIT_DEFAULT, err); ejsDestroyVM(ejs); mprDestroy(MPR_EXIT_DEFAULT); return err; }
static void startCgi(MaQueue *q) { MaRequest *req; MaConn *conn; MprCmd *cmd; MprHash *hp; cchar *baseName; char **argv, **envv, *fileName; int index, argc, varCount; argv = 0; argc = 0; conn = q->conn; req = conn->request; if ((req->form || req->flags & MA_REQ_UPLOADING) && conn->state <= MPR_HTTP_STATE_CONTENT) { /* Delay starting the CGI process if uploading files or a form request. This enables env vars to be defined with file upload and form data before starting the CGI gateway. */ return; } cmd = q->queueData = mprCreateCmd(req); if (conn->http->forkCallback) { cmd->forkCallback = conn->http->forkCallback; cmd->forkData = conn->http->forkData; } /* Build the commmand line arguments */ argc = 1; /* argv[0] == programName */ buildArgs(conn, cmd, &argc, &argv); fileName = argv[0]; baseName = mprGetPathBase(q, fileName); if (strncmp(baseName, "nph-", 4) == 0 || (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0)) { /* Pretend we've seen the header for Non-parsed Header CGI programs */ cmd->userFlags |= MA_CGI_SEEN_HEADER; } /* Build environment variables */ varCount = mprGetHashCount(req->headers) + mprGetHashCount(req->formVars); envv = (char**) mprAlloc(cmd, (varCount + 1) * (int) sizeof(char*)); index = 0; hp = mprGetFirstHash(req->headers); while (hp) { if (hp->data) { envv[index] = mprStrcat(cmd, -1, hp->key, "=", (char*) hp->data, NULL); index++; } hp = mprGetNextHash(req->headers, hp); } hp = mprGetFirstHash(req->formVars); while (hp) { if (hp->data) { envv[index] = mprStrcat(cmd, -1, hp->key, "=", (char*) hp->data, NULL); index++; } hp = mprGetNextHash(req->formVars, hp); } envv[index] = 0; mprAssert(index <= varCount); cmd->stdoutBuf = mprCreateBuf(cmd, MA_BUFSIZE, -1); cmd->stderrBuf = mprCreateBuf(cmd, MA_BUFSIZE, -1); cmd->lastActivity = mprGetTime(cmd); mprSetCmdDir(cmd, mprGetPathDir(q, fileName)); mprSetCmdCallback(cmd, cgiCallback, conn); maSetHeader(conn, 0, "Last-Modified", req->host->currentDate); maDontCacheResponse(conn); maPutForService(q, maCreateHeaderPacket(q), 0); if (mprStartCmd(cmd, argc, argv, envv, MPR_CMD_IN | MPR_CMD_OUT | MPR_CMD_ERR) < 0) { maFailRequest(conn, MPR_HTTP_CODE_SERVICE_UNAVAILABLE, "Can't run CGI process: %s, URI %s", fileName, req->url); return; } /* This will dedicate this thread to the connection. It will also put the socket into blocking mode. */ maDedicateThreadToConn(conn); }
/* * 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 main(int argc, char *argv[], char *envp[]) #endif { char *cp, *method; int i, j, err; err = 0; outputArgs = outputQuery = outputEnv = outputPost = 0; outputBytes = outputHeaderLines = responseStatus = 0; outputLocation = 0; nonParsedHeader = 0; responseMsg = 0; hasError = 0; timeout = 0; queryBuf = 0; queryLen = 0; numQueryKeys = numPostKeys = 0; originalArgc = argc; originalArgv = argv; mpr = mprCreate(argc, argv, NULL); #if _WIN32 && !WINCE _setmode(0, O_BINARY); _setmode(1, O_BINARY); _setmode(2, O_BINARY); #endif if (strncmp(mprGetPathBase(mpr, argv[0]), "nph-", 4) == 0) { nonParsedHeader++; } if (getArgv(mpr, &argc, &argv, originalArgc, originalArgv) < 0) { error(mpr, "Can't read CGI input"); } for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { continue; } for (cp = &argv[i][1]; *cp; cp++) { switch (*cp) { case 'a': outputArgs++; break; case 'b': if (++i >= argc) { err = __LINE__; } else { outputBytes = atoi(argv[i]); } break; case 'e': outputEnv++; break; case 'h': if (++i >= argc) { err = __LINE__; } else { outputHeaderLines = atoi(argv[i]); nonParsedHeader++; } break; case 'l': if (++i >= argc) { err = __LINE__; } else { outputLocation = argv[i]; if (responseStatus == 0) { responseStatus = 302; } } break; case 'n': nonParsedHeader++; break; case 'p': outputPost++; break; case 'q': outputQuery++; break; case 's': if (++i >= argc) { err = __LINE__; } else { responseStatus = atoi(argv[i]); } break; case 't': if (++i >= argc) { err = __LINE__; } else { timeout = atoi(argv[i]); } break; default: err = __LINE__; break; } } } if (err) { mprError(mpr, "usage: cgiProgram -aenp [-b bytes] [-h lines]\n" "\t[-l location] [-s status] [-t timeout]\n" "\tor set the HTTP_SWITCHES environment variable\n"); mprError(mpr, "Error at cgiProgram:%d\n", __LINE__); exit(255); } method = getenv("REQUEST_METHOD") ; if (method == 0) { method = "GET"; } else { if (strcmp(method, "POST") == 0) { postBuf = mprCreateBuf(mpr, -1, -1); if (getPostData(mpr, postBuf) < 0) { error(mpr, "Can't read CGI input"); } if (strcmp(safeGetenv("CONTENT_TYPE"), "application/x-www-form-urlencoded") == 0) { numPostKeys = getVars(mpr, &postKeys, mprGetBufStart(postBuf), mprGetBufLength(postBuf)); } } } if (hasError) { if (! nonParsedHeader) { mprPrintf(mpr, "HTTP/1.0 %d %s\r\n\r\n", responseStatus, responseMsg); mprPrintf(mpr, "<HTML><BODY><p>Error: %d -- %s</p></BODY></HTML>\r\n", responseStatus, responseMsg); } exit(2); } if (nonParsedHeader) { if (responseStatus == 0) { mprPrintf(mpr, "HTTP/1.0 200 OK\r\n"); } else { mprPrintf(mpr, "HTTP/1.0 %d %s\r\n", responseStatus, responseMsg ? responseMsg: ""); } mprPrintf(mpr, "Connection: close\r\n"); mprPrintf(mpr, "X-CGI-CustomHeader: Any value at all\r\n"); } mprPrintf(mpr, "Content-type: %s\r\n", "text/html"); if (outputHeaderLines) { j = 0; for (i = 0; i < outputHeaderLines; i++) { mprPrintf(mpr, "X-CGI-%d: A loooooooooooooooooooooooong string\r\n", i); } } if (outputLocation) { mprPrintf(mpr, "Location: %s\r\n", outputLocation); } if (responseStatus) { mprPrintf(mpr, "Status: %d\r\n", responseStatus); } mprPrintf(mpr, "\r\n"); if ((outputBytes + outputArgs + outputEnv + outputQuery + outputPost + outputLocation + responseStatus) == 0) { outputArgs++; outputEnv++; outputQuery++; outputPost++; } if (outputBytes) { j = 0; for (i = 0; i < outputBytes; i++) { putchar('0' + j); j++; if (j > 9) { if (++outputBytes > 0) { putchar('\r'); } if (++outputBytes > 0) { putchar('\n'); } j = 0; } } } /* else */ { mprPrintf(mpr, "<HTML><TITLE>cgiProgram: Output</TITLE><BODY>\r\n"); if (outputArgs) { #if _WIN32 mprPrintf(mpr, "<P>CommandLine: %s</P>\r\n", GetCommandLine()); #endif mprPrintf(mpr, "<H2>Args</H2>\r\n"); for (i = 0; i < argc; i++) { mprPrintf(mpr, "<P>ARG[%d]=%s</P>\r\n", i, argv[i]); } } #if !VXWORKS && !WINCE if (outputEnv) { printEnv(envp); } #endif if (outputQuery) { printQuery(); } if (outputPost) { printPost(postBuf); } if (timeout) { mprSleep(mpr, timeout * MPR_TICKS_PER_SEC); } mprPrintf(mpr, "</BODY></HTML>\r\n"); } #if VXWORKS /* * VxWorks pipes need an explicit eof string */ write(1, MPR_CMD_VXWORKS_EOF, MPR_CMD_VXWORKS_EOF_LEN); write(2, MPR_CMD_VXWORKS_EOF, MPR_CMD_VXWORKS_EOF_LEN); /* * Must not call exit(0) in Vxworks as that will exit the task before the CGI handler can cleanup. Must use return 0. */ #endif return 0; }