/* Nota: find_exec.c has been taken from dld */
/* Modifications from Tristan Gingold: 
	copy_of(): use a static buffer 
	           renamed copy_of_exec_file and public.
	dld_find_executable: check if the file is relative (../)
		             '::' patch
	dld_find_executable is renamed chkr_find_executable
	add include and comments.
*/

/* Given a filename, dld_find_executable searches the directories listed in the
   environment variable PATH for a file with that filename.
   A new copy of the complete path name of that file is returned.  This new
   string may be disposed by free() later on.
*/

/* This file is part of DLD, a dynamic link/unlink editor for C.
   
   Copyright (C) 1990 by W. Wilson Ho.

   The author can be reached electronically by how@cs.ucdavis.edu or
   through physical mail at:

   W. Wilson Ho
   Division of Computer Science
   University of California at Davis
   Davis, CA 95616
 */

/* This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 1, or (at your option) any
   later version. */

#include <sys/file.h>
#include <sys/param.h>
#include <unistd.h>
#include <fcntl.h>
#include "checker.h"

static void simplify_path(void);

#define DEFAULT_PATH ".:~/bin::/usr/local/bin:/usr/new:/usr/ucb:/usr/bin:/bin:/usr/hosts"

static char exec_name_buffer[MAXPATHLEN];

char *
copy_of_exec_file(register char *s)
{
    exec_name_buffer[0] = '\0';
    strcpy (exec_name_buffer, s);
    simplify_path();
    return exec_name_buffer;
}

/* ABSOLUTE_FILENAME_P (fname): True if fname is an absolute filename */
#ifdef atarist
#define ABSOLUTE_FILENAME_P(fname)	((fname[0] == '/') || \
	(fname[0] && (fname[1] == ':')))
#else
#define ABSOLUTE_FILENAME_P(fname)	(fname[0] == '/')
#endif /* atarist */

char *
chkr_find_executable (char *file)
{
    char *search;
    char name[MAXPATHLEN];
    register char *p;
    int again = 0;

    if (ABSOLUTE_FILENAME_P(file))
	return copy_of_exec_file (file);
  
    if (strchr(file,'/') != (char*)0)  /* contains a '/' */
    {
        getcwd(name,MAXPATHLEN);
        strcat (name, "/");
	strcat (name, file);
	      
	if (access (name, X_OK) == 0)
	    return copy_of_exec_file (name);
    }
    
    if (((search = (char *) getenv("DLDPATH")) == 0) &&
	((search = (char *) getenv("PATH")) == 0))
	search = DEFAULT_PATH;
	
    p = search;
    
    while (*p || again) {    
	
	register char *next;

	next = name;
	
	/* copy directory name into [name] */
	while (*p && *p != ':') *next++ = *p++;
	*next = 0;
 	if ( *p == ':' && *(p+1) == 0) again ^= 1; /* once more if PATH ends with ':' */
	if (*p) p++;

 	if (name[0] == 0 || (name[0] == '.' && name[1] == 0))
	    getcwd (name,MAXPATHLEN);
	
	strcat (name, "/");
	strcat (name, file);
	      
	if (access (name, X_OK) == 0)
	    return copy_of_exec_file (name);
    }

    return 0;
}

static void
simplify_path(void)
{
 char *path = exec_name_buffer;
 char *sl = path;
 char *sl1;
 if(*path != '/')
   return;
 do
   {
     while (*sl != '/')
       if (*sl == '\0')
         return;
       else
         sl++;
     do
       {
         /* NOTA: each time we use memmove, we must not forget the '\0'! */
         if (sl[1] == '/')
           memmove(sl, sl + 1, strlen(sl + 1) + 1);
         else if (sl[1] == '.' && sl[2] == '/')
           memmove(sl, sl + 2, strlen(sl + 2) + 1);
         else if (sl[1] == '.' && sl[2] == '.' && sl[3] == '/')
           {
             for(sl1 = sl - 1; sl1 >= path && *sl1 != '/'; sl1--)
               ;
             if (*sl1 != '/' || sl1 == sl)
               return; /* ERROR */
             memmove(sl1, sl + 3, strlen(sl + 3) + 1);
             continue;
           }
         else break;
       }
     while(1);
     sl++;	/* next directory */
   }
 while(1);
}