Index: kdelibs/kdesu/ssh.h
===================================================================
--- kdelibs/kdesu/ssh.h	(Revision 1063492)
+++ kdelibs/kdesu/ssh.h	(Arbeitskopie)
@@ -29,8 +29,11 @@
                         const QByteArray &command = QByteArray());
     ~SshProcess();
 
-    enum Errors { SshNotFound=1, SshNeedsPassword, SshIncorrectPassword };
+    enum Errors { NoError=0, SshNeedsNoPassword=0, SshNotFound=1, SshNeedsPassword, SshIncorrectPassword };
+    enum ExtendedErrors { GeneralError=-1 };
 
+    enum ExecType { NormalExec=0, PasswordCorrectCheck=1, PasswordNeededCheck=2 };
+
     /**
      * Sets the target host.
      */
@@ -59,7 +62,7 @@
     /**
      * Executes the command.
      */
-    int exec(const char *password, int check=0);
+    int exec(const char *password, int check=NormalExec);
 
     QByteArray prompt() const;
     QByteArray error() const;
@@ -69,6 +72,7 @@
     virtual QByteArray displayAuth();
 
 private:
+    enum SshResult { SshProtocolError=-1, SshNoError=0, StoppedAtPasswordPrompt=1, SshOtherError=255 };
     int ConverseSsh(const char *password, int check);
 
 protected:
Index: kdelibs/kdesu/stub.cpp
===================================================================
--- kdelibs/kdesu/stub.cpp	(Revision 1063492)
+++ kdelibs/kdesu/stub.cpp	(Arbeitskopie)
@@ -105,95 +105,101 @@
 
 int StubProcess::ConverseStub(int check)
 {
-    QByteArray line, tmp;
-
+    // stub header
     while (1)
     {
-	line = readLine();
-	if (line.isNull())
-	    return -1;
+        QByteArray line = readLine();
+        if (line.isNull()) {
+            return StubProtocolError;
+        }
 
-	if (line == "kdesu_stub")
-	{
-	    // This makes parsing a lot easier.
-	    enableLocalEcho(false);
-	    if (check) writeLine("stop");
-	    else writeLine("ok");
-	    break;
-	} 
+        if (line == "kdesu_stub") {
+            // This makes parsing a lot easier.
+            enableLocalEcho(false);
+            writeLine(check ? "stop" : "ok");
+            break;
+        }
     }
 
+    // stub commands
+    StubResult stubResult;
+
     while (1)
     {
-	line = readLine();
-	if (line.isNull())
-	    return -1;
+        QByteArray line = readLine();
+        if (line.isNull()) {
+            stubResult = StubProtocolError;
+            break;
+        }
 
         if (line == "display") {
-	    writeLine(display());
-	} else if (line == "display_auth") {
+            writeLine(display());
+        } else if (line == "display_auth") {
 #ifdef Q_WS_X11
-	    writeLine(displayAuth());
+            writeLine(displayAuth());
 #else
-	    writeLine("");
+            writeLine(QByteArray());
 #endif
-	} else if (line == "command") {
-	    writeLine(m_Command);
-	} else if (line == "path") {
-	    QByteArray path = qgetenv("PATH");
-            if (!path.isEmpty() && path[0] == ':')
+        } else if (line == "command") {
+            writeLine(m_Command);
+        } else if (line == "path") {
+            QByteArray path = qgetenv("PATH");
+            if (!path.isEmpty() && path[0] == ':') {
                 path = path.mid(1);
-	    if (m_User == "root") {
-		if (!path.isEmpty())
-		    path = "/sbin:/bin:/usr/sbin:/usr/bin:" + path;
-		else
-		    path = "/sbin:/bin:/usr/sbin:/usr/bin";
             }
-	    writeLine(path);
-	} else if (line == "user") {
-	    writeLine(m_User);
-	} else if (line == "priority") {
-	    tmp.setNum(m_Priority);
-	    writeLine(tmp);
-	} else if (line == "scheduler") {
-	    if (m_Scheduler == SchedRealtime) writeLine("realtime");
-	    else writeLine("normal");
-	} else if (line == "xwindows_only") {
-	    if (m_bXOnly) writeLine("no");
-	    else writeLine("yes");
-	} else if (line == "app_startup_id") {
-	    QList<QByteArray> env = environment();
-	    QByteArray tmp;
-	    for(int i = 0; i < env.count(); ++i)
-	    {
-                const char startup_env[] = "DESKTOP_STARTUP_ID=";
-                if (env.at(i).startsWith(startup_env))
-                    tmp = env.at(i).mid(sizeof(startup_env) - 1);
-	    }
-	    if( tmp.isEmpty())
-		tmp = "0"; // krazy:exclude=doublequote_chars
-	    writeLine(tmp);
-	} else if (line == "app_start_pid") { // obsolete
-	    // Force the pid_t returned from getpid() into
-	    // something QByteArray understands; avoids ambiguity
-	    // between short and unsigned short in particular.
-	    tmp.setNum((PIDType<sizeof(pid_t)>::PID_t)(getpid()));
-	    writeLine(tmp);
-	} else if (line == "environment") { // additional env vars
-	    QList<QByteArray> env = environment();
-            for (int i = 0; i < env.count(); ++i)
-                writeLine(env.at(i));
-	    writeLine( "" );
-	} else if (line == "end") {
-	    return 0;
-	} else
-	{
-	    kWarning(kdesuDebugArea()) << k_lineinfo << "Unknown request:" << line;
-	    return 1;
-	}
+            if (m_User == "root") {
+                if (!path.isEmpty())
+                    path = "/sbin:/bin:/usr/sbin:/usr/bin:" + path;
+                else
+                    path = "/sbin:/bin:/usr/sbin:/usr/bin";
+            }
+            writeLine(path);
+        } else if (line == "user") {
+            writeLine(m_User);
+        } else if (line == "priority") {
+            writeLine(QByteArray::number(m_Priority));
+        } else if (line == "scheduler") {
+            writeLine((m_Scheduler==SchedRealtime) ? "realtime" : "normal");
+        } else if (line == "xwindows_only") {
+            writeLine(m_bXOnly ? "no" : "yes");
+        } else if (line == "app_startup_id") {
+            const QList<QByteArray> env = environment();
+            QByteArray appStartupId;
+            const char startup_env[] = "DESKTOP_STARTUP_ID=";
+            const int idOffset = sizeof(startup_env) - 1;
+            foreach(const QByteArray& envVar, env)
+            {
+                if (envVar.startsWith(startup_env)) {
+                    appStartupId = envVar.mid(idOffset);
+                    break;
+                }
+            }
+            if (appStartupId.isEmpty())
+                appStartupId = "0"; // krazy:exclude=doublequote_chars
+            writeLine(appStartupId);
+        } else if (line == "app_start_pid") { // obsolete
+            // Force the pid_t returned from getpid() into
+            // something QByteArray understands; avoids ambiguity
+            // between short and unsigned short in particular.
+            QByteArray startPid = QByteArray::number((PIDType<sizeof(pid_t)>::PID_t)( getpid() ));
+            writeLine(startPid);
+        } else if (line == "environment") { // additional env vars
+            const QList<QByteArray> env = environment();
+            foreach(const QByteArray& envVar, env) {
+                writeLine(envVar);
+            }
+            writeLine(QByteArray());
+        } else if (line == "end") {
+            stubResult = StubNoError;
+            break;
+        } else {
+            kWarning(kdesuDebugArea()) << k_lineinfo << "Unknown request:" << line;
+            stubResult = StubUnknownCommand;
+            break;
+        }
     }
 
-    return 0;
+    return stubResult;
 }
 
 
Index: kdelibs/kdesu/stub.h
===================================================================
--- kdelibs/kdesu/stub.h	(Revision 1063492)
+++ kdelibs/kdesu/stub.h	(Arbeitskopie)
@@ -19,7 +19,7 @@
 #include <kdesu/kdesu_export.h>
 
 namespace KDESu {
-    
+
 namespace KDESuPrivate { class KCookie; }
 
 
@@ -71,8 +71,16 @@
 protected:
 
     /**
-     * Exchange all parameters with kdesu_stub.
+     * .
      */
+    enum StubResult { StubProtocolError=-1, StubNoError=0, StubUnknownCommand=1, StubOtherError=255 };
+
+    /**
+     * Exchange all parameters with kdesu_stub, e.g. the authentication tokens (X11).
+     * @param check Flag to indicate if this is a normal execution (=Zero)
+     *  or just a check (other values than Zero).
+     * @return a value from StubResult
+     */
     int ConverseStub(int check);
 
     /**
Index: kdelibs/kdesu/CMakeLists.txt
===================================================================
--- kdelibs/kdesu/CMakeLists.txt	(Revision 1063492)
+++ kdelibs/kdesu/CMakeLists.txt	(Arbeitskopie)
@@ -37,9 +37,9 @@
 
 set(kdesu_stub_SRCS kdesu_stub.c )
 
-kde4_add_executable(kdesu_stub NOGUI ${kdesu_stub_SRCS})
+kde4_add_executable(kdesu_stub4 NOGUI ${kdesu_stub_SRCS})
 
-install(TARGETS kdesu_stub DESTINATION ${LIBEXEC_INSTALL_DIR} )
+install(TARGETS kdesu_stub4 ${INSTALL_TARGETS_DEFAULT_ARGS} )
 
 
 ########### install files ###############
Index: kdelibs/kdesu/ssh.cpp
===================================================================
--- kdelibs/kdesu/ssh.cpp	(Revision 1063492)
+++ kdelibs/kdesu/ssh.cpp	(Arbeitskopie)
@@ -45,7 +45,7 @@
 public:
     SshProcessPrivate(const QByteArray &host)
         : m_Host( host )
-        , m_Stub( "kdesu_stub" )
+        , m_Stub( "kdesu_stub4" )
     {}
     QByteArray m_Prompt;
     QByteArray m_Host;
@@ -82,74 +82,74 @@
 
 int SshProcess::checkInstall(const char *password)
 {
-    return exec(password, 1);
+    return exec(password, PasswordCorrectCheck);
 }
 
 
 int SshProcess::checkNeedPassword()
 {
-    return exec(0L, 2);
+    return exec((const char*)0, PasswordNeededCheck);
 }
 
 
 int SshProcess::exec(const char *password, int check)
 {
-    if (check)
-    setTerminal(true);
+    if (check != NormalExec)
+        setTerminal(true);
 
     QList<QByteArray> args;
     args += "-l"; args += m_User;
     args += "-o"; args += "StrictHostKeyChecking=no";
     args += d->m_Host; args += d->m_Stub;
 
-    if (StubProcess::exec("ssh", args) < 0)
-    {
-        return check ? SshNotFound : -1;
+    if (StubProcess::exec("ssh", args) < 0) {
+        return (check != NormalExec) ? (int)SshNotFound : (int)GeneralError;
     }
 
-    int ret = ConverseSsh(password, check);
-    if (ret < 0)
-    {
-        if (!check)
+    const int sshResult = ConverseSsh(password, check);
+kDebug()<<"ssh executing..."<<sshResult;
+    if (sshResult == SshProtocolError) {
+        if (check == NormalExec)
             kError(kdesuDebugArea()) << k_lineinfo << "Conversation with ssh failed.";
-        return ret;
+        return GeneralError;
     }
-    if (check == 2)
-    {
-        if (ret == 1)
-        {
-            kill(m_Pid, SIGTERM);
-            waitForChild();
-        }
-        return ret;
+    if (check == PasswordNeededCheck) {
+        kill(m_Pid, SIGTERM);
+        waitForChild();
+
+        return (sshResult == StoppedAtPasswordPrompt) ? SshNeedsPassword : SshNeedsNoPassword;
     }
 
-    if (m_bErase && password)
+    if (m_bErase && password) {
         memset(const_cast<char *>(password), 0, qstrlen(password));
+    }
 
-    ret = ConverseStub(check);
-    if (ret < 0)
-    {
-        if (!check)
+    const int stubResult = ConverseStub(check);
+kDebug()<<"stub conversing..."<<stubResult;
+    if (stubResult == StubProtocolError) {
+        if (check == NormalExec)
             kError(kdesuDebugArea()) << k_lineinfo << "Conversation with kdesu_stub failed.";
-        return ret;
+        return GeneralError;
     }
-    else if (ret == 1)
-    {
+    // TODO: unknown command is not a good way to check for incorrect password,
+    // could also be a broken kdesu_stub
+    // exit code of ssh (255) would be a better way
+    else if (stubResult == StubUnknownCommand) {
         kill(m_Pid, SIGTERM);
         waitForChild();
-        ret = SshIncorrectPassword;
+        return SshIncorrectPassword;
     }
 
-    if (check == 1)
-    {
+    if (check == PasswordCorrectCheck) {
         waitForChild();
-        return 0;
+        return NoError;
     }
 
     setExitString("Waiting for forwarded connections to terminate");
-    ret = waitForChild();
-    return ret;
+    // TODO: results of waitForChild are not defined
+    int result = waitForChild();
+
+    return result;
 }
 
 QByteArray SshProcess::prompt() const
@@ -178,68 +178,68 @@
 
 int SshProcess::ConverseSsh(const char *password, int check)
 {
-    unsigned i, j, colon;
+    int result;
 
-    QByteArray line;
-    int state = 0;
+    enum ConverseState { AwaitingPasswordPrompt, PasswordGiven };
+    ConverseState state = AwaitingPasswordPrompt;
 
-    while (state < 2)
+    while (true)
     {
-        line = readLine();
-        const uint len = line.length();
-        if (line.isNull())
-            return -1;
+        const QByteArray line = readLine();
+kDebug()<<line;
+        if (line.isNull()) {
+            result = SshProtocolError;
+            break;
+        }
 
-        switch (state) {
-        case 0:
+        if (state== AwaitingPasswordPrompt) {
             // Check for "kdesu_stub" header.
             if (line == "kdesu_stub")
             {
                 unreadLine(line);
-                return 0;
+                result = NoError;
+                break;
             }
 
             // Match "Password: " with the regex ^[^:]+:[\w]*$.
-            for (i=0,j=0,colon=0; i<len; i++)
-            {
-                if (line[i] == ':')
-                {
-                    j = i; colon++;
+            uint j = 0;
+            uint colon = 0;
+            const uint len = line.length();
+            for (unsigned int i=0; i<len; i++) {
+                if (line[i] == ':') {
+                    j = i;
+                    ++colon;
                     continue;
                 }
-                if (!isspace(line[i]))
-                    j++;
+                if (!isspace(line[i])) {
+                    ++j;
+                }
             }
-            if ((colon == 1) && (line[j] == ':'))
-            {
-                if (check == 2)
-                {
+            if ((colon == 1) && (line[j] == ':')) {
+                if (check == PasswordNeededCheck) {
                     d->m_Prompt = line;
-                    return SshNeedsPassword;
+                    result = StoppedAtPasswordPrompt;
+                    break;
                 }
                 WaitSlave();
                 write(fd(), password, strlen(password));
                 write(fd(), "\n", 1);
-                state++;
-                break;
+                state = PasswordGiven;
+                continue;
             }
 
             // Warning/error message.
             d->m_Error += line; d->m_Error += '\n';
-            if (m_bTerminal)
+            if (m_bTerminal) {
                 fprintf(stderr, "ssh: %s\n", line.constData());
+            }
+        } else if (state == PasswordGiven) {
+            result = line.isEmpty() ? SshNoError : SshProtocolError;
             break;
-
-        case 1:
-            if (line.isEmpty())
-            {
-                state++;
-                break;
-            }
-            return -1;
         }
     }
-    return 0;
+
+    return result;
 }
 
 
