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 <argp.h>
#include <cm.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.

Enumerations

enum  WhenceFlags { WH_ALL = 1 , WH_VERBOSE = 2 }

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 **sp)
 Extract the next directory path from the PATH string.
void normalend ()
 Exit the program successfully.
void 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 * file_name [MAXLEN+1]
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.

Enumeration Type Documentation

◆ WhenceFlags

Enumerator
WH_ALL 
WH_VERBOSE 

Definition at line 32 of file whence.c.

32{ WH_ALL = 1, WH_VERBOSE = 2 } WhenceFlags;
WhenceFlags
Definition whence.c:32
@ WH_ALL
Definition whence.c:32
@ WH_VERBOSE
Definition whence.c:32

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 236 of file whence.c.

236 {
237 fprintf(stderr, "%s; error %d; %s\n", pgmid, rc, err_msg);
238 exit(EXIT_FAILURE);
239}
char err_msg[MAXLEN]

◆ 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 175 of file whence.c.

175 {
176 int i, last_slash;
177 char tmp_file_spec[PATH_MAX];
178 int file_spec_l;
179 struct stat stat_struct;
180
181 if (stat(file_spec, &stat_struct) != -1)
182 if ((stat_struct.st_mode & S_IFMT) == S_IFDIR) {
183 if (file_spec[strlen(file_path)] != '/')
184 strnz__cat(file_spec, "/", MAXLEN - 1);
185 strnz__cpy(file_path, file_spec, MAXLEN - 1);
186 file_name[0] = '\0';
187 return (0);
188 }
189 if (strlen(file_spec) == 0) {
190 strnz__cpy(file_spec, "./", MAXLEN - 1);
191 file_name[0] = '\0';
192 return (0);
193 }
194 strnz__cpy(tmp_file_spec, file_spec, MAXLEN - 1);
195 last_slash = -1;
196 file_spec_l = strlen(tmp_file_spec);
197 if (file_spec_l > 0) {
198 i = 0;
199 while (i < file_spec_l && tmp_file_spec[i] != '\0') {
200 if (tmp_file_spec[i] == '/') {
201 last_slash = i;
202 break;
203 }
204 i++;
205 }
206 }
207 if (last_slash < 0) {
208 strnz__cpy(file_path, "./", MAXLEN - 1);
209 if (strcmp(file_spec, ".") == 0)
210 file_name[0] = '\0';
211 else
212 strnz__cpy(file_name, tmp_file_spec, MAXLEN - 1);
213 strnz__cpy(file_spec, file_path, MAXLEN - 1);
214 strnz__cat(file_spec, file_name, MAXLEN - 1);
215 } else {
216 tmp_file_spec[last_slash] = '\0';
217 strnz__cpy(file_path, tmp_file_spec, MAXLEN - 1);
218 strnz__cat(file_path, "/", MAXLEN - 1);
219 if (last_slash < file_spec_l)
220 last_slash++;
221 strnz__cpy(file_name, tmp_file_spec + last_slash, MAXLEN - 1);
222 }
223 return (0);
224}
#define MAXLEN
Definition curskeys.c:15
char * file_name[MAXLEN+1]
Definition whence.c:25
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:435
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:464

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 77 of file whence.c.

77 {
78 struct wh_opts wh_opts = {0};
79 wh_opts.flags = 0;
80 wh_opts.argv[0] = nullptr;
81
82 argp_parse(&argp, argc, argv, 0, 0, &wh_opts);
83 path_p = getenv("PATH");
84 if (path_p == nullptr)
85 ABEND(argv[0], 0, "PATH environment variable not set");
86 if (wh_opts.flags & WH_VERBOSE)
87 printf("%s\n", path_p);
88 while (optind < argc) {
89 whence(wh_opts.argv[optind++], wh_opts.flags);
90 }
91 normalend();
92}
void normalend()
Exit the program successfully.
Definition whence.c:228
void ABEND(char *, int, char *)
Exit the program with an error message.
Definition whence.c:236
void whence(char *, int)
Find the full path of a file in the directories specified by the PATH environment variable.
Definition whence.c:103
char * path_p
Definition whence.c:23

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

Here is the call graph for this function:

◆ next_path()

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

Extract the next directory path from the PATH string.

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

This function takes a buffer and a pointer to the current position in the PATH string, and extracts the next directory path. If the next character in the PATH string is a colon, it treats it as an empty path and uses the current working directory. Otherwise, it copies characters until it reaches a colon or the end of the string, and returns the length of the extracted path.

Definition at line 146 of file whence.c.

146 {
147 int dl;
148
149 if (**sp == ':') {
150 (*sp)++;
151 getcwd(dp, PATH_MAX);
152 return (strlen(dp));
153 } else {
154 dl = 0;
155 while (**sp != '\0' && **sp != '\n' && **sp != '\r' && **sp != ':') {
156 *dp++ = *(*sp)++;
157 dl++;
158 }
159 *dp = '\0';
160 if (**sp == ':' && *++(*sp) == '\0')
161 (*sp)--;
162 return (dl);
163 }
164}

Referenced by whence().

Here is the caller graph for this function:

◆ normalend()

void normalend ( )

Exit the program successfully.

This function is called to exit the program with a success status. It simply calls the exit function with EXIT_SUCCESS.

Definition at line 228 of file whence.c.

228{ exit(EXIT_SUCCESS); }

Referenced by main().

Here is the caller graph for this function:

◆ whence()

void 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 103 of file whence.c.

103 {
104 char file_spec[PATH_MAX];
105 char file_dir[PATH_MAX];
106 char file_name[PATH_MAX];
107 char try_spec[PATH_MAX];
108 char try_dir[PATH_MAX];
109 int path_l;
110 struct stat stat_struct;
111
112 strnz__cpy(file_spec, file_spec_p, MAXLEN - 1);
114 file_spec_parts(file_spec, file_dir, file_name);
115 path_p = path_s;
116 path_l = next_path(try_dir, &path_p);
117 while (path_l != 0) {
118 strnz__cpy(try_spec, try_dir, MAXLEN - 1);
119 if (try_spec[path_l] != '/')
120 strnz__cat(try_spec, "/", MAXLEN - 1);
121 strnz__cat(try_spec, file_name, MAXLEN - 1);
122 if (flags & WH_VERBOSE) {
123 if (stat(try_spec, &stat_struct) == -1)
124 printf("- %s\n", try_spec);
125 else
126 printf("found %s\n", try_spec);
127 } else if (stat(try_spec, &stat_struct) == 0) {
128 printf("%s\n", try_spec);
129 if (!(flags & WH_ALL))
130 return;
131 }
132 path_l = next_path(try_dir, &path_p);
133 }
134}
char path_s[MAXLEN]
Definition whence.c:24
int file_spec_parts(char *, char *, char *)
Split a file specification into directory and file name components.
Definition whence.c:175
int next_path(char *, char **)
Extract the next directory path from the PATH string.
Definition whence.c:146

References file_spec_parts(), next_path(), path_p, path_s, strnz__cat(), strnz__cpy(), WH_ALL, 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 35 of file whence.c.

◆ argp_program_version

const char* argp_program_version = CM_VERSION

Definition at line 34 of file whence.c.

◆ file_name

char* file_name[MAXLEN+1]

Definition at line 25 of file whence.c.

◆ path_p

char* path_p

Definition at line 23 of file whence.c.

Referenced by main(), and whence().

◆ path_s

char path_s[MAXLEN]

Definition at line 24 of file whence.c.

Referenced by whence().

◆ wh_flags

int wh_flags = 0

Definition at line 33 of file whence.c.