@@ -848,24 +848,102 @@ class AgentManager(object):
848
848
def AutodetectBinary (argv , config ):
849
849
"""Detects the correct binary to run and sets BINARY_SSH accordingly,
850
850
if it is not already set."""
851
+
852
+ # Set default binary to use, in case the binary can't be found otherwise.
853
+ DEFAULT_BINARY = "ssh"
854
+
851
855
# If BINARY_SSH is set by the user, respect that and do nothing.
852
856
if config .Get ("BINARY_SSH" ):
853
857
print ("Will run '{0}' as ssh binary - set by user via BINARY_SSH"
854
858
.format (config .Get ("BINARY_SSH" )), loglevel = LOG_DEBUG )
855
859
return
856
860
857
- # If BINARY_DIR is set, look for the binary in this directory.
861
+ # Get name of running programe
858
862
runtime_name = argv [0 ]
859
- if config .Get ("BINARY_DIR" ):
860
- binary_name = os .path .basename (runtime_name )
861
- binary_path = os .path .join (config .Get ("BINARY_DIR" ), binary_name )
862
- if not os .path .isfile (binary_path ) or not os .access (binary_path , os .X_OK ):
863
- binary_path = os .path .join (config .Get ("BINARY_DIR" ), "ssh" )
863
+ binary_name = os .path .basename (runtime_name )
864
864
865
+ # Look for runtime_name or DEFAULT_BINARY in BINARY_DIR.
866
+ binary_dir = config .Get ("BINARY_DIR" )
867
+ if binary_dir :
868
+ # Use first valid find between the runtime binary and the default binary.
869
+ binaries = [FindBinaryInDirectory (binary_dir , name )
870
+ for name in (binary_name , DEFAULT_BINARY )]
871
+ binary_path = next ((path for path in binaries if path is not None ), None )
872
+ if binary_path :
873
+ config .Set ("BINARY_SSH" , binary_path )
874
+ print ("Will run '{0}' as ssh binary - detected based on BINARY_DIR"
875
+ .format (binary_path ), loglevel = LOG_DEBUG )
876
+ return
877
+
878
+ # Look for runtime_name or DEFAULT_BINARY in PATH.
879
+ # Use first valid find between the runtime binary and the default binary.
880
+ binaries = [FindAutodetectBinaryInPath (name )
881
+ for name in (runtime_name , DEFAULT_BINARY )]
882
+ binary_path = next ((path for path in binaries if path is not None ), None )
883
+ if binary_path :
865
884
config .Set ("BINARY_SSH" , binary_path )
866
- print ("Will run '{0}' as ssh binary - deteced based on BINARY_DIR "
885
+ print ("Will run '{0}' as ssh binary - detected from argv[0] and $PATH "
867
886
.format (config .Get ("BINARY_SSH" )), loglevel = LOG_DEBUG )
868
- return
887
+ else :
888
+ message = textwrap .dedent ("""\
889
+ ssh-ident was invoked in place of the binary {0} (determined from argv[0]).
890
+ Neither this binary nor 'ssh' could be found in $PATH.
891
+
892
+ PATH="{1}"
893
+
894
+ You need to adjust your setup for ssh-ident to work: consider setting
895
+ BINARY_SSH or BINARY_DIR in your config, or running ssh-ident some
896
+ other way.""" )
897
+ print (message .format (argv [0 ], os .environ ['PATH' ]), loglevel = LOG_ERROR )
898
+ sys .exit (255 )
899
+
900
+
901
+ def GetNormalizedSystemPath ():
902
+ """Returns a the system PATH as a list, with symlinks etc.
903
+ being normalized."""
904
+ # Paths in PATH may be not-normalized, example: "/usr/bin/../foo",
905
+ # or "/opt/scripts///". Normalize them before comparison.
906
+ normalized_path = [
907
+ os .path .normpath (p ) for p in os .environ ['PATH' ].split (os .pathsep )]
908
+
909
+ return normalized_path
910
+
911
+ def FindBinaryInDirectory (binary_dir , binary_name ):
912
+ """Looks for an executable with a given name in a given directory and
913
+ returns the binary path if it was found."""
914
+ binary_path = os .path .join (binary_dir , binary_name )
915
+ if os .path .isfile (binary_path ) and os .access (binary_path , os .X_OK ):
916
+ return binary_path
917
+ else :
918
+ return None
919
+
920
+ def FindBinaryInPath (binary_name , search_path = None ):
921
+ """Looks for an executable with a given name in a given directory and
922
+ returns the binary path if it was found."""
923
+ if not search_path :
924
+ search_path = GetNormalizedSystemPath ()
925
+
926
+ # Find an executable with the desired name.
927
+ binary_path = distutils .spawn .find_executable (binary_name , search_path )
928
+
929
+ return binary_path
930
+
931
+ def FindBinary (binary_dir , binary_name ):
932
+ """Looks for an executable binary_name in binary_dir and PATH and
933
+ returns the binary path if it was found."""
934
+ if binary_dir :
935
+ binary_path = FindBinaryInDirectory (binary_dir , binary_name )
936
+ if binary_path :
937
+ return binary_path
938
+
939
+ # Look for binary in PATH.
940
+ binary_path = FindBinaryInPath (binary_name )
941
+ if binary_path :
942
+ return binary_path
943
+
944
+ def FindAutodetectBinaryInPath (runtime_name ):
945
+ """Looks for the correct binary that is supposed to runin PATH and returns
946
+ the binary path if it was found."""
869
947
870
948
# argv[0] could be pretty much anything the caller decides to set
871
949
# it to: an absolute path, a relative path (common in older systems),
@@ -907,37 +985,13 @@ def AutodetectBinary(argv, config):
907
985
# Remove the path containing the ssh-ident symlink (or whatever) from
908
986
# the search path, so we do not cause an infinite loop.
909
987
# Note that:
910
- # - paths in PATH may be not-normalized, example: "/usr/bin/../foo",
911
- # or "/opt/scripts///". Normalize them before comparison.
912
988
# - paths in PATH may be repeated multiple times. We have to exclude
913
989
# all instances of the ssh-ident path.
914
- normalized_path = [
915
- os .path .normpath (p ) for p in os .environ ['PATH' ].split (os .pathsep )]
990
+ normalized_path = GetNormalizedSystemPath ()
916
991
search_path = os .pathsep .join ([
917
992
p for p in normalized_path if p != ssh_ident_path ])
918
993
919
- # Find an executable with the desired name.
920
- binary_path = distutils .spawn .find_executable (binary_name , search_path )
921
- if not binary_path :
922
- # Nothing found. Try to find something named 'ssh'.
923
- binary_path = distutils .spawn .find_executable ('ssh' )
924
-
925
- if binary_path :
926
- config .Set ("BINARY_SSH" , binary_path )
927
- print ("Will run '{0}' as ssh binary - deteced from argv[0] and $PATH"
928
- .format (config .Get ("BINARY_SSH" )), loglevel = LOG_DEBUG )
929
- else :
930
- message = textwrap .dedent ("""\
931
- ssh-ident was invoked in place of the binary {0} (determined from argv[0]).
932
- Neither this binary nor 'ssh' could be found in $PATH.
933
-
934
- PATH="{1}"
935
-
936
- You need to adjust your setup for ssh-ident to work: consider setting
937
- BINARY_SSH or BINARY_DIR in your config, or running ssh-ident some
938
- other way.""" )
939
- print (message .format (argv [0 ], os .environ ['PATH' ]), loglevel = LOG_ERROR )
940
- sys .exit (255 )
994
+ return FindBinaryInPath (binary_name , search_path )
941
995
942
996
def ParseCommandLine (argv , config ):
943
997
"""Parses the command line parameters in argv
@@ -976,6 +1030,7 @@ def main(argv):
976
1030
print = SshIdentPrint (config )
977
1031
978
1032
AutodetectBinary (argv , config )
1033
+
979
1034
# Check that BINARY_SSH is not ssh-ident.
980
1035
# This can happen if the user sets a binary name only (e.g. 'scp') and a
981
1036
# symlink with the same name was set up.
0 commit comments