2
3
4
5
6
7
10
11
12
13
14
15
16
34#include <sys/socket.h>
62 intmax_t file_size_min;
88int a_toi(
char *, bool *);
89bool
chrep(
char *,
char,
char);
100size_t
strnz(
char *, size_t);
101size_t
strnlf(
char *, size_t);
102bool
str_subc(
char *,
char *,
char,
char *,
int);
103char *
rep_substring(
const char *,
const char *,
const char *);
111size_t
ssnprintf(
char *, size_t,
const char *, ...);
112size_t
strnz__cpy(
char *,
const char *, size_t);
113size_t
strnz__cat(
char *,
const char *, size_t);
116size_t
string_ncat(String *,
const String *, size_t);
117size_t
string_ncpy(String *,
const String *, size_t);
147
148
149
150
151
152
153
154
156 struct tm *tp = local ? localtime(t) : gmtime(t);
158 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S%z", tp);
160 strftime(buf, n,
"%Y-%m-%dT%H:%M:%SZ", tp);
165
166
167
168
169
170
173 memset(&tmv, 0,
sizeof tmv);
176 if (strptime(s,
"%Y-%m-%dT%H:%M:%S", &tmv) == NULL)
179 time_t t = mktime(&tmv);
187
188
189
190
191
192
193
196 localtime_r(&t, &tmv);
197 strftime(buf, n,
"%Y-%m-%dT%H:%M:%S", &tmv);
201
202
203
204
207 time_t t = time(NULL);
212
213
214
215
216
217
219 uid_t uid = getuid();
220 struct passwd *pw = getpwuid(uid);
223 ssnprintf(user_str
, maxlen - 1
, "%s (%u)", pw->pw_name
, (
unsigned int)uid
);
227
228
230 if (s ==
nullptr || *s ==
'\0')
232 char *p = s + strlen(s) - 1;
233 while (p >= s && *p ==
' ')
236 return (size_t)(p - s + 1);
239
240
241
242
243
244
247 struct ifaddrs *ifaddr, *ifa;
248 char host[INET_ADDRSTRLEN];
249 bool comma_before = false;
251 if (getifaddrs(&ifaddr) == -1) {
252 perror(
"getifaddrs");
257 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
258 if (ifa->ifa_addr == NULL)
261 if (ifa->ifa_addr->sa_family == AF_INET) {
262 struct sockaddr_in *pAddr = (
struct sockaddr_in *)ifa->ifa_addr;
265 inet_ntop(AF_INET, &pAddr->sin_addr, host, INET_ADDRSTRLEN);
268 snprintf(tmp_str,
MAXLEN - 1,
",[%s-%s]", ifa->ifa_name, host);
270 snprintf(tmp_str,
MAXLEN - 1,
"[%s-%s]", ifa->ifa_name, host);
279
280
281
283 if (s ==
nullptr || *s ==
'\0')
291 while (*(d - 1) ==
' ' && d > s)
294 return (size_t)(d - s);
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311size_t
ssnprintf(
char *buf, size_t buf_size,
const char *format, ...) {
315 va_start(args, format);
316 n = vsnprintf(buf, buf_size, format, args);
322
323
324
325
326
327
328
329
330
332 if (arg_str ==
nullptr || *arg_str ==
'\0')
340 while (*p !=
'\0' && argc < max_args) {
341 while (isspace((
unsigned char)*p))
351 if (*p ==
'\\' && *(p + 1) ==
'"') {
354 }
else if (*p ==
'"') {
362 if (isspace((
unsigned char)*p)) {
372 argv[argc++] = strdup(tmp_str);
378
379
380
381
382
383
384
386 for (
int i = 0; i < argc; i++) {
396
397
398
400 if (s ==
nullptr || *s ==
'\0')
403 if (*s >=
'A' && *s <=
'Z')
410
411
412
414 if (s ==
nullptr || *s ==
'\0')
417 if (*s >=
'a' && *s <=
'z')
424
425
426
427
428
429
430
431
432
433
434
439 if (d !=
nullptr && max_len > 0)
444 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
452
453
454
455
456
457
458
459
460
461
462
463
468 if (d !=
nullptr && max_len > 0)
473 while (*d !=
'\0' && *d !=
'\n' && *d !=
'\r' && d < e) {
477 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && d < e) {
485
486
487
490 if (s ==
nullptr || *s ==
'\0')
492 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r') {
500
501
502
503
504
505
506size_t
strnz(
char *s, size_t max_len) {
509 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
512 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
520
521
522
523
527 if (s ==
nullptr || *s ==
'\0' || max_len == 0)
530 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && s < e) {
540
541
542
543
544
548 if (s ==
nullptr || *s ==
'\0' || l == 0)
550 for (p = s, m = 1; *p !=
'\0'; p++, m++)
552 rs = p = (
char *)malloc(m);
555 while (*s !=
'\0' && *s !=
'\n' && *s !=
'\r' && p < e)
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581bool
str_subc(
char *d,
char *s,
char ReplaceChr,
char *Withstr,
int l) {
589 while (*s !=
'\0' && d < e) {
590 if (*s == ReplaceChr) {
591 while (*Withstr !=
'\0' && d < e)
601
602
603
604
605
617
618
619
624 if (l > 1 && s[l - 1] ==
'\"') {
625 memmove(s, s + 1, l - 2);
631
632
633
634
636 if (s ==
nullptr || strlen(s) < 2)
639 if (l > 1 && s[0] ==
'\"' && s[l - 1] ==
'\"') {
640 memmove(s, s + 1, l - 2);
647
648
649
650
651
652bool
chrep(
char *s,
char old_chr,
char new_chr) {
663
664
665
666
667
668
669
670
671int a_toi(
char *s, bool *a_toi_error) {
673 *a_toi_error = false;
676 rc = (
int)strtol(s,
nullptr, 10);
677 if (rc < 0 || errno) {
684
685
686
687
688
689
690
691
692
693
694
697 unsigned long value = (
unsigned long)strtoull(str, &endptr, 10);
700 switch (tolower(*endptr)) {
702 return value * 1024ULL * 1024ULL * 1024ULL;
704 return value * 1024ULL * 1024ULL;
706 return value * 1024ULL;
712
713
714
715
716
720 buffer[0] = (uint8_t)cp;
722 }
else if (cp <= 0x7FF) {
724 buffer[0] = (uint8_t)(0xC0 | ((cp >> 6) & 0x1F));
725 buffer[1] = (uint8_t)(0x80 | (cp & 0x3F));
727 }
else if (cp <= 0xFFFF) {
729 buffer[0] = (uint8_t)(0xE0 | ((cp >> 12) & 0x0F));
730 buffer[1] = (uint8_t)(0x80 | ((cp >> 6) & 0x3F));
731 buffer[2] = (uint8_t)(0x80 | (cp & 0x3F));
733 }
else if (cp <= 0x10FFFF) {
735 buffer[0] = (uint8_t)(0xF0 | ((cp >> 18) & 0x07));
736 buffer[1] = (uint8_t)(0x80 | ((cp >> 12) & 0x3F));
737 buffer[2] = (uint8_t)(0x80 | ((cp >> 6) & 0x3F));
738 buffer[3] = (uint8_t)(0x80 | (cp & 0x3F));
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
768 while (*s && *s !=
'm' && *s !=
'K')
770 if (*s ==
'm' || *s ==
'K')
774 if ((
unsigned char)*s <= 127) {
785
786
789 if (fs ==
nullptr || *fs ==
'\0')
791 while (*fs !=
'\0') {
799
800
801
802
803
827
828
829
830
857
858
859
860
861
862
874
877 if (s ==
nullptr || *s ==
'\0')
901
902
903
906 if (str ==
nullptr || *str ==
'\0')
908 const char tgt[3] =
"~/";
910 char *e = getenv(
"HOME");
920
921
931 while (*p++ !=
'\0') {
932 if (*p ==
' ' || *p ==
'\t' || *p ==
'\n') {
938 while (--p > dir && *p ==
'/') {
945
946
947
948
949
951bool
trim_ext(
char *buf,
char *filename) {
952 if (!filename || !*filename || !buf)
959 while (filename < --s) {
968 while (filename < s) {
978
979
980
981
982
983
986 if (!path || !*path || !buf)
992 if (*s ==
'/' || *s ==
'\\') {
1005
1006
1007
1008
1009
1011bool
dir_name(
char *buf,
char *path) {
1012 if (!path || !*path || !buf)
1019 while (tmp_str < --s) {
1020 if (*s ==
'/' || *s ==
'\\') {
1025 while (tmp_str < --s && (*s ==
'/' || *s ==
'\\'))
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1052 if (spec ==
nullptr || *spec ==
'\0')
1059 if (faccessat(AT_FDCWD, spec, mode, AT_EACCESS) != 0) {
1064 if (fstatat(AT_FDCWD, spec, &sb, 0) != 0) {
1069 if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1103 if (in_spec ==
nullptr || *in_spec ==
'\0')
1113 if ((faccessat(AT_FDCWD, spec, mode, AT_EACCESS)) != 0) {
1118 if ((fstatat(AT_FDCWD, spec, &sb, 0)) != 0) {
1123 if ((sb.st_mode & S_IFMT) != S_IFREG) {
1144
1145
1146
1147
1150 if (file_name ==
nullptr || *file_name ==
'\0' || file_spec ==
nullptr)
1154 char *p, *fnp, *dir;
1159 while (*fnp && *fnp !=
'/')
1163 if ((p = getenv(
"PATH")) ==
nullptr)
1166 dir = strtok(path,
":");
1171 if (access(file_spec, F_OK) == 0) {
1179
1180
1185 if (!mkdir(dir, 0755)) {
1200
1201
1204 if (spec ==
nullptr || *spec ==
'\0')
1212 while (*s !=
'\0') {
1215 if (*s ==
'\"' || *s ==
'\'') {
1229
1230
1231
1232
1235 struct stat statbuf;
1236 if (stat(path, &statbuf) == 0)
1237 if (S_ISDIR(statbuf.st_mode))
1242
1243
1244
1245
1248 struct stat link_stat;
1249 struct stat target_stat;
1251 if (lstat(path, &link_stat) == 0)
1252 if (S_ISLNK(link_stat.st_mode))
1253 if (stat(path, &target_stat) == 0)
1254 if (S_ISDIR(target_stat.st_mode))
1259
1260
1264 int ret = regcomp(®ex, pattern, REG_EXTENDED);
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1302char *
rep_substring(
const char *org_s,
const char *tgt_s,
const char *rep_s) {
1305 if (*org_s ==
'\0' || *tgt_s ==
'\0' || *rep_s ==
'\0')
1307 if (strstr(org_s, tgt_s) ==
nullptr)
1308 return strdup(org_s);
1309 if (strstr(rep_s, tgt_s) !=
nullptr)
1311 if (tgt_s == rep_s || tgt_s == org_s || rep_s == org_s)
1312 return strdup(org_s);
1313 if (strcmp(org_s, tgt_s) == 0)
1314 return strdup(rep_s);
1315 char *out_s, *ip, *tmp;
1316 int tgt_l = strlen(tgt_s);
1317 int rep_l = strlen(rep_s);
1321 while ((tmp = strstr(ip, tgt_s)) !=
nullptr) {
1325 out_s = malloc(strlen(org_s) + (rep_l - tgt_l) * n + 1);
1332 char *p = strstr(ip, tgt_s);
1338 ip += head_l + tgt_l;
1344
1345
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1379
1380
1381
1382
1383
1393 str
.l = strlen(s) + 1;
1394 str
.s = (
char *)malloc(str
.l);
1399
1400
1401
1402
1403
1414 str
.s = (
char *)malloc(str
.l);
1419
1420
1421
1422
1433
1434
1435
1436
1437
1439size_t
string_cpy(String *dest,
const String *src) {
1443 dest
->s = (
char *)realloc(dest
->s, src
->l);
1450
1451
1452
1453
1454
1456size_t
string_cat(String *dest,
const String *src) {
1459 size_t new_len = strlen(dest
->s) + strlen(src
->s) + 1;
1460 if (dest
->l < new_len) {
1461 dest
->s = (
char *)realloc(dest
->s, new_len);
1468
1469
1470
1471
1472
1473
1475size_t
string_ncat(String *dest,
const String *src, size_t n) {
1478 size_t dest_len = strlen(dest
->s);
1479 size_t src_len = strlen(src
->s);
1480 size_t cat_len = (n < src_len) ? n : src_len;
1481 size_t new_len = dest_len + cat_len + 1;
1482 if (dest
->l < new_len) {
1483 dest
->s = (
char *)realloc(dest
->s, new_len);
1486 strncat(dest
->s, src
->s, cat_len);
1490
1491
1492
1493
1494
1496size_t
string_ncpy(String *dest,
const String *src, size_t n) {
1499 size_t src_len = strlen(src
->s);
1500 size_t cpy_len = (n < src_len) ? n : src_len;
1501 size_t new_len = cpy_len + 1;
1502 if (dest
->l < new_len) {
1503 dest
->s = (
char *)realloc(dest
->s, new_len);
1506 strncpy(dest
->s, src
->s, cpy_len);
1507 dest
->s[cpy_len] =
'\0';
1511
1512
1515
1516
1517
1518
1519
1533 cmenu_log_fd = open(
"/tmp/cmenu.log", O_WRONLY | O_CREAT | O_TRUNC,
1534 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1537 if (ttyname_r(STDERR_FILENO, ttyname,
sizeof(ttyname)) == 0)
1540 cmenu_user
, ttyname
);
1544
1545
1549 time_t now = time(NULL);
1550 struct tm *t = localtime(&now);
1551 strftime(time_buf,
sizeof(time_buf),
"%Y-%m-%dT%H:%M:%S%z", t);
1560
1561
size_t rtrim(char *)
Trims trailing spaces from string s in place.
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.
error_source_t error_source
int display_error(char *em0, char *em1, char *em2, char *em3)
Display an error message window or print to stderr.
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.
bool strnfill(char *, char, int)
Fills string s with character c n.
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.
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.
int wccp_to_str(wchar_t cp, uint8_t *buffer)
Converts a Unicode code point to a UTF-8 encoded string.
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 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 file_spec_name(char *, char *)
extracts the file name component of a file specification
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.
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.
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.