2
3
4
5
6
7
10
11
12
13
14
15
16
35#include <sys/socket.h>
68 intmax_t file_size_min;
94int a_toi(
char *,
bool *);
95bool chrep(
char *,
char,
char);
106size_t
strnz(
char *, size_t);
107size_t
strnlf(
char *, size_t);
108bool str_subc(
char *,
char *,
char,
char *,
int);
109char *
rep_substring(
const char *,
const char *,
const char *);
117size_t
ssnprintf(
char *, size_t,
const char *, ...);
118size_t
strnz__cpy(
char *,
const char *, size_t);
119size_t
strnz__cat(
char *,
const char *, size_t);
122size_t
string_ncat(String *,
const String *, size_t);
123size_t
string_ncpy(String *,
const String *, size_t);
133char *
fill_field(
char *accept_s,
char *display_s,
char fill_char,
int flen);
154
155
156
157
158
159
162 struct stat control_st, fut_st;
163 if (!stat(control, &control_st))
164 if (!lstat(fut, &fut_st))
165 if (fut_st.st_mtime > control_st.st_mtime)
170
171
172
173
174
175
177 const char *key_name) {
178 for (size_t i = 0; options[i].name != NULL || options[i].key != 0; i++) {
180 if (options[i].name == NULL && options[i].doc != NULL &&
181 options[i].key == 0) {
186 if (options[i].name && strcmp(options[i].name, key_name) == 0) {
192 if (options[i].key > 0 && options[i].key < 127) {
193 char short_str[2] = {(
char)options[i].key,
'\0'};
194 if (strcmp(short_str, key_name) == 0) {
203
204
205
206
207
208
212 if (s == NULL || *s ==
'\0')
215 while (s < e && *s !=
'\0') {
221 if ((
int)(s - str) != len)
226
227
228
229
230
231
236 if (s == NULL || *s ==
'\0')
243 while (s < e && *s !=
'\0') {
250 if ((
int)(s - str) != 7)
256
257
258
259
260
261
262
263
265 struct tm *tp = local ? localtime(t) : gmtime(t);
267 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S%z", tp);
269 strftime(buf, n,
"%Y-%m-%dT%H:%M:%SZ", tp);
274
275
276
277
278
279
282 memset(&tmv, 0,
sizeof tmv);
285 if (strptime(s,
"%Y-%m-%dT%H:%M:%S", &tmv) == NULL)
288 time_t t = mktime(&tmv);
296
297
298
299
300
301
302
305 localtime_r(&t, &tmv);
306 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S", &tmv);
310
311
312
313
316 time_t t = time(NULL);
321
322
323
324
325
326
328 uid_t uid = getuid();
329 struct passwd *pw = getpwuid(uid);
332 ssnprintf(user_str
, maxlen - 1
, "%s (%u)", pw->pw_name
, (
unsigned int)uid
);
336
337
339 if (s ==
nullptr || *s ==
'\0')
341 char *p = s + strlen(s) - 1;
342 while (p >= s && *p ==
' ')
345 return (size_t)(p - s + 1);
348
349
350
351
352
353
356 struct ifaddrs *ifaddr, *ifa;
357 char host[INET_ADDRSTRLEN];
358 bool comma_before =
false;
360 if (getifaddrs(&ifaddr) == -1) {
361 perror(
"getifaddrs");
366 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
367 if (ifa->ifa_addr == NULL)
370 if (ifa->ifa_addr->sa_family == AF_INET) {
371 struct sockaddr_in *pAddr = (
struct sockaddr_in *)ifa->ifa_addr;
374 inet_ntop(AF_INET, &pAddr->sin_addr, host, INET_ADDRSTRLEN);
377 snprintf(tmp_str,
MAXLEN - 1,
",[%s-%s]", ifa->ifa_name, host);
379 snprintf(tmp_str,
MAXLEN - 1,
"[%s-%s]", ifa->ifa_name, host);
388
389
390
392 if (s ==
nullptr || *s ==
'\0')
400 while (*(d - 1) ==
' ' && d > s)
403 return (size_t)(d - s);
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420size_t
ssnprintf(
char *buf, size_t buf_size,
const char *format, ...) {
424 va_start(args, format);
425 n = vsnprintf(buf, buf_size, format, args);
431
432
433
434
435
436
437
438
439
441 if (arg_str ==
nullptr || *arg_str ==
'\0')
449 while (*p !=
'\0' && argc < max_args) {
450 while (isspace((
unsigned char)*p))
460 if (*p ==
'\\' && *(p + 1) ==
'"') {
463 }
else if (*p ==
'"') {
471 if (isspace((
unsigned char)*p)) {
481 argv[argc++] = strdup(tmp_str);
483 argv[argc] =
nullptr;
487
488
489
490
491
492
493
495 for (
int i = 0; i < argc; i++) {
496 if (argv[i] !=
nullptr) {
505
506
507
509 if (s ==
nullptr || *s ==
'\0')
512 if (*s >=
'A' && *s <=
'Z')
519
520
521
523 if (s ==
nullptr || *s ==
'\0')
526 if (*s >=
'a' && *s <=
'z')
533
534
535
536
537
538
539
540
541
542
543
547 if (s ==
nullptr || d ==
nullptr || max_len == 0) {
548 if (d !=
nullptr && max_len > 0)
553 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
561
562
563
564
565
566
567
568
569
570
571
572
576 if (s ==
nullptr || d ==
nullptr || max_len == 0) {
577 if (d !=
nullptr && max_len > 0)
582 while (*d !=
'\0' && *d !=
'\n' && *d !=
'\r' && d < e) {
586 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
594
595
596
599 if (s ==
nullptr || *s ==
'\0')
601 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r') {
609
610
611
612
613
614
615size_t
strnz(
char *s, size_t max_len) {
618 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
621 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
629
630
631
632
636 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
639 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
649
650
651
652
653
657 if (s ==
nullptr || *s ==
'\0' || l == 0)
659 for (p = s, m = 1; *p !=
'\0'; p++, m++)
661 ms = p = (
char *)malloc(m);
664 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && p < e)
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690bool str_subc(
char *d,
char *s,
char ReplaceChr,
char *Withstr,
int l) {
692 if (s ==
nullptr || d ==
nullptr || Withstr ==
nullptr || l == 0) {
693 if (d !=
nullptr && l > 0)
698 while (*s !=
'\0' && d < e) {
699 if (*s == ReplaceChr) {
700 while (*Withstr !=
'\0' && d < e)
710
711
712
713
714
715
716
717
722 if (l > 1 && s[l - 1] ==
'\"') {
723 memmove(s, s + 1, l - 2);
729
730
731
732
734 if (s ==
nullptr || strlen(s) < 2)
737 if (l > 1 && s[0] ==
'\"' && s[l - 1] ==
'\"') {
738 memmove(s, s + 1, l - 2);
745
746
747
748
749
750bool chrep(
char *s,
char old_chr,
char new_chr) {
761
762
763
764
765
766
767
768
769int a_toi(
char *s,
bool *a_toi_error) {
771 *a_toi_error =
false;
774 rc = (
int)strtol(s,
nullptr, 10);
775 if (rc < 0 || errno) {
782
783
784
785
786
787
788
789
790
791
792
795 unsigned long value = (
unsigned long)strtoull(str, &endptr, 10);
798 switch (tolower(*endptr)) {
800 return value * 1024ULL * 1024ULL * 1024ULL;
802 return value * 1024ULL * 1024ULL;
804 return value * 1024ULL;
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
834 while (*s && *s !=
'm' && *s !=
'K')
836 if (*s ==
'm' || *s ==
'K')
840 if ((
unsigned char)*s <= 127) {
851
852
855 if (fs ==
nullptr || *fs ==
'\0')
857 while (*fs !=
'\0') {
865
866
867
868
869
872 if (fs ==
nullptr || *fs ==
'\0' || fp ==
nullptr) {
893
894
895
896
899 if (fs ==
nullptr || *fs ==
'\0' || file_name ==
nullptr) {
900 if (file_name !=
nullptr)
923
924
925
926
927
928
940
943 if (s ==
nullptr || *s ==
'\0')
967
968
969
972 if (str ==
nullptr || *str ==
'\0')
974 const char tgt[3] =
"~/";
976 char *e = getenv(
"HOME");
986
987
997 while (*p++ !=
'\0') {
998 if (*p ==
' ' || *p ==
'\t' || *p ==
'\n') {
1004 while (--p > dir && *p ==
'/') {
1005 if (*(p - 1) !=
'~')
1011
1012
1013
1014
1015
1017bool trim_ext(
char *buf,
char *filename) {
1018 if (!filename || !*filename || !buf)
1025 while (filename < --s) {
1034 while (filename < s) {
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1055char *
fdname(
int fd,
char *out_path) {
1058 snprintf(proc_path,
sizeof(proc_path),
"/proc/self/fd/%d", fd);
1059 ssize_t len = readlink(proc_path, out_path,
MAXLEN - 1);
1062 out_path[len] =
'\0';
1068 char buf[
MAXLEN] = {
'\0'};
1069 char err_str[
MAXLEN] = {
'\0'};
1093 char buf[
MAXLEN] = {
'\0'};
1117
1118
1119
1120
1121
1122
1125 if (!path || !*path || !buf)
1131 if (*s ==
'/' || *s ==
'\\') {
1144
1145
1146
1147
1148
1150bool dir_name(
char *buf,
char *path) {
1151 if (!path || !*path || !buf)
1158 while (tmp_str < --s) {
1159 if (*s ==
'/' || *s ==
'\\') {
1164 while (tmp_str < --s && (*s ==
'/' || *s ==
'\\'))
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1191 if (spec ==
nullptr || *spec ==
'\0')
1198 if (faccessat(AT_FDCWD, spec, mode, AT_EACCESS) != 0) {
1203 if (fstatat(AT_FDCWD, spec, &sb, 0) != 0) {
1208 if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1242 if (in_spec ==
nullptr || *in_spec ==
'\0')
1252 if ((faccessat(AT_FDCWD, spec, mode, AT_EACCESS)) != 0) {
1257 if ((fstatat(AT_FDCWD, spec, &sb, 0)) != 0) {
1262 if ((sb.st_mode & S_IFMT) != S_IFREG) {
1283
1284
1285
1286
1289 if (file_name ==
nullptr || *file_name ==
'\0' || file_spec ==
nullptr)
1293 char *p, *fnp, *dir;
1298 while (*fnp && *fnp !=
'/')
1302 if ((p = getenv(
"PATH")) ==
nullptr)
1305 dir = strtok(path,
":");
1306 while (dir !=
nullptr) {
1310 if (access(file_spec, F_OK) == 0) {
1313 dir = strtok(
nullptr,
":");
1318
1319
1324 if (!mkdir(dir, 0755)) {
1339
1340
1343 if (spec ==
nullptr || *spec ==
'\0')
1351 while (*s !=
'\0') {
1354 if (*s ==
'\"' || *s ==
'\'') {
1368
1369
1370
1371
1374 struct stat statbuf;
1375 if (stat(path, &statbuf) == 0)
1376 if (S_ISDIR(statbuf.st_mode))
1381
1382
1383
1384
1387 struct stat link_stat;
1388 struct stat target_stat;
1390 if (lstat(path, &link_stat) == 0)
1391 if (S_ISLNK(link_stat.st_mode))
1392 if (stat(path, &target_stat) == 0)
1393 if (S_ISDIR(target_stat.st_mode))
1398
1399
1403 int ret = regcomp(®ex, pattern, REG_EXTENDED);
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1441char *
rep_substring(
const char *org_s,
const char *tgt_s,
const char *rep_s) {
1442 if (org_s ==
nullptr || tgt_s ==
nullptr || rep_s ==
nullptr)
1444 if (*org_s ==
'\0' || *tgt_s ==
'\0' || *rep_s ==
'\0')
1446 if (strstr(org_s, tgt_s) ==
nullptr)
1447 return strdup(org_s);
1448 if (strstr(rep_s, tgt_s) !=
nullptr)
1450 if (tgt_s == rep_s || tgt_s == org_s || rep_s == org_s)
1451 return strdup(org_s);
1452 if (strcmp(org_s, tgt_s) == 0)
1453 return strdup(rep_s);
1454 char *out_s, *ip, *tmp;
1455 int tgt_l = strlen(tgt_s);
1456 int rep_l = strlen(rep_s);
1460 while ((tmp = strstr(ip, tgt_s)) !=
nullptr) {
1464 out_s = malloc(strlen(org_s) + (rep_l - tgt_l) * n + 1);
1471 char *p = strstr(ip, tgt_s);
1477 ip += head_l + tgt_l;
1483
1484
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1518
1519
1520
1521
1522
1532 str
.l = strlen(s) + 1;
1533 str
.s = (
char *)malloc(str
.l);
1538
1539
1540
1541
1542
1553 str
.s = (
char *)malloc(str
.l);
1558
1559
1560
1561
1564 if (string
.s ==
nullptr)
1572
1573
1574
1575
1576
1578size_t
string_cpy(String *dest,
const String *src) {
1579 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1582 dest
->s = (
char *)realloc(dest
->s, src
->l);
1589
1590
1591
1592
1593
1595size_t
string_cat(String *dest,
const String *src) {
1596 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1598 size_t new_len = strlen(dest
->s) + strlen(src
->s) + 1;
1599 if (dest
->l < new_len) {
1600 dest
->s = (
char *)realloc(dest
->s, new_len);
1607
1608
1609
1610
1611
1612
1614size_t
string_ncat(String *dest,
const String *src, size_t n) {
1615 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1617 size_t dest_len = strlen(dest
->s);
1618 size_t src_len = strlen(src
->s);
1619 size_t cat_len = (n < src_len) ? n : src_len;
1620 size_t new_len = dest_len + cat_len + 1;
1621 if (dest
->l < new_len) {
1622 dest
->s = (
char *)realloc(dest
->s, new_len);
1625 strncat(dest
->s, src
->s, cat_len);
1629
1630
1631
1632
1633
1635size_t
string_ncpy(String *dest,
const String *src, size_t n) {
1636 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1638 size_t src_len = strlen(src
->s);
1639 size_t cpy_len = (n < src_len) ? n : src_len;
1640 size_t new_len = cpy_len + 1;
1641 if (dest
->l < new_len) {
1642 dest
->s = (
char *)realloc(dest
->s, new_len);
1645 strncpy(dest
->s, src
->s, cpy_len);
1646 dest
->s[cpy_len] =
'\0';
1650
1651
1654
1655
1656
1657
1658
1672 cmenu_log_fd = open(
"/tmp/cmenu.log", O_WRONLY | O_CREAT | O_TRUNC,
1673 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1676 if (ttyname_r(STDERR_FILENO, ttyname,
sizeof(ttyname)) == 0)
1679 cmenu_user
, ttyname
);
1683
1684
1688 time_t now = time(NULL);
1689 struct tm *t = localtime(&now);
1690 strftime(time_buf,
sizeof(time_buf),
"%Y-%m-%dT%H:%M:%S%z", t);
1699
1700
1714 while (*s !=
'\0') {
1725 if (yyyy < 1 || mm < 1 || mm > 12 || dd < 1)
1727 int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1728 if ((yyyy % 4 == 0 && yyyy % 100 != 0) || (yyyy % 400 == 0))
1729 days_in_month[2] = 29;
1730 if (dd > days_in_month[mm])
1735 if (hh < 0 || hh > 23 || mm < 0 || mm > 59 || ss < 0 || ss > 59)
1739void numeric(
char *d,
char *s) {
1740 while (*s !=
'\0') {
1741 if (*s ==
'-' || *s ==
'.' || (*s >=
'0' && *s <=
'9'))
1749char *
fill_field(
char *accept_s,
char *display_s,
char fill_char,
int flen) {
1751 char *d = display_s;
1753 while (*s !=
'\0' && d < e)
size_t rtrim(char *)
Trims trailing spaces from string s in place.
char * stdio_names(char *, char *)
String mk_string(size_t)
Create a String struct with a dynamically allocated string.
char stdio_names_str[MAXLEN]
bool str_to_bool(const char *)
Converts String to boolean true or false.
char * stdio_fdnames(char *, char *)
char * fill_field(char *, char *, char, int)
error_source_t error_source
int display_error(char *, char *, char *, char *)
Display an error message window or print to stderr.
void numeric(char *d, char *s)
Extract numeric characters from source string to destination string.
bool is_valid_date(int yyyy, int mm, int dd)
Check if a given date is valid, including leap years.
void left_justify(char *s)
Left justify string by removing leading spaces.
bool is_valid_time(int hh, int mm, int ss)
Check if a given time is valid.
void right_justify(char *, int)
Right justify string by removing trailing spaces and adding leadingspaces.
bool locate_file_in_path(char *, char *)
Locates a file in the system PATH.
size_t canonicalize_file_spec(char *)
Removes quotes and trims at first space.
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
int destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
bool parse_local_timestamp(const char *, time_t *)
Parses an ISO 8601 timestamp string in local time and converts it to time_t.
bool trim_ext(char *, char *)
trims the file extension from "filename" and copies the result to "buf"
bool stripz_quotes(char *)
removes leading and trailing double quotes if present
void write_cmenu_log(char *)
Write message to C-Menu log file with timestamp.
size_t trim(char *)
Trims leading and trailing spaces from string s in place.
char * get_local_timestamp()
Returns the current local time as an ISO 8601 formatted string.
bool is_directory(const char *)
Checks if the given path is a directory.
bool file_spec_path(char *, char *)
extracts the path component of a file specification
bool str_to_upper(char *)
Converts a string to uppercase.
bool dir_name(char *, char *)
Returns the directory name of a file specification.
double str_to_double(char *)
converts string to double
bool str_to_lower(char *)
Converts a string to lowercase.
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
bool expand_tilde(char *, int)
Replaces "~/" in string with the user's home directory.
bool strip_quotes(char *)
removes leading and trailing double quotes if present
bool is_valid_regex(const char *)
Checks if the given regular expression pattern is valid.
void open_cmenu_log()
Open new C-Menu log file.
char * strnz_dup(char *, size_t)
Allocates memory for and duplicates string s up to length l or until line feed or carriage return.
bool file_spec_name(char *, char *)
extracts the file name component of a file specification
size_t strip_ansi(char *, char *)
Strips ANSI SGR escape sequences (ending in 'm') from string s to d.
bool mk_dir(char *dir)
If directory doesn't exist, make it.
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
bool str_subc(char *, char *, char, char *, int)
Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all...
bool get_argp_doc_by_name(char *comment, const struct argp_option *, const char *)
Retrieves the documentation string for a given key name from an argp options array.
bool verify_file(char *, int)
Verifies that the file specified by "in_spec" exists and is accessible with the permissions specified...
char * rep_substring(const char *, const char *, const char *)
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
bool is_symlink_to_dir(const char *)
Checks if the given path is a symbolic link to a directory.
size_t strnlf(char *, size_t)
terminates string with line feed
int a_toi(char *, bool *)
a safer alternative to atoi() for converting ASCII strings to integers.
bool is_hex_str(char *, int)
Validates that a string consists of exactly len hexadecimal digits.
void write_cmenu_log_nt(char *)
Write message to C-Menu log file without timestamp.
bool verify_dir(char *, int)
Verifies that the directory specified by "spec" exists and is accessible with the permissions specifi...
bool chrep(char *, char, char)
Replaces all occurrences of old_chr in s with new_chr in place.
bool base_name(char *, char *)
Returns the base name of a file specification.
char * get_ip_addresses(char *, int)
Retrieves the IP addresses of the local machine and formats them into a string.
bool normalize_file_spec(char *)
replace backslashes with forward lashes
char * format_local_timestamp(time_t, char *, size_t)
Formats a time_t as an ISO 8601 string in local time.
bool is_newer(char *, char *)
Checks if the file specified by "fut" is newer than the file specified by "control".
char * fdname(int, char *)
Retrieves the file path associated with a given file descriptor.
int str_to_args(char **, char *, int)
Converts a string into an array of argument strings.
char * get_user_str(char *, size_t)
Retrieves the current user's name and UID, and formats it into a string.
bool trim_path(char *)
Trims trailing spaces and slashes from directory path in place.
unsigned long a_to_ul(const char *)
Converts a string to an unsigned long long integer, with support for suffixes K, M,...
size_t strz(char *)
Terminates string at new line or carriage return.
bool unstr_hex_clr(char *, char *)
Validates that a string is a hex color code in the format "#RRGGBB".
char * iso8601_time(char *, int, time_t *, bool)
Formats a struct tm as an ISO 8601 string.
size_t string_cpy(String *, const String *)
Copy src String to dest String, allocating additional memory for dest String if necessary.
String to_string(const char *)
String functions provide a simple string library to facilitate string manipulation in C,...
size_t string_ncpy(String *, const String *, size_t)
copies up to n characters from src String to dest String, allocating additional memory for dest Strin...
size_t string_cat(String *, const String *)
Concatenates src String to dest String, allocating additional memory for dest String if necessary.
String free_string(String)
Free the dynamically allocated String.
size_t string_ncat(String *, const String *, size_t)
Concatenates up to n characters from src String to dest String, allocating additional memory for dest...
int segmentation_fault()
Function to intentionally cause a segmentation fault for testing purposes.