Compare commits

...

2 Commits

Author SHA1 Message Date
Alf Gaida
d286267068 Adding upstream version 0.9.0+20150908. 2015-09-23 00:02:08 +02:00
Alf Gaida
442af30319 Adding upstream version 0.9.0+20150831. 2015-09-04 01:22:16 +02:00
12 changed files with 700 additions and 106 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
build

View File

@ -22,6 +22,8 @@ set ( HDRS
set ( SRCS
passworddialog.cpp
sudo.cpp
su.cpp
main.cpp
)
@ -56,11 +58,13 @@ add_executable(lxqt-sudo
target_link_libraries(lxqt-sudo
Qt5::Widgets
util
lxqt
)
target_compile_definitions(lxqt-sudo
PRIVATE "LXQTSUDO_SUDO=\"sudo\""
PRIVATE "LXQTSUDO_SU=\"su\""
PRIVATE "LXQTSUDO=\"lxqt-sudo\""
PRIVATE "LXQT_VERSION=\"${LXQT_VERSION}\""
)

133
main.cpp
View File

@ -27,30 +27,34 @@
#include <LXQt/Application>
#include "passworddialog.h"
#include <QFileInfo>
#include <QDir>
#include <QProcess>
#include <QTimer>
#include <QTextStream>
#include <QMessageBox>
#include <QSocketNotifier>
#include <sstream>
#include <QDebug>
extern const QString app_master;
const QString app_master{QStringLiteral(LXQTSUDO)};
const QString app_version{QStringLiteral(LXQT_VERSION)};
const QString sudo_prog{QStringLiteral(LXQTSUDO_SUDO)};
const QString sudo_pwd_prompt{QStringLiteral("Password:\n")};
extern const QString sudo_prog;
extern int sudo(QStringList const & args, PasswordDialog & dlg);
extern const QString su_prog;
extern int su(QStringList const & args, PasswordDialog & dlg);
void usage(QString const & err = QString())
{
if (!err.isEmpty())
QTextStream(stderr) << err << '\n';
QTextStream(stdout)
<< QObject::tr("Usage: %1 command [arguments...]\n\n"
"GUI frontend for %2\n\n"
<< QObject::tr("Usage: %1 [option] [command [arguments...]]\n\n"
"GUI frontend for %2/%3\n\n"
"Arguments:\n"
" option:\n"
" -h|--help Print this help.\n"
" -v|--version Print version information.\n"
" -s|--su Use %3(1) as backend (instead of the default %2(8)).\n"
" command Command to run.\n"
" arguments Optional arguments for command.\n\n").arg(app_master).arg(sudo_prog);
" arguments Optional arguments for command.\n\n").arg(app_master).arg(sudo_prog).arg(su_prog);
if (!err.isEmpty())
QMessageBox(QMessageBox::Critical, app_master, err, QMessageBox::Ok).exec();
}
@ -61,12 +65,20 @@ void version()
<< QObject::tr("%1 version %2\n").arg(app_master).arg(app_version);
}
int master(int argc, char **argv)
enum backend_t
{
//master
LxQt::Application app(argc, argv, true);
app.setQuitOnLastWindowClosed(false);
BACK_SUDO
, BACK_SU
};
int main(int argc, char **argv)
{
LXQt::Application app(argc, argv, true);
app.setQuitOnLastWindowClosed(false);
backend_t backend = BACK_SUDO;
QStringList args = app.arguments();
args.removeAt(0);
if (1 >= argc)
{
usage(QObject::tr("%1: no command to run provided!").arg(app_master));
@ -83,94 +95,23 @@ int master(int argc, char **argv)
{
version();
return 0;
} else if ("-s" == arg1 || "--su" == arg1)
{
backend = BACK_SU;
args.removeAt(0);
}
//any other arguments we simply forward to sudo
}
QStringList args = app.arguments();
//check for provided command is done before
args.removeAt(0);
PasswordDialog dlg(args);
dlg.setModal(true);
app.setActiveWindow(&dlg);
lxqtApp->setActiveWindow(&dlg);
QScopedPointer<QProcess> sudo{new QProcess};
QObject::connect(&dlg, &QDialog::finished, [&sudo, &dlg] (int result)
switch (backend)
{
if (QDialog::Accepted == result)
{
sudo->write(QByteArray{}.append(dlg.password().append('\n')));
} else
{
sudo->terminate();
if (!sudo->waitForFinished(1000))
sudo->kill();
case BACK_SUDO:
return sudo(args, dlg);
case BACK_SU:
return su(args, dlg);
}
});
//start background process -> sudo
sudo->setProcessChannelMode(QProcess::ForwardedOutputChannel);
sudo->setReadChannel(QProcess::StandardError);
QString last_line;
int ret;
QObject::connect(sudo.data(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished)
, [&app, &ret, &last_line, &dlg] (int exitCode, QProcess::ExitStatus exitStatus)
{
ret = QProcess::NormalExit == exitStatus ? exitCode : 255;
if (0 != ret && last_line.startsWith(QStringLiteral("%1:").arg(sudo_prog)))
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Child '%1' process failed!\n%2").arg(sudo_prog).arg(last_line), QMessageBox::Ok).exec();
app.quit();
});
QObject::connect(sudo.data(), &QProcess::readyReadStandardError, [&sudo, &dlg, &last_line]
{
QByteArray err = sudo->readAllStandardError();
if (sudo_pwd_prompt == err.constData())
{
dlg.show();
return;
}
QTextStream{stderr, QIODevice::WriteOnly} << err;
int nl_pos = err.lastIndexOf('\n');
if (-1 == nl_pos)
last_line += err;
else
{
if (err.endsWith('\n'))
err.remove(err.size() - 1, 1);
nl_pos = err.lastIndexOf('\n');
if (-1 != nl_pos)
err.remove(0, nl_pos + 1);
last_line = err;
}
});
//forward all stdin to child
QTextStream std_in{stdin, QIODevice::ReadOnly};
QSocketNotifier stdin_watcher{0/*stdin*/, QSocketNotifier::Read};
QObject::connect(&stdin_watcher, &QSocketNotifier::activated, [&std_in, &sudo]
{
QString line{std_in.readLine()};
if (!std_in.atEnd())
line += QLatin1Char('\n');
sudo->write(line.toStdString().c_str());
if (std_in.atEnd())
sudo->closeWriteChannel();
});
sudo->start(sudo_prog, QStringList() << QStringLiteral("-S")
<< QStringLiteral("-p") << sudo_pwd_prompt
<< args);
app.exec();
sudo->waitForFinished(-1);
return ret;
}
int main(int argc, char **argv)
{
return master(argc, argv);
}

View File

@ -2,12 +2,20 @@
.SH NAME
\fBlxqt-sudo\fR \- execute a command as privileged user
.SH SYNOPSIS
\fBlxqt-sudo\fR \fIcommand\fR [\fIarguments\fR]
\fBlxqt-sudo\fR [\fIoption\fR] [\fIcommand\fR [\fIarguments\fR]]
.SH DESCRIPTION
\fBlxqt-sudo\fR is a graphical QT frontend for plain \fBsudo(8)\fR (for requesting optional password in GUI fashion).
\fBlxqt-sudo\fR is a graphical QT frontend for plain \fBsudo(8)\fR or \fBsu(1)\fR(for requesting optional password in GUI fashion).
.br
When invoked it simply spawns child \fIsudo\fR process with requested \fIcommand\fR (and \fIarguments\fR). If \fIsudo\fR requests user's password,
the GUI password dialog is shown and (after submit) the password is provided to \fIsudo\fR.
When invoked it simply spawns child \fIsudo\fR or \fIsu\fR process with requested \fIcommand\fR (and optional \fIarguments\fR). If \fIsudo\fR/\fIsu\fR requests user's password,
the GUI password dialog is shown and (after submit) the password is provided to backend.
.SH OPTIONS
\fBoption\fR is one of:
.br
-h|--help Print help.
.br
-v|--version Print version information.
.br
-s|--su Use \fBsu\fR as backend (instead of the default \fBsudo\fR).
.SH "REPORTING BUGS"
Report bugs to https://github.com/lxde/lxqt/issues
.SH "SEE ALSO"

193
su.cpp Normal file
View File

@ -0,0 +1,193 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org
*
* Copyright: 2015 LXQt team
* Authors:
* Palo Kisa <palo.kisa@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include <LXQt/Application>
#include "passworddialog.h"
#include <QMessageBox>
#include <QSocketNotifier>
#include <QDebug>
#include <QThread>
#include <pty.h>
#include <unistd.h>
#include <memory>
#include <csignal>
#include <sys/wait.h>
#include <fcntl.h>
extern const QString app_master;
extern const QString su_prog;
const QString su_prog{QStringLiteral(LXQTSUDO_SU)};
static const QString su_pwd_prompt_end{QStringLiteral(": ")};
static const QChar nl{QLatin1Char('\n')};
static void child(QString const & arg, PasswordDialog & dlg)
{
std::string s_prog = su_prog.toStdString()
, s_arg = arg.toStdString();
char const * params[] = {
s_prog.c_str()
, "-c"
, s_arg.c_str()
, nullptr
};
setsid(); //session leader
execvp(params[0], const_cast<char **>(params));
//exec never returns in case of success
QTextStream{stderr, QIODevice::WriteOnly} << QObject::tr("%1: Failed to exec '%2': %3\n").arg(app_master).arg(su_prog).arg(strerror(errno));
exit(1);
}
static void stopChild(int & childPid
, int & pwdFd
, int & ret)
{
close(pwdFd);
kill(childPid, SIGINT);
int res, status;
for (int cnt = 10; 0 == (res = waitpid(childPid, &status, WNOHANG)) && 0 < cnt; --cnt)
QThread::msleep(100);
if (0 == res)
{
kill(childPid, SIGKILL);
ret = 1;
} else
{
ret = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
}
childPid = -1;
}
static int parent(int childPid, int pwdFd, PasswordDialog & dlg)
{
//set the FD as non-blocking
if (0 != fcntl(pwdFd, F_SETFL, O_NONBLOCK))
{
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Failed to set non-block: %1").arg(strerror(errno)), QMessageBox::Ok).exec();
return 1;
}
FILE * pwd_f = fdopen(pwdFd, "r+");
if (nullptr == pwd_f)
{
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Failed to fdopen: %1").arg(strerror(errno)), QMessageBox::Ok).exec();
return 1;
}
QTextStream child_str{pwd_f};
int ret;
QObject::connect(&dlg, &QDialog::finished, [&] (int result)
{
if (QDialog::Accepted == result)
{
child_str << dlg.password().append(nl);
child_str.flush();
} else
{
stopChild(childPid, pwdFd, ret);
lxqtApp->quit();
}
});
bool check_pwd = true;
QString last_line;
QScopedPointer<QSocketNotifier> pwd_watcher{new QSocketNotifier{pwdFd, QSocketNotifier::Read}};
QObject::connect(pwd_watcher.data(), &QSocketNotifier::activated, [&]
{
QString line = child_str.readAll();
if (line.isEmpty())
{
pwd_watcher.reset(nullptr);
if (last_line.startsWith(QStringLiteral("%1:").arg(su_prog)))
{
pwd_watcher.reset(nullptr); //stop the notifications events
stopChild(childPid, pwdFd, ret);
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Child '%1' process failed!\n%2").arg(su_prog).arg(last_line), QMessageBox::Ok).exec();
}
lxqtApp->quit();
} else
{
if (check_pwd)
{
//check only first output of child(su)
check_pwd = false;
if (!line.contains(nl) && line.endsWith(su_pwd_prompt_end))
{
//if now echo is turned off, su requests password struct termios tios;
struct termios tios;
Q_ASSERT(0 == tcgetattr(pwdFd, &tios));
if (!(ECHO & tios.c_lflag))
{
dlg.show();
return;
}
}
}
QTextStream{stderr, QIODevice::WriteOnly} << line;
//assuming text oriented output
QStringList lines = line.split(nl, QString::SkipEmptyParts);
last_line = lines.isEmpty() ? QString() : lines.back();
}
});
lxqtApp->exec();
if (0 < childPid)
{
int res, status;
res = waitpid(childPid, &status, 0);
ret = (childPid == res && WIFEXITED(status)) ? WEXITSTATUS(status) : 1;
}
return ret;
}
int su(QStringList const & args, PasswordDialog & dlg)
{
int pid, fd;
if (1 != args.size())
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("With %1 backend only one argument/command is supported!").arg(su_prog), QMessageBox::Ok).exec();
else if (0 == (pid = forkpty(&fd, nullptr, nullptr, nullptr)))
child(args[0], dlg); //never returns
else if (-1 == pid)
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Failed to fork: %1").arg(strerror(errno)), QMessageBox::Ok).exec();
else
return parent(pid, fd, dlg);
return 1;
}

116
sudo.cpp Normal file
View File

@ -0,0 +1,116 @@
/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://lxqt.org
*
* Copyright: 2015 LXQt team
* Authors:
* Palo Kisa <palo.kisa@gmail.com>
*
* This program or library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include <LXQt/Application>
#include "passworddialog.h"
#include <QProcess>
#include <QMessageBox>
#include <QSocketNotifier>
#include <QDebug>
extern const QString sudo_prog;
const QString sudo_prog{QStringLiteral(LXQTSUDO_SUDO)};
const QString sudo_pwd_prompt{QStringLiteral("Password:\n")};
int sudo(QStringList const & args, PasswordDialog & dlg)
{
QScopedPointer<QProcess> sudo{new QProcess};
QObject::connect(&dlg, &QDialog::finished, [&sudo, &dlg] (int result)
{
if (QDialog::Accepted == result)
{
sudo->write(QByteArray{}.append(dlg.password().append('\n')));
} else
{
sudo->terminate();
if (!sudo->waitForFinished(1000))
sudo->kill();
}
});
//start background process -> sudo
sudo->setProcessChannelMode(QProcess::ForwardedOutputChannel);
sudo->setReadChannel(QProcess::StandardError);
QString last_line;
int ret;
QObject::connect(sudo.data(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished)
, [&ret, &last_line, &dlg] (int exitCode, QProcess::ExitStatus exitStatus)
{
ret = QProcess::NormalExit == exitStatus ? exitCode : 255;
if (0 != ret && last_line.startsWith(QStringLiteral("%1:").arg(sudo_prog)))
QMessageBox(QMessageBox::Critical, dlg.windowTitle()
, QObject::tr("Child '%1' process failed!\n%2").arg(sudo_prog).arg(last_line), QMessageBox::Ok).exec();
lxqtApp->quit();
});
QObject::connect(sudo.data(), &QProcess::readyReadStandardError, [&sudo, &dlg, &last_line]
{
QByteArray err = sudo->readAllStandardError();
if (sudo_pwd_prompt == err.constData())
{
dlg.show();
return;
}
QTextStream{stderr, QIODevice::WriteOnly} << err;
int nl_pos = err.lastIndexOf('\n');
if (-1 == nl_pos)
last_line += err;
else
{
if (err.endsWith('\n'))
err.remove(err.size() - 1, 1);
nl_pos = err.lastIndexOf('\n');
if (-1 != nl_pos)
err.remove(0, nl_pos + 1);
last_line = err;
}
});
//forward all stdin to child
QTextStream std_in{stdin, QIODevice::ReadOnly};
QSocketNotifier stdin_watcher{0/*stdin*/, QSocketNotifier::Read};
QObject::connect(&stdin_watcher, &QSocketNotifier::activated, [&std_in, &sudo]
{
QString line{std_in.readLine()};
if (!std_in.atEnd())
line += QLatin1Char('\n');
sudo->write(line.toStdString().c_str());
if (std_in.atEnd())
sudo->closeWriteChannel();
});
sudo->start(sudo_prog, QStringList() << QStringLiteral("-S")
<< QStringLiteral("-p") << sudo_pwd_prompt
<< args);
lxqtApp->exec();
sudo->waitForFinished(-1);
return ret;
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
<TS version="2.1" language="de">
<context>
<name>PasswordDialog</name>
<message>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="el">
<context>
<name>PasswordDialog</name>
<message>
<location filename="../passworddialog.ui" line="20"/>
<location filename="../build/ui_passworddialog.h" line="129"/>
<source>LXQt sudo</source>
<translation>LXQt sudo</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="77"/>
<location filename="../build/ui_passworddialog.h" line="134"/>
<source>Command:</source>
<translation>Εντολή:</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="84"/>
<location filename="../build/ui_passworddialog.h" line="135"/>
<source>Password:</source>
<translation>Κωδικός πρόσβασης:</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="43"/>
<source>&lt;b&gt;%1&lt;/b&gt; needs administrative privileges.
Please enter your password.</source>
<translation>Το &lt;b&gt;%1&lt;/b&gt; απαιτεί προνόμια διαχειριστή.
Παρακαλώ εισαγάγετε τον κωδικό πρόσβασης.</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="54"/>
<source>Attempt #%1</source>
<translation>Προσπάθεια #%1</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../main.cpp" line="57"/>
<source>Usage: %1 command [arguments...]
GUI frontend for %2
Arguments:
command Command to run.
arguments Optional arguments for command.
</source>
<translation>Χρήση: %1 εντολή [ορίσματα...]
Περιβάλλον συστήματος υποστήριξης του %2
Ορίσματα:
εντολή Η εντολή προς εκτέλεση.
ορίσματα Προαιρετικά ορίσματα για την εντολή.
</translation>
</message>
<message>
<location filename="../main.cpp" line="69"/>
<source>%1 version %2
</source>
<translation>%1 έκδοση %2
</translation>
</message>
<message>
<location filename="../main.cpp" line="80"/>
<source>%1: no command to run provided!</source>
<translation>%1: δεν παρείχατε κάποια εντολή προς εκτέλεση!</translation>
</message>
<message>
<location filename="../main.cpp" line="131"/>
<source>Child &apos;%1&apos; process failed!
%2</source>
<translation>Η θυγατρική διεργασία «%1» απέτυχε!
%2</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="it">
<context>
<name>Communication</name>
<message>
<location filename="../communication.cpp" line="85"/>
<source>%1: Communication - unable to create shared memory(%2B), </source>
<translation>%1: Comunicazione - non è stato possibile creare memoria condivisa(%2B), </translation>
</message>
<message>
<location filename="../communication.cpp" line="183"/>
<source>%1: Communication - password is too long(%2) for aquired shared memory(%3), has to be cut-off...
</source>
<translation>%1: Comunicazione - password troppo lunga(%2) per acquisire memoria condivisa(%3) deve essere accorciata...
</translation>
</message>
</context>
<context>
<name>PasswordDialog</name>
<message>
<location filename="../passworddialog.ui" line="20"/>
<location filename="../build/ui_passworddialog.h" line="129"/>
<source>LXQt sudo</source>
<translation></translation>
</message>
<message>
<location filename="../passworddialog.ui" line="77"/>
<location filename="../build/ui_passworddialog.h" line="134"/>
<source>Command:</source>
<translation>Comando:</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="84"/>
<location filename="../build/ui_passworddialog.h" line="135"/>
<source>Password:</source>
<translation></translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="43"/>
<source>&lt;b&gt;%1&lt;/b&gt; needs administrative privileges.
Please enter your password.</source>
<translation>&lt;b&gt;%1&lt;/b&gt; richiede privilegi di amministratore.
Per favore inserire la password.</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="53"/>
<source>Attempt #%1</source>
<translation>Tentativo #%1</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../main.cpp" line="58"/>
<source>Usage: %1 command [arguments...]
GUI frontend for %2
Arguments:
command Command to run.
arguments Optional arguments for command.
</source>
<translation>Uso: %1 comando [argomenti...]
Frontend grafico per %2
Argomenti:
comando Comando da eseguire.
argomenti Argomenti opzionali per il comando.
</translation>
</message>
<message>
<location filename="../main.cpp" line="70"/>
<source>%1 version %2
</source>
<translation>%1 versione %2
</translation>
</message>
<message>
<location filename="../main.cpp" line="81"/>
<source>%1: no command to run provided!</source>
<translation>%1: non è stato immesso nessun comando da eseguire!</translation>
</message>
<message>
<location filename="../main.cpp" line="156"/>
<source>Child &apos;%1&apos; process failed!
%2</source>
<translation>Sottoprocesso %1 fallito!
%2</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
<context>
<name>PasswordDialog</name>
<message>
<location filename="../passworddialog.ui" line="20"/>
<location filename="../build/ui_passworddialog.h" line="129"/>
<source>LXQt sudo</source>
<translation>LXQt sudo</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="77"/>
<location filename="../build/ui_passworddialog.h" line="134"/>
<source>Command:</source>
<translation>Komenda:</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="84"/>
<location filename="../build/ui_passworddialog.h" line="135"/>
<source>Password:</source>
<translation>Hasło:</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="43"/>
<source>&lt;b&gt;%1&lt;/b&gt; needs administrative privileges.
Please enter your password.</source>
<translation>&lt;b&gt;%1&lt;/b&gt; potrzebuje uprawnień administratora.
Proszę wprowadź hasło.</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="54"/>
<source>Attempt #%1</source>
<translation>Próba #%1</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../main.cpp" line="57"/>
<source>Usage: %1 command [arguments...]
GUI frontend for %2
Arguments:
command Command to run.
arguments Optional arguments for command.
</source>
<translation>Sposób użycia: %1 komenda [argumenty...]
Graficzna nakładka na %2
Argumenty:
komenda Komenda do wykonania.
argumenty Opcjonalne argumenty dla komendy.
</translation>
</message>
<message>
<location filename="../main.cpp" line="69"/>
<source>%1 version %2
</source>
<translation>%1 wersja %2
</translation>
</message>
<message>
<location filename="../main.cpp" line="80"/>
<source>%1: no command to run provided!</source>
<translation>%1: nie podano komendy do wykonania!</translation>
</message>
<message>
<location filename="../main.cpp" line="131"/>
<source>Child &apos;%1&apos; process failed!
%2</source>
<translation>Wykonanie procesu &apos;%1&apos; nie powiodło się!
%2</translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
<TS version="2.1" language="sk">
<context>
<name>PasswordDialog</name>
<message>

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0">
<context>
<name>PasswordDialog</name>
<message>
<location filename="../passworddialog.ui" line="20"/>
<location filename="../build/ui_passworddialog.h" line="129"/>
<source>LXQt sudo</source>
<translation>LXQt sudo</translation>
</message>
<message>
<location filename="../passworddialog.ui" line="77"/>
<location filename="../build/ui_passworddialog.h" line="134"/>
<source>Command:</source>
<translation></translation>
</message>
<message>
<location filename="../passworddialog.ui" line="84"/>
<location filename="../build/ui_passworddialog.h" line="135"/>
<source>Password:</source>
<translation></translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="43"/>
<source>&lt;b&gt;%1&lt;/b&gt; needs administrative privileges.
Please enter your password.</source>
<translation>&lt;b&gt;%1&lt;/b&gt;
</translation>
</message>
<message>
<location filename="../passworddialog.cpp" line="54"/>
<source>Attempt #%1</source>
<translation> %1</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="../main.cpp" line="57"/>
<source>Usage: %1 command [arguments...]
GUI frontend for %2
Arguments:
command Command to run.
arguments Optional arguments for command.
</source>
<translation>%1 [...]
%2
</translation>
</message>
<message>
<location filename="../main.cpp" line="69"/>
<source>%1 version %2
</source>
<translation>%1 %s</translation>
</message>
<message>
<location filename="../main.cpp" line="80"/>
<source>%1: no command to run provided!</source>
<translation>%1</translation>
</message>
<message>
<location filename="../main.cpp" line="131"/>
<source>Child &apos;%1&apos; process failed!
%2</source>
<translation>&apos;%1&apos;
%2</translation>
</message>
</context>
</TS>