Closed ricardopadilha closed 3 years ago
Thanks for reporting that possible issue.
I've just tested wsdd on a Linux machine with the -n/--hostname
option and provided a name with a dash, but I also tried changing the hostname accordingly using hostnamectl --set-hostname
and ran wsdd without any arguments. In both cases the host appears in the Network view of the Explorer - without quotes. This even applies to "Eric-5N2".
Could you please provide the following information:
hostname -f
python3 -c 'import socket; print(socket.gethostname())'
I further assume you are using Windows 10. Is that correct?
How do you launch wsdd?
From a shell script, using start-stop-daemon from busybox. The command line is (including the variables generated in the script):
start() {
local name
local options="--preserve-case --user nobody:nobody --chroot ${tmp_dir}"
_firmware_check
name=$(_host_name)
if [ ! -z "${name}" ]; then
options="${options:-} --hostname \"${name}\""
fi
name=$(_workgroup_name)
if [ ! -z "${name}" ]; then
options="${options:-} --workgroup \"${name}\""
fi
name=$(_domain_name)
if [ ! -z "${name}" ]; then
options="${options:-} --domain \"${name}\""
fi
start-stop-daemon -S --oknodo --background --make-pidfile --pidfile "${pidfile}" --exec "${daemon}" -- ${options} &> "${logfile}"
}
This ends up looking like this in the output of ps axw
:
python3 /mnt/DroboFS/Shares/DroboApps/wsdd/sbin/wsdd.py --preserve-case --user nobody:nobody --chroot /tmp/DroboApps/wsdd --hostname "Eric-5N2" --workgroup "WORKGROUP"
Which OS you are running wsdd on?
This is an embedded Linux NAS, running kernel 3.2.96 and busybox. If you need, I can dig the rest, but it is pretty spartan. Python 3.9.7 was cross-compiled from source.
# hostname -f
Eric-5N2
# python3 -c 'import socket; print(socket.gethostname())'
Eric-5N2
I further assume you are using Windows 10. Is that correct?
The client machine is running Windows 10 Home edition, yes.
Huh, I changed the script so that the start-stop-daemon line ends up like this:
python3 /mnt/DroboFS/Shares/DroboApps/wsdd/sbin/wsdd.py --preserve-case --user nobody:nobody --chroot /tmp/DroboApps/wsdd --hostname Eric-5N2 --workgroup WORKGROUP
(i.e., without the additional quotes) and it worked fine.
This is very strange. The quotes are there as part of safe scripting practices, that is, quote strings values whenever possible. I'm kind of surprised that python3 is getting the quotes at all.
I'm pretty sure that hostnames and workgroup names can't have spaces in them, but what about domain names? Could the --domain
argument be a string with spaces?
Alright, you already noticed what's going on here.
This ends up looking like this in the output of
ps axw
:python3 /mnt/DroboFS/Shares/DroboApps/wsdd/sbin/wsdd.py --preserve-case --user nobody:nobody --chroot /tmp/DroboApps/wsdd --hostname "Eric-5N2" --workgroup "WORKGROUP"
Apparently, you are actually providing a hostname that contains quotes (and a workgroup containing them as well). Notice that the command line you are seeing in the ps output (or htop, or similar tools) show you what Python receives, not what a shell would interpret. So you pass quotes and... you get quotes.
The quotes are there as part of safe scripting practices, that is, quote strings values whenever possible. I'm kind of surprised that python3 is getting the quotes at all.
In principle quotes are good. But you construct a command from variables here. Notice that a variable is expanded only once by the shell. If a variable contains quotes they are used as they are. If you want another substitution pass you need eval
:
$ name=foo
$ options="here comes my hostname \"${name}\" \$SHELL"
$ echo $options
here comes my hostname "foo" $SHELL
$ eval echo $options
here comes my hostname foo /bin/bash
I'm pretty sure that hostnames and workgroup names can't have spaces in them
I am note sure if the "Computer Name" that is shown in the network view of Explorer can contain spaces, but I doubt it. If it would work for discovery/display then it would not work for resolving the hostname. Same goes for the domain name. I am not sure about the work group name, but that's archaic anyway.
In the startup script you do something like this:
name=$(_host_name) if [ ! -z "${name}" ]; then options="${options:-} --hostname \"${name}\"" fi
I am not sure, what _host_name
is doing. But if it just returns the output of hostname
then there is actually no need for this block and you can remove it. Wsdd automatically uses the hostname of the machine it runs on.
So you pass quotes and... you get quotes.
I mean, technically I want the quotes because if there is a chance that a hostname can have spaces, I would rather be safe than sorry. Oh well, if passing a hostname with quotes is too troublesome, then I'll just leave it without.
Side note: I want the outcome of the second line, but in the sense that a string that potentially has spaces remains quoted. It is obvious to me now that I'm going the wrong way about it, but I wonder if there is a way to do that without invoking eval, and adding even more backslashes.
But if it just returns the output of hostname then there is actually no need for this block and you can remove it
It reads the hostname from a config file. In theory, it should match the output of hostname, but it may happen that hostname is not yet configured by the time wsdd is started. The only guarantee that I have is that eventually the hostname will be the value from the config file. I know it is weird, but then again, we're talking about embedded Linux here.
In any case, if neither hostnames, domain names, or workgroup names can have spaces, I guess this issue is solved. I'll try to find a way to get the quoting right, but that is not a wsdd issue. Thanks again for the help.
So you pass quotes and... you get quotes.
I mean, technically I want the quotes because if there is a chance that a hostname can have spaces, I would rather be safe than sorry. Oh well, if passing a hostname with quotes is too troublesome, then I'll just leave it without.
But actually, the way spaces are handled above does not protect you "against" spaces. Instead, it breaks functionality.
Let me demonstrate this with a small shell script named args.sh
that is a placeholder for start-stop-daemon
or wsdd
and just prints the arguments as they would be seen by any program (e.g., like argv in C)
#!/bin/bash
for arg in "$@"; do echo " * arg <${arg}>"; done
$ ./args.sh 1 "2 3" 4
* arg <1>
* arg <2 3>
* arg <4>
Now lets do the stuff from the startup/init script:
$ name="foo"
$ options="--hostname \"${name}\""
$ echo $options
--hostname "foo"
$ ./args.sh $options
* arg <--hostname>
* arg <"foo">
That's the original "quote problem". Now lets change the name such that it contains spaces
$ name="foo bar" # notice multiple spaces
$ options="--hostname \"${name}\""
$ echo $options
--hostname "foo bar" # only a single space between foo and bar
$ ./args.sh $options
* arg <--hostname>
* arg <"foo>
* arg <bar">
That's definitely not the intention. Instead of two arguments, the application is presented with three and two of them contain a single instance of a quote character. That's what I meant with my unprecise statement "If a variable contains quotes they are used as they are". The reason why one gets three arguments is the word splitting that happens during expansion.
The simple solution here would be eval, which is often considered evil. If you can trust all inputs, the eval approach might be good. Otherwise you should use arrays or make use of parameter expansion with alternate values. Refer to the Bash FAQ #50 for a clean solution.
But if it just returns the output of hostname then there is actually no need for this block and you can remove it
It reads the hostname from a config file. [...]
Ok. I understand.
Instead of two arguments, the application is presented with three and two of them contain a single instance of a quote character.
Yep, in retrospect it seems obvious. It goes to show that perhaps the easiest (safest?) way to do this would be to pass the arguments via env variable or a config file.
If you can trust all inputs, the eval approach might be good.
My use case probably fits that description, and if that is indeed the case, I might as well trust my input not to have spaces, as it shouldn't have in the first place.
Regardless, thanks again for the help troubleshooting this.
Hi,
I've been trying to run wsdd on a Linux machine, and I noticed that if my hostname contains a dash (e.g., "computer-name"), then Windows 10 machines list the Linux machine with quotes in Windows Explorer. If I try to click the quoted name, the connection fails.
Here's a screen capture of what appears on Windows Explorer:
If I use a name without a dash, then everything works fine. Is there some option or argument that I should be using?