How to use Process() with an argument containing a semicolon?

Hi!

I have an issue calling mount_smbfs with a user from a specific domain. A sample shell call is

mount_smbfs -N -o nodev,nosuid "//DOMAIN;USER:PASS@SERVER_ADDRESS" /SOMEPATH

Using the code below I get an invalid command because the semicolon ends the command in shell.

var server     = "//DOMAIN;USER:PASS@SERVER_ADDRESS"
let remotePath = "/REMOTEPATH"
let localPath  = "/LOCALPATH"
let cmd  = Process()

cmd.executableURL = URL(fileURLWithPath: "/sbin/mount_smbfs")
cmd.arguments     = ["-N", "-o nodev,nosuid", "\(server)\(remotePath)", localPath]

Using a quoted semicolon

var server     = "//DOMAIN\;USER:PASS@SERVER_ADDRESS"

does also not work, because the backslash is quoted to DOMAIN\\;USER automatically via Process class. So I end up with two backslash.

Using quotes did also not work for me.

Any clue how to solve this issue?

Have you tried to escape the semi colon (replacing with its % equivalent) ?

No. I tried backslash quoting and quotes.

Unfortunately it does not work using percent encoding. In Terminal I get this error:

$ mount_smbfs -N -o nodev,nosuid "//DOMAIN%59USER:PASS@SERVER_ADDRESS/REMOTEPATH" /LOCALPATH
mount_smbfs: server rejected the connection: Authentication error

Also it does not work in my application.

Oops. The code has to be Hex encoded. It does also not work:

$ mount_smbfs -N -o nodev,nosuid "//DOMAIN%3BUSER:PASS@SERVER_ADDRESS/REMOTEPATH" /LOCALPATH
mount_smbfs: server rejected the connection: Authentication error
Accepted Answer

Process doesn’t run a shell. Rather, the arguments you pass to it get sent directly to the kernel which passes them verbatim to the child process. For example, this code:

import Foundation

func main() throws {
    let p = Process()
    p.executableURL = URL(fileURLWithPath: "/Users/quinn/echo.sh")
    p.arguments = [ "Hello;Goodbye", "~/Cruel", "World", "!" ]
    try p.run()
    p.waitUntilExit()
}

try! main()

running this script:

% cat echo.sh
#! /bin/sh

while [ $# -gt 0 ]
do
    echo $1
    shift
done

prints:

Hello;Goodbye
~/Cruel
World
!

Note that the semicolon is passed through, there’s no expansion of ~, and the ! isn’t interpreted.

The problem with your Process code is that you’re passing -o nodev,nosuid as one argument, whereas the shell passes it as two. Consider this:

% /Users/quinn/echo.sh -o nodev,nosuid "//DOMAIN;USER:PASS@SERVER_ADDRESS" /SOMEPATH
-o
nodev,nosuid
//DOMAIN;USER:PASS@SERVER_ADDRESS
/SOMEPATH

As to how you get mount_smbfs to do what you want, that’s not really my area of expertise. However, if you can get it working from the shell then I can explain how to achieve the same result using Process.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for your explanation. My assumption was obviously wrong.

In fact the command

mount_smbfs -onodev,nosuid "//DOMAIN;USER:PASS@SERVER_ADDRESS/REMOTEPATH" /SOMEPATH

works well in shell. Note: The password needs a HTML like % encoding for funny chars, e.g. "my%23pass" for "my#pass".

I use a similar call already with sshfs on a Linux server. Now I will perform some more debugging to get a clue what's wrong. I will post a reply with my discoveries.

Now I got it working. I fixed the "-o" option by removing the space and removed all additional quoting.

Many thanks for your help (again).

How to use Process() with an argument containing a semicolon?
 
 
Q