示例#1
0
文件: commands.c 项目: stroxler/lcthw
int Command_install(
        apr_pool_t *p, const char *url, const char *configure_opts,
        const char *make_opts, const char *install_opts
) {
    int rc = 0;
    // first clean up
    check(Shell_exec(CLEANUP_SH, NULL) == 0,
          "Faild to clean up before building.");
    // next, make sure it isn't already installed
    rc = DB_find(url);
    check(rc != -1, "Error checking the installed database");
    if (rc == 1) {
        log_info("Package already installed.");
        return 0;
    }
    // it isn't installed. So, fetch.
    rc = Command_fetch(p, url, 0);
    // if fetch worked, build.
    if (rc == 1) {
        rc = Command_build(p, url, configure_opts, make_opts, install_opts);
    } else if (rc == 0) {
        // no install needed... I haven't read fetch yet so I'm not sure how
        // this would happen.
        log_info("Depends successfully installed: %s", url);
    } else {
        sentinel("Install failed: %s", url);
    }
    // cleanup again. It doesn't matter whether we check errors this time.
    Shell_exec(CLEANUP_SH, NULL);
    return 0;
error:
    return -1;
}
示例#2
0
/*! \brief parse the CGI request and send it to the shell
 *
 *  \param pxNetCon   Input. The netconn to use to send and receive data.
 *  \param request    Input. The incoming CGI request.
 *
 */
static void prvweb_ParseCGIRequest( struct netconn *pxNetCon, char* request )
{
portCHAR cgi_present = false, loop;
signed portCHAR * pcStringCmd;
signed portCHAR * CurrentChar;
signed portCHAR * pcStringReply;
eExecStatus       xExeStatus;
portCHAR *pcResp_data;
portLONG header_size;

  /* when entering this function, path contains :
               command.cgi?arg1=val1&arg2=val2
  it should be command arg1=val1 arg2=val2 after parsing operation */

  /* allocate command space */
  pcStringCmd = pvPortMalloc( 100 );
  if (pcStringCmd != NULL)
  {

    loop = true;
    CurrentChar = pcStringCmd;
    while (loop)
    {
      switch (*request)
      {
        case '.':
        {
          if (cgi_present == false)
          {
            cgi_present = true;
            request += strlen(".cgi");
          }
          else
          {
            *CurrentChar++ = *request++;
          }
        break;
        }
        /* move ? and & to space */
        case '?':
        case '&':
          *CurrentChar++ = ' ';
          request++;
        break;
        case '%':
          /* move %20 to space */
          if ((*(request+1) == '2') && (*(request+2) == '0'))
          {
            *CurrentChar++ = ' ';
            request += 3;
          }
          /* keep %22 */
          else if ((*(request+1) == '2') && (*(request+2) == '2'))
          {
            *CurrentChar++ = '"';
            request += 3;
          }
          /* else keep the % symbol */
          else
          {
            *CurrentChar++ = *request++;
          }
        break;
        case '\r':
        case '\n':
        case '\0':
        case ' ':
          *CurrentChar = '\0';
          loop = false;
        break;
        default:
          *CurrentChar++ = *request++;
        break;
      }
    }

    /* send command to the shell, no error control for this module */
    xExeStatus = Shell_exec(pcStringCmd, SYS_MODID_HTTP, -1, &pcStringReply);
    /* free buffer */
    vPortFree(pcStringCmd);

    if (pcStringReply != NULL)
    {
        pcResp_data = pvPortMalloc( 130 + strlen( (char *)pcStringReply ) ); // 130(header size) + sizeof( reply )
        if( NULL == pcResp_data )
        {
           if( SHELL_EXECSTATUS_OK == xExeStatus )
           {
              vPortFree(pcStringReply);
           }
           NAKED_TRACE_COM2( "ParseCGIRequest(): reply mem alloc failed" );
           // Avoid returning an error page so that the remote web browser keeps
           // on trying.
           return;
        }
        /* add the header */
        header_size = prulweb_BuildHeaders( pcResp_data, 200, "OK", "", "", "text/html");
        // Add the data.
        strcpy( pcResp_data + header_size, (char *)pcStringReply );
        if( SHELL_EXECSTATUS_OK == xExeStatus )
        {
           vPortFree(pcStringReply);
        }

        /* send the response to network */
        netconn_write(pxNetCon, pcResp_data, (u16_t)strlen( pcResp_data ), NETCONN_COPY );
        vPortFree( pcResp_data );
    }
  }
  else
  {
    NAKED_TRACE_COM2( "ParseCGIRequest(): request mem alloc failed" );
    // Avoid returning an error page so that the remote web browser keeps on trying.
  }
}
示例#3
0
文件: commands.c 项目: stroxler/lcthw
int Command_fetch(apr_pool_t *p, const char *url, int fetch_only) {
    int rc = 0;
    const char *depends_file = NULL;

    // create the uri as an apr type
    // see https://apr.apache.org/docs/apr-util/0.9/structapr__uri__t.html
    // all you need to know for this program is that:
    //   - port of 0 indicates a default / a port-less url
    //   - path is the url as a string
    //   - scheme is the protocol (e.g. http, ftp, etc). I *think* this allows
    //     us to give plain old file paths if we want to, and then scheme would
    //     be null. The code seems to suggest it, anyway.
    apr_uri_t info = { .port = 0 };
    apr_status_t rv = apr_uri_parse(p, url, &info);
    check(rv = APR_SUCCESS, "Failed to parse URL: %s", url);

    // apr_fnmatch is apr's filename expression matcher. It follows roughly
    // the same rules as filename expansion in bash. The last entry can be
    // used to set flags that modify the pattern matching. 0 leads to defaults.
    //    -> It returns either APR_SUCCESS or APR_FNM_NOMATCH.
    if (apr_fnmatch(GIT_PAT, info.path, 0) == APR_SUCCESS) {
        rc = Shell_exec(GIT_SH, "URL", url, NULL);
        check(rc == 0, "git failed.");
    } else if (apr_fnmatch(DEPEND_PAT, info.path, 0) == APR_SUCCESS) {
        // we want to call Command_depends after downloading.
        check (!fetch_only, "No point in fetching a DEPENDS file");
        // download to depends_file, unless url is a local path.
        if (info.scheme) {
            depends_file = DEPENDS_PATH;
            rc = Shell_exec(CURL_SH, "URL", url, "TARGET", depends_file, NULL);
            check(rc == 0, "Curl failed.");
        } else {
            depends_file = info.path;
        }
        // recursively process the devpkg list
        log_info("Building according to DEPENDS: %s", url);
        rv = Command_depends(p, depends_file);
        check(rv == 0, "Failed to process the DEPENDS: %s", url);
        // return 0 because we don't actually install anything in *this*
        // command .. although we may have in Command_depends. A return code
        // of 1 means that we still need to build/install, which is not the
        // case here.
        return 0;
    } else if (apr_fnmatch(TAR_GZ_PAT, info.path, 0) == APR_SUCCESS) {
        // download if needed
        if (info.scheme) {
            rc = Shell_exec(CURL_SH, "URL", url, "TARGET", TAR_GZ_SRC, NULL);
            check(rc == 0, "Failed to curl source %s", url);
        }
        // build. See db.c for a discussion of the apr call.
        rv = apr_dir_make_recursive(
                BUILD_DIR, APR_UREAD | APR_UWRITE | APR_UEXECUTE, p
        );
        check(rc == APR_SUCCESS, "Failed to make directory %s", BUILD_DIR);
        rc = Shell_exec(TAR_SH, "FILE", TAR_GZ_SRC, NULL);
        check(rc == 0, "Failed to untar %s", TAR_GZ_SRC);
    } else if (apr_fnmatch(TAR_BZ2_PAT, info.path, 0) == APR_SUCCESS) {
        /* (note: this is copy-paste code - C kinda encourages this sometimes)
         * Zed has a small bug in this code: he redefines rc as apr_status_t
         * and then uses it for the output of Shell_exec. It works, but oops. I
         * fixed it by using copy-pasted code from the preceding block. */
        // download if needed
        if (info.scheme) {
            rc = Shell_exec(CURL_SH, "URL", url, "TARGET", TAR_BZ2_SRC, NULL);
            check(rc == 0, "Failed to curl source %s", url);
        }
        // build. See db.c for a discussion of the apr call.
        rv = apr_dir_make_recursive(
                BUILD_DIR, APR_UREAD | APR_UWRITE | APR_UEXECUTE, p
        );
        check(rc == APR_SUCCESS, "Failed to make directory %s", BUILD_DIR);
        rc = Shell_exec(TAR_SH, "FILE", TAR_BZ2_SRC, NULL);
        check(rc == 0, "Failed to untar %s", TAR_BZ2_SRC);
    } else {
        sentinel("Dont know how to handle this type of url: %s", url);
    }

    return 1; // indicates an install was actually run... the only
              // non-error case where we get a different code is DEPEND.
error:
    return -1;
}

int Command_build(
        apr_pool_t *p, const char *url, const char *configure_opts,
        const char *make_opts, const char *install_opts
) {
    int rc = 0;
    // check that build dir exists
    check(access(BUILD_DIR, X_OK | R_OK | W_OK) == 0,
          "Build directory doesn't exist: %s", BUILD_DIR);
    // if there's a config script, run it.
    if (access(CONFIG_SCRIPT, X_OK) == 0) {
        log_info("Has config script, running it.");
        rc = Shell_exec(CONFIGURE_SH, "OPTS", configure_opts, NULL);
        check(rc == 0, "Failed to configure.");
    }
    // make
    rc = Shell_exec(MAKE_SH, "OPTS", make_opts, NULL);
    check(rc == 0, "Failed to build.");
    // install. Note that if you pass install options, they have to
    // include the work "install", since we only add it if there aren't any lol
    rc = Shell_exec(
            INSTALL_SH, "TARGET", install_opts? install_opts : "install",
            NULL
    );
    check(rc == 0, "Failed to install.");
    // clean up
    rc = Shell_exec(CLEANUP_SH, NULL);
    check(rc == 0, "Failed to cleanup after build.");
    // update the db
    rc = DB_update(url);
    check(rc == 0, "Failed to add this package to the database.");

    return 0;
error:
    return -1;
}