exec path problems

An exec Gotcha

Tcl looks for a command to be exec'ed in a sequence of directories, part of which includes the PATH. Exactly what name exec searches for (command vs command.exe vs command.bat, etc.) and the sequence of directories searched differs among operating systems and is nicely documented in the exec man page: https://www.tcl-lang.org/man/tcl/TclCmd/exec.htm

A potential gotcha occurs when the PATH used by the user's shell differs from the directories examined by Tcl. The two programs may well look in the same directories but may not do so in the same sequence. This is a problem for all programs that need to execute external programs, and isn't restricted to interpreters such as Tcl/Perl/Python/PHP.

When this happens, calling the command from the shell or commandline (say Dos) works but execing it from Tcl either fails completely or calls a different program with the same name. This is not an uncommon problem as shown by questions on comp.lang.tcl.

E.g. With ImageMagick installed on Windows

# this works
dos> convert a.tif a.jpg

#but this results in an error
tclsh> exec convert a.tif a.jpg
  Invalid Parameter - a.jpg
  Child process exited abnormally 

What's happening here is that Tcl is invoking C:\WINDOWS\system32\convert.exe (which is a different program that converts FAT filesystems to NTFS) while dos invokes the convert.exe installed in the ImageMagick directory (which is what we want).

The moral of the story is not to assume that if a command works from the commandline, then it will also be execed successfully by Tcl or any other interpreter or program.

A solution that may work better is to invoke external programs by their full path name.

So for the e.g. above, assuming that ImageMagick is installed in C:\Program Files: this will work:

tclsh> exec {C:/Program Files/ImageMagick-6.3.8-Q16/convert} a.tif a.jpg

Of course, the difficulty with that is locating the full pathname of the program. For instance, while you may code the above exec in your program, your user might have imagemagic 6.4.9 installed on D drive, so your application still won't find it.

A typical approach for handling that problem is to make the full pathname a configurable setting for your program, and have a reasonably smart mechanism for providing a default when the user has not explicitly set the setting. The shortest way to compute a default is probably to use auto_execok, but remember that this command returns a list of arguments for exec, so {*} may be appropriate.