예제 #1
0
Slave *Slave::createSlave(const QString &protocol, const KURL &url, int &error, QString &error_text)
{
    // kdDebug(7002) << "createSlave '" << protocol << "' for " << url.prettyURL() << endl;
    // Firstly take into account all special slaves
    if(protocol == "data")
        return new DataProtocol();

    DCOPClient *client = kapp->dcopClient();
    if(!client->isAttached())
        client->attach();

    QString prefix = locateLocal("socket", KGlobal::instance()->instanceName());
    KTempFile socketfile(prefix, QString::fromLatin1(".slave-socket"));
    if(socketfile.status() != 0)
    {
        error_text = i18n("Unable to create io-slave: %1").arg(strerror(errno));
        error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
        return 0;
    }

#ifdef __CYGWIN__
    socketfile.close();
#endif

    KServerSocket *kss = new KServerSocket(QFile::encodeName(socketfile.name()));

    Slave *slave = new Slave(kss, protocol, socketfile.name());

    // WABA: if the dcopserver is running under another uid we don't ask
    // klauncher for a slave, because the slave might have that other uid
    // as well, which might either be a) undesired or b) make it impossible
    // for the slave to connect to the application.
    // In such case we start the slave via KProcess.
    // It's possible to force this by setting the env. variable
    // KDE_FORK_SLAVES, Clearcase seems to require this.
    static bool bForkSlaves = !QCString(getenv("KDE_FORK_SLAVES")).isEmpty();

    if(bForkSlaves || !client->isAttached() || client->isAttachedToForeignServer())
    {
        QString _name = KProtocolInfo::exec(protocol);
        if(_name.isEmpty())
        {
            error_text = i18n("Unknown protocol '%1'.").arg(protocol);
            error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
            delete slave;
            return 0;
        }
        QString lib_path = KLibLoader::findLibrary(_name.latin1());
        if(lib_path.isEmpty())
        {
            error_text = i18n("Can not find io-slave for protocol '%1'.").arg(protocol);
            error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
            return 0;
        }

        KProcess proc;

        proc << locate("exe", "kioslave") << lib_path << protocol << "" << socketfile.name();
        kdDebug(7002) << "kioslave"
                      << ", " << lib_path << ", " << protocol << ", " << QString::null << ", " << socketfile.name() << endl;

        proc.start(KProcess::DontCare);

        slave->setPID(proc.pid());
        QTimer::singleShot(1000 * SLAVE_CONNECTION_TIMEOUT_MIN, slave, SLOT(timeout()));
        return slave;
    }


    QByteArray params, reply;
    QCString replyType;
    QDataStream stream(params, IO_WriteOnly);
    stream << protocol << url.host() << socketfile.name();

    QCString launcher = KApplication::launcher();
    if(!client->call(launcher, launcher, "requestSlave(QString,QString,QString)", params, replyType, reply))
    {
        error_text = i18n("Cannot talk to klauncher");
        error = KIO::ERR_SLAVE_DEFINED;
        delete slave;
        return 0;
    }
    QDataStream stream2(reply, IO_ReadOnly);
    QString errorStr;
    pid_t pid;
    stream2 >> pid >> errorStr;
    if(!pid)
    {
        error_text = i18n("Unable to create io-slave:\nklauncher said: %1").arg(errorStr);
        error = KIO::ERR_CANNOT_LAUNCH_PROCESS;
        delete slave;
        return 0;
    }

    slave->setPID(pid);
    QTimer::singleShot(1000 * SLAVE_CONNECTION_TIMEOUT_MIN, slave, SLOT(timeout()));

    return slave;
}