| Summary: | Report wrong command-line options | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | Portable OpenSSH | Reporter: | bonniot | ||||||||
| Component: | scp | Assignee: | Assigned to nobody <unassigned-bugs> | ||||||||
| Status: | CLOSED FIXED | ||||||||||
| Severity: | normal | CC: | djm, dtucker | ||||||||
| Priority: | P2 | Keywords: | low-hanging-fruit | ||||||||
| Version: | 4.6p1 | ||||||||||
| Hardware: | Other | ||||||||||
| OS: | Linux | ||||||||||
| Bug Depends on: | |||||||||||
| Bug Blocks: | 2076 | ||||||||||
| Attachments: |
|
||||||||||
|
Description
bonniot
2008-03-18 03:25:22 AEDT
To clarify, this is the case with long options (starting with --...). Example: touch a; scp --foobarbaz a b does not report any error or warning. scp does report unknown options:
$ scp -X a: b:
scp: illegal option -- X
usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
[-l limit] [-o ssh_option] [-P port] [-S program]
[[user@]host1:]file1 ... [[user@]host2:]file2
It also reports --options options on OpenBSD:
$ scp --blah a: b:
scp: illegal option -- -
usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
[-l limit] [-o ssh_option] [-P port] [-S program]
[[user@]host1:]file1 ... [[user@]host2:]file2
I think what is happening that GNU getopt is swallowing the long options before scp sees them. There isn't much scp could do here except perhaps avoid the system getopt() for its own and I don't think this is worth it.
I don't know scp interracts with getopt. But it seems to me that either getopt offers a way to know that that long option was given, and scp could fail/warn if it does not know the option. Or getopt does not allow that, and a bug report/feature request is in order. whatever it is, it doesn't seem to be gnu-getopt specific. or if it is, it's not enabled with the default set of defines.
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int ch;
while ((ch = getopt(argc, argv, "abc:")) != -1) {
printf("opt %c optarg %s\n", ch, optarg ? optarg : "(null)");
}
}
gives me:
$ ./a.out --foo
./a.out: invalid option -- '-'
opt ? optarg (null)
./a.out: invalid option -- 'f'
opt ? optarg (null)
./a.out: invalid option -- 'o'
opt ? optarg (null)
./a.out: invalid option -- 'o'
opt ? optarg (null)
whatever it is, I think it's in our compat library:
$ nm scp | grep -i getop
08051710 T BSDgetopt
sure looks like something of ours: $ gcc getopt-test.c -Dgetopt=BSDgetopt openbsd-compat/libopenbsd-compat.a $ ./a.out -a opt a optarg (null) $ ./a.out --foo $ ok, so it turns out the original upstream source in OpenBSD's getopt.c had the same behaviour, but was replaced in 2004 with getopt_long.c which doesn't. For long-term maintainability I think we should switch. What I'm going to do is 1) factor out the portability changes in getopt.c 2) add getopt_long.c to openssh and remove getopt.c 3) pull the portability changes into getopt_long.c Created attachment 2257 [details]
Factor out portability changes in getopt.c
Created attachment 2258 [details]
import getopt_long.c from openbsd
Created attachment 2259 [details]
apply portability changes to getopt_long.c switch over to it and remove getopt.c
With these changes I get the following for your testcase:
$ touch a; ./scp --foobarbaz a b
unknown option -- -
usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
[-l limit] [-o ssh_option] [-P port] [-S program]
[[user@]host1:]file1 ... [[user@]host2:]file2
Thanks for the report (and patience :-). These changes will be in the 6.3p1 release.
Thank you for the fix :) Any chance the portability fixes could be applied upstream? It's already as upstream as it gets. The file with the bug in openbsd is dead, and the current version of the current file is fine. Set all RESOLVED bugs to CLOSED with release of OpenSSH 7.1 |