Replaced old sftp ioslave with backported version
Source: https://github.com/sandsmark/kde2-kio-sftp-kde4 Licence: GPLv2 or later This resolves issue #276. Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>pull/279/head
parent
d4e06b7696
commit
fd94618b63
@ -1,3 +0,0 @@
|
|||||||
Dawit Alemayehu <adawit@kde.org>
|
|
||||||
Lucas Fisher <ljfisher@iastate.edu>
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
|||||||
- add dialog to ask for username
|
|
||||||
- rename() causes SSH to die
|
|
||||||
- How to handle overwrite?
|
|
||||||
- After the user cancels with the stop button, we get ERR_CANNOT_LAUNCH_PROCESS
|
|
||||||
errors, until we kill the ioslave. Same thing after trying the wrong passwd
|
|
||||||
too many times.
|
|
||||||
This is happening because TDEProcess thinks that the ssh process is still running
|
|
||||||
even though it exited.
|
|
||||||
- How to handle password and caching?
|
|
||||||
- Write our own askpass program using kde
|
|
||||||
- set env SSH_ASKPASS_PROGRAM before launching
|
|
||||||
-how to do this? TDEProcess doesn't give us access to env variables.
|
|
||||||
- Our askpass program can probably talk to the tdesu daemon to implement caching.
|
|
||||||
- chmod() succeeds, but konqueror always puts permissions to 0 afterwards. The properties
|
|
||||||
dialog is right though.
|
|
||||||
Nevermind - ftp ioslave does this too! Maybe a bug with konqueror.
|
|
||||||
- stat does not give us group and owner names, only numbers. We could cache the uid/name and
|
|
||||||
gid/name so we can give names when doing a stat also.
|
|
||||||
|
|
||||||
7-13-2001 - ReadLink stopped working. sftp server always retuns a file not found error
|
|
||||||
- Need to implement 64 bit file lengths-->write DataStream << for u_int64
|
|
||||||
Still need to offer 32 bit size since this is what kde wants. ljf
|
|
||||||
- rename() isn't exactly causing ioslave to die. The stat of the file we are
|
|
||||||
going to rename is killing the slave. The slave dies in the statEntry() call.
|
|
||||||
I don't know what I am putting in the UDS entry that is causing this. ljf
|
|
||||||
7-14-2001 - got put, mimetype working ljf
|
|
||||||
- fixed readlink problem - I was sending the wrong path. doh! ljf
|
|
||||||
7-17-2001 - If the user changes the host, the slave doesn't change host! setHost() is not
|
|
||||||
called, nor is another ioslave spawned. I have not investigated the problem
|
|
||||||
yet. ljf
|
|
||||||
7-21-2001 - got slave working with kde 2.2 cvs
|
|
||||||
7-22-2001 - probable solution to getting password prompt -- open with controlling
|
|
||||||
but don't connect stdin/out to terminal. duh!
|
|
||||||
8-9-2001 - Doh! I haven't kept very good logs. Look at the cvs logs for better info.
|
|
||||||
- At this point tdeio_sftp is using KSshProcess which I wrote in order to make
|
|
||||||
a standard interface to the various version of ssh out there. So far it is
|
|
||||||
working fairly well. We also now report host key changes to the user and
|
|
||||||
allow them to choose whether or not to continue. This is a big improvement.
|
|
||||||
- Todo: support use of keys and ssh agent
|
|
||||||
put()'s resume functionality needs some work
|
|
||||||
1-26-2002 - Rewrote put() following the ftp::put() so it should behave the same way
|
|
||||||
- increase the size of the data packet we ask for in ::get up to 60k.
|
|
||||||
Through-put increases nicely.
|
|
||||||
- Call closeConnection() from construction. Keeps from having unused ssh
|
|
||||||
processes laying around after failed operations.
|
|
||||||
2-19-2002 - get() now emits mimetype, fixes problem with konqi not downloading file for
|
|
||||||
viewing in kpart.
|
|
||||||
- get port number using getservbyname instead of hard coding it.
|
|
||||||
2-27-2002 - testing before committing back to cvs, test with openssh 3, ssh 3
|
|
||||||
6-?-2002 - rewrote openConnection() to using new KSshProcess connect proceedures
|
|
||||||
7-20-2002 - Don't put up a message box when auth fails because of now or changed key,
|
|
||||||
the call to error() will put up the dialog.
|
|
||||||
- Connect fails and no more password are prompted for when we get
|
|
||||||
ERR_AUTH_FAILED from KSshProcess.
|
|
||||||
9-15-2002 - stuff
|
|
||||||
9-29-2002 - the last i18n string updates, fixed problem with uploading files to
|
|
||||||
openssh server.
|
|
||||||
5-8-2003 - check whether operation types are supported by the negotiated sftp
|
|
||||||
protocol version
|
|
@ -1,3 +0,0 @@
|
|||||||
##### create translation templates ##############
|
|
||||||
|
|
||||||
tde_l10n_create_template( "tdeio_sftp" )
|
|
@ -1,12 +0,0 @@
|
|||||||
DEBUGGING
|
|
||||||
|
|
||||||
The best way to debug this slave is to send debug info to a
|
|
||||||
file using 'tdedebugDialog --fullmode'. Then you can 'tail -f' the file to
|
|
||||||
see debug messages in real-time.
|
|
||||||
|
|
||||||
I also suggest getting the openssh source and recompiling sftp-server to
|
|
||||||
send messages to the auth log. This can be done in sftp-server.c be defining
|
|
||||||
DEBUG_SFTP_SERVER.
|
|
||||||
|
|
||||||
You can do the same with the ssh client by finding the two calls to log_init()
|
|
||||||
in ssh.c and changing the last argument from 1 to 0 and recompiling.
|
|
@ -1,25 +0,0 @@
|
|||||||
## Makefile.am of tdebase/tdeioslave/sftp
|
|
||||||
|
|
||||||
INCLUDES = $(all_includes)
|
|
||||||
AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
|
|
||||||
METASOURCES = AUTO
|
|
||||||
|
|
||||||
####### Files
|
|
||||||
|
|
||||||
check_PROGRAMS = ksshprocesstest
|
|
||||||
|
|
||||||
ksshprocesstest_SOURCES = ksshprocesstest.cpp
|
|
||||||
ksshprocesstest_LDADD = $(LIB_TDESYCOCA) ksshprocess.lo process.lo atomicio.lo
|
|
||||||
|
|
||||||
kde_module_LTLIBRARIES = tdeio_sftp.la
|
|
||||||
|
|
||||||
tdeio_sftp_la_SOURCES = process.cpp atomicio.cpp tdeio_sftp.cpp sftpfileattr.cpp ksshprocess.cpp
|
|
||||||
tdeio_sftp_la_LIBADD = $(LIB_TDEIO)
|
|
||||||
tdeio_sftp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
|
|
||||||
noinst_HEADERS = atomicio.h tdeio_sftp.h ksshprocess.h process.h sftpfileattr.h sftp.h
|
|
||||||
|
|
||||||
kdelnk_DATA = sftp.protocol
|
|
||||||
kdelnkdir = $(kde_servicesdir)
|
|
||||||
|
|
||||||
messages:
|
|
||||||
$(XGETTEXT) *.cpp -o $(podir)/tdeio_sftp.pot
|
|
@ -1,5 +0,0 @@
|
|||||||
TODO:
|
|
||||||
=====
|
|
||||||
|
|
||||||
- Support for use of public keys, maybe ssh-agent, a key management app, etc.
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#include "includes.h"
|
|
||||||
//RCSID("$OpenBSD: atomicio.c,v 1.9 2001/03/02 18:54:30 deraadt Exp $");
|
|
||||||
|
|
||||||
//#include "xmalloc.h"
|
|
||||||
#include "atomicio.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <kdebug.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ensure all of data on socket comes through. f==read || f==write
|
|
||||||
*/
|
|
||||||
|
|
||||||
ssize_t atomicio(int fd, char *_s, size_t n, bool read)
|
|
||||||
{
|
|
||||||
char *s = _s;
|
|
||||||
ssize_t res;
|
|
||||||
ssize_t pos = 0;
|
|
||||||
|
|
||||||
while (n > pos) {
|
|
||||||
if( read)
|
|
||||||
res = ::read(fd, s + pos, n - pos);
|
|
||||||
else
|
|
||||||
res = ::write(fd, s + pos, n - pos);
|
|
||||||
|
|
||||||
switch (res) {
|
|
||||||
case -1:
|
|
||||||
kdDebug() << "atomicio(): errno=" << errno << endl;
|
|
||||||
#ifdef EWOULDBLOCK
|
|
||||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
|
||||||
#else
|
|
||||||
if (errno == EINTR || errno == EAGAIN)
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
case 0:
|
|
||||||
return (res);
|
|
||||||
default:
|
|
||||||
pos += res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (pos);
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
#ifndef atomicio_h
|
|
||||||
#define atomicio_h
|
|
||||||
|
|
||||||
/* $OpenBSD: atomicio.h,v 1.3 2001/03/02 18:54:30 deraadt Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure all of data on socket comes through. f==read || f==write
|
|
||||||
*/
|
|
||||||
ssize_t atomicio(int fd, char *_s, size_t n, bool read = true);
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,623 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
ksshprocess.h - description
|
|
||||||
-------------------
|
|
||||||
begin : Tue Jul 31 2001
|
|
||||||
copyright : (C) 2001 by Lucas Fisher
|
|
||||||
email : ljfisher@purdue.edu
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef KSSHPROCESS_H
|
|
||||||
#define KSSHPROCESS_H
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <tqvaluelist.h>
|
|
||||||
|
|
||||||
#include <kdebug.h>
|
|
||||||
|
|
||||||
#include "process.h"
|
|
||||||
|
|
||||||
#define KSSHPROC 7120
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides version independent access to ssh. Currently supported
|
|
||||||
* versions of SSH are:
|
|
||||||
* OpenSSH 2.9p1
|
|
||||||
* OpenSSH 2.9p2
|
|
||||||
* OpenSSH 3.0
|
|
||||||
* OpenSSH 3.1
|
|
||||||
* Commercial SSH 3.0.0
|
|
||||||
* Other versions of OpenSSH and commerical SSH will probably work also.
|
|
||||||
*
|
|
||||||
* To setup a SSH connection first create a list of options to use and tell
|
|
||||||
* KSshProcess about your options. Then start the ssh connection. Once the
|
|
||||||
* connection is setup use the stdin, stdout, stderr, and pty file descriptors
|
|
||||||
* to communicate with ssh. For a detailed example of how to use, see
|
|
||||||
* ksshprocesstest.cpp.
|
|
||||||
*
|
|
||||||
* @author Lucas Fisher
|
|
||||||
*
|
|
||||||
* Example: Connect to ssh server on localhost
|
|
||||||
* KSshProcess::SshOpt opt;
|
|
||||||
* KSshProcess::SshOptList options;
|
|
||||||
*
|
|
||||||
* opt.opt = KSshProcess::SSH_HOST;
|
|
||||||
* opt.str = "localhost";
|
|
||||||
* options.append(opt);
|
|
||||||
*
|
|
||||||
* opt.opt = KSshProcess::SSH_USERNAME;
|
|
||||||
* opt.str = "me";
|
|
||||||
* options.append(opt);
|
|
||||||
*
|
|
||||||
* KSshProcess ssh;
|
|
||||||
* if( !ssh.setOptions(options) ) {
|
|
||||||
* int err = ssh.error();
|
|
||||||
* // process error
|
|
||||||
* return false;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* int err;
|
|
||||||
* TQString errMsg;
|
|
||||||
* while( !ssh.connect() ) {
|
|
||||||
* err = ssh.error(errMsg);
|
|
||||||
*
|
|
||||||
* switch( err ) {
|
|
||||||
* case KSshProcess::ERR_NEW_HOST_KEY:
|
|
||||||
* case KSshProcess::ERR_DIFF_HOST_KEY:
|
|
||||||
* // ask user to accept key
|
|
||||||
* if( acceptHostKey ) {
|
|
||||||
* ssh.acceptKey(true);
|
|
||||||
* }
|
|
||||||
* break;
|
|
||||||
*
|
|
||||||
* case KSshProcess::ERR_NEED_PASSWORD:
|
|
||||||
* // ask user for password
|
|
||||||
* ssh.password(userPassword);
|
|
||||||
* break;
|
|
||||||
*
|
|
||||||
* case KSshProcess::ERR_NEED_KEY_PASSPHRASE:
|
|
||||||
* // ask user for their key passphrase
|
|
||||||
* ssh.keyPassphrase(keyPassphrase);
|
|
||||||
* break;
|
|
||||||
*
|
|
||||||
* default:
|
|
||||||
* // somethings wrong, alert user
|
|
||||||
* return;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* // We have an open ssh connection to localhost
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
class KSshProcess {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* SSH Option
|
|
||||||
*
|
|
||||||
* Stores SSH options for use with KSshProcess.
|
|
||||||
*
|
|
||||||
* SSH options are configured much like UDS entries.
|
|
||||||
* Each option is assigned a constant and a string, bool,
|
|
||||||
* or number is assigned based on the option.
|
|
||||||
*
|
|
||||||
* @author Lucas Fisher (ljfisher@iastate.edu)
|
|
||||||
*/
|
|
||||||
class SshOpt {
|
|
||||||
public:
|
|
||||||
TQ_UINT32 opt;
|
|
||||||
TQString str;
|
|
||||||
TQ_INT32 num;
|
|
||||||
bool boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of SshOptions and associated iterators
|
|
||||||
*/
|
|
||||||
typedef TQValueList<SshOpt> SshOptList;
|
|
||||||
typedef TQValueListIterator<SshOpt> SshOptListIterator;
|
|
||||||
typedef TQValueListConstIterator<SshOpt> SshOptListConstIterator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ssh versions supported by KSshProcess. Subject to change
|
|
||||||
* at any time.
|
|
||||||
*/
|
|
||||||
enum SshVersion {
|
|
||||||
OPENSSH_3_6,
|
|
||||||
OPENSSH,
|
|
||||||
SSH,
|
|
||||||
SSH_VER_MAX,
|
|
||||||
UNKNOWN_VER
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSH options supported by KSshProcess. Set SshOpt::opt to one of these
|
|
||||||
* values.
|
|
||||||
*/
|
|
||||||
// we cannot do this like UDSAtomType (ORing the type with the name) because
|
|
||||||
// we have too many options for ssh and not enough bits.
|
|
||||||
enum SshOptType {
|
|
||||||
/**
|
|
||||||
* Request server to invoke subsystem. (str)
|
|
||||||
*/
|
|
||||||
SSH_SUBSYSTEM,
|
|
||||||
/**
|
|
||||||
* Connect to port on the server. (num)
|
|
||||||
*/
|
|
||||||
SSH_PORT,
|
|
||||||
/**
|
|
||||||
* Connect to host. (str)
|
|
||||||
*/
|
|
||||||
SSH_HOST,
|
|
||||||
/**
|
|
||||||
* connect using this username. (str)
|
|
||||||
*/
|
|
||||||
SSH_USERNAME,
|
|
||||||
/**
|
|
||||||
* connect using this password. (str)
|
|
||||||
*/
|
|
||||||
SSH_PASSWD,
|
|
||||||
/**
|
|
||||||
* connect using this version of the SSH protocol. num == 1 or 2
|
|
||||||
*/
|
|
||||||
SSH_PROTOCOL,
|
|
||||||
/**
|
|
||||||
* whether to forward X11 connections. (boolean)
|
|
||||||
*/
|
|
||||||
SSH_FORWARDX11,
|
|
||||||
/**
|
|
||||||
* whether to do agent forwarding. (boolean)
|
|
||||||
*/
|
|
||||||
SSH_FORWARDAGENT,
|
|
||||||
/**
|
|
||||||
* use as escape character. 0 for none (num)
|
|
||||||
*/
|
|
||||||
SSH_ESCAPE_CHAR,
|
|
||||||
/**
|
|
||||||
* command for ssh to perform once it is connected (str)
|
|
||||||
*/
|
|
||||||
SSH_COMMAND,
|
|
||||||
/**
|
|
||||||
* Set ssh verbosity. This may be added multiple times. It may also cause KSSHProcess
|
|
||||||
* to fail since we don't understand all the debug messages.
|
|
||||||
*/
|
|
||||||
SSH_VERBOSE,
|
|
||||||
/**
|
|
||||||
* Set a ssh option as one would find in the ssh_config file
|
|
||||||
* The str member should be set to 'optName value'
|
|
||||||
*/
|
|
||||||
SSH_OPTION,
|
|
||||||
/**
|
|
||||||
* Set some other option not supported by KSSHProcess. The option should
|
|
||||||
* be specified in the str member of SshOpt. Careful with this since
|
|
||||||
* not all versions of SSH support the same options.
|
|
||||||
*/
|
|
||||||
SSH_OTHER,
|
|
||||||
SSH_OPT_MAX // always last
|
|
||||||
}; // that's all for now
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Errors that KSshProcess can encounter. When a member function returns
|
|
||||||
* false, call error() to retrieve one of these error codes.
|
|
||||||
*/
|
|
||||||
enum SshError {
|
|
||||||
/**
|
|
||||||
* Don't recognize the ssh version
|
|
||||||
*/
|
|
||||||
ERR_UNKNOWN_VERSION,
|
|
||||||
/**
|
|
||||||
* Cannot lauch ssh client
|
|
||||||
*/
|
|
||||||
ERR_CANNOT_LAUNCH,
|
|
||||||
/**
|
|
||||||
* Interaction with the ssh client failed. This happens when we can't
|
|
||||||
* find the password prompt or something similar
|
|
||||||
*/
|
|
||||||
ERR_INTERACT,
|
|
||||||
/**
|
|
||||||
* Arguments for both a remotely executed subsystem and command were provide.
|
|
||||||
* Only one or the other may be used
|
|
||||||
*/
|
|
||||||
ERR_CMD_SUBSYS_CONFLICT,
|
|
||||||
/**
|
|
||||||
* No password was supplied
|
|
||||||
*/
|
|
||||||
ERR_NEED_PASSWD,
|
|
||||||
/**
|
|
||||||
* No passphrase was supplied.
|
|
||||||
*/
|
|
||||||
ERR_NEED_PASSPHRASE,
|
|
||||||
/**
|
|
||||||
* No usename was supplied
|
|
||||||
*/
|
|
||||||
ERR_NEED_USERNAME,
|
|
||||||
/**
|
|
||||||
* Timed out waiting for a response from ssh or the server
|
|
||||||
*/
|
|
||||||
ERR_TIMED_OUT,
|
|
||||||
/**
|
|
||||||
* Internal error, probably from a system call
|
|
||||||
*/
|
|
||||||
ERR_INTERNAL,
|
|
||||||
/**
|
|
||||||
* ssh was disconnect from the host
|
|
||||||
*/
|
|
||||||
ERR_DISCONNECTED,
|
|
||||||
/**
|
|
||||||
* No ssh options have been set. Call setArgs() before calling connect.
|
|
||||||
*/
|
|
||||||
ERR_NO_OPTIONS,
|
|
||||||
/**
|
|
||||||
* A host key was received from an unknown host.
|
|
||||||
* Call connect() with the acceptHostKey argument to accept the key.
|
|
||||||
*/
|
|
||||||
ERR_NEW_HOST_KEY,
|
|
||||||
/**
|
|
||||||
* A host key different from what is stored in the user's known_hosts file
|
|
||||||
* has be received. This is an indication of an attack
|
|
||||||
*/
|
|
||||||
ERR_DIFF_HOST_KEY,
|
|
||||||
/**
|
|
||||||
* A new or different host key was rejected by the caller. The ssh
|
|
||||||
* connection was terminated and the ssh process killed.
|
|
||||||
*/
|
|
||||||
ERR_HOST_KEY_REJECTED,
|
|
||||||
/**
|
|
||||||
* An invalid option was found in the SSH option list
|
|
||||||
*/
|
|
||||||
ERR_INVALID_OPT,
|
|
||||||
/**
|
|
||||||
* SSH accepted host key without prompting user.
|
|
||||||
*/
|
|
||||||
ERR_ACCEPTED_KEY,
|
|
||||||
/**
|
|
||||||
* Authentication failed
|
|
||||||
*/
|
|
||||||
ERR_AUTH_FAILED,
|
|
||||||
/**
|
|
||||||
* Authentication failed because a new host key was detected and
|
|
||||||
* SSH is configured with strict host key checking enabled.
|
|
||||||
*/
|
|
||||||
ERR_AUTH_FAILED_NEW_KEY,
|
|
||||||
/**
|
|
||||||
* Authentication failed because a changed host key was detected and
|
|
||||||
* SSH is configured with strict host key checking enabled.
|
|
||||||
*/
|
|
||||||
ERR_AUTH_FAILED_DIFF_KEY,
|
|
||||||
/**
|
|
||||||
* The remote host closed the connection for unknown reasons.
|
|
||||||
*/
|
|
||||||
ERR_CLOSED_BY_REMOTE_HOST,
|
|
||||||
/**
|
|
||||||
* We have no idea what happened
|
|
||||||
*/
|
|
||||||
ERR_UNKNOWN,
|
|
||||||
/**
|
|
||||||
* The connect state machine entered an invalid state.
|
|
||||||
*/
|
|
||||||
ERR_INVALID_STATE,
|
|
||||||
ERR_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a SSH process using the first SSH binary found in the PATH
|
|
||||||
*/
|
|
||||||
KSshProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a SSH process using the specified SSH binary.
|
|
||||||
* @param pathToSsh The fully qualified path name of the ssh binary
|
|
||||||
* KSshProcess should use to setup a SSH connection.
|
|
||||||
*/
|
|
||||||
KSshProcess(TQString pathToSsh);
|
|
||||||
~KSshProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the ssh binary KSshProcess should use. This will only affect the
|
|
||||||
* next ssh connection attempt using this instance.
|
|
||||||
*
|
|
||||||
* @param pathToSsh Full path to the ssh binary.
|
|
||||||
*
|
|
||||||
* @return True if the ssh binary is found and KSshProcess
|
|
||||||
* recognizes the version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool setSshPath(TQString pathToSsh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the ssh version.
|
|
||||||
*
|
|
||||||
* @return The ssh version or -1 if KSshProcess does not recognize
|
|
||||||
* the ssh version. The returned value corresponds to the
|
|
||||||
* member of the SshVersion enum.
|
|
||||||
*/
|
|
||||||
SshVersion version();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a string describing the ssh version
|
|
||||||
*
|
|
||||||
* @return A string describing the ssh version recognized by KSshProcess
|
|
||||||
*/
|
|
||||||
//TQString versionStr();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the last error encountered by KSshProcess.
|
|
||||||
*
|
|
||||||
* @param msg Set to the error message, if any, outputted by ssh when it is run.
|
|
||||||
*
|
|
||||||
* @return The error number. See SshError for descriptions.
|
|
||||||
*/
|
|
||||||
int error(TQString& msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the last error encountered by KSshProcess.
|
|
||||||
* @return The error number. See SshError for descriptions.
|
|
||||||
*/
|
|
||||||
int error() { return mError; }
|
|
||||||
|
|
||||||
TQString errorMsg() { return mErrorMsg; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a signal to the ssh process. Do not use this to end the
|
|
||||||
* ssh connection as it will not correctly reset the internal
|
|
||||||
* state of the KSshProcess object. Use KSshProcess::disconnect()
|
|
||||||
* instead.
|
|
||||||
*
|
|
||||||
* @param signal The signal to send to the ssh process. See 'kill -l'
|
|
||||||
* for a list of possible signals.
|
|
||||||
* The default signal is SIGKILL which kills ssh.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void kill(int signal = SIGKILL);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pid of the ssh process started by this instance of KSshProcess.
|
|
||||||
* Only valid if KSshProcess::running() returns true;
|
|
||||||
*
|
|
||||||
* @return The pid of the running ssh process.
|
|
||||||
*/
|
|
||||||
int pid() { return ssh.pid(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether a ssh connection has been established with a
|
|
||||||
* remote host. A establish connection means ssh has successfully
|
|
||||||
* authenticated with the remote host and user data can be transfered
|
|
||||||
* between the local and remote host. This cannot return
|
|
||||||
* true unless the most recent call to KSshProccess::connect() returned true.
|
|
||||||
*
|
|
||||||
* @return True if a ssh connection has been established with a remote
|
|
||||||
* host. False otherwise.
|
|
||||||
*/
|
|
||||||
bool connected() { return mConnected; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether a ssh process is currently running. This only indicates
|
|
||||||
* if a ssh process has been started and is still running. It does not
|
|
||||||
* tell if authentication has been successful. This may return true
|
|
||||||
* even if the most recent call to KSshProcess::connect() returned false.
|
|
||||||
*
|
|
||||||
* @return True if a ssh process started by this instance of KSshProcess
|
|
||||||
* is running. False otherwise.
|
|
||||||
*/
|
|
||||||
bool running() { return mRunning; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the command line arguments ssh is run with using kdDebug.
|
|
||||||
*/
|
|
||||||
void printArgs();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the SSH options.
|
|
||||||
* This must be called before connect(). See SshOptType for a list of
|
|
||||||
* supported ssh options. The required options are SSH_USERNAME
|
|
||||||
* and SSH_HOST.
|
|
||||||
*
|
|
||||||
* To reset the saved options, just recall setOptions() again with
|
|
||||||
* a different options list.
|
|
||||||
*
|
|
||||||
* @param opts A list of SshOpt objects specifying the ssh options.
|
|
||||||
*
|
|
||||||
* @return True if all options are valid. False if unrecognized options
|
|
||||||
* or a required option is missing. Call error()
|
|
||||||
* for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool setOptions(const SshOptList& opts);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a ssh connection based on the options provided by setOptions().
|
|
||||||
* Sets one of the following error codes on failure:
|
|
||||||
* <ul>
|
|
||||||
* <li>ERR_NO_OPTIONS</li>
|
|
||||||
* <li>ERR_CANNOT_LAUNCH</li>
|
|
||||||
* <li>ERR_INVALID_STATE</li>
|
|
||||||
* <li>ERR_NEED_PASSWD</li>
|
|
||||||
* <li>ERR_AUTH_FAILED</li>
|
|
||||||
* <li>ERR_NEW_HOST_KEY</li>
|
|
||||||
* <li>ERR_KEY_ACCEPTED</li>
|
|
||||||
* <li>ERR_DIFF_HOST_KEY</li>
|
|
||||||
* <li>ERR_INTERNAL</li>
|
|
||||||
* <li>ERR_INTERACT</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param acceptHostKey When true KSshProcess will automatically accept
|
|
||||||
* unrecognized or changed host keys.
|
|
||||||
*
|
|
||||||
* @return True if the ssh connection is successful. False if the connection
|
|
||||||
* fails. Call error() to get the reason for the failure.
|
|
||||||
*/
|
|
||||||
bool connect();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect ssh from the host. This kills the ssh process and
|
|
||||||
* resets the internal state of this KSshProcess object. After a
|
|
||||||
* disconnect, the same KSshProcess can be used to connect to a
|
|
||||||
* host.
|
|
||||||
*/
|
|
||||||
void disconnect();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call to respond to a ERR_NEW_HOST_KEY or ERR_DIFF_HOST_KEY error.
|
|
||||||
*
|
|
||||||
* @param accept True to accept the host key, false to not accept the
|
|
||||||
* host key and kill ssh.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void acceptHostKey(bool accept);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call to respond to a ERR_NEED_PASSWD or ERR_NEED_PASSPHRASE error.
|
|
||||||
*
|
|
||||||
* @param password The user password to give ssh.
|
|
||||||
*/
|
|
||||||
void setPassword(TQString password);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access to standard in and out of the ssh process.
|
|
||||||
*
|
|
||||||
* @return The file description for stdin and stdout of the ssh process.
|
|
||||||
*/
|
|
||||||
int stdioFd() { return ssh.stdioFd(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access to standard error of the ssh process.
|
|
||||||
*
|
|
||||||
* @return The file descriptior for stderr of the ssh process.
|
|
||||||
*/
|
|
||||||
int stderrFd() { return ssh.stderrFd(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access the pty to which the ssh process is attached.
|
|
||||||
*
|
|
||||||
* @return The file descriptor of pty to which ssh is attached.
|
|
||||||
*/
|
|
||||||
int pty() { return ssh.fd(); }
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Path the the ssh binary.
|
|
||||||
*/
|
|
||||||
TQString mSshPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSH version. This is an index into the supported SSH
|
|
||||||
* versions array, and the various messages arrays.
|
|
||||||
*/
|
|
||||||
SshVersion mVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User's password. Zero this out when it is no longer needed.
|
|
||||||
*/
|
|
||||||
TQString mPassword;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User's username.
|
|
||||||
*/
|
|
||||||
TQString mUsername;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of host we are connecting to.
|
|
||||||
*/
|
|
||||||
TQString mHost;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accept new or changed host keys if true.
|
|
||||||
*/
|
|
||||||
bool mAcceptHostKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to tell use if we have an open, authenticated ssh
|
|
||||||
* session going.
|
|
||||||
*/
|
|
||||||
bool mConnected;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag to tell us if we have started a ssh process, we use this
|
|
||||||
* to make sure we kill ssh before going away.
|
|
||||||
*/
|
|
||||||
bool mRunning;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save any key fingerprint msg from ssh so we can present
|
|
||||||
* it to the caller.
|
|
||||||
*/
|
|
||||||
TQString mKeyFingerprint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The location of the known host key file. We grab this from
|
|
||||||
* any error messages ssh prints out.
|
|
||||||
*/
|
|
||||||
TQString mKnownHostsFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The state of our connect state machine.
|
|
||||||
*/
|
|
||||||
int mConnectState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Port on on which the target ssh server is listening.
|
|
||||||
*/
|
|
||||||
int mPort;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The last error number encountered. This is only valid for the
|
|
||||||
* last error.
|
|
||||||
*/
|
|
||||||
SshError mError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An error message that corresponds to the error number set in
|
|
||||||
* mError. Optional.
|
|
||||||
*/
|
|
||||||
TQString mErrorMsg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to the SSH process we ceate. Handles communication
|
|
||||||
* to and from the SSH process using stdin, stdout, stderr, and
|
|
||||||
* pty.
|
|
||||||
*/
|
|
||||||
MyPtyProcess ssh;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of arguments we start SSH with.
|
|
||||||
*/
|
|
||||||
QCStringList mArgs;
|
|
||||||
void init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler to clean up when ssh process terminates.
|
|
||||||
*/
|
|
||||||
static void SIGCHLD_handler(int signo);
|
|
||||||
void installSignalHandlers();
|
|
||||||
void removeSignalHandlers();
|
|
||||||
|
|
||||||
TQString getLine();
|
|
||||||
|
|
||||||
static TQRegExp versionStrs[];
|
|
||||||
static const char * const passwordPrompt[];
|
|
||||||
static const char * const passphrasePrompt[];
|
|
||||||
static const char * const authSuccessMsg[];
|
|
||||||
static const char * const authFailedMsg[];
|
|
||||||
static TQRegExp hostKeyMissingMsg[];
|
|
||||||
static const char * const hostKeyChangedMsg[];
|
|
||||||
static const char * const continuePrompt[];
|
|
||||||
static const char * const hostKeyAcceptedMsg[];
|
|
||||||
static const char * const tryAgainMsg[];
|
|
||||||
static TQRegExp hostKeyVerifyFailedMsg[];
|
|
||||||
static const char * const connectionClosedMsg[];
|
|
||||||
static const char * const changeHostKeyOnDiskPrompt[];
|
|
||||||
static TQRegExp keyFingerprintMsg[];
|
|
||||||
static TQRegExp knownHostsFileMsg[];
|
|
||||||
};
|
|
||||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||||||
#include "ksshprocess.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
|
|
||||||
if( argc < 5 ) {
|
|
||||||
cout << "Usage: " << argv[0] <<
|
|
||||||
" <ssh path> <host> <username> <password>" << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
KSshProcess ssh(argv[1]);
|
|
||||||
cout << ssh.version() << endl;
|
|
||||||
|
|
||||||
KSshProcess::SshOptList opts;
|
|
||||||
KSshProcess::SshOpt opt;
|
|
||||||
|
|
||||||
opt.opt = KSshProcess::SSH_PORT;
|
|
||||||
opt.num = 22;
|
|
||||||
opts.append(opt);
|
|
||||||
|
|
||||||
opt.opt = KSshProcess::SSH_HOST;
|
|
||||||
opt.str = TQString(argv[2]);
|
|
||||||
opts.append(opt);
|
|
||||||
|
|
||||||
opt.opt = KSshProcess::SSH_USERNAME;
|
|
||||||
opt.str = TQString(argv[3]);
|
|
||||||
opts.append(opt);
|
|
||||||
|
|
||||||
// opt.opt = KSshProcess::SSH_PASSWD;
|
|
||||||
// opt.str = TQString(argv[4]);
|
|
||||||
// opts.append(opt);
|
|
||||||
|
|
||||||
if( !ssh.setOptions(opts) ) {
|
|
||||||
cout << "ksshprocesstest: setOptions failed" << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh.printArgs();
|
|
||||||
|
|
||||||
bool stop = false;
|
|
||||||
bool connected;
|
|
||||||
char buf[256];
|
|
||||||
char c;
|
|
||||||
while( !stop && !(connected = ssh.connect()) ) {
|
|
||||||
cout << "ksshprocesstest: Error num - " << ssh.error() << endl;
|
|
||||||
cout << "ksshprocesstest: Error msg - " << ssh.errorMsg().latin1() << endl;
|
|
||||||
switch( ssh.error() ) {
|
|
||||||
case KSshProcess::ERR_NEED_PASSWD:
|
|
||||||
case KSshProcess::ERR_NEED_PASSPHRASE:
|
|
||||||
cout << "Password: ";
|
|
||||||
cin >> buf;
|
|
||||||
cout << "password is " << buf << endl;
|
|
||||||
ssh.setPassword(TQString(buf));
|
|
||||||
break;
|
|
||||||
case KSshProcess::ERR_NEW_HOST_KEY:
|
|
||||||
case KSshProcess::ERR_DIFF_HOST_KEY:
|
|
||||||
cout << "Accept host key? (y/n): ";
|
|
||||||
cin >> c;
|
|
||||||
cout << "Answered " << c << endl;
|
|
||||||
ssh.acceptHostKey(c == 'y' ? true : false);
|
|
||||||
break;
|
|
||||||
case KSshProcess::ERR_AUTH_FAILED:
|
|
||||||
cout << "ksshprocesstest: auth failed." << endl;
|
|
||||||
stop = true;
|
|
||||||
break;
|
|
||||||
case KSshProcess::ERR_AUTH_FAILED_NEW_KEY:
|
|
||||||
cout << "ksshprocesstest: auth failed because of new key." << endl;
|
|
||||||
stop = true;
|
|
||||||
break;
|
|
||||||
case KSshProcess::ERR_AUTH_FAILED_DIFF_KEY:
|
|
||||||
cout << "ksshprocesstest: auth failed because of changed key." << endl;
|
|
||||||
stop = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KSshProcess::ERR_INTERACT:
|
|
||||||
case KSshProcess::ERR_INTERNAL:
|
|
||||||
case KSshProcess::ERR_UNKNOWN:
|
|
||||||
case KSshProcess::ERR_INVALID_STATE:
|
|
||||||
case KSshProcess::ERR_CANNOT_LAUNCH:
|
|
||||||
case KSshProcess::ERR_HOST_KEY_REJECTED:
|
|
||||||
cout << "ksshprocesstest: FATAL ERROR" << endl;
|
|
||||||
stop = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( connected ) {
|
|
||||||
cout << "ksshprocesstest: Successfully connected to " << argv[2] << endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cout << "ksshprocesstest: Connect to " << argv[2] << " failed." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,493 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This file is part of the KDE project, module tdesu.
|
|
||||||
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
|
|
||||||
*
|
|
||||||
* This file contains code from TEShell.C of the KDE konsole.
|
|
||||||
* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
|
|
||||||
*
|
|
||||||
* This is free software; you can use this library under the GNU Library
|
|
||||||
* General Public License, version 2. See the file "COPYING.LIB" for the
|
|
||||||
* exact licensing terms.
|
|
||||||
*
|
|
||||||
* process.cpp: Functionality to build a front end to password asking
|
|
||||||
* terminal programs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#if defined(__SVR4) && defined(sun)
|
|
||||||
#include <stropts.h>
|
|
||||||
#include <sys/stream.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
#include <sys/select.h> // Needed on some systems.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <tqglobal.h>
|
|
||||||
#include <tqcstring.h>
|
|
||||||
#include <tqfile.h>
|
|
||||||
|
|
||||||
#include <kdebug.h>
|
|
||||||
#include <kstandarddirs.h>
|
|
||||||
|
|
||||||
#include "process.h"
|
|
||||||
#include <tdesu/tdesu_pty.h>
|
|
||||||
#include <tdesu/kcookie.h>
|
|
||||||
|
|
||||||
|
|
||||||
MyPtyProcess::MyPtyProcess()
|
|
||||||
{
|
|
||||||
m_bTerminal = false;
|
|
||||||
m_bErase = false;
|
|
||||||
m_pPTY = 0L;
|
|
||||||
m_Pid = -1;
|
|
||||||
m_Fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int MyPtyProcess::init()
|
|
||||||
{
|
|
||||||
delete m_pPTY;
|
|
||||||
m_pPTY = new PTY();
|
|
||||||
m_Fd = m_pPTY->getpt();
|
|
||||||
if (m_Fd < 0)
|
|
||||||
return -1;
|
|
||||||
if ((m_pPTY->grantpt() < 0) || (m_pPTY->unlockpt() < 0))
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "Master setup failed.\n" << endl;
|
|
||||||
m_Fd = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
m_TTY = m_pPTY->ptsname();
|
|
||||||
m_stdoutBuf.resize(0);
|
|
||||||
m_stderrBuf.resize(0);
|
|
||||||
m_ptyBuf.resize(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MyPtyProcess::~MyPtyProcess()
|
|
||||||
{
|
|
||||||
delete m_pPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read one line of input. The terminal is in canonical mode, so you always
|
|
||||||
* read a line at at time, but it's possible to receive multiple lines in
|
|
||||||
* one time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
TQCString MyPtyProcess::readLineFrom(int fd, TQCString& inbuf, bool block)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
TQCString ret;
|
|
||||||
|
|
||||||
if (!inbuf.isEmpty())
|
|
||||||
{
|
|
||||||
|
|
||||||
pos = inbuf.find('\n');
|
|
||||||
|
|
||||||
if (pos == -1)
|
|
||||||
{
|
|
||||||
ret = inbuf;
|
|
||||||
inbuf.resize(0);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ret = inbuf.left(pos);
|
|
||||||
inbuf = inbuf.mid(pos+1);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int flags = fcntl(fd, F_GETFL);
|
|
||||||
if (flags < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "fcntl(F_GETFL): " << perror << "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (block)
|
|
||||||
flags &= ~O_NONBLOCK;
|
|
||||||
else
|
|
||||||
flags |= O_NONBLOCK;
|
|
||||||
if (fcntl(fd, F_SETFL, flags) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "fcntl(F_SETFL): " << perror << "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nbytes;
|
|
||||||
char buf[256];
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
nbytes = read(fd, buf, 255);
|
|
||||||
if (nbytes == -1)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
if (nbytes == 0)
|
|
||||||
break; // eof
|
|
||||||
|
|
||||||
buf[nbytes] = '\000';
|
|
||||||
inbuf += buf;
|
|
||||||
|
|
||||||
pos = inbuf.find('\n');
|
|
||||||
if (pos == -1)
|
|
||||||
{
|
|
||||||
ret = inbuf;
|
|
||||||
inbuf.resize(0);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ret = inbuf.left(pos);
|
|
||||||
inbuf = inbuf.mid(pos+1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyPtyProcess::writeLine(TQCString line, bool addnl)
|
|
||||||
{
|
|
||||||
if (!line.isEmpty())
|
|
||||||
write(m_Fd, line, line.length());
|
|
||||||
if (addnl)
|
|
||||||
write(m_Fd, "\n", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyPtyProcess::unreadLineFrom(TQCString inbuf, TQCString line, bool addnl)
|
|
||||||
{
|
|
||||||
if (addnl)
|
|
||||||
line += '\n';
|
|
||||||
if (!line.isEmpty())
|
|
||||||
inbuf.prepend(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fork and execute the command. This returns in the parent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int MyPtyProcess::exec(TQCString command, QCStringList args)
|
|
||||||
{
|
|
||||||
kdDebug(PTYPROC) << "MyPtyProcess::exec(): " << command << endl;// << ", args = " << args << endl;
|
|
||||||
|
|
||||||
if (init() < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Open the pty slave before forking. See SetupTTY()
|
|
||||||
int slave = open(m_TTY, O_RDWR);
|
|
||||||
if (slave < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "Could not open slave pty.\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also create a socket pair to connect to standard in/out.
|
|
||||||
// This will allow use to bypass the terminal.
|
|
||||||
int inout[2];
|
|
||||||
int err[2];
|
|
||||||
int ok = 1;
|
|
||||||
ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, inout) >= 0;
|
|
||||||
ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err ) >= 0;
|
|
||||||
if( !ok ) {
|
|
||||||
kdDebug(PTYPROC) << "Could not create socket" << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
m_stdinout = inout[0];
|
|
||||||
m_err = err[0];
|
|
||||||
|
|
||||||
if ((m_Pid = fork()) == -1)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "fork(): " << perror << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent
|
|
||||||
if (m_Pid)
|
|
||||||
{
|
|
||||||
close(slave);
|
|
||||||
close(inout[1]);
|
|
||||||
close(err[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Child
|
|
||||||
|
|
||||||
ok = 1;
|
|
||||||
ok &= dup2(inout[1], STDIN_FILENO) >= 0;
|
|
||||||
ok &= dup2(inout[1], STDOUT_FILENO) >= 0;
|
|
||||||
ok &= dup2(err[1], STDERR_FILENO) >= 0;
|
|
||||||
|
|
||||||
if( !ok )
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << "dup of socket descriptor failed" << endl;
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(inout[1]);
|
|
||||||
close(inout[0]);
|
|
||||||
close(err[1]);
|
|
||||||
close(err[0]);
|
|
||||||
|
|
||||||
if (SetupTTY(slave) < 0)
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
// From now on, terminal output goes through the tty.
|
|
||||||
TQCString path;
|
|
||||||
if (command.contains('/'))
|
|
||||||
path = command;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TQString file = TDEStandardDirs::findExe(command);
|
|
||||||
if (file.isEmpty())
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << command << " not found\n";
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
path = TQFile::encodeName(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i;
|
|
||||||
const char * argp[32];
|
|
||||||
argp[0] = path;
|
|
||||||
QCStringList::Iterator it;
|
|
||||||
for (i=1, it=args.begin(); it!=args.end() && i<31; it++) {
|
|
||||||
argp[i++] = *it;
|
|
||||||
kdDebug(PTYPROC) << *it << endl;
|
|
||||||
}
|
|
||||||
argp[i] = 0L;
|
|
||||||
execv(path, (char * const *)argp);
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "execv(\"" << path << "\"): " << perror << "\n";
|
|
||||||
_exit(1);
|
|
||||||
return -1; // Shut up compiler. Never reached.
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait until the terminal is set into no echo mode. At least one su
|
|
||||||
* (RH6 w/ Linux-PAM patches) sets noecho mode AFTER writing the Password:
|
|
||||||
* prompt, using TCSAFLUSH. This flushes the terminal I/O queues, possibly
|
|
||||||
* taking the password with it. So we wait until no echo mode is set
|
|
||||||
* before writing the password.
|
|
||||||
* Note that this is done on the slave fd. While Linux allows tcgetattr() on
|
|
||||||
* the master side, Solaris doesn't.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int MyPtyProcess::WaitSlave()
|
|
||||||
{
|
|
||||||
int slave = open(m_TTY, O_RDWR);
|
|
||||||
if (slave < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "Could not open slave tty.\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct termios tio;
|
|
||||||
struct timeval tv;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (tcgetattr(slave, &tio) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
|
|
||||||
close(slave);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (tio.c_lflag & ECHO)
|
|
||||||
{
|
|
||||||
kdDebug(PTYPROC) << k_lineinfo << "Echo mode still on." << endl;
|
|
||||||
// sleep 1/10 sec
|
|
||||||
tv.tv_sec = 0; tv.tv_usec = 100000;
|
|
||||||
select(slave, 0L, 0L, 0L, &tv);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
close(slave);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int MyPtyProcess::enableLocalEcho(bool enable)
|
|
||||||
{
|
|
||||||
int slave = open(m_TTY, O_RDWR);
|
|
||||||
if (slave < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "Could not open slave tty.\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
struct termios tio;
|
|
||||||
if (tcgetattr(slave, &tio) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
|
|
||||||
close(slave); return -1;
|
|
||||||
}
|
|
||||||
if (enable)
|
|
||||||
tio.c_lflag |= ECHO;
|
|
||||||
else
|
|
||||||
tio.c_lflag &= ~ECHO;
|
|
||||||
if (tcsetattr(slave, TCSANOW, &tio) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "tcsetattr(): " << perror << "\n";
|
|
||||||
close(slave); return -1;
|
|
||||||
}
|
|
||||||
close(slave);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy output to stdout until the child process exists, or a line of output
|
|
||||||
* matches `m_Exit'.
|
|
||||||
* We have to use waitpid() to test for exit. Merely waiting for EOF on the
|
|
||||||
* pty does not work, because the target process may have children still
|
|
||||||
* attached to the terminal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int MyPtyProcess::waitForChild()
|
|
||||||
{
|
|
||||||
int ret, state, retval = 1;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
fd_set fds;
|
|
||||||
FD_ZERO(&fds);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
tv.tv_sec = 1; tv.tv_usec = 0;
|
|
||||||
FD_SET(m_Fd, &fds);
|
|
||||||
ret = select(m_Fd+1, &fds, 0L, 0L, &tv);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
if (errno == EINTR) continue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "select(): " << perror << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
TQCString line = readLine(false);
|
|
||||||
while (!line.isNull())
|
|
||||||
{
|
|
||||||
if (!m_Exit.isEmpty() && !tqstrnicmp(line, m_Exit, m_Exit.length()))
|
|
||||||
kill(m_Pid, SIGTERM);
|
|
||||||
if (m_bTerminal)
|
|
||||||
{
|
|
||||||
fputs(line, stdout);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
}
|
|
||||||
line = readLine(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the process is still alive
|
|
||||||
ret = waitpid(m_Pid, &state, WNOHANG);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
if (errno == ECHILD)
|
|
||||||
retval = 0;
|
|
||||||
else
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "waitpid(): " << perror << "\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret == m_Pid)
|
|
||||||
{
|
|
||||||
if (WIFEXITED(state))
|
|
||||||
retval = WEXITSTATUS(state);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SetupTTY: Creates a new session. The filedescriptor "fd" should be
|
|
||||||
* connected to the tty. It is closed after the tty is reopened to make it
|
|
||||||
* our controlling terminal. This way the tty is always opened at least once
|
|
||||||
* so we'll never get EIO when reading from it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int MyPtyProcess::SetupTTY(int fd)
|
|
||||||
{
|
|
||||||
// Reset signal handlers
|
|
||||||
for (int sig = 1; sig < NSIG; sig++)
|
|
||||||
signal(sig, SIG_DFL);
|
|
||||||
signal(SIGHUP, SIG_IGN);
|
|
||||||
|
|
||||||
// Close all file handles
|
|
||||||
// struct rlimit rlp;
|
|
||||||
// getrlimit(RLIMIT_NOFILE, &rlp);
|
|
||||||
// for (int i = 0; i < (int)rlp.rlim_cur; i++)
|
|
||||||
// if (i != fd) close(i);
|
|
||||||
|
|
||||||
// Create a new session.
|
|
||||||
setsid();
|
|
||||||
|
|
||||||
// Open slave. This will make it our controlling terminal
|
|
||||||
int slave = open(m_TTY, O_RDWR);
|
|
||||||
if (slave < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "Could not open slave side: " << perror << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
#if defined(__SVR4) && defined(sun)
|
|
||||||
|
|
||||||
// Solaris STREAMS environment.
|
|
||||||
// Push these modules to make the stream look like a terminal.
|
|
||||||
ioctl(slave, I_PUSH, "ptem");
|
|
||||||
ioctl(slave, I_PUSH, "ldterm");
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Connect stdin, stdout and stderr
|
|
||||||
// dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
|
|
||||||
// if (slave > 2)
|
|
||||||
// close(slave);
|
|
||||||
|
|
||||||
// Disable OPOST processing. Otherwise, '\n' are (on Linux at least)
|
|
||||||
// translated to '\r\n'.
|
|
||||||
struct termios tio;
|
|
||||||
if (tcgetattr(slave, &tio) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tio.c_oflag &= ~OPOST;
|
|
||||||
if (tcsetattr(slave, TCSANOW, &tio) < 0)
|
|
||||||
{
|
|
||||||
kdError(PTYPROC) << k_lineinfo << "tcsetattr(): " << perror << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This file is part of the KDE project, module tdesu.
|
|
||||||
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
|
|
||||||
*
|
|
||||||
* This is free software; you can use this library under the GNU Library
|
|
||||||
* General Public License, version 2. See the file "COPYING.LIB" for the
|
|
||||||
* exact licensing terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __Process_h_Included__
|
|
||||||
#define __Process_h_Included__
|
|
||||||
|
|
||||||
#include <tqcstring.h>
|
|
||||||
#include <tqstring.h>
|
|
||||||
#include <tqstringlist.h>
|
|
||||||
#include <tqvaluelist.h>
|
|
||||||
|
|
||||||
#define PTYPROC 7120
|
|
||||||
|
|
||||||
class PTY;
|
|
||||||
typedef TQValueList<TQCString> QCStringList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronous communication with tty programs.
|
|
||||||
*
|
|
||||||
* PtyProcess provides synchronous communication with tty based programs.
|
|
||||||
* The communications channel used is a pseudo tty (as opposed to a pipe)
|
|
||||||
* This means that programs which require a terminal will work.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MyPtyProcess
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MyPtyProcess();
|
|
||||||
virtual ~MyPtyProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fork off and execute a command. The command's standard in and output
|
|
||||||
* are connected to the pseudo tty. They are accessible with @ref #readLine
|
|
||||||
* and @ref #writeLine.
|
|
||||||
* @param command The command to execute.
|
|
||||||
* @param args The arguments to the command.
|
|
||||||
*/
|
|
||||||
int exec(TQCString command, QCStringList args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a line from the program's standard out. Depending on the @em block
|
|
||||||
* parameter, this call blocks until a single, full line is read.
|
|
||||||
* @param block Block until a full line is read?
|
|
||||||
* @return The output string.
|
|
||||||
*/
|
|
||||||
TQCString readLine(bool block = true)
|
|
||||||
{ return readLineFrom(m_Fd, m_ptyBuf, block); }
|
|
||||||
|
|
||||||
TQCString readLineFromPty(bool block = true)
|
|
||||||
{ return readLineFrom(m_Fd, m_ptyBuf, block); }
|
|
||||||
|
|
||||||
TQCString readLineFromStdout(bool block = true)
|
|
||||||
{ return readLineFrom(m_stdinout, m_stdoutBuf, block); }
|
|
||||||
|
|
||||||
TQCString readLineFromStderr(bool block = true)
|
|
||||||
{ return readLineFrom(m_err, m_stderrBuf, block); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a line of text to the program's standard in.
|
|
||||||
* @param line The text to write.
|
|
||||||
* @param addNewline Adds a '\n' to the line.
|
|
||||||
*/
|
|
||||||
void writeLine(TQCString line, bool addNewline=true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put back a line of input.
|
|
||||||
* @param line The line to put back.
|
|
||||||
* @param addNewline Adds a '\n' to the line.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void unreadLine(TQCString line, bool addNewline = true)
|
|
||||||
{ unreadLineFrom(m_ptyBuf, line, addNewline); }
|
|
||||||
|
|
||||||
void unreadLineFromPty(TQCString line, bool addNewline = true)
|
|
||||||
{ unreadLineFrom(m_ptyBuf, line, addNewline); }
|
|
||||||
|
|
||||||
void unreadLineFromStderr(TQCString line, bool addNewline = true)
|
|
||||||
{ unreadLineFrom(m_stderrBuf, line, addNewline); }
|
|
||||||
|
|
||||||
void unreadLineFromStdout(TQCString line, bool addNewline = true)
|
|
||||||
{ unreadLineFrom(m_stdoutBuf, line, addNewline); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set exit string. If a line of program output matches this,
|
|
||||||
* @ref #waitForChild() will terminate the program and return.
|
|
||||||
*/
|
|
||||||
void setExitString(TQCString exit) { m_Exit = exit; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for the child to exit. See also @ref #setExitString.
|
|
||||||
*/
|
|
||||||
int waitForChild();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the pty has cleared the ECHO flag. This is useful
|
|
||||||
* when programs write a password prompt before they disable ECHO.
|
|
||||||
* Disabling it might flush any input that was written.
|
|
||||||
*/
|
|
||||||
int WaitSlave();
|
|
||||||
|
|
||||||
/** Enables/disables local echo on the pseudo tty. */
|
|
||||||
int enableLocalEcho(bool enable=true);
|
|
||||||
|
|
||||||
/** Enable/disable terminal output. Relevant only to some subclasses. */
|
|
||||||
void setTerminal(bool terminal) { m_bTerminal = terminal; }
|
|
||||||
|
|
||||||
/** Overwritte the password as soon as it is used. Relevant only to
|
|
||||||
* some subclasses. */
|
|
||||||
void setErase(bool erase) { m_bErase = erase; }
|
|
||||||
|
|
||||||
/** Return the filedescriptor of the process. */
|
|
||||||
int fd() {return m_Fd;}
|
|
||||||
|
|
||||||
/** Return the pid of the process. */
|
|
||||||
int pid() {return m_Pid;}
|
|
||||||
|
|
||||||
int stdioFd() {return m_stdinout;}
|
|
||||||
|
|
||||||
int stderrFd() {return m_err;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool m_bErase, m_bTerminal;
|
|
||||||
int m_Pid, m_Fd, m_stdinout, m_err;
|
|
||||||
TQCString m_Command, m_Exit;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int init();
|
|
||||||
int SetupTTY(int fd);
|
|
||||||
|
|
||||||
PTY *m_pPTY;
|
|
||||||
TQCString m_TTY;
|
|
||||||
TQCString m_ptyBuf, m_stderrBuf, m_stdoutBuf;
|
|
||||||
|
|
||||||
TQCString readLineFrom(int fd, TQCString& inbuf, bool block);
|
|
||||||
void unreadLineFrom(TQCString inbuf, TQCString line, bool addnl);
|
|
||||||
class PtyProcessPrivate;
|
|
||||||
PtyProcessPrivate *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,91 +0,0 @@
|
|||||||
/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* draft-ietf-secsh-filexfer-01.txt
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* version */
|
|
||||||
#define SSH2_FILEXFER_VERSION 3
|
|
||||||
|
|
||||||
/* client to server */
|
|
||||||
#define SSH2_FXP_INIT 1
|
|
||||||
#define SSH2_FXP_OPEN 3
|
|
||||||
#define SSH2_FXP_CLOSE 4
|
|
||||||
#define SSH2_FXP_READ 5
|
|
||||||
#define SSH2_FXP_WRITE 6
|
|
||||||
#define SSH2_FXP_LSTAT 7
|
|
||||||
#define SSH2_FXP_FSTAT 8
|
|
||||||
#define SSH2_FXP_SETSTAT 9
|
|
||||||
#define SSH2_FXP_FSETSTAT 10
|
|
||||||
#define SSH2_FXP_OPENDIR 11
|
|
||||||
#define SSH2_FXP_READDIR 12
|
|
||||||
#define SSH2_FXP_REMOVE 13
|
|
||||||
#define SSH2_FXP_MKDIR 14
|
|
||||||
#define SSH2_FXP_RMDIR 15
|
|
||||||
#define SSH2_FXP_REALPATH 16
|
|
||||||
#define SSH2_FXP_STAT 17
|
|
||||||
#define SSH2_FXP_RENAME 18
|
|
||||||
#define SSH2_FXP_READLINK 19
|
|
||||||
#define SSH2_FXP_SYMLINK 20
|
|
||||||
|
|
||||||
/* server to client */
|
|
||||||
#define SSH2_FXP_VERSION 2
|
|
||||||
#define SSH2_FXP_STATUS 101
|
|
||||||
#define SSH2_FXP_HANDLE 102
|
|
||||||
#define SSH2_FXP_DATA 103
|
|
||||||
#define SSH2_FXP_NAME 104
|
|
||||||
#define SSH2_FXP_ATTRS 105
|
|
||||||
|
|
||||||
#define SSH2_FXP_EXTENDED 200
|
|
||||||
#define SSH2_FXP_EXTENDED_REPLY 201
|
|
||||||
|
|
||||||
/* attributes */
|
|
||||||
#define SSH2_FILEXFER_ATTR_SIZE 0x00000001
|
|
||||||
#define SSH2_FILEXFER_ATTR_UIDGID 0x00000002
|
|
||||||
#define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004
|
|
||||||
#define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008
|
|
||||||
#define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000
|
|
||||||
|
|
||||||
/* portable open modes */
|
|
||||||
#define SSH2_FXF_READ 0x00000001
|
|
||||||
#define SSH2_FXF_WRITE 0x00000002
|
|
||||||
#define SSH2_FXF_APPEND 0x00000004
|
|
||||||
#define SSH2_FXF_CREAT 0x00000008
|
|
||||||
#define SSH2_FXF_TRUNC 0x00000010
|
|
||||||
#define SSH2_FXF_EXCL 0x00000020
|
|
||||||
|
|
||||||
/* status messages */
|
|
||||||
#define SSH2_FX_OK 0
|
|
||||||
#define SSH2_FX_EOF 1
|
|
||||||
#define SSH2_FX_NO_SUCH_FILE 2
|
|
||||||
#define SSH2_FX_PERMISSION_DENIED 3
|
|
||||||
#define SSH2_FX_FAILURE 4
|
|
||||||
#define SSH2_FX_BAD_MESSAGE 5
|
|
||||||
#define SSH2_FX_NO_CONNECTION 6
|
|
||||||
#define SSH2_FX_CONNECTION_LOST 7
|
|
||||||
#define SSH2_FX_OP_UNSUPPORTED 8
|
|
||||||
#define SSH2_FX_MAX 8
|
|
@ -1,345 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
sftpfileattr.cpp - description
|
|
||||||
-------------------
|
|
||||||
begin : Sat Jun 30 2001
|
|
||||||
copyright : (C) 2001 by Lucas Fisher
|
|
||||||
email : ljfisher@iastate.edu
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "sftpfileattr.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <tqstring.h>
|
|
||||||
#include <tqdatastream.h>
|
|
||||||
|
|
||||||
#include <tdeio/global.h>
|
|
||||||
#include <kremoteencoding.h>
|
|
||||||
|
|
||||||
using namespace TDEIO;
|
|
||||||
|
|
||||||
sftpFileAttr::sftpFileAttr(){
|
|
||||||
clear();
|
|
||||||
mDirAttrs = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sftpFileAttr::sftpFileAttr(KRemoteEncoding* encoding){
|
|
||||||
clear();
|
|
||||||
mDirAttrs = false;
|
|
||||||
mEncoding = encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Constructor to initialize the file attributes on declaration. */
|
|
||||||
sftpFileAttr::sftpFileAttr(TQ_ULLONG size, uid_t uid, gid_t gid,
|
|
||||||
mode_t permissions, time_t atime,
|
|
||||||
time_t mtime, TQ_UINT32 extendedCount) {
|
|
||||||
clear();
|
|
||||||
mDirAttrs = false;
|
|
||||||
mSize = size;
|
|
||||||
mUid = uid;
|
|
||||||
mGid = gid;
|
|
||||||
mAtime = atime;
|
|
||||||
mMtime = mtime;
|
|
||||||
mPermissions = permissions;
|
|
||||||
mExtendedCount = extendedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
sftpFileAttr::~sftpFileAttr(){
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a UDSEntry describing the file.
|
|
||||||
The UDSEntry is generated from the sftp file attributes. */
|
|
||||||
UDSEntry sftpFileAttr::entry() {
|
|
||||||
UDSEntry entry;
|
|
||||||
UDSAtom atom;
|
|
||||||
|
|
||||||
atom.m_uds = UDS_NAME;
|
|
||||||
atom.m_str = mFilename;
|
|
||||||
entry.append(atom);
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_SIZE ) {
|
|
||||||
atom.m_uds = UDS_SIZE;
|
|
||||||
atom.m_long = mSize;
|
|
||||||
entry.append(atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) {
|
|
||||||
atom.m_uds = UDS_ACCESS_TIME;
|
|
||||||
atom.m_long = mAtime;
|
|
||||||
entry.append(atom);
|
|
||||||
|
|
||||||
atom.m_uds = UDS_MODIFICATION_TIME;
|
|
||||||
atom.m_long = mMtime;
|
|
||||||
entry.append(atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_UIDGID ) {
|
|
||||||
if( mUserName.isEmpty() || mGroupName.isEmpty() )
|
|
||||||
getUserGroupNames();
|
|
||||||
|
|
||||||
atom.m_uds = UDS_USER;
|
|
||||||
atom.m_str = mUserName;
|
|
||||||
entry.append(atom);
|
|
||||||
|
|
||||||
atom.m_uds = UDS_GROUP;
|
|
||||||
atom.m_str = mGroupName;
|
|
||||||
entry.append(atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) {
|
|
||||||
atom.m_uds = UDS_ACCESS;
|
|
||||||
atom.m_long = mPermissions;
|
|
||||||
entry.append(atom);
|
|
||||||
|
|
||||||
mode_t type = fileType();
|
|
||||||
|
|
||||||
// Set the type if we know what it is
|
|
||||||
if( type != 0 ) {
|
|
||||||
atom.m_uds = UDS_FILE_TYPE;
|
|
||||||
atom.m_long = (mLinkType ? mLinkType:type);
|
|
||||||
entry.append(atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( S_ISLNK(type) ) {
|
|
||||||
atom.m_uds = UDS_LINK_DEST;
|
|
||||||
atom.m_str = mLinkDestination;
|
|
||||||
entry.append(atom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use to output the file attributes to a sftp packet */
|
|
||||||
TQDataStream& operator<< (TQDataStream& s, const sftpFileAttr& fa) {
|
|
||||||
s << (TQ_UINT32)fa.mFlags;
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE )
|
|
||||||
{ s << (TQ_ULLONG)fa.mSize; }
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID )
|
|
||||||
{ s << (TQ_UINT32)fa.mUid << (TQ_UINT32)fa.mGid; }
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS )
|
|
||||||
{ s << (TQ_UINT32)fa.mPermissions; }
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME )
|
|
||||||
{ s << (TQ_UINT32)fa.mAtime << (TQ_UINT32)fa.mMtime; }
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
|
|
||||||
s << (TQ_UINT32)fa.mExtendedCount;
|
|
||||||
// XXX: Write extensions to data stream here
|
|
||||||
// s.writeBytes(extendedtype).writeBytes(extendeddata);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Use to read a file attribute from a sftp packet */
|
|
||||||
TQDataStream& operator>> (TQDataStream& s, sftpFileAttr& fa) {
|
|
||||||
|
|
||||||
// XXX Add some error checking in here in case
|
|
||||||
// we get a bad sftp packet.
|
|
||||||
|
|
||||||
fa.clear();
|
|
||||||
|
|
||||||
if( fa.mDirAttrs ) {
|
|
||||||
TQCString fn;
|
|
||||||
s >> fn;
|
|
||||||
fn.truncate( fn.size() );
|
|
||||||
|
|
||||||
fa.mFilename = fa.mEncoding->decode( fn );
|
|
||||||
|
|
||||||
s >> fa.mLongname;
|
|
||||||
fa.mLongname.truncate( fa.mLongname.size() );
|
|
||||||
//kdDebug() << ">>: ftpfileattr long filename (" << fa.mLongname.size() << ")= " << fa.mLongname << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
s >> fa.mFlags; // get flags
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE ) {
|
|
||||||
TQ_ULLONG fileSize;
|
|
||||||
s >> fileSize;
|
|
||||||
fa.setFileSize(fileSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
TQ_UINT32 x;
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID ) {
|
|
||||||
s >> x; fa.setUid(x);
|
|
||||||
s >> x; fa.setGid(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) {
|
|
||||||
s >> x; fa.setPermissions(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) {
|
|
||||||
s >> x; fa.setAtime(x);
|
|
||||||
s >> x; fa.setMtime(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
|
|
||||||
s >> x; fa.setExtendedCount(x);
|
|
||||||
// XXX: Read in extensions from data stream here
|
|
||||||
// s.readBytes(extendedtype).readBytes(extendeddata);
|
|
||||||
}
|
|
||||||
|
|
||||||
fa.getUserGroupNames();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
/** Parse longname for the owner and group names. */
|
|
||||||
void sftpFileAttr::getUserGroupNames(){
|
|
||||||
// Get the name of the owner and group of the file from longname.
|
|
||||||
TQString user, group;
|
|
||||||
if( mLongname.isEmpty() ) {
|
|
||||||
// do not have the user name so use the user id instead
|
|
||||||
user.setNum(mUid);
|
|
||||||
group.setNum(mGid);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int field = 0;
|
|
||||||
int i = 0;
|
|
||||||
int l = mLongname.length();
|
|
||||||
|
|
||||||
TQString longName = mEncoding->decode( mLongname );
|
|
||||||
|
|
||||||
kdDebug(7120) << "Decoded: " << longName << endl;
|
|
||||||
|
|
||||||
// Find the beginning of the third field which contains the user name.
|
|
||||||
while( field != 2 ) {
|
|
||||||
if( longName[i].isSpace() ) {
|
|
||||||
field++; i++;
|
|
||||||
while( i < l && longName[i].isSpace() ) { i++; }
|
|
||||||
}
|
|
||||||
else { i++; }
|
|
||||||
}
|
|
||||||
// i is the index of the first character of the third field.
|
|
||||||
while( i < l && !longName[i].isSpace() ) {
|
|
||||||
user.append(longName[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// i is the first character of the space between fields 3 and 4
|
|
||||||
// user contains the owner's user name
|
|
||||||
while( i < l && longName[i].isSpace() ) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// i is the first character of the fourth field
|
|
||||||
while( i < l && !longName[i].isSpace() ) {
|
|
||||||
group.append(longName[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
// group contains the name of the group.
|
|
||||||
}
|
|
||||||
|
|
||||||
mUserName = user;
|
|
||||||
mGroupName = group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** No descriptions */
|
|
||||||
kdbgstream& operator<< (kdbgstream& s, sftpFileAttr& a) {
|
|
||||||
s << "Filename: " << a.mFilename
|
|
||||||
<< ", Uid: " << a.mUid
|
|
||||||
<< ", Gid: " << a.mGid
|
|
||||||
<< ", Username: " << a.mUserName
|
|
||||||
<< ", GroupName: " << a.mGroupName
|
|
||||||
<< ", Permissions: " << a.mPermissions
|
|
||||||
<< ", size: " << a.mSize
|
|
||||||
<< ", atime: " << a.mAtime
|
|
||||||
<< ", mtime: " << a.mMtime
|
|
||||||
<< ", extended cnt: " << a.mExtendedCount;
|
|
||||||
|
|
||||||
if (S_ISLNK(a.mLinkType)) {
|
|
||||||
s << ", Link Type: " << a.mLinkType;
|
|
||||||
s << ", Link Destination: " << a.mLinkDestination;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Make sure it builds with NDEBUG */
|
|
||||||
kndbgstream& operator<< (kndbgstream& s, sftpFileAttr& ) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clear all attributes and flags. */
|
|
||||||
void sftpFileAttr::clear(){
|
|
||||||
clearAtime();
|
|
||||||
clearMtime();
|
|
||||||
clearGid();
|
|
||||||
clearUid();
|
|
||||||
clearFileSize();
|
|
||||||
clearPermissions();
|
|
||||||
clearExtensions();
|
|
||||||
mFilename = TQString::null;
|
|
||||||
mGroupName = TQString::null;
|
|
||||||
mUserName = TQString::null;
|
|
||||||
mLinkDestination = TQString::null;
|
|
||||||
mFlags = 0;
|
|
||||||
mLongname = "\0";
|
|
||||||
mLinkType = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the size of the sftp attribute. */
|
|
||||||
TQ_UINT32 sftpFileAttr::size() const{
|
|
||||||
TQ_UINT32 size = 4; // for the attr flag
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_SIZE )
|
|
||||||
size += 8;
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_UIDGID )
|
|
||||||
size += 8;
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS )
|
|
||||||
size += 4;
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME )
|
|
||||||
size += 8;
|
|
||||||
|
|
||||||
if( mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
|
|
||||||
size += 4;
|
|
||||||
// add size of extensions
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the file type as determined from the file permissions */
|
|
||||||
mode_t sftpFileAttr::fileType() const{
|
|
||||||
mode_t type = 0;
|
|
||||||
|
|
||||||
if( S_ISLNK(mPermissions) )
|
|
||||||
type |= S_IFLNK;
|
|
||||||
|
|
||||||
if( S_ISREG(mPermissions) )
|
|
||||||
type |= S_IFREG;
|
|
||||||
else if( S_ISDIR(mPermissions) )
|
|
||||||
type |= S_IFDIR;
|
|
||||||
else if( S_ISCHR(mPermissions) )
|
|
||||||
type |= S_IFCHR;
|
|
||||||
else if( S_ISBLK(mPermissions) )
|
|
||||||
type |= S_IFBLK;
|
|
||||||
else if( S_ISFIFO(mPermissions) )
|
|
||||||
type |= S_IFIFO;
|
|
||||||
else if( S_ISSOCK(mPermissions) )
|
|
||||||
type |= S_IFSOCK;
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sftpFileAttr::setEncoding( KRemoteEncoding* encoding )
|
|
||||||
{
|
|
||||||
mEncoding = encoding;
|
|
||||||
}
|
|
@ -1,261 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
sftpfileattr.h - description
|
|
||||||
-------------------
|
|
||||||
begin : Sat Jun 30 2001
|
|
||||||
copyright : (C) 2001 by Lucas Fisher
|
|
||||||
email : ljfisher@iastate.edu
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef SFTPFILEATTR_H
|
|
||||||
#define SFTPFILEATTR_H
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <tqglobal.h>
|
|
||||||
#include <tqstring.h>
|
|
||||||
#include <tqdatastream.h>
|
|
||||||
|
|
||||||
#include <tdeio/global.h>
|
|
||||||
#include <kdebug.h>
|
|
||||||
|
|
||||||
#include "sftp.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
*@author Lucas Fisher
|
|
||||||
*/
|
|
||||||
|
|
||||||
class KRemoteEncoding;
|
|
||||||
|
|
||||||
class sftpFileAttr {
|
|
||||||
|
|
||||||
private: // Private attributes
|
|
||||||
/** Name of file. */
|
|
||||||
TQString mFilename;
|
|
||||||
|
|
||||||
/** Specifies which fields of the file attribute are available. */
|
|
||||||
TQ_UINT32 mFlags;
|
|
||||||
|
|
||||||
/** Size of the file in bytes. Should be 64 bit safe. */
|
|
||||||
TQ_ULLONG mSize;
|
|
||||||
|
|
||||||
/** User id of the owner of the file. */
|
|
||||||
uid_t mUid;
|
|
||||||
|
|
||||||
/** Group id of the group to which the file belongs. */
|
|
||||||
gid_t mGid;
|
|
||||||
|
|
||||||
/** POSIX permissions of the file. */
|
|
||||||
mode_t mPermissions;
|
|
||||||
|
|
||||||
/** Last access time of the file in seconds from Jan 1, 1970. */
|
|
||||||
time_t mAtime;
|
|
||||||
|
|
||||||
/** Last modification time of file in seconds since Jan. 1, 1970. */
|
|
||||||
time_t mMtime;
|
|
||||||
|
|
||||||
/** Number of file attribute extensions.
|
|
||||||
Not currently implemented */
|
|
||||||
TQ_UINT32 mExtendedCount;
|
|
||||||
|
|
||||||
/** Longname of the file as found in a SSH_FXP_NAME sftp packet.
|
|
||||||
These contents are parse to return the file's owner name and
|
|
||||||
gr oup name. */
|
|
||||||
TQCString mLongname;
|
|
||||||
|
|
||||||
TQString mUserName;
|
|
||||||
TQString mGroupName;
|
|
||||||
|
|
||||||
/** If file is a link, contains the destination of the link */
|
|
||||||
TQString mLinkDestination;
|
|
||||||
|
|
||||||
/** If resource is a link, contains the type the link,e.g. file,dir... */
|
|
||||||
mode_t mLinkType;
|
|
||||||
|
|
||||||
/** Whether >> operator should read filename and longname from the stream. */
|
|
||||||
bool mDirAttrs;
|
|
||||||
|
|
||||||
/** Holds the encoding of the remote host */
|
|
||||||
KRemoteEncoding* mEncoding;
|
|
||||||
|
|
||||||
public:
|
|
||||||
sftpFileAttr();
|
|
||||||
|
|
||||||
sftpFileAttr(KRemoteEncoding* encoding);
|
|
||||||
|
|
||||||
~sftpFileAttr();
|
|
||||||
|
|
||||||
/** Constructor to initialize the file attributes on declaration. */
|
|
||||||
sftpFileAttr(TQ_ULLONG size_, uid_t uid_, gid_t gid_, mode_t permissions_,
|
|
||||||
time_t atime_, time_t mtime_, TQ_UINT32 extendedCount_ = 0);
|
|
||||||
|
|
||||||
/** Return the size of the sftp attribute not including filename or longname*/
|
|
||||||
TQ_UINT32 size() const;
|
|
||||||
|
|
||||||
/** Clear all attributes and flags. */
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/** Set the size of the file. */
|
|
||||||
void setFileSize(TQ_ULLONG s)
|
|
||||||
{ mSize = s; mFlags |= SSH2_FILEXFER_ATTR_SIZE; }
|
|
||||||
|
|
||||||
/** The size file attribute will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. */
|
|
||||||
void clearFileSize()
|
|
||||||
{ mSize = 0; mFlags &= ~SSH2_FILEXFER_ATTR_SIZE; }
|
|
||||||
|
|
||||||
/** Returns the size of the file. */
|
|
||||||
TQ_ULLONG fileSize() const { return mSize; }
|
|
||||||
|
|
||||||
/** Sets the POSIX permissions of the file. */
|
|
||||||
void setPermissions(mode_t p)
|
|
||||||
{ mPermissions = p; mFlags |= SSH2_FILEXFER_ATTR_PERMISSIONS; }
|
|
||||||
|
|
||||||
/** The permissions file attribute will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. */
|
|
||||||
void clearPermissions()
|
|
||||||
{ mPermissions = 0; mFlags &= ~SSH2_FILEXFER_ATTR_PERMISSIONS; }
|
|
||||||
|
|
||||||
/** Returns the POSIX permissons of the file. */
|
|
||||||
mode_t permissions() const { return mPermissions; }
|
|
||||||
|
|
||||||
/** Sets the group id of the file. */
|
|
||||||
void setGid(gid_t id)
|
|
||||||
{ mGid = id; mFlags |= SSH2_FILEXFER_ATTR_UIDGID; }
|
|
||||||
|
|
||||||
/** Neither the gid or uid file attributes will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. This is
|
|
||||||
equivalent to clearUid() */
|
|
||||||
void clearGid()
|
|
||||||
{ mGid = 0; mFlags &= SSH2_FILEXFER_ATTR_UIDGID; }
|
|
||||||
|
|
||||||
/** Returns the group id of the file. */
|
|
||||||
gid_t gid() const { return mGid; }
|
|
||||||
|
|
||||||
/** Sets the uid of the file. */
|
|
||||||
void setUid(uid_t id)
|
|
||||||
{ mUid = id; mFlags |= SSH2_FILEXFER_ATTR_UIDGID; }
|
|
||||||
|
|
||||||
/** Neither the gid or uid file attributes will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. This is
|
|
||||||
equivalent to clearGid() */
|
|
||||||
void clearUid()
|
|
||||||
{ mUid = 0; mFlags &= SSH2_FILEXFER_ATTR_UIDGID; }
|
|
||||||
|
|
||||||
/** Returns the user id of the file. */
|
|
||||||
gid_t uid() const { return mUid; }
|
|
||||||
|
|
||||||
/** Set the modificatoin time of the file in seconds since Jan. 1, 1970. */
|
|
||||||
void setMtime(time_t t)
|
|
||||||
{ mMtime = t; mFlags |= SSH2_FILEXFER_ATTR_ACMODTIME; }
|
|
||||||
|
|
||||||
/** Neither the mtime or atime file attributes will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. This is
|
|
||||||
equivalent to clearAtime() */
|
|
||||||
void clearMtime()
|
|
||||||
{ mMtime = 0; mFlags &= SSH2_FILEXFER_ATTR_ACMODTIME; }
|
|
||||||
|
|
||||||
/** Returns the modification time of the file in seconds since Jan. 1, 1970. */
|
|
||||||
time_t mtime() const { return mMtime; }
|
|
||||||
|
|
||||||
/** Sets the access time of the file in seconds since Jan. 1, 1970. */
|
|
||||||
void setAtime(time_t t)
|
|
||||||
{ mAtime = t; mFlags |= SSH2_FILEXFER_ATTR_ACMODTIME; }
|
|
||||||
|
|
||||||
/** Neither the atime or mtime file attributes will not be included in the UDSEntry
|
|
||||||
or when the file attribute is written to the sftp packet. This is
|
|
||||||
equivalent to clearMtime() */
|
|
||||||
void clearAtime()
|
|
||||||
{ mAtime = 0; mFlags &= SSH2_FILEXFER_ATTR_ACMODTIME; }
|
|
||||||
|
|
||||||
/** Returns the last access time of the file in seconds since Jan. 1, 1970. */
|
|
||||||
time_t atime() const { return mAtime; }
|
|
||||||
|
|
||||||
/** Sets the number of file attribute extensions. */
|
|
||||||
void setExtendedCount(unsigned int c)
|
|
||||||
{ mExtendedCount = c; mFlags |= SSH2_FILEXFER_ATTR_EXTENDED; }
|
|
||||||
|
|
||||||
/** No extensions will be included when the file attribute is written
|
|
||||||
to a sftp packet. */
|
|
||||||
void clearExtensions()
|
|
||||||
{ mExtendedCount = 0; mFlags &= ~SSH2_FILEXFER_ATTR_EXTENDED; }
|
|
||||||
|
|
||||||
/** Returns the number of file attribute extentsions. */
|
|
||||||
unsigned int extendedCount() const { return mExtendedCount; }
|
|
||||||
|
|
||||||
/** Returns the flags for the sftp file attributes. */
|
|
||||||
unsigned int flags() const { return mFlags; }
|
|
||||||
|
|
||||||
/** Sets file's longname. See sftpFileAttr::longname. */
|
|
||||||
void setLongname(TQString l) { mLongname = l.latin1(); }
|
|
||||||
|
|
||||||
/** Returns a string describing the file attributes. The format is specific
|
|
||||||
to the implementation of the sftp server. In most cases (ie OpenSSH)
|
|
||||||
this is similar to the long output of 'ls'. */
|
|
||||||
TQString longname() const { return mLongname; }
|
|
||||||
|
|
||||||
void setLinkDestination(const TQString& target)
|
|
||||||
{ mLinkDestination = target; }
|
|
||||||
|
|
||||||
TQString linkDestination()
|
|
||||||
{ return mLinkDestination; }
|
|
||||||
|
|
||||||
/** Sets the actual type a symbolic link points to. */
|
|
||||||
void setLinkType (mode_t type) { mLinkType = type; }
|
|
||||||
|
|
||||||
mode_t linkType() const { return mLinkType; }
|
|
||||||
|
|
||||||
/** No descriptions */
|
|
||||||
void setFilename(const TQString& fn)
|
|
||||||
{ mFilename = fn; }
|
|
||||||
|
|
||||||
TQString filename() const
|
|
||||||
{ return mFilename; }
|
|
||||||
|
|
||||||
/** Returns a UDSEntry describing the file.
|
|
||||||
The UDSEntry is generated from the sftp file attributes. */
|
|
||||||
TDEIO::UDSEntry entry();
|
|
||||||
|
|
||||||
/** Use to output the file attributes to a sftp packet
|
|
||||||
This will only write the sftp ATTR structure to the stream.
|
|
||||||
It will never write the filename and longname because the client
|
|
||||||
never sends those to the server. */
|
|
||||||
friend TQDataStream& operator<< (TQDataStream&, const sftpFileAttr&);
|
|
||||||
|
|
||||||
/** Use to read a file attribute from a sftp packet.
|
|
||||||
Read this carefully! If the DirAttrs flag is true, this will
|
|
||||||
read the filename, longname, and file attributes from the stream.
|
|
||||||
This is for use with listing directories.
|
|
||||||
If the DirAttrs flag is false, this will only read file attributes
|
|
||||||
from the stream.
|
|
||||||
BY DEFAULT, A NEW INSTANCE HAS DirAttrs == false */
|
|
||||||
friend TQDataStream& operator>> (TQDataStream&, sftpFileAttr&);
|
|
||||||
|
|
||||||
/** Parse longname for the owner and group names. */
|
|
||||||
void getUserGroupNames();
|
|
||||||
|
|
||||||
/** Sets the DirAttrs flag. This flag affects how the >> operator works on data streams. */
|
|
||||||
void setDirAttrsFlag(bool flag){ mDirAttrs = flag; }
|
|
||||||
|
|
||||||
/** Gets the DirAttrs flag. */
|
|
||||||
bool getDirAttrsFlag() const { return mDirAttrs; }
|
|
||||||
|
|
||||||
friend kdbgstream& operator<< (kdbgstream& s, sftpFileAttr& a);
|
|
||||||
friend kndbgstream& operator<< (kndbgstream& s, sftpFileAttr& a);
|
|
||||||
|
|
||||||
/** Returns the file type as determined from the file permissions */
|
|
||||||
mode_t fileType() const;
|
|
||||||
|
|
||||||
/** Set the encoding of the remote file system */
|
|
||||||
void setEncoding( KRemoteEncoding* encoding );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue