2001-02-23 18:21:44 +00:00
|
|
|
/*
|
2004-04-27 12:31:57 +00:00
|
|
|
* psftp.c: (platform-independent) front end for PSFTP.
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2001-02-24 12:02:35 +00:00
|
|
|
#include <stdarg.h>
|
2001-02-23 18:21:44 +00:00
|
|
|
#include <assert.h>
|
2001-08-26 11:35:11 +00:00
|
|
|
#include <limits.h>
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
#include "putty.h"
|
2003-08-24 12:47:46 +00:00
|
|
|
#include "psftp.h"
|
2001-02-24 16:08:56 +00:00
|
|
|
#include "storage.h"
|
|
|
|
#include "ssh.h"
|
2021-04-22 16:58:40 +00:00
|
|
|
#include "ssh/sftp.h"
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2009-04-23 17:39:36 +00:00
|
|
|
const char *const appname = "PSFTP";
|
|
|
|
|
2001-08-25 17:09:23 +00:00
|
|
|
/*
|
|
|
|
* Since SFTP is a request-response oriented protocol, it requires
|
|
|
|
* no buffer management: when we send data, we stop and wait for an
|
|
|
|
* acknowledgement _anyway_, and so we can't possibly overfill our
|
|
|
|
* send buffer.
|
|
|
|
*/
|
|
|
|
|
2001-12-13 18:42:34 +00:00
|
|
|
static int psftp_connect(char *userhost, char *user, int portnumber);
|
2002-02-27 22:30:57 +00:00
|
|
|
static int do_sftp_init(void);
|
2018-11-03 08:25:28 +00:00
|
|
|
static void do_sftp_cleanup(void);
|
2001-12-13 18:42:34 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* sftp client state.
|
|
|
|
*/
|
|
|
|
|
2020-02-02 10:00:43 +00:00
|
|
|
static char *pwd, *homedir;
|
2019-07-06 16:44:15 +00:00
|
|
|
static LogContext *psftp_logctx = NULL;
|
2018-09-11 15:23:38 +00:00
|
|
|
static Backend *backend;
|
2020-02-02 10:00:42 +00:00
|
|
|
static Conf *conf;
|
2020-02-02 10:00:43 +00:00
|
|
|
static bool sent_eof = false;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
/* ------------------------------------------------------------
|
|
|
|
* Seat vtable.
|
|
|
|
*/
|
|
|
|
|
2021-09-16 13:46:49 +00:00
|
|
|
static size_t psftp_output(Seat *, SeatOutputType type, const void *, size_t);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool psftp_eof(Seat *);
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
|
|
|
static const SeatVtable psftp_seat_vt = {
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.output = psftp_output,
|
|
|
|
.eof = psftp_eof,
|
New Seat callback, seat_sent().
This is used to notify the Seat that some data has been cleared from
the backend's outgoing data buffer. In other words, it notifies the
Seat that it might be worth calling backend_sendbuffer() again.
We've never needed this before, because until now, Seats have always
been the 'main program' part of the application, meaning they were
also in control of the event loop. So they've been able to call
backend_sendbuffer() proactively, every time they go round the event
loop, instead of having to wait for a callback.
But now, the SSH proxy is the first example of a Seat without
privileged access to the event loop, so it has no way to find out that
the backend's sendbuffer has got smaller. And without that, it can't
pass that notification on to plug_sent, to unblock in turn whatever
the proxied connection might have been waiting to send.
In fact, before this commit, sshproxy.c never called plug_sent at all.
As a result, large data uploads over an SSH jump host would hang
forever as soon as the outgoing buffer filled up for the first time:
the main backend (to which sshproxy.c was acting as a Socket) would
carefully stop filling up the buffer, and then never receive the call
to plug_sent that would cause it to start again.
The new callback is ignored everywhere except in sshproxy.c. It might
be a good idea to remove backend_sendbuffer() entirely and convert all
previous uses of it into non-empty implementations of this callback,
so that we've only got one system; but for the moment, I haven't done
that.
2021-06-27 12:52:48 +00:00
|
|
|
.sent = nullseat_sent,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.get_userpass_input = filexfer_get_userpass_input,
|
2021-09-12 10:48:42 +00:00
|
|
|
.notify_session_started = nullseat_notify_session_started,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.notify_remote_exit = nullseat_notify_remote_exit,
|
2021-05-22 11:47:51 +00:00
|
|
|
.notify_remote_disconnect = nullseat_notify_remote_disconnect,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.connection_fatal = console_connection_fatal,
|
|
|
|
.update_specials_menu = nullseat_update_specials_menu,
|
|
|
|
.get_ttymode = nullseat_get_ttymode,
|
|
|
|
.set_busy_status = nullseat_set_busy_status,
|
Reorganise host key checking and confirmation.
Previously, checking the host key against the persistent cache managed
by the storage.h API was done as part of the seat_verify_ssh_host_key
method, i.e. separately by each Seat.
Now that check is done by verify_ssh_host_key(), which is a new
function in ssh/common.c that centralises all the parts of host key
checking that don't need an interactive prompt. It subsumes the
previous verify_ssh_manual_host_key() that checked against the Conf,
and it does the check against the storage API that each Seat was
previously doing separately. If it can't confirm or definitively
reject the host key by itself, _then_ it calls out to the Seat, once
an interactive prompt is definitely needed.
The main point of doing this is so that when SshProxy forwards a Seat
call from the proxy SSH connection to the primary Seat, it won't print
an announcement of which connection is involved unless it's actually
going to do something interactive. (Not that we're printing those
announcements _yet_ anyway, but this is a piece of groundwork that
works towards doing so.)
But while I'm at it, I've also taken the opportunity to clean things
up a bit by renaming functions sensibly. Previously we had three very
similarly named functions verify_ssh_manual_host_key(), SeatVtable's
'verify_ssh_host_key' method, and verify_host_key() in storage.h. Now
the Seat method is called 'confirm' rather than 'verify' (since its
job is now always to print an interactive prompt, so it looks more
like the other confirm_foo methods), and the storage.h function is
called check_stored_host_key(), which goes better with store_host_key
and avoids having too many functions with similar names. And the
'manual' function is subsumed into the new centralised code, so
there's now just *one* host key function with 'verify' in the name.
Several functions are reindented in this commit. Best viewed with
whitespace changes ignored.
2021-10-25 17:12:17 +00:00
|
|
|
.confirm_ssh_host_key = console_confirm_ssh_host_key,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.confirm_weak_crypto_primitive = console_confirm_weak_crypto_primitive,
|
|
|
|
.confirm_weak_cached_hostkey = console_confirm_weak_cached_hostkey,
|
|
|
|
.is_utf8 = nullseat_is_never_utf8,
|
|
|
|
.echoedit_update = nullseat_echoedit_update,
|
|
|
|
.get_x_display = nullseat_get_x_display,
|
|
|
|
.get_windowid = nullseat_get_windowid,
|
|
|
|
.get_window_pixel_size = nullseat_get_window_pixel_size,
|
|
|
|
.stripctrl_new = console_stripctrl_new,
|
2021-09-12 08:52:46 +00:00
|
|
|
.set_trust_status = nullseat_set_trust_status,
|
|
|
|
.can_set_trust_status = nullseat_can_set_trust_status_yes,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.verbose = cmdline_seat_verbose,
|
|
|
|
.interactive = nullseat_interactive_yes,
|
|
|
|
.get_cursor_position = nullseat_get_cursor_position,
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
};
|
|
|
|
static Seat psftp_seat[1] = {{ &psftp_seat_vt }};
|
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* A nasty loop macro that lets me get an escape-sequence sanitised
|
|
|
|
* version of a string for display, and free it automatically
|
|
|
|
* afterwards.
|
|
|
|
*/
|
2019-03-09 16:03:40 +00:00
|
|
|
static StripCtrlChars *string_scc;
|
|
|
|
#define with_stripctrl(varname, input) \
|
|
|
|
for (char *varname = stripctrl_string(string_scc, input); varname; \
|
2019-02-20 07:09:10 +00:00
|
|
|
sfree(varname), varname = NULL)
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Manage sending requests and waiting for replies.
|
|
|
|
*/
|
|
|
|
struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
|
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
|
|
|
struct sftp_request *rreq;
|
|
|
|
|
|
|
|
sftp_register(req);
|
|
|
|
pktin = sftp_recv();
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
if (pktin == NULL) {
|
|
|
|
seat_connection_fatal(
|
|
|
|
psftp_seat, "did not receive SFTP response packet from server");
|
|
|
|
}
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
rreq = sftp_find_request(pktin);
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
if (rreq != req) {
|
|
|
|
seat_connection_fatal(
|
|
|
|
psftp_seat,
|
|
|
|
"unable to understand SFTP response packet from server: %s",
|
|
|
|
fxp_error());
|
|
|
|
}
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
return pktin;
|
|
|
|
}
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Higher-level helper functions used in commands.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2001-02-24 12:02:35 +00:00
|
|
|
* Attempt to canonify a pathname starting from the pwd. If
|
|
|
|
* canonification fails, at least fall back to returning a _valid_
|
|
|
|
* pathname (though it may be ugly, eg /home/simon/../foobar).
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
char *canonify(const char *name)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-24 12:02:35 +00:00
|
|
|
char *fullname, *canonname;
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2001-02-24 12:02:35 +00:00
|
|
|
if (name[0] == '/') {
|
2019-09-08 19:29:00 +00:00
|
|
|
fullname = dupstr(name);
|
2001-02-24 12:02:35 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
const char *slash;
|
|
|
|
if (pwd[strlen(pwd) - 1] == '/')
|
|
|
|
slash = "";
|
|
|
|
else
|
|
|
|
slash = "/";
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
fullname = dupcat(pwd, slash, name);
|
2001-02-24 12:02:35 +00:00
|
|
|
}
|
2001-02-24 16:08:56 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_realpath_send(fullname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
canonname = fxp_realpath_recv(pktin, req);
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2001-02-24 12:02:35 +00:00
|
|
|
if (canonname) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(fullname);
|
|
|
|
return canonname;
|
2001-02-26 16:39:15 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Attempt number 2. Some FXP_REALPATH implementations
|
|
|
|
* (glibc-based ones, in particular) require the _whole_
|
|
|
|
* path to point to something that exists, whereas others
|
|
|
|
* (BSD-based) only require all but the last component to
|
|
|
|
* exist. So if the first call failed, we should strip off
|
|
|
|
* everything from the last slash onwards and try again,
|
|
|
|
* then put the final component back on.
|
|
|
|
*
|
|
|
|
* Special cases:
|
|
|
|
*
|
|
|
|
* - if the last component is "/." or "/..", then we don't
|
|
|
|
* bother trying this because there's no way it can work.
|
|
|
|
*
|
|
|
|
* - if the thing actually ends with a "/", we remove it
|
|
|
|
* before we start. Except if the string is "/" itself
|
|
|
|
* (although I can't see why we'd have got here if so,
|
|
|
|
* because surely "/" would have worked the first
|
|
|
|
* time?), in which case we don't bother.
|
|
|
|
*
|
|
|
|
* - if there's no slash in the string at all, give up in
|
|
|
|
* confusion (we expect at least one because of the way
|
|
|
|
* we constructed the string).
|
|
|
|
*/
|
|
|
|
|
|
|
|
int i;
|
|
|
|
char *returnname;
|
|
|
|
|
|
|
|
i = strlen(fullname);
|
|
|
|
if (i > 2 && fullname[i - 1] == '/')
|
|
|
|
fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */
|
|
|
|
while (i > 0 && fullname[--i] != '/');
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Give up on special cases.
|
|
|
|
*/
|
|
|
|
if (fullname[i] != '/' || /* no slash at all */
|
|
|
|
!strcmp(fullname + i, "/.") || /* ends in /. */
|
|
|
|
!strcmp(fullname + i, "/..") || /* ends in /.. */
|
|
|
|
!strcmp(fullname, "/")) {
|
|
|
|
return fullname;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now i points at the slash. Deal with the final special
|
|
|
|
* case i==0 (ie the whole path was "/nonexistentfile").
|
|
|
|
*/
|
|
|
|
fullname[i] = '\0'; /* separate the string */
|
|
|
|
if (i == 0) {
|
|
|
|
req = fxp_realpath_send("/");
|
|
|
|
} else {
|
|
|
|
req = fxp_realpath_send(fullname);
|
|
|
|
}
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
canonname = fxp_realpath_recv(pktin, req);
|
|
|
|
|
|
|
|
if (!canonname) {
|
|
|
|
/* Even that failed. Restore our best guess at the
|
|
|
|
* constructed filename and give up */
|
|
|
|
fullname[i] = '/'; /* restore slash and last component */
|
|
|
|
return fullname;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a canonical name for all but the last path
|
|
|
|
* component. Concatenate the last component and return.
|
|
|
|
*/
|
|
|
|
returnname = dupcat(canonname,
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
(strendswith(canonname, "/") ? "" : "/"),
|
|
|
|
fullname + i + 1);
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(fullname);
|
|
|
|
sfree(canonname);
|
|
|
|
return returnname;
|
2001-02-26 16:39:15 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
static int bare_name_compare(const void *av, const void *bv)
|
2001-09-09 16:31:26 +00:00
|
|
|
{
|
2004-12-16 16:37:37 +00:00
|
|
|
const char **a = (const char **) av;
|
|
|
|
const char **b = (const char **) bv;
|
|
|
|
return strcmp(*a, *b);
|
2001-09-09 16:31:26 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 16:43:19 +00:00
|
|
|
static void not_connected(void)
|
|
|
|
{
|
|
|
|
printf("psftp: not connected to a host; use \"open host.name\"\n");
|
|
|
|
}
|
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* The meat of the `get' and `put' commands.
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool sftp_get_file(char *fname, char *outfname, bool recurse, bool restart)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
struct fxp_handle *fh;
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2003-09-27 17:52:34 +00:00
|
|
|
struct fxp_xfer *xfer;
|
2018-10-26 22:08:58 +00:00
|
|
|
uint64_t offset;
|
2006-08-12 15:20:19 +00:00
|
|
|
WFile *file;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool toret, shown_err = false;
|
2011-08-11 17:59:30 +00:00
|
|
|
struct fxp_attrs attrs;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
/*
|
|
|
|
* In recursive mode, see if we're dealing with a directory.
|
|
|
|
* (If we're not in recursive mode, we need not even check: the
|
|
|
|
* subsequent FXP_OPEN will return a usable error message.)
|
|
|
|
*/
|
2004-12-30 13:51:37 +00:00
|
|
|
if (recurse) {
|
2019-09-08 19:29:00 +00:00
|
|
|
bool result;
|
2001-12-13 18:42:34 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_stat_send(fname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
result = fxp_stat_recv(pktin, req, &attrs);
|
|
|
|
|
|
|
|
if (result &&
|
|
|
|
(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
|
|
|
|
(attrs.permissions & 0040000)) {
|
|
|
|
|
|
|
|
struct fxp_handle *dirhandle;
|
|
|
|
size_t nnames, namesize;
|
|
|
|
struct fxp_name **ournames;
|
|
|
|
struct fxp_names *names;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First, attempt to create the destination directory,
|
|
|
|
* unless it already exists.
|
|
|
|
*/
|
|
|
|
if (file_type(outfname) != FILE_TYPE_DIRECTORY &&
|
|
|
|
!create_directory(outfname)) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, outfname)
|
|
|
|
printf("%s: Cannot create directory\n", san);
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Now get the list of filenames in the remote
|
|
|
|
* directory.
|
|
|
|
*/
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_opendir_send(fname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
dirhandle = fxp_opendir_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!dirhandle) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, fname)
|
|
|
|
printf("%s: unable to open directory: %s\n",
|
|
|
|
san, fxp_error());
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nnames = namesize = 0;
|
|
|
|
ournames = NULL;
|
|
|
|
while (1) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
req = fxp_readdir_send(dirhandle);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
names = fxp_readdir_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (names == NULL) {
|
|
|
|
if (fxp_error_type() == SSH_FX_EOF)
|
|
|
|
break;
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, fname)
|
|
|
|
printf("%s: reading directory: %s\n",
|
|
|
|
san, fxp_error());
|
2013-07-11 17:24:44 +00:00
|
|
|
|
|
|
|
req = fxp_close_send(dirhandle);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fxp_close_recv(pktin, req);
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(ournames);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (names->nnames == 0) {
|
|
|
|
fxp_free_names(names);
|
|
|
|
break;
|
|
|
|
}
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarrayn(ournames, namesize, nnames, names->nnames);
|
2019-09-08 19:29:00 +00:00
|
|
|
for (i = 0; i < names->nnames; i++)
|
|
|
|
if (strcmp(names->names[i].filename, ".") &&
|
|
|
|
strcmp(names->names[i].filename, "..")) {
|
|
|
|
if (!vet_filename(names->names[i].filename)) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, names->names[i].filename)
|
|
|
|
printf("ignoring potentially dangerous server-"
|
|
|
|
"supplied filename '%s'\n", san);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
|
|
|
ournames[nnames++] =
|
|
|
|
fxp_dup_name(&names->names[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fxp_free_names(names);
|
|
|
|
}
|
|
|
|
req = fxp_close_send(dirhandle);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_close_recv(pktin, req);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sort the names into a clear order. This ought to
|
|
|
|
* make things more predictable when we're doing a
|
|
|
|
* reget of the same directory, just in case two
|
|
|
|
* readdirs on the same remote directory return a
|
|
|
|
* different order.
|
|
|
|
*/
|
2013-07-11 17:24:39 +00:00
|
|
|
if (nnames > 0)
|
|
|
|
qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* If we're in restart mode, find the last filename on
|
|
|
|
* this list that already exists. We may have to do a
|
|
|
|
* reget on _that_ file, but shouldn't have to do
|
|
|
|
* anything on the previous files.
|
|
|
|
*
|
|
|
|
* If none of them exists, of course, we start at 0.
|
|
|
|
*/
|
|
|
|
i = 0;
|
2007-04-02 08:44:00 +00:00
|
|
|
if (restart) {
|
|
|
|
while (i < nnames) {
|
|
|
|
char *nextoutfname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool nonexistent;
|
2013-07-11 17:24:10 +00:00
|
|
|
nextoutfname = dir_file_cat(outfname,
|
|
|
|
ournames[i]->filename);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
nonexistent = (file_type(nextoutfname) ==
|
|
|
|
FILE_TYPE_NONEXISTENT);
|
2007-04-02 08:44:00 +00:00
|
|
|
sfree(nextoutfname);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
if (nonexistent)
|
2007-04-02 08:44:00 +00:00
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (i > 0)
|
|
|
|
i--;
|
|
|
|
}
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Now we're ready to recurse. Starting at ournames[i]
|
|
|
|
* and continuing on to the end of the list, we
|
|
|
|
* construct a new source and target file name, and
|
|
|
|
* call sftp_get_file again.
|
|
|
|
*/
|
|
|
|
for (; i < nnames; i++) {
|
|
|
|
char *nextfname, *nextoutfname;
|
|
|
|
bool retd;
|
|
|
|
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
nextfname = dupcat(fname, "/", ournames[i]->filename);
|
2013-07-11 17:24:10 +00:00
|
|
|
nextoutfname = dir_file_cat(outfname, ournames[i]->filename);
|
2019-09-08 19:29:00 +00:00
|
|
|
retd = sftp_get_file(
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
nextfname, nextoutfname, recurse, restart);
|
2019-09-08 19:29:00 +00:00
|
|
|
restart = false; /* after first partial file, do full */
|
|
|
|
sfree(nextoutfname);
|
|
|
|
sfree(nextfname);
|
|
|
|
if (!retd) {
|
|
|
|
for (i = 0; i < nnames; i++) {
|
|
|
|
fxp_free_name(ournames[i]);
|
|
|
|
}
|
|
|
|
sfree(ournames);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Done this recursion level. Free everything.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < nnames; i++) {
|
|
|
|
fxp_free_name(ournames[i]);
|
|
|
|
}
|
|
|
|
sfree(ournames);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_stat_send(fname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
if (!fxp_stat_recv(pktin, req, &attrs))
|
2011-08-11 17:59:30 +00:00
|
|
|
attrs.flags = 0;
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_open_send(fname, SSH_FXF_READ, NULL);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fh = fxp_open_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
if (!fh) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, fname)
|
|
|
|
printf("%s: open for read: %s\n", san, fxp_error());
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2001-08-26 11:35:11 +00:00
|
|
|
|
|
|
|
if (restart) {
|
2019-09-08 19:29:00 +00:00
|
|
|
file = open_existing_wfile(outfname, NULL);
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
file = open_new_file(outfname, GET_PERMISSIONS(attrs, -1));
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
2006-08-12 15:20:19 +00:00
|
|
|
if (!file) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, outfname)
|
|
|
|
printf("local: unable to open %s\n", san);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_close_send(fh);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_close_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
if (restart) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (seek_file(file, 0, FROM_END) == -1) {
|
|
|
|
close_wfile(file);
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, outfname)
|
|
|
|
printf("reget: cannot restart %s - file too large\n", san);
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_close_send(fh);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_close_recv(pktin, req);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = get_file_posn(file);
|
|
|
|
printf("reget: restarting at file position %"PRIu64"\n", offset);
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
offset = 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, fname) {
|
|
|
|
with_stripctrl(sano, outfname)
|
|
|
|
printf("remote:%s => local:%s\n", san, sano);
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: we can use FXP_FSTAT here to get the file size, and
|
|
|
|
* thus put up a progress bar.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
toret = true;
|
2003-09-27 17:52:34 +00:00
|
|
|
xfer = xfer_download_init(fh, offset);
|
2003-09-28 14:24:01 +00:00
|
|
|
while (!xfer_done(xfer)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
void *vbuf;
|
|
|
|
int retd, len;
|
|
|
|
int wpos, wlen;
|
|
|
|
|
|
|
|
xfer_download_queue(xfer);
|
|
|
|
pktin = sftp_recv();
|
|
|
|
retd = xfer_download_gotpkt(xfer, pktin);
|
|
|
|
if (retd <= 0) {
|
|
|
|
if (!shown_err) {
|
|
|
|
printf("error while reading: %s\n", fxp_error());
|
|
|
|
shown_err = true;
|
|
|
|
}
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
if (retd == INT_MIN) /* pktin not even freed */
|
2013-07-11 17:24:53 +00:00
|
|
|
sfree(pktin);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
toret = false;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (xfer_download_data(xfer, &vbuf, &len)) {
|
|
|
|
unsigned char *buf = (unsigned char *)vbuf;
|
|
|
|
|
|
|
|
wpos = 0;
|
|
|
|
while (wpos < len) {
|
|
|
|
wlen = write_to_file(file, buf + wpos, len - wpos);
|
|
|
|
if (wlen <= 0) {
|
|
|
|
printf("error while writing local file\n");
|
|
|
|
toret = false;
|
|
|
|
xfer_set_error(xfer);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wpos += wlen;
|
|
|
|
}
|
|
|
|
if (wpos < len) { /* we had an error */
|
|
|
|
toret = false;
|
|
|
|
xfer_set_error(xfer);
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(vbuf);
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2003-09-27 17:52:34 +00:00
|
|
|
xfer_cleanup(xfer);
|
|
|
|
|
2006-08-12 15:20:19 +00:00
|
|
|
close_wfile(file);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_close_send(fh);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fxp_close_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return toret;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool sftp_put_file(char *fname, char *outfname, bool recurse, bool restart)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
struct fxp_handle *fh;
|
2003-09-28 14:24:01 +00:00
|
|
|
struct fxp_xfer *xfer;
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2018-10-26 22:08:58 +00:00
|
|
|
uint64_t offset;
|
2006-08-12 15:20:19 +00:00
|
|
|
RFile *file;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool err = false, eof;
|
2011-08-11 17:59:30 +00:00
|
|
|
struct fxp_attrs attrs;
|
|
|
|
long permissions;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
/*
|
|
|
|
* In recursive mode, see if we're dealing with a directory.
|
|
|
|
* (If we're not in recursive mode, we need not even check: the
|
|
|
|
* subsequent fopen will return an error message.)
|
|
|
|
*/
|
2004-12-30 13:51:37 +00:00
|
|
|
if (recurse && file_type(fname) == FILE_TYPE_DIRECTORY) {
|
2019-09-08 19:29:00 +00:00
|
|
|
bool result;
|
|
|
|
size_t nnames, namesize;
|
|
|
|
char *name, **ournames;
|
2018-12-27 16:52:23 +00:00
|
|
|
const char *opendir_err;
|
2019-09-08 19:29:00 +00:00
|
|
|
DirHandle *dh;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
size_t i;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* First, attempt to create the destination directory,
|
|
|
|
* unless it already exists.
|
|
|
|
*/
|
|
|
|
req = fxp_stat_send(outfname);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
result = fxp_stat_recv(pktin, req, &attrs);
|
|
|
|
if (!result ||
|
|
|
|
!(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
|
|
|
|
!(attrs.permissions & 0040000)) {
|
|
|
|
req = fxp_mkdir_send(outfname, NULL);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
result = fxp_mkdir_recv(pktin, req);
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
printf("%s: create directory: %s\n",
|
|
|
|
outfname, fxp_error());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now get the list of filenames in the local directory.
|
|
|
|
*/
|
|
|
|
nnames = namesize = 0;
|
|
|
|
ournames = NULL;
|
|
|
|
|
|
|
|
dh = open_directory(fname, &opendir_err);
|
|
|
|
if (!dh) {
|
|
|
|
printf("%s: unable to open directory: %s\n", fname, opendir_err);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while ((name = read_filename(dh)) != NULL) {
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarray(ournames, namesize, nnames);
|
2019-09-08 19:29:00 +00:00
|
|
|
ournames[nnames++] = name;
|
|
|
|
}
|
|
|
|
close_directory(dh);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sort the names into a clear order. This ought to make
|
|
|
|
* things more predictable when we're doing a reput of the
|
|
|
|
* same directory, just in case two readdirs on the same
|
|
|
|
* local directory return a different order.
|
|
|
|
*/
|
2013-07-11 17:24:39 +00:00
|
|
|
if (nnames > 0)
|
|
|
|
qsort(ournames, nnames, sizeof(*ournames), bare_name_compare);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* If we're in restart mode, find the last filename on this
|
|
|
|
* list that already exists. We may have to do a reput on
|
|
|
|
* _that_ file, but shouldn't have to do anything on the
|
|
|
|
* previous files.
|
|
|
|
*
|
|
|
|
* If none of them exists, of course, we start at 0.
|
|
|
|
*/
|
|
|
|
i = 0;
|
2007-04-02 08:44:00 +00:00
|
|
|
if (restart) {
|
|
|
|
while (i < nnames) {
|
|
|
|
char *nextoutfname;
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
nextoutfname = dupcat(outfname, "/", ournames[i]);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_stat_send(nextoutfname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_stat_recv(pktin, req, &attrs);
|
2007-04-02 08:44:00 +00:00
|
|
|
sfree(nextoutfname);
|
|
|
|
if (!result)
|
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (i > 0)
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we're ready to recurse. Starting at ournames[i]
|
2019-09-08 19:29:00 +00:00
|
|
|
* and continuing on to the end of the list, we
|
|
|
|
* construct a new source and target file name, and
|
|
|
|
* call sftp_put_file again.
|
|
|
|
*/
|
|
|
|
for (; i < nnames; i++) {
|
|
|
|
char *nextfname, *nextoutfname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool retd;
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2013-07-11 17:24:10 +00:00
|
|
|
nextfname = dir_file_cat(fname, ournames[i]);
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
nextoutfname = dupcat(outfname, "/", ournames[i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
retd = sftp_put_file(nextfname, nextoutfname, recurse, restart);
|
|
|
|
restart = false; /* after first partial file, do full */
|
|
|
|
sfree(nextoutfname);
|
|
|
|
sfree(nextfname);
|
|
|
|
if (!retd) {
|
|
|
|
for (size_t i = 0; i < nnames; i++) {
|
|
|
|
sfree(ournames[i]);
|
|
|
|
}
|
|
|
|
sfree(ournames);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Done this recursion level. Free everything.
|
|
|
|
*/
|
|
|
|
for (size_t i = 0; i < nnames; i++) {
|
|
|
|
sfree(ournames[i]);
|
|
|
|
}
|
|
|
|
sfree(ournames);
|
|
|
|
|
|
|
|
return true;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2011-08-11 17:59:30 +00:00
|
|
|
file = open_existing_file(fname, NULL, NULL, NULL, &permissions);
|
2006-08-12 15:20:19 +00:00
|
|
|
if (!file) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("local: unable to open %s\n", fname);
|
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2011-08-11 17:59:30 +00:00
|
|
|
attrs.flags = 0;
|
|
|
|
PUT_PERMISSIONS(attrs, permissions);
|
2001-08-26 11:35:11 +00:00
|
|
|
if (restart) {
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_open_send(outfname, SSH_FXF_WRITE, &attrs);
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_open_send(outfname,
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
|
|
|
|
&attrs);
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fh = fxp_open_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
if (!fh) {
|
2019-09-08 19:29:00 +00:00
|
|
|
close_rfile(file);
|
|
|
|
printf("%s: open for write: %s\n", outfname, fxp_error());
|
|
|
|
return false;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
if (restart) {
|
2019-09-08 19:29:00 +00:00
|
|
|
struct fxp_attrs attrs;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool retd;
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_fstat_send(fh);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
retd = fxp_fstat_recv(pktin, req, &attrs);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!retd) {
|
|
|
|
printf("read size of %s: %s\n", outfname, fxp_error());
|
|
|
|
err = true;
|
2014-12-20 16:53:01 +00:00
|
|
|
goto cleanup;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
if (!(attrs.flags & SSH_FILEXFER_ATTR_SIZE)) {
|
|
|
|
printf("read size of %s: size was not given\n", outfname);
|
|
|
|
err = true;
|
2014-12-20 16:53:01 +00:00
|
|
|
goto cleanup;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
offset = attrs.size;
|
|
|
|
printf("reput: restarting at file position %"PRIu64"\n", offset);
|
2006-08-12 15:20:19 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (seek_file((WFile *)file, offset, FROM_START) != 0)
|
|
|
|
seek_file((WFile *)file, 0, FROM_END); /* *shrug* */
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2018-10-26 22:08:58 +00:00
|
|
|
offset = 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
printf("local:%s => remote:%s\n", fname, outfname);
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: we can use FXP_FSTAT here to get the file size, and
|
|
|
|
* thus put up a progress bar.
|
|
|
|
*/
|
2003-09-28 14:24:01 +00:00
|
|
|
xfer = xfer_upload_init(fh, offset);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
eof = false;
|
2003-09-28 14:24:01 +00:00
|
|
|
while ((!err && !eof) || !xfer_done(xfer)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char buffer[4096];
|
|
|
|
int len, ret;
|
|
|
|
|
|
|
|
while (xfer_upload_ready(xfer) && !err && !eof) {
|
|
|
|
len = read_from_file(file, buffer, sizeof(buffer));
|
|
|
|
if (len == -1) {
|
|
|
|
printf("error while reading local file\n");
|
|
|
|
err = true;
|
|
|
|
} else if (len == 0) {
|
|
|
|
eof = true;
|
|
|
|
} else {
|
|
|
|
xfer_upload_data(xfer, buffer, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix a deadlock in SFTP upload.
I tried to do an SFTP upload through connection sharing the other day
and found that pscp sent some data and then hung. Now I debug it, what
seems to have happened was that we were looping in sftp_recv() waiting
for an SFTP packet from the remote, but we didn't have any outstanding
SFTP requests that the remote was going to reply to. Checking further,
xfer_upload_ready() reported true, so we _could_ have sent something -
but the logic in the upload loop had a hole through which we managed
to get into 'waiting for a packet' state.
I think what must have happened is that xfer_upload_ready() reported
false so that we entered sftp_recv(), but then the event loop inside
sftp_recv() ran a toplevel callback that made xfer_upload_ready()
return true. So, the fix: sftp_recv() is our last-ditch fallback, and
we always try emptying our callback queue and rechecking upload_ready
before we resort to waiting for a remote packet.
This not only fixes the hang I observed: it also hugely improves the
upload speed. My guess is that the bug must have been preventing us
from filling our outgoing request pipeline a _lot_ - but I didn't
notice it until the one time the queue accidentally ended up empty,
rather than just sparse enough to make transfers slow.
Annoyingly, I actually considered this fix back when I was trying to
fix the proftpd issue mentioned in commit cd97b7e7e. I decided fixing
ssh_sendbuffer() was a better idea. In fact it would have been an even
better idea to do both! Oh well, better late than never.
2020-02-25 21:27:34 +00:00
|
|
|
if (toplevel_callback_pending() && !err && !eof) {
|
|
|
|
/* If we have pending callbacks, they might make
|
|
|
|
* xfer_upload_ready start to return true. So we should
|
|
|
|
* run them and then re-check xfer_upload_ready, before
|
|
|
|
* we go as far as waiting for an entire packet to
|
|
|
|
* arrive. */
|
|
|
|
run_toplevel_callbacks();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!xfer_done(xfer)) {
|
|
|
|
pktin = sftp_recv();
|
|
|
|
ret = xfer_upload_gotpkt(xfer, pktin);
|
|
|
|
if (ret <= 0) {
|
2013-07-11 17:24:53 +00:00
|
|
|
if (ret == INT_MIN) /* pktin not even freed */
|
|
|
|
sfree(pktin);
|
|
|
|
if (!err) {
|
|
|
|
printf("error while writing: %s\n", fxp_error());
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
err = true;
|
2013-07-11 17:24:53 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:24:01 +00:00
|
|
|
xfer_cleanup(xfer);
|
|
|
|
|
2014-12-20 16:53:01 +00:00
|
|
|
cleanup:
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_close_send(fh);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
2016-12-29 11:25:34 +00:00
|
|
|
if (!fxp_close_recv(pktin, req)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!err) {
|
|
|
|
printf("error while closing: %s", fxp_error());
|
|
|
|
err = true;
|
|
|
|
}
|
2016-12-28 14:34:53 +00:00
|
|
|
}
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2006-08-12 15:20:19 +00:00
|
|
|
close_rfile(file);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return !err;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
2004-12-30 13:51:37 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* A remote wildcard matcher, providing a similar interface to the
|
|
|
|
* local one in psftp.h.
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct SftpWildcardMatcher {
|
|
|
|
struct fxp_handle *dirh;
|
|
|
|
struct fxp_names *names;
|
|
|
|
int namepos;
|
|
|
|
char *wildcard, *prefix;
|
|
|
|
} SftpWildcardMatcher;
|
|
|
|
|
|
|
|
SftpWildcardMatcher *sftp_begin_wildcard_matching(char *name)
|
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2004-12-30 13:51:37 +00:00
|
|
|
char *wildcard;
|
|
|
|
char *unwcdir, *tmpdir, *cdir;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int len;
|
|
|
|
bool check;
|
2004-12-30 13:51:37 +00:00
|
|
|
SftpWildcardMatcher *swcm;
|
|
|
|
struct fxp_handle *dirh;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't handle multi-level wildcards; so we expect to find
|
|
|
|
* a fully specified directory part, followed by a wildcard
|
|
|
|
* after that.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
wildcard = stripslashes(name, false);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
|
|
|
unwcdir = dupstr(name);
|
|
|
|
len = wildcard - name;
|
|
|
|
unwcdir[len] = '\0';
|
|
|
|
if (len > 0 && unwcdir[len-1] == '/')
|
2019-09-08 19:29:00 +00:00
|
|
|
unwcdir[len-1] = '\0';
|
2004-12-30 13:51:37 +00:00
|
|
|
tmpdir = snewn(1 + len, char);
|
|
|
|
check = wc_unescape(tmpdir, unwcdir);
|
|
|
|
sfree(tmpdir);
|
|
|
|
|
|
|
|
if (!check) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("Multiple-level wildcards are not supported\n");
|
|
|
|
sfree(unwcdir);
|
|
|
|
return NULL;
|
2004-12-30 13:51:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cdir = canonify(unwcdir);
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_opendir_send(cdir);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
dirh = fxp_opendir_recv(pktin, req);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
|
|
|
if (dirh) {
|
2019-09-08 19:29:00 +00:00
|
|
|
swcm = snew(SftpWildcardMatcher);
|
|
|
|
swcm->dirh = dirh;
|
|
|
|
swcm->names = NULL;
|
|
|
|
swcm->wildcard = dupstr(wildcard);
|
|
|
|
swcm->prefix = unwcdir;
|
2004-12-30 13:51:37 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("Unable to open %s: %s\n", cdir, fxp_error());
|
|
|
|
swcm = NULL;
|
|
|
|
sfree(unwcdir);
|
2004-12-30 13:51:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sfree(cdir);
|
|
|
|
|
|
|
|
return swcm;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *sftp_wildcard_get_filename(SftpWildcardMatcher *swcm)
|
|
|
|
{
|
|
|
|
struct fxp_name *name;
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2004-12-30 13:51:37 +00:00
|
|
|
|
|
|
|
while (1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (swcm->names && swcm->namepos >= swcm->names->nnames) {
|
|
|
|
fxp_free_names(swcm->names);
|
|
|
|
swcm->names = NULL;
|
|
|
|
}
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!swcm->names) {
|
|
|
|
req = fxp_readdir_send(swcm->dirh);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
swcm->names = fxp_readdir_recv(pktin, req);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!swcm->names) {
|
|
|
|
if (fxp_error_type() != SSH_FX_EOF) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, swcm->prefix)
|
|
|
|
printf("%s: reading directory: %s\n",
|
|
|
|
san, fxp_error());
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
return NULL;
|
|
|
|
} else if (swcm->names->nnames == 0) {
|
2012-06-20 17:39:32 +00:00
|
|
|
/*
|
|
|
|
* Another failure mode which we treat as EOF is if
|
|
|
|
* the server reports success from FXP_READDIR but
|
|
|
|
* returns no actual names. This is unusual, since
|
|
|
|
* from most servers you'd expect at least "." and
|
|
|
|
* "..", but there's nothing forbidding a server from
|
|
|
|
* omitting those if it wants to.
|
|
|
|
*/
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
swcm->namepos = 0;
|
|
|
|
}
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
assert(swcm->names && swcm->namepos < swcm->names->nnames);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
name = &swcm->names->names[swcm->namepos++];
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!strcmp(name->filename, ".") || !strcmp(name->filename, ".."))
|
|
|
|
continue; /* expected bad filenames */
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!vet_filename(name->filename)) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, name->filename)
|
|
|
|
printf("ignoring potentially dangerous server-"
|
|
|
|
"supplied filename '%s'\n", san);
|
2019-09-08 19:29:00 +00:00
|
|
|
continue; /* unexpected bad filename */
|
|
|
|
}
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!wc_match(swcm->wildcard, name->filename))
|
|
|
|
continue; /* doesn't match the wildcard */
|
2004-12-30 13:51:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* We have a working filename. Return it.
|
|
|
|
*/
|
|
|
|
return dupprintf("%s%s%s", swcm->prefix,
|
|
|
|
(!swcm->prefix[0] ||
|
|
|
|
swcm->prefix[strlen(swcm->prefix)-1]=='/' ?
|
|
|
|
"" : "/"),
|
|
|
|
name->filename);
|
2004-12-30 13:51:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sftp_finish_wildcard_matching(SftpWildcardMatcher *swcm)
|
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2004-12-30 13:51:37 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_close_send(swcm->dirh);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fxp_close_recv(pktin, req);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
|
|
|
if (swcm->names)
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_free_names(swcm->names);
|
2004-12-30 13:51:37 +00:00
|
|
|
|
|
|
|
sfree(swcm->prefix);
|
|
|
|
sfree(swcm->wildcard);
|
|
|
|
|
|
|
|
sfree(swcm);
|
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
/*
|
|
|
|
* General function to match a potential wildcard in a filename
|
|
|
|
* argument and iterate over every matching file. Used in several
|
|
|
|
* PSFTP commands (rmdir, rm, chmod, mv).
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool wildcard_iterate(char *filename, bool (*func)(void *, char *), void *ctx)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
char *unwcfname, *newname, *cname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool is_wc, toret;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
|
|
|
unwcfname = snewn(strlen(filename)+1, char);
|
|
|
|
is_wc = !wc_unescape(unwcfname, filename);
|
|
|
|
|
|
|
|
if (is_wc) {
|
2019-09-08 19:29:00 +00:00
|
|
|
SftpWildcardMatcher *swcm = sftp_begin_wildcard_matching(filename);
|
|
|
|
bool matched = false;
|
|
|
|
sfree(unwcfname);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!swcm)
|
|
|
|
return false;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
toret = true;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
while ( (newname = sftp_wildcard_get_filename(swcm)) != NULL ) {
|
|
|
|
cname = canonify(newname);
|
2013-07-11 17:43:41 +00:00
|
|
|
sfree(newname);
|
2019-09-08 19:29:00 +00:00
|
|
|
matched = true;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
if (!func(ctx, cname))
|
|
|
|
toret = false;
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(cname);
|
|
|
|
}
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!matched) {
|
|
|
|
/* Politely warn the user that nothing matched. */
|
|
|
|
printf("%s: nothing matched\n", filename);
|
|
|
|
}
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_finish_wildcard_matching(swcm);
|
2005-01-01 12:34:32 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
cname = canonify(unwcfname);
|
|
|
|
toret = func(ctx, cname);
|
|
|
|
sfree(cname);
|
|
|
|
sfree(unwcfname);
|
2005-01-01 12:34:32 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return toret;
|
2005-01-01 12:34:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handy helper function.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool is_wildcard(char *name)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
char *unwcfname = snewn(strlen(name)+1, char);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool is_wc = !wc_unescape(unwcfname, name);
|
2005-01-01 12:34:32 +00:00
|
|
|
sfree(unwcfname);
|
|
|
|
return is_wc;
|
|
|
|
}
|
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Actual sftp commands.
|
|
|
|
*/
|
|
|
|
struct sftp_command {
|
|
|
|
char **words;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
size_t nwords, wordssize;
|
2019-09-08 19:29:00 +00:00
|
|
|
int (*obey) (struct sftp_command *); /* returns <0 to quit */
|
2004-12-16 16:37:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int sftp_cmd_null(struct sftp_command *cmd)
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
return 1; /* success */
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sftp_cmd_unknown(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
printf("psftp: unknown command \"%s\"\n", cmd->words[0]);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0; /* failure */
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sftp_cmd_quit(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-12-16 19:19:59 +00:00
|
|
|
int sftp_cmd_close(struct sftp_command *cmd)
|
|
|
|
{
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 19:19:59 +00:00
|
|
|
}
|
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend_connected(backend)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char ch;
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
backend_special(backend, SS_EOF, 0);
|
2018-10-29 19:50:29 +00:00
|
|
|
sent_eof = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_recvdata(&ch, 1);
|
2004-12-16 19:19:59 +00:00
|
|
|
}
|
|
|
|
do_sftp_cleanup();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-05-15 13:57:06 +00:00
|
|
|
void list_directory_from_sftp_warn_unsorted(void)
|
|
|
|
{
|
|
|
|
printf("Directory is too large to sort; writing file names unsorted\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void list_directory_from_sftp_print(struct fxp_name *name)
|
|
|
|
{
|
|
|
|
with_stripctrl(san, name->longname)
|
|
|
|
printf("%s\n", san);
|
|
|
|
}
|
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
/*
|
|
|
|
* List a directory. If no arguments are given, list pwd; otherwise
|
|
|
|
* list the directory given in words[1].
|
|
|
|
*/
|
|
|
|
int sftp_cmd_ls(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
struct fxp_handle *dirh;
|
|
|
|
struct fxp_names *names;
|
2015-05-15 10:15:42 +00:00
|
|
|
const char *dir;
|
|
|
|
char *cdir, *unwcdir, *wildcard;
|
2004-12-16 16:37:37 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd->nwords < 2)
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = ".";
|
2004-12-16 16:37:37 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = cmd->words[1];
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2004-12-16 17:45:29 +00:00
|
|
|
unwcdir = snewn(1 + strlen(dir), char);
|
|
|
|
if (wc_unescape(unwcdir, dir)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = unwcdir;
|
|
|
|
wildcard = NULL;
|
2004-12-16 17:45:29 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *tmpdir;
|
|
|
|
int len;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool check;
|
2004-12-16 17:45:29 +00:00
|
|
|
|
2013-07-14 10:46:07 +00:00
|
|
|
sfree(unwcdir);
|
2019-09-08 19:29:00 +00:00
|
|
|
wildcard = stripslashes(dir, false);
|
|
|
|
unwcdir = dupstr(dir);
|
|
|
|
len = wildcard - dir;
|
|
|
|
unwcdir[len] = '\0';
|
|
|
|
if (len > 0 && unwcdir[len-1] == '/')
|
|
|
|
unwcdir[len-1] = '\0';
|
|
|
|
tmpdir = snewn(1 + len, char);
|
|
|
|
check = wc_unescape(tmpdir, unwcdir);
|
|
|
|
sfree(tmpdir);
|
|
|
|
if (!check) {
|
|
|
|
printf("Multiple-level wildcards are not supported\n");
|
|
|
|
sfree(unwcdir);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
dir = unwcdir;
|
2004-12-16 17:45:29 +00:00
|
|
|
}
|
|
|
|
|
2004-12-16 16:37:37 +00:00
|
|
|
cdir = canonify(dir);
|
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, cdir)
|
|
|
|
printf("Listing directory %s\n", san);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_opendir_send(cdir);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
dirh = fxp_opendir_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
|
|
|
if (dirh == NULL) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("Unable to open %s: %s\n", dir, fxp_error());
|
|
|
|
sfree(cdir);
|
|
|
|
sfree(unwcdir);
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
} else {
|
2019-05-15 13:57:06 +00:00
|
|
|
struct list_directory_from_sftp_ctx *ctx =
|
|
|
|
list_directory_from_sftp_new();
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
while (1) {
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_readdir_send(dirh);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
names = fxp_readdir_recv(pktin, req);
|
|
|
|
|
|
|
|
if (names == NULL) {
|
|
|
|
if (fxp_error_type() == SSH_FX_EOF)
|
|
|
|
break;
|
|
|
|
printf("Reading directory %s: %s\n", dir, fxp_error());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (names->nnames == 0) {
|
|
|
|
fxp_free_names(names);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < names->nnames; i++)
|
|
|
|
if (!wildcard || wc_match(wildcard, names->names[i].filename))
|
2019-05-15 13:57:06 +00:00
|
|
|
list_directory_from_sftp_feed(ctx, &names->names[i]);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_free_names(names);
|
|
|
|
}
|
2019-05-15 13:57:06 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_close_send(dirh);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
fxp_close_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2019-05-15 13:57:06 +00:00
|
|
|
list_directory_from_sftp_finish(ctx);
|
|
|
|
list_directory_from_sftp_free(ctx);
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sfree(cdir);
|
2004-12-16 17:45:29 +00:00
|
|
|
sfree(unwcdir);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change directories. We do this by canonifying the new name, then
|
|
|
|
* trying to OPENDIR it. Only if that succeeds do we set the new pwd.
|
|
|
|
*/
|
|
|
|
int sftp_cmd_cd(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
struct fxp_handle *dirh;
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2004-12-16 16:37:37 +00:00
|
|
|
char *dir;
|
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd->nwords < 2)
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = dupstr(homedir);
|
2017-06-19 16:39:32 +00:00
|
|
|
else {
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = canonify(cmd->words[1]);
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_opendir_send(dir);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
dirh = fxp_opendir_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
|
|
|
if (!dirh) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, dir)
|
|
|
|
printf("Directory %s: %s\n", san, fxp_error());
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(dir);
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_close_send(dirh);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
fxp_close_recv(pktin, req);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
|
|
|
sfree(pwd);
|
|
|
|
pwd = dir;
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, pwd)
|
|
|
|
printf("Remote directory is now %s\n", san);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print current directory. Easy as pie.
|
|
|
|
*/
|
|
|
|
int sftp_cmd_pwd(struct sftp_command *cmd)
|
|
|
|
{
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, pwd)
|
|
|
|
printf("Remote directory is %s\n", san);
|
2004-12-16 16:37:37 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-12-16 17:35:20 +00:00
|
|
|
* Get a file and save it at the local end. We have three very
|
|
|
|
* similar commands here. The basic one is `get'; `reget' differs
|
|
|
|
* in that it checks for the existence of the destination file and
|
|
|
|
* starts from where a previous aborted transfer left off; `mget'
|
|
|
|
* differs in that it interprets all its arguments as files to
|
|
|
|
* transfer (never as a different local name for a remote file) and
|
|
|
|
* can handle wildcards.
|
2004-12-16 16:37:37 +00:00
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int sftp_general_get(struct sftp_command *cmd, bool restart, bool multiple)
|
2004-12-16 16:37:37 +00:00
|
|
|
{
|
2004-12-30 13:51:37 +00:00
|
|
|
char *fname, *unwcfname, *origfname, *origwfname, *outfname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int i, toret;
|
|
|
|
bool recurse = false;
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = 1;
|
|
|
|
while (i < cmd->nwords && cmd->words[i][0] == '-') {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!strcmp(cmd->words[i], "--")) {
|
|
|
|
/* finish processing options */
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
} else if (!strcmp(cmd->words[i], "-r")) {
|
|
|
|
recurse = true;
|
|
|
|
} else {
|
|
|
|
printf("%s: unrecognised option '%s'\n", cmd->words[0], cmd->words[i]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
i++;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= cmd->nwords) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("%s: expects a filename\n", cmd->words[0]);
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
toret = 1;
|
2004-12-16 17:35:20 +00:00
|
|
|
do {
|
2019-09-08 19:29:00 +00:00
|
|
|
SftpWildcardMatcher *swcm;
|
|
|
|
|
|
|
|
origfname = cmd->words[i++];
|
|
|
|
unwcfname = snewn(strlen(origfname)+1, char);
|
|
|
|
|
|
|
|
if (multiple && !wc_unescape(unwcfname, origfname)) {
|
|
|
|
swcm = sftp_begin_wildcard_matching(origfname);
|
|
|
|
if (!swcm) {
|
|
|
|
sfree(unwcfname);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
origwfname = sftp_wildcard_get_filename(swcm);
|
|
|
|
if (!origwfname) {
|
|
|
|
/* Politely warn the user that nothing matched. */
|
|
|
|
printf("%s: nothing matched\n", origfname);
|
|
|
|
sftp_finish_wildcard_matching(swcm);
|
|
|
|
sfree(unwcfname);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
origwfname = origfname;
|
|
|
|
swcm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (origwfname) {
|
|
|
|
fname = canonify(origwfname);
|
|
|
|
|
|
|
|
if (!multiple && i < cmd->nwords)
|
|
|
|
outfname = cmd->words[i++];
|
|
|
|
else
|
|
|
|
outfname = stripslashes(origwfname, false);
|
|
|
|
|
|
|
|
toret = sftp_get_file(fname, outfname, recurse, restart);
|
|
|
|
|
|
|
|
sfree(fname);
|
|
|
|
|
|
|
|
if (swcm) {
|
|
|
|
sfree(origwfname);
|
|
|
|
origwfname = sftp_wildcard_get_filename(swcm);
|
|
|
|
} else {
|
|
|
|
origwfname = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sfree(unwcfname);
|
|
|
|
if (swcm)
|
|
|
|
sftp_finish_wildcard_matching(swcm);
|
|
|
|
if (!toret)
|
|
|
|
return toret;
|
2004-12-16 17:35:20 +00:00
|
|
|
|
|
|
|
} while (multiple && i < cmd->nwords);
|
2004-12-16 16:37:37 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return toret;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
int sftp_cmd_get(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_get(cmd, false, false);
|
2004-12-16 17:35:20 +00:00
|
|
|
}
|
|
|
|
int sftp_cmd_mget(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_get(cmd, false, true);
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
int sftp_cmd_reget(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_get(cmd, true, false);
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-12-16 17:35:20 +00:00
|
|
|
* Send a file and store it at the remote end. We have three very
|
|
|
|
* similar commands here. The basic one is `put'; `reput' differs
|
|
|
|
* in that it checks for the existence of the destination file and
|
|
|
|
* starts from where a previous aborted transfer left off; `mput'
|
|
|
|
* differs in that it interprets all its arguments as files to
|
|
|
|
* transfer (never as a different remote name for a local file) and
|
|
|
|
* can handle wildcards.
|
2004-12-16 16:37:37 +00:00
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int sftp_general_put(struct sftp_command *cmd, bool restart, bool multiple)
|
2004-12-16 16:37:37 +00:00
|
|
|
{
|
2004-12-30 13:51:37 +00:00
|
|
|
char *fname, *wfname, *origoutfname, *outfname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int i;
|
|
|
|
int toret;
|
|
|
|
bool recurse = false;
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = 1;
|
|
|
|
while (i < cmd->nwords && cmd->words[i][0] == '-') {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!strcmp(cmd->words[i], "--")) {
|
|
|
|
/* finish processing options */
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
} else if (!strcmp(cmd->words[i], "-r")) {
|
|
|
|
recurse = true;
|
|
|
|
} else {
|
|
|
|
printf("%s: unrecognised option '%s'\n", cmd->words[0], cmd->words[i]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
i++;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= cmd->nwords) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("%s: expects a filename\n", cmd->words[0]);
|
|
|
|
return 0;
|
2004-12-16 16:37:37 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
toret = 1;
|
2004-12-16 17:35:20 +00:00
|
|
|
do {
|
2019-09-08 19:29:00 +00:00
|
|
|
WildcardMatcher *wcm;
|
|
|
|
fname = cmd->words[i++];
|
|
|
|
|
|
|
|
if (multiple && test_wildcard(fname, false) == WCTYPE_WILDCARD) {
|
|
|
|
wcm = begin_wildcard_matching(fname);
|
|
|
|
wfname = wildcard_get_filename(wcm);
|
|
|
|
if (!wfname) {
|
|
|
|
/* Politely warn the user that nothing matched. */
|
|
|
|
printf("%s: nothing matched\n", fname);
|
|
|
|
finish_wildcard_matching(wcm);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wfname = fname;
|
|
|
|
wcm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (wfname) {
|
|
|
|
if (!multiple && i < cmd->nwords)
|
|
|
|
origoutfname = cmd->words[i++];
|
|
|
|
else
|
|
|
|
origoutfname = stripslashes(wfname, true);
|
|
|
|
|
|
|
|
outfname = canonify(origoutfname);
|
|
|
|
toret = sftp_put_file(wfname, outfname, recurse, restart);
|
|
|
|
sfree(outfname);
|
|
|
|
|
|
|
|
if (wcm) {
|
|
|
|
sfree(wfname);
|
|
|
|
wfname = wildcard_get_filename(wcm);
|
|
|
|
} else {
|
|
|
|
wfname = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wcm)
|
|
|
|
finish_wildcard_matching(wcm);
|
|
|
|
|
|
|
|
if (!toret)
|
|
|
|
return toret;
|
2004-12-16 16:37:37 +00:00
|
|
|
|
2004-12-16 17:35:20 +00:00
|
|
|
} while (multiple && i < cmd->nwords);
|
2001-02-23 18:21:44 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return toret;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2001-08-26 11:35:11 +00:00
|
|
|
int sftp_cmd_put(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_put(cmd, false, false);
|
2004-12-16 17:35:20 +00:00
|
|
|
}
|
|
|
|
int sftp_cmd_mput(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_put(cmd, false, true);
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
int sftp_cmd_reput(struct sftp_command *cmd)
|
|
|
|
{
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return sftp_general_put(cmd, true, false);
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
int sftp_cmd_mkdir(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
char *dir;
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool result;
|
2005-01-01 12:34:32 +00:00
|
|
|
int i, ret;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
|
|
|
|
if (cmd->nwords < 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("mkdir: expects a directory\n");
|
|
|
|
return 0;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
ret = 1;
|
|
|
|
for (i = 1; i < cmd->nwords; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = canonify(cmd->words[i]);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
req = fxp_mkdir_send(dir, NULL);
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
pktin = sftp_wait_for_reply(req);
|
2019-09-08 19:29:00 +00:00
|
|
|
result = fxp_mkdir_recv(pktin, req);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!result) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, dir)
|
|
|
|
printf("mkdir %s: %s\n", san, fxp_error());
|
2019-09-08 19:29:00 +00:00
|
|
|
ret = 0;
|
|
|
|
} else
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, dir)
|
|
|
|
printf("mkdir %s: OK\n", san);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(dir);
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool sftp_action_rmdir(void *vctx, char *dir)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool result;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_rmdir_send(dir);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_rmdir_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
if (!result) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("rmdir %s: %s\n", dir, fxp_error());
|
|
|
|
return false;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 16:35:57 +00:00
|
|
|
printf("rmdir %s: OK\n", dir);
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sftp_cmd_rmdir(struct sftp_command *cmd)
|
|
|
|
{
|
2005-01-01 12:34:32 +00:00
|
|
|
int i, ret;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
|
|
|
|
if (cmd->nwords < 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("rmdir: expects a directory\n");
|
|
|
|
return 0;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
ret = 1;
|
|
|
|
for (i = 1; i < cmd->nwords; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
ret &= wildcard_iterate(cmd->words[i], sftp_action_rmdir, NULL);
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool sftp_action_rm(void *vctx, char *fname)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool result;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_remove_send(fname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_remove_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
if (!result) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("rm %s: %s\n", fname, fxp_error());
|
|
|
|
return false;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 16:35:57 +00:00
|
|
|
printf("rm %s: OK\n", fname);
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sftp_cmd_rm(struct sftp_command *cmd)
|
|
|
|
{
|
2005-01-01 12:34:32 +00:00
|
|
|
int i, ret;
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
if (cmd->nwords < 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("rm: expects a filename\n");
|
|
|
|
return 0;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
ret = 1;
|
|
|
|
for (i = 1; i < cmd->nwords; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
ret &= wildcard_iterate(cmd->words[i], sftp_action_rm, NULL);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool check_is_dir(char *dstfname)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2005-01-01 12:34:32 +00:00
|
|
|
struct fxp_attrs attrs;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool result;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_stat_send(dstfname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_stat_recv(pktin, req, &attrs);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
|
|
|
if (result &&
|
2019-09-08 19:29:00 +00:00
|
|
|
(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
|
|
|
|
(attrs.permissions & 0040000))
|
|
|
|
return true;
|
2005-01-01 12:34:32 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2005-01-01 12:34:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sftp_context_mv {
|
|
|
|
char *dstfname;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool dest_is_dir;
|
2005-01-01 12:34:32 +00:00
|
|
|
};
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool sftp_action_mv(void *vctx, char *srcfname)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
struct sftp_context_mv *ctx = (struct sftp_context_mv *)vctx;
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2005-01-01 12:34:32 +00:00
|
|
|
const char *error;
|
|
|
|
char *finalfname, *newcanon = NULL;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool toret, result;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
|
|
|
if (ctx->dest_is_dir) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *p;
|
|
|
|
char *newname;
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
p = srcfname + strlen(srcfname);
|
|
|
|
while (p > srcfname && p[-1] != '/') p--;
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
newname = dupcat(ctx->dstfname, "/", p);
|
2019-09-08 19:29:00 +00:00
|
|
|
newcanon = canonify(newname);
|
|
|
|
sfree(newname);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
finalfname = newcanon;
|
2005-01-01 12:34:32 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
finalfname = ctx->dstfname;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_rename_send(srcfname, finalfname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_rename_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
error = result ? NULL : fxp_error();
|
|
|
|
|
|
|
|
if (error) {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, finalfname)
|
|
|
|
printf("mv %s %s: %s\n", srcfname, san, error);
|
2019-09-08 19:29:00 +00:00
|
|
|
toret = false;
|
2005-01-01 12:34:32 +00:00
|
|
|
} else {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, finalfname)
|
|
|
|
printf("%s -> %s\n", srcfname, san);
|
2019-09-08 19:29:00 +00:00
|
|
|
toret = true;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
sfree(newcanon);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return toret;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sftp_cmd_mv(struct sftp_command *cmd)
|
|
|
|
{
|
2019-12-22 08:15:52 +00:00
|
|
|
struct sftp_context_mv ctx[1];
|
2005-01-01 12:34:32 +00:00
|
|
|
int i, ret;
|
2001-08-26 11:35:11 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
if (cmd->nwords < 3) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("mv: expects two filenames\n");
|
|
|
|
return 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2005-01-01 12:34:32 +00:00
|
|
|
|
|
|
|
ctx->dstfname = canonify(cmd->words[cmd->nwords-1]);
|
2001-08-26 11:35:11 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
/*
|
|
|
|
* If there's more than one source argument, or one source
|
|
|
|
* argument which is a wildcard, we _require_ that the
|
|
|
|
* destination is a directory.
|
|
|
|
*/
|
|
|
|
ctx->dest_is_dir = check_is_dir(ctx->dstfname);
|
|
|
|
if ((cmd->nwords > 3 || is_wildcard(cmd->words[1])) && !ctx->dest_is_dir) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("mv: multiple or wildcard arguments require the destination"
|
|
|
|
" to be a directory\n");
|
|
|
|
sfree(ctx->dstfname);
|
|
|
|
return 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
/*
|
|
|
|
* Now iterate over the source arguments.
|
|
|
|
*/
|
|
|
|
ret = 1;
|
|
|
|
for (i = 1; i < cmd->nwords-1; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
ret &= wildcard_iterate(cmd->words[i], sftp_action_mv, ctx);
|
2005-01-01 12:34:32 +00:00
|
|
|
|
2005-01-01 13:01:13 +00:00
|
|
|
sfree(ctx->dstfname);
|
2005-01-01 12:34:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sftp_context_chmod {
|
|
|
|
unsigned attrs_clr, attrs_xor;
|
|
|
|
};
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool sftp_action_chmod(void *vctx, char *fname)
|
2005-01-01 12:34:32 +00:00
|
|
|
{
|
|
|
|
struct fxp_attrs attrs;
|
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool result;
|
2005-01-01 12:34:32 +00:00
|
|
|
unsigned oldperms, newperms;
|
|
|
|
struct sftp_context_chmod *ctx = (struct sftp_context_chmod *)vctx;
|
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_stat_send(fname);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_stat_recv(pktin, req, &attrs);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
if (!result || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("get attrs for %s: %s\n", fname,
|
|
|
|
result ? "file permissions not provided" : fxp_error());
|
|
|
|
return false;
|
2005-01-01 12:34:32 +00:00
|
|
|
}
|
2001-08-26 11:35:11 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
attrs.flags = SSH_FILEXFER_ATTR_PERMISSIONS; /* perms _only_ */
|
|
|
|
oldperms = attrs.permissions & 07777;
|
|
|
|
attrs.permissions &= ~ctx->attrs_clr;
|
|
|
|
attrs.permissions ^= ctx->attrs_xor;
|
|
|
|
newperms = attrs.permissions & 07777;
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
if (oldperms == newperms)
|
2019-09-08 19:29:00 +00:00
|
|
|
return true; /* no need to do anything! */
|
2003-06-29 14:26:09 +00:00
|
|
|
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_setstat_send(fname, attrs);
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
result = fxp_setstat_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
if (!result) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("set attrs for %s: %s\n", fname, fxp_error());
|
|
|
|
return false;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
printf("%s: %04o -> %04o\n", fname, oldperms, newperms);
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
int sftp_cmd_chmod(struct sftp_command *cmd)
|
|
|
|
{
|
2005-01-01 12:34:32 +00:00
|
|
|
char *mode;
|
|
|
|
int i, ret;
|
2019-12-22 08:15:52 +00:00
|
|
|
struct sftp_context_chmod ctx[1];
|
2001-08-26 11:35:11 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
not_connected();
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2001-08-26 11:35:11 +00:00
|
|
|
if (cmd->nwords < 3) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("chmod: expects a mode specifier and a filename\n");
|
|
|
|
return 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to parse the mode specifier in cmd->words[1]. We
|
|
|
|
* don't support the full horror of Unix chmod; instead we
|
|
|
|
* support a much simpler syntax in which the user can either
|
|
|
|
* specify an octal number, or a comma-separated sequence of
|
|
|
|
* [ugoa]*[-+=][rwxst]+. (The initial [ugoa] sequence may
|
|
|
|
* _only_ be omitted if the only attribute mentioned is t,
|
|
|
|
* since all others require a user/group/other specification.
|
|
|
|
* Additionally, the s attribute may not be specified for any
|
|
|
|
* [ugoa] specifications other than exactly u or exactly g.
|
|
|
|
*/
|
2005-01-01 12:34:32 +00:00
|
|
|
ctx->attrs_clr = ctx->attrs_xor = 0;
|
2001-08-26 11:35:11 +00:00
|
|
|
mode = cmd->words[1];
|
|
|
|
if (mode[0] >= '0' && mode[0] <= '9') {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (mode[strspn(mode, "01234567")]) {
|
|
|
|
printf("chmod: numeric file modes should"
|
|
|
|
" contain digits 0-7 only\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ctx->attrs_clr = 07777;
|
|
|
|
sscanf(mode, "%o", &ctx->attrs_xor);
|
|
|
|
ctx->attrs_xor &= ctx->attrs_clr;
|
2001-08-26 11:35:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
while (*mode) {
|
|
|
|
char *modebegin = mode;
|
|
|
|
unsigned subset, perms;
|
|
|
|
int action;
|
|
|
|
|
|
|
|
subset = 0;
|
|
|
|
while (*mode && *mode != ',' &&
|
|
|
|
*mode != '+' && *mode != '-' && *mode != '=') {
|
|
|
|
switch (*mode) {
|
|
|
|
case 'u': subset |= 04700; break; /* setuid, user perms */
|
|
|
|
case 'g': subset |= 02070; break; /* setgid, group perms */
|
|
|
|
case 'o': subset |= 00007; break; /* just other perms */
|
|
|
|
case 'a': subset |= 06777; break; /* all of the above */
|
|
|
|
default:
|
|
|
|
printf("chmod: file mode '%.*s' contains unrecognised"
|
|
|
|
" user/group/other specifier '%c'\n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin, *mode);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
mode++;
|
|
|
|
}
|
|
|
|
if (!*mode || *mode == ',') {
|
|
|
|
printf("chmod: file mode '%.*s' is incomplete\n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
action = *mode++;
|
|
|
|
if (!*mode || *mode == ',') {
|
|
|
|
printf("chmod: file mode '%.*s' is incomplete\n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
perms = 0;
|
|
|
|
while (*mode && *mode != ',') {
|
|
|
|
switch (*mode) {
|
|
|
|
case 'r': perms |= 00444; break;
|
|
|
|
case 'w': perms |= 00222; break;
|
|
|
|
case 'x': perms |= 00111; break;
|
|
|
|
case 't': perms |= 01000; subset |= 01000; break;
|
|
|
|
case 's':
|
|
|
|
if ((subset & 06777) != 04700 &&
|
|
|
|
(subset & 06777) != 02070) {
|
|
|
|
printf("chmod: file mode '%.*s': set[ug]id bit should"
|
|
|
|
" be used with exactly one of u or g only\n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
perms |= 06000;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("chmod: file mode '%.*s' contains unrecognised"
|
|
|
|
" permission specifier '%c'\n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin, *mode);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
mode++;
|
|
|
|
}
|
|
|
|
if (!(subset & 06777) && (perms &~ subset)) {
|
|
|
|
printf("chmod: file mode '%.*s' contains no user/group/other"
|
|
|
|
" specifier and permissions other than 't' \n",
|
|
|
|
(int)strcspn(modebegin, ","), modebegin);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
perms &= subset;
|
|
|
|
switch (action) {
|
|
|
|
case '+':
|
|
|
|
ctx->attrs_clr |= perms;
|
|
|
|
ctx->attrs_xor |= perms;
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
ctx->attrs_clr |= perms;
|
|
|
|
ctx->attrs_xor &= ~perms;
|
|
|
|
break;
|
|
|
|
case '=':
|
|
|
|
ctx->attrs_clr |= subset;
|
|
|
|
ctx->attrs_xor |= perms;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*mode) mode++; /* eat comma */
|
|
|
|
}
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
ret = 1;
|
|
|
|
for (i = 2; i < cmd->nwords; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
ret &= wildcard_iterate(cmd->words[i], sftp_action_chmod, ctx);
|
2001-08-26 11:35:11 +00:00
|
|
|
|
2005-01-01 12:34:32 +00:00
|
|
|
return ret;
|
2001-08-26 11:35:11 +00:00
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
|
2001-12-13 18:42:34 +00:00
|
|
|
static int sftp_cmd_open(struct sftp_command *cmd)
|
|
|
|
{
|
2004-01-21 19:56:08 +00:00
|
|
|
int portnumber;
|
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("psftp: already connected\n");
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd->nwords < 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("open: expects a host name\n");
|
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2004-01-21 19:56:08 +00:00
|
|
|
if (cmd->nwords > 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
portnumber = atoi(cmd->words[2]);
|
|
|
|
if (portnumber == 0) {
|
|
|
|
printf("open: invalid port number\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2004-01-21 19:56:08 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
portnumber = 0;
|
2004-01-21 19:56:08 +00:00
|
|
|
|
|
|
|
if (psftp_connect(cmd->words[1], NULL, portnumber)) {
|
2018-09-11 15:23:38 +00:00
|
|
|
backend = NULL; /* connection is already closed */
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1; /* this is fatal */
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
do_sftp_init();
|
2001-12-13 19:26:51 +00:00
|
|
|
return 1;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2001-12-16 13:33:04 +00:00
|
|
|
static int sftp_cmd_lcd(struct sftp_command *cmd)
|
|
|
|
{
|
2003-08-24 12:47:46 +00:00
|
|
|
char *currdir, *errmsg;
|
2001-12-16 13:33:04 +00:00
|
|
|
|
|
|
|
if (cmd->nwords < 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("lcd: expects a local directory name\n");
|
|
|
|
return 0;
|
2001-12-16 13:33:04 +00:00
|
|
|
}
|
|
|
|
|
2003-08-24 12:47:46 +00:00
|
|
|
errmsg = psftp_lcd(cmd->words[1]);
|
|
|
|
if (errmsg) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("lcd: unable to change directory: %s\n", errmsg);
|
|
|
|
sfree(errmsg);
|
|
|
|
return 0;
|
2001-12-16 13:33:04 +00:00
|
|
|
}
|
|
|
|
|
2003-08-24 12:47:46 +00:00
|
|
|
currdir = psftp_getcwd();
|
2001-12-16 13:33:04 +00:00
|
|
|
printf("New local directory is %s\n", currdir);
|
|
|
|
sfree(currdir);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sftp_cmd_lpwd(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
char *currdir;
|
|
|
|
|
2003-08-24 12:47:46 +00:00
|
|
|
currdir = psftp_getcwd();
|
2001-12-16 13:33:04 +00:00
|
|
|
printf("Current local directory is %s\n", currdir);
|
|
|
|
sfree(currdir);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sftp_cmd_pling(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
int exitcode;
|
|
|
|
|
|
|
|
exitcode = system(cmd->words[1]);
|
|
|
|
return (exitcode == 0);
|
|
|
|
}
|
|
|
|
|
2001-09-09 16:29:51 +00:00
|
|
|
static int sftp_cmd_help(struct sftp_command *cmd);
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
static struct sftp_cmd_lookup {
|
2015-05-15 10:15:42 +00:00
|
|
|
const char *name;
|
2001-09-09 16:29:51 +00:00
|
|
|
/*
|
|
|
|
* For help purposes, there are two kinds of command:
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-09-09 16:29:51 +00:00
|
|
|
* - primary commands, in which `longhelp' is non-NULL. In
|
|
|
|
* this case `shorthelp' is descriptive text, and `longhelp'
|
|
|
|
* is longer descriptive text intended to be printed after
|
|
|
|
* the command name.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-09-09 16:29:51 +00:00
|
|
|
* - alias commands, in which `longhelp' is NULL. In this case
|
|
|
|
* `shorthelp' is the name of a primary command, which
|
|
|
|
* contains the help that should double up for this command.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool listed; /* do we list this in primary help? */
|
2015-05-15 10:15:42 +00:00
|
|
|
const char *shorthelp;
|
|
|
|
const char *longhelp;
|
2001-05-06 14:35:20 +00:00
|
|
|
int (*obey) (struct sftp_command *);
|
2001-02-23 18:21:44 +00:00
|
|
|
} sftp_lookup[] = {
|
|
|
|
/*
|
|
|
|
* List of sftp commands. This is binary-searched so it MUST be
|
|
|
|
* in ASCII order.
|
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"!", true, "run a local command",
|
|
|
|
"<command>\n"
|
|
|
|
/* FIXME: this example is crap for non-Windows. */
|
|
|
|
" Runs a local command. For example, \"!del myfile\".\n",
|
|
|
|
sftp_cmd_pling
|
2001-12-16 13:33:04 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"bye", true, "finish your SFTP session",
|
|
|
|
"\n"
|
|
|
|
" Terminates your SFTP session and quits the PSFTP program.\n",
|
|
|
|
sftp_cmd_quit
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"cd", true, "change your remote working directory",
|
|
|
|
" [ <new working directory> ]\n"
|
|
|
|
" Change the remote working directory for your SFTP session.\n"
|
|
|
|
" If a new working directory is not supplied, you will be\n"
|
|
|
|
" returned to your home directory.\n",
|
|
|
|
sftp_cmd_cd
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"chmod", true, "change file permissions and modes",
|
|
|
|
" <modes> <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
|
|
|
|
" Change the file permissions on one or more remote files or\n"
|
|
|
|
" directories.\n"
|
|
|
|
" <modes> can be any octal Unix permission specifier.\n"
|
|
|
|
" Alternatively, <modes> can include the following modifiers:\n"
|
|
|
|
" u+r make file readable by owning user\n"
|
|
|
|
" u+w make file writable by owning user\n"
|
|
|
|
" u+x make file executable by owning user\n"
|
|
|
|
" u-r make file not readable by owning user\n"
|
|
|
|
" [also u-w, u-x]\n"
|
|
|
|
" g+r make file readable by members of owning group\n"
|
|
|
|
" [also g+w, g+x, g-r, g-w, g-x]\n"
|
|
|
|
" o+r make file readable by all other users\n"
|
|
|
|
" [also o+w, o+x, o-r, o-w, o-x]\n"
|
|
|
|
" a+r make file readable by absolutely everybody\n"
|
|
|
|
" [also a+w, a+x, a-r, a-w, a-x]\n"
|
|
|
|
" u+s enable the Unix set-user-ID bit\n"
|
|
|
|
" u-s disable the Unix set-user-ID bit\n"
|
|
|
|
" g+s enable the Unix set-group-ID bit\n"
|
|
|
|
" g-s disable the Unix set-group-ID bit\n"
|
|
|
|
" +t enable the Unix \"sticky bit\"\n"
|
|
|
|
" You can give more than one modifier for the same user (\"g-rwx\"), and\n"
|
|
|
|
" more than one user for the same modifier (\"ug+w\"). You can\n"
|
|
|
|
" use commas to separate different modifiers (\"u+rwx,g+s\").\n",
|
|
|
|
sftp_cmd_chmod
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
2004-12-16 19:19:59 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"close", true, "finish your SFTP session but do not quit PSFTP",
|
|
|
|
"\n"
|
|
|
|
" Terminates your SFTP session, but does not quit the PSFTP\n"
|
|
|
|
" program. You can then use \"open\" to start another SFTP\n"
|
|
|
|
" session, to the same server or to a different one.\n",
|
|
|
|
sftp_cmd_close
|
2004-12-16 19:19:59 +00:00
|
|
|
},
|
2001-09-09 16:29:51 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"del", true, "delete files on the remote server",
|
|
|
|
" <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
|
|
|
|
" Delete a file or files from the server.\n",
|
|
|
|
sftp_cmd_rm
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"delete", false, "del", NULL, sftp_cmd_rm
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"dir", true, "list remote files",
|
|
|
|
" [ <directory-name> ]/[ <wildcard> ]\n"
|
|
|
|
" List the contents of a specified directory on the server.\n"
|
|
|
|
" If <directory-name> is not given, the current working directory\n"
|
|
|
|
" is assumed.\n"
|
|
|
|
" If <wildcard> is given, it is treated as a set of files to\n"
|
|
|
|
" list; otherwise, all files are listed.\n",
|
|
|
|
sftp_cmd_ls
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"exit", true, "bye", NULL, sftp_cmd_quit
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"get", true, "download a file from the server to your local machine",
|
|
|
|
" [ -r ] [ -- ] <filename> [ <local-filename> ]\n"
|
|
|
|
" Downloads a file on the server and stores it locally under\n"
|
|
|
|
" the same name, or under a different one if you supply the\n"
|
|
|
|
" argument <local-filename>.\n"
|
|
|
|
" If -r specified, recursively fetch a directory.\n",
|
|
|
|
sftp_cmd_get
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"help", true, "give help",
|
|
|
|
" [ <command> [ <command> ... ] ]\n"
|
|
|
|
" Give general help if no commands are specified.\n"
|
|
|
|
" If one or more commands are specified, give specific help on\n"
|
|
|
|
" those particular commands.\n",
|
|
|
|
sftp_cmd_help
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"lcd", true, "change local working directory",
|
|
|
|
" <local-directory-name>\n"
|
|
|
|
" Change the local working directory of the PSFTP program (the\n"
|
|
|
|
" default location where the \"get\" command will save files).\n",
|
|
|
|
sftp_cmd_lcd
|
2001-12-16 13:33:04 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"lpwd", true, "print local working directory",
|
|
|
|
"\n"
|
|
|
|
" Print the local working directory of the PSFTP program (the\n"
|
|
|
|
" default location where the \"get\" command will save files).\n",
|
|
|
|
sftp_cmd_lpwd
|
2001-12-16 13:33:04 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"ls", true, "dir", NULL,
|
|
|
|
sftp_cmd_ls
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
2004-12-16 17:35:20 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"mget", true, "download multiple files at once",
|
|
|
|
" [ -r ] [ -- ] <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
|
|
|
|
" Downloads many files from the server, storing each one under\n"
|
|
|
|
" the same name it has on the server side. You can use wildcards\n"
|
|
|
|
" such as \"*.c\" to specify lots of files at once.\n"
|
|
|
|
" If -r specified, recursively fetch files and directories.\n",
|
|
|
|
sftp_cmd_mget
|
2004-12-16 17:35:20 +00:00
|
|
|
},
|
2001-09-09 16:29:51 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"mkdir", true, "create directories on the remote server",
|
|
|
|
" <directory-name> [ <directory-name>... ]\n"
|
|
|
|
" Creates directories with the given names on the server.\n",
|
|
|
|
sftp_cmd_mkdir
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
2004-12-16 17:35:20 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"mput", true, "upload multiple files at once",
|
|
|
|
" [ -r ] [ -- ] <filename-or-wildcard> [ <filename-or-wildcard>... ]\n"
|
|
|
|
" Uploads many files to the server, storing each one under the\n"
|
|
|
|
" same name it has on the client side. You can use wildcards\n"
|
|
|
|
" such as \"*.c\" to specify lots of files at once.\n"
|
|
|
|
" If -r specified, recursively store files and directories.\n",
|
|
|
|
sftp_cmd_mput
|
2004-12-16 17:35:20 +00:00
|
|
|
},
|
2001-09-09 16:29:51 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"mv", true, "move or rename file(s) on the remote server",
|
|
|
|
" <source> [ <source>... ] <destination>\n"
|
|
|
|
" Moves or renames <source>(s) on the server to <destination>,\n"
|
|
|
|
" also on the server.\n"
|
|
|
|
" If <destination> specifies an existing directory, then <source>\n"
|
|
|
|
" may be a wildcard, and multiple <source>s may be given; all\n"
|
|
|
|
" source files are moved into <destination>.\n"
|
|
|
|
" Otherwise, <source> must specify a single file, which is moved\n"
|
|
|
|
" or renamed so that it is accessible under the name <destination>.\n",
|
|
|
|
sftp_cmd_mv
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
2001-12-13 18:42:34 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"open", true, "connect to a host",
|
|
|
|
" [<user>@]<hostname> [<port>]\n"
|
|
|
|
" Establishes an SFTP connection to a given host. Only usable\n"
|
|
|
|
" when you are not already connected to a server.\n",
|
|
|
|
sftp_cmd_open
|
2001-12-13 18:42:34 +00:00
|
|
|
},
|
2001-12-19 18:49:32 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"put", true, "upload a file from your local machine to the server",
|
|
|
|
" [ -r ] [ -- ] <filename> [ <remote-filename> ]\n"
|
|
|
|
" Uploads a file to the server and stores it there under\n"
|
|
|
|
" the same name, or under a different one if you supply the\n"
|
|
|
|
" argument <remote-filename>.\n"
|
|
|
|
" If -r specified, recursively store a directory.\n",
|
|
|
|
sftp_cmd_put
|
2001-12-19 18:49:32 +00:00
|
|
|
},
|
2001-09-09 16:31:26 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"pwd", true, "print your remote working directory",
|
|
|
|
"\n"
|
|
|
|
" Print the current remote working directory for your SFTP session.\n",
|
|
|
|
sftp_cmd_pwd
|
2001-09-09 16:31:26 +00:00
|
|
|
},
|
2001-09-09 16:29:51 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"quit", true, "bye", NULL,
|
|
|
|
sftp_cmd_quit
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"reget", true, "continue downloading files",
|
|
|
|
" [ -r ] [ -- ] <filename> [ <local-filename> ]\n"
|
|
|
|
" Works exactly like the \"get\" command, but the local file\n"
|
|
|
|
" must already exist. The download will begin at the end of the\n"
|
|
|
|
" file. This is for resuming a download that was interrupted.\n"
|
|
|
|
" If -r specified, resume interrupted \"get -r\".\n",
|
|
|
|
sftp_cmd_reget
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"ren", true, "mv", NULL,
|
|
|
|
sftp_cmd_mv
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"rename", false, "mv", NULL,
|
|
|
|
sftp_cmd_mv
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"reput", true, "continue uploading files",
|
|
|
|
" [ -r ] [ -- ] <filename> [ <remote-filename> ]\n"
|
|
|
|
" Works exactly like the \"put\" command, but the remote file\n"
|
|
|
|
" must already exist. The upload will begin at the end of the\n"
|
|
|
|
" file. This is for resuming an upload that was interrupted.\n"
|
|
|
|
" If -r specified, resume interrupted \"put -r\".\n",
|
|
|
|
sftp_cmd_reput
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"rm", true, "del", NULL,
|
|
|
|
sftp_cmd_rm
|
2001-09-09 16:29:51 +00:00
|
|
|
},
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
"rmdir", true, "remove directories on the remote server",
|
|
|
|
" <directory-name> [ <directory-name>... ]\n"
|
|
|
|
" Removes the directory with the given name on the server.\n"
|
|
|
|
" The directory will not be removed unless it is empty.\n"
|
|
|
|
" Wildcards may be used to specify multiple directories.\n",
|
|
|
|
sftp_cmd_rmdir
|
2001-09-09 16:29:51 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
const struct sftp_cmd_lookup *lookup_command(const char *name)
|
2001-09-09 16:29:51 +00:00
|
|
|
{
|
|
|
|
int i, j, k, cmp;
|
|
|
|
|
|
|
|
i = -1;
|
2019-01-04 07:13:08 +00:00
|
|
|
j = lenof(sftp_lookup);
|
2001-09-09 16:29:51 +00:00
|
|
|
while (j - i > 1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
k = (j + i) / 2;
|
|
|
|
cmp = strcmp(name, sftp_lookup[k].name);
|
|
|
|
if (cmp < 0)
|
|
|
|
j = k;
|
|
|
|
else if (cmp > 0)
|
|
|
|
i = k;
|
|
|
|
else {
|
|
|
|
return &sftp_lookup[k];
|
|
|
|
}
|
2001-09-09 16:29:51 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sftp_cmd_help(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (cmd->nwords == 1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Give short help on each command.
|
|
|
|
*/
|
|
|
|
int maxlen;
|
|
|
|
maxlen = 0;
|
|
|
|
for (i = 0; i < lenof(sftp_lookup); i++) {
|
|
|
|
int len;
|
|
|
|
if (!sftp_lookup[i].listed)
|
|
|
|
continue;
|
|
|
|
len = strlen(sftp_lookup[i].name);
|
|
|
|
if (maxlen < len)
|
|
|
|
maxlen = len;
|
|
|
|
}
|
|
|
|
for (i = 0; i < lenof(sftp_lookup); i++) {
|
|
|
|
const struct sftp_cmd_lookup *lookup;
|
|
|
|
if (!sftp_lookup[i].listed)
|
|
|
|
continue;
|
|
|
|
lookup = &sftp_lookup[i];
|
|
|
|
printf("%-*s", maxlen+2, lookup->name);
|
|
|
|
if (lookup->longhelp == NULL)
|
|
|
|
lookup = lookup_command(lookup->shorthelp);
|
|
|
|
printf("%s\n", lookup->shorthelp);
|
|
|
|
}
|
2001-09-09 16:29:51 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Give long help on specific commands.
|
|
|
|
*/
|
|
|
|
for (i = 1; i < cmd->nwords; i++) {
|
|
|
|
const struct sftp_cmd_lookup *lookup;
|
|
|
|
lookup = lookup_command(cmd->words[i]);
|
|
|
|
if (!lookup) {
|
|
|
|
printf("help: %s: command not found\n", cmd->words[i]);
|
|
|
|
} else {
|
|
|
|
printf("%s", lookup->name);
|
|
|
|
if (lookup->longhelp == NULL)
|
|
|
|
lookup = lookup_command(lookup->shorthelp);
|
|
|
|
printf("%s", lookup->longhelp);
|
|
|
|
}
|
|
|
|
}
|
2001-09-09 16:29:51 +00:00
|
|
|
}
|
2001-12-13 19:26:51 +00:00
|
|
|
return 1;
|
2001-09-09 16:29:51 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Command line reading and parsing.
|
|
|
|
*/
|
2001-08-04 14:19:51 +00:00
|
|
|
struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-23 18:21:44 +00:00
|
|
|
char *line;
|
|
|
|
struct sftp_command *cmd;
|
|
|
|
char *p, *q, *r;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool quoting;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2003-03-29 16:14:26 +00:00
|
|
|
cmd = snew(struct sftp_command);
|
2001-02-23 18:21:44 +00:00
|
|
|
cmd->words = NULL;
|
|
|
|
cmd->nwords = 0;
|
|
|
|
cmd->wordssize = 0;
|
|
|
|
|
|
|
|
line = NULL;
|
2004-11-27 13:20:21 +00:00
|
|
|
|
|
|
|
if (fp) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (modeflags & 1)
|
|
|
|
printf("psftp> ");
|
|
|
|
line = fgetline(fp);
|
2004-11-27 13:20:21 +00:00
|
|
|
} else {
|
2018-09-11 15:23:38 +00:00
|
|
|
line = ssh_sftp_get_cmdline("psftp> ", !backend);
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2004-11-27 13:20:21 +00:00
|
|
|
|
|
|
|
if (!line || !*line) {
|
2019-09-08 19:29:00 +00:00
|
|
|
cmd->obey = sftp_cmd_quit;
|
|
|
|
if ((mode == 0) || (modeflags & 1))
|
|
|
|
printf("quit\n");
|
2013-07-14 10:46:07 +00:00
|
|
|
sfree(line);
|
2019-09-08 19:29:00 +00:00
|
|
|
return cmd; /* eof */
|
2004-11-27 13:20:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
line[strcspn(line, "\r\n")] = '\0';
|
|
|
|
|
2001-12-13 19:26:51 +00:00
|
|
|
if (modeflags & 1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("%s\n", line);
|
2001-12-13 19:26:51 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
|
|
|
p = line;
|
2001-12-16 13:33:04 +00:00
|
|
|
while (*p && (*p == ' ' || *p == '\t'))
|
2019-09-08 19:29:00 +00:00
|
|
|
p++;
|
2001-12-16 13:33:04 +00:00
|
|
|
|
|
|
|
if (*p == '!') {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Special case: the ! command. This is always parsed as
|
|
|
|
* exactly two words: one containing the !, and the second
|
|
|
|
* containing everything else on the line.
|
|
|
|
*/
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
cmd->nwords = 2;
|
|
|
|
sgrowarrayn(cmd->words, cmd->wordssize, cmd->nwords, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
cmd->words[0] = dupstr("!");
|
|
|
|
cmd->words[1] = dupstr(p+1);
|
2008-11-24 18:19:55 +00:00
|
|
|
} else if (*p == '#') {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Special case: comment. Entire line is ignored.
|
|
|
|
*/
|
|
|
|
cmd->nwords = cmd->wordssize = 0;
|
2001-12-16 13:33:04 +00:00
|
|
|
} else {
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Parse the command line into words. The syntax is:
|
|
|
|
* - double quotes are removed, but cause spaces within to be
|
|
|
|
* treated as non-separating.
|
|
|
|
* - a double-doublequote pair is a literal double quote, inside
|
|
|
|
* _or_ outside quotes. Like this:
|
|
|
|
*
|
|
|
|
* firstword "second word" "this has ""quotes"" in" and""this""
|
|
|
|
*
|
|
|
|
* becomes
|
|
|
|
*
|
|
|
|
* >firstword<
|
|
|
|
* >second word<
|
|
|
|
* >this has "quotes" in<
|
|
|
|
* >and"this"<
|
|
|
|
*/
|
|
|
|
while (1) {
|
|
|
|
/* skip whitespace */
|
|
|
|
while (*p && (*p == ' ' || *p == '\t'))
|
|
|
|
p++;
|
2012-08-22 18:36:44 +00:00
|
|
|
/* terminate loop */
|
|
|
|
if (!*p)
|
|
|
|
break;
|
2019-09-08 19:29:00 +00:00
|
|
|
/* mark start of word */
|
|
|
|
q = r = p; /* q sits at start, r writes word */
|
|
|
|
quoting = false;
|
|
|
|
while (*p) {
|
|
|
|
if (!quoting && (*p == ' ' || *p == '\t'))
|
|
|
|
break; /* reached end of word */
|
|
|
|
else if (*p == '"' && p[1] == '"')
|
|
|
|
p += 2, *r++ = '"'; /* a literal quote */
|
|
|
|
else if (*p == '"')
|
|
|
|
p++, quoting = !quoting;
|
|
|
|
else
|
|
|
|
*r++ = *p++;
|
|
|
|
}
|
|
|
|
if (*p)
|
|
|
|
p++; /* skip over the whitespace */
|
|
|
|
*r = '\0';
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarray(cmd->words, cmd->wordssize, cmd->nwords);
|
2019-09-08 19:29:00 +00:00
|
|
|
cmd->words[cmd->nwords++] = dupstr(q);
|
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
2004-11-27 13:20:21 +00:00
|
|
|
sfree(line);
|
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/*
|
|
|
|
* Now parse the first word and assign a function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (cmd->nwords == 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
cmd->obey = sftp_cmd_null;
|
2001-02-23 18:21:44 +00:00
|
|
|
else {
|
2019-09-08 19:29:00 +00:00
|
|
|
const struct sftp_cmd_lookup *lookup;
|
|
|
|
lookup = lookup_command(cmd->words[0]);
|
|
|
|
if (!lookup)
|
|
|
|
cmd->obey = sftp_cmd_unknown;
|
|
|
|
else
|
|
|
|
cmd->obey = lookup->obey;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
|
2020-02-05 19:45:27 +00:00
|
|
|
static void sftp_cmd_free(struct sftp_command *cmd)
|
|
|
|
{
|
|
|
|
if (cmd->words) {
|
|
|
|
for (size_t i = 0; i < cmd->nwords; i++)
|
|
|
|
sfree(cmd->words[i]);
|
|
|
|
sfree(cmd->words);
|
|
|
|
}
|
|
|
|
sfree(cmd);
|
|
|
|
}
|
|
|
|
|
2002-02-27 22:20:30 +00:00
|
|
|
static int do_sftp_init(void)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-06-29 14:26:09 +00:00
|
|
|
struct sftp_packet *pktin;
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
struct sftp_request *req;
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
/*
|
2019-09-08 19:29:00 +00:00
|
|
|
* Do protocol initialisation.
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
|
|
|
if (!fxp_init()) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Fatal: unable to initialise SFTP: %s\n", fxp_error());
|
|
|
|
return 1; /* failure */
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find out where our home directory is.
|
|
|
|
*/
|
Clean up handling of the return value from sftp_find_request. In many
places we simply enforce by assertion that it will match the request
we sent out a moment ago: in fact it can also return NULL, so it makes
more sense to report a proper error message if it doesn't return the
expected value, and while we're at it, have that error message
whatever message was helpfully left in fxp_error() by
sftp_find_request when it failed.
To do this, I've written a centralised function in psftp.c called
sftp_wait_for_reply, which is handed a request that's just been sent
out and deals with the mechanics of waiting for its reply, returning
the reply when it arrives, and aborting with a sensible error if
anything else arrives instead. The numerous sites in psftp.c which
called sftp_find_request have all been rewritten to do this instead,
and as a side effect they now look more sensible. The only other uses
of sftp_find_request were in xfer_*load_gotpkt, which had to be
tweaked in its own way.
While I'm here, also fix memory management in sftp_find_request, which
was freeing its input packet on some but not all error return paths.
[originally from svn r9894]
2013-07-06 20:43:21 +00:00
|
|
|
req = fxp_realpath_send(".");
|
|
|
|
pktin = sftp_wait_for_reply(req);
|
|
|
|
homedir = fxp_realpath_recv(pktin, req);
|
2003-06-29 14:26:09 +00:00
|
|
|
|
2001-02-23 18:21:44 +00:00
|
|
|
if (!homedir) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Warning: failed to resolve home directory: %s\n",
|
|
|
|
fxp_error());
|
|
|
|
homedir = dupstr(".");
|
2001-02-23 18:21:44 +00:00
|
|
|
} else {
|
2019-02-20 07:09:10 +00:00
|
|
|
with_stripctrl(san, homedir)
|
|
|
|
printf("Remote working directory is %s\n", san);
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
|
|
|
pwd = dupstr(homedir);
|
2002-02-27 22:20:30 +00:00
|
|
|
return 0;
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
|
2018-11-03 08:25:28 +00:00
|
|
|
static void do_sftp_cleanup(void)
|
2003-12-19 12:44:46 +00:00
|
|
|
{
|
|
|
|
char ch;
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend) {
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
backend_special(backend, SS_EOF, 0);
|
2018-10-29 19:50:29 +00:00
|
|
|
sent_eof = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_recvdata(&ch, 1);
|
2018-09-11 15:23:38 +00:00
|
|
|
backend_free(backend);
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_cleanup_request();
|
2018-09-11 15:23:38 +00:00
|
|
|
backend = NULL;
|
2004-01-21 19:56:08 +00:00
|
|
|
}
|
2003-12-19 12:44:46 +00:00
|
|
|
if (pwd) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(pwd);
|
|
|
|
pwd = NULL;
|
2003-12-19 12:44:46 +00:00
|
|
|
}
|
|
|
|
if (homedir) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(homedir);
|
|
|
|
homedir = NULL;
|
2003-12-19 12:44:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-25 22:27:16 +00:00
|
|
|
int do_sftp(int mode, int modeflags, char *batchfile)
|
2001-12-13 18:42:34 +00:00
|
|
|
{
|
|
|
|
FILE *fp;
|
2001-12-13 19:26:51 +00:00
|
|
|
int ret;
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-08-04 14:19:51 +00:00
|
|
|
/*
|
|
|
|
* Batch mode?
|
2001-02-23 18:21:44 +00:00
|
|
|
*/
|
2001-08-04 14:19:51 +00:00
|
|
|
if (mode == 0) {
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------
|
|
|
|
* Now we're ready to do Real Stuff.
|
|
|
|
*/
|
|
|
|
while (1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
struct sftp_command *cmd;
|
|
|
|
cmd = sftp_getcmd(NULL, 0, 0);
|
|
|
|
if (!cmd)
|
|
|
|
break;
|
|
|
|
ret = cmd->obey(cmd);
|
2020-02-05 19:45:27 +00:00
|
|
|
sftp_cmd_free(cmd);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
} else {
|
|
|
|
fp = fopen(batchfile, "r");
|
|
|
|
if (!fp) {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("Fatal: unable to open %s\n", batchfile);
|
|
|
|
return 1;
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
ret = 0;
|
2001-08-04 14:19:51 +00:00
|
|
|
while (1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
struct sftp_command *cmd;
|
|
|
|
cmd = sftp_getcmd(fp, mode, modeflags);
|
|
|
|
if (!cmd)
|
|
|
|
break;
|
|
|
|
ret = cmd->obey(cmd);
|
2020-02-05 19:45:27 +00:00
|
|
|
sftp_cmd_free(cmd);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
if (ret == 0) {
|
|
|
|
if (!(modeflags & 2))
|
|
|
|
break;
|
|
|
|
}
|
2001-08-04 14:19:51 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
fclose(fp);
|
|
|
|
/*
|
|
|
|
* In batch mode, and if exit on command failure is enabled,
|
|
|
|
* any command failure causes the whole of PSFTP to fail.
|
|
|
|
*/
|
|
|
|
if (ret == 0 && !(modeflags & 2)) return 2;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|
2015-06-25 22:27:16 +00:00
|
|
|
return 0;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Dirty bits: integration with PuTTY.
|
|
|
|
*/
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool verbose = false;
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2018-09-11 14:02:59 +00:00
|
|
|
void ldisc_echoedit_update(Ldisc *ldisc) { }
|
2021-09-14 09:13:28 +00:00
|
|
|
void ldisc_check_sendok(Ldisc *ldisc) { }
|
2001-02-24 16:08:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Receive a block of data from the SSH link. Block until all data
|
|
|
|
* is available.
|
|
|
|
*
|
|
|
|
* To do this, we repeatedly call the SSH protocol module, with our
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
* own psftp_output() function to catch the data that comes back. We
|
2001-02-24 16:08:56 +00:00
|
|
|
* do this until we have enough data.
|
|
|
|
*/
|
2018-12-01 09:56:32 +00:00
|
|
|
static bufchain received_data;
|
2019-02-20 07:09:10 +00:00
|
|
|
static BinarySink *stderr_bs;
|
2019-02-06 20:42:44 +00:00
|
|
|
static size_t psftp_output(
|
2021-09-16 13:46:49 +00:00
|
|
|
Seat *seat, SeatOutputType type, const void *data, size_t len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-24 16:08:56 +00:00
|
|
|
/*
|
2021-09-16 13:46:49 +00:00
|
|
|
* Non-stdout data (both stderr and SSH auth banners) is just
|
|
|
|
* spouted to local stderr (optionally via a sanitiser) and
|
|
|
|
* otherwise ignored.
|
2001-02-24 16:08:56 +00:00
|
|
|
*/
|
2021-09-16 13:46:49 +00:00
|
|
|
if (type != SEAT_OUTPUT_STDOUT) {
|
2019-02-20 07:09:10 +00:00
|
|
|
put_data(stderr_bs, data, len);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
2018-12-01 09:56:32 +00:00
|
|
|
bufchain_add(&received_data, data, len);
|
2001-08-25 17:09:23 +00:00
|
|
|
return 0;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool psftp_eof(Seat *seat)
|
2011-09-13 11:44:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We expect to be the party deciding when to close the
|
|
|
|
* connection, so if we see EOF before we sent it ourselves, we
|
|
|
|
* should panic.
|
|
|
|
*/
|
|
|
|
if (!sent_eof) {
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
seat_connection_fatal(
|
|
|
|
psftp_seat, "Received unexpected end-of-file from SFTP server");
|
2011-09-13 11:44:03 +00:00
|
|
|
}
|
2018-10-29 19:50:29 +00:00
|
|
|
return false;
|
2011-09-13 11:44:03 +00:00
|
|
|
}
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
2019-02-06 20:42:44 +00:00
|
|
|
bool sftp_recvdata(char *buf, size_t len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2018-12-01 09:56:32 +00:00
|
|
|
while (len > 0) {
|
|
|
|
while (bufchain_size(&received_data) == 0) {
|
|
|
|
if (backend_exitcode(backend) >= 0 ||
|
|
|
|
ssh_sftp_loop_iteration() < 0)
|
|
|
|
return false; /* doom */
|
|
|
|
}
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t got = bufchain_fetch_consume_up_to(&received_data, buf, len);
|
2018-12-01 09:56:32 +00:00
|
|
|
buf += got;
|
|
|
|
len -= got;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
2019-02-06 20:42:44 +00:00
|
|
|
bool sftp_senddata(const char *buf, size_t len)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2018-09-11 15:23:38 +00:00
|
|
|
backend_send(backend, buf, len);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t sftp_sendbuffer(void)
|
2016-04-08 23:24:12 +00:00
|
|
|
{
|
2018-09-11 15:23:38 +00:00
|
|
|
return backend_sendbuffer(backend);
|
2016-04-08 23:24:12 +00:00
|
|
|
}
|
2001-02-24 16:08:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Short description of parameters.
|
|
|
|
*/
|
|
|
|
static void usage(void)
|
|
|
|
{
|
|
|
|
printf("PuTTY Secure File Transfer (SFTP) client\n");
|
|
|
|
printf("%s\n", ver);
|
2004-02-22 14:57:40 +00:00
|
|
|
printf("Usage: psftp [options] [user@]host\n");
|
2001-02-24 16:08:56 +00:00
|
|
|
printf("Options:\n");
|
2005-03-19 02:26:58 +00:00
|
|
|
printf(" -V print version information and exit\n");
|
|
|
|
printf(" -pgpfp print PGP key fingerprints and exit\n");
|
2001-08-04 14:19:51 +00:00
|
|
|
printf(" -b file use specified batchfile\n");
|
|
|
|
printf(" -bc output batchfile commands\n");
|
|
|
|
printf(" -be don't stop batchfile processing if errors\n");
|
2001-02-24 16:08:56 +00:00
|
|
|
printf(" -v show verbose messages\n");
|
2002-09-11 17:30:36 +00:00
|
|
|
printf(" -load sessname Load settings from saved session\n");
|
|
|
|
printf(" -l user connect with specified username\n");
|
2001-02-24 16:08:56 +00:00
|
|
|
printf(" -P port connect to specified port\n");
|
2021-09-28 17:04:15 +00:00
|
|
|
printf(" -pwfile file login with password read from specified file\n");
|
2002-09-11 17:30:36 +00:00
|
|
|
printf(" -1 -2 force use of particular SSH protocol version\n");
|
2021-04-19 14:57:13 +00:00
|
|
|
printf(" -ssh -ssh-connection\n");
|
|
|
|
printf(" force use of particular SSH protocol variant\n");
|
2004-12-30 16:45:11 +00:00
|
|
|
printf(" -4 -6 force use of IPv4 or IPv6\n");
|
2002-09-11 17:30:36 +00:00
|
|
|
printf(" -C enable compression\n");
|
2014-09-20 22:49:47 +00:00
|
|
|
printf(" -i key private key file for user authentication\n");
|
2006-02-19 12:52:28 +00:00
|
|
|
printf(" -noagent disable use of Pageant\n");
|
|
|
|
printf(" -agent enable use of Pageant\n");
|
New option to reject 'trivial' success of userauth.
Suggested by Manfred Kaiser, who also wrote most of this patch
(although outlying parts, like documentation and SSH-1 support, are by
me).
This is a second line of defence against the kind of spoofing attacks
in which a malicious or compromised SSH server rushes the client
through the userauth phase of SSH without actually requiring any auth
inputs (passwords or signatures or whatever), and then at the start of
the connection phase it presents something like a spoof prompt,
intended to be taken for part of userauth by the user but in fact with
some more sinister purpose.
Our existing line of defence against this is the trust sigil system,
and as far as I know, that's still working. This option allows a bit of
extra defence in depth: if you don't expect your SSH server to
trivially accept authentication in the first place, then enabling this
option will cause PuTTY to disconnect if it unexpectedly does so,
without the user having to spot the presence or absence of a fiddly
little sigil anywhere.
Several types of authentication count as 'trivial'. The obvious one is
the SSH-2 "none" method, which clients always try first so that the
failure message will tell them what else they can try, and which a
server can instead accept in order to authenticate you unconditionally.
But there are two other ways to do it that we know of: one is to run
keyboard-interactive authentication and send an empty INFO_REQUEST
packet containing no actual prompts for the user, and another even
weirder one is to send USERAUTH_SUCCESS in response to the user's
preliminary *offer* of a public key (instead of sending the usual PK_OK
to request an actual signature from the key).
This new option detects all of those, by clearing the 'is_trivial_auth'
flag only when we send some kind of substantive authentication response
(be it a password, a k-i prompt response, a signature, or a GSSAPI
token). So even if there's a further path through the userauth maze we
haven't spotted, that somehow avoids sending anything substantive, this
strategy should still pick it up.
2021-06-19 14:39:15 +00:00
|
|
|
printf(" -no-trivial-auth\n");
|
|
|
|
printf(" disconnect if SSH authentication succeeds trivially\n");
|
2021-03-27 17:33:54 +00:00
|
|
|
printf(" -hostkey keyid\n");
|
2014-09-20 22:49:47 +00:00
|
|
|
printf(" manually specify a host key (may be repeated)\n");
|
2002-09-11 17:30:36 +00:00
|
|
|
printf(" -batch disable all interactive prompts\n");
|
2019-02-20 07:09:10 +00:00
|
|
|
printf(" -no-sanitise-stderr don't strip control chars from"
|
|
|
|
" standard error\n");
|
2017-02-11 23:03:46 +00:00
|
|
|
printf(" -proxycmd command\n");
|
|
|
|
printf(" use 'command' as local proxy\n");
|
2015-11-08 11:57:39 +00:00
|
|
|
printf(" -sshlog file\n");
|
|
|
|
printf(" -sshrawlog file\n");
|
|
|
|
printf(" log protocol details to a file\n");
|
2020-11-25 15:12:56 +00:00
|
|
|
printf(" -logoverwrite\n");
|
|
|
|
printf(" -logappend\n");
|
|
|
|
printf(" control what happens when a log file already exists\n");
|
2002-03-06 20:13:22 +00:00
|
|
|
cleanup_exit(1);
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
2004-04-17 20:25:09 +00:00
|
|
|
static void version(void)
|
|
|
|
{
|
2017-01-21 14:55:53 +00:00
|
|
|
char *buildinfo_text = buildinfo("\n");
|
|
|
|
printf("psftp: %s\n%s\n", ver, buildinfo_text);
|
|
|
|
sfree(buildinfo_text);
|
2017-02-15 19:50:14 +00:00
|
|
|
exit(0);
|
2004-04-17 20:25:09 +00:00
|
|
|
}
|
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
/*
|
2001-12-13 18:42:34 +00:00
|
|
|
* Connect to a host.
|
2001-02-24 16:08:56 +00:00
|
|
|
*/
|
2001-12-13 18:42:34 +00:00
|
|
|
static int psftp_connect(char *userhost, char *user, int portnumber)
|
2001-02-24 16:08:56 +00:00
|
|
|
{
|
2001-12-13 18:42:34 +00:00
|
|
|
char *host, *realhost;
|
2003-05-04 14:18:18 +00:00
|
|
|
const char *err;
|
2001-02-24 16:08:56 +00:00
|
|
|
|
|
|
|
/* Separate host and username */
|
|
|
|
host = userhost;
|
|
|
|
host = strrchr(host, '@');
|
|
|
|
if (host == NULL) {
|
2019-09-08 19:29:00 +00:00
|
|
|
host = userhost;
|
2001-02-24 16:08:56 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
*host++ = '\0';
|
|
|
|
if (user) {
|
|
|
|
printf("psftp: multiple usernames specified; using \"%s\"\n",
|
|
|
|
user);
|
|
|
|
} else
|
|
|
|
user = userhost;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
2004-07-25 14:00:26 +00:00
|
|
|
/*
|
|
|
|
* If we haven't loaded session details already (e.g., from -load),
|
|
|
|
* try looking for a session called "host".
|
|
|
|
*/
|
2020-01-30 06:40:22 +00:00
|
|
|
if (!cmdline_loaded_session()) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Try to load settings for `host' into a temporary config */
|
|
|
|
Conf *conf2 = conf_new();
|
|
|
|
conf_set_str(conf2, CONF_host, "");
|
|
|
|
do_defaults(host, conf2);
|
|
|
|
if (conf_get_str(conf2, CONF_host)[0] != '\0') {
|
|
|
|
/* Settings present and include hostname */
|
|
|
|
/* Re-load data into the real config. */
|
|
|
|
do_defaults(host, conf);
|
|
|
|
} else {
|
|
|
|
/* Session doesn't exist or mention a hostname. */
|
|
|
|
/* Use `host' as a bare hostname. */
|
|
|
|
conf_set_str(conf, CONF_host, host);
|
|
|
|
}
|
2013-07-22 19:55:55 +00:00
|
|
|
conf_free(conf2);
|
2004-07-25 14:00:26 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Patch in hostname `host' to session details. */
|
|
|
|
conf_set_str(conf, CONF_host, host);
|
2002-10-07 17:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-02-22 15:29:45 +00:00
|
|
|
* Force protocol to SSH if the user has somehow contrived to
|
|
|
|
* select one we don't support (e.g. by loading an inappropriate
|
|
|
|
* saved session). In that situation we assume the port number is
|
|
|
|
* useless too.)
|
2002-10-07 17:31:52 +00:00
|
|
|
*/
|
2020-02-22 15:29:45 +00:00
|
|
|
if (!backend_vt_from_proto(conf_get_int(conf, CONF_protocol))) {
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_set_int(conf, CONF_protocol, PROT_SSH);
|
|
|
|
conf_set_int(conf, CONF_port, 22);
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
2004-07-25 16:10:48 +00:00
|
|
|
/*
|
|
|
|
* If saved session / Default Settings says SSH-1 (`1 only' or `1'),
|
|
|
|
* then change it to SSH-2, on the grounds that that's more likely to
|
|
|
|
* work for SFTP. (Can be overridden with `-1' option.)
|
|
|
|
* But if it says `2 only' or `2', respect which.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if ((conf_get_int(conf, CONF_sshprot) & ~1) != 2) /* is it 2 or 3? */
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int(conf, CONF_sshprot, 2);
|
2004-07-25 16:10:48 +00:00
|
|
|
|
2002-08-04 21:18:56 +00:00
|
|
|
/*
|
|
|
|
* Enact command-line overrides.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
cmdline_run_saved(conf);
|
2002-08-04 21:18:56 +00:00
|
|
|
|
2001-10-30 21:45:27 +00:00
|
|
|
/*
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
* Muck about with the hostname in various ways.
|
2001-10-30 21:45:27 +00:00
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
|
|
|
|
char *host = hostbuf;
|
|
|
|
char *p, *q;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Trim leading whitespace.
|
|
|
|
*/
|
|
|
|
host += strspn(host, " \t");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See if host is of the form user@host, and separate out
|
|
|
|
* the username if so.
|
|
|
|
*/
|
|
|
|
if (host[0] != '\0') {
|
|
|
|
char *atsign = strrchr(host, '@');
|
|
|
|
if (atsign) {
|
|
|
|
*atsign = '\0';
|
|
|
|
conf_set_str(conf, CONF_username, host);
|
|
|
|
host = atsign + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove any remaining whitespace.
|
|
|
|
*/
|
|
|
|
p = hostbuf;
|
|
|
|
q = host;
|
|
|
|
while (*q) {
|
|
|
|
if (*q != ' ' && *q != '\t')
|
|
|
|
*p++ = *q;
|
|
|
|
q++;
|
|
|
|
}
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
conf_set_str(conf, CONF_host, hostbuf);
|
|
|
|
sfree(hostbuf);
|
2002-10-16 11:35:13 +00:00
|
|
|
}
|
|
|
|
|
2001-02-24 16:08:56 +00:00
|
|
|
/* Set username */
|
|
|
|
if (user != NULL && user[0] != '\0') {
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_str(conf, CONF_username, user);
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (portnumber)
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int(conf, CONF_port, portnumber);
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2001-09-12 20:11:48 +00:00
|
|
|
/*
|
|
|
|
* Disable scary things which shouldn't be enabled for simple
|
|
|
|
* things like SCP and SFTP: agent forwarding, port forwarding,
|
|
|
|
* X forwarding.
|
|
|
|
*/
|
2018-10-29 19:57:31 +00:00
|
|
|
conf_set_bool(conf, CONF_x11_forward, false);
|
|
|
|
conf_set_bool(conf, CONF_agentfwd, false);
|
|
|
|
conf_set_bool(conf, CONF_ssh_simple, true);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
char *key;
|
|
|
|
while ((key = conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) != NULL)
|
|
|
|
conf_del_str_str(conf, CONF_portfwd, key);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
2001-09-12 20:11:48 +00:00
|
|
|
|
2001-09-05 19:48:52 +00:00
|
|
|
/* Set up subsystem name. */
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_set_str(conf, CONF_remote_cmd, "sftp");
|
2018-10-29 19:57:31 +00:00
|
|
|
conf_set_bool(conf, CONF_ssh_subsys, true);
|
|
|
|
conf_set_bool(conf, CONF_nopty, true);
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2001-09-05 19:48:52 +00:00
|
|
|
/*
|
2005-03-10 16:36:05 +00:00
|
|
|
* Set up fallback option, for SSH-1 servers or servers with the
|
2001-09-05 19:48:52 +00:00
|
|
|
* sftp subsystem not enabled but the server binary installed
|
|
|
|
* in the usual place. We only support fallback on Unix
|
2001-09-05 19:58:25 +00:00
|
|
|
* systems, and we use a kludgy piece of shellery which should
|
|
|
|
* try to find sftp-server in various places (the obvious
|
|
|
|
* systemwide spots /usr/lib and /usr/local/lib, and then the
|
|
|
|
* user's PATH) and finally give up.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-09-05 19:58:25 +00:00
|
|
|
* test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server
|
|
|
|
* test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server
|
|
|
|
* exec sftp-server
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-09-05 19:48:52 +00:00
|
|
|
* the idea being that this will attempt to use either of the
|
|
|
|
* obvious pathnames and then give up, and when it does give up
|
|
|
|
* it will print the preferred pathname in the error messages.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_set_str(conf, CONF_remote_cmd2,
|
2019-09-08 19:29:00 +00:00
|
|
|
"test -x /usr/lib/sftp-server &&"
|
|
|
|
" exec /usr/lib/sftp-server\n"
|
|
|
|
"test -x /usr/local/lib/sftp-server &&"
|
|
|
|
" exec /usr/local/lib/sftp-server\n"
|
|
|
|
"exec sftp-server");
|
2018-10-29 19:57:31 +00:00
|
|
|
conf_set_bool(conf, CONF_ssh_subsys2, false);
|
2001-09-05 19:48:52 +00:00
|
|
|
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
psftp_logctx = log_init(console_cli_logpolicy, conf);
|
2017-02-11 00:23:36 +00:00
|
|
|
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
platform_psftp_pre_conn_setup(console_cli_logpolicy);
|
2017-02-11 00:44:00 +00:00
|
|
|
|
2020-02-22 15:29:45 +00:00
|
|
|
err = backend_init(backend_vt_from_proto(
|
|
|
|
conf_get_int(conf, CONF_protocol)),
|
|
|
|
psftp_seat, &backend, psftp_logctx, conf,
|
2018-09-11 15:23:38 +00:00
|
|
|
conf_get_str(conf, CONF_host),
|
|
|
|
conf_get_int(conf, CONF_port),
|
|
|
|
&realhost, 0,
|
2018-10-29 19:57:31 +00:00
|
|
|
conf_get_bool(conf, CONF_tcp_keepalives));
|
2001-02-24 16:08:56 +00:00
|
|
|
if (err != NULL) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fprintf(stderr, "ssh_init: %s\n", err);
|
|
|
|
return 1;
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
2018-09-11 15:23:38 +00:00
|
|
|
while (!backend_sendok(backend)) {
|
|
|
|
if (backend_exitcode(backend) >= 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
return 1;
|
|
|
|
if (ssh_sftp_loop_iteration() < 0) {
|
|
|
|
fprintf(stderr, "ssh_init: error during SSH connection setup\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2003-08-24 12:47:46 +00:00
|
|
|
}
|
2001-02-24 16:08:56 +00:00
|
|
|
if (verbose && realhost != NULL)
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("Connected to %s\n", realhost);
|
2003-12-19 12:44:46 +00:00
|
|
|
if (realhost != NULL)
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(realhost);
|
2001-12-13 18:42:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
void cmdline_error(const char *p, ...)
|
2002-08-04 21:18:56 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2002-11-20 20:09:02 +00:00
|
|
|
fprintf(stderr, "psftp: ");
|
2002-08-04 21:18:56 +00:00
|
|
|
va_start(ap, p);
|
|
|
|
vfprintf(stderr, p, ap);
|
|
|
|
va_end(ap);
|
2002-11-20 20:09:02 +00:00
|
|
|
fprintf(stderr, "\n try typing \"psftp -h\" for help\n");
|
2002-08-04 21:18:56 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
const bool share_can_be_downstream = true;
|
|
|
|
const bool share_can_be_upstream = false;
|
2013-11-17 14:05:41 +00:00
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
static stdio_sink stderr_ss;
|
|
|
|
static StripCtrlChars *stderr_scc;
|
|
|
|
|
2020-01-30 06:40:22 +00:00
|
|
|
const unsigned cmdline_tooltype = TOOLTYPE_FILETRANSFER;
|
|
|
|
|
2001-12-13 18:42:34 +00:00
|
|
|
/*
|
|
|
|
* Main program. Parse arguments etc.
|
|
|
|
*/
|
2003-08-24 12:47:46 +00:00
|
|
|
int psftp_main(int argc, char *argv[])
|
2001-12-13 18:42:34 +00:00
|
|
|
{
|
2015-06-25 22:27:16 +00:00
|
|
|
int i, ret;
|
2001-12-13 18:42:34 +00:00
|
|
|
int portnumber = 0;
|
|
|
|
char *userhost, *user;
|
|
|
|
int mode = 0;
|
|
|
|
int modeflags = 0;
|
2019-02-20 07:09:10 +00:00
|
|
|
bool sanitise_stderr = true;
|
2001-12-13 18:42:34 +00:00
|
|
|
char *batchfile = NULL;
|
|
|
|
|
|
|
|
sk_init();
|
|
|
|
|
|
|
|
userhost = user = NULL;
|
|
|
|
|
2004-07-25 14:00:26 +00:00
|
|
|
/* Load Default Settings before doing anything else. */
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf = conf_new();
|
|
|
|
do_defaults(NULL, conf);
|
2004-07-25 14:00:26 +00:00
|
|
|
|
2001-12-13 18:42:34 +00:00
|
|
|
for (i = 1; i < argc; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int ret;
|
|
|
|
if (argv[i][0] != '-') {
|
2002-08-04 21:18:56 +00:00
|
|
|
if (userhost)
|
|
|
|
usage();
|
|
|
|
else
|
|
|
|
userhost = dupstr(argv[i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, conf);
|
|
|
|
if (ret == -2) {
|
|
|
|
cmdline_error("option \"%s\" requires an argument", argv[i]);
|
|
|
|
} else if (ret == 2) {
|
|
|
|
i++; /* skip next argument */
|
|
|
|
} else if (ret == 1) {
|
|
|
|
/* We have our own verbosity in addition to `flags'. */
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
if (cmdline_verbose())
|
2019-09-08 19:29:00 +00:00
|
|
|
verbose = true;
|
|
|
|
} else if (strcmp(argv[i], "-h") == 0 ||
|
|
|
|
strcmp(argv[i], "-?") == 0 ||
|
2012-09-19 17:08:15 +00:00
|
|
|
strcmp(argv[i], "--help") == 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
usage();
|
2005-03-19 02:26:58 +00:00
|
|
|
} else if (strcmp(argv[i], "-pgpfp") == 0) {
|
|
|
|
pgp_fingerprints();
|
|
|
|
return 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (strcmp(argv[i], "-V") == 0 ||
|
2012-09-19 17:08:15 +00:00
|
|
|
strcmp(argv[i], "--version") == 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
version();
|
|
|
|
} else if (strcmp(argv[i], "-batch") == 0) {
|
|
|
|
console_batch_mode = true;
|
|
|
|
} else if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) {
|
|
|
|
mode = 1;
|
|
|
|
batchfile = argv[++i];
|
|
|
|
} else if (strcmp(argv[i], "-bc") == 0) {
|
|
|
|
modeflags = modeflags | 1;
|
|
|
|
} else if (strcmp(argv[i], "-be") == 0) {
|
|
|
|
modeflags = modeflags | 2;
|
2019-02-20 07:09:10 +00:00
|
|
|
} else if (strcmp(argv[i], "-sanitise-stderr") == 0) {
|
|
|
|
sanitise_stderr = true;
|
|
|
|
} else if (strcmp(argv[i], "-no-sanitise-stderr") == 0) {
|
|
|
|
sanitise_stderr = false;
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (strcmp(argv[i], "--") == 0) {
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
cmdline_error("unknown option \"%s\"", argv[i]);
|
|
|
|
}
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
|
|
|
argc -= i;
|
|
|
|
argv += i;
|
2018-09-11 15:23:38 +00:00
|
|
|
backend = NULL;
|
2001-12-13 18:42:34 +00:00
|
|
|
|
2019-02-20 07:09:10 +00:00
|
|
|
stdio_sink_init(&stderr_ss, stderr);
|
|
|
|
stderr_bs = BinarySink_UPCAST(&stderr_ss);
|
|
|
|
if (sanitise_stderr) {
|
|
|
|
stderr_scc = stripctrl_new(stderr_bs, false, L'\0');
|
|
|
|
stderr_bs = BinarySink_UPCAST(stderr_scc);
|
|
|
|
}
|
|
|
|
|
2019-03-09 16:03:40 +00:00
|
|
|
string_scc = stripctrl_new(NULL, false, L'\0');
|
|
|
|
|
2004-07-28 11:04:22 +00:00
|
|
|
/*
|
|
|
|
* If the loaded session provides a hostname, and a hostname has not
|
|
|
|
* otherwise been specified, pop it in `userhost' so that
|
|
|
|
* `psftp -load sessname' is sufficient to start a session.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (!userhost && conf_get_str(conf, CONF_host)[0] != '\0') {
|
2019-09-08 19:29:00 +00:00
|
|
|
userhost = dupstr(conf_get_str(conf, CONF_host));
|
2004-07-28 11:04:22 +00:00
|
|
|
}
|
|
|
|
|
2001-12-13 18:42:34 +00:00
|
|
|
/*
|
|
|
|
* If a user@host string has already been provided, connect to
|
|
|
|
* it now.
|
|
|
|
*/
|
|
|
|
if (userhost) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int ret;
|
|
|
|
ret = psftp_connect(userhost, user, portnumber);
|
|
|
|
sfree(userhost);
|
|
|
|
if (ret)
|
|
|
|
return 1;
|
|
|
|
if (do_sftp_init())
|
|
|
|
return 1;
|
2001-12-13 18:42:34 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
printf("psftp: no hostname specified; use \"open host.name\""
|
|
|
|
" to connect\n");
|
2001-12-13 18:42:34 +00:00
|
|
|
}
|
2001-02-23 18:21:44 +00:00
|
|
|
|
2015-06-25 22:27:16 +00:00
|
|
|
ret = do_sftp(mode, modeflags, batchfile);
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend && backend_connected(backend)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char ch;
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
backend_special(backend, SS_EOF, 0);
|
2018-10-29 19:50:29 +00:00
|
|
|
sent_eof = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
sftp_recvdata(&ch, 1);
|
2001-02-24 16:08:56 +00:00
|
|
|
}
|
2004-12-16 19:19:59 +00:00
|
|
|
do_sftp_cleanup();
|
2001-02-24 16:08:56 +00:00
|
|
|
random_save_seed();
|
2003-12-19 12:44:46 +00:00
|
|
|
cmdline_cleanup();
|
|
|
|
sk_cleanup();
|
2001-02-24 16:08:56 +00:00
|
|
|
|
2019-07-06 16:44:15 +00:00
|
|
|
stripctrl_free(string_scc);
|
|
|
|
stripctrl_free(stderr_scc);
|
|
|
|
|
|
|
|
if (psftp_logctx)
|
|
|
|
log_free(psftp_logctx);
|
|
|
|
|
2015-06-25 22:27:16 +00:00
|
|
|
return ret;
|
2001-02-23 18:21:44 +00:00
|
|
|
}
|