#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>

/* 
 * This code is derived from
 * http://www.arsc.edu/support/news/T3Enews/T3Enews183.shtml
 */

#define MY_PATH_MAX 1024

int checkpath( char *path, char *exec ) {
  int            rc;   /* Return code for strlen and access      */
  char          *str;  /* Temporary string for access()          */
  DIR           *dir;  /* Dir struct for opendir() and readdir() */
  struct dirent *ent;  /* Dir entry struct from readdir()        */

  /* Find an executable file in path that has same name as exec */
  dir = opendir( path );
  while ( ( ent = readdir( dir ) ) != NULL )
    if ( strcmp( ent->d_name, exec ) == 0 ) {
      str = ( char * ) malloc( MY_PATH_MAX * sizeof( char ) );
      rc  = strlen( path );
      strncpy( str, path, rc );
      str[rc] = '/'; str[rc+1] = '\0';
      rc = access( strcat( str, ent->d_name ), X_OK );
      free( str ); closedir( dir );
      return rc == 0 ? 1 : 0;
    }
  closedir( dir ); return 0;
}

char *returnrelative( char *path, char *exec ) {
  int   len,  /* Length of cwd             */
        i;    /* Index                     */
  char *cwd;  /* Current working directory */

  cwd = ( char * ) malloc( MY_PATH_MAX * sizeof( char ) );
  cwd = getcwd( cwd, MY_PATH_MAX );
  len = strlen( cwd );

  if ( strcmp( cwd, path ) == 0 ) {          /* Are cwd and path the same?  */
    path[0] = '.'; path[1] = '\0';
  } else if ( len < strlen( path ) ) {       /* Remove CWD from path        */
    for ( i = 0; i < len; i++ )
      if ( cwd[i] != path[i] ) break;
    if ( i == len )                          /* CWD is in beginning of path */
      if ( i == 1 ) { path = path + i;     } /* Fix up path if cwd == '/'   */
      else          { path = path + i + 1; }
  }
  free( cwd  );
  return path;
}

char *whereami( char *argv0 ) {
  int   s,    /* Start of a path in PATH envvar */
        len,  /* Length of PATH envvar          */
        i;    /* Index                          */
  char *str;  /* PATH envvar or executable name */

  if ( ( str = rindex( argv0, '/' ) ) != NULL ) {
    str[0] = '\0';
    return argv0;
  } else {
    str = getenv( "PATH" ); len = strlen( str );
    for ( i = 0, s = 0; i < len; i++ )
      if ( str[i] == ':' ) {
        str[i] = '\0';
        if ( checkpath( str + s, argv0 ) ) break;
        else                                 s = i + 1;
      }
    return returnrelative( str + s, argv0 );
  }
  return NULL;
}

