C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
whence.c File Reference

Find the full path of a file in the directories specified by the. More...

#include "cm.h"
#include <argp.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
Include dependency graph for whence.c:

Go to the source code of this file.

Macros

#define _GNU_SOURCE

Enumerations

enum  WhenceFlags {
  WH_ALL = 1 , WH_VERBOSE = 2 , WH_EXECUTABLE = 4 , WH_SETUID = 8 ,
  WH_ALL = 1 , WH_VERBOSE = 2 , WH_EXECUTABLE = 4 , WH_SETUID = 8
}
enum  WhenceFlags {
  WH_ALL = 1 , WH_VERBOSE = 2 , WH_EXECUTABLE = 4 , WH_SETUID = 8 ,
  WH_ALL = 1 , WH_VERBOSE = 2 , WH_EXECUTABLE = 4 , WH_SETUID = 8
}

Functions

void ABEND (char *pgmid, int rc, char *err_msg)
 Exit the program with an error message.
int file_spec_parts (char *file_spec, char *file_path, char *file_name)
 Split a file specification into directory and file name components.
int main (int argc, char **argv)
int next_path (char *dp, char **pp)
 Get the next directory path from a colon-separated list of paths.
size_t strnz__cat (char *, const char *, size_t)
 safer alternative to strncat
size_t strnz__cat (char *d, const char *s, size_t max_len)
 safer alternative to strncat
size_t strnz__cpy (char *, const char *, size_t)
 safer alternative to strncpy
size_t strnz__cpy (char *d, const char *s, size_t max_len)
 safer alternative to strncpy
int whence (char *file_spec_p, int flags)
 Find the full path of a file in the directories specified by the PATH environment variable.

Variables

const char * argp_program_bug_address = "billxwaller@gmail.com"
const char * argp_program_version = CM_VERSION
char * path_p
char path_s [MAXLEN]
int wh_flags = 0

Detailed Description

Find the full path of a file in the directories specified by the.

Author
Bill Waller Copyright (c) 2025 MIT License billx.nosp@m.wall.nosp@m.er@gm.nosp@m.ail..nosp@m.com
Date
2026-02-09

Definition in file whence.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 10 of file whence.c.

Enumeration Type Documentation

◆ WhenceFlags [1/2]

Enumerator
WH_ALL 
WH_VERBOSE 
WH_EXECUTABLE 
WH_SETUID 
WH_ALL 
WH_VERBOSE 
WH_EXECUTABLE 
WH_SETUID 

Definition at line 34 of file whence.c.

34 { WH_ALL = 1,
35 WH_VERBOSE = 2,
36 WH_EXECUTABLE = 4,
WhenceFlags
Definition whence.c:34
@ WH_SETUID
Definition whence.c:37
@ WH_ALL
Definition whence.c:34
@ WH_VERBOSE
Definition whence.c:35
@ WH_EXECUTABLE
Definition whence.c:36

◆ WhenceFlags [2/2]

Enumerator
WH_ALL 
WH_VERBOSE 
WH_EXECUTABLE 
WH_SETUID 
WH_ALL 
WH_VERBOSE 
WH_EXECUTABLE 
WH_SETUID 

Definition at line 34 of file whence.c.

34 { WH_ALL = 1,
35 WH_VERBOSE = 2,
36 WH_EXECUTABLE = 4,

Function Documentation

◆ ABEND()

void ABEND ( char * pgmid,
int rc,
char * err_msg )

Exit the program with an error message.

Parameters
pgmidThe name of the program
rcThe return code to exit with
err_msgThe error message to display

This function is called to exit the program with an error status. It prints the program name, return code, and error message to the standard error stream, and then exits with the specified return code.

Definition at line 274 of file whence.c.

274 {
275 fprintf(stderr, _("%s; error %d; %s\n"), pgmid, rc, err_msg);
276 exit(EXIT_FAILURE);
277}
char err_msg[MAXLEN]
#define _(String)
Definition amort.c:23

◆ file_spec_parts()

int file_spec_parts ( char * file_spec,
char * file_path,
char * file_name )

Split a file specification into directory and file name components.

Parameters
file_specThe full file specification to split
file_pathA buffer to store the extracted directory path
file_nameA buffer to store the extracted file name
Returns
0 on success

This function takes a file specification, checks if it is a directory, and if so, it sets the file path accordingly. If the file specification is empty, it defaults to the current directory. Otherwise, it splits the file specification into the directory and file name components based on the last occurrence of a slash ('/').

Definition at line 217 of file whence.c.

217 {
218 int i, last_slash;
219 char tmp_file_spec[PATH_MAX];
220 int file_spec_l;
221 struct stat stat_struct;
222
223 if (stat(file_spec, &stat_struct) != -1)
224 if ((stat_struct.st_mode & S_IFMT) == S_IFDIR) {
225 if (file_spec[strlen(file_path)] != '/')
226 strnz__cat(file_spec, "/", MAXLEN - 1);
227 strnz__cpy(file_path, file_spec, MAXLEN - 1);
228 file_name[0] = '\0';
229 return (0);
230 }
231 if (strlen(file_spec) == 0) {
232 strnz__cpy(file_spec, "./", MAXLEN - 1);
233 file_name[0] = '\0';
234 return (0);
235 }
236 strnz__cpy(tmp_file_spec, file_spec, MAXLEN - 1);
237 last_slash = -1;
238 file_spec_l = strlen(tmp_file_spec);
239 if (file_spec_l > 0) {
240 i = 0;
241 while (i < file_spec_l && tmp_file_spec[i] != '\0') {
242 if (tmp_file_spec[i] == '/') {
243 last_slash = i;
244 break;
245 }
246 i++;
247 }
248 }
249 if (last_slash < 0) {
250 strnz__cpy(file_path, "./", MAXLEN - 1);
251 if (strcmp(file_spec, ".") == 0)
252 file_name[0] = '\0';
253 else
254 strnz__cpy(file_name, tmp_file_spec, MAXLEN - 1);
255 strnz__cpy(file_spec, file_path, MAXLEN - 1);
256 strnz__cat(file_spec, file_name, MAXLEN - 1);
257 } else {
258 tmp_file_spec[last_slash] = '\0';
259 strnz__cpy(file_path, tmp_file_spec, MAXLEN - 1);
260 strnz__cat(file_path, "/", MAXLEN - 1);
261 if (last_slash < file_spec_l)
262 last_slash++;
263 strnz__cpy(file_name, tmp_file_spec + last_slash, MAXLEN - 1);
264 }
265 return (0);
266}
#define MAXLEN
Definition curskeys.c:15
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:518
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:549

References strnz__cat(), and strnz__cpy().

Referenced by whence().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int argc,
char ** argv )

Definition at line 95 of file whence.c.

95 {
96 struct wh_opts wh_opts = {};
97 wh_opts.flags = 0;
98 wh_opts.argv[0] = nullptr;
99 wh_opts.path_env = nullptr;
100 int i = 0;
101 int found = 0;
102 argp_parse(&argp, argc, argv, 0, 0, &wh_opts);
103 if (wh_opts.path_env != nullptr)
104 path_p = getenv(wh_opts.path_env);
105 else
106 path_p = getenv("PATH");
107 if (path_p == nullptr)
108 ABEND(argv[0], 0, _("Search PATH not set"));
109 if (wh_opts.flags & WH_VERBOSE)
110 printf("%s\n", path_p);
111 while (i < wh_opts.argc)
112 found = whence(wh_opts.argv[i++], wh_opts.flags);
113 if (found == 0)
114 exit(1);
115 exit(0);
116}
int whence(char *, int)
Find the full path of a file in the directories specified by the PATH environment variable.
Definition whence.c:127
char * path_p
Definition whence.c:24
void ABEND(char *, int, char *)
Exit the program with an error message.
Definition whence.c:274

References ABEND(), path_p, WH_VERBOSE, and whence().

Here is the call graph for this function:

◆ next_path()

int next_path ( char * dp,
char ** pp )

Get the next directory path from a colon-separated list of paths.

Parameters
dpA buffer to store the extracted directory path
ppA pointer to the current position in the path string
Returns
The length of the extracted directory path

This function takes a pointer to a colon-separated list of paths and extracts the next directory path from it. If the current character is a colon, it retrieves the current working directory instead. The extracted directory path is stored in the provided buffer, and the function returns the length of the extracted path.

Definition at line 188 of file whence.c.

188 {
189 int dl;
190
191 if (**pp == ':') {
192 (*pp)++;
193 getcwd(dp, PATH_MAX);
194 return (strlen(dp));
195 } else {
196 dl = 0;
197 while (**pp != '\0' && **pp != '\n' && **pp != '\r' && **pp != ':') {
198 *dp++ = *(*pp)++;
199 dl++;
200 }
201 *dp = '\0';
202 if (**pp == ':' && *++(*pp) == '\0')
203 (*pp)--;
204 return (dl);
205 }
206}

Referenced by whence().

Here is the caller graph for this function:

◆ whence()

int whence ( char * file_spec_p,
int flags )

Find the full path of a file in the directories specified by the PATH environment variable.

Parameters
file_spec_pThe file specification to search for
flagsFlags to control the behavior of the search (e.g., verbose mode, list all matches)

This function takes a file specification, extracts the directory and file name components, and searches through the directories specified in the PATH environment variable to find matches. It prints the full path of each match found, and if verbose mode is enabled, it also indicates whether each attempted path was found or not.

Definition at line 127 of file whence.c.

127 {
128 char file_spec[PATH_MAX];
129 char file_dir[PATH_MAX];
130 char file_name[PATH_MAX];
131 char try_spec[PATH_MAX];
132 char try_dir[PATH_MAX];
133 int path_l;
134 int found = 0;
135 struct stat stat_struct;
136
137 strnz__cpy(file_spec, file_spec_p, MAXLEN - 1);
139 file_spec_parts(file_spec, file_dir, file_name);
140 path_p = path_s;
141 path_l = next_path(try_dir, &path_p);
142 while (path_l != 0) {
143 strnz__cpy(try_spec, try_dir, MAXLEN - 1);
144 if (try_spec[path_l] != '/')
145 strnz__cat(try_spec, "/", MAXLEN - 1);
146 strnz__cat(try_spec, file_name, MAXLEN - 1);
147 if (stat(try_spec, &stat_struct) != 0) {
148 if (flags & WH_VERBOSE)
149 printf("- %s\n", try_spec);
150 path_l = next_path(try_dir, &path_p);
151 continue;
152 }
153 if (flags & WH_SETUID)
154 if (!(stat_struct.st_mode & S_ISUID)) {
155 path_l = next_path(try_dir, &path_p);
156 continue;
157 }
158 if (flags & WH_EXECUTABLE)
159 if (!(stat_struct.st_mode & S_ISUID)) {
160 path_l = next_path(try_dir, &path_p);
161 continue;
162 }
163 if (!(stat_struct.st_mode & S_IXUSR)) {
164 path_l = next_path(try_dir, &path_p);
165 continue;
166 }
167 found++;
168 if (flags & WH_VERBOSE)
169 printf(_("found %s\n"), try_spec);
170 else {
171 printf("%s\n", try_spec);
172 if (!(flags & WH_ALL))
173 return found;
174 }
175 path_l = next_path(try_dir, &path_p);
176 }
177 return found;
178}
int next_path(char *, char **)
Get the next directory path from a colon-separated list of paths.
Definition whence.c:188
int file_spec_parts(char *, char *, char *)
Split a file specification into directory and file name components.
Definition whence.c:217
char path_s[MAXLEN]
Definition whence.c:25

References file_spec_parts(), next_path(), path_p, path_s, strnz__cat(), strnz__cpy(), WH_ALL, WH_EXECUTABLE, WH_SETUID, and WH_VERBOSE.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ argp_program_bug_address

const char* argp_program_bug_address = "billxwaller@gmail.com"

Definition at line 40 of file whence.c.

◆ argp_program_version

const char* argp_program_version = CM_VERSION

Definition at line 39 of file whence.c.

◆ path_p

char * path_p

Definition at line 24 of file whence.c.

Referenced by main(), and whence().

◆ path_s

char path_s

Definition at line 25 of file whence.c.

Referenced by whence().

◆ wh_flags

int wh_flags = 0

Definition at line 38 of file whence.c.