mirror of
https://invent.kde.org/system/dolphin
synced 2024-11-05 18:47:12 +00:00
Better error reporting
svn path=/trunk/kdeutils/kdepasswd/; revision=55529
This commit is contained in:
parent
c6719462a9
commit
6c9726aeb7
4 changed files with 152 additions and 86 deletions
|
@ -1,11 +1,12 @@
|
|||
/* vi: ts=8 sts=4 sw=4
|
||||
*
|
||||
* $Id: $
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of the KDE project, module kdesu.
|
||||
* Copyright (C) 2000 Geert Jansen <jansen@kde.org>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <qcstring.h>
|
||||
|
@ -15,16 +16,13 @@
|
|||
#include <kaboutdata.h>
|
||||
#include <kcmdlineargs.h>
|
||||
#include <kmessagebox.h>
|
||||
#include <kstddirs.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "passwd.h"
|
||||
#include "passwddlg.h"
|
||||
|
||||
|
||||
const char *Version = "1.0";
|
||||
|
||||
static KCmdLineOptions options[] = {
|
||||
static KCmdLineOptions options[] =
|
||||
{
|
||||
{ "user", I18N_NOOP("Change password of this user."), 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
@ -33,9 +31,8 @@ static KCmdLineOptions options[] = {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
KAboutData aboutData("kdepasswd", I18N_NOOP("KDE passwd"),
|
||||
Version, I18N_NOOP("Changes a Unix password."),
|
||||
KAboutData::License_Artistic,
|
||||
"Copyright (c) 2000 Geert Jansen");
|
||||
VERSION, I18N_NOOP("Changes a Unix password."),
|
||||
KAboutData::License_Artistic, "Copyright (c) 2000 Geert Jansen");
|
||||
aboutData.addAuthor("Geert Jansen", I18N_NOOP("Maintainer"),
|
||||
"jansen@kde.org", "http://www.stack.nl/~geertj/");
|
||||
|
||||
|
@ -43,17 +40,12 @@ int main(int argc, char **argv)
|
|||
KCmdLineArgs::addCmdLineOptions(options);
|
||||
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
||||
|
||||
KApplication app;
|
||||
|
||||
QCString user;
|
||||
if (args->count())
|
||||
user = args->arg(0);
|
||||
|
||||
KApplication app;
|
||||
|
||||
if (KStandardDirs::findExe("passwd").isEmpty()) {
|
||||
kDebugFatal("passwd not found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
QCString oldpass;
|
||||
int result = KDEpasswd1Dialog::getPassword(oldpass, user);
|
||||
if (result != KDEpasswd1Dialog::Accepted)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
@ -29,28 +30,25 @@
|
|||
#include "passwd.h"
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ID __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define ID "PasswdProcess"
|
||||
#endif
|
||||
|
||||
|
||||
PasswdProcess::PasswdProcess(QCString user)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if (user.isEmpty()) {
|
||||
if (user.isEmpty())
|
||||
{
|
||||
pw = getpwuid(getuid());
|
||||
if (pw == 0L) {
|
||||
kdDebug() << "You don't exist!";
|
||||
if (pw == 0L)
|
||||
{
|
||||
kdDebug(1512) << "You don't exist!\n";
|
||||
return;
|
||||
}
|
||||
m_User = pw->pw_name;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
pw = getpwnam(user);
|
||||
if (pw == 0L) {
|
||||
kdDebug() << ID << ": User " << user.data() << "does not exist.";
|
||||
if (pw == 0L)
|
||||
{
|
||||
kdDebug(1512) << k_lineinfo << "User " << user << "does not exist.\n";
|
||||
return;
|
||||
}
|
||||
m_User = user;
|
||||
|
@ -65,7 +63,7 @@ PasswdProcess::~PasswdProcess()
|
|||
|
||||
int PasswdProcess::checkCurrent(const char *oldpass)
|
||||
{
|
||||
return exec(oldpass, 0L, 1) != 1;
|
||||
return exec(oldpass, 0L, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,26 +75,24 @@ int PasswdProcess::exec(const char *oldpass, const char *newpass,
|
|||
if (check)
|
||||
setTerminal(true);
|
||||
|
||||
QString path = KStandardDirs::findExe("passwd");
|
||||
if (path.isEmpty()) {
|
||||
kdDebug() << "passwd not found!";
|
||||
return -1;
|
||||
}
|
||||
QCString cpath = path.latin1();
|
||||
// Try to set the default locale to make the parsing of the output
|
||||
// of `passwd' easier.
|
||||
putenv("LANG=C");
|
||||
|
||||
QCStringList args;
|
||||
args += m_User;
|
||||
if (PtyProcess::exec(cpath, args) < 0)
|
||||
return -1;
|
||||
|
||||
int ret = ConversePasswd(oldpass, newpass, check);
|
||||
if (ret < 0) {
|
||||
kdDebug() << ID << ": Conversation with passwd failed";
|
||||
return -1;
|
||||
}
|
||||
if (ret == 1) {
|
||||
kill(m_Pid, SIGKILL);
|
||||
waitForChild();
|
||||
int ret = PtyProcess::exec("passwd", args);
|
||||
if (ret < 0)
|
||||
{
|
||||
kdDebug(1512) << k_lineinfo << "Passwd not found!\n";
|
||||
return PasswdNotFound;
|
||||
}
|
||||
|
||||
ret = ConversePasswd(oldpass, newpass, check);
|
||||
if (ret < 0)
|
||||
kdDebug(1512) << k_lineinfo << "Conversation with passwd failed.\n";
|
||||
|
||||
waitForChild();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -104,6 +100,7 @@ int PasswdProcess::exec(const char *oldpass, const char *newpass,
|
|||
/*
|
||||
* The tricky thing is to make this work with a lot of different passwd
|
||||
* implementations. We _don't_ want implementation specific routines.
|
||||
* Return values: -1 = unknown error, 0 = ok, >0 = error code.
|
||||
*/
|
||||
|
||||
int PasswdProcess::ConversePasswd(const char *oldpass, const char *newpass,
|
||||
|
@ -112,30 +109,34 @@ int PasswdProcess::ConversePasswd(const char *oldpass, const char *newpass,
|
|||
QCString line;
|
||||
int state = 0;
|
||||
|
||||
while (state < 7) {
|
||||
while (state != 7)
|
||||
{
|
||||
line = readLine();
|
||||
if (line.isNull()) {
|
||||
if (state == 6)
|
||||
break;
|
||||
else
|
||||
return -1;
|
||||
if (line.isNull())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
// Eat garbage, wait for prompt
|
||||
if (isPrompt(line, "password")) {
|
||||
if (isPrompt(line, "password"))
|
||||
{
|
||||
WaitSlave();
|
||||
write(m_Fd, oldpass, strlen(oldpass));
|
||||
write(m_Fd, "\n", 1);
|
||||
state++; break;
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
if (m_bTerminal) fputs(line, stdout);
|
||||
if (m_bTerminal)
|
||||
fputs(line, stdout);
|
||||
break;
|
||||
|
||||
case 1: case 3: case 5:
|
||||
case 1: case 3: case 6:
|
||||
// Wait for \n
|
||||
if (line.isEmpty()) {
|
||||
if (line.isEmpty())
|
||||
{
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
|
@ -144,41 +145,67 @@ int PasswdProcess::ConversePasswd(const char *oldpass, const char *newpass,
|
|||
|
||||
case 2:
|
||||
// Wait for second prompt.
|
||||
if (isPrompt(line, "new")) {
|
||||
if (isPrompt(line, "new"))
|
||||
{
|
||||
if (check)
|
||||
return 1;
|
||||
{
|
||||
kill(m_Pid, SIGKILL);
|
||||
waitForChild();
|
||||
return 0;
|
||||
}
|
||||
WaitSlave();
|
||||
write(m_Fd, newpass, strlen(newpass));
|
||||
write(m_Fd, "\n", 1);
|
||||
state++; break;
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
// Assume error message.
|
||||
if (m_bTerminal) fputs(line, stdout);
|
||||
// Assume incorrect password.
|
||||
if (m_bTerminal)
|
||||
fputs(line, stdout);
|
||||
m_Error = line;
|
||||
return -1;
|
||||
return PasswordIncorrect;
|
||||
|
||||
case 4:
|
||||
// Wait for third prompt
|
||||
if (isPrompt(line, "password")) {
|
||||
if (isPrompt(line, "re"))
|
||||
{
|
||||
WaitSlave();
|
||||
write(m_Fd, newpass, strlen(newpass));
|
||||
write(m_Fd, "\n", 1);
|
||||
state++; break;
|
||||
state += 2;
|
||||
break;
|
||||
}
|
||||
// Assume error message.
|
||||
if (m_bTerminal) fputs(line, stdout);
|
||||
// Warning or error about the new password
|
||||
if (m_bTerminal)
|
||||
fputs(line, stdout);
|
||||
m_Error = line;
|
||||
return -1;
|
||||
state++;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// Wait for EOF, but no prompt.
|
||||
if (isPrompt(line, "password"))
|
||||
return 1;
|
||||
if (m_bTerminal) fputs(line, stdout);
|
||||
case 5:
|
||||
// Wait for either a "Reenter password" or a "Enter password" prompt
|
||||
if (isPrompt(line, "re"))
|
||||
{
|
||||
WaitSlave();
|
||||
write(m_Fd, newpass, strlen(newpass));
|
||||
write(m_Fd, "\n", 1);
|
||||
state++;
|
||||
break;
|
||||
}
|
||||
else if (isPrompt(line, "password"))
|
||||
{
|
||||
kill(m_Pid, SIGKILL);
|
||||
waitForChild();
|
||||
return PasswordNotGood;
|
||||
}
|
||||
if (m_bTerminal)
|
||||
fputs(line, stdout);
|
||||
m_Error += line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kdDebug() << ID << ": Conversation ended";
|
||||
kdDebug(1512) << k_lineinfo << "Conversation ended successfully.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -187,8 +214,10 @@ bool PasswdProcess::isPrompt(QCString line, const char *word)
|
|||
{
|
||||
unsigned i, j, colon;
|
||||
|
||||
for (i=0,j=0,colon=0; i<line.length(); i++) {
|
||||
if (line[i] == ':') {
|
||||
for (i=0,j=0,colon=0; i<line.length(); i++)
|
||||
{
|
||||
if (line[i] == ':')
|
||||
{
|
||||
j = i; colon++;
|
||||
continue;
|
||||
}
|
||||
|
@ -200,7 +229,6 @@ bool PasswdProcess::isPrompt(QCString line, const char *word)
|
|||
return false;
|
||||
if (word == 0L)
|
||||
return true;
|
||||
|
||||
return line.contains(word, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vi: ts=8 sts=4 sw=4
|
||||
*
|
||||
* $Id: $
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of the KDE project, module kdesu.
|
||||
* Copyright (C) 2000 Geert Jansen <jansen@kde.org>
|
||||
|
@ -23,6 +23,8 @@ public:
|
|||
PasswdProcess(QCString user=0);
|
||||
~PasswdProcess();
|
||||
|
||||
enum Errors { PasswdNotFound=1, PasswordIncorrect, PasswordNotGood };
|
||||
|
||||
int checkCurrent(const char *oldpass);
|
||||
int exec(const char *oldpass, const char *newpass, int check=0);
|
||||
|
||||
|
|
|
@ -33,12 +33,31 @@ KDEpasswd1Dialog::~KDEpasswd1Dialog()
|
|||
bool KDEpasswd1Dialog::checkPassword(const char *password)
|
||||
{
|
||||
PasswdProcess proc(m_User);
|
||||
|
||||
int ret = proc.checkCurrent(password);
|
||||
if (ret != 0) {
|
||||
switch (ret)
|
||||
{
|
||||
case -1:
|
||||
KMessageBox::error(this, i18n("Conversation with `passwd' failed."));
|
||||
done(Rejected);
|
||||
return true;
|
||||
|
||||
case 0:
|
||||
return true;
|
||||
|
||||
case PasswdProcess::PasswdNotFound:
|
||||
KMessageBox::error(this, i18n("Could not find the program `passwd'."));
|
||||
return true;
|
||||
|
||||
case PasswdProcess::PasswordIncorrect:
|
||||
KMessageBox::sorry(this, i18n("Incorrect password! Please try again."));
|
||||
return false;
|
||||
|
||||
default:
|
||||
KMessageBox::error(this, i18n("Internal error: illegal return value "
|
||||
"from PasswdProcess::checkCurrent."));
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,11 +93,36 @@ KDEpasswd2Dialog::~KDEpasswd2Dialog()
|
|||
bool KDEpasswd2Dialog::checkPassword(const char *password)
|
||||
{
|
||||
PasswdProcess proc(m_User);
|
||||
int ret = proc.exec(m_Pass, password);
|
||||
if (ret != 0) {
|
||||
KMessageBox::error(this, proc.error());
|
||||
return false;
|
||||
|
||||
if (strlen(password) > 8)
|
||||
{
|
||||
KMessageBox::information(this,
|
||||
i18n("Your password will be truncated to 8 characters."));
|
||||
const_cast<char *>(password)[8] = '\000';
|
||||
}
|
||||
|
||||
int ret = proc.exec(m_Pass, password);
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
if (!proc.error().isEmpty())
|
||||
{
|
||||
// The pw change succeeded but there is a warning.
|
||||
KMessageBox::information(this, proc.error());
|
||||
}
|
||||
return true;
|
||||
|
||||
case PasswdProcess::PasswordNotGood:
|
||||
// The pw change did not succeed. Print the error.
|
||||
KMessageBox::sorry(this, proc.error());
|
||||
return false;
|
||||
|
||||
default:
|
||||
KMessageBox::sorry(this, i18n("Conversation with `passwd' failed."));
|
||||
done(Rejected);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue