C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
Utility functions

string manipulation, file handling, and error reporting. More...

Functions

unsigned long a_to_ul (const char *str)
 Converts a string to an unsigned long long integer, with support for suffixes K, M, and G for kilobytes, megabytes, and gigabytes respectively.
int a_toi (char *s, bool *a_toi_error)
 a safer alternative to atoi() for converting ASCII strings to integers.
bool base_name (char *buf, char *path)
 Returns the base name of a file specification.
size_t canonicalize_file_spec (char *spec)
 Removes quotes and trims at first space.
bool chrep (char *s, char old_chr, char new_chr)
 Replaces all occurrences of old_chr in s with new_chr in place.
int destroy_argv (uint argc, char **argv)
 Deallocates memory allocated for argument strings in argv.
bool dir_name (char *buf, char *path)
 Returns the directory name of a file specification.
bool expand_tilde (char *str, uint path_maxlen)
 Replaces "~/" in string with the user's home directory.
char * fdname (int fd, char *out_path)
 Retrieves the file path associated with a given file descriptor.
bool file_spec_name (char *file_name, char *fs)
 extracts the file name component of a file specification
bool file_spec_path (char *fp, char *fs)
 extracts the path component of a file specification
char * format_local_timestamp (time_t t, char *buf, size_t n)
 Formats a time_t as an ISO 8601 string in local time.
bool get_argp_doc_by_name (char *comment, const struct argp_option *options, const char *key_name)
 Retrieves the documentation string for a given key name from an argp options array.
char * get_ip_addresses (char *ip_str, uint maxlen)
 Retrieves the IP addresses of the local machine and formats them into a string.
char * get_local_timestamp ()
 Returns the current local time as an ISO 8601 formatted string.
char * get_user_str (char *user_str, size_t maxlen)
 Retrieves the current user's name and UID, and formats it into a string.
bool is_directory (const char *path)
 Checks if the given path is a directory.
bool is_hex_str (char *str, uint len)
 Validates that a string consists of exactly len hexadecimal digits.
bool is_newer (char *control, char *fut)
 Checks if the file specified by "fut" is newer than the file specified by "control".
bool is_symlink_to_dir (const char *path)
 Checks if the given path is a symbolic link to a directory.
bool is_valid_regex (const char *pattern)
 Checks if the given regular expression pattern is valid.
bool locate_file_in_path (char *file_spec, char *file_name)
 Locates a file in the system PATH.
bool mk_dir (char *dir)
 If directory doesn't exist, make it.
bool normalize_file_spec (char *fs)
 replace backslashes with forward lashes
bool parse_local_timestamp (const char *s, time_t *out)
 Parses an ISO 8601 timestamp string in local time and converts it to time_t.
char * rep_substring (const char *org_s, const char *tgt_s, const char *rep_s)
 Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
size_t ssnprintf (char *buf, size_t buf_size, const char *format,...)
 ssnprintf was designed to be a safer alternative to snprintf.
bool str_subc (char *d, char *s, char ReplaceChr, char *Withstr, uint l)
 Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all occurrences of a character in a string with another string, copying the result to a destination buffer.
int str_to_args (char **argv, char *arg_str, uint max_args)
 Converts a string into an array of argument strings.
double str_to_double (char *s)
 converts string to double
bool str_to_lower (char *s)
 Converts a string to lowercase.
bool str_to_upper (char *s)
 Converts a string to uppercase.
char * strerror__r (int errnum, char *buf, size_t buflen)
 A thread-safe alternative to strerror() that writes the error message corresponding to errnum into the provided buffer.
size_t strip_ansi (char *d, char *s)
 Strips ANSI SGR escape sequences (ending in 'm') from string s to d.
bool strip_quotes (char *s)
 removes leading and trailing double quotes if present
bool stripz_quotes (char *s)
 removes leading and trailing double quotes if present
size_t strnlf (char *s, size_t max_len)
 terminates string with line feed
size_t strnz (char *s, size_t max_len)
 terminates string at New Line, Carriage Return, or max_len
size_t strnz__cat (char *d, const char *s, size_t max_len)
 safer alternative to strncat
size_t strnz__cpy (char *d, const char *s, size_t max_len)
 safer alternative to strncpy
char * strnz_dup (char *s, size_t l)
 Allocates memory for and duplicates string s up to length l or until line feed or carriage return.
size_t strz (char *s)
 Terminates string at new line or carriage return.
size_t trim (char *s)
 Trims leading and trailing spaces from string s in place.
bool trim_ext (char *buf, char *filename)
 trims the file extension from "filename" and copies the result to "buf"
bool trim_path (char *dir)
 Trims trailing spaces and slashes from directory path in place.
bool unstr_hex_clr (char *dst, char *str)
 Validates that a string is a hex color code in the format "#RRGGBB".
bool verify_dir (char *spec, uint imode)
 Verifies that the directory specified by "spec" exists and is accessible with the permissions specified by "imode".
bool verify_file (char *in_spec, uint imode)
 Verifies that the file specified by "in_spec" exists and is accessible with the permissions specified by "imode".

Detailed Description

string manipulation, file handling, and error reporting.

These functions provide common operations such as trimming strings, converting case, safely copying and concatenating strings, verifying file and directory access, and locating files in the system PATH. They are designed to be robust and handle edge cases gracefully, making them useful for a wide range of applications.

Function Documentation

◆ a_to_ul()

unsigned long a_to_ul ( const char * str)

Converts a string to an unsigned long long integer, with support for suffixes K, M, and G for kilobytes, megabytes, and gigabytes respectively.

Parameters
str- string to convert
Returns
converted unsigned long long value, or 0 if str is nullptr, empty, or invalid

This function is useful for parsing human-readable file sizes or memory sizes that may include suffixes to indicate the scale of the value. If the string is invalid (e.g., contains non-numeric characters other than the optional suffix), this function returns 0. The caller must ensure that the input string is a valid representation of an unsigned long long integer with an optional suffix before calling this function.

Definition at line 812 of file futil.c.

812 {
813 char *endptr;
814 unsigned long value = (unsigned long)strtoull(str, &endptr, 10);
815 if (endptr == str)
816 return 0;
817 switch (tolower(*endptr)) {
818 case 'g':
819 return value * 1024ULL * 1024ULL * 1024ULL;
820 case 'm':
821 return value * 1024ULL * 1024ULL;
822 case 'k':
823 return value * 1024ULL;
824 default:
825 return value;
826 }
827}

◆ a_toi()

int a_toi ( char * s,
bool * a_toi_error )

a safer alternative to atoi() for converting ASCII strings to integers.

Parameters
sis the input string
a_toi_erroris a pointer to a boolean that will be set to true if an error occurs during conversion, or false if the conversion is successful.
Returns
converted integer value, or -1 if an error occurs

Accepts positive integers only. Sets a_toi_error to (-1) on error

Definition at line 784 of file futil.c.

784 {
785 if (s == nullptr || *s == '\0') {
786 *a_toi_error = true;
787 return -1;
788 }
789 int rc = -1;
790 *a_toi_error = false;
791 errno = 0;
792 if (*s != 0)
793 rc = (uint)strtol(s, nullptr, 10);
794 if (rc < 0 || errno) {
795 rc = -1;
796 *a_toi_error = true;
797 }
798 return rc;
799}

Referenced by parse_ansi_str(), ui_assign_chyron_win(), and ui_parse_ansi().

Here is the caller graph for this function:

◆ base_name()

bool base_name ( char * buf,
char * path )

Returns the base name of a file specification.

Parameters
buf- buffer to receive result
path- file specification
Returns
true if successful
Note
The caller is responsible for ensuring that "buf" has enough space to receive the result.

Definition at line 1132 of file futil.c.

1133 {
1134 if (!path || !*path || !buf)
1135 return false;
1136 char *s = path;
1137 char *d = buf;
1138 *d = '\0';
1139 while (*s) {
1140 if (*s == '/' || *s == '\\') {
1141 d = buf;
1142 } else {
1143 *d++ = *s;
1144 }
1145 s++;
1146 }
1147 *d = '\0';
1148 if (d == buf)
1149 return false;
1150 return true;

Referenced by build_prompt(), exec_objects(), form_exec_receiver(), form_process(), init_form_files(), init_pick_files(), main(), and view_init_input().

Here is the caller graph for this function:

◆ canonicalize_file_spec()

size_t canonicalize_file_spec ( char * spec)

Removes quotes and trims at first space.

Parameters
spec- file specification to canonicalize
Returns
length of resulting string

Definition at line 1350 of file futil.c.

1351 {
1352 if (spec == nullptr || *spec == '\0')
1353 return 0;
1354 char tmp_s[MAXLEN];
1355 char *s;
1356 s = spec;
1357 char *d;
1358 d = tmp_s;
1359 uint l = 0;
1360 while (*s != '\0') {
1361 if (*s == ' ')
1362 break;
1363 if (*s == '\"' || *s == '\'') {
1364 s++;
1365 continue;
1366 ;
1367 }
1368 *d++ = *s++;
1369 l++;
1370 }
1371 *d = '\0';
1372 strnz__cpy(spec, tmp_s, MAXLEN - 1);
1373 l = strlen(spec);
1374 return l;
#define MAXLEN
Definition curskeys.c:15
size_t strnz__cpy(char *d, const char *s, size_t max_len)
safer alternative to strncpy
Definition futil.c:518

References strnz__cpy().

Referenced by locate_file_in_path(), verify_file(), and verify_spec_arg().

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

◆ chrep()

bool chrep ( char * s,
char old_chr,
char new_chr )

Replaces all occurrences of old_chr in s with new_chr in place.

Parameters
s- string to modify
old_chr- character to replace
new_chr- character to insert
Returns
true if successful or false if string s is null

Definition at line 765 of file futil.c.

765 {
766 if (s == nullptr)
767 return false;
768 while (*s != '\0') {
769 if (*s == old_chr)
770 *s = new_chr;
771 s++;
772 }
773 return true;
774}

Referenced by parse_menu_description().

Here is the caller graph for this function:

◆ destroy_argv()

int destroy_argv ( uint argc,
char ** argv )

Deallocates memory allocated for argument strings in argv.

Parameters
argc- count of allocated vectors in argv
argv- array of pointers to arguments
Note
the caller must ensure that argc accurately reflects the number of allocated strings in argv, and that argv is not null. After calling this function, the pointers in argv will be set to nullptr to prevent dangling pointers.

Definition at line 468 of file futil.c.

468 {
469 for (uint i = 0; i < argc; i++) {
470 if (argv[i] != nullptr) {
471 free(argv[i]);
472 argv[i] = nullptr;
473 }
474 }
475 argc = 0;
476 return argc;
477}

Referenced by destroy_init(), destroy_view(), display_pick_help(), enter_file_spec(), exec_objects(), form_engine(), form_exec_receiver(), form_process(), init_pick(), menu_cmd_processor(), new_pick_view(), parse_opt_args(), view_display_help(), and view_init_input().

Here is the caller graph for this function:

◆ dir_name()

bool dir_name ( char * buf,
char * path )

Returns the directory name of a file specification.

Parameters
buf- buffer to receive result
path- file specification
Returns
true if successful
Note
The caller is responsible for ensuring that "buf" has enough space to receive the result.

Definition at line 1158 of file futil.c.

1159 {
1160 if (!path || !*path || !buf)
1161 return false;
1162 char tmp_str[MAXLEN];
1163 strnz__cpy(tmp_str, path, MAXLEN);
1164 char *s = tmp_str;
1165 while (*s++)
1166 ;
1167 while (tmp_str < --s) {
1168 if (*s == '/' || *s == '\\') {
1169 *s = '\0';
1170 break;
1171 }
1172 }
1173 while (tmp_str < --s && (*s == '/' || *s == '\\'))
1174 *s = '\0';
1175 char *d = buf;
1176 *d = '\0';
1177 s = tmp_str;
1178 while (*s) {
1179 *d++ = *s++;
1180 }
1181 *d = '\0';
1182 if (d == buf)
1183 return false;
1184 return true;

References strnz__cpy().

Here is the call graph for this function:

◆ expand_tilde()

bool expand_tilde ( char * str,
uint path_maxlen )

Replaces "~/" in string with the user's home directory.

Parameters
str- string to modify
path_maxlen- maximum length of resulting string
Returns
true if successful, false if str is nullptr or empty

Definition at line 989 of file futil.c.

990 {
991 if (str == nullptr || *str == '\0')
992 return false;
993 const char tgt[3] = "~/";
994 char path[MAXLEN];
995 char *e = getenv("HOME");
996 strnz__cpy(path, e, MAXLEN - 1);
997 strnz__cat(path, "/", MAXLEN - 1);
998 char *tmp;
999 tmp = rep_substring(str, tgt, path);
1000 strnz__cpy(str, tmp, path_maxlen - 1);
1001 free(tmp);
1002 return true;
size_t strnz__cat(char *d, const char *s, size_t max_len)
safer alternative to strncat
Definition futil.c:549
char * rep_substring(const char *, const char *, const char *)
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
Definition futil.c:1449

References rep_substring(), strnz__cat(), and strnz__cpy().

Referenced by enter_file_spec(), init_form_files(), init_pick_files(), init_view_files(), main(), mapp_initialization(), mk_dir(), process_config_file(), process_config_files(), read_theme(), verify_dir(), verify_file(), verify_spec_arg(), and view_init_input().

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

◆ fdname()

char * fdname ( int fd,
char * out_path )

Retrieves the file path associated with a given file descriptor.

Parameters
fd- file descriptor
out_path- buffer to receive the file path
Returns
0 on success, -1 on failure

This function uses the /proc filesystem to read the symbolic link corresponding to the file descriptor. It constructs the path to the symbolic link in /proc/self/fd/ and uses readlink to retrieve the actual file path. The caller must ensure that out_path has enough space to hold the resulting path. If readlink fails, this function returns -1 and does not modify out_path.

Definition at line 1073 of file futil.c.

1074 {
1075 char proc_path[MAXLEN];
1076
1077 snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", fd);
1078 ssize_t len = readlink(proc_path, out_path, MAXLEN - 1);
1079 if (len == -1)
1080 return nullptr;
1081 out_path[len] = '\0';
1082 return out_path;

Referenced by stdio_fdnames().

Here is the caller graph for this function:

◆ file_spec_name()

bool file_spec_name ( char * file_name,
char * fs )

extracts the file name component of a file specification

Parameters
file_name- name component to return
fs- full file specification
Note
The caller is responsible for ensuring that "file_name" has enough space to receive the result.

Definition at line 916 of file futil.c.

917 {
918 if (fs == nullptr || *fs == '\0' || file_name == nullptr) {
919 if (file_name != nullptr)
920 *file_name = '\0';
921 return false;
922 }
923 char *d, *l, *s;
924 l = nullptr;
925 s = fs;
926 while (*s != '\0') {
927 if (*s == '/')
928 l = s;
929 s++;
930 }
931 if (l == nullptr)
932 s = fs;
933 else
934 s = ++l;
935 d = file_name;
936 while (*s != '\0')
937 *d++ = *s++;
938 *d = '\0';
939 return true;

◆ file_spec_path()

bool file_spec_path ( char * fp,
char * fs )

extracts the path component of a file specification

Parameters
fp- path component to return
fs- full file specification
Returns
true if successful
Note
The caller is responsible for ensuring that "fp" has enough space to receive the result.

Definition at line 889 of file futil.c.

890 {
891 if (fs == nullptr || *fs == '\0' || fp == nullptr) {
892 if (fp != nullptr)
893 *fp = '\0';
894 return false;
895 }
896 char *d, *l, *s;
897 s = fp;
898 d = fs;
899 l = nullptr;
900 while (*s != '\0') {
901 if (*s == '/')
902 l = d;
903 *d++ = *s++;
904 }
905 if (l == nullptr)
906 *fp = '\0'; // no slash, so no path
907 else
908 *l = '\0';
909 return true;

◆ format_local_timestamp()

char * format_local_timestamp ( time_t t,
char * buf,
size_t n )

Formats a time_t as an ISO 8601 string in local time.

Parameters
t- time to format
buf- buffer to receive formatted string
n- size of buffer
Returns
pointer to buf
Note
The caller is responsible for ensuring that buf has enough space to hold the resulting string. The ISO 8601 format produced is "YYYY-MM-DDTHH:MM:SS" followed by the local time zone offset (e.g., "+hhmm" or "-hhmm"). This function uses strftime internally, so the actual format may vary based on the implementation of strftime and the locale settings.

Definition at line 273 of file futil.c.

273 {
274 struct tm tmv;
275 localtime_r(&t, &tmv);
276 strftime(buf, n, "%Y-%m-%dT%H:%M:%S", &tmv);
277 return buf;
278}

Referenced by debug_out(), and get_local_timestamp().

Here is the caller graph for this function:

◆ get_argp_doc_by_name()

bool get_argp_doc_by_name ( char * comment,
const struct argp_option * options,
const char * key_name )

Retrieves the documentation string for a given key name from an argp options array.

Parameters
comment- buffer to receive the documentation string
options- array of argp_option structures to search
key_name- the long option name or short option character

Definition at line 164 of file futil.c.

165 {
166 for (size_t i = 0; options[i].name != NULL || options[i].key != 0; i++) {
167 // Skip purely cosmetic header/group entries in argp
168 if (options[i].name == NULL && options[i].doc != NULL &&
169 options[i].key == 0) {
170 continue;
171 }
172
173 // 1. Check against the long option name (e.g., "verbose")
174 if (options[i].name && strcmp(options[i].name, key_name) == 0) {
175 strnz__cpy(comment, options[i].doc, MAXLEN - 1);
176 return true;
177 }
178
179 // 2. Check against the short option key character (e.g., 'v')
180 if (options[i].key > 0 && options[i].key < 127) {
181 char short_str[2] = {(char)options[i].key, '\0'};
182 if (strcmp(short_str, key_name) == 0) {
183 strnz__cpy(comment, options[i].doc, MAXLEN - 1);
184 return true;
185 }
186 }
187 }
188 return false; // Key not found in the argp structure
189}

References strnz__cpy().

Referenced by print_argp_doc().

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

◆ get_ip_addresses()

char * get_ip_addresses ( char * ip_str,
uint maxlen )

Retrieves the IP addresses of the local machine and formats them into a string.

Parameters
ip_str- buffer to receive formatted string of IP addresses
maxlen- size of buffer
Returns
pointer to ip_str containing the formatted IP addresses, or nullptr if an error occurs

This function uses getifaddrs to retrieve a linked list of network interfaces on the local machine. It iterates through the list and checks for interfaces with IPv4 addresses (AF_INET). For each valid interface, it converts the binary IP address to a human-readable string using inet_ntop and appends it to the provided buffer in the format "[interface-name-IP-address]". Multiple interfaces are separated by commas. The caller must ensure that ip_str has enough space to hold the resulting string. If getifaddrs fails, this function returns nullptr and does not modify the buffer.

Definition at line 324 of file futil.c.

324 {
325 char tmp_str[MAXLEN];
326 struct ifaddrs *ifaddr, *ifa;
327 char host[INET_ADDRSTRLEN];
328 bool comma_before = false;
329 // getifaddrs returns a linked list of network interface structures
330 if (getifaddrs(&ifaddr) == -1) {
331 perror("getifaddrs");
332 exit(EXIT_FAILURE);
333 }
334 ip_str[0] = '\0';
335 // Walk through the linked list
336 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
337 if (ifa->ifa_addr == NULL)
338 continue;
339 // Check for IPv4 addresses
340 if (ifa->ifa_addr->sa_family == AF_INET) {
341 struct sockaddr_in *pAddr = (struct sockaddr_in *)ifa->ifa_addr;
342
343 // Convert binary IP to human-readable string
344 inet_ntop(AF_INET, &pAddr->sin_addr, host, INET_ADDRSTRLEN);
345
346 if (comma_before)
347 snprintf(tmp_str, MAXLEN - 1, ",[%s-%s]", ifa->ifa_name, host);
348 else
349 snprintf(tmp_str, MAXLEN - 1, "[%s-%s]", ifa->ifa_name, host);
350 strnz__cat(ip_str, tmp_str, maxlen - 1);
351 comma_before = true;
352 }
353 }
354 freeifaddrs(ifaddr); // Clean up the memory allocated by getifaddrs
355 return ip_str;
356}

References strnz__cat().

Referenced by debug_out().

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

◆ get_local_timestamp()

char * get_local_timestamp ( )

Returns the current local time as an ISO 8601 formatted string.

Returns
pointer to static buffer containing the current local timestamp in ISO 8601 format
Note
The returned string is stored in a static buffer, so it will be overwritten by subsequent calls to this function. The format of the returned string is "YYYY-MM-DDTHH:MM:SS" followed by the local time zone offset (e.g., "+hhmm" or "-hhmm"). This function uses the current system time and formats it using strftime internally, so the actual format may vary based on the implementation of strftime and the locale settings.

Definition at line 284 of file futil.c.

284 {
285 static char buf[32];
286 time_t t = time(NULL);
287 format_local_timestamp(t, buf, sizeof buf);
288 return buf;
289}
char * format_local_timestamp(time_t, char *, size_t)
Formats a time_t as an ISO 8601 string in local time.
Definition futil.c:273

References format_local_timestamp().

Referenced by debug_out().

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

◆ get_user_str()

char * get_user_str ( char * user_str,
size_t maxlen )

Retrieves the current user's name and UID, and formats it into a string.

Parameters
user_str- buffer to receive formatted string
maxlen- size of buffer
Returns
pointer to user_str containing the formatted user information, or nullptr if an error occurs

This function uses getuid to retrieve the current user's UID, then uses getpwuid to get the corresponding passwd structure, which contains the user's name. It formats the user's name and UID into the provided buffer in the format "User: username (uid)\n". The caller must ensure that user_str has enough space to hold the resulting string. If getpwuid fails (e.g., if the UID does not exist), this function returns nullptr and does not modify the buffer.

Definition at line 297 of file futil.c.

297 {
298 uid_t uid = getuid();
299 struct passwd *pw = getpwuid(uid);
300 if (pw == NULL)
301 return nullptr;
302 ssnprintf(user_str, maxlen - 1, "%s (%u)", pw->pw_name, (uint)uid);
303 return user_str;
304}
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:390

References ssnprintf().

Referenced by debug_out().

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

◆ is_directory()

bool is_directory ( const char * path)

Checks if the given path is a directory.

Parameters
path- path to check
Returns
0 exists 1 is a directory -1 does not exist

Definition at line 1381 of file futil.c.

1382 {
1383 struct stat statbuf;
1384 if (stat(path, &statbuf) == 0)
1385 if (S_ISDIR(statbuf.st_mode))
1386 return true;
1387 return false;

Referenced by main().

Here is the caller graph for this function:

◆ is_hex_str()

bool is_hex_str ( char * str,
uint len )

Validates that a string consists of exactly len hexadecimal digits.

Parameters
str- input string to validate
len- expected number of hexadecimal digits
Returns
true if str is a valid hex string of the specified length, false otherwise

This function checks that the input string contains only hexadecimal characters (0-9, A-F, a-f) and that the total number of hex digits matches the specified length. If the input string is valid, it returns true; otherwise, it returns false. The caller must ensure that the input string is not null and has at least one character before calling this function.

Definition at line 197 of file futil.c.

197 {
198 char *s = str;
199 char *e;
200 if (s == NULL || *s == '\0')
201 return false;
202 e = (s + len + 1);
203 while (s < e && *s != '\0') {
204 if (!isxdigit(*s)) {
205 return false;
206 }
207 s++;
208 }
209 if ((uint)(s - str) != len)
210 return false;
211 return true;
212}

◆ is_newer()

bool is_newer ( char * control,
char * fut )

Checks if the file specified by "fut" is newer than the file specified by "control".

Parameters
control- path to the control file
fut- path to the file to compare against the control file
Returns
true if "fut" is newer than "control", false otherwise

This function uses the stat system call to retrieve the modification times of both files. It compares the modification time of "fut" with that of "control" and returns true if "fut" has a more recent modification time. If either file cannot be accessed or if any error occurs during the stat calls, this function returns false. The caller must ensure that both file paths are valid and that the files exist before calling this function.

Definition at line 148 of file futil.c.

148 {
149 // is fut newer than control?
150 struct stat control_st, fut_st;
151 if (!stat(control, &control_st))
152 if (!lstat(fut, &fut_st))
153 if (fut_st.st_mtime > control_st.st_mtime)
154 return true;
155 return false;
156}

◆ is_symlink_to_dir()

bool is_symlink_to_dir ( const char * path)

Checks if the given path is a symbolic link to a directory.

Parameters
path- path to check
Returns
0 exists 1 symbolic link to a directory -1 does not exist or not a symbolic link to a directory

Definition at line 1394 of file futil.c.

1395 {
1396 struct stat link_stat;
1397 struct stat target_stat;
1398
1399 if (lstat(path, &link_stat) == 0)
1400 if (S_ISLNK(link_stat.st_mode))
1401 if (stat(path, &target_stat) == 0)
1402 if (S_ISDIR(target_stat.st_mode))
1403 return true; // symbolic link to a directory
1404 return false;

Referenced by main().

Here is the caller graph for this function:

◆ is_valid_regex()

bool is_valid_regex ( const char * pattern)

Checks if the given regular expression pattern is valid.

Parameters
pattern- regular expression pattern to check
Returns
true if the pattern is valid, false otherwise

Definition at line 1409 of file futil.c.

1410 {
1411 regex_t regex;
1412 uint ret = regcomp(&regex, pattern, REG_EXTENDED);
1413 regfree(&regex);
1414 if (ret == 0)
1415 return true;
1416 return false;

Referenced by main().

Here is the caller graph for this function:

◆ locate_file_in_path()

bool locate_file_in_path ( char * file_spec,
char * file_name )

Locates a file in the system PATH.

Parameters
file_spec- buffer to receive located file specification
file_name- name of file to locate
Returns
true if file is located
Note
file_spec must be large enough to receive the result

Definition at line 1296 of file futil.c.

1297 {
1298 if (file_name == nullptr || *file_name == '\0' || file_spec == nullptr)
1299 return false;
1300 char path[MAXLEN];
1301 char ifn[MAXLEN];
1302 char *p, *fnp, *dir;
1303
1304 canonicalize_file_spec(file_name);
1305 strnz__cpy(ifn, file_name, MAXLEN - 1);
1306 fnp = ifn;
1307 while (*fnp && *fnp != '/')
1308 fnp++;
1309 if (*fnp == '/')
1310 return false;
1311 if ((p = getenv("PATH")) == nullptr)
1312 return false;
1313 strnz__cpy(path, p, MAXLEN - 1);
1314 dir = strtok(path, ":");
1315 while (dir != nullptr) {
1316 strnz__cpy(file_spec, dir, MAXLEN - 1);
1317 strnz__cat(file_spec, "/", MAXLEN - 1);
1318 strnz__cat(file_spec, file_name, MAXLEN - 1);
1319 if (access(file_spec, F_OK) == 0) {
1320 return true;
1321 }
1322 dir = strtok(nullptr, ":");
1323 }
1324 return false;
size_t canonicalize_file_spec(char *)
Removes quotes and trims at first space.
Definition futil.c:1350

References canonicalize_file_spec(), strnz__cat(), and strnz__cpy().

Referenced by init_form_files(), init_pick_files(), and verify_spec_arg().

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

◆ mk_dir()

bool mk_dir ( char * dir)

If directory doesn't exist, make it.

Parameters
dirdirectory name
Returns
true if directory now exists or false otherwise

Directory does not exist and unable to create

Definition at line 1329 of file futil.c.

1330 {
1331 expand_tilde(dir, MAXLEN - 1);
1332 if (!verify_dir(dir, S_WCOK | S_QUIET)) {
1333 if (!mkdir(dir, 0755)) {
1335 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
1336 strnz__cpy(em1, "mkdir ", MAXLEN - 1);
1337 strnz__cat(em1, dir, MAXLEN - 1);
1338 strnz__cat(em1, " failed", MAXLEN - 1);
1339 strerror__r(errno, em2, MAXLEN - 1);
1340 ui_display_error(em0, em1, em2, nullptr);
1341 return false;
1342 }
1343 return true;
1344 }
1345 return true;
#define S_QUIET
Definition cm.h:264
#define S_WCOK
Definition cm.h:263
char em1[MAXLEN]
Definition ui_common.c:47
char em2[MAXLEN]
Definition ui_common.c:48
char em0[MAXLEN]
Definition ui_common.c:46
bool expand_tilde(char *str, uint path_maxlen)
Replaces "~/" in string with the user's home directory.
Definition futil.c:989
char * strerror__r(int errnum, char *buf, size_t buflen)
A thread-safe alternative to strerror() that writes the error message corresponding to errnum into th...
Definition futil.c:748
bool verify_dir(char *, uint)
Verifies that the directory specified by "spec" exists and is accessible with the permissions specifi...
Definition futil.c:1198
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition ui_common.c:1200

References em0, em1, em2, expand_tilde(), ssnprintf(), strerror__r(), strnz__cat(), strnz__cpy(), ui_display_error(), and verify_dir().

Referenced by enter_file_spec().

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

◆ normalize_file_spec()

bool normalize_file_spec ( char * fs)

replace backslashes with forward lashes

Parameters
fs- file specification to normalize
Returns
true if successful, false if fs is nullptr or empty

Definition at line 872 of file futil.c.

873 {
874 if (fs == nullptr || *fs == '\0')
875 return false;
876 while (*fs != '\0') {
877 if (*fs == '\\')
878 *fs = '/';
879 fs++;
880 }
881 return true;

◆ parse_local_timestamp()

bool parse_local_timestamp ( const char * s,
time_t * out )

Parses an ISO 8601 timestamp string in local time and converts it to time_t.

Parameters
s- ISO 8601 timestamp string to parse (e.g., "2024-06-01T12:34:56")
out- pointer to time_t variable to receive the result
Returns
true if parsing and conversion were successful, false otherwise

This function expects the input string to be in the format "YYYY-MM-DDTHH:MM:SS" representing local time. It uses strptime to parse the string into a struct tm, then uses mktime to convert it to time_t. The caller must ensure that the input string is properly formatted and represents a valid date and time. If the input string is invalid or if any error occurs during parsing or conversion, this function returns false and does not modify the output variable.

Definition at line 250 of file futil.c.

250 {
251 struct tm tmv;
252 memset(&tmv, 0, sizeof tmv);
253 tmv.tm_isdst = -1;
254
255 if (strptime(s, "%Y-%m-%dT%H:%M:%S", &tmv) == NULL)
256 return false;
257
258 time_t t = mktime(&tmv);
259 if (t == (time_t)-1)
260 return false;
261
262 *out = t;
263 return true;
264}

◆ rep_substring()

char * rep_substring ( const char * org_s,
const char * tgt_s,
const char * rep_s )

Replace all occurrences of "tgt_s" in "org_s" with "rep_s".

Parameters
org_s- original string
tgt_s- target substring to replace
rep_s- replacement substring
Returns
A pointer to the newly allocated string with replacements or a copy of the replacement string if original string is the same as target string This is a special case that allows for replacing the entire original string. If any parameter is nullptr, the function returns nullptr. If "tgt_s" is not found in "org_s", the function returns a copy of "org_s". If target substring is not found the function returns a copy of the original string.
Note
allocates memory for the return value, so the caller is responsible for freeing this memory when it is no longer needed to avoid memory leaks. Does not modify the original string "org_s".
Assumes that "tgt_s" and "rep_s" are null-terminated strings. If they are not, the behavior is undefined.
Does not perform any bounds checking on the input strings, so it is the caller's responsibility to ensure that they are valid and that the resulting string does not exceed available memory.
Uses the standard library functions strlen, strstr, malloc, and strcpy, which may have their own limitations and behaviors that the caller should be aware of.
Does not handle overlapping occurrences of "tgt_s" in "org_s". If "tgt_s" can overlap with itself in "org_s", the behavior may be unexpected. The caller should ensure that "tgt_s" does not contain overlapping patterns to avoid this issue.
Does not handle cases where "tgt_s" is a substring of "rep_s", which could lead to unintended consequences if "tgt_s" appears in "rep_s". The caller should ensure that "tgt_s" and "rep_s" are distinct to avoid this issue.

Definition at line 1449 of file futil.c.

1450 {
1451 if (*org_s == '\0' || *tgt_s == '\0' || *rep_s == '\0')
1452 return nullptr;
1453 if (strstr(org_s, tgt_s) == nullptr)
1454 return strdup(org_s);
1455 if (strstr(rep_s, tgt_s) != nullptr)
1456 return nullptr;
1457 if (tgt_s == rep_s || tgt_s == org_s || rep_s == org_s)
1458 return strdup(org_s);
1459 if (strcmp(org_s, tgt_s) == 0)
1460 return strdup(rep_s);
1461 char *out_s, *ip, *tmp;
1462 uint tgt_l = strlen(tgt_s);
1463 uint rep_l = strlen(rep_s);
1464 uint head_l;
1465 uint n = 0;
1466 ip = (char *)org_s;
1467 while ((tmp = strstr(ip, tgt_s)) != nullptr) {
1468 n++;
1469 ip = tmp + tgt_l;
1470 }
1471 out_s = malloc(strlen(org_s) + (rep_l - tgt_l) * n + 1);
1472 if (!out_s) {
1473 return nullptr;
1474 }
1475 tmp = out_s;
1476 ip = (char *)org_s;
1477 while (n--) {
1478 char *p = strstr(ip, tgt_s);
1479 head_l = p - ip;
1480 strnz__cpy(tmp, ip, head_l);
1481 tmp += head_l;
1482 strnz__cpy(tmp, rep_s, MAXLEN - 1);
1483 tmp += rep_l;
1484 ip += head_l + tgt_l;
1485 }
1486 strnz__cpy(tmp, ip, MAXLEN - 1);
1487 return out_s;

◆ ssnprintf()

size_t ssnprintf ( char * buf,
size_t buf_size,
const char * format,
... )

ssnprintf was designed to be a safer alternative to snprintf.

It ensures that the buffer is not overflowed by taking the buffer size as a parameter and using vsnprintf internally. It also returns the number of characters that would have been written if enough space had been available, allowing the caller to detect truncation. This function is particularly useful in situations where the formatted string may exceed the buffer size, as it prevents buffer overflows and provides a way to handle such cases gracefully.

Parameters
buf- buffer to receive formatted string
buf_size- size of buffer
format- printf-style format string
...- arguments
Returns
number of characters that would have been written if enough space had been available

Definition at line 390 of file futil.c.

390 {
391 if (buf == nullptr || format == nullptr || buf_size == 0)
392 return 0;
393 size_t n;
394 va_list args;
395
396 va_start(args, format);
397 n = vsnprintf(buf, buf_size, format, args);
398 va_end(args);
399
400 return n;
401}

Referenced by debug_out(), display_line(), display_split_line(), enter_file_spec(), finder(), fork_exec(), form_desc_error(), form_parse_desc(), form_process(), form_write(), get_cmd_char(), get_user_str(), handle_signal(), init_view_full_screen(), lp(), mapp_initialization(), menu_engine(), mk_dir(), new_init(), new_pick(), new_view(), open_pick_win(), pad_refresh(), parse_menu_description(), picker(), signal_handler(), stdio_fdnames(), stdio_names(), ui_action_disposition(), ui_add_pair(), ui_answer_yn(), ui_color_from_rgb(), ui_compile_chyron(), ui_display_error(), ui_open_log(), ui_perror(), ui_register_read_fd(), ui_set_chyron_key(), ui_set_chyron_key_cb(), ui_surface_box(), ui_surface_new(), ui_timeout_prompt(), ui_update_timeout_prompt(), verify_dir(), verify_file(), view_cmd_processor(), view_init_input(), write_config(), and write_view_buffer().

Here is the caller graph for this function:

◆ str_subc()

bool str_subc ( char * d,
char * s,
char ReplaceChr,
char * Withstr,
uint l )

Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all occurrences of a character in a string with another string, copying the result to a destination buffer.

Parameters
d- destination string
s- source string
ReplaceChr- character to replace
Withstr- string to insert
l- maximum length to copy
Returns
true if successful, false if any parameter is invalid

This function ensures that the total length of the resulting string does not exceed the specified limit, and that the result is null-terminated. This function is useful for simple string substitutions where you want to replace a single character with a longer string, such as replacing spaces with underscores or tabs with spaces.

Note
The caller must ensure that "d" has enough space to receive the result, and that "l" is sufficient to hold the result. This function does not perform any bounds checking on "d" or "Withstr", so it is the caller's responsibility to ensure that they are valid and that "l" is appropriate for the operation.

Definition at line 680 of file futil.c.

680 {
681 if (d == nullptr || s == nullptr || Withstr == nullptr || l == 0)
682 return false;
683 char *e;
684 if (l == 0) {
685 if (l > 0)
686 *d = '\0';
687 return false;
688 }
689 e = d + l;
690 while (*s != '\0' && d < e) {
691 if (*s == ReplaceChr) {
692 while (*Withstr != '\0' && d < e)
693 *d++ = *Withstr++;
694 s++;
695 } else
696 *d++ = *s++;
697 }
698 *d = '\0';
699 return true;
700}

Referenced by view_cmd_processor().

Here is the caller graph for this function:

◆ str_to_args()

int str_to_args ( char ** argv,
char * arg_str,
uint max_args )

Converts a string into an array of argument strings.

Parameters
argv- array of pointers to arguments
arg_str- string containing arguments
max_args- maximum number of arguments to parse
Returns
argc, a count of allocated vectors in argv

Handles quoted strings and escaped quotes, preserving text inside quotes as individual arguments. It has been in service for many years without problems.

Note
The caller is responsible for deallocating the strings in argv.

Definition at line 412 of file futil.c.

412 {
413 if (argv == nullptr || arg_str == nullptr || max_args == 0)
414 return 0;
415 if (*arg_str == '\0')
416 return 0;
417 uint argc = 0;
418 char *p = arg_str;
419 char tmp_str[MAXLEN];
420 uint in_quotes = 0;
421 char *d = tmp_str;
422
423 while (*p != '\0' && argc < max_args) {
424 while (isspace((unsigned char)*p))
425 p++;
426 if (*p == '\0')
427 break;
428 if (*p == '"') {
429 in_quotes = 1;
430 p++;
431 }
432 while (*p != '\0') {
433 if (in_quotes) {
434 if (*p == '\\' && *(p + 1) == '"') {
435 *d++ = '"';
436 p += 2;
437 } else if (*p == '"') {
438 *d++ = '\0';
439 p++;
440 in_quotes = 0;
441 break;
442 } else
443 *d++ = *p++;
444 } else {
445 if (isspace((unsigned char)*p)) {
446 *d++ = '\0';
447 p++;
448 break;
449 } else
450 *d++ = *p++;
451 }
452 }
453 *d = '\0';
454 d = tmp_str;
455 argv[argc++] = strdup(tmp_str);
456 }
457 argv[argc] = nullptr;
458 return argc;
459}

Referenced by enter_file_spec(), exec_objects(), form_exec_receiver(), form_process(), init_pick(), menu_cmd_processor(), and view_init_input().

Here is the caller graph for this function:

◆ str_to_double()

double str_to_double ( char * s)

converts string to double

Parameters
s- string to convert
Returns
converted double value, or 0.0 if s is nullptr, empty, or invalid
Note
The caller must ensure that the string is a valid representation of a double before calling this function.
Parameters
s- string to convert
Returns
converted double value, or 0.0 if s is nullptr, empty, or invalid
Note
The caller must ensure that the string is a valid representation of a double before calling this function.

Definition at line 948 of file futil.c.

949 {
950 char *e;
951 double d;
952
953 if (!s || !*s)
954 return false;
955 d = strtod(s, &e);
956 return d;

Referenced by process_config_file().

Here is the caller graph for this function:

◆ str_to_lower()

bool str_to_lower ( char * s)

Converts a string to lowercase.

Parameters
s- string to convert
Returns
true if successful, false if s is nullptr or empty

Definition at line 482 of file futil.c.

482 {
483 if (s == nullptr || *s == '\0')
484 return false;
485 while (*s != '\0') {
486 if (*s >= 'A' && *s <= 'Z')
487 *s = *s + 'a' - 'A';
488 s++;
489 }
490 return true;
491}

Referenced by form_parse_desc().

Here is the caller graph for this function:

◆ str_to_upper()

bool str_to_upper ( char * s)

Converts a string to uppercase.

Parameters
s- string to convert
Returns
true if successful, false if s is nullptr or empty

Definition at line 496 of file futil.c.

496 {
497 if (s == nullptr || *s == '\0')
498 return false;
499 while (*s != '\0') {
500 if (*s >= 'a' && *s <= 'z')
501 *s = *s + 'A' - 'a';
502 s++;
503 }
504 return true;
505}

Referenced by process_config_file().

Here is the caller graph for this function:

◆ strerror__r()

char * strerror__r ( int errnum,
char * buf,
size_t buflen )

A thread-safe alternative to strerror() that writes the error message corresponding to errnum into the provided buffer.

Parameters
errnum- error number (typically from errno)
buf- buffer to receive the error message
buflen- size of the buffer
Returns
pointer to buf containing the error message, or nullptr if buf is null or buflen is zero

This function uses strerror_r to retrieve the error message in a thread-safe manner. If the error number is unknown, it formats a default message indicating that the error is unknown. The caller must ensure that buf has enough space to hold the resulting string.

Definition at line 748 of file futil.c.

748 {
749 char tmp_str[MAXLEN];
750 if (buf == nullptr || buflen == 0)
751 return nullptr;
752 strnz__cpy(tmp_str, strerror_r(errnum, buf, buflen), MAXLEN - 1);
753 if (buf == nullptr)
754 snprintf(buf, buflen, "error %d: unknown error", errnum);
755 else
756 snprintf(buf, buflen, "error %d: %s", errnum, tmp_str);
757 return buf;
758}

References strnz__cpy().

Referenced by enter_file_spec(), form_parse_desc(), form_process(), form_write(), mk_dir(), view_cmd_processor(), view_init_input(), and write_view_buffer().

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

◆ strip_ansi()

size_t strip_ansi ( char * d,
char * s )

Strips ANSI SGR escape sequences (ending in 'm') from string s to d.

Parameters
dDestination string
sSource string
Returns
Length of stripped string
char dest[1024];
char src[] = "\033[31mThis is red text\033[0m
size_t len = strip_ansi(dest, src);
Result: dest = "This is red text", len = 17
@example stripansi.c

Only handles SGR sequences ending in 'm' or 'K' Skips non-ASCII characters The caller must ensure that d has enough space to hold the stripped string This function does not allocate memory; it assumes d is pre-allocated This function processes the entire string until the null terminator This function does not modify the source string s

Definition at line 848 of file futil.c.

849 {
850 size_t l = 0;
851 while (*s) {
852 if (*s == '\033') {
853 while (*s && *s != 'm' && *s != 'K')
854 s++;
855 if (*s == 'm' || *s == 'K')
856 s++;
857 continue;
858 } else {
859 if ((unsigned char)*s <= 127) {
860 *d++ = *s++;
861 l++;
862 } else
863 s++;
864 }
865 }
866 *d = '\0';
867 return l;

Referenced by main(), and write_view_buffer().

Here is the caller graph for this function:

◆ strip_quotes()

bool strip_quotes ( char * s)

removes leading and trailing double quotes if present

Parameters
s- string to strip quotes from
Returns
true if successful, false if s is nullptr or empty

If the string has a leading double quote and a trailing double quote, this function removes them in place. If the string does not have both leading and trailing double quotes, it is left unchanged. The function returns true if the operation was successful (i.e., if the string was modified or if it was valid), and false if the input string was null or empty.

Definition at line 710 of file futil.c.

710 {
711 uint l = strlen(s);
712 if (l > 1 && s[l - 1] == '\"') {
713 memmove(s, s + 1, l - 2);
714 s[l - 2] = '\0';
715 }
716 return true;
717}

Referenced by init_form_files(), and init_view_files().

Here is the caller graph for this function:

◆ stripz_quotes()

bool stripz_quotes ( char * s)

removes leading and trailing double quotes if present

Parameters
s- string to strip quotes from
Returns
true if quotes were removed

Same as STRIP_QUOTES but returns true if quotes were removed

Definition at line 723 of file futil.c.

723 {
724 if (s == nullptr || *s == '\0')
725 return false;
726 if (strlen(s) < 2)
727 return false;
728 uint l = strlen(s);
729 if (l > 1 && s[0] == '\"' && s[l - 1] == '\"') {
730 memmove(s, s + 1, l - 2);
731 s[l - 2] = '\0';
732 return true;
733 }
734 return false;
735}

Referenced by verify_spec_arg().

Here is the caller graph for this function:

◆ strnlf()

size_t strnlf ( char * s,
size_t max_len )

terminates string with line feed

Parameters
sstring to terminate
max_lenmaximum length to scan
Returns
length of resulting string

Definition at line 619 of file futil.c.

619 {
620 if (s == nullptr || *s == '\0' || max_len == 0)
621 return 0;
622 char *e;
623 size_t len = 0;
624 if (*s == '\0' || max_len == 0)
625 return 0;
626 e = s + max_len;
627 while (*s != '\0' && *s != '\n' && *s != '\r' && s < e) {
628 s++;
629 len++;
630 }
631 *s++ = '\n';
632 len++;
633 *s = '\0';
634 return (len);
635}

Referenced by write_view_buffer().

Here is the caller graph for this function:

◆ strnz()

size_t strnz ( char * s,
size_t max_len )

terminates string at New Line, Carriage Return, or max_len

Parameters
sstring to terminate
max_len- maximum length to scan
Returns
length of resulting string

The use case is to ensure that strings read from files or user input do not contain embedded newlines or carriage returns. WARNING: This function is prone to segmentation faults because it attempts to write a terminating zero. Do not use strnz() on: read-only function arguments such as const and quoted literals or strings not terminated in the first max_len characters

Definition at line 599 of file futil.c.

599 {
600 if (s == nullptr || *s == '\0' || max_len == 0)
601 return 0;
602 char *e;
603 size_t len = 0;
604 if (*s == '\0' || max_len == 0)
605 return 0;
606 e = s + max_len;
607 while (*s != '\0' && *s != '\n' && *s != '\r' && s < e) {
608 s++;
609 len++;
610 }
611 *s = '\0';
612 return (len);
613}

Referenced by display_form(), enter_file_spec(), form_display_fields(), form_fmt_field(), and ui_perror().

Here is the caller graph for this function:

◆ strnz__cat()

size_t strnz__cat ( char * d,
const char * s,
size_t max_len )

safer alternative to strncat

Parameters
d- destination string
s- source string
max_len- maximum length to copy
Returns
length of resulting string

Append string s to d, ensuring that the total length of d does not exceed max_len, and that the resulting string is null-terminated. It also treats newline and carriage return characters as string terminators, preventing them from being included in the result. This is particularly useful when concatenating user input or file data, where embedded newlines could cause issues.

Definition at line 549 of file futil.c.

549 {
550 if (d == nullptr || s == nullptr)
551 return 0;
552 char *e;
553 size_t len = 0;
554 if (max_len == 0) {
555 if (max_len > 0)
556 *d = '\0';
557 return 0;
558 }
559 e = d + max_len;
560 while (*d != '\0' && *d != '\n' && *d != '\r' && d < e) {
561 d++;
562 len++;
563 }
564 while (*s != '\0' && *s != '\n' && *s != '\r' && d < e) {
565 *d++ = *s++;
566 len++;
567 }
568 *d = '\0';
569 return len;
570}

Referenced by build_prompt(), derive_file_spec(), display_form(), display_pick_help(), enter_file_spec(), exec_objects(), expand_tilde(), file_spec_parts(), form_engine(), form_exec_cmd(), form_exec_receiver(), form_parse_desc(), form_process(), form_read_data(), form_write(), get_ip_addresses(), init_form(), init_menu_files(), init_pick(), init_view_files(), locate_file_in_path(), mapp_initialization(), menu_cmd_processor(), mk_dir(), new_pick_view(), new_view_file(), output_objects(), parse_menu_description(), picker(), popup_ckeys(), search(), stdio_fdnames(), stdio_names(), verify_spec_arg(), view_cmd_processor(), view_display_help(), view_init_input(), whence(), write_config(), and write_view_buffer().

Here is the caller graph for this function:

◆ strnz__cpy()

size_t strnz__cpy ( char * d,
const char * s,
size_t max_len )

safer alternative to strncpy

copies string s to d, ensuring that the total length of d does not exceed max_len, and that the resulting string is null-terminated. It also treats newline and carriage return characters as string terminators, preventing them from being included in the result. This is particularly useful when copying user input or file data, where embedded newlines could cause issues.

Parameters
d- destination string
s- source string
max_len- maximum length to copy
Returns
length of resulting string

Definition at line 518 of file futil.c.

518 {
519 if (d == nullptr || s == nullptr)
520 return 0;
521 char *e;
522 size_t len = 0;
523 if (max_len == 0) {
524 if (max_len > 0)
525 *d = '\0';
526 return 0;
527 }
528 e = d + max_len;
529 while (*s != '\0' && *s != '\n' && *s != '\r' && d < e) {
530 *d++ = *s++;
531 len++;
532 }
533 *d = '\0';
534 return len;
535}

Referenced by build_prompt(), canonicalize_file_spec(), derive_file_spec(), dir_name(), display_form(), display_pick_help(), display_prompt(), enter_file_spec(), exec_objects(), expand_tilde(), file_spec_parts(), form_desc_error(), form_engine(), form_exec_cmd(), form_exec_receiver(), form_fmt_field(), form_parse_desc(), form_process(), form_read_data(), form_write(), get_argp_doc_by_name(), get_cmd_arg(), handle_signal(), init_form(), init_form_files(), init_lf(), init_menu_files(), init_pick(), init_pick_files(), init_view_files(), locate_file_in_path(), log_strnz(), main(), mapp_initialization(), menu_cmd_processor(), mk_dir(), new_form(), new_pick_view(), new_view_file(), output_objects(), parse_menu_description(), picker(), popup_ckeys(), process_config_file(), process_config_files(), rep_substring(), save_object(), search(), stdio_fdnames(), stdio_names(), strerror__r(), ui_answer_yn(), ui_border_ysplit_text(), ui_display_error(), ui_open_log(), ui_perror(), ui_surface_box(), ui_timeout_prompt(), verify_dir(), verify_file(), verify_spec_arg(), view_cmd_processor(), view_display_help(), view_file(), view_init_input(), whence(), write_config(), and write_view_buffer().

Here is the caller graph for this function:

◆ strnz_dup()

char * strnz_dup ( char * s,
size_t l )

Allocates memory for and duplicates string s up to length l or until line feed or carriage return.

Parameters
s- string to duplicate
l- maximum length to copy
Returns
pointer to allocated memory

Definition at line 642 of file futil.c.

642 {
643 if (s == nullptr || *s == '\0' || l == 0)
644 return nullptr;
645 char *p, *ms, *e;
646 size_t m;
647 if (*s == '\0' || l == 0)
648 return nullptr;
649 for (p = s, m = 1; *p != '\0'; p++, m++)
650 ;
651 ms = p = (char *)malloc(m);
652 if (ms != nullptr) {
653 e = ms + l;
654 while (*s != '\0' && *s != '\n' && *s != '\r' && p < e)
655 *p++ = *s++;
656 *p = '\0';
657 }
658 return ms;
659}

Referenced by new_view().

Here is the caller graph for this function:

◆ strz()

size_t strz ( char * s)

Terminates string at new line or carriage return.

Parameters
sstring to terminate

Definition at line 575 of file futil.c.

575 {
576 size_t l = 0;
577 if (s == nullptr || *s == '\0')
578 return 0;
579 while (*s != '\0' && *s != '\n' && *s != '\r') {
580 s++;
581 l++;
582 }
583 *s = '\0';
584 return l;
585}

◆ trim()

size_t trim ( char * s)

Trims leading and trailing spaces from string s in place.

Parameters
s- string to trim
Returns
length of trimmed string

Definition at line 361 of file futil.c.

361 {
362 if (s == nullptr || *s == '\0')
363 return 0;
364 char *p = s;
365 char *d = s;
366 while (*p == ' ')
367 p++;
368 while (*p != '\0')
369 *d++ = *p++;
370 while (*(d - 1) == ' ' && d > s)
371 d--;
372 *d = '\0';
373 return (size_t)(d - s);
374}

Referenced by form_fmt_field(), form_parse_desc(), left_justify(), menu_cmd_processor(), parse_menu_description(), right_justify(), and right_justify().

Here is the caller graph for this function:

◆ trim_ext()

bool trim_ext ( char * buf,
char * filename )

trims the file extension from "filename" and copies the result to "buf"

Parameters
buf- buffer to receive result
filename- filename to trim
Note
The caller is responsible for ensuring that "buf" has enough space to receive the result.

Definition at line 1035 of file futil.c.

1036 {
1037 if (!filename || !*filename || !buf)
1038 return false;
1039 char *s = filename;
1040 char *d = buf;
1041 *d = '\0';
1042 while (*s)
1043 s++;
1044 while (filename < --s) {
1045 if (*s == '.') {
1046 break;
1047 }
1048 }
1049 if (*s != '.') {
1050 while (*filename)
1051 *d++ = *filename++;
1052 } else {
1053 while (filename < s) {
1054 *d++ = *filename++;
1055 }
1056 }
1057 *d = '\0';
1058 if (d == buf)
1059 return false;
1060 return true;

◆ trim_path()

bool trim_path ( char * dir)

Trims trailing spaces and slashes from directory path in place.

Parameters
dir- directory path to trim
Returns
true if successful

Definition at line 1007 of file futil.c.

1008 {
1009 if (!dir)
1010 return false;
1011 char *p;
1012
1013 if (!dir || !*dir)
1014 return false;
1015 p = dir;
1016 while (*p++ != '\0') {
1017 if (*p == ' ' || *p == '\t' || *p == '\n') {
1018 *p = '\0';
1019 break;
1020 }
1021 }
1022 --p;
1023 while (--p > dir && *p == '/') {
1024 if (*(p - 1) != '~')
1025 *p = '\0';
1026 }
1027 return true;

Referenced by derive_file_spec().

Here is the caller graph for this function:

◆ unstr_hex_clr()

bool unstr_hex_clr ( char * dst,
char * str )

Validates that a string is a hex color code in the format "#RRGGBB".

Parameters
dst- buffer to receive validated hex color string
str- input string to validate
Returns
true if str is a valid hex color code, false otherwise

This function checks that the input string starts with a '#' character, followed by exactly six hexadecimal digits (0-9, A-F, a-f). If the input string is valid, it copies the hex color code into the provided destination buffer. The caller must ensure that dst has enough space to hold the resulting string (at least 8 characters including the null terminator). If the input string is invalid (e.g., does not start with '#', contains non-hex characters, or does not have exactly six hex digits), this function returns false and does not modify the destination buffer.

Definition at line 220 of file futil.c.

220 {
221 char *s = str;
222 char *e;
223 char *d;
224 if (s == NULL || *s == '\0')
225 return false;
226 if (*s != '#')
227 return false;
228 d = dst;
229 *d++ = *s++;
230 e = (s + 6);
231 while (s < e && *s != '\0') {
232 if (!isxdigit(*s)) {
233 return false;
234 }
235 *d++ = *s++;
236 }
237 *d = '\0';
238 if ((uint)(s - str) != 7)
239 return false;
240 return true;
241}

Referenced by process_config_file().

Here is the caller graph for this function:

◆ verify_dir()

bool verify_dir ( char * spec,
uint imode )

Verifies that the directory specified by "spec" exists and is accessible with the permissions specified by "imode".

Parameters
spec- directory specification
imode- access mode F_OK - existence R_OK - read W_OK - Write X_OK - Execute S_WCOK - Write or Create S_QUIET - Suppress Error Messages
Returns
true if successful

S_WCOK and S_QUIET are stripped before calling faccessat

Definition at line 1198 of file futil.c.

1199 {
1200 if (spec == nullptr || *spec == '\0')
1201 return false;
1202 expand_tilde(spec, MAXLEN);
1203 struct stat sb;
1204 errno = 0;
1205 src_line = 0;
1206 uint mode = imode & ~(S_WCOK | S_QUIET);
1207 if (faccessat(AT_FDCWD, spec, mode, AT_EACCESS) != 0) {
1208 src_line = __LINE__ - 1;
1209 src_name = __FILE__;
1210 strnz__cpy(fn, "faccessat", MAXLEN - 1);
1211 } else {
1212 if (fstatat(AT_FDCWD, spec, &sb, 0) != 0) {
1213 src_line = __LINE__ - 1;
1214 src_name = __FILE__;
1215 strnz__cpy(fn, "fstatat", MAXLEN - 1);
1216 } else {
1217 if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1218 src_line = __LINE__ - 1;
1219 src_name = __FILE__;
1220 strnz__cpy(fn, "verify_file", MAXLEN - 1);
1221 strnz__cpy(em2, "Not a regular file.", MAXLEN - 1);
1222 }
1223 }
1224 }
1225 if (src_line != 0) {
1226 if (!(mode & S_QUIET)) {
1227 ssnprintf(em0, MAXLEN - 1, "%s failed in %s at line %d", fn,
1229 strnz__cpy(em1, spec, MAXLEN - 1);
1230 strnz__cpy(em3, "Check the file", MAXLEN - 1);
1232 }
1233 return false;
1234 }
1235 return true;
char fn[MAXLEN]
Definition ui_common.c:45
uint src_line
Definition ui_common.c:43
char * src_name
Definition ui_common.c:44
char em3[MAXLEN]
Definition ui_common.c:49

References em0, em1, em2, em3, expand_tilde(), fn, src_line, src_name, ssnprintf(), strnz__cpy(), and ui_display_error().

Referenced by mapp_initialization(), mk_dir(), and verify_spec_arg().

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

◆ verify_file()

bool verify_file ( char * in_spec,
uint imode )

Verifies that the file specified by "in_spec" exists and is accessible with the permissions specified by "imode".

Parameters
in_spec- directory specification
imode- access mode F_OK - existence R_OK - read W_OK - Write X_OK - Execute S_WCOK - Write or Create S_QUIET - Suppress Error Messages
Returns
true if successful

S_WCOK and S_QUIET are stripped before calling faccessat

Definition at line 1249 of file futil.c.

1250 {
1251 if (in_spec == nullptr || *in_spec == '\0')
1252 return false;
1253 struct stat sb;
1254 char spec[MAXLEN];
1255 strnz__cpy(spec, in_spec, MAXLEN - 1);
1256 uint mode = imode & ~(S_WCOK | S_QUIET);
1257 errno = 0;
1258 src_line = 0;
1260 expand_tilde(spec, MAXLEN);
1261 if ((faccessat(AT_FDCWD, spec, mode, AT_EACCESS)) != 0) {
1262 src_line = __LINE__ - 1;
1263 src_name = __FILE__;
1264 strnz__cpy(fn, "faccessat", MAXLEN - 1);
1265 } else {
1266 if ((fstatat(AT_FDCWD, spec, &sb, 0)) != 0) {
1267 src_line = __LINE__ - 1;
1268 src_name = __FILE__;
1269 strnz__cpy(fn, "fstatat", MAXLEN - 1);
1270 } else {
1271 if ((sb.st_mode & S_IFMT) != S_IFREG) {
1272 src_line = __LINE__ - 1;
1273 src_name = __FILE__;
1274 strnz__cpy(fn, "verify_file", MAXLEN - 1);
1275 strnz__cpy(em2, "Not a regular file.", MAXLEN - 1);
1276 }
1277 }
1278 }
1279 if (src_line != 0) {
1280 if (imode & S_QUIET)
1281 return false;
1282 ssnprintf(em0, MAXLEN - 1, _("%s failed in %s at line %d"), fn, src_name,
1283 src_line);
1284 strnz__cpy(em1, spec, MAXLEN - 1);
1285 strnz__cpy(em3, "Check the file", MAXLEN - 1);
1287 return false;
1288 }
1289 return true;
#define _(String)
Definition amort.c:23

References canonicalize_file_spec(), em0, em1, em2, em3, expand_tilde(), fn, src_line, src_name, ssnprintf(), strnz__cpy(), and ui_display_error().

Referenced by verify_spec_arg().

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