51 printf(
"%s\n", qPrintable(QDBusUtil::argumentToString(v)));
55 if (v.metaType() == QMetaType::fromType<QStringList>()) {
56 const QStringList sl = v.toStringList();
57 for (
const QString &s : sl)
58 printf(
"%s\n", qPrintable(s));
59 }
else if (v.metaType() == QMetaType::fromType<QVariantList>()) {
60 const QVariantList vl = v.toList();
61 for (
const QVariant &var : vl)
63 }
else if (v.metaType() == QMetaType::fromType<QVariantMap>()) {
64 const QVariantMap map = v.toMap();
65 QVariantMap::ConstIterator it = map.constBegin();
66 for ( ; it != map.constEnd(); ++it) {
67 printf(
"%s: ", qPrintable(it.key()));
70 }
else if (v.metaType() == QMetaType::fromType<QDBusVariant>()) {
71 printArg(qvariant_cast<QDBusVariant>(v).variant());
72 }
else if (v.metaType() == QMetaType::fromType<QDBusArgument>()) {
73 QDBusArgument arg = qvariant_cast<QDBusArgument>(v);
74 if (arg.currentSignature() == QLatin1String(
"av"))
75 printArg(qdbus_cast<QVariantList>(arg));
76 else if (arg.currentSignature() == QLatin1String(
"a{sv}"))
77 printArg(qdbus_cast<QVariantMap>(arg));
79 printf(
"qdbus: I don't know how to display an argument of type '%s', run with --literal.\n",
80 qPrintable(arg.currentSignature()));
81 }
else if (v.metaType().isValid()) {
82 printf(
"%s\n", qPrintable(v.toString()));
86static void listObjects(
const QString &service,
const QString &path)
89 QDBusMessage call = QDBusMessage::createMethodCall(service, path.isEmpty() ? QLatin1String(
"/") : path,
90 QLatin1String(
"org.freedesktop.DBus.Introspectable"),
91 QLatin1String(
"Introspect"));
92 QDBusReply<QString> xml = connection.call(call);
99 QDBusError err = xml.error();
100 if (err.type() == QDBusError::ServiceUnknown)
101 fprintf(stderr,
"Service '%s' does not exist.\n", qPrintable(service));
103 printf(
"Error: %s\n%s\n", qPrintable(err.name()), qPrintable(err.message()));
106 }
else if (!xml.isValid()) {
112 doc.setContent(xml.value());
113 QDomElement node = doc.documentElement();
114 QDomElement child = node.firstChildElement();
115 while (!child.isNull()) {
116 if (child.tagName() == QLatin1String(
"node")) {
117 QString sub = path + QLatin1Char(
'/') + child.attribute(QLatin1String(
"name"));
118 printf(
"%s\n", qPrintable(sub));
119 listObjects(service, sub);
121 child = child.nextSiblingElement();
125static void listInterface(
const QString &service,
const QString &path,
const QString &interface)
127 QDBusInterface iface(service, path, interface, connection);
128 if (!iface.isValid()) {
129 QDBusError err(iface.lastError());
130 fprintf(stderr,
"Interface '%s' not available in object %s at %s:\n%s (%s)\n",
131 qPrintable(interface), qPrintable(path), qPrintable(service),
132 qPrintable(err.name()), qPrintable(err.message()));
135 const QMetaObject *mo = iface.metaObject();
138 for (
int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
139 QMetaProperty mp = mo->property(i);
142 if (mp.isReadable() && mp.isWritable())
144 else if (mp.isReadable())
149 printf(
" %s %s.%s\n", mp.typeName(), qPrintable(interface), mp.name());
153 for (
int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
154 QMetaMethod mm = mo->method(i);
156 QByteArray signature = mm.methodSignature();
157 signature.truncate(signature.indexOf(
'('));
158 printf(
"%s %s%s%s %s.%s(",
159 mm.methodType() == QMetaMethod::Signal ?
"signal" :
"method",
160 mm.tag(), *mm.tag() ?
" " :
"",
161 *mm.typeName() ? mm.typeName() :
"void",
162 qPrintable(interface), signature.constData());
164 QList<QByteArray> types = mm.parameterTypes();
165 QList<QByteArray> names = mm.parameterNames();
167 for (
int i = 0; i < types.size(); ++i) {
170 types.at(i).constData());
171 if (!names.at(i).isEmpty())
172 printf(
" %s", names.at(i).constData());
182 QDBusMessage call = QDBusMessage::createMethodCall(service, path.isEmpty() ? QLatin1String(
"/") : path,
183 QLatin1String(
"org.freedesktop.DBus.Introspectable"),
184 QLatin1String(
"Introspect"));
185 QDBusReply<QString> xml = connection.call(call);
187 if (!xml.isValid()) {
188 QDBusError err = xml.error();
189 if (err.type() == QDBusError::ServiceUnknown)
190 fprintf(stderr,
"Service '%s' does not exist.\n", qPrintable(service));
192 printf(
"Error: %s\n%s\n", qPrintable(err.name()), qPrintable(err.message()));
197 doc.setContent(xml.value());
198 QDomElement node = doc.documentElement();
199 QDomElement child = node.firstChildElement();
200 while (!child.isNull()) {
201 if (child.tagName() == QLatin1String(
"interface")) {
202 QString ifaceName = child.attribute(QLatin1String(
"name"));
203 if (QDBusUtil::isValidInterfaceName(ifaceName))
204 listInterface(service, path, ifaceName);
206 qWarning(
"Invalid D-BUS interface name '%s' found while parsing introspection",
207 qPrintable(ifaceName));
210 child = child.nextSiblingElement();
228static int placeCall(
const QString &service,
const QString &path,
const QString &interface,
229 const QString &member,
const QStringList& arguments,
bool try_prop=
true)
231 QDBusInterface iface(service, path, interface, connection);
237 bool matchFound =
false;
238 QStringList args = arguments;
240 if (!args.isEmpty()) {
241 const QMetaObject *mo = iface.metaObject();
242 QByteArray match = member.toLatin1();
245 for (
int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
246 QMetaMethod mm = mo->method(i);
247 QByteArray signature = mm.methodSignature();
248 if (signature.startsWith(match))
253 while (!matchFound) {
256 if (knownIds.isEmpty()) {
261 if (try_prop && args.size() == 1) {
263 proparg += interface;
265 proparg += args.first();
266 if (!placeCall(service, path,
"org.freedesktop.DBus.Properties",
"Set", proparg,
false))
269 fprintf(stderr,
"Cannot find '%s.%s' in object %s at %s\n",
270 qPrintable(interface), qPrintable(member), qPrintable(path),
271 qPrintable(service));
275 QMetaMethod mm = mo->method(knownIds.takeFirst());
276 QList<QByteArray> types = mm.parameterTypes();
277 for (
int i = 0; i < types.size(); ++i) {
278 if (types.at(i).endsWith(
'&')) {
281 while (types.size() > i)
287 for (
int i = 0; !args.isEmpty() && i < types.size(); ++i) {
288 const QMetaType metaType = QMetaType::fromName(types.at(i));
289 if (!metaType.isValid()) {
290 fprintf(stderr,
"Cannot call method '%s' because type '%s' is unknown to this tool\n",
291 qPrintable(member), types.at(i).constData());
294 const int id = metaType.id();
298 if ((id == QMetaType::QVariantList || id == QMetaType::QStringList)
299 && args.at(0) == QLatin1String(
"("))
302 p = argument = args.takeFirst();
304 if (id == QMetaType::UChar) {
307 p = QVariant::fromValue<uchar>(p.toUInt());
308 }
else if (id < QMetaType::User && id != QMetaType::QVariantMap) {
311 fprintf(stderr,
"Could not convert '%s' to type '%s'.\n",
312 qPrintable(argument), types.at(i).constData());
315 }
else if (id == qMetaTypeId<QDBusVariant>()) {
317 p = QVariant::fromValue(tmp);
318 }
else if (id == qMetaTypeId<QDBusObjectPath>()) {
319 QDBusObjectPath path(argument);
320 if (path.path().isNull()) {
321 fprintf(stderr,
"Cannot pass argument '%s' because it is not a valid object path.\n",
322 qPrintable(argument));
325 p = QVariant::fromValue(path);
326 }
else if (id == qMetaTypeId<QDBusSignature>()) {
327 QDBusSignature sig(argument);
328 if (sig.signature().isNull()) {
329 fprintf(stderr,
"Cannot pass argument '%s' because it is not a valid signature.\n",
330 qPrintable(argument));
333 p = QVariant::fromValue(sig);
335 fprintf(stderr,
"Sorry, can't pass arg of type '%s'.\n",
336 types.at(i).constData());
341 if (params.size() == types.size() && args.isEmpty())
343 else if (knownIds.isEmpty()) {
344 fprintf(stderr,
"Invalid number of parameters\n");
350 QDBusMessage reply = iface.callWithArgumentList(QDBus::Block, member, params);
351 if (reply.type() == QDBusMessage::ErrorMessage) {
352 QDBusError err = reply;
357 if (err.type() == QDBusError::UnknownMethod && try_prop) {
359 proparg += interface;
361 if (!placeCall(service, path,
"org.freedesktop.DBus.Properties",
"Get", proparg,
false))
364 if (err.type() == QDBusError::ServiceUnknown)
365 fprintf(stderr,
"Service '%s' does not exist.\n", qPrintable(service));
367 printf(
"Error: %s\n%s\n", qPrintable(err.name()), qPrintable(err.message()));
369 }
else if (reply.type() != QDBusMessage::ReplyMessage) {
370 fprintf(stderr,
"Invalid reply type %d\n",
int(reply.type()));
374 const QVariantList replyArguments = reply.arguments();
375 for (
const QVariant &v : replyArguments)
398 const QStringList services = bus->registeredServiceNames();
399 QMap<QString, QStringList> servicesWithAliases;
401 for (
const QString &serviceName : services) {
402 QDBusReply<QString> reply = bus->serviceOwner(serviceName);
403 QString owner = reply;
406 servicesWithAliases[owner].append(serviceName);
409 for (QMap<QString,QStringList>::const_iterator it = servicesWithAliases.constBegin();
410 it != servicesWithAliases.constEnd(); ++it) {
411 QStringList names = it.value();
413 printf(
"%s\n", qPrintable(names.join(QLatin1String(
"\n "))));
420 QCoreApplication app(argc, argv);
421 QStringList args = app.arguments();
424 bool connectionOpened =
false;
425 while (!args.isEmpty() && args.at(0).startsWith(QLatin1Char(
'-'))) {
426 QString arg = args.takeFirst();
427 if (arg == QLatin1String(
"--system")) {
428 connection = QDBusConnection::systemBus();
429 connectionOpened =
true;
430 }
else if (arg == QLatin1String(
"--bus")) {
431 if (!args.isEmpty()) {
432 connection = QDBusConnection::connectToBus(args.takeFirst(),
"QDBus");
433 connectionOpened =
true;
435 }
else if (arg == QLatin1String(
"--literal")) {
437 }
else if (arg == QLatin1String(
"--help")) {
443 if (!connectionOpened)
444 connection = QDBusConnection::sessionBus();
446 if (!connection.isConnected()) {
447 const QDBusError lastError = connection.lastError();
448 if (lastError.isValid()) {
449 fprintf(stderr,
"Could not connect to D-Bus server: %s: %s\n",
450 qPrintable(lastError.name()),
451 qPrintable(lastError.message()));
454 fprintf(stderr,
"Could not connect to D-Bus server: Unable to load dbus libraries\n");
459 QDBusConnectionInterface *bus = connection.interface();
460 if (args.isEmpty()) {
461 printAllServices(bus);
465 QString service = args.takeFirst();
466 if (!QDBusUtil::isValidBusName(service)) {
467 if (service.contains(QLatin1Char(
'*'))) {
468 if (globServices(bus, service))
471 fprintf(stderr,
"Service '%s' is not a valid name.\n", qPrintable(service));
475 if (args.isEmpty()) {
476 listObjects(service, QString());
480 QString path = args.takeFirst();
481 if (!QDBusUtil::isValidObjectPath(path)) {
482 fprintf(stderr,
"Path '%s' is not a valid path name.\n", qPrintable(path));
485 if (args.isEmpty()) {
486 listAllInterfaces(service, path);
490 QString interface = args.takeFirst();
492 int pos = interface.lastIndexOf(QLatin1Char(
'.'));
497 member = interface.mid(pos + 1);
498 interface.truncate(pos);
500 if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) {
501 fprintf(stderr,
"Interface '%s' is not a valid interface name.\n", qPrintable(interface));
504 if (!QDBusUtil::isValidMemberName(member)) {
505 fprintf(stderr,
"Method name '%s' is not a valid member name.\n", qPrintable(member));
509 int ret = placeCall(service, path, interface, member, args);