2
3
4
5
6
7
10
11
12
13
14
15
16
35#include <sys/socket.h>
61 uintmax_t file_size_min;
87int a_toi(
char *,
bool *);
88bool chrep(
char *,
char,
char);
99size_t
strnz(
char *, size_t);
100size_t
strnlf(
char *, size_t);
101bool str_subc(
char *,
char *,
char,
char *, uint);
102char *
rep_substring(
const char *,
const char *,
const char *);
110size_t
ssnprintf(
char *, size_t,
const char *, ...);
111size_t
strnz__cpy(
char *,
const char *, size_t);
112size_t
strnz__cat(
char *,
const char *, size_t);
115size_t
string_ncat(String *,
const String *, size_t);
116size_t
string_ncpy(String *,
const String *, size_t);
126char *
fill_field(
char *accept_s,
char *display_s,
char fill_char, uint flen);
147
148
149
150
151
152
155 struct stat control_st, fut_st;
156 if (!stat(control, &control_st))
157 if (!lstat(fut, &fut_st))
158 if (fut_st.st_mtime > control_st.st_mtime)
163
164
165
166
167
168
170 const char *key_name) {
171 for (size_t i = 0; options[i].name != NULL || options[i].key != 0; i++) {
173 if (options[i].name == NULL && options[i].doc != NULL &&
174 options[i].key == 0) {
179 if (options[i].name && strcmp(options[i].name, key_name) == 0) {
185 if (options[i].key > 0 && options[i].key < 127) {
186 char short_str[2] = {(
char)options[i].key,
'\0'};
187 if (strcmp(short_str, key_name) == 0) {
196
197
198
199
200
201
205 if (s == NULL || *s ==
'\0')
208 while (s < e && *s !=
'\0') {
214 if ((uint)(s - str) != len)
219
220
221
222
223
224
229 if (s == NULL || *s ==
'\0')
236 while (s < e && *s !=
'\0') {
243 if ((uint)(s - str) != 7)
249
250
251
252
253
254
255
256
258 struct tm *tp = local ? localtime(t) : gmtime(t);
260 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S%z", tp);
262 strftime(buf, n,
"%Y-%m-%dT%H:%M:%SZ", tp);
267
268
269
270
271
272
275 memset(&tmv, 0,
sizeof tmv);
278 if (strptime(s,
"%Y-%m-%dT%H:%M:%S", &tmv) == NULL)
281 time_t t = mktime(&tmv);
289
290
291
292
293
294
295
298 localtime_r(&t, &tmv);
299 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S", &tmv);
303
304
305
306
309 time_t t = time(NULL);
314
315
316
317
318
319
321 uid_t uid = getuid();
322 struct passwd *pw = getpwuid(uid);
329
330
332 if (s ==
nullptr || *s ==
'\0')
334 char *p = s + strlen(s) - 1;
335 while (p >= s && *p ==
' ')
338 return (size_t)(p - s + 1);
341
342
343
344
345
346
349 struct ifaddrs *ifaddr, *ifa;
350 char host[INET_ADDRSTRLEN];
351 bool comma_before =
false;
353 if (getifaddrs(&ifaddr) == -1) {
354 perror(
"getifaddrs");
359 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
360 if (ifa->ifa_addr == NULL)
363 if (ifa->ifa_addr->sa_family == AF_INET) {
364 struct sockaddr_in *pAddr = (
struct sockaddr_in *)ifa->ifa_addr;
367 inet_ntop(AF_INET, &pAddr->sin_addr, host, INET_ADDRSTRLEN);
370 snprintf(tmp_str,
MAXLEN - 1,
",[%s-%s]", ifa->ifa_name, host);
372 snprintf(tmp_str,
MAXLEN - 1,
"[%s-%s]", ifa->ifa_name, host);
381
382
383
385 if (s ==
nullptr || *s ==
'\0')
393 while (*(d - 1) ==
' ' && d > s)
396 return (size_t)(d - s);
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413size_t
ssnprintf(
char *buf, size_t buf_size,
const char *format, ...) {
417 va_start(args, format);
418 n = vsnprintf(buf, buf_size, format, args);
424
425
426
427
428
429
430
431
432
434 if (arg_str ==
nullptr || *arg_str ==
'\0')
442 while (*p !=
'\0' && argc < max_args) {
443 while (isspace((
unsigned char)*p))
453 if (*p ==
'\\' && *(p + 1) ==
'"') {
456 }
else if (*p ==
'"') {
464 if (isspace((
unsigned char)*p)) {
474 argv[argc++] = strdup(tmp_str);
476 argv[argc] =
nullptr;
480
481
482
483
484
485
486
488 for (uint i = 0; i < argc; i++) {
489 if (argv[i] !=
nullptr) {
498
499
500
502 if (s ==
nullptr || *s ==
'\0')
505 if (*s >=
'A' && *s <=
'Z')
512
513
514
516 if (s ==
nullptr || *s ==
'\0')
519 if (*s >=
'a' && *s <=
'z')
526
527
528
529
530
531
532
533
534
535
536
540 if (s ==
nullptr || d ==
nullptr || max_len == 0) {
541 if (d !=
nullptr && max_len > 0)
546 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
554
555
556
557
558
559
560
561
562
563
564
565
569 if (s ==
nullptr || d ==
nullptr || max_len == 0) {
570 if (d !=
nullptr && max_len > 0)
575 while (*d !=
'\0' && *d !=
'\n' && *d !=
'\r' && d < e) {
579 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
587
588
589
592 if (s ==
nullptr || *s ==
'\0')
594 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r') {
602
603
604
605
606
607
608size_t
strnz(
char *s, size_t max_len) {
611 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
614 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
622
623
624
625
629 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
632 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
642
643
644
645
646
650 if (s ==
nullptr || *s ==
'\0' || l == 0)
652 for (p = s, m = 1; *p !=
'\0'; p++, m++)
654 ms = p = (
char *)malloc(m);
657 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && p < e)
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683bool str_subc(
char *d,
char *s,
char ReplaceChr,
char *Withstr, uint l) {
685 if (s ==
nullptr || d ==
nullptr || Withstr ==
nullptr || l == 0) {
686 if (d !=
nullptr && l > 0)
691 while (*s !=
'\0' && d < e) {
692 if (*s == ReplaceChr) {
693 while (*Withstr !=
'\0' && d < e)
703
704
705
706
707
708
709
710
715 if (l > 1 && s[l - 1] ==
'\"') {
716 memmove(s, s + 1, l - 2);
722
723
724
725
727 if (s ==
nullptr || strlen(s) < 2)
730 if (l > 1 && s[0] ==
'\"' && s[l - 1] ==
'\"') {
731 memmove(s, s + 1, l - 2);
738
739
740
741
742
743bool chrep(
char *s,
char old_chr,
char new_chr) {
754
755
756
757
758
759
760
761
762int a_toi(
char *s,
bool *a_toi_error) {
764 *a_toi_error =
false;
767 rc = (uint)strtol(s,
nullptr, 10);
768 if (rc < 0 || errno) {
775
776
777
778
779
780
781
782
783
784
785
788 unsigned long value = (
unsigned long)strtoull(str, &endptr, 10);
791 switch (tolower(*endptr)) {
793 return value * 1024ULL * 1024ULL * 1024ULL;
795 return value * 1024ULL * 1024ULL;
797 return value * 1024ULL;
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
827 while (*s && *s !=
'm' && *s !=
'K')
829 if (*s ==
'm' || *s ==
'K')
833 if ((
unsigned char)*s <= 127) {
844
845
848 if (fs ==
nullptr || *fs ==
'\0')
850 while (*fs !=
'\0') {
858
859
860
861
862
865 if (fs ==
nullptr || *fs ==
'\0' || fp ==
nullptr) {
886
887
888
889
892 if (fs ==
nullptr || *fs ==
'\0' || file_name ==
nullptr) {
893 if (file_name !=
nullptr)
916
917
918
919
920
921
933
936 if (s ==
nullptr || *s ==
'\0')
960
961
962
965 if (str ==
nullptr || *str ==
'\0')
967 const char tgt[3] =
"~/";
969 char *e = getenv(
"HOME");
979
980
990 while (*p++ !=
'\0') {
991 if (*p ==
' ' || *p ==
'\t' || *p ==
'\n') {
997 while (--p > dir && *p ==
'/') {
1004
1005
1006
1007
1008
1010bool trim_ext(
char *buf,
char *filename) {
1011 if (!filename || !*filename || !buf)
1018 while (filename < --s) {
1027 while (filename < s) {
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1048char *
fdname(
int fd,
char *out_path) {
1051 snprintf(proc_path,
sizeof(proc_path),
"/proc/self/fd/%d", fd);
1052 ssize_t len = readlink(proc_path, out_path,
MAXLEN - 1);
1055 out_path[len] =
'\0';
1061 char buf[
MAXLEN] = {
'\0'};
1062 char err_str[
MAXLEN] = {
'\0'};
1086 char buf[
MAXLEN] = {
'\0'};
1087 char buf0[
MAXLEN] = {
'\0'};
1090 for (
int i = 0; i < 16; i++) {
1100
1101
1102
1103
1104
1105
1108 if (!path || !*path || !buf)
1114 if (*s ==
'/' || *s ==
'\\') {
1127
1128
1129
1130
1131
1133bool dir_name(
char *buf,
char *path) {
1134 if (!path || !*path || !buf)
1141 while (tmp_str < --s) {
1142 if (*s ==
'/' || *s ==
'\\') {
1147 while (tmp_str < --s && (*s ==
'/' || *s ==
'\\'))
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1174 if (spec ==
nullptr || *spec ==
'\0')
1181 if (faccessat(AT_FDCWD, spec, mode, AT_EACCESS) != 0) {
1186 if (fstatat(AT_FDCWD, spec, &sb, 0) != 0) {
1191 if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1225 if (in_spec ==
nullptr || *in_spec ==
'\0')
1235 if ((faccessat(AT_FDCWD, spec, mode, AT_EACCESS)) != 0) {
1240 if ((fstatat(AT_FDCWD, spec, &sb, 0)) != 0) {
1245 if ((sb.st_mode & S_IFMT) != S_IFREG) {
1266
1267
1268
1269
1272 if (file_name ==
nullptr || *file_name ==
'\0' || file_spec ==
nullptr)
1276 char *p, *fnp, *dir;
1281 while (*fnp && *fnp !=
'/')
1285 if ((p = getenv(
"PATH")) ==
nullptr)
1288 dir = strtok(path,
":");
1289 while (dir !=
nullptr) {
1293 if (access(file_spec, F_OK) == 0) {
1296 dir = strtok(
nullptr,
":");
1301
1302
1307 if (!mkdir(dir, 0755)) {
1322
1323
1326 if (spec ==
nullptr || *spec ==
'\0')
1334 while (*s !=
'\0') {
1337 if (*s ==
'\"' || *s ==
'\'') {
1351
1352
1353
1354
1357 struct stat statbuf;
1358 if (stat(path, &statbuf) == 0)
1359 if (S_ISDIR(statbuf.st_mode))
1364
1365
1366
1367
1370 struct stat link_stat;
1371 struct stat target_stat;
1373 if (lstat(path, &link_stat) == 0)
1374 if (S_ISLNK(link_stat.st_mode))
1375 if (stat(path, &target_stat) == 0)
1376 if (S_ISDIR(target_stat.st_mode))
1381
1382
1386 uint ret = regcomp(®ex, pattern, REG_EXTENDED);
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1424char *
rep_substring(
const char *org_s,
const char *tgt_s,
const char *rep_s) {
1425 if (org_s ==
nullptr || tgt_s ==
nullptr || rep_s ==
nullptr)
1427 if (*org_s ==
'\0' || *tgt_s ==
'\0' || *rep_s ==
'\0')
1429 if (strstr(org_s, tgt_s) ==
nullptr)
1430 return strdup(org_s);
1431 if (strstr(rep_s, tgt_s) !=
nullptr)
1433 if (tgt_s == rep_s || tgt_s == org_s || rep_s == org_s)
1434 return strdup(org_s);
1435 if (strcmp(org_s, tgt_s) == 0)
1436 return strdup(rep_s);
1437 char *out_s, *ip, *tmp;
1438 uint tgt_l = strlen(tgt_s);
1439 uint rep_l = strlen(rep_s);
1443 while ((tmp = strstr(ip, tgt_s)) !=
nullptr) {
1447 out_s = malloc(strlen(org_s) + (rep_l - tgt_l) * n + 1);
1454 char *p = strstr(ip, tgt_s);
1460 ip += head_l + tgt_l;
1466
1467
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1501
1502
1503
1504
1505
1515 str
.l = strlen(s) + 1;
1516 str
.s = (
char *)malloc(str
.l);
1521
1522
1523
1524
1525
1536 str
.s = (
char *)malloc(str
.l);
1541
1542
1543
1544
1547 if (string
.s ==
nullptr)
1555
1556
1557
1558
1559
1561size_t
string_cpy(String *dest,
const String *src) {
1562 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1565 dest
->s = (
char *)realloc(dest
->s, src
->l);
1572
1573
1574
1575
1576
1578size_t
string_cat(String *dest,
const String *src) {
1579 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1581 size_t new_len = strlen(dest
->s) + strlen(src
->s) + 1;
1582 if (dest
->l < new_len) {
1583 dest
->s = (
char *)realloc(dest
->s, new_len);
1590
1591
1592
1593
1594
1595
1597size_t
string_ncat(String *dest,
const String *src, size_t n) {
1598 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1600 size_t dest_len = strlen(dest
->s);
1601 size_t src_len = strlen(src
->s);
1602 size_t cat_len = (n < src_len) ? n : src_len;
1603 size_t new_len = dest_len + cat_len + 1;
1604 if (dest
->l < new_len) {
1605 dest
->s = (
char *)realloc(dest
->s, new_len);
1608 strncat(dest
->s, src
->s, cat_len);
1612
1613
1614
1615
1616
1618size_t
string_ncpy(String *dest,
const String *src, size_t n) {
1619 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1621 size_t src_len = strlen(src
->s);
1622 size_t cpy_len = (n < src_len) ? n : src_len;
1623 size_t new_len = cpy_len + 1;
1624 if (dest
->l < new_len) {
1625 dest
->s = (
char *)realloc(dest
->s, new_len);
1628 strncpy(dest
->s, src
->s, cpy_len);
1629 dest
->s[cpy_len] =
'\0';
1633
1634
1637
1638
1639
1640
1641
1655 cmenu_log_fd = open(
"/tmp/cmenu.log", O_WRONLY | O_CREAT | O_TRUNC,
1656 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1659 if (ttyname_r(STDERR_FILENO, ttyname,
sizeof(ttyname)) == 0)
1662 cmenu_user
, ttyname
);
1666
1667
1671 time_t now = time(NULL);
1672 struct tm *t = localtime(&now);
1673 strftime(time_buf,
sizeof(time_buf),
"%Y-%m-%dT%H:%M:%S%z", t);
1682
1683
1697 while (*s !=
'\0') {
1708 if (yyyy < 1 || mm < 1 || mm > 12 || dd < 1)
1710 uint days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1711 if ((yyyy % 4 == 0 && yyyy % 100 != 0) || (yyyy % 400 == 0))
1712 days_in_month[2] = 29;
1713 if (dd > days_in_month[mm])
1718 if (hh > 23 || mm > 59 || ss > 59)
1722void numeric(
char *d,
char *s) {
1723 while (*s !=
'\0') {
1724 if (*s ==
'-' || *s ==
'.' || (*s >=
'0' && *s <=
'9'))
1732char *
fill_field(
char *accept_s,
char *display_s,
char fill_char, uint flen) {
1734 char *d = display_s;
1736 while (*s !=
'\0' && d < e)
size_t rtrim(char *)
Trims trailing spaces from string s in place.
char stdio_names_str[4096]
char * stdio_names(char *, char *)
String mk_string(size_t)
Create a String struct with a dynamically allocated string.
bool str_to_bool(const char *)
Converts String to boolean true or false.
char * fill_field(char *, char *, char, uint)
char * stdio_fdnames(char *, char *)
error_source_t error_source
int display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
bool is_valid_date(uint yyyy, uint mm, uint dd)
Check if a given date is valid, including leap years.
void numeric(char *d, char *s)
Extract numeric characters from source string to destination string.
bool is_valid_time(uint hh, uint mm, uint ss)
Check if a given time is valid.
void right_justify(char *, uint)
Right justify string by removing trailing spaces and adding leadingspaces.
void left_justify(char *s)
Left justify string by removing leading spaces.
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
char * iso8601_time(char *, uint, time_t *, bool)
Formats a struct tm as an ISO 8601 string.
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 without 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.
bool is_hex_str(char *, uint)
Validates that a string consists of exactly len hexadecimal digits.
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 strip_quotes(char *)
removes leading and trailing double quotes if present
int str_to_args(char **, char *, uint)
Converts a string into an array of argument strings.
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.
bool expand_tilde(char *, uint)
Replaces "~/" in string with the user's home directory.
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 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.
char * get_ip_addresses(char *, uint)
Retrieves the IP addresses of the local machine and formats them into a string.
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.
bool verify_file(char *, uint)
Verifies that the file specified by "in_spec" exists and is accessible with the permissions specified...
size_t strnlf(char *, size_t)
terminates string with line feed
void write_cmenu_log_ts(char *)
Write message to C-Menu log file with timestamp.
int a_toi(char *, bool *)
a safer alternative to atoi() for converting ASCII strings to integers.
bool str_subc(char *, char *, char, char *, uint)
Replaces "ReplaceChr" in "s" with "Withstr" in "d" won't copy more than "l" bytes to "d" Replaces all...
int destroy_argv(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
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.
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.
bool verify_dir(char *, uint)
Verifies that the directory specified by "spec" exists and is accessible with the permissions specifi...
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".
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.