Пример #1
0
void NDnsWorker::run()
{
	hostent *h = 0;

#ifdef HAVE_GETHOSTBYNAME_R
	hostent buf;
	char char_buf[1024];
	int err;
	gethostbyname_r(host.data(), &buf, char_buf, sizeof(char_buf), &h, &err);
#else
	// lock for gethostbyname
	QMutexLocker locker(workerMutex);

	// check for cancel
	workerCancelled->lock();
	bool cancel = cancelled;
	workerCancelled->unlock();

	if(!cancel)
		h = gethostbyname(host.data());
#endif

	// FIXME: not ipv6 clean, currently.
	if(!h || h->h_addrtype != AF_INET) {
		success = false;
		QApplication::postEvent(par, new NDnsWorkerEvent(this));
		return;
	}

	in_addr a = *((struct in_addr *)h->h_addr_list[0]);
	addr.setAddress(ntohl(a.s_addr));
	success = true;

	QApplication::postEvent(par, new NDnsWorkerEvent(this));
}
Пример #2
0
QByteArray K3BookmarkDrag::encodedData( const char* mime ) const
{
    QByteArray a;
    Q3CString mimetype( mime );
    if ( mimetype == "text/uri-list" )
        return Q3UriDrag::encodedData( mime );
    else if ( mimetype == "application/x-xbel" )
    {
        a = m_doc.toByteArray();
        //kDebug(7043) << "K3BookmarkDrag::encodedData " << m_doc.toCString();
    }
    else if ( mimetype == "text/plain" )
    {
        KUrl::List m_lstDragURLs;
        if ( K3URLDrag::decode( this, m_lstDragURLs ) )
        {
            QStringList uris;
            KUrl::List::ConstIterator uit = m_lstDragURLs.constBegin();
            KUrl::List::ConstIterator uEnd = m_lstDragURLs.constEnd();
            for ( ; uit != uEnd ; ++uit )
                uris.append( (*uit).prettyUrl() );

            Q3CString s = uris.join( "\n" ).toLocal8Bit();
            a.resize( s.length() + 1 ); // trailing zero
            memcpy( a.data(), s.data(), s.length() + 1 );
        }
    }
    return a;
}
Пример #3
0
int XmlProtocol::internalWriteString(const QString &s, TrackItem::Type t, int id)
{
	QString out=ensureGTEncoded(s);
	Q3CString cs = s.utf8();
	QByteArray a(cs.length());
	memcpy(a.data(), cs.data(), a.size());
	return internalWriteData(a, t, id);
}
Пример #4
0
Q3CString Q3CString::rightJustify(uint width, char fill, bool truncate) const
{
    Q3CString result;
    int len = qstrlen(constData());
    int padlen = width - len;
    if (padlen > 0) {
        result.resize(len+padlen);
        memset(result.data(), fill, padlen);
        memcpy(result.data()+padlen, constData(), len);
    } else {
        if (truncate)
            result = left(width);
        else
            result = *this;
    }
    return result;
}
int main( int argc, char** argv ) {

  KAboutData aboutData( "test_cryptoconfig", 0, ki18n("CryptoConfig Test"), "0.1" );
  KCmdLineArgs::init( argc, argv, &aboutData );
  KApplication app( false );

  Kleo::CryptoConfig * config = new QGpgMECryptoConfig();

  // Dynamic querying of the options
  cout << "Components:" << endl;
  QStringList components = config->componentList();

  for( QStringList::Iterator compit = components.begin(); compit != components.end(); ++compit ) {
    cout << "Component " << (*compit).toLocal8Bit().constData() << ":" << endl;
    const Kleo::CryptoConfigComponent* comp = config->component( *compit );
    assert( comp );
    QStringList groups = comp->groupList();
    for( QStringList::Iterator groupit = groups.begin(); groupit != groups.end(); ++groupit ) {
      const Kleo::CryptoConfigGroup* group = comp->group( *groupit );
      assert( group );
      cout << " Group " << (*groupit).toLocal8Bit().constData() << ": descr=\"" << group->description().toLocal8Bit().constData() << "\""
           << " level=" << group->level() << endl;
      QStringList entries = group->entryList();
      for( QStringList::Iterator entryit = entries.begin(); entryit != entries.end(); ++entryit ) {
        const Kleo::CryptoConfigEntry* entry = group->entry( *entryit );
        assert( entry );
        cout << "  Entry " << (*entryit).toLocal8Bit().constData() << ":"
             << " descr=\"" << entry->description().toLocal8Bit().constData() << "\""
             << " " << ( entry->isSet() ? "is set" : "is not set" );
        if ( !entry->isList() )
          switch( entry->argType() ) {
          case Kleo::CryptoConfigEntry::ArgType_None:
            break;
          case Kleo::CryptoConfigEntry::ArgType_Int:
            cout << " int value=" << entry->intValue();
            break;
          case Kleo::CryptoConfigEntry::ArgType_UInt:
            cout << " uint value=" << entry->uintValue();
            break;
          case Kleo::CryptoConfigEntry::ArgType_LDAPURL:
          case Kleo::CryptoConfigEntry::ArgType_URL:
            cout << " URL value=" << entry->urlValue().prettyUrl().toLocal8Bit().constData();
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_Path:
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_DirPath:
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_String:

            cout << " string value=" << entry->stringValue().toLocal8Bit().constData();
            break;
          case Kleo::CryptoConfigEntry::NumArgType:
            // just metadata and should never actually occur in the switch
            break;
          }
        else // lists
        {
          switch( entry->argType() ) {
          case Kleo::CryptoConfigEntry::ArgType_None: {
            cout << " set " << entry->numberOfTimesSet() << " times";
            break;
          }
          case Kleo::CryptoConfigEntry::ArgType_Int: {
            assert( entry->isOptional() ); // empty lists must be allowed (see issue121)
            Q3ValueList<int> lst = entry->intValueList();
            QString str;
            for( Q3ValueList<int>::Iterator it = lst.begin(); it != lst.end(); ++it ) {
              str += QString::number( *it );
            }
            cout << " int values=" << str.toLocal8Bit().constData();
            break;
          }
          case Kleo::CryptoConfigEntry::ArgType_UInt: {
            assert( entry->isOptional() ); // empty lists must be allowed (see issue121)
            Q3ValueList<uint> lst = entry->uintValueList();
            QString str;
            for( Q3ValueList<uint>::Iterator it = lst.begin(); it != lst.end(); ++it ) {
              str += QString::number( *it );
            }
            cout << " uint values=" << str.toLocal8Bit().constData();
            break;
          }
          case Kleo::CryptoConfigEntry::ArgType_LDAPURL:
          case Kleo::CryptoConfigEntry::ArgType_URL: {
              assert( entry->isOptional() ); // empty lists must be allowed (see issue121)
              KUrl::List urls = entry->urlValueList();
              cout << " url values=" << urls.toStringList().join(" ").toLocal8Bit().constData() << "\n    ";
          }
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_Path:
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_DirPath:
            // fallthrough
          case Kleo::CryptoConfigEntry::ArgType_String: {
            assert( entry->isOptional() ); // empty lists must be allowed (see issue121)
            QStringList lst = entry->stringValueList();
            cout << " string values=" << lst.join(" ").toLocal8Bit().constData();
            break;
          }
          case Kleo::CryptoConfigEntry::NumArgType:
            // just metadata and should never actually occur in the switch
            break;
          }
        }
        cout << endl;
      }
      // ...
    }
  }

  {
    // Static querying of a single boolean option
    static const char* s_groupName = "Monitor";
    static const char* s_entryName = "quiet";
    Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
    if ( entry ) {
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_None );
      bool val = entry->boolValue();
      cout << "quiet option initially: " << ( val ? "is set" : "is not set" ) << endl;

      entry->setBoolValue( !val );
      assert( entry->isDirty() );
      config->sync( true );

      // Clear cached values!
      config->clear();

      // Check new value
      Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( entry );
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_None );
      cout << "quiet option now: " << ( val ? "is set" : "is not set" ) << endl;
      assert( entry->boolValue() == !val );

      // Set to default
      entry->resetToDefault();
      assert( entry->boolValue() == false ); // that's the default
      assert( entry->isDirty() );
      assert( !entry->isSet() );
      config->sync( true );
      config->clear();

      // Check value
      entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( !entry->isDirty() );
      assert( !entry->isSet() );
      cout << "quiet option reset to default: " << ( entry->boolValue() ? "is set" : "is not set" ) << endl;
      assert( entry->boolValue() == false );

      // Reset old value
      entry->setBoolValue( val );
      assert( entry->isDirty() );
      config->sync( true );

      cout << "quiet option reset to initial: " << ( val ? "is set" : "is not set" ) << endl;
    }
    else
      cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl;
  }

  {
    // Static querying and setting of a single int option
    static const char* s_groupName = "LDAP";
    static const char* s_entryName = "ldaptimeout";
    Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
    if ( entry ) {
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_UInt );
      uint val = entry->uintValue();
      cout << "LDAP timeout initially: " << val << " seconds." << endl;

      // Test setting the option directly, then querying again
      //system( "echo 'ldaptimeout:0:101' | gpgconf --change-options dirmngr" );
      // Now let's do it with the C++ API instead
      entry->setUIntValue( 101 );
      assert( entry->isDirty() );
      config->sync( true );

      // Clear cached values!
      config->clear();

      // Check new value
      Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( entry );
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_UInt );
      cout << "LDAP timeout now: " << entry->uintValue() << " seconds." << endl;
      assert( entry->uintValue() == 101 );

      // Set to default
      entry->resetToDefault();
      assert( entry->uintValue() == 100 );
      assert( entry->isDirty() );
      assert( !entry->isSet() );
      config->sync( true );
      config->clear();

      // Check value
      entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( !entry->isDirty() );
      assert( !entry->isSet() );
      cout << "LDAP timeout reset to default, " << entry->uintValue() << " seconds." << endl;
      assert( entry->uintValue() == 100 );

      // Reset old value
      entry->setUIntValue( val );
      assert( entry->isDirty() );
      config->sync( true );

      cout << "LDAP timeout reset to initial " << val << " seconds." << endl;
    }
    else
      cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl;
  }

  {
    // Static querying and setting of a single string option
    static const char* s_groupName = "Debug";
    static const char* s_entryName = "log-file";
    Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
    if ( entry ) {
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_Path );
      QString val = entry->stringValue();
      cout << "Log-file initially: " << val.toLocal8Bit().constData() << endl;

      // Test setting the option, sync'ing, then querying again
      entry->setStringValue( QString::fromUtf8( "/tmp/test:%e5ä" ) );
      assert( entry->isDirty() );
      config->sync( true );

      // Let's see how it prints it
      system( "gpgconf --list-options dirmngr | grep log-file" );

      // Clear cached values!
      config->clear();

      // Check new value
      Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( entry );
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_Path );
      cout << "Log-file now: " << entry->stringValue().toLocal8Bit().constData() << endl;
      assert( entry->stringValue() == QString::fromUtf8( "/tmp/test:%e5ä" ) ); // (or even with %e5 decoded)

      // Reset old value
#if 0
      QString arg( val );
      if ( !arg.isEmpty() )
        arg.prepend( '"' );
      Q3CString sys;
      sys.sprintf( "echo 'log-file:%s' | gpgconf --change-options dirmngr", arg.local8Bit().data() );
      system( sys.data() );
#endif
      entry->setStringValue( val );
      assert( entry->isDirty() );
      config->sync( true );

      cout << "Log-file reset to initial " << val.toLocal8Bit().constData() << endl;
    }
    else
      cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl;
  }

  {
    // Static querying and setting of the LDAP URL list option
    static const char* s_groupName = "LDAP";
    static const char* s_entryName = "LDAP Server";
    Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
    if ( entry ) {
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_LDAPURL );
      assert( entry->isList() );
      KUrl::List val = entry->urlValueList();
      cout << "URL list initially: " << val.toStringList().join(", ").toLocal8Bit().constData() << endl;

      // Test setting the option, sync'ing, then querying again
      KUrl::List lst;
      // We use non-empty paths to workaround a bug in KUrl (kdelibs-3.2)
      lst << KUrl( "ldap://a:389/?b" );
      // Test with query containing a literal ':' (KUrl supports this)
      // and a ' ' (KUrl will escape it, see issue119)
      lst << KUrl( "ldap://foo:389/?a:b c" );
      lst << KUrl( "ldap://server:389/?a%3db,c=DE" ); // the query contains a literal ','
      //cout << " trying to set: " << lst.toStringList().join(", ").local8Bit() << endl;
      assert( lst[0].query() == "?b" );
      assert( lst[1].query() == "?a:b%20c" ); // see, the space got escaped
      entry->setURLValueList( lst );
      assert( entry->isDirty() );
      config->sync( true );

      // Let's see how it prints it
      system( "gpgconf --list-options dirmngr | grep 'LDAP Server'" );

      // Clear cached values!
      config->clear();

      // Check new value
      Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName );
      assert( entry );
      assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_LDAPURL );
      assert( entry->isList() );
      // Get raw a:b:c:d:e form
      QStringList asStringList = entry->stringValueList();
      assert( asStringList.count() == 3 );
      cout << "asStringList[0]=" << asStringList[0].toLocal8Bit().constData() << endl;
      cout << "asStringList[1]=" << asStringList[1].toLocal8Bit().constData() << endl;
      cout << "asStringList[2]=" << asStringList[2].toLocal8Bit().constData() << endl;
      assert( asStringList[0] == "a:389:::b" );
      assert( asStringList[1] == "foo:389:::a%3ab c" ); // the space must be decoded (issue119)
      assert( asStringList[2] == "server:389:::a=b,c=DE" ); // all decoded
      // Get KUrl form
      KUrl::List newlst = entry->urlValueList();
      cout << "URL list now: " << newlst.toStringList().join(", ").toLocal8Bit().constData() << endl;
      assert( newlst.count() == 3 );
      //cout << "newlst[0]=" << newlst[0].url().local8Bit() << endl;
      //cout << "lst[0]=" << lst[0].url().local8Bit() << endl;
      assert( newlst[0] == lst[0] );
      assert( newlst[1] == lst[1] );
      assert( newlst[2].url() == "ldap://server:389/?a=b,c=DE" ); // != lst[2] due to the encoded =

      // Reset old value
      entry->setURLValueList( val );
      assert( entry->isDirty() );
      config->sync( true );

      cout << "URL list reset to initial: " << val.toStringList().join(", ").toLocal8Bit().constData() << endl;
    }
    else
      cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl;
  }

  cout << "Done." << endl;
}
Пример #6
0
bool Q3Process::start( QStringList *env )
{
#if defined(QT_Q3PROCESS_DEBUG)
    qDebug( "Q3Process::start()" );
#endif
    reset();

    if ( _arguments.isEmpty() )
	return false;

    // Open the pipes.  Make non-inheritable copies of input write and output
    // read handles to avoid non-closable handles (this is done by the
    // DuplicateHandle() call).
    SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };
#ifndef Q_OS_WINCE
    // I guess there is no stdin stdout and stderr on Q_OS_WINCE to dup
    // CreatePipe and DupilcateHandle aren't available for Q_OS_WINCE
    HANDLE tmpStdin, tmpStdout, tmpStderr;
    if ( comms & Stdin ) {
	if ( !CreatePipe( &d->pipeStdin[0], &tmpStdin, &secAtt, 0 ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !DuplicateHandle( GetCurrentProcess(), tmpStdin, GetCurrentProcess(), &d->pipeStdin[1], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !CloseHandle( tmpStdin ) ) {
	    d->closeHandles();
	    return false;
	}
    }
    if ( comms & Stdout ) {
	if ( !CreatePipe( &tmpStdout, &d->pipeStdout[1], &secAtt, 0 ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !DuplicateHandle( GetCurrentProcess(), tmpStdout, GetCurrentProcess(), &d->pipeStdout[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !CloseHandle( tmpStdout ) ) {
	    d->closeHandles();
	    return false;
	}
    }
    if ( comms & Stderr ) {
	if ( !CreatePipe( &tmpStderr, &d->pipeStderr[1], &secAtt, 0 ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !DuplicateHandle( GetCurrentProcess(), tmpStderr, GetCurrentProcess(), &d->pipeStderr[0], 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
	    d->closeHandles();
	    return false;
	}
	if ( !CloseHandle( tmpStderr ) ) {
	    d->closeHandles();
	    return false;
	}
    }
    if ( comms & DupStderr ) {
	CloseHandle( d->pipeStderr[1] );
	d->pipeStderr[1] = d->pipeStdout[1];
    }
#endif

    // construct the arguments for CreateProcess()
    QString args;
    QString appName;
    QStringList::Iterator it = _arguments.begin();
    args = *it;
    ++it;
    if ( args.endsWith( QLatin1String(".bat") ) && args.contains( QLatin1Char(' ') ) ) {
	// CreateProcess() seems to have a strange semantics (see also
	// http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_11138647.html):
	// If you start a batch file with spaces in the filename, the first
	// argument to CreateProcess() must be the name of the batchfile
	// without quotes, but the second argument must start with the same
	// argument with quotes included. But if the same approach is used for
	// .exe files, it doesn't work.
	appName = args;
	args = QLatin1Char('"') + args + QLatin1Char('"');
    }
    for ( ; it != _arguments.end(); ++it ) {
	QString tmp = *it;
	// escape a single " because the arguments will be parsed
	tmp.replace( QLatin1String("\""), QLatin1String("\\\"") );
	if ( tmp.isEmpty() || tmp.contains( QLatin1Char(' ') ) || tmp.contains( QLatin1Char('\t') ) ) {
	    // The argument must not end with a \ since this would be interpreted
	    // as escaping the quote -- rather put the \ behind the quote: e.g.
	    // rather use "foo"\ than "foo\"
	    QString endQuote( QLatin1String("\"") );
	    int i = tmp.length();
	    while ( i>0 && tmp.at( i-1 ) == QLatin1Char('\\') ) {
		--i;
		endQuote += QLatin1String("\\");
	    }
	    args += QString( QLatin1String(" \"") ) + tmp.left( i ) + endQuote;
	} else {
	    args += QLatin1Char(' ') + tmp;
	}
    }
#if defined(QT_Q3PROCESS_DEBUG)
    qDebug( "Q3Process::start(): args [%s]", args.latin1() );
#endif

    // CreateProcess()
    bool success;
    d->newPid();
#ifdef UNICODE
    if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
	STARTUPINFOW startupInfo = {
	    sizeof( STARTUPINFO ), 0, 0, 0,
	    (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
	    0, 0, 0,
	    STARTF_USESTDHANDLES,
	    0, 0, 0,
	    d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1]
	};
	TCHAR *applicationName;
	if ( appName.isNull() )
	    applicationName = 0;
	else
	    applicationName = _wcsdup( (TCHAR*)appName.ucs2() );
	TCHAR *commandLine = _wcsdup( (TCHAR*)args.ucs2() );
	QByteArray envlist;
	if ( env != 0 ) {
	    int pos = 0;
	    // add PATH if necessary (for DLL loading)
	    QByteArray path = qgetenv( "PATH" );
	    if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) {
		QString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData()));
		uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
		envlist.resize( envlist.size() + tmpSize );
		memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize );
		pos += tmpSize;
	    }
	    // add the user environment
	    for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) {
		QString tmp = *it;
		uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
		envlist.resize( envlist.size() + tmpSize );
		memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize );
		pos += tmpSize;
	    }
	    // add the 2 terminating 0 (actually 4, just to be on the safe side)
	    envlist.resize( envlist.size()+4 );
	    envlist[pos++] = 0;
	    envlist[pos++] = 0;
	    envlist[pos++] = 0;
	    envlist[pos++] = 0;
	}
	success = CreateProcessW( applicationName, commandLine,
		0, 0, TRUE, ( comms==0 ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW )
#ifndef Q_OS_WINCE
		| CREATE_UNICODE_ENVIRONMENT
#endif
		, env==0 ? 0 : envlist.data(),
                (TCHAR*)QDir::toNativeSeparators(workingDir.absPath()).ucs2(),
		&startupInfo, d->pid );
	free( applicationName );
	free( commandLine );
    } else
#endif // UNICODE
    {
#ifndef Q_OS_WINCE
	STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0,
	    (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
	    0, 0, 0,
	    STARTF_USESTDHANDLES,
	    0, 0, 0,
	    d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1]
	};
	QByteArray envlist;
	if ( env != 0 ) {
	    int pos = 0;
	    // add PATH if necessary (for DLL loading)
	    QByteArray path = qgetenv( "PATH" );
	    if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) {
		Q3CString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData())).local8Bit();
		uint tmpSize = tmp.length() + 1;
		envlist.resize( envlist.size() + tmpSize );
		memcpy( envlist.data()+pos, tmp.data(), tmpSize );
		pos += tmpSize;
	    }
	    // add the user environment
	    for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) {
		Q3CString tmp = (*it).local8Bit();
		uint tmpSize = tmp.length() + 1;
		envlist.resize( envlist.size() + tmpSize );
		memcpy( envlist.data()+pos, tmp.data(), tmpSize );
		pos += tmpSize;
	    }
	    // add the terminating 0 (actually 2, just to be on the safe side)
	    envlist.resize( envlist.size()+2 );
	    envlist[pos++] = 0;
	    envlist[pos++] = 0;
	}
	char *applicationName;
	if ( appName.isNull() )
	    applicationName = 0;
	else
	    applicationName = const_cast<char *>(appName.toLocal8Bit().data());
	success = CreateProcessA( applicationName,
		const_cast<char *>(args.toLocal8Bit().data()),
		0, 0, TRUE, comms==0 ? CREATE_NEW_CONSOLE : DETACHED_PROCESS,
		env==0 ? 0 : envlist.data(),
                (const char*)QDir::toNativeSeparators(workingDir.absPath()).local8Bit(),
		&startupInfo, d->pid );
#endif // Q_OS_WINCE
    }
    if  ( !success ) {
	d->deletePid();
	return false;
    }

#ifndef Q_OS_WINCE
    if ( comms & Stdin )
	CloseHandle( d->pipeStdin[0] );
    if ( comms & Stdout )
        CloseHandle( d->pipeStdout[1] );
    if ( (comms & Stderr) && !(comms & DupStderr) )
	CloseHandle( d->pipeStderr[1] );
#endif

    if ( ioRedirection || notifyOnExit ) {
	d->lookup->start( 100 );
    }

    // cleanup and return
    return true;
}