some more win32'fication to fix non-ascii filename handling
[kdelibs.git] / kdesu / ssh.cpp
blobfb2ce4d637185e398785e0b9269ad2072c13fe33
1 /* vi: ts=8 sts=4 sw=4
3 * This file is part of the KDE project, module kdesu.
4 * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
6 * This is free software; you can use this library under the GNU Library
7 * General Public License, version 2. See the file "COPYING.LIB" for the
8 * exact licensing terms.
10 * ssh.cpp: Execute a program on a remote machine using ssh.
13 #include "ssh.h"
14 #include "kcookie.h"
16 #include <config.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
31 #include <QtCore/QBool>
33 #include <kdebug.h>
34 #include <klocale.h>
35 #include <kstandarddirs.h>
37 namespace KDESu {
39 using namespace KDESuPrivate;
41 class SshProcess::SshProcessPrivate
43 public:
44 SshProcessPrivate(const QByteArray &host)
45 : m_Host( host )
46 , m_Stub( "kdesu_stub" )
48 QByteArray m_Prompt;
49 QByteArray m_Host;
50 QByteArray m_Error;
51 QByteArray m_Stub;
55 SshProcess::SshProcess(const QByteArray &host, const QByteArray &user, const QByteArray &command)
56 : d( new SshProcessPrivate(host) )
58 m_User = user;
59 m_Command = command;
60 srand(time(0L));
64 SshProcess::~SshProcess()
66 delete d;
69 void SshProcess::setHost(const QByteArray &host)
71 d->m_Host = host;
75 void SshProcess::setStub(const QByteArray &stub)
77 d->m_Stub = stub;
81 int SshProcess::checkInstall(const char *password)
83 return exec(password, 1);
87 int SshProcess::checkNeedPassword()
89 return exec(0L, 2);
93 int SshProcess::exec(const char *password, int check)
95 if (check)
96 setTerminal(true);
98 QList<QByteArray> args;
99 args += "-l"; args += m_User;
100 args += "-o"; args += "StrictHostKeyChecking=no";
101 args += d->m_Host; args += d->m_Stub;
103 if (StubProcess::exec("ssh", args) < 0)
105 return check ? SshNotFound : -1;
108 int ret = ConverseSsh(password, check);
109 if (ret < 0)
111 if (!check)
112 kError(900) << k_lineinfo << "Conversation with ssh failed\n";
113 return ret;
115 if (check == 2)
117 if (ret == 1)
119 kill(m_Pid, SIGTERM);
120 waitForChild();
122 return ret;
125 if (m_bErase && password)
126 memset(const_cast<char *>(password), 0, qstrlen(password));
128 ret = ConverseStub(check);
129 if (ret < 0)
131 if (!check)
132 kError(900) << k_lineinfo << "Conversation with kdesu_stub failed\n";
133 return ret;
135 else if (ret == 1)
137 kill(m_Pid, SIGTERM);
138 waitForChild();
139 ret = SshIncorrectPassword;
142 if (check == 1)
144 waitForChild();
145 return 0;
148 setExitString("Waiting for forwarded connections to terminate");
149 ret = waitForChild();
150 return ret;
153 QByteArray SshProcess::prompt() const
155 return d->m_Prompt;
158 QByteArray SshProcess::error() const
160 return d->m_Error;
165 * Conversation with ssh.
166 * If check is 0, this waits for either a "Password: " prompt,
167 * or the header of the stub. If a prompt is received, the password is
168 * written back. Used for running a command.
169 * If check is 1, operation is the same as 0 except that if a stub header is
170 * received, the stub is stopped with the "stop" command. This is used for
171 * checking a password.
172 * If check is 2, operation is the same as 1, except that no password is
173 * written. The prompt is saved to m_Prompt. Used for checking the need for
174 * a password.
177 int SshProcess::ConverseSsh(const char *password, int check)
179 unsigned i, j, colon;
181 QByteArray line;
182 int state = 0;
184 while (state < 2)
186 line = readLine();
187 const uint len = line.length();
188 if (line.isNull())
189 return -1;
191 switch (state) {
192 case 0:
193 // Check for "kdesu_stub" header.
194 if (line == "kdesu_stub")
196 unreadLine(line);
197 return 0;
200 // Match "Password: " with the regex ^[^:]+:[\w]*$.
201 for (i=0,j=0,colon=0; i<len; i++)
203 if (line[i] == ':')
205 j = i; colon++;
206 continue;
208 if (!isspace(line[i]))
209 j++;
211 if ((colon == 1) && (line[j] == ':'))
213 if (check == 2)
215 d->m_Prompt = line;
216 return SshNeedsPassword;
218 WaitSlave();
219 write(fd(), password, strlen(password));
220 write(fd(), "\n", 1);
221 state++;
222 break;
225 // Warning/error message.
226 d->m_Error += line; d->m_Error += '\n';
227 if (m_bTerminal)
228 fprintf(stderr, "ssh: %s\n", line.constData());
229 break;
231 case 1:
232 if (line.isEmpty())
234 state++;
235 break;
237 return -1;
240 return 0;
244 // Display redirection is handled by ssh natively.
245 QByteArray SshProcess::display()
247 return "no";
251 QByteArray SshProcess::displayAuth()
253 return "no";
256 void SshProcess::virtual_hook( int id, void* data )
257 { StubProcess::virtual_hook( id, data ); }