/* -*- Mode: C -*- */ /* * wh - show full paths of potential commands * * This file was placed in the Public Domain by its author on 14 * March 1999. Those who modify this file are encouraged to send * mail to Rick Campbell with their Public * Domain modifications so that they can be included in future * versions. * */ static const char Copyright [] = "Placed in the Public Domain on 14 March 1999."; /* Table of Contents */ /* -*- Mode: C -*- */ /* Table of Contents */ /* Headers, etc. */ /* Prototypes */ /* list */ /* main */ /* scan_directory */ /* usage */ /* Headers, etc. */ #include #include #include #include #include #include #include #include #include #ifdef WH_ANSI # define ALLOCATE( SIZE ) malloc (SIZE) # define RELEASE( POINTER) free (POINTER); #else /* WH_ANSI */ # define ALLOCATE( SIZE ) alloca (SIZE) # define RELEASE( POINTER ) #endif /* WH_ANSI */ static char* Program_Name = (char*)NULL; /* Prototypes */ static void list (char* pathname, char** list_options, unsigned int list_options_count); int main (int argument_count, char** argument_vector); static void scan_directory (char* directory_start, char* directory_limit, char* target, unsigned int target_length, char** list_options, unsigned int list_options_count); static void usage (); /* list */ static void list (char* pathname, char** list_options, unsigned int list_options_count) { pid_t child = 0; char** exec_arguments = (char**)NULL; unsigned int index = 0; exec_arguments = (char**)(ALLOCATE (list_options_count + 3)); assert (exec_arguments != ((char**)NULL)); exec_arguments [0] = "ls"; for (index = 0; index < list_options_count; ++index) { exec_arguments [index + 1] = list_options [index]; } exec_arguments [list_options_count + 1] = pathname; exec_arguments [list_options_count + 2] = (char*)NULL; child = fork (); if (child == 0) { execvp ("ls", exec_arguments); } else { int child_status = 0; waitpid (child, &child_status, 0); assert (WIFEXITED (child_status)); RELEASE ((void*)exec_arguments); } } /* main */ int main (int argument_count, char** argument_vector) { unsigned int index = 0; char* limit = (char*)NULL; char** list_options = (char**)NULL; unsigned int list_options_count = 0; char* path_list = (char*)NULL; char* start = (char*)NULL; char* target = (char*)NULL; unsigned int target_length = 0; Program_Name = argument_vector [0]; if (argument_count <= 1) { usage (); } assert (argument_count > 1); list_options_count = argument_count - 2; if (list_options_count != 0) { list_options = ALLOCATE (list_options_count); for (index = 0; index < list_options_count; ++index) { list_options [index] = argument_vector [index + 1]; } } target = argument_vector [argument_count - 1]; target_length = strlen (target); assert (target_length > 0); path_list = getenv ("PATH"); assert (path_list != (char*)NULL); start = path_list; limit = strchr (start, ':'); while (1) { scan_directory (start, limit, target, target_length, list_options, list_options_count); start = limit + 1; limit = strchr (start, ':'); if (limit == ((char*)NULL)) { scan_directory (start, (start + strlen (start)), target, target_length, list_options, list_options_count); break; } } RELEASE ((void*)list_options) return 0; } /* scan_directory */ static void scan_directory (char* directory_start, char* directory_limit, char* target, unsigned int target_length, char** list_options, unsigned int list_options_count) { unsigned int directory_length = 0; unsigned int length = 0; char* path = (char*)NULL; struct stat status; directory_length = directory_limit - directory_start; length = directory_length + target_length + 1; path = ALLOCATE (length + 1); assert (path != (char*)NULL); strncpy (path, directory_start, directory_length); path [directory_length] = '/'; strncpy (path + directory_length + 1, target, target_length); path [length] = '\0'; if (stat (path, &status) == 0) { list (path, list_options, list_options_count); } else if (errno != ENOENT) { fprintf (stderr, "%s: stat(2) failed for \"%s\".\n", Program_Name, path); perror ("stat"); exit (1); } RELEASE ((void*)path); } /* usage */ static void usage () { fprintf (stderr, "Usage: %s LS_OPTION* program_name\n", Program_Name); exit (1); }