Exemple #1
0
/*
    Path is the path to the esp.json
 */
static int defineApp(HttpRoute *route, cchar *path)
{
    EspRoute    *eroute;

    if ((eroute = espRoute(route)) == 0) {
        return MPR_ERR_MEMORY;
    }
    eroute->top = eroute;
    if (path) {
        if (!mprPathExists(path, R_OK)) {
            mprLog("error esp", 0, "Cannot open %s", path);
            return MPR_ERR_CANT_FIND;
        }
        httpSetRouteHome(route, mprGetPathDir(path));
        eroute->configFile = sclone(path);
    }
    espSetDefaultDirs(route);

    httpAddRouteHandler(route, "espHandler", "");
    httpAddRouteIndex(route, "index.esp");
    httpAddRouteIndex(route, "index.html");
    httpSetRouteXsrf(route, 1);
    mprLog("info esp", 3, "ESP app: %s", path);
    return 0;
}
Exemple #2
0
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;
}
Exemple #3
0
/*
    Set the platform objects location
 */
PUBLIC int httpSetPlatformDir(cchar *path)
{
    Http    *http;

    http = HTTP;
    if (path) {
        if (mprPathExists(path, X_OK)) {
            http->platformDir = mprGetAbsPath(path);
        } else {
            /*
                Possible source tree platform directory
             */
            http->platformDir = mprJoinPath(mprGetPathDir(mprGetPathDir(mprGetPathDir(mprGetAppPath()))), path);
            if (!mprPathExists(http->platformDir, X_OK)) {
                http->platformDir = mprGetAbsPath(path);
            }
        }
    } else {
        http->platformDir = mprGetPathDir(mprGetPathDir(mprGetAppPath()));
    }
    return 0;
}
Exemple #4
0
static void outputHeader(HttpQueue *q, cchar *path, int nameSize)
{
    Dir     *dir;
    char    *parent, *parentSuffix;
    int     reverseOrder, fancy, isRootDir;

    dir = q->conn->data;
    fancy = 1;
    path = mprEscapeHtml(path);

    httpWrite(q, "<!DOCTYPE HTML PUBLIC \"-/*W3C//DTD HTML 3.2 Final//EN\">\r\n");
    httpWrite(q, "<html>\r\n <head>\r\n  <title>Index of %s</title>\r\n", path);
    httpWrite(q, " </head>\r\n");
    httpWrite(q, "<body>\r\n");

    httpWrite(q, "<h1>Index of %s</h1>\r\n", path);

    if (dir->sortOrder > 0) {
        reverseOrder = 'D';
    } else {
        reverseOrder = 'A';
    }
    if (dir->fancyIndexing == 0) {
        fancy = '0';
    } else if (dir->fancyIndexing == 1) {
        fancy = '1';
    } else if (dir->fancyIndexing == 2) {
        fancy = '2';
    }
    parent = mprGetPathDir(path);
    if (parent[strlen(parent) - 1] != '/') {
        parentSuffix = "/";
    } else {
        parentSuffix = "";
    }
    isRootDir = (strcmp(path, "/") == 0);

    if (dir->fancyIndexing == 2) {
        httpWrite(q, "<table><tr><th><img src=\"/icons/blank.gif\" alt=\"[ICO]\" /></th>");

        httpWrite(q, "<th><a href=\"?C=N;O=%c;F=%c\">Name</a></th>", reverseOrder, fancy);
        httpWrite(q, "<th><a href=\"?C=M;O=%c;F=%c\">Last modified</a></th>", reverseOrder, fancy);
        httpWrite(q, "<th><a href=\"?C=S;O=%c;F=%c\">Size</a></th>", reverseOrder, fancy);
        httpWrite(q, "<th><a href=\"?C=D;O=%c;F=%c\">Description</a></th>\r\n", reverseOrder, fancy);

        httpWrite(q, "</tr><tr><th colspan=\"5\"><hr /></th></tr>\r\n");

        if (! isRootDir) {
            httpWrite(q, "<tr><td valign=\"top\"><img src=\"/icons/back.gif\"");
            httpWrite(q, "alt=\"[DIR]\" /></td><td><a href=\"%s%s\">", parent, parentSuffix);
            httpWrite(q, "Parent Directory</a></td>");
            httpWrite(q, "<td align=\"right\">  - </td></tr>\r\n");
        }

    } else if (dir->fancyIndexing == 1) {
        httpWrite(q, "<pre><img src=\"/icons/space.gif\" alt=\"Icon\" /> ");

        httpWrite(q, "<a href=\"?C=N;O=%c;F=%c\">Name</a>%*s", reverseOrder, fancy, nameSize - 3, " ");
        httpWrite(q, "<a href=\"?C=M;O=%c;F=%c\">Last modified</a>       ", reverseOrder, fancy);
        httpWrite(q, "<a href=\"?C=S;O=%c;F=%c\">Size</a>               ", reverseOrder, fancy);
        httpWrite(q, "<a href=\"?C=D;O=%c;F=%c\">Description</a>\r\n", reverseOrder, fancy);

        httpWrite(q, "<hr />");

        if (! isRootDir) {
            httpWrite(q, "<img src=\"/icons/parent.gif\" alt=\"[DIR]\" />");
            httpWrite(q, " <a href=\"%s%s\">Parent Directory</a>\r\n", parent, parentSuffix);
        }

    } else {
        httpWrite(q, "<ul>\n");
        if (! isRootDir) {
            httpWrite(q, "<li><a href=\"%s%s\"> Parent Directory</a></li>\r\n", parent, parentSuffix);
        }
    }
}
Exemple #5
0
/*
    Executed by the child process
 */
static void cmdTaskEntry(char *program, MprCmdTaskFn entry, int cmdArg)
{
    MprCmd          *cmd;
    MprCmdFile      *files;
    WIND_TCB        *tcb;
    char            *item;
    int             inFd, outFd, errFd, id, next;

    cmd = (MprCmd*) cmdArg;

    /*
        Open standard I/O files (in/out are from the server's perspective)
     */
    files = cmd->files;
    inFd = open(files[MPR_CMD_STDIN].name, O_RDONLY, 0666);
    outFd = open(files[MPR_CMD_STDOUT].name, O_WRONLY, 0666);
    errFd = open(files[MPR_CMD_STDERR].name, O_WRONLY, 0666);

    if (inFd < 0 || outFd < 0 || errFd < 0) {
        exit(255);
    }
    id = taskIdSelf();
    ioTaskStdSet(id, 0, inFd);
    ioTaskStdSet(id, 1, outFd);
    ioTaskStdSet(id, 2, errFd);

    /*
        Now that we have opened the stdin and stdout, wakeup our parent.
     */
    semGive(cmd->startCond);

    /*
        Create the environment
     */
    if (envPrivateCreate(id, -1) < 0) {
        exit(254);
    }
    for (ITERATE_ITEMS(cmd->env, item, next)) {
        putenv(item);
    }

#if !VXWORKS
{
    char    *dir;
    int     rc;

    /*
        Set current directory if required
        WARNING: Setting working directory on VxWorks is global
     */
    if (cmd->dir) {
        rc = chdir(cmd->dir);
    } else {
        dir = mprGetPathDir(cmd->program);
        rc = chdir(dir);
    }
    if (rc < 0) {
        mprLog("error mpr cmd", 0, "Cannot change directory to %s", cmd->dir);
        exit(255);
    }
}
#endif

    /*
        Call the user's entry point
     */
    (entry)(cmd->argc, (char**) cmd->argv, (char**) cmd->env);

    tcb = taskTcb(id);
    cmd->status = tcb->exitCode;

    /*
        Cleanup
     */
    envPrivateDestroy(id);
    close(inFd);
    close(outFd);
    close(errFd);
    semGive(cmd->exitCond);
}
Exemple #6
0
/*
    Determine the windows program to invoke.
    Support UNIX style "#!/program" bang directives on windows.
    Also supports ".cmd" and ".bat" alternatives.
 */
static void prepWinProgram(MprCmd *cmd)
{
#if ME_WIN_LIKE
    MprFile     *file;
    cchar       *bat, *ext, *shell, *cp, *start;
    char        bang[ME_MAX_FNAME + 1], *path, *pp;

    /*
        Map separators, convert carriage-returns and newlines to spaces and remove quotes on the command
     */
    path = mprAlloc(slen(cmd->argv[0]) * 2 + 1);
    strcpy(path, cmd->argv[0]);
    for (pp = path; *pp; pp++) {
        if (*pp == '/') {
            *pp = '\\';
        } else if (*pp == '\r' || *pp == '\n') {
            *pp = ' ';
        }
    }
    if (*path == '\"') {
        if ((pp = strrchr(++path, '"')) != 0) {
            *pp = '\0';
        }
        path = sclone(path);
    }
    cmd->argv[0] = path;

    /*
        Support ".cmd" and ".bat" files that take precedence
     */
    if ((ext = mprGetPathExt(path)) == 0) {
        if ((bat = mprSearchPath(mprJoinPathExt(path, ".cmd"), MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) {
            bat = mprSearchPath(mprJoinPathExt(path, ".bat"), MPR_SEARCH_EXE, cmd->searchPath, NULL);
        }
        if (bat) {
            if ((shell = getenv("COMSPEC")) == 0) {
                shell = "cmd.exe";
            }
            cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 4) * sizeof(char*));
            memmove((void*) &cmd->argv[3], (void*) cmd->argv, sizeof(char*) * (cmd->argc + 1));
            cmd->argv[0] = sclone(shell);
            cmd->argv[1] = sclone("/Q");
            cmd->argv[2] = sclone("/C");
            cmd->argv[3] = bat;
            cmd->argc += 3;
            cmd->argv[cmd->argc] = 0;
            return;
        }
    }
    if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) {
        if (mprReadFile(file, bang, ME_MAX_FNAME) > 0) {
            mprCloseFile(file);
            bang[ME_MAX_FNAME] = '\0';
            if (bang[0] == '#' && bang[1] == '!') {
                cp = start = &bang[2];
                shell = ssplit(&bang[2], "\r\n", NULL);
                if (!mprIsPathAbs(shell)) {
                    /*
                        If we cannot access the command shell and the command is not an absolute path,
                        look in the same directory as the script.
                     */
                    if (mprPathExists(shell, X_OK)) {
                        shell = mprJoinPath(mprGetPathDir(path), shell);
                    }
                }
                /*
                    Get length of argv with NULL and add one
                 */
                assert(cmd->argv[cmd->argc] == 0);
                cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 2) * sizeof(char*));
                cmd->argv[cmd->argc + 1] = 0;

                /*
                    Copy up to make room to insert the shell argument. This copies the original NULL
                 */
                memmove((void*) &cmd->argv[1], (void*) cmd->argv, sizeof(char*) * cmd->argc);
                cmd->argv[0] = sclone(shell);
                cmd->argv[1] = path;
                cmd->argc += 1;
                assert(cmd->argv[cmd->argc] == 0);
            }
        } else {
            mprCloseFile(file);
        }
    }
#endif
}
Exemple #7
0
/*
    If the program has a UNIX style "#!/program" string at the start of the file that program will be selected 
    and the original program will be passed as the first arg to that program with argv[] appended after that. If 
    the program is not found, this routine supports a safe intelligent search for the command. If all else fails, 
    we just return in program the fileName we were passed in. script will be set if we are modifying the program 
    to run and we have extracted the name of the file to run as a script.
 */
static void findExecutable(HttpConn *conn, char **program, char **script, char **bangScript, cchar *fileName)
{
    HttpRx      *rx;
    HttpTx      *tx;
    HttpRoute   *route;
    MprKey      *kp;
    MprFile     *file;
    cchar       *actionProgram, *ext, *cmdShell, *cp, *start, *path;
    char        buf[ME_MAX_FNAME + 1];

    rx = conn->rx;
    tx = conn->tx;
    route = rx->route;

    *bangScript = 0;
    *script = 0;
    *program = 0;
    path = 0;

    actionProgram = mprGetMimeProgram(rx->route->mimeTypes, rx->mimeType);
    ext = tx->ext;

    /*
        If not found, go looking for the fileName with the extensions defined in appweb.conf. 
        NOTE: we don't use PATH deliberately!!!
     */
    if (access(fileName, X_OK) < 0) {
        for (kp = 0; (kp = mprGetNextKey(route->extensions, kp)) != 0; ) {
            path = sjoin(fileName, ".", kp->key, NULL);
            if (access(path, X_OK) == 0) {
                break;
            }
            path = 0;
        }
        if (kp) {
            ext = kp->key;
        } else {
            path = fileName;
        }

    } else {
        path = fileName;
    }
    assert(path && *path);

#if ME_WIN_LIKE
    if (ext && (strcmp(ext, ".bat") == 0 || strcmp(ext, ".cmd") == 0)) {
        /*
            Let a mime action override COMSPEC
         */
        if (actionProgram) {
            cmdShell = actionProgram;
        } else {
            cmdShell = getenv("COMSPEC");
        }
        if (cmdShell == 0) {
            cmdShell = "cmd.exe";
        }
        *script = sclone(path);
        *program = sclone(cmdShell);
        return;
    }
#endif

    if (actionProgram) {
        *program = sclone(actionProgram);

    } else if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) {
        if (mprReadFile(file, buf, ME_MAX_FNAME) > 0) {
            mprCloseFile(file);
            buf[ME_MAX_FNAME] = '\0';
            if (buf[0] == '#' && buf[1] == '!') {
                cp = start = &buf[2];
                cmdShell = ssplit(&buf[2], "\r\n", NULL);
                if (!mprIsPathAbs(cmdShell)) {
                    /*
                        If we cannot access the command shell and the command is not an absolute path, 
                        look in the same directory as the script.
                     */
                    if (mprPathExists(cmdShell, X_OK)) {
                        cmdShell = mprJoinPath(mprGetPathDir(path), cmdShell);
                    }
                }
                *program = sclone(cmdShell);
                *bangScript = sclone(path);
                return;
            }
        } else {
            mprCloseFile(file);
        }
    }

    if (actionProgram) {
        *program = sclone(actionProgram);
        *bangScript = sclone(path);
    } else {
        *program = sclone(path);
    }
    return;
}
Exemple #8
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
}
Exemple #9
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;
}
Exemple #10
0
/*
    If the program has a UNIX style "#!/program" string at the start of the file that program will be selected 
    and the original program will be passed as the first arg to that program with argv[] appended after that. If 
    the program is not found, this routine supports a safe intelligent search for the command. If all else fails, 
    we just return in program the fileName we were passed in. script will be set if we are modifying the program 
    to run and we have extracted the name of the file to run as a script.
 */
static void findExecutable(MaConn *conn, char **program, char **script, char **bangScript, char *fileName)
{
    MaRequest       *req;
    MaResponse      *resp;
    MaLocation      *location;
    MprHash         *hp;
    MprFile         *file;
    cchar           *actionProgram, *ext, *cmdShell;
    char            *tok, buf[MPR_MAX_FNAME + 1], *path;

    req = conn->request;
    resp = conn->response;
    location = req->location;

    *bangScript = 0;
    *script = 0;
    *program = 0;
    path = 0;

    actionProgram = maGetMimeActionProgram(conn->host, req->mimeType);
    ext = resp->extension;

    /*
        If not found, go looking for the fileName with the extensions defined in appweb.conf. 
        NOTE: we don't use PATH deliberately!!!
     */
    if (access(fileName, X_OK) < 0 /* && *ext == '\0' */) {
        for (hp = 0; (hp = mprGetNextHash(location->extensions, hp)) != 0; ) {
            path = mprStrcat(resp, -1, fileName, ".", hp->key, NULL);
            if (access(path, X_OK) == 0) {
                break;
            }
            mprFree(path);
            path = 0;
        }
        if (hp) {
            ext = hp->key;
        } else {
            path = fileName;
        }

    } else {
        path = fileName;
    }
    mprAssert(path && *path);

#if BLD_WIN_LIKE
    if (ext && (strcmp(ext, ".bat") == 0 || strcmp(ext, ".cmd") == 0)) {
        /*
            Let a mime action override COMSPEC
         */
        if (actionProgram) {
            cmdShell = actionProgram;
        } else {
            cmdShell = getenv("COMSPEC");
        }
        if (cmdShell == 0) {
            cmdShell = "cmd.exe";
        }
        *script = mprStrdup(resp, path);
        *program = mprStrdup(resp, cmdShell);
        return;
    }
#endif

    if ((file = mprOpen(resp, path, O_RDONLY, 0)) != 0) {
        if (mprRead(file, buf, MPR_MAX_FNAME) > 0) {
            mprFree(file);
            buf[MPR_MAX_FNAME] = '\0';
            if (buf[0] == '#' && buf[1] == '!') {
                cmdShell = mprStrTok(&buf[2], " \t\r\n", &tok);
                if (cmdShell[0] != '/' && (cmdShell[0] != '\0' && cmdShell[1] != ':')) {
                    /*
                        If we can't access the command shell and the command is not an absolute path, 
                        look in the same directory as the script.
                     */
                    if (mprPathExists(resp, cmdShell, X_OK)) {
                        cmdShell = mprJoinPath(resp, mprGetPathDir(resp, path), cmdShell);
                    }
                }
                if (actionProgram) {
                    *program = mprStrdup(resp, actionProgram);
                } else {
                    *program = mprStrdup(resp, cmdShell);
                }
                *bangScript = mprStrdup(resp, path);
                return;
            }
        } else {
            mprFree(file);
        }
    }

    if (actionProgram) {
        *program = mprStrdup(resp, actionProgram);
        *bangScript = mprStrdup(resp, path);
    } else {
        *program = mprStrdup(resp, path);
    }
    return;
}
Exemple #11
0
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);
}
Exemple #12
0
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);
}
Exemple #13
0
/*
    Convert an ESP web page into C code
    Directives:

        <%@ include "file"  Include an esp file
        <%@ layout "file"   Specify a layout page to use. Use layout "" to disable layout management
        <%@ content         Mark the location to substitute content in a layout pag

        <%                  Begin esp section containing C code
        <%^ global          Put esp code at the global level
        <%^ start           Put esp code at the start of the function
        <%^ end             Put esp code at the end of the function

        <%=                 Begin esp section containing an expression to evaluate and substitute
        <%= [%fmt]          Begin a formatted expression to evaluate and substitute. Format is normal printf format.
                            Use %S for safe HTML escaped output.
        %>                  End esp section
        -%>                 End esp section and trim trailing newline

        @@var               Substitue the value of a variable. Var can also be simple expressions (without spaces)
        @#field             Lookup the current record for the value of the field.

 */
char *espBuildScript(HttpRoute *route, cchar *page, cchar *path, cchar *cacheName, cchar *layout, char **err)
{
    EspParse    parse;
    char        *control, *incBuf, *incText, *global, *token, *body, *where;
    char        *rest, *start, *end, *include, *line, *fmt, *layoutPage, *layoutBuf;
    ssize       len;
    int         tid;

    mprAssert(page);

    body = start = end = global = "";
    *err = 0;

    memset(&parse, 0, sizeof(parse));
    parse.data = (char*) page;
    parse.next = parse.data;

    if ((parse.token = mprCreateBuf(-1, -1)) == 0) {
        return 0;
    }
    tid = getEspToken(&parse);
    while (tid != ESP_TOK_EOF) {
        token = mprGetBufStart(parse.token);
#if FUTURE
        if (parse.lineNumber != lastLine) {
            body = sfmt("\n# %d \"%s\"\n", parse.lineNumber, path);
        }
#endif
        switch (tid) {
        case ESP_TOK_CODE:
            if (*token == '^') {
                for (token++; *token && isspace((int) *token); token++) ;
                where = stok(token, " \t\r\n", &rest);
                if (rest == 0) {
                    ;
                } else if (scmp(where, "global") == 0) {
                    global = sjoin(global, rest, NULL);

                } else if (scmp(where, "start") == 0) {
                    if (*start == '\0') {
                        start = "  ";
                    }
                    start = sjoin(start, rest, NULL);

                } else if (scmp(where, "end") == 0) {
                    if (*end == '\0') {
                        end = "  ";
                    }
                    end = sjoin(end, rest, NULL);
                }
            } else {
                body = sjoin(body, token, NULL);
            }
            break;

        case ESP_TOK_CONTROL:
            /* NOTE: layout parsing not supported */
            control = stok(token, " \t\r\n", &token);
            if (scmp(control, "content") == 0) {
                body = sjoin(body, CONTENT_MARKER, NULL);

            } else if (scmp(control, "include") == 0) {
                if (token == 0) {
                    token = "";
                }
                token = strim(token, " \t\r\n\"", MPR_TRIM_BOTH);
                token = mprNormalizePath(token);
                if (token[0] == '/') {
                    include = sclone(token);
                } else {
                    include = mprJoinPath(mprGetPathDir(path), token);
                }
                if ((incText = mprReadPathContents(include, &len)) == 0) {
                    *err = sfmt("Can't read include file: %s", include);
                    return 0;
                }
                /* Recurse and process the include script */
                incBuf = 0;
                if ((incBuf = espBuildScript(route, incText, include, NULL, NULL, err)) == 0) {
                    return 0;
                }
                body = sjoin(body, incBuf, NULL);

            } else if (scmp(control, "layout") == 0) {
                token = strim(token, " \t\r\n\"", MPR_TRIM_BOTH);
                if (*token == '\0') {
                    layout = 0;
                } else {
                    token = mprNormalizePath(token);
                    if (token[0] == '/') {
                        layout = sclone(token);
                    } else {
                        layout = mprJoinPath(mprGetPathDir(path), token);
                    }
                    if (!mprPathExists(layout, F_OK)) {
                        *err = sfmt("Can't access layout page %s", layout);
                        return 0;
                    }
                }

            } else {
                *err = sfmt("Unknown control %s at line %d", control, parse.lineNumber);
                return 0;                
            }
            break;

        case ESP_TOK_ERR:
            return 0;

        case ESP_TOK_EXPR:
            /* <%= expr %> */
            if (*token == '%') {
                fmt = stok(token, ": \t\r\n", &token);
                if (token == 0) { 
                    token = "";
                }
            } else {
                fmt = "%s";
            }
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            body = sjoin(body, "  espRender(conn, \"", fmt, "\", ", token, ");\n", NULL);
            break;

        case ESP_TOK_FIELD:
            /* @#field */
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            body = sjoin(body, "  espRender(conn, getField(\"", token, "\"));\n", NULL);
            break;

        case ESP_TOK_LITERAL:
            line = joinLine(token, &len);
            body = sfmt("%s  espRenderBlock(conn, \"%s\", %d);\n", body, line, len);
            break;

        case ESP_TOK_VAR:
            /* @@var */
            token = strim(token, " \t\r\n;", MPR_TRIM_BOTH);
            /* espRenderParam uses espRenderSafeString */
            body = sjoin(body, "  espRenderParam(conn, \"", token, "\");\n", NULL);
            break;

        default:
            return 0;
        }
        tid = getEspToken(&parse);
    }
    if (cacheName) {
        /*
            CacheName will only be set for the outermost invocation
         */
        if (layout && mprPathExists(layout, R_OK)) {
            if ((layoutPage = mprReadPathContents(layout, &len)) == 0) {
                *err = sfmt("Can't read layout page: %s", layout);
                return 0;
            }
            layoutBuf = 0;
            if ((layoutBuf = espBuildScript(route, layoutPage, layout, NULL, NULL, err)) == 0) {
                return 0;
            }
            body = sreplace(layoutBuf, CONTENT_MARKER, body);
        }
        if (start && start[slen(start) - 1] != '\n') {
            start = sjoin(start, "\n", NULL);
        }
        if (end && end[slen(end) - 1] != '\n') {
            end = sjoin(end, "\n", NULL);
        }
        mprAssert(slen(path) > slen(route->dir));
        mprAssert(sncmp(path, route->dir, slen(route->dir)) == 0);
        if (sncmp(path, route->dir, slen(route->dir)) == 0) {
            path = &path[slen(route->dir) + 1];
        }
        body = sfmt(\
            "/*\n   Generated from %s\n */\n"\
            "#include \"esp-app.h\"\n"\
            "%s\n"\
            "static void %s(HttpConn *conn) {\n"\
            "%s%s%s"\
            "}\n\n"\
            "%s int esp_%s(HttpRoute *route, MprModule *module) {\n"\
            "   espDefineView(route, \"%s\", %s);\n"\
            "   return 0;\n"\
            "}\n",
            path, global, cacheName, start, body, end, ESP_EXPORT_STRING, cacheName, mprGetPortablePath(path), cacheName);
        mprLog(6, "Create ESP script: \n%s\n", body);
    }
    return body;
}
Exemple #14
0
/*
 *  Executed by the child process
 */
static void cmdTaskEntry(char *program, MprCmdTaskFn entry, int cmdArg)
{
    MprCmd          *cmd;
    MprCmdFile      *files;
    WIND_TCB        *tcb;
    char            **ep, *dir;
    int             inFd, outFd, errFd, id, rc;

    cmd = (MprCmd*) cmdArg;

    /*
     *  Open standard I/O files (in/out are from the server's perspective)
     */
    files = cmd->files;
    inFd = open(files[MPR_CMD_STDIN].name, O_RDONLY, 0666);
    outFd = open(files[MPR_CMD_STDOUT].name, O_WRONLY, 0666);
    errFd = open(files[MPR_CMD_STDERR].name, O_WRONLY, 0666);

    if (inFd < 0 || outFd < 0 || errFd < 0) {
        exit(255);
    }

    id = taskIdSelf();
    ioTaskStdSet(id, 0, inFd);
    ioTaskStdSet(id, 1, outFd);
    ioTaskStdSet(id, 2, errFd);

    /*
     *  Now that we have opened the stdin and stdout, wakeup our parent.
     */
    semGive(cmd->startCond);

    /*
     *  Create the environment
     */
    if (envPrivateCreate(id, -1) < 0) {
        exit(254);
    }
    for (ep = cmd->env; ep && *ep; ep++) {
        putenv(*ep);
    }

    /*
     *  Set current directory if required
     */
    if (cmd->dir) {
        rc = chdir(cmd->dir);
    } else {
        dir = mprGetPathDir(cmd, cmd->program);
        rc = chdir(dir);
        mprFree(dir);
    }
    if (rc < 0) {
        mprLog(cmd, 0, "cmd: Can't change directory to %s", cmd->dir);
        exit(255);
    }

    /*
     *  Call the user's entry point
     */
    (entry)(cmd->argc, cmd->argv, cmd->env);

    tcb = taskTcb(id);
    cmd->status = tcb->exitCode;

    /*
     *  Cleanup
     */
    envPrivateDestroy(id);
    close(inFd);
    close(outFd);
    close(errFd);
    semGive(cmd->exitCond);
}
Exemple #15
0
/*
    WARNING: may yield
 */
PUBLIC int espLoadConfig(HttpRoute *route)
{
    EspRoute    *eroute;
    cchar       *name, *package;
    bool        modified;

    eroute = route->eroute;
    if (!route->update) {
        return 0;
    }
    package = mprJoinPath(mprGetPathDir(eroute->configFile), "package.json");
    modified = 0;
    ifConfigModified(route, eroute->configFile, &modified);
    ifConfigModified(route, package, &modified);

    if (modified) {
        lock(esp);
        httpInitConfig(route);
#if DEPRECATED || 1
        /* Don't reload if configFile == package.json */
        if (!mprSamePath(package, eroute->configFile)) {
#endif
            if (mprPathExists(package, R_OK)) {
                if (httpLoadConfig(route, package) < 0) {
                    unlock(esp);
                    return MPR_ERR_CANT_LOAD;
                }
            }
        }
        if (httpLoadConfig(route, eroute->configFile) < 0) {
            unlock(esp);
            return MPR_ERR_CANT_LOAD;
        }
        if ((name = espGetConfig(route, "name", 0)) != 0) {
            eroute->appName = name;
        }
        if (espLoadCompilerRules(route) < 0) {
            return MPR_ERR_CANT_OPEN;
        }
        unlock(esp);
    }
    if (!route->cookie) {
        httpSetRouteCookie(route, sfmt("esp-%s", eroute->appName));
    }
    if (route->database && !eroute->edi) {
        if (espOpenDatabase(route, route->database) < 0) {
            mprLog("error esp", 0, "Cannot open database %s", route->database);
            return MPR_ERR_CANT_LOAD;
        }
    }
#if !ME_STATIC
    if (!(route->flags & HTTP_ROUTE_NO_LISTEN)) {
        MprJson     *preload, *item;
        cchar       *errMsg, *source;
        char        *kind;
        int         i;

        /*
            WARNING: may yield when compiling modules
         */
        if (eroute->combine) {
            source = mprJoinPaths(route->home, httpGetDir(route, "CACHE"), sfmt("%s.c", eroute->appName), NULL);
        } else {
            source = mprJoinPaths(route->home, httpGetDir(route, "SRC"), "app.c", NULL);
        }
        lock(esp);
        if (espLoadModule(route, NULL, "app", source, &errMsg) < 0) {
            if (eroute->combine) {
                mprLog("error esp", 0, "%s", errMsg);
                unlock(esp);
                return MPR_ERR_CANT_LOAD;
            }
        }
        if (!eroute->combine && (preload = mprGetJsonObj(route->config, "esp.preload")) != 0) {
            for (ITERATE_JSON(preload, item, i)) {
                source = ssplit(sclone(item->value), ":", &kind);
                if (*kind == '\0') {
                    kind = "controller";
                }
                source = mprJoinPaths(route->home, httpGetDir(route, "CONTROLLERS"), source, NULL);
                if (espLoadModule(route, NULL, kind, source, &errMsg) < 0) {
                    mprLog("error esp", 0, "Cannot preload esp module %s. %s", source, errMsg);
                    unlock(esp);
                    return MPR_ERR_CANT_LOAD;
                }
            }
        }
        unlock(esp);
    }