Check if at least one Wayland session is running - c++

I'm using Qt and want to check if any Wayland session is running.
For now I have this just for test code, that works as expected:
QProcess process;
process.setProgram("bash");
process.setArguments({"-c", "loginctl list-sessions --no-legend | awk '{print $1}'"});
process.start();
process.waitForFinished();
const QByteArrayList sessionsList = process.readAll().split('\n');
foreach (const QByteArray &sessionID, sessionsList) {
if (sessionID.isEmpty())
continue;
process.setArguments({"-c", "loginctl show-session " + sessionID});
process.start();
process.waitForFinished();
if (process.readAll().contains("Type=wayland"))
qDebug() << "At least one Wayland session is running";
}
Is it possible to get rid of QProcess and use Linux C++ API?

You can try to connect to Wayland. If you can connect to a Wayland composer it is running otherwise is not running or someone haven't set the environment variables correctly and not used the default name.
#include <wayland/wayland-client-core.h>
bool isWaylandRunning(){
auto display = wl_display_connect(nullptr);
if (display){
wl_display_disconnect(display);
return true;
} else {
return false;
}
}

Related

I need to check if the process is running using pid in QT

I want to check if the process is running with process id (pid).
My project is developed using QT and can be executed on both Windows and Linux.
So my code need to be able to run on both OS.
I have searched full through stackoverflow but I couldn't find expected result.
I already tried to execute cmd command -
tasklist, kill. But I still can't get result.
I think there is a way to use QProcess to get access of specified process with pid.
Here are my code I used.
#ifdef Q_OS_WIN32
QVariant variant(this->pid);
QString cmd = "tasklist /nh /fi \"pid eq " + variant.toString() + "\"";
QProcess process;
process.start(cmd);
process.waitForReadyRead();
QString result = process.readAll();
process.terminate();
if (result.indexOf(variant.toString()) >= 0)
{
return true;
}
else {
return false;
}
#else
QVariant variant(this->pid);
QString cmd = "kill -0 " + variant.toString();
QProcess process;
process.start(cmd);
process.waitForReadyRead();
QString result = process.readAll();
process.terminate();
if (result.indexOf("No") >= 0)
{
return false;
}
else {
return true;
}
#endif
I want to get help.

Issue Commands to QProcess once its started

So in the code I have now below it loads up gphoto2 with no problem and adds the ---shell switch to it. How can I add one more line to issue a command to that shell the command i want to issue to the shell is "start-preview-stream" Thanks again!
QProcess gphoto2;
gphoto2.start("gphoto2", QStringList() << "--shell");
if (!gphoto2.waitForStarted()){
qDebug("gPhoto2 didn't start properly");
return 1;
}
qDebug("gPhoto2 Started Successfully");
Debug Shows
gPhoto2 Started Successfully
I have also tried the following with no luck
QProcess gphoto2;
gphoto2.start("gphoto2", QStringList() << "--shell" << "start-preview-stream");
if (!gphoto2.waitForStarted()){
qDebug("gPhoto2 didn't start properly");
return 1;
}
qDebug("gPhoto2 Started Successfully");
If you just need to send that string to the process's standard input stream, you need to write() to the QProcess:
QProcess gphoto2;
gphoto2.start("gphoto2", QStringList() << "--shell");
if (!gphoto2.waitForStarted()){
qDebug("gPhoto2 didn't start properly");
return 1;
}
qDebug("gPhoto2 Started Successfully");
gphoto2.write("start-preview-stream\n");
(obviously, you'll need to add some appropriate checking of the return value etc.)

Qt: How to get live output of a running QProcess

I have to get the output of a QProcess while it is running. Therefore I have written the following Code:
CommandExecutor_C::CommandExecutor_C():
mProcessStatus(AI_UNKNOWN),
mOnTdiActiveCallback(),
mTdiProcess(new QProcess)
{
connect(mTdiProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(CheckOutput()));
connect(mTdiProcess, SIGNAL(readyReadStandardError()), this, SLOT(CheckOutput()));
}
void CommandExecutor_C::ExecuteCommand(QString &aCommand)
{
mTdiProcess->start(aCommand, QProcess::Unbuffered | QProcess::ReadWrite);
LOGINFO(FB_TDI,"Launch command: " + aCommand.toStdString());
}
void CommandExecutor_C::CheckOutput()
{
QString StdOut = QString(mTdiProcess->readAllStandardOutput());
QString StdErr = QString(mTdiProcess->readAllStandardError());
mProcessStatus = CheckTdiAutomationInterface(StdOut.toStdString(), StdErr.toStdString());
if(mProcessStatus != AI_UNKNOWN)
{
OnTdiActive(mProcessStatus);
}
}
This works fine if QProcess gets finished but in my case the Process starts an automation interface which should run in background permanently. Therefore I have used "readyReadStandardOutput" and connect it to the slot CheckOutput(). CheckOutput() is getting called just if the process has been finished. Otherwise I am waiting endless.
I have googled a lot about the problem but nothing worked. I am very sure that the output is getting buffered and does just return if the Process has finished. Therefore I have started the Process in Unbuffered-Mode. I have also tried to forward the channels of mTdiProcess. Here the Code:
void CommandExecutor_C::ExecuteCommand(QString &aCommand)
{
mTdiProcess->setProcessChannelMode(QProcess::ForwardedChannels);
mTdiProcess->start(aCommand, QProcess::Unbuffered | QProcess::ReadWrite);
LOGINFO(FB_TDI,"Launch command: " + aCommand.toStdString());
}
But nothing worked. I hope you can help me.
I am using Qt 5.4.2 if that's important.
I usually check the output in regular intervals like this:
bool returnBool = false;
while (returnBool == false)
{
/*! Wait one second if the process finishes. Then read all output to
* stdout and stderr and redo. */
returnBool = process.waitForFinished(1000);
QString outputStdOut = process.readAllStandardOutput();
QString outputStdErr = process.readAllStandardError();
}

How to shutdown Linux using C++ or Qt without call to "system()"?

I want to shutdown an Embedded Linux when a close button is pushed on the UI. I know I can do it with a call to system:
system("shutdown -P now");
Ref: Link
But knowing that using system is not advised, I'ld like to know if there is another way in C++ to do this (if there is also a specific way to do this using Qt, I'ld also like to know it although a general C++ method is more important).
On Linux you can call the reboot system call to poweroff, halt, or reboot.
The following snippet shows how to poweroff a machine, but note that it will of course only work on Linux :
#include <unistd.h>
#include <linux/reboot.h>
int main() {
reboot(LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF, 0);
}
Of course, you will need sufficient privileges to use this syscall.
Under glibc you'll need:
#include <unistd.h>
#include <linux/reboot.h>
#include <sys/reboot.h>
int main() {
sync();
reboot(LINUX_REBOOT_CMD_POWER_OFF);
}
Again, as always, you'll need to be running with sufficient privileges.
reboot's man page
If your system have systemd, then you can use logind functionality via D-Bus. Qt solution is the following (just tested):
QDBusInterface logind{"org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus()};
const auto message = logind.callWithArgumentList(QDBus::Block, "CanPowerOff", {});
QDBusPendingReply< QString > canPowerOff = message;
Q_ASSERT(canPowerOff.isFinished());
if (canPowerOff.isError()) {
const auto error = canPowerOff.error();
qWarning().noquote()
<< QDBusInterface::tr("Asynchronous call finished with error: %1 (%2)")
.arg(error.name(), error.message());
return EXIT_FAILURE;
}
if (canPowerOff.value() == "yes") {
QDBusPendingReply<> powerOff = logind.callWithArgumentList(QDBus::Block, "PowerOff", {true, });
Q_ASSERT(powerOff.isFinished());
if (powerOff.isError()) {
const auto error = powerOff.error();
qWarning().noquote()
<< QDBusInterface::tr("Asynchronous call finished with error: %1 (%2)")
.arg(error.name(), error.message());
return EXIT_FAILURE;
}
} else {
qCritical().noquote()
<< QCoreApplication::translate("poweroff", "Can't power off: CanPowerOff() result is %1")
.arg(canPowerOff.value());
return EXIT_FAILURE;
}
Also possible there is a need to add a file /etc/polkit-1/localauthority/50-local.d/10-enable-shutdown.pkla to suppress interactive authentication requirement:
[Enable shoutdown for users]
Identity=unix-group:users
Action=org.freedesktop.login1;org.freedesktop.login1.power-off;org.freedesktop.login1.power-off-ignore-inhibit;org.freedesktop.login1.power-off-multiple-sessions
ResultAny=yes
ResultInactive=yes
ResultActive=yes
The Qt way is to use QProcess to run the shutdown command:
QProcess process;
process.startDetached("shutdown -P now");
If your problem is that you think system() isn't secure, you can use
system("/bin/sh shutdown -P now");
then you can be sure you're using the right shutdown function.

How to Detect "Network is Unreachable" via Ping using QProcess?

I am having an issue while pinging to Destination / local IP using QProcess. QProcess returns "0" when ping is Successfull while Also when ping gives "Network is Unreachable" error (seen manually on terminal).
Actually I need to check the network connection in my application. To implement it, i used a very simple concept of ping using QProcess. I need to pop up a messagebox if there is any network error otherwise application starts normally without any popup message.
Here is my code for ping :
bool App::pingPcuStatus(void)
{
const QString IP ="192.168.49.44";
bool ret = false;
int status;
if ( IP == "0.0.0.0") {
status = 1;
}
else {
QProcess pingProcess;
QString exec = "ping";
QStringList params;
params << "-c" << "1" << IP;
status = pingProcess.execute(exec, params); //status = 0 , if Ping Successfull
pingProcess.close();
}
ret = (status) ? false : true;
return ret;
}
But while debugging I found, it returns "true" even i am not conected to network. (I tried manual ping with same command on terminal, it gives "Network is Unreachable" error).
This leads to a big bug in my case.
What is the best way to capture this error using QProcess or any other way to resolve it ???
Any Idea or Suggestion are welcome.
Original answer from https://stackoverflow.com/a/2148360/793796:
QProcess pingProcess;
QString exec = "ping";
QStringList params;
params << "-c" << "1" << IP;
pingProcess.start(exec,params,QIODevice::ReadOnly);
pingProcess.waitForFinished(-1);
QString p_stdout = pingProcess.readAllStandardOutput();
QString p_stderr = pingProcess.readAllStandardError();
Then you can parse stdout & stderr.