Exemple #1
0
void
setextlibpath(const char *name, const char *val)
{
	int flag;
	char *p, *cp;

	if (!strcmp(name, "BEGINLIBPATH"))
		flag = BEGIN_LIBPATH;
	else if (!strcmp(name, "ENDLIBPATH"))
		flag = END_LIBPATH;
	else if (!strcmp(name, "LIBPATHSTRICT"))
		flag = LIBPATHSTRICT;
	else
		return;

	/* convert slashes to backslashes */
	strdupx(cp, val, ATEMP);
	for (p = cp; *p; p++) {
		if (*p == '/')
			*p = '\\';
	}

	DosSetExtLIBPATH(cp, flag);

	afree(cp, ATEMP);
}
Exemple #2
0
int main(int argc, char **argv, char **envp)
{
    int i;
#if defined(_MSC_VER)
    intptr_t rc;
#endif
    FILE *pStdErr = stderr;
    FILE *pStdOut = stdout;

    /*
     * Parse arguments.
     */
    if (argc <= 1)
        return usage(pStdErr, name(argv[0]));
    for (i = 1; i < argc; i++)
    {
        if (argv[i][0] == '-')
        {
            int fd;
            int fdOpened;
            int fOpen;
            char *psz = &argv[i][1];
            if (*psz == '-')
            {
                /* '--' ? */
                if (!psz[1])
                {
                    i++;
                    break;
                }

                /* convert to short. */
                if (!strcmp(psz, "-help"))
                    psz = "h";
                else if (!strcmp(psz, "-version"))
                    psz = "V";
                else if (!strcmp(psz, "-env"))
                    psz = "E";
                else if (!strcmp(psz, "-chdir"))
                    psz = "C";
                else if (!strcmp(psz, "-zap-env"))
                    psz = "Z";
                else if (!strcmp(psz, "-close"))
                    psz = "c";
            }

            /*
             * Deal with the obligatory help and version switches first.
             */
            if (*psz == 'h')
            {
                usage(pStdOut, name(argv[0]));
                return 0;
            }
            if (*psz == 'V')
            {
                printf("kmk_redirect - kBuild version %d.%d.%d (r%u)\n"
                       "Copyright (C) 2007-2009 knut st. osmundsen\n",
                       KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
                       KBUILD_SVN_REV);
                return 0;
            }

            /*
             * Environment switch?
             */
            if (*psz == 'E')
            {
                psz++;
                if (*psz == ':' || *psz == '=')
                    psz++;
                else
                {
                    if (i + 1 >= argc)
                    {
                        fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
                        return 1;
                    }
                    psz = argv[++i];
                }
#ifdef __OS2__
                if (    !strncmp(psz, "BEGINLIBPATH=",  sizeof("BEGINLIBPATH=") - 1)
                        ||  !strncmp(psz, "ENDLIBPATH=",    sizeof("ENDLIBPATH=") - 1)
                        ||  !strncmp(psz, "LIBPATHSTRICT=", sizeof("LIBPATHSTRICT=") - 1))
                {
                    ULONG ulVar = *psz == 'B' ? BEGIN_LIBPATH
                                  : *psz == 'E' ? END_LIBPATH
                                  :               LIBPATHSTRICT;
                    const char *pszVal = strchr(psz, '=') + 1;
                    APIRET rc = DosSetExtLIBPATH(pszVal, ulVar);
                    if (rc)
                    {
                        fprintf(pStdErr, "%s: error: DosSetExtLibPath(\"%s\", %.*s (%lu)): %lu\n",
                                name(argv[0]), pszVal, pszVal - psz - 1, psz, ulVar, rc);
                        return 1;
                    }
                }
                else
#endif /* __OS2__ */
                    if (putenv(psz))
                    {
                        fprintf(pStdErr, "%s: error: putenv(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
                        return 1;
                    }
                continue;
            }

            /*
             * Change directory switch?
             */
            if (*psz == 'C')
            {
                psz++;
                if (*psz == ':' || *psz == '=')
                    psz++;
                else
                {
                    if (i + 1 >= argc)
                    {
                        fprintf(pStdErr, "%s: syntax error: no argument for %s\n", name(argv[0]), argv[i]);
                        return 1;
                    }
                    psz = argv[++i];
                }
                if (!chdir(psz))
                    continue;
#ifdef _MSC_VER
                {
                    /* drop trailing slash if any. */
                    size_t cch = strlen(psz);
                    if (    cch > 2
                            &&  (psz[cch - 1] == '/' || psz[cch - 1] == '\\')
                            &&  psz[cch - 1] != ':')
                    {
                        int rc2;
                        char *pszCopy = strdup(psz);
                        do  pszCopy[--cch] = '\0';
                        while (    cch > 2
                                   &&  (pszCopy[cch - 1] == '/' || pszCopy[cch - 1] == '\\')
                                   &&  pszCopy[cch - 1] != ':');
                        rc2 = chdir(pszCopy);
                        free(pszCopy);
                        if (!rc2)
                            continue;
                    }
                }
#endif
                fprintf(pStdErr, "%s: error: chdir(\"%s\"): %s\n", name(argv[0]), psz, strerror(errno));
                return 1;
            }

            /*
             * Zap environment switch?
             * This is a bit of a hack.
             */
            if (*psz == 'Z')
            {
                unsigned j = 0;
                while (envp[j] != NULL)
                    j++;
                while (j-- > 0)
                {
                    char *pszEqual = strchr(envp[j], '=');
                    char *pszCopy;

                    if (pszEqual)
                        *pszEqual = '\0';
                    pszCopy = strdup(envp[j]);
                    if (pszEqual)
                        *pszEqual = '=';

#if defined(_MSC_VER) || defined(__OS2__)
                    putenv(pszCopy);
#else
                    unsetenv(pszCopy);
#endif
                    free(pszCopy);
                }
                continue;
            }

            /*
             * Close the specified file descriptor (no stderr/out/in aliases).
             */
            if (*psz == 'c')
            {
                psz++;
                if (!*psz)
                {
                    i++;
                    if (i >= argc)
                    {
                        fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0]));
                        return 1;
                    }
                    psz = argv[i];
                }

                fd = (int)strtol(psz, &psz, 0);
                if (!fd || *psz)
                {
                    fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]);
                    return 1;

                }
                if (fd < 0)
                {
                    fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]);
                    return 1;
                }
                /** @todo deal with stderr */
                close(fd);
                continue;
            }

            /*
             * Parse a file descriptor argument.
             */

            /* mode */
            switch (*psz)
            {
            case 'r':
                psz++;
                if (*psz == '+')
                {
                    fOpen = O_RDWR;
                    psz++;
                }
                else
                    fOpen = O_RDONLY;
                break;

            case 'w':
                psz++;
                if (*psz == '+')
                {
                    psz++;
                    fOpen = O_RDWR | O_CREAT | O_TRUNC;
                }
                else
                    fOpen = O_WRONLY | O_CREAT | O_TRUNC;
                break;

            case 'a':
                psz++;
                if (*psz == '+')
                {
                    psz++;
                    fOpen = O_RDWR | O_CREAT | O_APPEND;
                }
                else
                    fOpen = O_WRONLY | O_CREAT | O_APPEND;
                break;

            case 'i': /* make sure stdin is read-only. */
                fOpen = O_RDONLY;
                break;

            case '+':
                fprintf(pStdErr, "%s: syntax error: Unexpected '+' in '%s'\n", name(argv[0]), argv[i]);
                return 1;

            default:
                fOpen = O_RDWR | O_CREAT | O_TRUNC;
                break;
            }

            /* binary / text modifiers */
            switch (*psz)
            {
            case 'b':
#ifdef O_BINARY
                fOpen |= O_BINARY;
#endif
                psz++;
                break;

            case 't':
#ifdef O_TEXT
                fOpen |= O_TEXT;
#endif
                psz++;
                break;

            default:
#ifdef O_BINARY
                fOpen |= O_BINARY;
#endif
                break;

            }

            /* convert to file descriptor number */
            switch (*psz)
            {
            case 'i':
                fd = 0;
                psz++;
                break;

            case 'o':
                fd = 1;
                psz++;
                break;

            case 'e':
                fd = 2;
                psz++;
                break;

            case '0':
                if (!psz[1])
                {
                    fd = 0;
                    psz++;
                    break;
                }
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                fd = (int)strtol(psz, &psz, 0);
                if (!fd)
                {
                    fprintf(pStdErr, "%s: error: failed to convert '%s' to a number\n", name(argv[0]), argv[i]);
                    return 1;

                }
                if (fd < 0)
                {
                    fprintf(pStdErr, "%s: error: negative fd %d (%s)\n", name(argv[0]), fd, argv[i]);
                    return 1;
                }
                break;

            /*
             * Invalid argument.
             */
            default:
                fprintf(pStdErr, "%s: error: failed to convert '%s' ('%s') to a file descriptor\n", name(argv[0]), psz, argv[i]);
                return 1;
            }

            /*
             * Check for the filename.
             */
            if (*psz)
            {
                if (*psz != ':' && *psz != '=')
                {
                    fprintf(pStdErr, "%s: syntax error: characters following the file descriptor: '%s' ('%s')\n", name(argv[0]), psz, argv[i]);
                    return 1;
                }
                psz++;
            }
            else
            {
                i++;
                if (i >= argc)
                {
                    fprintf(pStdErr, "%s: syntax error: missing filename argument.\n", name(argv[0]));
                    return 1;
                }
                psz = argv[i];
            }

            /*
             * Setup the redirection.
             */
            if (fd == fileno(pStdErr))
            {
                /*
                 * Move stderr to a new location, making it close on exec.
                 * If pStdOut has already teamed up with pStdErr, update it too.
                 */
                FILE *pNew;
                fdOpened = dup(fileno(pStdErr));
                if (fdOpened == -1)
                {
                    fprintf(pStdErr, "%s: error: failed to dup stderr (%d): %s\n", name(argv[0]), fileno(pStdErr), strerror(errno));
                    return 1;
                }
#ifdef _MSC_VER
                /** @todo figure out how to make the handle close-on-exec. We'll simply close it for now.
                 * SetHandleInformation + set FNOINHERIT in CRT.
                 */
#else
                if (fcntl(fdOpened, F_SETFD, FD_CLOEXEC) == -1)
                {
                    fprintf(pStdErr, "%s: error: failed to make stderr (%d) close-on-exec: %s\n", name(argv[0]), fdOpened, strerror(errno));
                    return 1;
                }
#endif

                pNew = fdopen(fdOpened, "w");
                if (!pNew)
                {
                    fprintf(pStdErr, "%s: error: failed to fdopen the new stderr (%d): %s\n", name(argv[0]), fdOpened, strerror(errno));
                    return 1;
                }
                if (pStdOut == pStdErr)
                    pStdOut = pNew;
                pStdErr = pNew;
            }
            else if (fd == 1 && pStdOut != pStdErr)
                pStdOut = pStdErr;

            /*
             * Close and open the new file descriptor.
             */
            close(fd);
#if defined(_MSC_VER)
            if (!strcmp(psz, "/dev/null"))
                psz = (char *)"nul";
#endif
            fdOpened = open(psz, fOpen, 0666);
            if (fdOpened == -1)
            {
                fprintf(pStdErr, "%s: error: failed to open '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
                return 1;
            }
            if (fdOpened != fd)
            {
                /* move it (dup2 returns 0 on MSC). */
                if (dup2(fdOpened, fd) == -1)
                {
                    fprintf(pStdErr, "%s: error: failed to dup '%s' as %d: %s\n", name(argv[0]), psz, fd, strerror(errno));
                    return 1;
                }
                close(fdOpened);
            }
        }
        else
        {
            fprintf(pStdErr, "%s: syntax error: Invalid argument '%s'.\n", name(argv[0]), argv[i]);
            return usage(pStdErr, name(argv[0]));
        }
    }

    /*
     * Make sure there's something to execute.
     */
    if (i >= argc)
    {
        fprintf(pStdErr, "%s: syntax error: nothing to execute!\n", name(argv[0]));
        return usage(pStdErr, name(argv[0]));
    }

#if defined(_MSC_VER)
    if (fileno(pStdErr) != 2) /* no close-on-exec flag on windows */
    {
        fclose(pStdErr);
        pStdErr = NULL;
    }

    /** @todo
     * We'll have to find the '--' in the commandline and pass that
     * on to CreateProcess or spawn. Otherwise, the argument qouting
     * is gonna be messed up.
     */
    rc = _spawnvp(_P_WAIT, argv[i], &argv[i]);
    if (rc == -1 && pStdErr)
    {
        fprintf(pStdErr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
        rc = 1;
    }
    return rc;
#else
    execvp(argv[i], &argv[i]);
    fprintf(pStdErr, "%s: error: _execvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
    return 1;
#endif
}
Exemple #3
0
int main(int argc, char *argv[]) {

  int do_load,do_unload,do_help,do_path;
  do_load=do_unload=do_help=do_path=0;

  char basepath[CCHMAXPATH];

  if (argc == 1)
    do_help = 1;
  else {
    for (int i=1; i < argc; i++) {
      if (strnicmp(argv[i],"-l", 2) == 0)
        do_load = 1;
      else if (strnicmp(argv[i],"-u", 2) == 0)
        do_unload = 1;
      else if (strnicmp(argv[i],"-h", 2) == 0) 
        do_help = 1;
      else if (strnicmp(argv[i],"-?", 2) == 0)
        do_help = 1;
      else if (strnicmp(argv[i],"-p", 2) == 0) {
        if (argc > i+1) {
          strcpy(basepath, argv[i+1]);
          if (basepath[strlen(basepath)] !='\\') {
            strcat(basepath, "\\");
          }
        do_path = 1;
        } else {
          do_help = 1;
        }
      }
    }
  }


  if (do_help) {
    printf("%s for OS/2 preloader\n"\
           "\n"\
           "Usage: %s [-h] [-l | -u] [-p path]\n"\
           "       -h display this help\n"\
           "       -l load modules\n"\
           "       -u unload modules\n"\
           "       -p specify fully qualified path to directory where EXE is located\n",
           MOZ_APP_DISPLAYNAME, argv[0]);
    return(1);
  }

  if (do_unload) {
    HEV hev = NULLHANDLE;
    if (DosOpenEventSem(SEMNAME, &hev) == NO_ERROR) {
      if (DosPostEventSem(hev) == NO_ERROR) {
        if (DosCloseEventSem(hev) == NO_ERROR) {
          return(0);
        }
      }
    }
    printf("%s for OS/2 preloader is not running\n", MOZ_APP_DISPLAYNAME);
    return(1);
  }

  if (do_path == 0) {
    /* Get the name of this EXE and use its location as the path */
    HMODULE hmodule;
    DosQueryModFromEIP(&hmodule, NULL, 0, NULL, NULL, (ULONG)ForceModuleLoad);
    DosQueryModuleName(hmodule, CCHMAXPATH, basepath);
    char *pchar = strrchr(basepath, '\\');
    pchar++;
    *pchar = '\0';
  }

  if (do_load) {
    ULONG ulCurMaxFH;
    LONG ulReqFH = 40;
    DosSetRelMaxFH(&ulReqFH, &ulCurMaxFH);

    HEV hev;
    if (DosCreateEventSem(SEMNAME, &hev, DC_SEM_SHARED, FALSE) != NO_ERROR) {
      printf("%s for OS/2 preloader is already running\n", MOZ_APP_DISPLAYNAME);
      return(1);
    }

    /* Add directory where EXE is located to LIBPATH */
    DosSetExtLIBPATH(basepath, BEGIN_LIBPATH);

    /* loop through list loading named modules */
    char filepath[CCHMAXPATH];
    HMODULE hmod;

    int i = 0, nummodules = 0;
    while (bindir[i]) {
      strcpy(filepath,basepath);
      strcat(filepath,bindir[i]);
   
      if (DosLoadModule(NULL, 0, filepath, &hmod) == NO_ERROR) {
        ForceModuleLoad(hmod);
        nummodules++;
      }
      i++;
    }

    i = 0;
    while (compdir[i]) {
      strcpy(filepath, basepath);
      strcat(filepath, "COMPONENTS\\");
      strcat(filepath, compdir[i]);

      if (DosLoadModule(NULL, 0, filepath, &hmod) == NO_ERROR) {
        ForceModuleLoad(hmod);
        nummodules++;
      }
      i++;
    }
   
    if (nummodules > 0) {
      if (DosWaitEventSem(hev, SEM_INDEFINITE_WAIT) != NO_ERROR) {
        printf("DosWaitEventSem failed\n");
        return(1);
      }

      if (DosCloseEventSem(hev) != NO_ERROR) {
        printf("DosCloseEventSem failed\n");
        return(1);
      }
    } else {
      printf("No modules available to load\n");
    }
  }

 return(0);
}
Exemple #4
0
// add a variable to the environment or alias to the alias list
int add_list( char *envstr, PCH pchList )
{
    char *line;
    PCH feptr, env_arg, env_end, last_var;
    unsigned int length;
    int rval = 0;
    ULONG size;     // size of environment or alias blocks

    // OS/2 & NT need semaphores to keep processes from simultaneously
    //  writing the alias list
    HMTX SemHandle = 0;
    char szVarName[32];

    if ( pchList == 0L )
        pchList = glpEnvironment;

    line = envstr;
    if ( *line == '=' ) {
        return ( error( ERROR_4DOS_BAD_SYNTAX, envstr ));
    }

    for ( ; (( *line ) && ( *line != '=' )); line++ ) {

        if ( pchList == glpAliasList ) {

            if ( iswhite( *line )) {
                strcpy( line, skipspace( line ) );
                break;
            }
        }
        else        // ensure environment entry is in upper case
            *line = (unsigned char)_ctoupper( *line );
    }

    if ( *line == '=' ) {

        // point to the first char of the argument
        line++;

        // collapse whitespace around '=' in aliases, but not in env
        //   variables, for COMMAND.COM compatibility (set abc def= ghi)
        if ( pchList == glpAliasList )
            strcpy( line, skipspace( line ));

    } else if ( *line ) {
        // add the missing '='
        strins( line, "=" );
        line++;
    }

    // removing single back quotes at the beginning and end of an alias
    //   argument (they're illegal there; the user is probably making a
    //   mistake with ALIAS /R)
    if (( *line == SINGLE_QUOTE ) && ( pchList == glpAliasList )) {

        // remove leading single quote
        strcpy( line, line + 1 );

        // remove trailing single quote
        if ((( length = strlen( line )) != 0 ) && ( line[--length] == SINGLE_QUOTE ))
            line[length] = '\0';
    }

    // block other processes & threads while updating alias list
    if ( pchList == glpAliasList ) {

        // disable signals temporarily
        HoldSignals();

        // get & lock a semaphore
        RequestSemaphore( &SemHandle, SEMAPHORE_NAME );
    }

    // get pointers to beginning & end of alias/environment space
    size = QueryMemSize( pchList );
        env_end = pchList + ( size - 4 );

    // get pointer to end of environment or alias variables
    last_var = end_of_env( pchList );

    length = strlen( envstr ) + 1;

    // special case for BeginLIBPATH and EndLIBPATH
    sscanf( envstr, "%31[^=]", szVarName );
    if (stricmp( szVarName, BEGINLIBPATH ) == 0) {
        if ((DosSetExtLIBPATH( line, BEGIN_LIBPATH ) == NO_ERROR))
            return 0;
        return ERROR_EXIT;
    }

    if (stricmp( szVarName, ENDLIBPATH ) == 0) {
        if ((DosSetExtLIBPATH( line, END_LIBPATH ) == NO_ERROR))
            return 0;
        return ERROR_EXIT;
    }

    // check for modification or deletion of existing entry
    if (( env_arg = get_list( envstr, pchList )) != 0L ) {

        // get the start of the alias or variable name
        for ( feptr = env_arg; (( feptr > pchList ) && ( feptr[-1] != '\0' )); feptr-- )
            ;

        if ( *line == '\0' ) {
            // delete an alias or environment variable
            memmove( feptr, next_env( feptr ), (unsigned int)( last_var - next_env(feptr)) + 1);
        } else {
            // get the relative length (vs. the old variable)
            length = strlen( line ) - strlen( env_arg );
        }
    }

    if ( *line != '\0' ) {

        // check for out of environment space
        if (( last_var + length ) >= env_end ) {

            // boost environment or alias list size
            if ( ReallocMem( pchList, size + ENVIRONMENT_SIZE ) == NULL) {
                rval = error((( pchList == glpAliasList ) ? ERROR_4DOS_OUT_OF_ALIAS : ERROR_4DOS_OUT_OF_ENVIRONMENT), NULL);
                goto add_bye;
            }

            // adjust the environment / alias list size
            size = QueryMemSize( pchList );
            if ( pchList == glpEnvironment )
                gpIniptr->EnvSize = (unsigned int)size;
            else if ( pchList == glpAliasList )
                gpIniptr->AliasSize = (unsigned int)size;
        }

        if ( env_arg != 0L ) {

            // modify an existing alias or environment variable
            //   adjust the space & insert new value
            feptr = next_env( feptr );
            memmove(( feptr + length ), feptr, (unsigned int)( last_var - feptr) + 1 );
            strcpy( env_arg, line );

        } else {
            // put it at the end & add an extra null
            strcpy( last_var, envstr );
            last_var[length] = '\0';
        }
    }

add_bye:
    if ( pchList == glpAliasList ) {
        // clear the semaphore
        FreeSemaphore( SemHandle );
        EnableSignals();
    }

    return rval;
}
Exemple #5
0
HRESULT InitializeXPIStub()
{
  char szBuf[MAX_BUF];
  char szXPIStubFile[MAX_BUF];
  char szEDosQueryProcAddr[MAX_BUF];
  APIRET rc;

  hXPIStubInst = NULL;

  if(!GetPrivateProfileString("Messages", "ERROR_DOSQUERYPROCADDR", "", szEDosQueryProcAddr, sizeof(szEDosQueryProcAddr), szFileIniInstall))
    return(1);

  /* change current directory to where xpistub.dll */
  /* change current directory to where xpistub.dll */
  strcpy(szBuf, siCFXpcomFile.szDestination);
  AppendBackSlash(szBuf, sizeof(szBuf));
  strcat(szBuf, "bin");
  chdir(szBuf);

  /* Set LIBPATHSTRICT */
  DosSetExtLIBPATH("T", LIBPATHSTRICT);

  /* Add it to LIBPATH */
  DosSetExtLIBPATH(szBuf, BEGIN_LIBPATH);

  /* build full path to xpistub.dll */
  strcpy(szXPIStubFile, szBuf);
  AppendBackSlash(szXPIStubFile, sizeof(szXPIStubFile));
  strcat(szXPIStubFile, "xpistub.dll");

  if(FileExists(szXPIStubFile) == FALSE)
    return(2);

  /* load xpistub.dll */
  if (DosLoadModule(NULL, 0, szXPIStubFile, &hXPIStubInst) != NO_ERROR)
  {
    sprintf(szBuf, szEDllLoad, szXPIStubFile);
    PrintError(szBuf, ERROR_CODE_SHOW);
    return(1);
  }
  if(DosQueryProcAddr(hXPIStubInst, 0, "_XPI_Init", &pfnXpiInit) != NO_ERROR)
  {
    sprintf(szBuf, szEDosQueryProcAddr, "_XPI_Init");
    PrintError(szBuf, ERROR_CODE_SHOW);
    return(1);
  }
  if(DosQueryProcAddr(hXPIStubInst, 0, "_XPI_Install", &pfnXpiInstall) != NO_ERROR)
  {
    sprintf(szBuf, szEDosQueryProcAddr, "_XPI_Install");
    PrintError(szBuf, ERROR_CODE_SHOW);
    return(1);
  }
  if(DosQueryProcAddr(hXPIStubInst, 0, "_XPI_Exit", &pfnXpiExit) != NO_ERROR)
  {
    sprintf(szBuf, szEDosQueryProcAddr, "_XPI_Exit");
    PrintError(szBuf, ERROR_CODE_SHOW);
    return(1);
  }

  return(0);
}
Exemple #6
0
HRESULT SmartUpdateJars()
{
  DWORD     dwIndex0;
  siC       *siCObject = NULL;
  HRESULT   hrResult;
  char      szBuf[MAX_BUF];
  char      szEXpiInstall[MAX_BUF];
  char      szArchive[MAX_BUF];
  char      szMsgSmartUpdateStart[MAX_BUF];
  char      szDlgExtractingTitle[MAX_BUF];

  if(!GetPrivateProfileString("Messages", "MSG_SMARTUPDATE_START", "", szMsgSmartUpdateStart, sizeof(szMsgSmartUpdateStart), szFileIniInstall))
    return(1);
  if(!GetPrivateProfileString("Messages", "DLG_EXTRACTING_TITLE", "", szDlgExtractingTitle, sizeof(szDlgExtractingTitle), szFileIniInstall))
    return(1);
  if(!GetPrivateProfileString("Messages", "STR_PROCESSINGFILE", "", szStrProcessingFile, sizeof(szStrProcessingFile), szFileIniInstall))
    exit(1);
  if(!GetPrivateProfileString("Messages", "STR_INSTALLING", "", szStrInstalling, sizeof(szStrInstalling), szFileIniInstall))
    exit(1);
  if(!GetPrivateProfileString("Messages", "STR_COPYINGFILE", "", szStrCopyingFile, sizeof(szStrCopyingFile), szFileIniInstall))
    exit(1);

  ShowMessage(szMsgSmartUpdateStart, TRUE);
  if(InitializeXPIStub() == WIZ_OK)
  {
    LogISXPInstall(W_START);
    strcpy(szBuf, sgProduct.szPath);
    if(*sgProduct.szSubPath != '\0')
    {
      AppendBackSlash(szBuf, sizeof(szBuf));
      strcat(szBuf, sgProduct.szSubPath);
    }
    hrResult = pfnXpiInit(szBuf, FILE_INSTALL_LOG, cbXPIProgress);

    /* Unset LIBPATHSTRICT */
    DosSetExtLIBPATH("F", LIBPATHSTRICT);

    ShowMessage(szMsgSmartUpdateStart, FALSE);
    InitProgressDlg();
    GetTotalArchivesToInstall();
    WinSetWindowText(dlgInfo.hWndDlg, szDlgExtractingTitle);

    dwIndex0          = 0;
    dwCurrentArchive  = 0;
    siCObject         = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
    while(siCObject)
    {
      if(siCObject->dwAttributes & SIC_SELECTED)
        /* Since the archive is selected, we need to process the file ops here */
         ProcessFileOps(T_PRE_ARCHIVE, siCObject->szReferenceName);

      /* launch smartupdate engine for earch jar to be installed */
      if((siCObject->dwAttributes & SIC_SELECTED)   &&
        !(siCObject->dwAttributes & SIC_LAUNCHAPP) &&
        !(siCObject->dwAttributes & SIC_DOWNLOAD_ONLY))
      {
        strcpy(szArchive, sgProduct.szAlternateArchiveSearchPath);
        AppendBackSlash(szArchive, sizeof(szArchive));
        strcat(szArchive, siCObject->szArchiveName);
        if((*sgProduct.szAlternateArchiveSearchPath == '\0') || (!FileExists(szArchive)))
        {
          strcpy(szArchive, szSetupDir);
          AppendBackSlash(szArchive, sizeof(szArchive));
          strcat(szArchive, siCObject->szArchiveName);
          if(!FileExists(szArchive))
          {
            strcpy(szArchive, szTempDir);
            AppendBackSlash(szArchive, sizeof(szArchive));
            strcat(szArchive, siCObject->szArchiveName);
            if(!FileExists(szArchive))
            {
              char szEFileNotFound[MAX_BUF];

              if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
              {
                sprintf(szBuf, szEFileNotFound, szArchive);
                PrintError(szBuf, ERROR_CODE_HIDE);
              }
              return(1);
            }
          }
        }

        if(dwCurrentArchive == 0)
        {
          ++dwCurrentArchive;
          UpdateGaugeArchiveProgressBar((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
        }

        sprintf(szBuf, szStrInstalling, siCObject->szDescriptionShort);
        WinSetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS0, szBuf);
        LogISXPInstallComponent(siCObject->szDescriptionShort);

        hrResult = pfnXpiInstall(szArchive, "", 0xFFFF);
        if(hrResult == E_REBOOT)
          bReboot = TRUE;
        else if((hrResult != WIZ_OK) &&
               !(siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
        {
          LogMSXPInstallStatus(siCObject->szArchiveName, hrResult);
          LogISXPInstallComponentResult(hrResult);
          if(GetPrivateProfileString("Messages", "ERROR_XPI_INSTALL", "", szEXpiInstall, sizeof(szEXpiInstall), szFileIniInstall))
          {
            char szErrorString[MAX_BUF];

            GetErrorString(hrResult, szErrorString, sizeof(szErrorString));
            sprintf(szBuf, "%s - %s: %d %s", szEXpiInstall, siCObject->szDescriptionShort, hrResult, szErrorString);
            PrintError(szBuf, ERROR_CODE_HIDE);
          }

          /* break out of the siCObject while loop */
          break;
        }

        ++dwCurrentArchive;
        UpdateGaugeArchiveProgressBar((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
        ProcessWindowsMessages();
        LogISXPInstallComponentResult(hrResult);

        if((hrResult != WIZ_OK) &&
          (siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
          /* reset the result to WIZ_OK if there was an error and the
           * component's attributes contains SIC_IGNORE_XPINSTALL_ERROR.
           * This should be done after LogISXPInstallComponentResult()
           * because we still should log the error value. */
          hrResult = WIZ_OK;
      }

      if(siCObject->dwAttributes & SIC_SELECTED)
        /* Since the archive is selected, we need to do the file ops here */
         ProcessFileOps(T_POST_ARCHIVE, siCObject->szReferenceName);

      ++dwIndex0;
      siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
    } /* while(siCObject) */

    LogMSXPInstallStatus(NULL, hrResult);
    pfnXpiExit();
    if(sgProduct.ulMode != SILENT)
      WinDestroyWindow(dlgInfo.hWndDlg);
  }
  else
  {
    ShowMessage(szMsgSmartUpdateStart, FALSE);
  }

  DeInitializeXPIStub();
  LogISXPInstall(W_END);

  return(hrResult);
}
int
main(int argc, char **argv)
{
  nsresult rv;
  char *lastSlash;

  char iniPath[MAXPATHLEN];
  char tmpPath[MAXPATHLEN];
  char greDir[MAXPATHLEN];
  PRBool greFound = PR_FALSE;

#if defined(XP_MACOSX)
  CFBundleRef appBundle = CFBundleGetMainBundle();
  if (!appBundle)
    return 1;

  CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(appBundle);
  if (!resourcesURL)
    return 1;

  CFURLRef absResourcesURL = CFURLCopyAbsoluteURL(resourcesURL);
  CFRelease(resourcesURL);
  if (!absResourcesURL)
    return 1;

  CFURLRef iniFileURL =
    CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
                                          absResourcesURL,
                                          CFSTR("application.ini"),
                                          false);
  CFRelease(absResourcesURL);
  if (!iniFileURL)
    return 1;

  CFStringRef iniPathStr =
    CFURLCopyFileSystemPath(iniFileURL, kCFURLPOSIXPathStyle);
  CFRelease(iniFileURL);
  if (!iniPathStr)
    return 1;

  CFStringGetCString(iniPathStr, iniPath, sizeof(iniPath),
                     kCFStringEncodingUTF8);
  CFRelease(iniPathStr);

#else

#ifdef XP_WIN
  wchar_t wide_path[MAX_PATH];
  if (!::GetModuleFileNameW(NULL, wide_path, MAX_PATH))
    return 1;

  WideCharToMultiByte(CP_UTF8, 0, wide_path,-1,
		      iniPath, MAX_PATH, NULL, NULL);

#elif defined(XP_OS2)
   PPIB ppib;
   PTIB ptib;

   DosGetInfoBlocks(&ptib, &ppib);
   DosQueryModuleName(ppib->pib_hmte, sizeof(iniPath), iniPath);

#elif defined(XP_BEOS)
   BEntry e((const char *)argv[0], true); // traverse symlink
   BPath p;
   status_t err;
   err = e.GetPath(&p);
   NS_ASSERTION(err == B_OK, "realpath failed");

   if (err == B_OK)
     // p.Path returns a pointer, so use strcpy to store path in iniPath
     strcpy(iniPath, p.Path());

#else
  // on unix, there is no official way to get the path of the current binary.
  // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
  // multiple applications, we will try a series of techniques:
  //
  // 1) use realpath() on argv[0], which works unless we're loaded from the
  //    PATH
  // 2) manually walk through the PATH and look for ourself
  // 3) give up

  struct stat fileStat;

  if (!realpath(argv[0], iniPath) || stat(iniPath, &fileStat)) {
    const char *path = getenv("PATH");
    if (!path)
      return 1;

    char *pathdup = strdup(path);
    if (!pathdup)
      return 1;

    PRBool found = PR_FALSE;
    char *token = strtok(pathdup, ":");
    while (token) {
      sprintf(tmpPath, "%s/%s", token, argv[0]);
      if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0) {
        found = PR_TRUE;
        break;
      }
      token = strtok(NULL, ":");
    }
    free (pathdup);
    if (!found)
      return 1;
  }
#endif

  lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
  if (!lastSlash)
    return 1;

  *(++lastSlash) = '\0';

  // On Linux/Win, look for XULRunner in appdir/xulrunner

  snprintf(greDir, sizeof(greDir),
           "%sxulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL,
           iniPath);

  greFound = FolderExists(greDir);

  strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));

#endif

  // If -app parameter was passed in, it is now time to take it under 
  // consideration.
  const char *appDataFile;
  appDataFile = getenv("XUL_APP_FILE");
  if (!appDataFile || !*appDataFile) 
    if (argc > 1 && IsArg(argv[1], "app")) {
      if (argc == 2) {
        Output(PR_FALSE, "specify APP-FILE (optional)\n");
        return 1;
      }
      argv[1] = argv[0];
      ++argv;
      --argc;

      appDataFile = argv[1];
      argv[1] = argv[0];
      ++argv;
      --argc;

      char kAppEnv[MAXPATHLEN];
      snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
      if (putenv(kAppEnv)) 
        Output(PR_FALSE, "Couldn't set %s.\n", kAppEnv);

      char *result = (char*) calloc(sizeof(char), MAXPATHLEN);
      if (NS_FAILED(GetRealPath(appDataFile, &result))) {
        Output(PR_TRUE, "Invalid application.ini path.\n");
        return 1;
      }
      
      // We have a valid application.ini path passed in to the -app parameter 
      // but not yet a valid greDir, so lets look for it also on the same folder
      // as the stub.
      if (!greFound) {
        lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
        if (!lastSlash)
          return 1;

        *(++lastSlash) = '\0';

        snprintf(greDir, sizeof(greDir), "%s" XPCOM_DLL, iniPath);
        greFound = FolderExists(greDir);
      }
      
      // copy it back.
      strcpy(iniPath, result);
    }
  
  nsINIParser parser;
  rv = parser.Init(iniPath);
  if (NS_FAILED(rv)) {
    fprintf(stderr, "Could not read application.ini\n");
    return 1;
  }

#ifdef WINCE
  // On Windows Mobile and WinCE, we can save a lot of time by not
  // waiting for XUL and XPCOM to load up.  Let's see if we can find
  // an existing app window to forward our command-line to now.

  // Shouldn't attempt this if the -no-remote parameter has been provided.
  bool noRemote = false;
  for (int i = 1; i < argc; i++) {
    if (IsArg(argv[i], "no-remote")) {
      noRemote = true;
      break;
    }
  }

  if (!noRemote) {
    char windowName[512];  // Is there a const for appname like VERSION_MAXLEN?
    rv = parser.GetString("App", "Name", windowName, sizeof(windowName));
    if (NS_FAILED(rv)) {
      fprintf(stderr, "Couldn't figure out the application name\n");
      return 1;
    }

    // Lookup the hidden message window created by nsNativeAppSupport
    strncat(windowName, "MessageWindow", sizeof(windowName) - strlen(windowName));
    WCHAR wWindowName[512];
    MultiByteToWideChar(CP_UTF8, 0, windowName, -1, wWindowName, sizeof(wWindowName));
    HWND wnd = ::FindWindowW(wWindowName, NULL);
    if (wnd) {
      // Forward the command-line and bail out
      ForwardToWindow(wnd);
      return 0;
    }
  }
#endif

  if (!greFound) {
    char minVersion[VERSION_MAXLEN];

    // If a gecko maxVersion is not specified, we assume that the app uses only
    // frozen APIs, and is therefore compatible with any xulrunner 1.x.
    char maxVersion[VERSION_MAXLEN] = "1.*";

    GREVersionRange range = {
      minVersion,
      PR_TRUE,
      maxVersion,
      PR_TRUE
    };

    rv = parser.GetString("Gecko", "MinVersion", minVersion, sizeof(minVersion));
    if (NS_FAILED(rv)) {
      fprintf(stderr,
              "The application.ini does not specify a [Gecko] MinVersion\n");
      return 1;
    }

    rv = parser.GetString("Gecko", "MaxVersion", maxVersion, sizeof(maxVersion));
    if (NS_SUCCEEDED(rv))
      range.upperInclusive = PR_TRUE;

    static const GREProperty kProperties[] = {
      { "xulrunner", "true" }
    };

    rv = GRE_GetGREPathWithProperties(&range, 1,
                                      kProperties, NS_ARRAY_LENGTH(kProperties),
                                      greDir, sizeof(greDir));
    if (NS_FAILED(rv)) {
      // XXXbsmedberg: Do something much smarter here: notify the
      // user/offer to download/?

      Output(PR_FALSE,
             "Could not find compatible GRE between version %s and %s.\n",
             range.lower, range.upper);
      return 1;
    }
#ifdef XP_UNIX
    // Using a symlinked greDir will fail during startup. Not sure why, but if
    // we resolve the symlink, everything works as expected.
    char resolved_greDir[MAXPATHLEN] = "";  
    if (realpath(greDir, resolved_greDir) && *resolved_greDir) {
      strncpy(greDir, resolved_greDir, MAXPATHLEN);
    }
#endif
  }

#ifdef XP_OS2
  // On OS/2 we need to set BEGINLIBPATH to be able to find XULRunner DLLs
  strcpy(tmpPath, greDir);
  lastSlash = strrchr(tmpPath, PATH_SEPARATOR_CHAR);
  if (lastSlash) {
    *lastSlash = '\0';
  }
  DosSetExtLIBPATH(tmpPath, BEGIN_LIBPATH);
#endif

  rv = XPCOMGlueStartup(greDir);
  if (NS_FAILED(rv)) {
    if (rv == NS_ERROR_OUT_OF_MEMORY) {
      char applicationName[2000] = "this application";
      parser.GetString("App", "Name", applicationName, sizeof(applicationName));
      Output(PR_TRUE, "Not enough memory available to start %s.\n",
             applicationName);
    } else {
      Output(PR_TRUE, "Couldn't load XPCOM.\n");
    }
    return 1;
  }

  static const nsDynamicFunctionLoad kXULFuncs[] = {
    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
    { "XRE_main", (NSFuncPtr*) &XRE_main },
    { nsnull, nsnull }
  };

  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
  if (NS_FAILED(rv)) {
    Output(PR_TRUE, "Couldn't load XRE functions.\n");
    return 1;
  }

  NS_LogInit();

  int retval;

  { // Scope COMPtr and AutoAppData
    nsCOMPtr<nsILocalFile> iniFile;
#ifdef XP_WIN
    // On Windows and Windows CE, iniPath is UTF-8 encoded,
    // so we need to convert it.
    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(iniPath), PR_FALSE,
                         getter_AddRefs(iniFile));
#else
    rv = NS_NewNativeLocalFile(nsDependentCString(iniPath), PR_FALSE,
                               getter_AddRefs(iniFile));
#endif
    if (NS_FAILED(rv)) {
      Output(PR_TRUE, "Couldn't find application.ini file.\n");
      return 1;
    }

    AutoAppData appData(iniFile);
    if (!appData) {
      Output(PR_TRUE, "Error: couldn't parse application.ini.\n");
      return 1;
    }

    NS_ASSERTION(appData->directory, "Failed to get app directory.");

    if (!appData->xreDirectory) {
      // chop "libxul.so" off the GRE path
      lastSlash = strrchr(greDir, PATH_SEPARATOR_CHAR);
      if (lastSlash) {
        *lastSlash = '\0';
      }
#ifdef XP_WIN
      // same as iniPath.
      NS_NewLocalFile(NS_ConvertUTF8toUTF16(greDir), PR_FALSE,
                      &appData->xreDirectory);
#else
      NS_NewNativeLocalFile(nsDependentCString(greDir), PR_FALSE,
                            &appData->xreDirectory);
#endif
    }

    retval = XRE_main(argc, argv, appData);
  }

  NS_LogTerm();

  XPCOMGlueShutdown();

  return retval;
}
int
main(int argc, char **argv)
{
  nsresult rv;
  char *lastSlash;

  char iniPath[MAXPATHLEN];
  char tmpPath[MAXPATHLEN];
  char greDir[MAXPATHLEN];
  bool greFound = false;

#if defined(XP_MACOSX)
  CFBundleRef appBundle = CFBundleGetMainBundle();
  if (!appBundle)
    return 1;

  CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(appBundle);
  if (!resourcesURL)
    return 1;

  CFURLRef absResourcesURL = CFURLCopyAbsoluteURL(resourcesURL);
  CFRelease(resourcesURL);
  if (!absResourcesURL)
    return 1;

  CFURLRef iniFileURL =
    CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
                                          absResourcesURL,
                                          CFSTR("application.ini"),
                                          false);
  CFRelease(absResourcesURL);
  if (!iniFileURL)
    return 1;

  CFStringRef iniPathStr =
    CFURLCopyFileSystemPath(iniFileURL, kCFURLPOSIXPathStyle);
  CFRelease(iniFileURL);
  if (!iniPathStr)
    return 1;

  CFStringGetCString(iniPathStr, iniPath, sizeof(iniPath),
                     kCFStringEncodingUTF8);
  CFRelease(iniPathStr);

#else

#ifdef XP_WIN
  wchar_t wide_path[MAX_PATH];
  if (!::GetModuleFileNameW(NULL, wide_path, MAX_PATH))
    return 1;

  WideCharToMultiByte(CP_UTF8, 0, wide_path,-1,
		      iniPath, MAX_PATH, NULL, NULL);

#elif defined(XP_OS2)
   PPIB ppib;
   PTIB ptib;

   DosGetInfoBlocks(&ptib, &ppib);
   DosQueryModuleName(ppib->pib_hmte, sizeof(iniPath), iniPath);

#else
  // on unix, there is no official way to get the path of the current binary.
  // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
  // multiple applications, we will try a series of techniques:
  //
  // 1) use realpath() on argv[0], which works unless we're loaded from the
  //    PATH
  // 2) manually walk through the PATH and look for ourself
  // 3) give up

  struct stat fileStat;
  strncpy(tmpPath, argv[0], sizeof(tmpPath));
  lastSlash = strrchr(tmpPath, '/');
  if (lastSlash) {
    *lastSlash = 0;
    realpath(tmpPath, iniPath);
  } else {
    const char *path = getenv("PATH");
    if (!path)
      return 1;

    char *pathdup = strdup(path);
    if (!pathdup)
      return 1;

    bool found = false;
    char *token = strtok(pathdup, ":");
    while (token) {
      sprintf(tmpPath, "%s/%s", token, argv[0]);
      if (stat(tmpPath, &fileStat) == 0) {
        found = true;
        lastSlash = strrchr(tmpPath, '/');
        *lastSlash = 0;
        realpath(tmpPath, iniPath);
        break;
      }
      token = strtok(NULL, ":");
    }
    free (pathdup);
    if (!found)
      return 1;
  }
  lastSlash = iniPath + strlen(iniPath);
  *lastSlash = '/';
#endif

#ifndef XP_UNIX
  lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
  if (!lastSlash)
    return 1;
#endif

  *(++lastSlash) = '\0';

  // On Linux/Win, look for XULRunner in appdir/xulrunner

  snprintf(greDir, sizeof(greDir),
           "%sxulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL,
           iniPath);

  greFound = FolderExists(greDir);

#ifdef XP_UNIX
  if (greFound) {
    char resolved_greDir[MAXPATHLEN] = "";
    if (realpath(greDir, resolved_greDir) && *resolved_greDir) {
      strncpy(greDir, resolved_greDir, MAXPATHLEN);
    }
  }
#endif

  strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));

#endif

  // If -app parameter was passed in, it is now time to take it under 
  // consideration.
  const char *appDataFile;
  appDataFile = getenv("XUL_APP_FILE");
  if (!appDataFile || !*appDataFile) 
    if (argc > 1 && IsArg(argv[1], "app")) {
      if (argc == 2) {
        Output(false, "specify APP-FILE (optional)\n");
        return 1;
      }
      argv[1] = argv[0];
      ++argv;
      --argc;

      appDataFile = argv[1];
      argv[1] = argv[0];
      ++argv;
      --argc;

      char kAppEnv[MAXPATHLEN];
      snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
      if (putenv(kAppEnv)) 
        Output(false, "Couldn't set %s.\n", kAppEnv);

      char *result = (char*) calloc(sizeof(char), MAXPATHLEN);
      if (NS_FAILED(GetRealPath(appDataFile, &result))) {
        Output(true, "Invalid application.ini path.\n");
        return 1;
      }
      
      // We have a valid application.ini path passed in to the -app parameter 
      // but not yet a valid greDir, so lets look for it also on the same folder
      // as the stub.
      if (!greFound) {
        lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
        if (!lastSlash)
          return 1;

        *(++lastSlash) = '\0';

        snprintf(greDir, sizeof(greDir), "%s" XPCOM_DLL, iniPath);
        greFound = FolderExists(greDir);
      }
      
      // copy it back.
      strcpy(iniPath, result);
    }
  
  nsINIParser parser;
  rv = parser.Init(iniPath);
  if (NS_FAILED(rv)) {
    fprintf(stderr, "Could not read application.ini\n");
    return 1;
  }

  if (!greFound) {
#ifdef XP_MACOSX
    // Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib
    CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
    CFURLRef absfwurl = nullptr;
    if (fwurl) {
      absfwurl = CFURLCopyAbsoluteURL(fwurl);
      CFRelease(fwurl);
    }

    if (absfwurl) {
      CFURLRef xulurl =
        CFURLCreateCopyAppendingPathComponent(NULL, absfwurl,
                                              CFSTR("XUL.framework"),
                                              true);

      if (xulurl) {
        CFURLRef xpcomurl =
          CFURLCreateCopyAppendingPathComponent(NULL, xulurl,
                                                CFSTR("libxpcom.dylib"),
                                                false);

        if (xpcomurl) {
          char tbuffer[MAXPATHLEN];

          if (CFURLGetFileSystemRepresentation(xpcomurl, true,
                                               (UInt8*) tbuffer,
                                               sizeof(tbuffer)) &&
              access(tbuffer, R_OK | X_OK) == 0) {
            if (realpath(tbuffer, greDir)) {
              greFound = true;
            }
            else {
              greDir[0] = '\0';
            }
          }

          CFRelease(xpcomurl);
        }

        CFRelease(xulurl);
      }

      CFRelease(absfwurl);
    }
#endif
    if (!greFound) {
      Output(false, "Could not find the Mozilla runtime.\n");
      return 1;
    }
  }

#ifdef XP_OS2
  // On OS/2 we need to set BEGINLIBPATH to be able to find XULRunner DLLs
  strcpy(tmpPath, greDir);
  lastSlash = strrchr(tmpPath, PATH_SEPARATOR_CHAR);
  if (lastSlash) {
    *lastSlash = '\0';
  }
  DosSetExtLIBPATH(tmpPath, BEGIN_LIBPATH);
#endif
  
  rv = XPCOMGlueStartup(greDir);
  if (NS_FAILED(rv)) {
    if (rv == NS_ERROR_OUT_OF_MEMORY) {
      char applicationName[2000] = "this application";
      parser.GetString("App", "Name", applicationName, sizeof(applicationName));
      Output(true, "Not enough memory available to start %s.\n",
             applicationName);
    } else {
      Output(true, "Couldn't load XPCOM.\n");
    }
    return 1;
  }

  static const nsDynamicFunctionLoad kXULFuncs[] = {
    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
    { "XRE_main", (NSFuncPtr*) &XRE_main },
    { nullptr, nullptr }
  };

  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
  if (NS_FAILED(rv)) {
    Output(true, "Couldn't load XRE functions.\n");
    return 1;
  }

  NS_LogInit();

  int retval;

  { // Scope COMPtr and AutoAppData
    nsCOMPtr<nsIFile> iniFile;
#ifdef XP_WIN
    // On Windows iniPath is UTF-8 encoded so we need to convert it.
    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(iniPath), false,
                         getter_AddRefs(iniFile));
#else
    rv = NS_NewNativeLocalFile(nsDependentCString(iniPath), false,
                               getter_AddRefs(iniFile));
#endif
    if (NS_FAILED(rv)) {
      Output(true, "Couldn't find application.ini file.\n");
      return 1;
    }

    AutoAppData appData(iniFile);
    if (!appData) {
      Output(true, "Error: couldn't parse application.ini.\n");
      return 1;
    }

    NS_ASSERTION(appData->directory, "Failed to get app directory.");

    if (!appData->xreDirectory) {
      // chop "libxul.so" off the GRE path
      lastSlash = strrchr(greDir, PATH_SEPARATOR_CHAR);
      if (lastSlash) {
        *lastSlash = '\0';
      }
#ifdef XP_WIN
      // same as iniPath.
      NS_NewLocalFile(NS_ConvertUTF8toUTF16(greDir), false,
                      &appData->xreDirectory);
#else
      NS_NewNativeLocalFile(nsDependentCString(greDir), false,
                            &appData->xreDirectory);
#endif
    }

    retval = XRE_main(argc, argv, appData, 0);
  }

  NS_LogTerm();

  return retval;
}