src/stdlib/path.c
/*===========================================
 * filepath -- Find file in sequence of paths
 *  handles NULL in either argument
 *  returns alloc'd buffer
 * Warning: if called with mode other than "r" this may not 
 *         do what you want, because 1) if file is not found, it appends ext.
 *         and 2) file always goes in 1st specified directory of path unless
 *         name is absolute or ./something
 *=========================================*/
- Find file in sequence of paths
handles NULL in either argument
returns alloc'd buffer
Warning: if called with mode other than "r" this may not
do what you want, because 1) if file is not found, it appends ext.
and 2) file always goes in 1st specified directory of path unless
name is absolute or ./something
- Find file in sequence of paths handles NULL in either argument returns alloc ' d buffer Warning : if called with mode other than " r " this may not do what you want because 1 ) if file is not found it appends ext . and 2 ) file always goes in 1st specified directory of path unless name is absolute or . / something
STRING
filepath (CNSTRING name, CNSTRING mode, CNSTRING path, CNSTRING  ext, INT utf8)
{
	char buf1[MAXPATHLEN], buf2[MAXPATHLEN];
	STRING p, q;
	INT nlen, elen;
	if (ISNULL(name)) return NULL;
	if (ISNULL(path)) return strsave(name);
	nlen = strlen(name);
	if (ext && *ext) {
		elen = strlen(ext);
		if ((nlen > elen) && path_match(name+nlen-elen, ext)) {
			ext = NULL;
			elen = 0;
		}
	}
	else { ext = NULL; elen = 0; }
	if (nlen + strlen(path) + elen >= MAXLINELEN) return NULL;
	if (is_path(name)) {
		if (ext) {
			strcpy(buf1,name);
			nlen = strlen(buf1);
			strcat(buf1, ext);
			if (access(buf1, 0) == 0) return strsave(buf1);
			buf1[nlen] = '\0'; 
			if (access(buf1, 0) == 0) return strsave(buf1);
		}
		if (access(name, 0) == 0) return strsave(name);
		if (is_dir_sep(name[0]) || (name[0] == '.' && is_dir_sep(name[1])))
			return strsave(name);
#ifdef WIN32
		if (name[0] && name[1]==':' && isasciiletter(name[0])) {
			return strsave(name);
		}
#endif
	}
	strcpy(buf1, path);
	zero_separate_path(buf1);
	p = buf1;
	while (*p) {
		q = buf2;
		strcpy(q, p);
		expand_special_fname_chars(buf2, sizeof(buf2), utf8);
		q += strlen(q);
		if (q>buf2 && !is_dir_sep(q[-1])) {
			strcpy(q, LLSTRDIRSEPARATOR);
			q++;
		}
		strcpy(q, name);
		if (ext) {
			nlen = strlen(buf2);
			strcat(buf2, ext);
			if (access(buf2, 0) == 0) return strsave(buf2);
			buf2[nlen] = '\0'; 
		}
		if (access(buf2, 0) == 0) return strsave(buf2);
		p += strlen(p);
		p++;
	}
	if (mode[0] == 'r') return NULL;
	p = buf1;
	q = buf2;
	strcpy(q, p);
	expand_special_fname_chars(buf2, sizeof(buf2), utf8);
	q += strlen(q);
	if (q>buf2 && !is_dir_sep(q[-1])) {
		strcpy(q, LLSTRDIRSEPARATOR);
		q++;
	}
	strcpy(q, name);
	if (ext) strcat(q, ext);
	return strsave(buf2);
}
STRING filepath ( CNSTRING name , CNSTRING mode , CNSTRING path , CNSTRING ext , INT utf8 ) { char buf1 [ MAXPATHLEN ] , buf2 [ MAXPATHLEN ] ; STRING p , q ; INT nlen , elen ; if ( ISNULL ( name ) ) return NULL ; if ( ISNULL ( path ) ) return strsave ( name ) ; nlen = strlen ( name ) ; if ( ext && * ext ) { elen = strlen ( ext ) ; if ( ( nlen > elen ) && path_match ( name + nlen - elen , ext ) ) { ext = NULL ; elen = 0 ; } } else { ext = NULL ; elen = 0 ; } if ( nlen + strlen ( path ) + elen >= MAXLINELEN ) return NULL ; if ( is_path ( name ) ) { if ( ext ) { strcpy ( buf1 , name ) ; nlen = strlen ( buf1 ) ; strcat ( buf1 , ext ) ; if ( access ( buf1 , 0 ) == 0 ) return strsave ( buf1 ) ; buf1 [ nlen ] = ' \0 ' ; if ( access ( buf1 , 0 ) == 0 ) return strsave ( buf1 ) ; } if ( access ( name , 0 ) == 0 ) return strsave ( name ) ; if ( is_dir_sep ( name [ 0 ] ) || ( name [ 0 ] == ' ' && is_dir_sep ( name [ 1 ] ) ) ) return strsave ( name ) ; #ifdef WIN32 if ( name [ 0 ] && name [ 1 ] == ' ' && isasciiletter ( name [ 0 ] ) ) { return strsave ( name ) ; } #endif } strcpy ( buf1 , path ) ; zero_separate_path ( buf1 ) ; p = buf1 ; while ( * p ) { q = buf2 ; strcpy ( q , p ) ; expand_special_fname_chars ( buf2 , sizeof ( buf2 ) , utf8 ) ; q += strlen ( q ) ; if ( q > buf2 && ! is_dir_sep ( q [ -1 ] ) ) { strcpy ( q , LLSTRDIRSEPARATOR ) ; q ++ ; } strcpy ( q , name ) ; if ( ext ) { nlen = strlen ( buf2 ) ; strcat ( buf2 , ext ) ; if ( access ( buf2 , 0 ) == 0 ) return strsave ( buf2 ) ; buf2 [ nlen ] = ' \0 ' ; } if ( access ( buf2 , 0 ) == 0 ) return strsave ( buf2 ) ; p += strlen ( p ) ; p ++ ; } if ( mode [ 0 ] == ' ' ) return NULL ; p = buf1 ; q = buf2 ; strcpy ( q , p ) ; expand_special_fname_chars ( buf2 , sizeof ( buf2 ) , utf8 ) ; q += strlen ( q ) ; if ( q > buf2 && ! is_dir_sep ( q [ -1 ] ) ) { strcpy ( q , LLSTRDIRSEPARATOR ) ; q ++ ; } strcpy ( q , name ) ; if ( ext ) strcat ( q , ext ) ; return strsave ( buf2 ) ; }
filepath -- Find file in sequence of paths
  handles NULL in either argument
  returns alloc'd buffer
 Warning: if called with mode other than "r" this may not
         do what you want, because 1) if file is not found, it appends ext.
filepath -- Find file in sequence of paths handles NULL in either argument returns alloc ' d buffer Warning : if called with mode other than " r " this may not do what you want because 1 ) if file is not found it appends ext .
/*  at this point ext is non-null only if name doesn't 
	 *  end in ext.  I.E. we need to check for name + ext and name
	 */ /* for absolute and relative path names we first check the
	 * pathname for validity relative to the current directory
	 */ /* If this is a path, i.e. it has multiple path elements
		 * use the name as is first.  So absolute paths don't
		 * get resolved by appending search paths.
		 */ /* remove extension */ /* fail if get here and name begins with a / or ./
		 * as we didn't find the file.
		 * however let foo/bar sneak thru, so we allow access
		 * to files in subdirectories of the search path if 
		 * named in the filename.
		 */ /* it is a relative path, so search for it in search path */ /* remove extension */