If you can find a free Pascal compiler, you can compile this. At least it works and shows the algorithm necessary.

program Whence (input, output); Uses Dos, my_funk; Const program_version = '1.00'; program_date = '17 March 1994'; VAR path_str : string; command_name : NameStr; command_extension : ExtStr; command_directory : DirStr; search_dir : DirStr; result : DirStr; procedure Check_for (file_name : string); { Check existence of the passed parameter. If exists, then state so } { and exit. } begin if Fsearch(file_name, '') <> '' then begin WriteLn('DOS command = ', Fexpand(file_name)); Halt(0); { structured ? whaddayamean structured ? } end; end; function Get_next_dir : DirStr; { Returns the next directory from the path variable, truncating the } { variable every time. Implicit input (but not passed as parameter) } { is, therefore, path_str } var semic_pos : Byte; begin semic_pos := Pos(';', path_str); if (semic_pos = 0) then begin Get_next_dir := ''; Exit; end; result := Copy(Path_str, 1, (semic_pos - 1)); { return result } { Hmm! although *I* never reference a Root drive (my directory tree) } { is 1/2 way structured), some network logon software which I run } { does (it adds Z:\ to the path). This means that I have to allow } { path entries with & without a terminating backslash. I'll delete } { anysuch here since I always add one in the main program below. } if (Copy(result, (Length(result)), 1) = '\') then Delete(result, Length(result), 1); path_str := Copy(path_str,(semic_pos + 1), (length(path_str) - semic_pos)); Get_next_dir := result; end; { Of function get_next_dir } begin { The following is a kludge which makes the function Get_next_dir easier } { to implement. By appending a semi-colon to the end of the path } { Get_next_dir doesn't need to handle the special case of the last entry } { which normally doesn't have a semic afterwards. It may be a kludge, } { but it's a documented kludge (you might even call it a refinement). } path_str := GetEnv('Path') + ';'; if (paramCount = 0) then begin WriteLn('Whence: V', program_version, ' from ', program_date); Writeln; WriteLn('Usage: WHENCE command[.extension]'); WriteLn; WriteLn('Whence is a ''find file''type utility witha difference'); Writeln('There are are already more than enough of those :-)'); Write ('Use Whence when you''re not sure where a command which you '); WriteLn('want to invoke'); WriteLn('actually resides.'); Write ('If you intend to invoke the command with an extension e.g '); Writeln('"my_cmd.exe param"'); Write ('then invoke Whence with the same extension e.g '); WriteLn('"Whence my_cmd.exe"'); Write ('otherwise a simple "Whence my_cmd" will suffice; Whence will '); Write ('then search the current directory and each directory in the '); Write ('for My_cmd.com, then My_cmd.exe and lastly for my_cmd.bat, '); Write ('just as DOS does'); Halt(0); end; Fsplit(paramStr(1), command_directory, command_name, command_extension); if (command_directory <> '') then begin WriteLn('directory detected *', command_directory, '*'); Halt(0); end; if (command_extension <> '') then begin path_str := Fsearch(paramstr(1), ''); { Current directory } if (path_str <> '') then WriteLn('Dos command = "', Fexpand(path_str), '"') else begin path_str := Fsearch(paramstr(1), GetEnv('path')); if (path_str <> '') then WriteLn('Dos command = "', Fexpand(path_str), '"') else Writeln('command not found in path.'); end; end else begin { O.K, the way it works, DOS looks for a command firstly in the current } { directory, then in each directory in the Path. If no extension is } { given and several commands of the same name exist, then .COM has } { priority over .EXE, has priority over .BAT } Check_for(paramstr(1) + '.com'); { won't return if file is found } Check_for(paramstr(1) + '.exe'); Check_for(paramstr(1) + '.bat'); { Not in current directory, search through path ... } search_dir := Get_next_dir; while (search_dir <> '') do begin Check_for(search_dir + '\' + paramstr(1) + '.com'); Check_for(search_dir + '\' + paramstr(1) + '.exe'); Check_for(search_dir + '\' + paramstr(1) + '.bat'); search_dir := Get_next_dir; end; WriteLn('DOS command not found: ', paramstr(1)); end; end.