예제 #1
0
bool findObject(const char *app, const char *obj, const char *func, KStringList args)
{
    QString f = func; // Qt is better with unicode strings, so use one.
    int left = f.find('(');
    int right = f.find(')');

    if(right < left)
    {
        qWarning("parentheses do not match");
        exit(1);
    }

    if(!f.isEmpty() && (left < 0))
        f += "()";

    // This may seem expensive but is done only once per invocation
    // of dcop, so it should be OK.
    //
    //
    QStringList intTypes;
    intTypes << "int"
             << "unsigned"
             << "long"
             << "bool";

    QStringList types;
    if(left > 0 && left + 1 < right - 1)
    {
        types = QStringList::split(',', f.mid(left + 1, right - left - 1));
        for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
        {
            QString lt = (*it).simplifyWhiteSpace();

            int s = lt.find(' ');

            // If there are spaces in the name, there may be two
            // reasons: the parameter name is still there, ie.
            // "QString URL" or it's a complicated int type, ie.
            // "unsigned long long int bool".
            //
            //
            if(s > 0)
            {
                QStringList partl = QStringList::split(' ', lt);

                // The zero'th part is -- at the very least -- a
                // type part. Any trailing parts *might* be extra
                // int-type keywords, or at most one may be the
                // parameter name.
                //
                //
                s = 1;

                while(s < (int)partl.count() && intTypes.contains(partl[s]))
                {
                    s++;
                }

                if(s < (int)partl.count() - 1)
                {
                    qWarning("The argument `%s' seems syntactically wrong.", lt.latin1());
                }
                if(s == (int)partl.count() - 1)
                {
                    partl.remove(partl.at(s));
                }

                lt = partl.join(" ");
                lt = lt.simplifyWhiteSpace();
            }

            (*it) = lt;
        }
        QString fc = f.left(left);
        fc += '(';
        bool first = true;
        for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
        {
            if(!first)
                fc += ",";
            first = false;
            fc += *it;
        }
        fc += ')';
        f = fc;
    }

    if(types.count() != args.count())
    {
        qWarning("arguments do not match");
        exit(1);
    }

    QByteArray data;
    QDataStream arg(data, IO_WriteOnly);

    uint i = 0;
    for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
    {
        marshall(arg, args, i, *it);
    }
    if((uint)i != args.count())
    {
        qWarning("arguments do not match");
        exit(1);
    }

    QCString foundApp;
    QCString foundObj;
    if(dcop->findObject(app, obj, f.latin1(), data, foundApp, foundObj))
    {
        if(bAppIdOnly)
            puts(foundApp.data());
        else
            printf("DCOPRef(%s,%s)\n", qStringToC(foundApp), qStringToC(foundObj));
        return true;
    }
    return false;
}
예제 #2
0
/**
 * Do the actual DCOP call
 */
int runDCOP(KStringList args, UserList users, Session session, const QString sessionName, bool readStdin, bool updateUserTime)
{
    bool DCOPrefmode = false;
    QCString app;
    QCString objid;
    QCString function;
    KStringList params;
    DCOPClient *client = 0L;
    int retval = 0;
    if(!args.isEmpty() && args[0].find("DCOPRef(") == 0)
    {
        int delimPos = args[0].findRev(',');
        if(delimPos == -1)
        {
            cerr_ << "Error: '" << args[0] << "' is not a valid DCOP reference." << endl;
            exit(-1);
        }
        app = args[0].mid(8, delimPos - 8);
        delimPos++;
        objid = args[0].mid(delimPos, args[0].length() - delimPos - 1);
        if(args.count() > 1)
            function = args[1];
        if(args.count() > 2)
        {
            params = args;
            params.remove(params.begin());
            params.remove(params.begin());
        }
        DCOPrefmode = true;
    }
    else
    {
        if(!args.isEmpty())
            app = args[0];
        if(args.count() > 1)
            objid = args[1];
        if(args.count() > 2)
            function = args[2];
        if(args.count() > 3)
        {
            params = args;
            params.remove(params.begin());
            params.remove(params.begin());
            params.remove(params.begin());
        }
    }

    bool firstRun = true;
    UserList::Iterator it;
    QStringList sessions;
    bool presetDCOPServer = false;
    //    char *dcopStr = 0L;
    QString dcopServer;

    for(it = users.begin(); it != users.end() || firstRun; ++it)
    {
        firstRun = false;

        // cout_ << "Iterating '" << it.key() << "'" << endl;

        if(session == QuerySessions)
        {
            QStringList sessions = dcopSessionList(it.key(), it.data());
            if(sessions.isEmpty())
            {
                if(users.count() <= 1)
                {
                    cout_ << "No active sessions";
                    if(!(*it).isEmpty())
                        cout_ << " for user " << *it;
                    cout_ << endl;
                }
            }
            else
            {
                cout_ << "Active sessions ";
                if(!(*it).isEmpty())
                    cout_ << "for user " << *it << " ";
                cout_ << ":" << endl;

                QStringList::Iterator sIt = sessions.begin();
                for(; sIt != sessions.end(); ++sIt)
                    cout_ << "  " << *sIt << endl;

                cout_ << endl;
            }
            continue;
        }

        if(getenv("DCOPSERVER"))
        {
            sessions.append(getenv("DCOPSERVER"));
            presetDCOPServer = true;
        }

        if(users.count() > 1 || (users.count() == 1 && (getenv("DCOPSERVER") == 0 /*&& getenv( "DISPLAY" ) == 0*/)))
        {
            sessions = dcopSessionList(it.key(), it.data());
            if(sessions.isEmpty())
            {
                if(users.count() > 1)
                    continue;
                else
                {
                    cerr_ << "ERROR: No active KDE sessions!" << endl
                          << "If you are sure there is one, please set the $DCOPSERVER variable manually" << endl
                          << "before calling dcop." << endl;
                    exit(-1);
                }
            }
            else if(!sessionName.isEmpty())
            {
                if(sessions.contains(sessionName))
                {
                    sessions.clear();
                    sessions.append(sessionName);
                }
                else
                {
                    cerr_ << "ERROR: The specified session doesn't exist!" << endl;
                    exit(-1);
                }
            }
            else if(sessions.count() > 1 && session != AllSessions)
            {
                cerr_ << "ERROR: Multiple available KDE sessions!" << endl
                      << "Please specify the correct session to use with --session or use the" << endl
                      << "--all-sessions option to broadcast to all sessions." << endl;
                exit(-1);
            }
        }

        if(users.count() > 1 || (users.count() == 1 && (getenv("ICEAUTHORITY") == 0 || getenv("DISPLAY") == 0)))
        {
            // Check for ICE authority file and if the file can be read by us
            QString home = it.data();
            QString iceFile = it.data() + "/.ICEauthority";
            QFileInfo fi(iceFile);
            if(iceFile.isEmpty())
            {
                cerr_ << "WARNING: Cannot determine home directory for user " << it.key() << "!" << endl
                      << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
                      << "calling dcop." << endl;
            }
            else if(fi.exists())
            {
                if(fi.isReadable())
                {
                    char *envStr = strdup(("ICEAUTHORITY=" + iceFile).ascii());
                    putenv(envStr);
                    // cerr_ << "ice: " << envStr << endl;
                }
                else
                {
                    cerr_ << "WARNING: ICE authority file " << iceFile << "is not readable by you!" << endl
                          << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
                          << "calling dcop." << endl;
                }
            }
            else
            {
                if(users.count() > 1)
                    continue;
                else
                {
                    cerr_ << "WARNING: Cannot find ICE authority file " << iceFile << "!" << endl
                          << "Please check permissions or set the $ICEAUTHORITY"
                          << " variable manually before" << endl
                          << "calling dcop." << endl;
                }
            }
        }

        // Main loop
        // If users is an empty list we're calling for the currently logged
        // in user. In this case we don't have a session, but still want
        // to iterate the loop once.
        QStringList::Iterator sIt = sessions.begin();
        for(; sIt != sessions.end() || users.isEmpty(); ++sIt)
        {
            if(!presetDCOPServer && !users.isEmpty())
            {
                QString dcopFile = it.data() + "/" + *sIt;
                QFile f(dcopFile);
                if(!f.open(IO_ReadOnly))
                {
                    cerr_ << "Can't open " << dcopFile << " for reading!" << endl;
                    exit(-1);
                }

                QStringList l(QStringList::split('\n', f.readAll()));
                dcopServer = l.first();

                if(dcopServer.isEmpty())
                {
                    cerr_ << "WARNING: Unable to determine DCOP server for session " << *sIt << "!" << endl
                          << "Please check permissions or set the $DCOPSERVER variable manually before" << endl
                          << "calling dcop." << endl;
                    exit(-1);
                }
            }

            delete client;
            client = new DCOPClient;
            if(!dcopServer.isEmpty())
                client->setServerAddress(dcopServer.ascii());
            bool success = client->attach();
            if(!success)
            {
                cerr_ << "ERROR: Couldn't attach to DCOP server!" << endl;
                retval = QMAX(retval, 1);
                if(users.isEmpty())
                    break;
                else
                    continue;
            }
            dcop = client;

            int argscount = args.count();
            if(DCOPrefmode)
                argscount++;
            switch(argscount)
            {
                case 0:
                    queryApplications("");
                    break;
                case 1:
                    if(endsWith(app, '*'))
                        queryApplications(app);
                    else
                        queryObjects(app, "");
                    break;
                case 2:
                    if(endsWith(objid, '*'))
                        queryObjects(app, objid);
                    else
                        queryFunctions(app, objid);
                    break;
                case 3:
                default:
                    if(updateUserTime)
                        sendUserTime(app);
                    if(readStdin)
                    {
                        KStringList::Iterator replaceArg = params.end();

                        KStringList::Iterator it = params.begin();
                        for(; it != params.end(); ++it)
                            if(*it == "%1")
                                replaceArg = it;

                        // Read from stdin until EOF and call function for each
                        // read line
                        while(!cin_.atEnd())
                        {
                            QString buf = cin_.readLine();

                            if(replaceArg != params.end())
                                *replaceArg = buf.local8Bit();

                            if(!buf.isNull())
                            {
                                int res = callFunction(app, objid, function, params);
                                retval = QMAX(retval, res);
                            }
                        }
                    }
                    else
                    {
                        // Just call function
                        //		    cout_ << "call " << app << ", " << objid << ", " << function << ", (params)" << endl;
                        int res = callFunction(app, objid, function, params);
                        retval = QMAX(retval, res);
                    }
                    break;
            }
            // Another sIt++ would make the loop infinite...
            if(users.isEmpty())
                break;
        }

        // Another it++ would make the loop infinite...
        if(it == users.end())
            break;
    }

    return retval;
}
예제 #3
0
int main(int argc, char **argv)
{
    bool readStdin = false;
    int numOptions = 0;
    QString user;
    Session session = DefaultSession;
    QString sessionName;
    bool updateUserTime = true;

    cin_.setEncoding(QTextStream::Locale);

    // Scan for command-line options first
    for(int pos = 1; pos <= argc - 1; pos++)
    {
        if(strcmp(argv[pos], "--help") == 0)
            showHelp(0);
        else if(strcmp(argv[pos], "--pipe") == 0)
        {
            readStdin = true;
            numOptions++;
        }
        else if(strcmp(argv[pos], "--user") == 0)
        {
            if(pos <= argc - 2)
            {
                user = QString::fromLocal8Bit(argv[pos + 1]);
                numOptions += 2;
                pos++;
            }
            else
            {
                cerr_ << "Missing username for '--user' option!" << endl << endl;
                showHelp(-1);
            }
        }
        else if(strcmp(argv[pos], "--session") == 0)
        {
            if(session == AllSessions)
            {
                cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
                showHelp(-1);
            }
            else if(pos <= argc - 2)
            {
                sessionName = QString::fromLocal8Bit(argv[pos + 1]);
                numOptions += 2;
                pos++;
            }
            else
            {
                cerr_ << "Missing session name for '--session' option!" << endl << endl;
                showHelp(-1);
            }
        }
        else if(strcmp(argv[pos], "--all-users") == 0)
        {
            user = "******";
            numOptions++;
        }
        else if(strcmp(argv[pos], "--list-sessions") == 0)
        {
            session = QuerySessions;
            numOptions++;
        }
        else if(strcmp(argv[pos], "--all-sessions") == 0)
        {
            if(!sessionName.isEmpty())
            {
                cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
                showHelp(-1);
            }
            session = AllSessions;
            numOptions++;
        }
        else if(strcmp(argv[pos], "--no-user-time") == 0)
        {
            updateUserTime = false;
            numOptions++;
        }
        else if(argv[pos][0] == '-')
        {
            cerr_ << "Unknown command-line option '" << argv[pos] << "'." << endl << endl;
            showHelp(-1);
        }
        else
            break; // End of options
    }

    argc -= numOptions;

    KStringList args;

#ifdef DCOPQUIT
    if(argc > 1)
    {
        QCString prog = argv[numOptions + 1];

        if(!prog.isEmpty())
        {
            args.append(prog);

            // Pass as-is if it ends with a wildcard
            if(prog[prog.length() - 1] != '*')
            {
                // Strip a trailing -<PID> part.
                int i = prog.findRev('-');
                if((i >= 0) && prog.mid(i + 1).toLong())
                {
                    prog = prog.left(i);
                }
                args.append("qt/" + prog);
                args.append("quit()");
            }
        }
    }
#else
    for(int i = numOptions; i < argc + numOptions - 1; i++)
        args.append(argv[i + 1]);
#endif

    if(readStdin && args.count() < 3)
    {
        cerr_ << "--pipe option only supported for function calls!" << endl << endl;
        showHelp(-1);
    }

    if(user == "*" && args.count() < 3 && session != QuerySessions)
    {
        cerr_ << "ERROR: The --all-users option is only supported for function calls!" << endl << endl;
        showHelp(-1);
    }

    if(session == QuerySessions && !args.isEmpty())
    {
        cerr_ << "ERROR: The --list-sessions option cannot be used for actual DCOP calls!" << endl << endl;
        showHelp(-1);
    }

    if(session == QuerySessions && user.isEmpty())
    {
        cerr_ << "ERROR: The --list-sessions option can only be used with the --user or" << endl << "--all-users options!" << endl << endl;
        showHelp(-1);
    }

    if(session != DefaultSession && session != QuerySessions && args.count() < 3)
    {
        cerr_ << "ERROR: The --session and --all-sessions options are only supported for function" << endl << "calls!" << endl << endl;
        showHelp(-1);
    }

    UserList users;
    if(user == "*")
        users = userList();
    else if(!user.isEmpty())
        users[user] = userList()[user];

    int retval = runDCOP(args, users, session, sessionName, readStdin, updateUserTime);

    return retval;
}
예제 #4
0
int callFunction(const char *app, const char *obj, const char *func, const KStringList args)
{
    QString f = func; // Qt is better with unicode strings, so use one.
    int left = f.find('(');
    int right = f.find(')');

    if(right < left)
    {
        qWarning("parentheses do not match");
        return (1);
    }

    if(left < 0)
    {
        // try to get the interface from the server
        bool ok = false;
        KStringList funcs = dcop->remoteFunctions(app, obj, &ok);
        QCString realfunc;
        if(!ok && args.isEmpty())
            goto doit;
        if(!ok)
        {
            qWarning("object not accessible");
            return (1);
        }
        for(const auto &it : funcs)
        {
            int l = it.find('(');
            int s;
            if(l > 0)
                s = it.findRev(' ', l);
            else
                s = it.find(' ');

            if(s < 0)
                s = 0;
            else
                s++;

            if(l > 0 && it.mid(s, l - s) == func)
            {
                realfunc = it.mid(s);
                const QString arguments = it.mid(l + 1, it.find(')') - l - 1);
                uint a = arguments.contains(',');
                if((a == 0 && !arguments.isEmpty()) || a > 0)
                    a++;
                if(a == args.count())
                    break;
            }
        }
        if(realfunc.isEmpty())
        {
            qWarning("no such function");
            return (1);
        }
        f = realfunc;
        left = f.find('(');
        right = f.find(')');
    }

doit:
    if(left < 0)
        f += "()";

    // This may seem expensive but is done only once per invocation
    // of dcop, so it should be OK.
    //
    //
    QStringList intTypes;
    intTypes << "int"
             << "unsigned"
             << "long"
             << "bool";

    QStringList types;
    if(left > 0 && left + 1 < right - 1)
    {
        types = QStringList::split(',', f.mid(left + 1, right - left - 1));
        for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
        {
            QString lt = (*it).simplifyWhiteSpace();

            int s = lt.find(' ');

            // If there are spaces in the name, there may be two
            // reasons: the parameter name is still there, ie.
            // "QString URL" or it's a complicated int type, ie.
            // "unsigned long long int bool".
            //
            //
            if(s > 0)
            {
                QStringList partl = QStringList::split(' ', lt);

                // The zero'th part is -- at the very least -- a
                // type part. Any trailing parts *might* be extra
                // int-type keywords, or at most one may be the
                // parameter name.
                //
                //
                s = 1;

                while(s < static_cast< int >(partl.count()) && intTypes.contains(partl[s]))
                {
                    s++;
                }

                if(s < static_cast< int >(partl.count()) - 1)
                {
                    qWarning("The argument `%s' seems syntactically wrong.", lt.latin1());
                }
                if(s == static_cast< int >(partl.count()) - 1)
                {
                    partl.remove(partl.at(s));
                }

                lt = partl.join(" ");
                lt = lt.simplifyWhiteSpace();
            }

            (*it) = lt;
        }
        QString fc = f.left(left);
        fc += '(';
        bool first = true;
        for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
        {
            if(!first)
                fc += ",";
            first = false;
            fc += *it;
        }
        fc += ')';
        f = fc;
    }

    QByteArray data, replyData;
    QCString replyType;
    QDataStream arg(data, IO_WriteOnly);

    uint i = 0;
    for(QStringList::Iterator it = types.begin(); it != types.end(); ++it)
        marshall(arg, args, i, *it);

    if(i != args.count())
    {
        qWarning("arguments do not match");
        return (1);
    }

    if(!dcop->call(app, obj, f.latin1(), data, replyType, replyData))
    {
        qWarning("call failed");
        return (1);
    }
    else
    {
        QDataStream reply(replyData, IO_ReadOnly);

        if(replyType != "void" && replyType != "ASYNC")
        {
            QCString replyString = demarshal(reply, replyType);
            if(!replyString.isEmpty())
                printf("%s\n", replyString.data());
            else
                printf("\n");
        }
    }
    return 0;
}