94 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* vi: set sw=4 ts=4: */
 | 
						|
/*
 | 
						|
 * Utility routines.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
 | 
						|
 *
 | 
						|
 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
 | 
						|
 */
 | 
						|
#include "libbb.h"
 | 
						|
 | 
						|
/* check if path points to an executable file;
 | 
						|
 * return 1 if found;
 | 
						|
 * return 0 otherwise;
 | 
						|
 */
 | 
						|
int FAST_FUNC file_is_executable(const char *name)
 | 
						|
{
 | 
						|
	struct stat s;
 | 
						|
	return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode));
 | 
						|
}
 | 
						|
 | 
						|
/* search (*PATHp) for an executable file;
 | 
						|
 * return allocated string containing full path if found;
 | 
						|
 *  PATHp points to the component after the one where it was found
 | 
						|
 *  (or NULL),
 | 
						|
 *  you may call find_executable again with this PATHp to continue
 | 
						|
 *  (if it's not NULL).
 | 
						|
 * return NULL otherwise; (PATHp is undefined)
 | 
						|
 * in all cases (*PATHp) contents are temporarily modified
 | 
						|
 * but are restored on return (s/:/NUL/ and back).
 | 
						|
 */
 | 
						|
char* FAST_FUNC find_executable(const char *filename, char **PATHp)
 | 
						|
{
 | 
						|
	/* About empty components in $PATH:
 | 
						|
	 * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
 | 
						|
	 * 8.3 Other Environment Variables - PATH
 | 
						|
	 * A zero-length prefix is a legacy feature that indicates the current
 | 
						|
	 * working directory. It appears as two adjacent colons ( "::" ), as an
 | 
						|
	 * initial colon preceding the rest of the list, or as a trailing colon
 | 
						|
	 * following the rest of the list.
 | 
						|
	 */
 | 
						|
	char *p, *n;
 | 
						|
 | 
						|
	p = *PATHp;
 | 
						|
	while (p) {
 | 
						|
		int ex;
 | 
						|
 | 
						|
		n = strchr(p, ':');
 | 
						|
		if (n) *n = '\0';
 | 
						|
		p = concat_path_file(
 | 
						|
			p[0] ? p : ".", /* handle "::" case */
 | 
						|
			filename
 | 
						|
		);
 | 
						|
		ex = file_is_executable(p);
 | 
						|
		if (n) *n++ = ':';
 | 
						|
		if (ex) {
 | 
						|
			*PATHp = n;
 | 
						|
			return p;
 | 
						|
		}
 | 
						|
		free(p);
 | 
						|
		p = n;
 | 
						|
	} /* on loop exit p == NULL */
 | 
						|
	return p;
 | 
						|
}
 | 
						|
 | 
						|
/* search $PATH for an executable file;
 | 
						|
 * return 1 if found;
 | 
						|
 * return 0 otherwise;
 | 
						|
 */
 | 
						|
int FAST_FUNC executable_exists(const char *filename)
 | 
						|
{
 | 
						|
	char *path = getenv("PATH");
 | 
						|
	char *ret = find_executable(filename, &path);
 | 
						|
	free(ret);
 | 
						|
	return ret != NULL;
 | 
						|
}
 | 
						|
 | 
						|
#if ENABLE_FEATURE_PREFER_APPLETS
 | 
						|
/* just like the real execvp, but try to launch an applet named 'file' first */
 | 
						|
int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
 | 
						|
{
 | 
						|
	if (find_applet_by_name(file) >= 0)
 | 
						|
		execvp(bb_busybox_exec_path, argv);
 | 
						|
	return execvp(file, argv);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void FAST_FUNC BB_EXECVP_or_die(char **argv)
 | 
						|
{
 | 
						|
	BB_EXECVP(argv[0], argv);
 | 
						|
	/* SUSv3-mandated exit codes */
 | 
						|
	xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
 | 
						|
	bb_perror_msg_and_die("can't execute '%s'", argv[0]);
 | 
						|
}
 |