/* Find the full program name from argv[0].
   Copyright 1994, 1995 Tristan Gingold
		  Written July 1994 by Tristan Gingold

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 2 of the
License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License 
along with this program; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.

The author may be reached by US/French mail:
		Tristan Gingold 
		8 rue Parmentier
		F-91120 PALAISEAU
		FRANCE
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include "checker.h"

#ifndef DEFAULT_PATH
#define DEFAULT_PATH ":/bin:/usr/bin:/usr/local/bin"
#endif
#ifndef DEFAULT_HOME
#define DEFAULT_HOME "/"
#endif

static int
try_filename (const char *file)
{
  int fd;
  if (access (file, X_OK) != 0)
    return -1;
  fd = open (file, O_RDONLY);
  if (fd == -1)
    return -1;
  if (chkr_prog_fd != -1)
    close (chkr_prog_fd);
  else
    chkr_prog_fd = fd_alloc_reserved ("executable");
  dup2 (fd, chkr_prog_fd);
  close (fd);
  return chkr_prog_fd;
}

#ifndef DONT_NEED_EXECUTABLE
/* This function is like strncat, but MAXLEN is the maximal length of DEST,
   not the maximal length of SRC.  */
static void
my_strncat(char *dest, const char *src, int maxlen)
{
  int len = strlen(dest);
  strncpy (dest + len, src, maxlen - len - 1);	/* 1 for the '\0'? */
}

/* The main function: from FILE and the PATH, search the full name of FILE.
 */
void
chkr_find_executable (const char *file)
{
  char name[MAXPATHLEN];
  char *path;
  
  /* If FILE is already a full path, this is easy!  */
  if (file[0] == '/')
    {
      try_filename (file);
      /* Only try this one.  */
      return;
    }

  /* If FILE contains a '/', the current directory must be used.  */
  if (strchr(file, '/') != (char*)0)
    {
      if (try_filename (file) != -1)
	return;
      /* Do not stop here. */
    }
  
  /* Get the path.  */
  path = chkr_getenv ("PATH");
  if (path == (char*)0)
    path = DEFAULT_PATH;
    
  /* Try each directory of the path.  */
  while (*path)
    {
      char *next = name;
      
      /* Test if we must insert a directory before.  */
      if (*path == ':' )
        {
	  /* Try the current one.  */
	  *next++ = '.';
        }
        
      /* Copy the directory into the name.  */
      while (*path && *path != ':')
        *next++ = *path++;
      *next = '\0';
      
      /* Skip the colon, only if the colon is not the last char of
	 your path.  */
      if (*path && path[1])
        path++; 
      
      my_strncat (name, "/", MAXPATHLEN);
      my_strncat (name, file, MAXPATHLEN);
      
      if (try_filename (name) != -1)
	return;
    }
    
  /* The current directory must always be tested, because the parent
     could use exeve() instead of execvp() for example.  */
  try_filename (file);
  return;
}  
#endif /* !DONT_NEED_EXECUTABLE */
