[scponly] getopt problem with long options
Chris Fensch
cf-scponly at fens.ch
Tue Jan 17 12:27:52 EST 2006
Hi,
I just wanted to let you guys know that after I upgraded from 4.1 to 4.3
(I missed the 4.2 release), I experienced some problems with rsync:
Jan 16 08:01:05 XXX scponly[22052]: option e is not permitted for use
with /usr/bin/rsync (arg was rver)(username: XXX(XXX), IP/port:
::ffff:XXX.XXX.XXX.XXX 25942 22))
Jan 16 08:01:05 XXX scponly[22052]: requested command (/usr/bin/rsync
--server -logDtprz --delete . /backup/subversion/) tried to use disallowed
argument (username: XXX(XXX), IP/port: ::ffff:XXX.XXX.XXX.XXX 25942 22))
As you can see the command was not dangerous at all. However, the
long argument '--server' gets parsed by getopt as:
'-' -> invalid/ignore
's' -> invalid/ignore
'e' -> valid 'e', argument 'rver'
For some reason the version of getopt on my system Linux / glibc 2.3.3,
cannot probably deal with long arguments (starting with a double dash
'--').
I found a solution, by using getopt_long instead of getopt. I don't know
if this is available on all system. In order to use, you simply have to
replace the "while ((ch = getopt ..." call in helper.c with:
struct option long_opt[] = {
{0, 0, 0, 0}
};
while ((ch = getopt_long(ac, av, cmdarg->opts, long_opt, NULL)) != -1)
The empty long_opt structure is necessary, otherwise you will get the same
broken behaviour regarding long options again. Also, in order for this to
compile, you have to include getopt.h, which isn't because, it is guarded
by #ifdef HAVE_GETOPT_H. HAVE_GETOPT_H will be defined in config.h, which
is included later. So you have to change the order of includes here.
Oh, and some notes on the "optreset" issue. It seems to me that with
glibc, setting "optind" to 1 seems enough to reset getopt or getopt_long.
According to the documentation in the getopt.c glibc source:
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* 1003.2 says this must be 1 before any call. */
int optind = 1;
As far as I understand the source code, it will also initialise (even if
optind == 1), if it is not initialised sofar. But, if you set optind = 0,
then it will run a reinitialisation.
Best Regards and I hope someone might find this useful
Chris
More information about the scponly
mailing list