2
3
4
5
6
7
10
11
12
13
14
15
16
35#include <sys/socket.h>
61 uintmax_t file_size_min;
85int a_toi(
char *,
bool *);
86bool chrep(
char *,
char,
char);
97size_t
strnz(
char *, size_t);
98size_t
strnlf(
char *, size_t);
99bool str_subc(
char *,
char *,
char,
char *, uint);
100char *
rep_substring(
const char *,
const char *,
const char *);
108size_t
ssnprintf(
char *, size_t,
const char *, ...);
111size_t
string_ncat(String *,
const String *, size_t);
112size_t
string_ncpy(String *,
const String *, size_t);
121char *
fill_field(
char *accept_s,
char *display_s,
char fill_char, uint flen);
142
143
144
145
146
147
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)
158
159
160
161
162
163
165 const char *key_name) {
166 for (size_t i = 0; options[i].name != NULL || options[i].key != 0; i++) {
168 if (options[i].name == NULL && options[i].doc != NULL &&
169 options[i].key == 0) {
174 if (options[i].name && strcmp(options[i].name, key_name) == 0) {
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) {
191
192
193
194
195
196
200 if (s == NULL || *s ==
'\0')
203 while (s < e && *s !=
'\0') {
209 if ((uint)(s - str) != len)
214
215
216
217
218
219
224 if (s == NULL || *s ==
'\0')
231 while (s < e && *s !=
'\0') {
238 if ((uint)(s - str) != 7)
243
244
245
246
247
248
249
252 memset(&tmv, 0,
sizeof tmv);
255 if (strptime(s,
"%Y-%m-%dT%H:%M:%S", &tmv) == NULL)
258 time_t t = mktime(&tmv);
266
267
268
269
270
271
272
275 localtime_r(&t, &tmv);
276 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S", &tmv);
280
281
282
283
286 time_t t = time(NULL);
291
292
293
294
295
296
298 uid_t uid = getuid();
299 struct passwd *pw = getpwuid(uid);
306
307
309 if (s ==
nullptr || *s ==
'\0')
311 char *p = s + strlen(s) - 1;
312 while (p >= s && *p ==
' ')
315 return (size_t)(p - s + 1);
318
319
320
321
322
323
326 struct ifaddrs *ifaddr, *ifa;
327 char host[INET_ADDRSTRLEN];
328 bool comma_before =
false;
330 if (getifaddrs(&ifaddr) == -1) {
331 perror(
"getifaddrs");
336 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
337 if (ifa->ifa_addr == NULL)
340 if (ifa->ifa_addr->sa_family == AF_INET) {
341 struct sockaddr_in *pAddr = (
struct sockaddr_in *)ifa->ifa_addr;
344 inet_ntop(AF_INET, &pAddr->sin_addr, host, INET_ADDRSTRLEN);
347 snprintf(tmp_str,
MAXLEN - 1,
",[%s-%s]", ifa->ifa_name, host);
349 snprintf(tmp_str,
MAXLEN - 1,
"[%s-%s]", ifa->ifa_name, host);
358
359
360
362 if (s ==
nullptr || *s ==
'\0')
370 while (*(d - 1) ==
' ' && d > s)
373 return (size_t)(d - s);
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390size_t
ssnprintf(
char *buf, size_t buf_size,
const char *format, ...) {
391 if (buf ==
nullptr || format ==
nullptr || buf_size == 0)
396 va_start(args, format);
397 n = vsnprintf(buf, buf_size, format, args);
403
404
405
406
407
408
409
410
411
413 if (argv ==
nullptr || arg_str ==
nullptr || max_args == 0)
415 if (*arg_str ==
'\0')
423 while (*p !=
'\0' && argc < max_args) {
424 while (isspace((
unsigned char)*p))
434 if (*p ==
'\\' && *(p + 1) ==
'"') {
437 }
else if (*p ==
'"') {
445 if (isspace((
unsigned char)*p)) {
455 argv[argc++] = strdup(tmp_str);
457 argv[argc] =
nullptr;
461
462
463
464
465
466
467
469 for (uint i = 0; i < argc; i++) {
470 if (argv[i] !=
nullptr) {
479
480
481
483 if (s ==
nullptr || *s ==
'\0')
486 if (*s >=
'A' && *s <=
'Z')
493
494
495
497 if (s ==
nullptr || *s ==
'\0')
500 if (*s >=
'a' && *s <=
'z')
507
508
509
510
511
512
513
514
515
516
517
519 if (d ==
nullptr || s ==
nullptr)
529 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
537
538
539
540
541
542
543
544
545
546
547
548
550 if (d ==
nullptr || s ==
nullptr)
560 while (*d !=
'\0' && *d !=
'\n' && *d !=
'\r' && d < e) {
564 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
572
573
574
577 if (s ==
nullptr || *s ==
'\0')
579 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r') {
587
588
589
590
591
592
593
594
595
596
597
599size_t
strnz(
char *s, size_t max_len) {
600 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
604 if (*s ==
'\0' || max_len == 0)
607 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
615
616
617
618
620 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
624 if (*s ==
'\0' || max_len == 0)
627 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
637
638
639
640
641
643 if (s ==
nullptr || *s ==
'\0' || l == 0)
647 if (*s ==
'\0' || l == 0)
649 for (p = s, m = 1; *p !=
'\0'; p++, m++)
651 ms = p = (
char *)malloc(m);
654 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && p < e)
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680bool str_subc(
char *d,
char *s,
char ReplaceChr,
char *Withstr, uint l) {
681 if (d ==
nullptr || s ==
nullptr || Withstr ==
nullptr || l == 0)
690 while (*s !=
'\0' && d < e) {
691 if (*s == ReplaceChr) {
692 while (*Withstr !=
'\0' && d < e)
702
703
704
705
706
707
708
709
712 if (l > 1 && s[l - 1] ==
'\"') {
713 memmove(s, s + 1, l - 2);
719
720
721
722
724 if (s ==
nullptr || *s ==
'\0')
729 if (l > 1 && s[0] ==
'\"' && s[l - 1] ==
'\"') {
730 memmove(s, s + 1, l - 2);
737
738
739
740
741
742
743
744
745
746
747
750 if (buf ==
nullptr || buflen == 0)
754 snprintf(buf, buflen,
"error %d: unknown error", errnum);
756 snprintf(buf, buflen,
"error %d: %s", errnum, tmp_str);
760
761
762
763
764
765bool chrep(
char *s,
char old_chr,
char new_chr) {
776
777
778
779
780
781
782
783
784int a_toi(
char *s,
bool *a_toi_error) {
785 if (s ==
nullptr || *s ==
'\0') {
790 *a_toi_error =
false;
793 rc = (uint)strtol(s,
nullptr, 10);
794 if (rc < 0 || errno) {
801
802
803
804
805
806
807
808
809
810
811
814 unsigned long value = (
unsigned long)strtoull(str, &endptr, 10);
817 switch (tolower(*endptr)) {
819 return value * 1024ULL * 1024ULL * 1024ULL;
821 return value * 1024ULL * 1024ULL;
823 return value * 1024ULL;
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
853 while (*s && *s !=
'm' && *s !=
'K')
855 if (*s ==
'm' || *s ==
'K')
859 if ((
unsigned char)*s <= 127) {
870
871
874 if (fs ==
nullptr || *fs ==
'\0')
876 while (*fs !=
'\0') {
884
885
886
887
888
891 if (fs ==
nullptr || *fs ==
'\0' || fp ==
nullptr) {
912
913
914
915
918 if (fs ==
nullptr || *fs ==
'\0' || file_name ==
nullptr) {
919 if (file_name !=
nullptr)
942
943
944
945
946
947
959
962 if (s ==
nullptr || *s ==
'\0')
986
987
988
991 if (str ==
nullptr || *str ==
'\0')
993 const char tgt[3] =
"~/";
995 char *e = getenv(
"HOME");
1005
1006
1016 while (*p++ !=
'\0') {
1017 if (*p ==
' ' || *p ==
'\t' || *p ==
'\n') {
1023 while (--p > dir && *p ==
'/') {
1024 if (*(p - 1) !=
'~')
1030
1031
1032
1033
1034
1036bool trim_ext(
char *buf,
char *filename) {
1037 if (!filename || !*filename || !buf)
1044 while (filename < --s) {
1053 while (filename < s) {
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1074char *
fdname(
int fd,
char *out_path) {
1077 snprintf(proc_path,
sizeof(proc_path),
"/proc/self/fd/%d", fd);
1078 ssize_t len = readlink(proc_path, out_path,
MAXLEN - 1);
1081 out_path[len] =
'\0';
1087 char buf[
MAXLEN] = {
'\0'};
1088 char err_str[
MAXLEN] = {
'\0'};
1112 char buf[
MAXLEN] = {
'\0'};
1113 char buf0[
MAXLEN] = {
'\0'};
1116 for (
int i = 0; i < 16; i++) {
1126
1127
1128
1129
1130
1131
1134 if (!path || !*path || !buf)
1140 if (*s ==
'/' || *s ==
'\\') {
1153
1154
1155
1156
1157
1159bool dir_name(
char *buf,
char *path) {
1160 if (!path || !*path || !buf)
1167 while (tmp_str < --s) {
1168 if (*s ==
'/' || *s ==
'\\') {
1173 while (tmp_str < --s && (*s ==
'/' || *s ==
'\\'))
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1200 if (spec ==
nullptr || *spec ==
'\0')
1207 if (faccessat(AT_FDCWD, spec, mode, AT_EACCESS) != 0) {
1212 if (fstatat(AT_FDCWD, spec, &sb, 0) != 0) {
1217 if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1251 if (in_spec ==
nullptr || *in_spec ==
'\0')
1261 if ((faccessat(AT_FDCWD, spec, mode, AT_EACCESS)) != 0) {
1266 if ((fstatat(AT_FDCWD, spec, &sb, 0)) != 0) {
1271 if ((sb.st_mode & S_IFMT) != S_IFREG) {
1292
1293
1294
1295
1298 if (file_name ==
nullptr || *file_name ==
'\0' || file_spec ==
nullptr)
1302 char *p, *fnp, *dir;
1307 while (*fnp && *fnp !=
'/')
1311 if ((p = getenv(
"PATH")) ==
nullptr)
1314 dir = strtok(path,
":");
1315 while (dir !=
nullptr) {
1319 if (access(file_spec, F_OK) == 0) {
1322 dir = strtok(
nullptr,
":");
1327
1328
1333 if (!mkdir(dir, 0755)) {
1348
1349
1352 if (spec ==
nullptr || *spec ==
'\0')
1360 while (*s !=
'\0') {
1363 if (*s ==
'\"' || *s ==
'\'') {
1377
1378
1379
1380
1383 struct stat statbuf;
1384 if (stat(path, &statbuf) == 0)
1385 if (S_ISDIR(statbuf.st_mode))
1390
1391
1392
1393
1396 struct stat link_stat;
1397 struct stat target_stat;
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))
1407
1408
1412 uint ret = regcomp(®ex, pattern, REG_EXTENDED);
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1450char *
rep_substring(
const char *org_s,
const char *tgt_s,
const char *rep_s) {
1451 if (*org_s ==
'\0' || *tgt_s ==
'\0' || *rep_s ==
'\0')
1453 if (strstr(org_s, tgt_s) ==
nullptr)
1454 return strdup(org_s);
1455 if (strstr(rep_s, tgt_s) !=
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);
1467 while ((tmp = strstr(ip, tgt_s)) !=
nullptr) {
1471 out_s = malloc(strlen(org_s) + (rep_l - tgt_l) * n + 1);
1478 char *p = strstr(ip, tgt_s);
1484 ip += head_l + tgt_l;
1490
1491
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1525
1526
1527
1528
1529
1539 str
.l = strlen(s) + 1;
1540 str
.s = (
char *)malloc(str
.l);
1545
1546
1547
1548
1549
1560 str
.s = (
char *)malloc(str
.l);
1565
1566
1567
1568
1571 if (string
.s ==
nullptr)
1579
1580
1581
1582
1583
1585size_t
string_cpy(String *dest,
const String *src) {
1586 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1589 dest
->s = (
char *)realloc(dest
->s, src
->l);
1596
1597
1598
1599
1600
1602size_t
string_cat(String *dest,
const String *src) {
1603 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1605 size_t new_len = strlen(dest
->s) + strlen(src
->s) + 1;
1606 if (dest
->l < new_len) {
1607 dest
->s = (
char *)realloc(dest
->s, new_len);
1614
1615
1616
1617
1618
1619
1621size_t
string_ncat(String *dest,
const String *src, size_t n) {
1622 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1624 size_t dest_len = strlen(dest
->s);
1625 size_t src_len = strlen(src
->s);
1626 size_t cat_len = (n < src_len) ? n : src_len;
1627 size_t new_len = dest_len + cat_len + 1;
1628 if (dest
->l < new_len) {
1629 dest
->s = (
char *)realloc(dest
->s, new_len);
1632 strncat(dest
->s, src
->s, cat_len);
1636
1637
1638
1639
1640
1642size_t
string_ncpy(String *dest,
const String *src, size_t n) {
1643 if (dest ==
nullptr || src ==
nullptr || src
->s ==
nullptr)
1645 size_t src_len = strlen(src
->s);
1646 size_t cpy_len = (n < src_len) ? n : src_len;
1647 size_t new_len = cpy_len + 1;
1648 if (dest
->l < new_len) {
1649 dest
->s = (
char *)realloc(dest
->s, new_len);
1652 strncpy(dest
->s, src
->s, cpy_len);
1653 dest
->s[cpy_len] =
'\0';
1657
1658
1661
1662
1663
1664
1665
1680 while (*s !=
'\0') {
1691 if (yyyy < 1 || mm < 1 || mm > 12 || dd < 1)
1693 uint days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1694 if ((yyyy % 4 == 0 && yyyy % 100 != 0) || (yyyy % 400 == 0))
1695 days_in_month[2] = 29;
1696 if (dd > days_in_month[mm])
1701 if (hh > 23 || mm > 59 || ss > 59)
1705void numeric(
char *d,
char *s) {
1706 while (*s !=
'\0') {
1707 if (*s ==
'-' || *s ==
'.' || (*s >=
'0' && *s <=
'9'))
1715char *
fill_field(
char *accept_s,
char *display_s,
char fill_char, uint flen) {
1717 char *d = display_s;
1719 while (*s !=
'\0' && d < e)
1727FileType file_type(
const char *filename) {
1728 FILE *file = fopen(filename,
"rb");
1730 return FT_UNREADABLE;
1732 unsigned char buffer[1024];
1733 size_t bytes_read = fread(buffer, 1,
sizeof(buffer), file);
1735 if (bytes_read == 0) {
1739 if (bytes_read >= 3 && buffer[0] == 0xFF && buffer[1] == 0xD8 && buffer[2] == 0xFF) {
1742 if (bytes_read >= 8 && buffer[0] == 0x89 && buffer[1] == 0x50 && buffer[2] == 0x4E && buffer[3] == 0x47 &&
1743 buffer[4] == 0x0D && buffer[5] == 0x0A && buffer[6] == 0x1A && buffer[7] == 0x0A) {
1746 if (bytes_read >= 4 && buffer[0] ==
'G' && buffer[1] ==
'I' && buffer[2] ==
'F' && buffer[3] ==
'8') {
1749 if (bytes_read >= 12 && buffer[0] ==
'R' && buffer[1] ==
'I' && buffer[2] ==
'F' && buffer[3] ==
'F' &&
1750 buffer[8] ==
'W' && buffer[9] ==
'E' && buffer[10] ==
'B' && buffer[11] ==
'P') {
1754 size_t control_chars = 0;
1755 for (size_t i = 0; i < bytes_read; i++) {
1756 unsigned char c = buffer[i];
1760 return FT_BINARY_GARBAGE;
1764 if (c < 32 && c != 9 && c != 10 && c != 13) {
1770 if ((
double)control_chars / bytes_read > 0.10) {
1771 return FT_BINARY_GARBAGE;
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 *)
char * rep_substring(const char *, const char *, const char *) __attribute__((nonnull(1
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
error_source_t error_source
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
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
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.
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
char 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.
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
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...
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...
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.
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.