1 /*
2 Copyright (C) 2011-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk3app.ctr
12 */
13
14 /** @file dk3app.c The dk3app module.
15 */
16
17
18 #include <libdk3c/dk3all.h>
19 #include <libdk3c/dk3unused.h>
20
21
22
23 #if DK3_HAVE_OPENSSL_RAND_H
24 #include <openssl/rand.h>
25 #endif
26
27
28
29
30
31
32
33 /** Names of preference scope attributes.
34 */
35 static dkChar const * const dk3app_scope_attributes[] = {
36 /* 0 */ dkT("user"),
37 /* 1 */ dkT("application"),
38 /* 2 */ dkT("application-group"),
39 /* 3 */ dkT("host"),
40 /* 4 */ dkT("language"),
41 /* 5 */ dkT("region"),
42 NULL
43 };
44
45
46
47 /** Text strings, not localized.
48 */
49 static dkChar const * const dk3app_no_loc[] = {
50 /* 0 */ dkT("bin"), /* Used to build bindir. */
51 /* 1 */ dkT("etc"), /* Used to build etcdir. */
52 /* 2 */ dkT("share"), /* Used to build sharedir. */
53 /* 3 */ dkT("var"), /* Used to build vardir. */
54 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
55 /* 4 */ dkT("\\log"), /* Used to build log directory. */
56 #else
57 /* 4 */ dkT("/log"), /* Used to build log directory. */
58 #endif
59 /* 5 */ dkT("-"), /* Used to build log file name. */
60 /* 6 */ dkT(".log"), /* Used to build log file name. */
61 /* 7 */ dkT("/"), /* Used to build log directory. */
62 /* 8 */ dkT("a"), /* Open mode for log file. */
63 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
64 /* 9 */ dkT("\\tmp"), /* Subdirectory for temporary files. */
65 #else
66 /* 9 */ dkT("/tmp"), /* Subdirectory for temporary files. */
67 #endif
68 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
69 /* 10 */ dkT("\\run"), /* Subdirectory for temporary files. */
70 #else
71 /* 10 */ dkT("/run"), /* Subdirectory for temporary files. */
72 #endif
73 /* 11 */ dkT("LANG"), /* Environment variable for language. */
74 /* 12 */ dkT("Control Panel\\International"), /* Reg key for language. */
75 /* 13 */ dkT("LocaleName"), /* Reg entry name for language. */
76 /* 14 */ dkT("sLanguage"), /* Alternative reg entry name for language. */
77 /* 15 */ dkT("utf8"), /* Encoding UTF-8 (modern variant). */
78 /* 16 */ dkT("UTF-8"), /* Encoding UTF-8 (older variant). */
79 /* 17 */ dkT("dk3app"), /* Subdirectory in system configuration. */
80 /* 18 */ dkT(".dk3app"), /* Subdirectory in home directory. */
81 /* 19 */ dkT("."), /* Current directory. */
82 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
83 /* 20 */ dkT("\\"), /* File name separator. */
84 #else
85 /* 20 */ dkT("/"), /* File name separator. */
86 #endif
87 /* 21 */ dkT("dk3pref.conf"), /* Configuration file name. */
88 /* 22 */ dkT("r"), /* File open mode for reading. */
89 /* 23 */ dkT("dk3app.str"), /* String table name. */
90 /* 24 */ dkT("w"), /* File open mode. */
91 /* 25 */ dkT("="), /* Used when writing preferences. */
92 /* 26 */ dkT("\n"), /* Used when writing preferences. */
93 /* 27 */ dkT("/ui/lang"), /* User interface, language. */
94 /* 28 */ dkT("/log/file/level"), /* Required log level for file. */
95 /* 29 */ dkT("/log/file/keep"), /* Required level to keep file. */
96 /* 30 */ dkT("/log/stderr/level"), /* Required log level for stderr. */
97 /* 31 */ dkT("/temp/dir/keep"), /* Required to keep temp dir. */
98 /* 32 */ dkT("-site"), /* Check for site-specific config files. */
99 /* 33 */ dkT("*"), /* Wildcard for all users ... */
100 /* 34 */ dkT("dk3conf.conf"), /* Configuration file name. */
101 /* 35 */ dkT("%lu"), /* scanf/printf format. */
102 /* 36 */ dkT("rb"), /* File open mode: Read binary. */
103 /* 37 */ dkT("/rand/types"), /* Preference name for allowed PRNG types. */
104 /* 38 */ dkT(".rnd-simple"), /* Preference name for simple seed file. */
105 /* 39 */ dkT(".rnd-lrand48"), /* Preference name for lrand48() seed file. */
106 /* 40 */ dkT(".rnd-random"), /* Preference name for random() seed file. */
107 /* 41 */ dkT(".rnd-openssl"), /* Preference name for OpenSSL seed file. */
108 /* 42 */ dkT("/rand/egd/name"), /* Preference name for EGD socket. */
109 /* 43 */ dkT("EGDSOCKET"), /* Environment variable name for EGD socket. */
110 /* 44 */ dkT("/dev/urandom"), /* Device name for seed data. */
111 /* 45 */ dkT("/dev/random"), /* Device name for seed data. */
112 /* 46 */ dkT("/rand/file/allowed"), /* Preference name. */
113 /* 47 */ dkT("en"), /* Default language name. */
114 #if 0
115 /* 48 */ dkT("/dir/uc2lat-t"), /* Preference name for LaTeX encoding. */
116 #else
117 /* 48 */ dkT("/dir/charmap"), /* Preference name for LaTeX encoding. */
118 #endif
119 /* 49 */
120 #if 0
121 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
122 dkT("\\uc2lat-t"),
123 #else
124 dkT("/uc2lat-t"),
125 #endif
126 #else
127 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
128 dkT("\\dktools\\charmap"), /* Character map subdirectory of share. */
129 #else
130 dkT("/dktools/charmap"), /* Character map subdirectory of share. */
131 #endif
132 #endif
133 /* 50 */ dkT("/silent"), /* Preference name for silent work. */
134 /* 51 */ dkT("/input/encoding/file"), /* Preference name. */
135 /* 52 */ dkT("/input/encoding/stdin"), /* Preference name. */
136 /* 53 */ dkT("wb"), /* File open mode: Read binary. */
137 /* 54 */ dkT(".dir"), /* Suffix for uc2lat *.dir files. */
138 /* 55 */ dkT(".lat"), /* Suffix for uc2lat *.lat files. */
139 /* 56 */ dkT("sbin"), /* sbin dirctory. */
140 };
141
142
143
144 /** Directories where binary executable can reside.
145 */
146 static dkChar const * const dk3app_bindir_candidates[] = {
147 /* 0 */
148 dkT("bin"),
149
150 /* 1 */
151 dkT("sbin"),
152
153 /* 2 */
154 dkT("lib"),
155
156 /* 3 */
157 dkT("libexec"),
158
159 NULL
160
161 };
162
163
164
165 /** Keywords for users configuration files.
166 These keywords can be used in the $HOME/.dk3app/dk3conf.conf file.
167 */
168 dkChar const * const dk3app_conf_file[] = {
169 /* 0 */ dkT("use-system-config-files"),
170 /* 1 */ dkT("ignore-system-config-files"),
171 NULL
172 };
173
174
175 /** Log level names.
176 */
177 static dkChar const * const dk3app_log_levels[] = {
178 dkT("n$one"),
179 dkT("pa$nic"),
180 dkT("f$atal"),
181 dkT("e$rror"),
182 dkT("w$arning"),
183 dkT("in$fo"),
184 dkT("pr$ogress"),
185 dkT("d$ebug"),
186 dkT("ig$nore"),
187 NULL
188 };
189
190 #if 0
191 static dkChar const * const dk3app_prng_type_names[] = {
192 /* 0 */ dkT("openssl"), /* OpenSSL PRNG. */
193 /* 1 */ dkT("random"), /* initstate()/setstate()/random() */
194 /* 2 */ dkT("rand48"), /* lrand48(). */
195 /* 3 */ dkT("simple"), /* srand()/rand(). */
196 NULL
197 };
198 #endif
199
200
201
202 /** Text strings, localization needed.
203 The texts strings are used as parts of diagnostic messages.
204 */
205 static dkChar const * const dk3app_kw[] = {
206 /* 0 */
207 dkT("\n"),
208
209 /* 1 */
210 dkT("PANIC"),
211
212 /* 2 */
213 dkT("FATAL"),
214
215 /* 3 */
216 dkT("ERROR"),
217
218 /* 4 */
219 dkT("Warning"),
220
221 /* 5 */
222 dkT("Information"),
223
224 /* 6 */
225 dkT("Progress"),
226
227 /* 7 */
228 dkT("Debug"),
229
230 /* 8 */
231 dkT(" "),
232
233 /* 9 */
234 dkT("Not enough memory (RAM/swap space)!"),
235
236 /* 10 */
237 dkT("# "),
238
239 /* 11 */
240 dkT(":"),
241
242 /* 12 */
243 dkT("Memory allocation ("),
244
245 /* 13 */
246 dkT(" bytes) failed!"),
247
248 /* 14 */
249 dkT("Memory allocation failed!"),
250
251 /* 15 */
252 dkT("Numeric overflow in size calculation!"),
253
254 /* 16 */
255 dkT("Numeric overflow in size calculation ("),
256
257 /* 17 */
258 dkT(" x "),
259
260 /* 18 */
261 dkT(" bytes)!"),
262
263 /* 19 */
264 dkT("Application \""),
265
266 /* 20 */
267 dkT("\" started."),
268
269 /* 21 */
270 dkT("Application \""),
271
272 /* 22 */
273 dkT("\" finished."),
274
275 /* 23 */
276 dkT("Application name: "),
277
278 /* 24 */
279 dkT("Application group: "),
280
281 /* 25 */
282 dkT("Executable file: "),
283
284 /* 26 */
285 dkT("Directory \"bin\": "),
286
287 /* 27 */
288 dkT("Directory \"etc\": "),
289
290 /* 28 */
291 dkT("Directory \"share\": "),
292
293 /* 29 */
294 dkT("Directory \"var\": "),
295
296 /* 30 */
297 dkT("Directory \"home\": "),
298
299 /* 31 */
300 dkT("Directory \"temp\": "),
301
302 /* 32 */
303 dkT("User: "),
304
305 /* 33 */
306 dkT("Log file: "),
307
308 /* 34 */
309 dkT("Language: "),
310
311 /* 35 */
312 dkT("Region: "),
313
314 /* 36 */
315 dkT("<unknown>"),
316
317 /* 37 */
318 dkT("The name of the temporary directory is too long!"),
319
320 /* 38 */
321 dkT("Destination buffer too small!"),
322
323 /* 39 */
324 dkT("The LANG environment variable is too long!"),
325
326 /* 40 */
327 dkT("Failed to find name of executable file!"),
328
329 /* 41 */
330 dkT("Too few directories in hierarchy!\nExecutable files should not reside in the root directory!"),
331
332 /* 42 */
333 dkT("File name of executable file too long!"),
334
335 /* 43 */
336 dkT("Failed to obtain the users login name!"),
337
338 /* 44 */
339 dkT("Failed to find the users home directory!"),
340
341 /* 45 */
342 dkT("File name for log file gets too long!"),
343
344 /* 46 */
345 dkT("Failed to create directory for log file!"),
346
347 /* 47 */
348 dkT("Failed to convert process ID to text!"),
349
350 /* 48 */
351 dkT("Failed to find application name!"),
352
353 /* 49 */
354 dkT("The name of the temporary directory is too long!"),
355
356 /* 50 */
357 dkT("Failed to find local state (var) directory!"),
358
359 /* 51 */
360 dkT("Preference name too long!"),
361
362 /* 52 */
363 dkT("Malformed preference entry on command line!"),
364
365 /* 53 */
366 dkT("Failed to find current working directory!"),
367
368 /* 54 */
369 dkT("Too many requests for temporary file names!"),
370
371 /* 55 */
372 dkT("Internal error (bug): Missing a file or directory name!"),
373
374 /* 56 */
375 dkT("Failed to save preference entry \""),
376
377 /* 57 */
378 dkT("\"=\""),
379
380 /* 58 */
381 dkT("\"!"),
382
383 /* 59 */
384 dkT("Directory name \""),
385
386 /* 60 */
387 dkT("\" too long!"),
388
389 /* 61 */
390 dkT("Failed to obtain information about \""),
391
392 /* 62 */
393 dkT("\"!\nThe stat() function failed!"),
394
395 /* 63 */
396 dkT("Failed to read directory \""),
397
398 /* 64 */
399 dkT("\"!"),
400
401 /* 65 */
402 dkT("File name \""),
403
404 /* 66 */
405 dkT("\" too long!"),
406
407 /* 67 */
408 dkT("Illegal characters in source string, conversion failed!"),
409
410 /* 68 */
411 dkT("Failed to remove directory!"),
412
413 /* 69 */
414 dkT("Failed to remove directory \""),
415
416 /* 70 */
417 dkT("\"!"),
418
419 /* 71 */
420 dkT("The HOMEDRIVE environment variable is not set!"),
421
422 /* 72 */
423 dkT("The HOMEPATH environment variable is not set!"),
424
425 /* 73 */
426 dkT("Failed to obtain information about a file!"),
427
428 /* 74 */
429 dkT("\""),
430
431 /* 75 */
432 dkT("\" is a directory!"),
433
434 /* 76 */
435 dkT("Can not open file, name refers to a directory!"),
436
437 /* 77 */
438 dkT("Failed to open file \""),
439
440 /* 78 */
441 dkT("\" for write access!"),
442
443 /* 79 */
444 dkT("Failed to open file for write access!"),
445
446 /* 80 */
447 dkT("Failed to obtain current time!"),
448
449 /* 81 */
450 dkT("File \""),
451
452 /* 82 */
453 dkT("\" exists but is not a directory!"),
454
455 /* 83 */
456 dkT("File exists but is not a directory!"),
457
458 /* 84 */
459 dkT("Failed to create directory \""),
460
461 /* 85 */
462 dkT("\"!"),
463
464 /* 86 */
465 dkT("Failed to create directory!"),
466
467 /* 87 */
468 dkT("Directory name too long!"),
469
470 /* 88 */
471 dkT("Failed to remove file \""),
472
473 /* 89 */
474 dkT("\"!"),
475
476 /* 90 */
477 dkT("Failed to remove file!"),
478
479 /* 91 */
480 dkT("No user name entry in user record!"),
481
482 /* 92 */
483 dkT("No user record for \""),
484
485 /* 93 */
486 dkT("\"!"),
487
488 /* 94 */
489 dkT("No matching user record found!"),
490
491 /* 95 */
492 dkT("No home directory entry in user record!"),
493
494 /* 96 */
495 dkT("Failed to obtain information about \""),
496
497 /* 97 */
498 dkT("\"!\nThe lstat() function failed!"),
499
500 /* 98 */
501 dkT("No information about a file, lstat() failed!"),
502
503 /* 99 */
504 dkT("No information about a file, lstat() failed!"),
505
506 /* 100 */
507 dkT("Owner of symlink \""),
508
509 /* 101 */
510 dkT("\" is not owner of file!"),
511
512 /* 102 */
513 dkT("Symlink owner is not file owner!"),
514
515 /* 103 */
516 dkT("Command \""),
517
518 /* 104 */
519 dkT("\" is too long!"),
520
521 /* 105 */
522 dkT("Command is too long!"),
523
524 /* 106 */
525 dkT("The PATH environment variable is not defined!"),
526
527 /* 107 */
528 dkT("No mkdir() function available!"),
529
530 /* 108 */
531 dkT("String too long!"),
532
533 /* 109 */
534 dkT("Command name too long!"),
535
536 /* 110 */
537 dkT("Too many \"..\" entries in file name \""),
538
539 /* 111 */
540 dkT("\"!"),
541
542 /* 112 */
543 dkT("Illegal character(s) in source string!"),
544
545 /* 113 */
546 dkT("Illegal character(s) in source buffer!"),
547
548 /* 114 */
549 dkT("Illegal destination encoding!"),
550
551 /* 115 */
552 dkT("Conversion to UTF-8 failed!"),
553
554 /* 116 */
555 dkT("Conversion to UTF-16 failed!"),
556
557 /* 117 */
558 dkT("Result character(s) not available for destination encoding!"),
559
560 /* 118 */
561 dkT("UTF-8 decoding failed!"),
562
563 /* 119 */
564 dkT("UTF-16 decoding failed!"),
565
566 /* 120 */
567 dkT("Failed to write data!"),
568
569 /* 121 */
570 dkT("Failed to flush output!"),
571
572 /* 122 */
573 dkT("Failed to close data stream object!"),
574
575 /* 123 */
576 dkT("Stream not opened for write operations!"),
577
578 /* 124 */
579 dkT("Failed to read data!"),
580
581 /* 125 */
582 dkT("Mismatch between encoding and character size!"),
583
584 /* 126 */
585 dkT("Too many \"..\" entries in file name!"),
586
587 /* 127 */
588 dkT("Unknown message digest type: \""),
589
590 /* 128 */
591 dkT("\"!"),
592
593 /* 129 */
594 dkT("Unknown encoding: \""),
595
596 /* 130 */
597 dkT("\"!"),
598
599 /* 131 */
600 dkT("Failed to find current host name!"),
601
602 /* 132 */
603 dkT("Host: "),
604
605 /* 133 */
606 dkT("Option \""),
607
608 /* 134 */
609 dkT("\" requires an argument!"),
610
611 /* 135 */
612 dkT("Option \""),
613
614 /* 136 */
615 dkT("\" too long for processing"),
616
617 /* 137 */
618 dkT("Ignoring irrelevant argument in \""),
619
620 /* 138 */
621 dkT("\"!"),
622
623 /* 139 */
624 dkT("Unknown option \""),
625
626 /* 140 */
627 dkT("\"!"),
628
629 /* 141 */
630 dkT("Not a numeric value: \""),
631
632 /* 142 */
633 dkT("\"!"),
634
635 /* 143 */
636 dkT("Failed to open file \""),
637
638 /* 144 */
639 dkT("\"!"),
640
641 /* 145 */
642 dkT("Failed to open file!"),
643
644 /* 146 */
645 dkT("Not a boolean value: \""),
646
647 /* 147 */
648 dkT("\"!"),
649
650 /* 148 */
651 dkT("Resource file \""),
652
653 /* 149 */
654 dkT("\" found."),
655
656 /* 150 */
657 dkT("Resource file \""),
658
659 /* 151 */
660 dkT("\" not found."),
661
662 /* 152 */
663 dkT("Configuration file \""),
664
665 /* 153 */
666 dkT("\" found."),
667
668 /* 154 */
669 dkT("Configuration file \""),
670
671 /* 155 */
672 dkT("\" not found."),
673
674 /* 156 */
675 dkT("No support for message digest \""),
676
677 /* 157 */
678 dkT("\"!"),
679
680 /* 158 */
681 dkT("Illegal message digest or encoding number!"),
682
683 /* 159 */
684 dkT("Checksumming is available for regular files only!"),
685
686 /* 160 */
687 dkT("Option name missing in long option: \""),
688
689 /* 161 */
690 dkT("\"!"),
691
692 /* 162 */
693 dkT("Failed to convert a numeric value to text!"),
694
695 /* 163 */
696 dkT("\"!"),
697
698 /* 164 */
699 dkT("Too many command line arguments! Ignoring \""),
700
701 /* 165 */
702 dkT("\"...!"),
703
704 /* 166 */
705 dkT("Internal error (bug) "),
706
707 /* 167 */
708 dkT("."),
709
710 /* 168 */
711 dkT("Too many file names match pattern \""),
712
713 /* 169 */
714 dkT("\", just one allowed!"),
715
716 /* 170 */
717 dkT("Write operation failed, "),
718
719 /* 171 */
720 dkT(" of "),
721
722 /* 172 */
723 dkT(" bytes written!"),
724
725 /* 173 */
726 dkT("Write operation failed!"),
727
728 /* 174 */
729 dkT("Write operation failed, "),
730
731 /* 175 */
732 dkT(" of "),
733
734 /* 176 */
735 dkT(" elements written!"),
736
737 /* 177 */
738 dkT("Failed to create random data!"),
739
740 /* 178 */
741 dkT("No usable PRNG found!"),
742
743 /* 179 */
744 dkT("Failed to seed simple PRNG!"),
745
746 /* 180 */
747 dkT("Failed to seed lrand48() PRNG!"),
748
749 /* 181 */
750 dkT("Failed to seed random() PRNG!"),
751
752 /* 182 */
753 dkT("Failed to seed OpenSSL PRNG!"),
754
755 /* 183 */
756 dkT("Seed file \""),
757
758 /* 184 */
759 dkT("\" not used (permissions)!"),
760
761 /* 185 */
762 dkT("Seed file \""),
763
764 /* 186 */
765 dkT("\" not used (symlink owner)!"),
766
767 /* 187 */
768 dkT("Unknown PRNG type: \""),
769
770 /* 188 */
771 dkT("\"!"),
772
773 /* 189 */
774 dkT("The srand()/rand() PRNG is not available!"),
775
776 /* 190 */
777 dkT("The srand48()/lrand48() PRNG is not available!"),
778
779 /* 191 */
780 dkT("The random() PRNG is not available!"),
781
782 /* 192 */
783 dkT("The OpenSSL PRNG is not available!"),
784
785 /* 193 */
786 dkT("Failed to save random seed data!"),
787
788 /* 194 */
789 dkT("HOME directory name too long!"),
790
791 /* 195 */
792 dkT("System configuration files skipped by user."),
793
794 /* 196 */
795 dkT("Attempt to obtain seed data from \""),
796
797 /* 197 */
798 dkT("\"."),
799
800 /* 198 */
801 dkT("Seed data: "),
802
803 /* 199 */
804 dkT(" bytes found."),
805
806 /* 200 */
807 dkT("Index out of range!"),
808
809 /* 201 */
810 dkT("Matrix expansion requires a square matrix!"),
811
812 /* 202 */
813 dkT("Not a directory: \""),
814
815 /* 203 */
816 dkT("\"!"),
817
818 /* 204 */
819 dkT("Encoding not supported by C runtime library!"),
820
821 /* 205 */
822 dkT("No directory containing LaTeX encoding tables found!"),
823
824 /* 206 */
825 dkT("Redefinition,\noverwriting \""),
826
827 /* 207 */
828 dkT("\" by \""),
829
830 /* 208 */
831 dkT("\"."),
832
833 /* 209 */
834 dkT("Syntax error,\nindex "),
835
836 /* 210 */
837 dkT(" is out of range 0...255."),
838
839 /* 211 */
840 dkT("Syntax error\nnear \""),
841
842 /* 212 */
843 dkT("\"!"),
844
845 /* 213 */
846 dkT("Syntax error,\nmissing LaTeX encoding!"),
847
848 /* 214 */
849 dkT("Syntax error,\nmissing index!"),
850
851 /* 215 */
852 dkT("No file name matches pattern \""),
853
854 /* 216 */
855 dkT("\"!"),
856
857 /* 217 */
858 dkT("Missing name of long option!"),
859
860 /* 218 */
861 dkT("Incomplete input sequence."),
862
863 /* 219 */
864 dkT("String contains non-ISO-LATIN-1 characters!"),
865
866 /* 220 */
867 dkT("Misconfigured start/end for range!"),
868
869 /* 221 */
870 dkT("New range conflicts with existing one!"),
871
872 /* 222 */
873 dkT("Not a hex number!"),
874
875 /* 223 */
876 dkT("Syntax error!"),
877
878 /* 224 */
879 dkT("Character redefinition!"),
880
881 /* 225 */
882 dkT("Range not declared in character directory!"),
883
884 /* 226 */
885 dkT("Package name conflicts with previous definition!"),
886
887 /* 227 */
888 dkT("Attempt to obtain seed data from CryptoAPI."),
889
890 /* 228 */
891 dkT("Attempt to obtain seed data from screen."),
892
893 /* 229 */
894 dkT("OpenSSL PRNG seeded successfully."),
895
896 /* 230 */
897 dkT("Attempt to read preferences file \""),
898
899 /* 231 */
900 dkT("\"."),
901
902 /* 232 */
903 dkT("LaTeX table directory: \""),
904
905 /* 233 */
906 dkT("\"."),
907
908 /* 234 */
909 dkT("Attempting LaTeX table directory: \""),
910
911 /* 235 */
912 dkT("\"."),
913
914 /* 236 */
915 dkT("Reading LaTeX table dir: \""),
916
917 /* 237 */
918 dkT("\"."),
919
920 /* 238 */
921 dkT("Registering LaTeX conversion range "),
922
923 /* 239 */
924 dkT("."),
925
926 /* 240 */
927 dkT("Loading LaTeX conversion data file \""),
928
929 /* 241 */
930 dkT("\"."),
931
932 /* 242 */
933 dkT("Failed to change into directory: \""),
934
935 /* 243 */
936 dkT("\"!"),
937
938 /* 244 */
939 dkT("Failed to enumerate printers!"),
940
941 /* 245 */
942 dkT("Record too large!"),
943
944 /* 246 */
945 dkT("File damaged or not a database file!"),
946
947 /* 247 */
948 dkT("No support for database type \""),
949
950 /* 248 */
951 dkT("\" available!"),
952
953 /* 249 */
954 dkT("Key not found in database!"),
955
956 /* 250 */
957 dkT("DB entry probably damaged - not a multibyte char string!"),
958
959 /* 251 */
960 dkT("Database opened for read access only!"),
961
962 /* 252 */
963 dkT("Error(s) occured while processing command line options!"),
964
965 /* 253 */
966 dkT("Failed to retrieve current locale!"),
967
968 /* 254 */
969 dkT("Current locale too long!"),
970
971 /* 255 */
972 dkT("Not a regular file: \""),
973
974 /* 256 */
975 dkT("\"!"),
976
977 /* 257 */
978 dkT("Image file type unknown or not supported!"),
979
980 /* 258 */
981 dkT("Bits per component restricted to 16!"),
982
983 /* 259 */
984 dkT("Incorrect page setup, no usable space between borders!"),
985
986 /* 260 */
987 dkT("Mathematical error in graphics calculations!"),
988
989 /* 261 */
990 dkT("Failed to set bitmap image frame!"),
991
992 /* 262 */
993 dkT("Flate compression not supported!"),
994
995 /* 263 */
996 dkT("Illegal compression cell type used!"),
997
998 /* 264 */
999 dkT("Error during previous compression operations!"),
1000
1001 /* 265 */
1002 dkT("Failed to retrieve console settings!"),
1003
1004 /* 266 */
1005 dkT("Failed to restore console settings!"),
1006
1007 /* 267 */
1008 dkT("Failed to modify console settings!"),
1009
1010 /* 268 */
1011 dkT("Failed to convert timestamp to local time!"),
1012
1013 /* 269 */
1014 dkT("No file name available for database!"),
1015
1016 /* 270 */
1017 dkT("Failed to change ownership for file:\n\""),
1018
1019 /* 271 */
1020 dkT("\"!"),
1021
1022 /* 272 */
1023 dkT("Failed to change permissions for file:\n\""),
1024
1025 /* 273 */
1026 dkT("\"!"),
1027
1028 /* 274 */
1029 dkT("Insufficient permissions to open network connection!"),
1030
1031 /* 275 */
1032 dkT("Unknown or illegal address family!"),
1033
1034 /* 276 */
1035 dkT("Process table overflow!"),
1036
1037 /* 277 */
1038 dkT("Too many open files!"),
1039
1040 /* 278 */
1041 dkT("Protocol not supported!"),
1042
1043 /* 279 */
1044 dkT("Failed to open network socket!"),
1045
1046 /* 280 */
1047 dkT("Failed to close socket!"),
1048
1049 /* 281 */
1050 dkT("Interrupted by signal or explicitly cancelled!"),
1051
1052 /* 282 */
1053 dkT("Failed to connect!"),
1054
1055 /* 283 */
1056 dkT("Failed to listen for incoming requests!"),
1057
1058 /* 284 */
1059 dkT("Failed to find IP address for:\n\""),
1060
1061 /* 285 */
1062 dkT("\"!"),
1063
1064 /* 286 */
1065 dkT("Host not found!"),
1066
1067 /* 287 */
1068 dkT("Host exists, but no IP address assigned!"),
1069
1070 /* 288 */
1071 dkT("Problem on DNS server!"),
1072
1073 /* 289 */
1074 dkT("Temporary problem on DNS server, try again later!"),
1075
1076 /* 290 */
1077 dkT("No gethostbyname() function available!"),
1078
1079 /* 291 */
1080 dkT("Can not connect to remote port 0!"),
1081
1082 /* 292 */
1083 dkT("Access denied by firewall or due to insufficient permissions!"),
1084
1085 /* 293 */
1086 dkT("Local address already in use!"),
1087
1088 /* 294 */
1089 dkT("Resources shortage, network operation failed!"),
1090
1091 /* 295 */
1092 dkT("Previous connection attempt not yet completed!"),
1093
1094 /* 296 */
1095 dkT("Connection refused, port not open on peer!"),
1096
1097 /* 297 */
1098 dkT("Socket already connected!"),
1099
1100 /* 298 */
1101 dkT("Network unreachable!"),
1102
1103 /* 299 */
1104 dkT("Timeout occured."),
1105
1106 /* 300 */
1107 dkT("No select() function available, timeout settings ignored!"),
1108
1109 /* 301 */
1110 dkT("Failed to retrieve socket state!"),
1111
1112 /* 302 */
1113 dkT("Failed to bind local address!"),
1114
1115 /* 303 */
1116 dkT(""),
1117
1118 /* 304 */
1119 dkT("Socket already bound to local address!"),
1120
1121 /* 305 */
1122 dkT("Failed to write data to socket!"),
1123
1124 /* 306 */
1125 dkT("Operation would block!"),
1126
1127 /* 307 */
1128 dkT("Connection reset by peer!"),
1129
1130 /* 308 */
1131 dkT("Peer address is required to send data via connectionless socket!"),
1132
1133 /* 309 */
1134 dkT("Peer address specification is not allowed for connected sockets!"),
1135
1136 /* 310 */
1137 dkT("Message too large to be sent atomically!"),
1138
1139 /* 311 */
1140 dkT("Sending queue full for socket!"),
1141
1142 /* 312 */
1143 dkT("Writing to a pipe without a reader!"),
1144
1145 /* 313 */
1146 dkT("Less bytes were written than required!"),
1147
1148 /* 314 */
1149 dkT("Failed to read data from socket!"),
1150
1151 /* 315 */
1152 dkT("Failed to shut down socket!"),
1153
1154 /* 316 */
1155 dkT("Socket not connected!"),
1156
1157 /* 317 */
1158 dkT("Failed to accept incoming connection request!"),
1159
1160 /* 318 */
1161 dkT("Connection aborted!"),
1162
1163 /* 319 */
1164 dkT("Network protocol error!"),
1165
1166 /* 320 */
1167 dkT("Network subsystem not available!"),
1168
1169 /* 321 */
1170 dkT("Windows sockets not initialized!"),
1171
1172 /* 322 */
1173 dkT("A blocking Winsock 1.1 operation is in progress!"),
1174
1175 /* 323 */
1176 dkT("Socket type doesn't correspond to address family!"),
1177
1178 /* 324 */
1179 dkT("Socket not configured for broadcasts!"),
1180
1181 /* 325 */
1182 dkT("Requested address is not available!"),
1183
1184 /* 326 */
1185 dkT("Host unreachable!"),
1186
1187 /* 327 */
1188 dkT("Windows sockets version not available!"),
1189
1190 /* 328 */
1191 dkT("Too many processes use Windows sockets at this time!"),
1192
1193 /* 329 */
1194 dkT("I/O error occured!"),
1195
1196 /* 330 */
1197 dkT("Too many symbolic links in path!"),
1198
1199 /* 331 */
1200 dkT("Illegal pathname (missing a parent directory)!"),
1201
1202 /* 332 */
1203 dkT("File system is mounted read-only!"),
1204
1205 /* 333 */
1206 dkT("Stale NFS file handle!"),
1207
1208 /* 334 */
1209 dkT("Server for remote file not available!"),
1210
1211 /* 335 */
1212 dkT("No space left on device!"),
1213
1214 /* 336 */
1215 dkT("Failed to wait for sockets to become ready!"),
1216
1217 /* 337 */
1218 dkT("Failed to convert text address to address!"),
1219
1220 /* 338 */
1221 dkT("Failed to find address for host!"),
1222
1223 /* 339 */
1224 dkT("Failed to set socket options!"),
1225
1226 /* 340 */
1227 dkT("Error while closing file!"),
1228
1229 /* 341 */
1230 dkT("Error while closing file\n\""),
1231
1232 /* 342 */
1233 dkT("\"!"),
1234
1235 /* 343 */
1236 dkT("Failed to write data to file:\n\""),
1237
1238 /* 344 */
1239 dkT("\"!"),
1240
1241 /* 345 */
1242 dkT("Failed to read data from file!"),
1243
1244 /* 346 */
1245 dkT("Failed to read data from file:\n\""),
1246
1247 /* 347 */
1248 dkT("\"!"),
1249
1250 /* 348 */
1251 dkT("Not an IP address: \""),
1252
1253 /* 349 */
1254 dkT("\"!"),
1255
1256 /* 350 */
1257 dkT("Not an IP address!"),
1258
1259 /* 351 */
1260 dkT("Failed to connect to: \""),
1261
1262 /* 352 */
1263 dkT("\"!"),
1264
1265 /* 353 */
1266 dkT("No function available to check blocking/non-blocking state!"),
1267
1268 /* 354 */
1269 dkT("Netmask is not a dotted IP address!"),
1270
1271 /* 355 */
1272 dkT("Netmask is not a bit number!"),
1273
1274 /* 356 */
1275 dkT("Netmask is not an IPv6 address!"),
1276
1277 /* 357 */
1278 dkT("No name resolution available, please specify IP address!"),
1279
1280 /* 358 */
1281 dkT("No select() function available!"),
1282
1283 /* 359 */
1284 dkT("No valid socket found in set!"),
1285
1286 /* 360 */
1287 dkT("Socket "),
1288
1289 /* 361 */
1290 dkT(" connected to client: "),
1291
1292 /* 362 */
1293 dkT("Connection from \""),
1294
1295 /* 363 */
1296 dkT("\" rejected!"),
1297
1298 /* 364 */
1299 dkT("Failed to create any listener socket for socket set!"),
1300
1301 /* 365 */
1302 dkT("Preference value of /threads/max higher than number of cores!"),
1303
1304 /* 366 */
1305 dkT("Failed to find unique file identifier for file\n\""),
1306
1307 /* 367 */
1308 dkT("\"!"),
1309
1310 /* 368 */
1311 dkT("Failed to find unique file identifier for a file!"),
1312
1313 /* 369 */
1314 dkT("Preference \""),
1315
1316 /* 370 */
1317 dkT("\" does not point to a directory!"),
1318
1319 /* 371 */
1320 dkT(""),
1321
1322 /* 372 */
1323 dkT("Socket "),
1324
1325 /* 373 */
1326 dkT(" listening: "),
1327
1328 /* 374 */
1329 dkT(""),
1330
1331 /* 375 */
1332 dkT("Socket "),
1333
1334 /* 376 */
1335 dkT(" connected:"),
1336
1337 /* 377 */
1338 dkT(""),
1339
1340 /* 378 */
1341 dkT("Multiple different font encodings required!"),
1342
1343 /* 379 */
1344 dkT("Font encoding both required and denied: `"),
1345
1346 /* 380 */
1347 dkT("'!"),
1348
1349 /* 381 */
1350 dkT("Font encoding can be used: `"),
1351
1352 /* 382 */
1353 dkT("'!"),
1354
1355 /* 383 */
1356 dkT("The following font encoding can not be used: `"),
1357
1358 /* 384 */
1359 dkT("'."),
1360
1361 /* 385 */
1362 dkT("All font encodings denied!"),
1363
1364 /* 386 */
1365 dkT("Too many entries on position "),
1366
1367 /* 387 */
1368 dkT(" in text line:\n\""),
1369
1370 /* 388 */
1371 dkT("\""),
1372
1373 /* 389 */
1374 dkT("Unexpected end of text after backslash in text:\n\""),
1375
1376 /* 390 */
1377 dkT("\""),
1378
1379 /* 391 */
1380 dkT("UTF-8 decoding failed for string:\n\""),
1381
1382 /* 392 */
1383 dkT("UTF-16 decoding failed for string:\n\""),
1384
1385 /* 393 */
1386 dkT("Non-ANSI characters in string:\n\""),
1387
1388 /* 394 */
1389 dkT("Non-URL characters in string:\n\""),
1390
1391 /* 395 */
1392 dkT("Character 0x"),
1393
1394 /* 396 */
1395 dkT("already defined!"),
1396
1397 /* 397 */
1398 dkT("Character redefinition!"),
1399
1400 /* 398 */
1401 dkT("First word is not a hexadecimal number!"),
1402
1403 /* 399 */
1404 dkT("_UNUSED_"),
1405
1406 /* 400 */
1407 dkT("No configuration data found for character!"),
1408
1409 /* 401 */
1410 dkT("No support for zlib compression!"),
1411
1412 /* 402 */
1413 dkT("No support for bzip2 compression!"),
1414
1415 /* 403 */
1416 dkT("No data files found to process!"),
1417
1418 /* 404 */
1419 dkT("Syntax error, unknown encoding!"),
1420
1421 /* 405 */
1422 dkT("Syntax error, no package names found!"),
1423
1424 /* 406 */
1425 dkT("Syntax error, missing value for attribute!"),
1426
1427 /* 407 */
1428 dkT("Missing \"share\" directory!"),
1429
1430 /* 408 */
1431 dkT("No data found for character!"),
1432
1433 /* 409 */
1434 dkT("No data found for character 0x"),
1435
1436 /* 410 */
1437 dkT("!"),
1438
1439 /* 411 */
1440 dkT("Conflicting font encoding requirements!"),
1441
1442 /* 412 */
1443 dkT("Failed to set buffer for file\n\""),
1444
1445 /* 413 */
1446 dkT("\"!"),
1447
1448 NULL
1449
1450 };
1451
1452
1453
1454 /** Preferences entry.
1455 */
1456 typedef struct _dk3app_pref_t {
1457 dkChar const *k; /**< Key (name). */
1458 dkChar const *v; /**< Value. */
1459 } dk3app_pref_t;
1460
1461
1462
1463 /** Message catalog.
1464 */
1465 typedef struct _dk3app_mc_t_ {
1466 dkChar const *n; /**< Name (always dynamically allocated). */
1467 dkChar const **msg; /**< Message texts. */
1468 int f; /**< Flag: Messages dynamically allocated. */
1469 size_t nmsg; /**< Number of messages. */
1470 } dk3app_mc_t;
1471
1472
1473
1474 /** Delete preferences entry, release memory.
1475 @param p Preference entry to delete.
1476 */
1477 static
1478 void
dk3app_pref_delete(dk3app_pref_t * p)1479 dk3app_pref_delete(dk3app_pref_t *p)
1480 {
1481 if(p) {
1482 dk3_release(p->k);
1483 dk3_release(p->v);
1484 dk3_delete(p);
1485 }
1486 }
1487
1488
1489
1490 /** Create new preferences entry, allocate memory.
1491 @param k Key (preference name).
1492 @param v Value.
1493 @return Pointer to new entry on success, NULL on error.
1494 */
1495 static
1496 dk3app_pref_t *
dk3app_pref_new(dkChar const * k,dkChar const * v)1497 dk3app_pref_new(dkChar const *k, dkChar const *v)
1498 {
1499 dk3app_pref_t *back = NULL;
1500
1501 if((k) && (v)) {
1502 back = dk3_new(dk3app_pref_t,1);
1503 if(back) {
1504 back->k = dk3str_dup_app(k, NULL);
1505 back->v = dk3str_dup_app(v, NULL);
1506 if(!((back->k) && (back->v))) {
1507 dk3app_pref_delete(back); back = NULL;
1508 }
1509 }
1510 }
1511 return back;
1512 }
1513
1514
1515
1516 /** Compare two preference entries by name.
1517 @param l Left entry.
1518 @param r Right entry.
1519 @param crit Comparison criteria (ignored).
1520 @return Comparison result l <=> r.
1521 */
1522 static
1523 int
dk3app_compare_pref(void const * l,void const * r,int DK3_ARG_UNUSED (crit))1524 dk3app_compare_pref(void const *l, void const *r, int DK3_ARG_UNUSED(crit) )
1525 {
1526 int back = 0;
1527 dk3app_pref_t const *pl = NULL; /* Left object. */
1528 dk3app_pref_t const *pr = NULL; /* Right object. */
1529
1530 DK3_UNUSED_ARG(crit)
1531 if(l) {
1532 if(r) {
1533 pl = (dk3app_pref_t const *)l; pr = (dk3app_pref_t const *)r;
1534 if(pl->k) {
1535 if(pr->k) {
1536 back = dk3str_cmp(pl->k, pr->k);
1537 } else { back = 1; }
1538 } else {
1539 if(pr->k) { back = -1; }
1540 }
1541 } else { back = 1; }
1542 } else {
1543 if(r) { back = -1; }
1544 }
1545 return back;
1546 }
1547
1548
1549
1550 /** Delete string table.
1551 @param ta Table to delete.
1552 @param n Number of entries in the table.
1553 */
1554 static
1555 void
dk3app_mc_table_delete(dkChar const ** ta,size_t n)1556 dk3app_mc_table_delete(dkChar const **ta, size_t n)
1557 {
1558 dkChar const **ptr = NULL; /* Start of string table. */
1559 size_t i = 0; /* Index of current element to process. */
1560
1561 ptr = ta;
1562 for(i = 0; i < n; i++) {
1563 if(*ptr) {
1564 dk3_delete(*ptr);
1565 }
1566 *(ptr++) = NULL;
1567 }
1568 dk3_delete(ta);
1569 }
1570
1571
1572
1573 /** Delete message catalog entry.
1574 @param mc Message catalog entry to delete.
1575 */
1576 static
1577 void
dk3app_mc_delete(dk3app_mc_t * mc)1578 dk3app_mc_delete(dk3app_mc_t *mc)
1579 {
1580
1581 if(mc) {
1582 dk3_release(mc->n);
1583 if(mc->f) {
1584 if(mc->msg) {
1585 dk3app_mc_table_delete(mc->msg, mc->nmsg);
1586 }
1587 } mc->f = 0; mc->msg = NULL;
1588 dk3_delete(mc);
1589 }
1590 }
1591
1592
1593
1594 /** Create message catalog entry.
1595 @param n Short file name of string table file.
1596 @param msg String table.
1597 @param nmsg Number of entries in \a msg.
1598 @param f Flag: The memory for \a msg was dynamically allocated.
1599 @param app Application structure for diagnostics, may be NULL.
1600 @return Pointer to message catalog entry on success, NULL on error.
1601 */
1602 static
1603 dk3app_mc_t *
dk3app_mc_new(dkChar const * n,dkChar const ** msg,size_t nmsg,int f,dk3_app_t * app)1604 dk3app_mc_new(
1605 dkChar const *n, dkChar const **msg, size_t nmsg, int f, dk3_app_t *app
1606 )
1607 {
1608 dk3app_mc_t *back = NULL;
1609
1610 back = dk3_new_app(dk3app_mc_t,1,app);
1611 if(back) {
1612 back->n = NULL; back->msg = NULL; back->f = f; back->nmsg = nmsg;
1613 back->n = dk3str_dup_app(n, app);
1614 if(back->n) {
1615 back->msg = msg;
1616 } else {
1617 dk3app_mc_delete(back); back = NULL;
1618 }
1619 }
1620 return back;
1621 }
1622
1623
1624
1625 /** Compare two message catalog entries.
1626 @param l Left entry.
1627 @param r Right entry.
1628 @param cr Comparison criteria (ignored).
1629 @return Comparison result.
1630 */
1631 static
1632 int
dk3app_mc_compare(void const * l,void const * r,int DK3_ARG_UNUSED (cr))1633 dk3app_mc_compare(void const *l, void const *r, int DK3_ARG_UNUSED(cr) )
1634 {
1635 int back = 0;
1636 dk3app_mc_t const *pl = NULL; /* Left message catalog. */
1637 dk3app_mc_t const *pr = NULL; /* Right message catalog. */
1638
1639 DK3_UNUSED_ARG(cr)
1640 if(l) {
1641 if(r) {
1642 pl = (dk3app_mc_t const *)l; pr = (dk3app_mc_t const *)r;
1643 if(pl->n) {
1644 if(pr->n) {
1645 back = dk3str_cmp(pl->n, pr->n);
1646 } else { back = 1; }
1647 } else {
1648 if(pr->n) { back = -1; }
1649 }
1650 } else { back = 1; }
1651 } else {
1652 if(r) { back = -1; }
1653 }
1654 return back;
1655 }
1656
1657
1658
1659 /** Write log message to a file.
1660 If the time has changed since the last message written to that
1661 file we write a new timestamp before writing the message.
1662 @param app Application structure.
1663 @param ll Log level, DK3_LL_xxx.
1664 @param msg Array of message parts.
1665 @param nmsg Number of elements in \a msg.
1666 @param fipo File to write to.
1667 @param last_time Timestamp of last message written to that file.
1668 */
1669 static
1670 void
dk3app_log_to_file(dk3_app_t * app,int ll,dkChar const * const * msg,size_t nmsg,FILE * fipo,dk3_time_t * last_time)1671 dk3app_log_to_file(
1672 dk3_app_t *app, int ll, dkChar const * const * msg, size_t nmsg,
1673 FILE *fipo, dk3_time_t *last_time
1674 )
1675 {
1676 dk3_time_t time_now; /* Current time. */
1677 dkChar tb[64]; /* Buffer to store current time as text. */
1678 char ulb[64]; /* Buffer for current time as char text. */
1679 char *sp = NULL; /* Source pointer used in conversion. */
1680 size_t i = 0; /* Index of current string to process. */
1681
1682 if(dk3sf_time(&time_now)) {
1683 if(time_now != *last_time) {
1684 if(dk3sf_time_convert_app(tb, DK3_SIZEOF(tb,dkChar), &time_now, NULL)) {
1685 *last_time = time_now;
1686 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[10], fipo);
1687 dk3sf_fputs(tb, fipo);
1688 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[0], fipo);
1689 }
1690 }
1691 }
1692 if(app->n_sourcefile) {
1693 dk3sf_fputs(app->n_sourcefile, fipo);
1694 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[11], fipo);
1695 if(app->sourceline) {
1696 sprintf(ulb, "%lu", app->sourceline);
1697 sp = ulb;
1698 while(*sp) { dk3sf_fputc( (dkChar)(*(sp++)), fipo); }
1699 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[11], fipo);
1700 }
1701 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[8], fipo);
1702 }
1703 if((ll >= DK3_LL_PANIC) && (ll <= DK3_LL_WARNING)) {
1704 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[ll], fipo);
1705 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[11], fipo);
1706 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[8], fipo);
1707 }
1708 for(i = 0; i < nmsg; i++) {
1709 if(msg[i]) {
1710 dk3sf_fputs(msg[i], fipo);
1711 }
1712 }
1713 dk3sf_fputs(((app->msg) ? app->msg : dk3app_kw)[0], fipo);
1714 }
1715
1716
1717
1718 static
1719 void
dk3app_create_parent_directory(const dkChar * fn)1720 dk3app_create_parent_directory(const dkChar *fn)
1721 {
1722 dkChar fnb[DK3_MAX_PATH];
1723 dkChar *ptr;
1724 dkChar *lptr;
1725
1726 if (dk3str_len(fn) < DK3_SIZEOF(fnb,dkChar)) {
1727 dk3str_cpy_not_overlapped(fnb, fn);
1728 ptr= fnb; lptr = NULL;
1729 while (dkT('\0') != *ptr) {
1730 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
1731 if (dkT('\\') == *ptr) { lptr = ptr; }
1732 #else
1733 if (dkT('/') == *ptr) { lptr = ptr; }
1734 #endif
1735 ptr++;
1736 }
1737 if (NULL != lptr) {
1738 *lptr = dkT('\0');
1739 (void)dk3sf_mkdir_app(fnb, 0700, NULL);
1740 }
1741 }
1742 }
1743
1744
1745
1746 /** Create ${HOME}/log directory for known log file name.
1747 @param app Application structure containing log file
1748 name in n_logfilename.
1749 */
1750 static
1751 void
dk3app_create_log_directory(dk3_app_t * app)1752 dk3app_create_log_directory(dk3_app_t *app)
1753 {
1754 dk3app_create_parent_directory(app->n_logfilename);
1755 }
1756
1757
1758
1759 /** Create ${HOME}/tmp directory for known log file name.
1760 @param app Application structure containing log file
1761 name in n_logfilename.
1762 */
1763 static
1764 void
dk3app_create_tmp_directory(dk3_app_t * app)1765 dk3app_create_tmp_directory(dk3_app_t *app)
1766 {
1767 dk3app_create_parent_directory(app->n_tmpdir);
1768 }
1769
1770
1771
1772 /** Write log message to log file.
1773 If the time has changed since the last message written to that
1774 file we write a new timestamp before writing the message.
1775 @param app Application structure.
1776 @param ll Log level, DK3_LL_xxx.
1777 @param msg Array of message parts.
1778 @param nmsg Number of elements in \a msg.
1779 */
1780 static
1781 void
dk3app_log_file(dk3_app_t * app,int ll,dkChar const * const * msg,size_t nmsg)1782 dk3app_log_file(dk3_app_t *app, int ll, dkChar const * const * msg, size_t nmsg)
1783 {
1784 FILE *fipo; /* Output file. */
1785 dk3_stat_t stb; /* File stat buffer. */
1786
1787 if(app->n_logfilename) {
1788 if (0 == app->cr_log) {
1789 /*
1790 Create ${HOME}/log directory if not yet done.
1791 */
1792 dk3app_create_log_directory(app);
1793 app->cr_log = 1;
1794 }
1795 if(app->f_first_file_log) {
1796 /*
1797 Daemons always attempt to append after existing log.
1798 */
1799 if(app->app_type == DK3_APP_TYPE_DAEMON) {
1800 app->f_first_file_log = 0;
1801 if(!dk3sf_stat_app(&stb, app->n_logfilename, NULL)) {
1802 app->f_first_file_log = 1;
1803 }
1804 }
1805 }
1806 fipo = dk3sf_fopen_app(app->n_logfilename, dk3app_no_loc[8], NULL);
1807 /* WRITE */
1808 if(fipo) {
1809 #if DK3_ON_WINDOWS && (DK3_CHAR_SIZE > 1)
1810 /* Switch to 16 bit characters. */
1811 #if defined(_MSC_VER)
1812 (void)_setmode(_fileno(fipo), _O_U16TEXT);
1813 #endif
1814 /* Write byte order marker. */
1815 if(app->f_first_file_log) {
1816 fputwc(0xFEFF, fipo);
1817 }
1818 #endif
1819 app->f_first_file_log = 0;
1820 dk3app_log_to_file(
1821 app, ll, msg, nmsg, fipo, &(app->t_last_log_file)
1822 );
1823 fclose(fipo);
1824 } else {
1825 }
1826 }
1827 }
1828
1829
1830
1831 int
dk3app_max_log_level(dk3_app_t const * app)1832 dk3app_max_log_level(dk3_app_t const *app)
1833 {
1834 int back = 0;
1835 if(app) {
1836 if(app->app_type != DK3_APP_TYPE_SILENT) {
1837 back = app->ll_file;
1838 if(app->app_type == DK3_APP_TYPE_COMMAND) {
1839 if(app->ll_stderr > back) {
1840 back = app->ll_stderr;
1841 }
1842 }
1843 }
1844 }
1845 return back;
1846 }
1847
1848 void
dk3app_log_msg(dk3_app_t * app,int ll,dkChar const * const * msg,size_t nmsg)1849 dk3app_log_msg(dk3_app_t *app, int ll, dkChar const * const * msg, size_t nmsg)
1850 {
1851
1852 if((app) && (msg) && (nmsg)) {
1853 if(app->f_readytolog) {
1854 if(ll < app->ll_highest) {
1855 app->ll_highest = ll;
1856 }
1857 switch(app->app_type) {
1858 case DK3_APP_TYPE_COMMAND: {
1859 if(app->ll_file >= ll) {
1860 dk3app_log_file(app, ll, msg, nmsg);
1861 } else {
1862 }
1863 if(app->ll_stderr >= ll) {
1864 dk3sf_initialize_stderr();
1865 dk3app_log_to_file(
1866 app, ll, msg, nmsg, stderr, &(app->t_last_log_stderr)
1867 );
1868 } else {
1869 }
1870 } break;
1871 case DK3_APP_TYPE_GUI:
1872 case DK3_APP_TYPE_DAEMON:
1873 {
1874 if(app->ll_file >= ll) {
1875 dk3app_log_file(app, ll, msg, nmsg);
1876 }
1877 } break;
1878 }
1879 } else {
1880 }
1881 } else {
1882 }
1883 }
1884
1885
1886
1887 void
dk3app_log_1(dk3_app_t * app,int ll,dkChar const * const * msg,size_t i1)1888 dk3app_log_1(dk3_app_t *app, int ll, dkChar const * const * msg, size_t i1)
1889 {
1890 dkChar const *m[2]; /* Message parts. */
1891
1892 if((app) && (msg)) {
1893 m[0] = msg[i1];
1894 m[1] = NULL;
1895 dk3app_log_msg(app, ll, (dkChar const * const *)m, 1);
1896 }
1897 }
1898
1899
1900
1901 void
dk3app_log_2(dk3_app_t * app,int ll,dkChar const * const * msg,size_t i,dkChar const * st)1902 dk3app_log_2(
1903 dk3_app_t *app, int ll, dkChar const * const * msg,
1904 size_t i, dkChar const *st
1905 )
1906 {
1907 dkChar const *m[3];
1908 if((app) && (msg)) {
1909 m[0] = msg[i];
1910 m[1] = st;
1911 m[2] = NULL;
1912 dk3app_log_msg(app, ll, (dkChar const * const *)m, 2);
1913 }
1914 }
1915
1916
1917 void
dk3app_log_3(dk3_app_t * app,int ll,dkChar const * const * msg,size_t i1,size_t i2,dkChar const * st)1918 dk3app_log_3(
1919 dk3_app_t *app, int ll, dkChar const * const * msg,
1920 size_t i1, size_t i2, dkChar const *st
1921 )
1922 {
1923 dkChar const *m[4]; /* Message parts. */
1924
1925 if((app) && (msg)) {
1926 m[0] = msg[i1];
1927 m[1] = st;
1928 m[2] = msg[i2];
1929 m[3] = NULL;
1930 dk3app_log_msg(app, ll, (dkChar const * const *)m, 3);
1931 }
1932 }
1933
1934
1935
1936 void
dk3app_log_5(dk3_app_t * app,int ll,dkChar const * const * msg,size_t i1,size_t i2,size_t i3,dkChar const * st1,dkChar const * st2)1937 dk3app_log_5(
1938 dk3_app_t *app, int ll, dkChar const * const * msg,
1939 size_t i1, size_t i2, size_t i3, dkChar const *st1, dkChar const *st2
1940 )
1941 {
1942 dkChar const *m[6]; /* Message parts. */
1943
1944 if((app) && (msg)) {
1945 m[0] = msg[i1];
1946 m[1] = st1;
1947 m[2] = msg[i2];
1948 m[3] = st2;
1949 m[4] = msg[i3];
1950 m[5] = NULL;
1951 dk3app_log_msg(app, ll, (dkChar const * const *)m, 5);
1952 }
1953 }
1954
1955
1956
1957 void
dk3app_log_i1(dk3_app_t * app,int ll,size_t i1)1958 dk3app_log_i1(dk3_app_t *app, int ll, size_t i1)
1959 {
1960
1961 if(app) {
1962 dk3app_log_1(app, ll, ((app->msg) ? app->msg : dk3app_kw), i1);
1963 }
1964 }
1965
1966
1967
1968 void
dk3app_log_i2(dk3_app_t * app,int ll,size_t i,dkChar const * st)1969 dk3app_log_i2(dk3_app_t *app, int ll, size_t i, dkChar const * st)
1970 {
1971 dkChar const *msg[3]; /* Message parts. */
1972
1973 if((app) && (i) && (st)) {
1974 if(i < DK3_SIZEOF(dk3app_kw,DK3_PCDKCHAR)) {
1975 msg[0] = ((app->msg) ? app->msg : dk3app_kw)[i];
1976 msg[1] = st;
1977 msg[2] = NULL;
1978 dk3app_log_msg(app, ll, (dkChar const * const *)msg, 2);
1979 }
1980 }
1981 }
1982
1983
1984
1985 void
dk3app_log_i3(dk3_app_t * app,int ll,size_t i1,size_t i2,dkChar const * st)1986 dk3app_log_i3(
1987 dk3_app_t *app, int ll,
1988 size_t i1, size_t i2, dkChar const *st
1989 )
1990 {
1991
1992 if(app) {
1993 dk3app_log_3(app, ll, ((app->msg) ? app->msg : dk3app_kw), i1, i2, st);
1994 }
1995 }
1996
1997
1998
1999 void
dk3app_log_i5(dk3_app_t * app,int ll,size_t i1,size_t i2,size_t i3,dkChar const * st1,dkChar const * st2)2000 dk3app_log_i5(
2001 dk3_app_t *app, int ll,
2002 size_t i1, size_t i2, size_t i3, dkChar const *st1, dkChar const *st2
2003 )
2004 {
2005
2006 if(app) {
2007 dk3app_log_5(
2008 app, ll, ((app->msg) ? app->msg : dk3app_kw), i1, i2, i3, st1, st2
2009 );
2010 }
2011 }
2012
2013
2014
2015 void
dk3app_set_source_file(dk3_app_t * app,dkChar const * fn)2016 dk3app_set_source_file(dk3_app_t *app, dkChar const *fn)
2017 {
2018 if(app) {
2019 app->n_sourcefile = fn;
2020 }
2021 }
2022
2023
2024
2025 void
dk3app_set_source_line(dk3_app_t * app,unsigned long li)2026 dk3app_set_source_line(dk3_app_t *app, unsigned long li)
2027 {
2028 if(app) {
2029 app->sourceline = li;
2030 }
2031 }
2032
2033
2034
2035 dkChar const *
dk3app_get_source_file(dk3_app_t const * app)2036 dk3app_get_source_file(dk3_app_t const *app)
2037 {
2038 dkChar const *back = NULL;
2039 if(app) {
2040 back = app->n_sourcefile;
2041 }
2042 return back;
2043 }
2044
2045
2046
2047 unsigned long
dk3app_get_source_line(dk3_app_t const * app)2048 dk3app_get_source_line(dk3_app_t const *app)
2049 {
2050 unsigned long back = 0UL;
2051 if(app) {
2052 back = app->sourceline;
2053 }
2054 return back;
2055 }
2056
2057
2058
2059 /** Find data (resource) file.
2060 String tables are resources too, so we check language and
2061 region subdirectories too.
2062 @param app Application structure.
2063 @param fn File name.
2064 @param db Destination buffer.
2065 @param sz Size of \a db (number of characters).
2066 @param verb Flag: Diagnostic messages enabled.
2067 @return 1 on success, 0 on error.
2068 */
2069 static
2070 int
dk3app_my_find_data_file(dk3_app_t * app,dkChar const * fn,dkChar * db,size_t sz,int verb)2071 dk3app_my_find_data_file(
2072 dk3_app_t *app, dkChar const *fn, dkChar *db, size_t sz, int verb
2073 )
2074 {
2075 int back = 0;
2076 dkChar const *p1 = NULL; /* dk3app, group or application name. */
2077 dkChar const *p2 = NULL; /* Language. */
2078 dkChar const *p3 = NULL; /* Region. */
2079 int cc = 1; /* Flag: Can go. */
2080 size_t mysz = 0; /* Size for calculation. */
2081 size_t sz1 = 0; /* Length of /xxx/share directory name. */
2082 size_t sz2 = 0; /* Length of short file name. */
2083 dk3_stat_t stb; /* Stat buffer to test existance of files. */
2084 int i = 0; /* Pass: 0=lang+region, 1=language, 0=share. */
2085 int j = 0; /* Pass: 0=app, 1=appgroup, 2=dk3app, 3=base. */
2086
2087 if((app) && (fn) && (db) && (sz)) {
2088 if(app->n_sharedir) {
2089 sz1 = dk3str_len(app->n_sharedir);
2090 sz2 = dk3str_len(fn);
2091 for(i = 0; ((back == 0) && (i < 4)); i++) {
2092 for(j = 0; ((back == 0) && (j < 4)); j++) {
2093 p1 = NULL; p2 = NULL; p3 = NULL; cc = 0;
2094 switch(i) {
2095 case 1: {
2096 if(app->n_language) {
2097 p2 = app->n_language; cc = 1;
2098 }
2099 } break;
2100 case 2: {
2101 p2 = dk3app_no_loc[47]; cc = 1;
2102 } break;
2103 case 3: {
2104 cc = 1;
2105 } break;
2106 default: {
2107 if(app->n_language) {
2108 p2 = app->n_language;
2109 if(app->n_region) {
2110 p3 = app->n_region; cc = 1;
2111 }
2112 }
2113 } break;
2114 }
2115 switch(j) {
2116 case 1: {
2117 if(app->n_appgroup) {
2118 p1 = app->n_appgroup;
2119 } else {
2120 cc = 0;
2121 }
2122 } break;
2123 case 2: {
2124 p1 = dk3app_no_loc[17];
2125 } break;
2126 case 3: {
2127 p1 = NULL;
2128 } break;
2129 default: {
2130 if(app->n_app) {
2131 p1 = app->n_app;
2132 } else {
2133 cc = 0;
2134 }
2135 } break;
2136 }
2137 if(cc) {
2138 mysz = sz1 + sz2 + 1;
2139 if(p1) { mysz += dk3str_len(p1); mysz++; }
2140 if(p2) { mysz += dk3str_len(p2); mysz++; }
2141 if(p3) { mysz += dk3str_len(p3); mysz++; }
2142 if(mysz < sz) {
2143 dk3str_cpy_not_overlapped(db, app->n_sharedir);
2144 if(p1) {
2145 dk3str_cat(db, dk3app_no_loc[20]); dk3str_cat(db, p1);
2146 }
2147 if(p2) {
2148 dk3str_cat(db, dk3app_no_loc[20]); dk3str_cat(db, p2);
2149 }
2150 if(p3) {
2151 dk3str_cat(db, dk3app_no_loc[20]); dk3str_cat(db, p3);
2152 }
2153 dk3str_cat(db, dk3app_no_loc[20]);
2154 dk3str_cat(db, fn);
2155 if(dk3sf_stat_app(&stb, db, NULL)) {
2156 switch((stb.ft) & (~(DK3_FT_SYMLINK))) {
2157 case DK3_FT_REGULAR: {
2158 back = 1;
2159 } break;
2160 }
2161 }
2162 if(back) {
2163 /* DEBUG: Resource file ... found. */
2164 dk3app_log_i3(app, DK3_LL_DEBUG, 148, 149, db);
2165 } else {
2166 /* DEBUG: Resource file ... not found. */
2167 dk3app_log_i3(app, DK3_LL_DEBUG, 150, 151, db);
2168 }
2169 }
2170 }
2171 }
2172 }
2173 } else {
2174 if(verb) {
2175 /* Internal error, no /xxx/share directory! */
2176 dk3app_log_i1(app, DK3_LL_ERROR, 55);
2177 }
2178 }
2179 }
2180 return back;
2181 }
2182
2183
2184
2185 /** Remove a file.
2186 The difference to dk3sf_remove_file_app() is that this function
2187 does not complain if the file does not exist.
2188 @param n File name.
2189 @param app Application structure for diagnostics, may be NULL.
2190 @return 1 on success, 0 on error.
2191 */
2192 static
2193 int
dk3app_remove_file_app(dkChar * n,dk3_app_t * app)2194 dk3app_remove_file_app(dkChar *n, dk3_app_t *app)
2195 {
2196 int back = 0;
2197 dk3_stat_t stb; /* Stat buffer to test existance of file. */
2198
2199 if(dk3sf_stat_app(&stb,n,app)) {
2200 back = dk3sf_remove_file_app(n, app);
2201 } else {
2202 back = 1; /* File does not exist. */
2203 }
2204 return back;
2205 }
2206
2207
2208
2209 /** Delete one temporaray file.
2210 @param app Application structure.
2211 @param n Number to build the file name.
2212 @param s Number to build the file suffix.
2213 @param f Pointer to error code variable.
2214 */
2215 static
2216 void
dk3app_delete_one_temp_file(dk3_app_t * app,unsigned long n,unsigned s,int * f)2217 dk3app_delete_one_temp_file(dk3_app_t *app, unsigned long n, unsigned s, int *f)
2218 {
2219 dkChar buffer[DK3_MAX_PATH]; /* Buffer to construct complete file name. */
2220 dkChar fnb2[16]; /* Buffer for short file name. */
2221 char fnb[16]; /* Buffer for numeric conversion. */
2222 dk3_app_t *ra = NULL; /* Application to use for diagnostics. */
2223 size_t sz = 0; /* Length needed for complete file name. */
2224
2225 sprintf(fnb, "/%08lx.%03x", n, s);
2226 ra = app;
2227 if((*f) & 1) { ra = NULL; }
2228 if(dk3str_cnv_c8_to_str_app(fnb2, 15, fnb, ra)) {
2229 sz = dk3str_len(app->n_tmpdir) + dk3str_len(fnb2);
2230 if(sz < DK3_SIZEOF(buffer,dkChar)) {
2231 dk3str_cpy_not_overlapped(buffer, app->n_tmpdir);
2232 dk3str_cat(buffer, fnb2);
2233 dk3str_correct_filename(buffer);
2234 #if VERSION_BEFORE_20150821
2235 ra = app;
2236 if((*f) & 4) { ra = NULL; }
2237 #endif
2238 if(!dk3app_remove_file_app(buffer, NULL)) {
2239 *f = ((*f) | 4);
2240 }
2241 } else {
2242 if(!((*f) & 2)) {
2243 dk3app_log_i1(app, DK3_LL_ERROR, 37);
2244 *f = ((*f) | 2);
2245 }
2246 }
2247 } else {
2248 *f = ((*f) | 1);
2249 }
2250 }
2251
2252
2253
2254 /** Delete all temporary files of an application for a core name.
2255 @param app Application structure.
2256 @param n Number to build core file name.
2257 @param f Pointer to error code variable.
2258 */
2259 static
2260 void
dk3app_delete_all_temp_files_for(dk3_app_t * app,unsigned long n,int * f)2261 dk3app_delete_all_temp_files_for(dk3_app_t *app, unsigned long n, int *f)
2262 {
2263 unsigned u; /* Used for file name suffix. */
2264
2265 for(u = 0; u < 0x1000U; u++) {
2266 dk3app_delete_one_temp_file(app, n, u, f);
2267 }
2268 }
2269
2270
2271
2272 /** Delete all temporary files of an application.
2273 @param app Application structure.
2274 */
2275 static
2276 void
dk3app_remove_temporary_files(dk3_app_t * app)2277 dk3app_remove_temporary_files(dk3_app_t *app)
2278 {
2279 unsigned long ul = 0UL; /* Used for base file name. */
2280 unsigned u = 0; /* Used for suffixes of final base. */
2281 int f = 0; /* Error checking variable. */
2282
2283 if(app->n_tmpdir) {
2284 f = 0;
2285 if(app->i_tmpcarry) {
2286 for(ul = 0UL; ul < 0xFFFFFFFFUL; ul++) {
2287 dk3app_delete_all_temp_files_for(app, ul, &f);
2288 }
2289 dk3app_delete_all_temp_files_for(app, 0xFFFFFFFFUL, &f);
2290 } else {
2291 for(ul = 0UL; ul < app->ul_tmpname; ul++) {
2292 dk3app_delete_all_temp_files_for(app, ul, &f);
2293 }
2294 for(u = 0; u < app->u_tmpsuffix; u++) {
2295 dk3app_delete_one_temp_file(app, app->ul_tmpname, u, &f);
2296 }
2297 dk3app_delete_one_temp_file(app, app->ul_tmpname, app->u_tmpsuffix, &f);
2298 }
2299 dk3sf_remove_dir_app(app->n_tmpdir, NULL);
2300 }
2301 }
2302
2303
2304
2305 /** Construct configuration file name candidate.
2306 When searching for files (configuration or resource files) we
2307 specify the sort file name without leading directory.
2308 During the search process we do several tests prepending
2309 directory names before the short file name.
2310 This function is used to construct a file name.
2311 @param app Application structure.
2312 @param fn File name.
2313 @param db Result buffer.
2314 @param sz Size of \a db (number of characters).
2315 @param passno Pass number (0-15).
2316 @param verb Flag: Diagnostic messages enabled.
2317 @return 1 on success, 0 on error.
2318 */
2319 static
2320 int
dk3app_config_name(dk3_app_t * app,dkChar const * fn,dkChar * db,size_t sz,int passno,int verb)2321 dk3app_config_name(
2322 dk3_app_t *app, dkChar const *fn, dkChar *db, size_t sz, int passno, int verb
2323 )
2324 {
2325 int back = 0;
2326 dkChar const *ptr1 = NULL; /* Base directory (etc or share). */
2327 dkChar const *ptr2 = NULL; /* Subdirectory (app, group, dk3app or none). */
2328 dkChar const *ptr3 = NULL; /* Application or group name. */
2329 size_t mysz = 0; /* Buffer size needed for all components. */
2330
2331 ptr1 = NULL; ptr2 = NULL; ptr3 = NULL;
2332 switch(passno) {
2333
2334 #if VERSION_BEFORE_20110219
2335 case 0: { ptr1 = app->n_sharedir; ptr2 = dk3app_no_loc[17]; } break;
2336 case 2: { ptr1 = app->n_sharedir; ptr2 = app->n_appgroup; } break;
2337 case 3: { ptr1 = app->n_etcdir; ptr2 = app->n_appgroup; } break;
2338 case 4: { ptr1 = app->n_sharedir; ptr2 = app->n_app; } break;
2339 case 5: { ptr1 = app->n_etcdir; ptr2 = app->n_app; } break;
2340 case 6: { ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18]; } break;
2341 case 7: {
2342 ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18]; ptr3 = app->n_appgroup;
2343 } break;
2344 case 8: {
2345 ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18]; ptr3 = app->n_app;
2346 } break;
2347 case 9: {
2348 ptr1 = dk3app_no_loc[19];
2349 } break;
2350 default: { /* 1 */
2351 ptr1 = app->n_etcdir; ptr2 = dk3app_no_loc[17];
2352 } break;
2353 #else
2354 case 0: {
2355 ptr1 = app->n_sharedir; ptr2 = dk3app_no_loc[17];
2356 } break;
2357 case 1: {
2358 ptr1 = app->n_etcdir; ptr2 = dk3app_no_loc[17];
2359 } break;
2360 case 2: {
2361 ptr1 = app->n_sharedir; ptr2 = dk3app_no_loc[17];
2362 } break;
2363 case 3: {
2364 ptr1 = app->n_etcdir; ptr2 = dk3app_no_loc[17];
2365 } break;
2366 case 4: {
2367 ptr1 = app->n_sharedir; ptr2 = app->n_appgroup;
2368 } break;
2369 case 5: {
2370 ptr1 = app->n_etcdir; ptr2 = app->n_appgroup;
2371 } break;
2372 case 6: {
2373 ptr1 = app->n_sharedir; ptr2 = app->n_appgroup;
2374 } break;
2375 case 7: {
2376 ptr1 = app->n_etcdir; ptr2 = app->n_appgroup;
2377 } break;
2378 case 8: {
2379 ptr1 = app->n_sharedir; ptr2 = app->n_app;
2380 } break;
2381 case 9: {
2382 ptr1 = app->n_etcdir; ptr2 = app->n_app;
2383 } break;
2384 case 10: {
2385 ptr1 = app->n_sharedir; ptr2 = app->n_app;
2386 } break;
2387 case 11: {
2388 ptr1 = app->n_etcdir; ptr2 = app->n_app;
2389 } break;
2390 case 12: {
2391 ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18];
2392 } break;
2393 case 13: {
2394 ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18]; ptr3 = app->n_appgroup;
2395 } break;
2396 case 14: {
2397 ptr1 = app->n_homedir; ptr2 = dk3app_no_loc[18]; ptr3 = app->n_app;
2398 } break;
2399 case 15: {
2400 ptr1 = dk3app_no_loc[19];
2401 } break;
2402 #endif
2403 }
2404 mysz = dk3str_len(fn);
2405 if(ptr1) {
2406 mysz += dk3str_len(ptr1);
2407 mysz++;
2408 }
2409 if(ptr2) {
2410 mysz += dk3str_len(ptr2);
2411 mysz++;
2412 }
2413 if(ptr3) {
2414 mysz += dk3str_len(ptr3);
2415 mysz++;
2416 }
2417 switch(passno) {
2418 case 2: case 3: case 6: case 7: case 10: case 11: {
2419 mysz += dk3str_len(dk3app_no_loc[32]);
2420 } break;
2421 }
2422 if(mysz < sz) {
2423 if(ptr1) {
2424 dk3str_cpy_not_overlapped(db, ptr1);
2425 if(ptr2) {
2426 dk3str_cat(db, dk3app_no_loc[20]);
2427 dk3str_cat(db, ptr2);
2428 }
2429 if(ptr3) {
2430 dk3str_cat(db, dk3app_no_loc[20]);
2431 dk3str_cat(db, ptr3);
2432 }
2433 switch(passno) {
2434 case 2: case 3: case 6: case 7: case 10: case 11: {
2435 dk3str_cat(db, dk3app_no_loc[32]);
2436 } break;
2437 }
2438 dk3str_cat(db, dk3app_no_loc[20]);
2439 dk3str_cat(db, fn);
2440 back = 1;
2441 } else {
2442 if(verb) {
2443 /* Internal error, some directory not set! */
2444 }
2445 }
2446 } else {
2447 if(verb) {
2448 dk3app_log_i1(app, DK3_LL_ERROR, 38);
2449 }
2450 }
2451 return back;
2452 }
2453
2454
2455
2456 /** Unconfigure application (delete registry key or config file).
2457 @param app Application to unconfigure.
2458 */
2459 static
2460 void
dk3app_do_unconfigure(dk3_app_t * app)2461 dk3app_do_unconfigure(dk3_app_t *app)
2462 {
2463 dkChar fnb[DK3_MAX_PATH]; /* File name buffer for config file. */
2464
2465 if(dk3app_config_name(app, dk3app_no_loc[21], fnb, DK3_MAX_PATH, 14, 0)) {
2466 (void)dk3sf_remove_file_app(fnb, app);
2467 }
2468 }
2469
2470
2471
2472 /** Save self-set preferences to registry or file.
2473 @param app Application structure.
2474 */
2475 static
2476 void
dk3app_do_save_config(dk3_app_t * app)2477 dk3app_do_save_config(dk3_app_t *app)
2478 {
2479 dkChar fnb[DK3_MAX_PATH]; /* File name buffer for conf file. */
2480 dkChar *ptr = NULL; /* Slash/backslash correction. */
2481 FILE *fipo = NULL; /* Used to write file. */
2482 dk3app_pref_t *p1 = NULL; /* Preference entry to process. */
2483 dk3app_pref_t *p2 = NULL; /* Check in higher priorized storage. */
2484
2485 if(dk3app_config_name(app, dk3app_no_loc[21], fnb, DK3_MAX_PATH, 14, 0)) {
2486
2487 ptr = dk3str_rchr(fnb, DK3_CHAR_SEP);
2488 if(ptr) {
2489 *ptr = dkT('\0');
2490
2491 dk3sf_mkdir_app(fnb, 0700, NULL);
2492 *ptr = DK3_CHAR_SEP;
2493 }
2494 fipo = dk3sf_fopen_app(fnb, dk3app_no_loc[24], app); /* WRITE */
2495 if(fipo) {
2496 #if DK3_ON_WINDOWS && (DK3_CHAR_SIZE > 1)
2497 /* Switch to 16 bit characters. */
2498 #if defined(_MSC_VER)
2499 (void)_setmode(_fileno(fipo), _O_U16TEXT);
2500 #endif
2501 /* Write byte order marker. */
2502 fputwc(0xFEFF, fipo);
2503 #endif
2504 if((app->s_varprefs) && (app->i_varprefs)) {
2505 dk3sto_it_reset(app->i_varprefs);
2506 while((p1 = (dk3app_pref_t *)dk3sto_it_next(app->i_varprefs)) != NULL) {
2507 p2 = NULL;
2508 if((app->s_selfprefs) && (app->i_selfprefs)) {
2509 p2 = (dk3app_pref_t *)dk3sto_it_find_like(app->i_selfprefs, p1, 0);
2510 }
2511 if(!(p2)) {
2512 dk3sf_fputs(p1->k, fipo);
2513 dk3sf_fputs(dk3app_no_loc[25], fipo);
2514 dk3sf_fputs(p1->v, fipo);
2515 dk3sf_fputs(dk3app_no_loc[26], fipo);
2516 }
2517 }
2518 }
2519 if((app->s_selfprefs) && (app->i_selfprefs)) {
2520 dk3sto_it_reset(app->i_selfprefs);
2521 while((p1 = (dk3app_pref_t *)dk3sto_it_next(app->i_selfprefs)) != NULL) {
2522 dk3sf_fputs(p1->k, fipo);
2523 dk3sf_fputs(dk3app_no_loc[25], fipo);
2524 dk3sf_fputs(p1->v, fipo);
2525 dk3sf_fputs(dk3app_no_loc[26], fipo);
2526 }
2527 }
2528 fclose(fipo);
2529 } else {
2530 }
2531 } else {
2532 }
2533 }
2534
2535
2536
2537
2538
2539 void
dk3app_close(dk3_app_t * app)2540 dk3app_close(dk3_app_t *app)
2541 {
2542 int i = 0; /* Used to release argv memory. */
2543 dk3app_pref_t *pref = NULL; /* Used to delete preference entries. */
2544 dk3app_mc_t *mcptr = NULL; /* Used to delete message catalogs. */
2545
2546
2547 if(app) {
2548 if(app->f_unconfigure) {
2549 dk3app_do_unconfigure(app);
2550 } else {
2551 if(app->f_prefschanged) {
2552 dk3app_do_save_config(app);
2553 }
2554 }
2555 /* Clean up preferences system. */
2556 if(app->s_selfprefs) {
2557 if(app->i_selfprefs) {
2558 dk3sto_it_reset(app->i_selfprefs);
2559 while((pref = (dk3app_pref_t *)dk3sto_it_next(app->i_selfprefs)) != NULL) {
2560 dk3app_pref_delete(pref);
2561 }
2562 dk3sto_it_close(app->i_selfprefs);
2563 }
2564 dk3sto_close(app->s_selfprefs);
2565 } app->s_selfprefs = NULL; app->i_selfprefs = NULL;
2566 if(app->s_cmdprefs) {
2567 if(app->i_cmdprefs) {
2568 dk3sto_it_reset(app->i_cmdprefs);
2569 while((pref = (dk3app_pref_t *)dk3sto_it_next(app->i_cmdprefs)) != NULL) {
2570 dk3app_pref_delete(pref);
2571 }
2572 dk3sto_it_close(app->i_cmdprefs);
2573 }
2574 dk3sto_close(app->s_cmdprefs);
2575 } app->s_cmdprefs = NULL; app->i_cmdprefs = NULL;
2576 if(app->s_sysprefs) {
2577 if(app->i_sysprefs) {
2578 dk3sto_it_reset(app->i_sysprefs);
2579 while((pref = (dk3app_pref_t *)dk3sto_it_next(app->i_sysprefs)) != NULL)
2580 {
2581 dk3app_pref_delete(pref);
2582 }
2583 dk3sto_it_close(app->i_sysprefs);
2584 }
2585 dk3sto_close(app->s_sysprefs);
2586 } app->s_sysprefs = NULL; app->i_sysprefs = NULL;
2587 if(app->s_constprefs) {
2588 if(app->i_constprefs) {
2589 dk3sto_it_reset(app->i_constprefs);
2590 while((pref = (dk3app_pref_t *)dk3sto_it_next(app->i_constprefs)) != NULL)
2591 {
2592 dk3app_pref_delete(pref);
2593 }
2594 dk3sto_it_close(app->i_constprefs);
2595 }
2596 dk3sto_close(app->s_constprefs);
2597 } app->s_constprefs = NULL; app->i_constprefs = NULL;
2598 if(app->s_varprefs) {
2599 if(app->i_varprefs) {
2600 dk3sto_it_reset(app->i_varprefs);
2601 while((pref = (dk3app_pref_t *)dk3sto_it_next(app->i_varprefs)) != NULL)
2602 {
2603 dk3app_pref_delete(pref);
2604 }
2605 dk3sto_it_close(app->i_varprefs);
2606 }
2607 dk3sto_close(app->s_varprefs);
2608 } app->s_varprefs = NULL; app->i_varprefs = NULL;
2609 /* Clean up temporary directory. */
2610 if(app->ll_highest > app->ll_tmp_keep) {
2611 dk3app_remove_temporary_files(app);
2612 }
2613 /* Remove log file if no longer needed. */
2614 if(DK3_APP_TYPE_DAEMON != app->app_type) {
2615 dk3app_log_i3(app, DK3_LL_DEBUG, 21, 22, app->n_app);
2616 if(app->ll_highest > app->ll_file_keep) {
2617 dk3sf_remove_file_app(app->n_logfilename, NULL);
2618 }
2619 }
2620 /* Unset resources, release resources. */
2621 app->ll_file = app->ll_stderr = app->ll_file_keep = app->ll_highest = 0;
2622 app->app_type = 0;
2623 app->msg = NULL;
2624 app->n_sourcefile = NULL;
2625 app->sourceline = 0UL;
2626 if(app->s_mc) {
2627 if(app->i_mc) {
2628 dk3sto_it_reset(app->i_mc);
2629 while((mcptr = (dk3app_mc_t *)dk3sto_it_next(app->i_mc)) != NULL)
2630 {
2631 dk3app_mc_delete(mcptr);
2632 }
2633 dk3sto_it_close(app->i_mc);
2634 }
2635 dk3sto_close(app->s_mc);
2636 } app->s_mc = NULL; app->i_mc = NULL;
2637 if(app->argv) {
2638 dkChar const **ptr;
2639 ptr = (dkChar const **)(app->argv);
2640 for(i = 0; i < app->argc; i++) {
2641 dk3_release(*ptr);
2642 ptr++;
2643 }
2644 }
2645 dk3_release(app->n_app);
2646 dk3_release(app->n_execfile);
2647 dk3_release(app->n_bindir);
2648 dk3_release(app->n_etcdir);
2649 dk3_release(app->n_sharedir);
2650 dk3_release(app->n_vardir);
2651 dk3_release(app->n_logname);
2652 dk3_release(app->n_homedir);
2653 dk3_release(app->n_appgroup);
2654 dk3_release(app->n_logfilename);
2655 dk3_release(app->n_tmpdir);
2656 dk3_release(app->n_language);
2657 dk3_release(app->n_region);
2658 dk3_release(app->n_langstr);
2659 dk3_release(app->n_hostname);
2660 dk3_delete(app);
2661 }
2662 }
2663
2664
2665
2666 int
dk3app_get_default_stdin_encoding(dk3_app_t const * app)2667 dk3app_get_default_stdin_encoding(dk3_app_t const *app)
2668 {
2669 int back = 0;
2670 if(app) {
2671 back = app->i_output_encoding;
2672 #if DK3_CHAR_SIZE > 1
2673 #if DK3_ON_WINDOWS
2674 back = DK3_FILE_ENCODING_ASCII;
2675 #endif
2676 #endif
2677 }
2678 return back;
2679 }
2680
2681
2682
2683 int
dk3app_get_default_file_encoding(dk3_app_t const * app)2684 dk3app_get_default_file_encoding(dk3_app_t const *app)
2685 {
2686 int back = 0;
2687 if(app) {
2688 back = app->i_output_encoding;
2689 #if DK3_CHAR_SIZE > 1
2690 #if DK3_ON_WINDOWS
2691 back = DK3_FILE_ENCODING_ASCII;
2692 #endif
2693 #endif
2694 }
2695 return back;
2696 }
2697
2698
2699
2700
2701 /** Initialize application structure.
2702 @param app Application to initialize.
2703 */
2704 static
2705 void
dk3app_init(dk3_app_t * app)2706 dk3app_init(dk3_app_t *app)
2707 {
2708
2709 app->app_type = 0;
2710 app->msg = NULL;
2711 app->n_sourcefile = NULL;
2712 app->sourceline = 0UL;
2713 app->ll_file = DK3_LL_NONE;
2714 app->ll_stderr = DK3_LL_INFO;
2715 app->ll_file_keep = DK3_LL_NONE;
2716 app->ll_tmp_keep = DK3_LL_NONE;
2717 app->ll_highest = DK3_LL_IGNORE;
2718 app->argv = NULL;
2719 app->argc = 0;
2720 app->n_app = NULL;
2721 app->n_execfile = NULL;
2722 app->n_bindir = NULL;
2723 app->n_etcdir = NULL;
2724 app->n_sharedir = NULL;
2725 app->n_vardir = NULL;
2726 app->n_logname = NULL;
2727 app->n_homedir = NULL;
2728 app->n_appgroup = NULL;
2729 app->n_logfilename = NULL;
2730 app->n_tmpdir = NULL;
2731 app->n_language = NULL;
2732 app->n_region = NULL;
2733 app->n_langstr = NULL;
2734 app->ul_tmpname = 0UL;
2735 app->u_tmpsuffix = 0U;
2736 app->i_tmpcarry = 0;
2737 app->n_hostname = NULL;
2738 #if DK3_CHAR_SIZE > 1
2739 app->i_encoding = DK3_ENCODING_UTF16;
2740 #if DK3_BIGENDIAN
2741 app->i_output_encoding = DK3_FILE_ENCODING_UTF16_MSB_FIRST;
2742 #else
2743 app->i_output_encoding = DK3_FILE_ENCODING_UTF16_LSB_FIRST;
2744 #endif
2745 #else
2746 app->i_encoding = DK3_ENCODING_PLAIN;
2747 app->i_output_encoding = DK3_FILE_ENCODING_ASCII;
2748 #endif
2749 app->i_stdin_input_encoding = dk3app_get_default_stdin_encoding(app);
2750
2751 app->i_file_input_encoding = dk3app_get_default_file_encoding(app);
2752 app->de = 0; /* No error found yet. */
2753 app->s_mc = NULL;
2754 app->i_mc = NULL;
2755 app->s_cmdprefs = NULL;
2756 app->i_cmdprefs = NULL;
2757 app->s_selfprefs = NULL;
2758 app->i_selfprefs = NULL;
2759 app->f_unconfigure = 0;
2760 app->f_prefschanged = 0;
2761 app->f_readytolog = 0;
2762 app->s_sysprefs = NULL;
2763 app->i_sysprefs = NULL;
2764 app->s_constprefs = NULL;
2765 app->i_constprefs = NULL;
2766 app->s_varprefs = NULL;
2767 app->i_varprefs = NULL;
2768 app->f_first_file_log = 1;
2769 app->f_rand_initialized = 0;
2770 app->f_rand_success = 0;
2771 app->rand_type = 0;
2772 app->cr_log = 0;
2773 app->cr_tmp = 0;
2774 app->t_last_log_stderr = (dk3_time_t)0UL;
2775 app->t_last_log_file = (dk3_time_t)0UL;
2776 }
2777
2778
2779
2780 /** Copy binary directory name to other directory names.
2781 @param app Application structure.
2782 */
2783 static
2784 void
dk3app_copy_bin_to_others(dk3_app_t * app)2785 dk3app_copy_bin_to_others(dk3_app_t *app)
2786 {
2787
2788 app->n_etcdir = dk3str_dup_app(app->n_bindir, NULL);
2789 if(app->n_etcdir) {
2790 app->n_sharedir = dk3str_dup_app(app->n_bindir, NULL);
2791 if(app->n_sharedir) {
2792 app->n_vardir = dk3str_dup_app(app->n_bindir, NULL);
2793 if(!(app->n_vardir)) {
2794 app->de = 9;
2795 }
2796 } else {
2797 app->de = 8;
2798 }
2799 } else {
2800 app->de = 7;
2801 }
2802 }
2803
2804
2805 #if DK3_ON_WINDOWS
2806
2807 #if VERSION_BEFORE_20131022
2808
2809 /** Open a registry key.
2810 @param k Parent key (HKLM or HKCU).
2811 @param n Key name.
2812 @param p Permissions needed.
2813 @param kp Pointer to result key variable.
2814 @return ERROR_SUCCESS on success, other values indicate an error.
2815 */
2816 static
2817 long
dk3app_reg_open_key(HKEY k,dkChar const * n,int p,HKEY * kp)2818 dk3app_reg_open_key(HKEY k, dkChar const *n, int p, HKEY *kp)
2819 {
2820 long back = 0L;
2821 #if DK3_CHAR_SIZE > 1
2822 back = RegOpenKeyExW(k, n, (DWORD)0, p, kp);
2823 #else
2824 back = RegOpenKeyExA(k, n, (DWORD)0, p, kp);
2825 #endif
2826 return back;
2827 }
2828
2829
2830
2831 /** Retrieve a value from the registry.
2832 @param k Registry key.
2833 @param n Entry name.
2834 @param tp Entry type.
2835 @param b Result buffer address.
2836 @param len In: size of buffer, out: number of bytes used.
2837 @return ERROR_SUCCESS on success, any other value indicates an error.
2838 */
2839 static
2840 long
dk3app_reg_query(HKEY k,dkChar const * n,DWORD * tp,LPBYTE b,DWORD * len)2841 dk3app_reg_query(HKEY k, dkChar const *n, DWORD *tp, LPBYTE b, DWORD *len)
2842 {
2843 long back = 0L;
2844 #if DK3_CHAR_SIZE > 1
2845 back = RegQueryValueExW(k, n, NULL, tp, b, len);
2846 #else
2847 back = RegQueryValueExA(k, n, NULL, tp, b, len);
2848 #endif
2849 return back;
2850 }
2851
2852
2853
2854 /** Retrieve string value from registry.
2855 @param k Key.
2856 @param n Entry name.
2857 @param b Result buffer.
2858 @param sz Size of \a b (number of characters).
2859 @return 1 on success, 0 on error.
2860 */
2861 static
2862 int
dk3app_reg_query_str(HKEY k,dkChar const * n,dkChar * b,size_t sz)2863 dk3app_reg_query_str(HKEY k, dkChar const *n, dkChar *b, size_t sz)
2864 {
2865 int back = 0;
2866 DWORD tp = REG_SZ; /* Registry entry type. */
2867 DWORD len = 0L; /* Length of arguments and results. */
2868 LONG res = 0L; /* Registry operation result. */
2869 tp = REG_SZ;
2870 len = (DWORD)(sz * DK3_CHAR_SIZE);
2871 res = dk3app_reg_query(k, n, &tp, (LPBYTE)b, &len);
2872 if(ERROR_SUCCESS == res) {
2873 if((REG_SZ == tp) || (REG_EXPAND_SZ == tp)) {
2874 if(len > 0) {
2875 #if DK3_CHAR_SIZE > 1
2876 len = len / DK3_CHAR_SIZE;
2877 #endif
2878 b[(((size_t)len) < sz) ? len : (sz - 1)] = dkT('\0');
2879 back = 1;
2880 }
2881 }
2882 }
2883 return back;
2884 }
2885
2886 #endif
2887
2888 #endif
2889
2890
2891
2892 /** Get users language/region/encoding setting.
2893 @param app Application structure.
2894 @param db Result buffer.
2895 @param sz Size of \a db (number of characters).
2896 @return 1 on success, 0 on error.
2897 */
2898 static
2899 int
dk3app_get_language_string(dk3_app_t * app,dkChar * db,size_t sz)2900 dk3app_get_language_string(
2901 #if (!(DK3_ON_WINDOWS)) && (DK3_CHAR_SIZE == 1)
2902 dk3_app_t *app,
2903 #else
2904 dk3_app_t * DK3_ARG_UNUSED(app),
2905 #endif
2906 dkChar *db,
2907 size_t sz
2908 )
2909 {
2910 int back = 0;
2911
2912 #if DK3_ON_WINDOWS
2913 DK3_UNUSED_ARG(app)
2914 #if VERSION_BEFORE_20131022
2915 {
2916 LONG res = 0L; /* Registry operation result. */
2917 HKEY key; /* Registry key. */
2918 res = dk3app_reg_open_key(
2919 HKEY_CURRENT_USER,
2920 dk3app_no_loc[12],
2921 KEY_READ,
2922 &key
2923 );
2924 if(ERROR_SUCCESS == res) {
2925 back = dk3app_reg_query_str(key, dk3app_no_loc[13], db, sz);
2926 if(back == 0) {
2927 back = dk3app_reg_query_str(key, dk3app_no_loc[14], db, sz);
2928 if(back) {
2929 db[2] = dkT('\0');
2930 }
2931 }
2932 RegCloseKey(key);
2933 }
2934 }
2935 #else
2936 {
2937 HKEY hk; /* Registry key. */
2938 if(dk3wreg_key_open_read(HKEY_CURRENT_USER, dk3app_no_loc[12], &hk, NULL)) {
2939 if(dk3wreg_get_sz(hk, dk3app_no_loc[13],db,sz,NULL)) {
2940 back = 1;
2941 } else {
2942 if(dk3wreg_get_sz(hk, dk3app_no_loc[14],db,sz,NULL)) {
2943 back = 1;
2944 db[2] = dkT('\0');
2945 }
2946 }
2947 dk3wreg_key_close(hk, dk3app_no_loc[12], NULL);
2948 }
2949 }
2950 #endif
2951
2952 #else
2953 #if DK3_CHAR_SIZE == 1
2954 {
2955 char *ptr; /* Pointer to environment variable contents. */
2956 ptr = getenv(dk3app_no_loc[11]);
2957 if(ptr) {
2958 if(dk3str_c8_len(ptr) < sz) {
2959 dk3str_c8_cpy_not_overlapped(db, ptr);
2960 back = 1;
2961 } else {
2962 dk3app_log_i1(app, DK3_LL_ERROR, 39);
2963 }
2964 }
2965 }
2966 #else
2967 DK3_UNUSED_ARG(app)
2968 #endif
2969 #endif
2970
2971 return back;
2972 }
2973
2974
2975
2976 /** Find language, region and encoding.
2977 @param app Application structure.
2978 */
2979 static
2980 void
dk3app_language_and_region(dk3_app_t * app)2981 dk3app_language_and_region(dk3_app_t *app)
2982 {
2983 dkChar buffer[DK3_MAX_PATH]; /* Buffer to store language/region name. */
2984 dkChar *ptr; /* Used to find region. */
2985 dkChar *p2; /* Used to convert to lower characters. */
2986
2987 if(dk3app_get_language_string(app, buffer, DK3_SIZEOF(buffer,dkChar))) {
2988 app->n_langstr = dk3str_dup_app(buffer, NULL);
2989 if(app->n_langstr) {
2990 ptr = dk3str_chr(buffer, dkT('.'));
2991 if(ptr) {
2992 *(ptr++) = dkT('\0');
2993 #if DK3_CHAR_SIZE == 1
2994 if(dk3str_casecmp(ptr, dk3app_no_loc[15]) == 0) {
2995 app->i_encoding = DK3_ENCODING_UTF8;
2996 app->i_output_encoding = DK3_FILE_ENCODING_UTF8;
2997 }
2998 if(dk3str_casecmp(ptr, dk3app_no_loc[16]) == 0) {
2999 app->i_encoding = DK3_ENCODING_UTF8;
3000 app->i_output_encoding = DK3_FILE_ENCODING_UTF8;
3001 }
3002 #endif
3003 }
3004 ptr = dk3str_chr(buffer, dkT('_'));
3005 #if DK3_ON_WINDOWS
3006 if(!(ptr)) { ptr = dk3str_chr(buffer, dkT('-')); }
3007 #endif
3008 if(ptr) {
3009 *(ptr++) = dkT('\0');
3010 p2 = ptr; while(*p2) { *p2 = dk3str_tolower(*p2); p2++; }
3011 app->n_region = dk3str_dup_app(ptr, NULL);
3012 if(!(app->n_region)) {
3013 app->de = 29;
3014 }
3015 }
3016 if(!(app->de)) {
3017 p2 = buffer; while(*p2) { *p2 = dk3str_tolower(*p2); p2++; }
3018 app->n_language = dk3str_dup_app(buffer, NULL);
3019 if(!(app->n_language)) {
3020 app->de = 30;
3021 }
3022 }
3023 } else {
3024 app->de = 28;
3025 }
3026 }
3027 }
3028
3029
3030
3031 /** Check whether a directory name is a root directory.
3032 @param dirname Directory name to check.
3033 @return 1 for root directory, 0 for others.
3034 */
3035 static
3036 int
dk3app_is_root_directory(dkChar const * dirname)3037 dk3app_is_root_directory(dkChar const *dirname)
3038 {
3039 int back = 0;
3040 #if DK3_ON_WINDOWS
3041 size_t sz;
3042 sz = dk3str_len(dirname);
3043 if(1 == sz) {
3044 if(dkT('\\') == dirname[0]) {
3045 back = 1;
3046 }
3047 } else {
3048 if(3 == sz) {
3049 if((dkT('a') <= dirname[0]) && (dkT('z') >= dirname[0])) {
3050 back = 1;
3051 } else {
3052 if((dkT('A') <= dirname[0]) && (dkT('Z') >= dirname[0])) {
3053 back = 1;
3054 }
3055 }
3056 if(back) {
3057 back = 0;
3058 if(dkT(':') == dirname[1]) {
3059 if(dkT('\\') == dirname[2]) {
3060 back = 1;
3061 }
3062 }
3063 }
3064 }
3065 }
3066 #else
3067 if(dk3str_len(dirname) == 1) {
3068 if(dkT('/') == dirname[0]) {
3069 back = 1;
3070 }
3071 }
3072 #endif
3073 return back;
3074 }
3075
3076
3077
3078 /** Reduce a directory name referring to a bin (or sbin or libexec/xxx
3079 directory.
3080 @param dirname Directory name to modify.
3081 @return 1 on success, 0 on error.
3082 */
3083 static
3084 int
dk3app_reduce_bindir_name(dkChar * dirname)3085 dk3app_reduce_bindir_name(dkChar *dirname)
3086 {
3087 dkChar buffer[DK3_MAX_PATH];
3088 dkChar *pCurrent; /* Current path component. */
3089 dkChar *pPrevious; /* Previous path component. */
3090 size_t sz;
3091 int ai; /* Array index. */
3092 int cc; /* Flag: Can continue. */
3093 int back = 0;
3094
3095 if(dk3str_len(dirname) < DK3_SIZEOF(buffer,dkChar)) {
3096 dk3str_cpy_not_overlapped(buffer, dirname);
3097 pCurrent = NULL; pPrevious = NULL;
3098 cc = 1;
3099 while(cc) {
3100 cc = 0;
3101 if(dk3str_len(buffer) > 1) {
3102 if(!dk3app_is_root_directory(buffer)) {
3103 pCurrent = dk3str_rchr(buffer, DK3_CHAR_SEP);
3104 if(pCurrent) {
3105 cc = 1;
3106 #if DK3_ON_WINDOWS
3107 ai = dk3str_array_index(dk3app_bindir_candidates,&(pCurrent[1]),0);
3108 #else
3109 ai = dk3str_array_index(dk3app_bindir_candidates,&(pCurrent[1]),1);
3110 #endif
3111 if(-1 < ai) {
3112 cc = 0;
3113 sz = dk3str_len(buffer);
3114 dirname[sz] = dkT('\0');
3115 back = 1;
3116 } else {
3117 if(pPrevious) { *pPrevious = DK3_CHAR_SEP; }
3118 pPrevious = pCurrent;
3119 *pCurrent = dkT('\0');
3120 }
3121 }
3122 }
3123 }
3124 }
3125 }
3126 return back;
3127 }
3128
3129
3130
3131 /** Find all the names. Set app->de on errors, don't report directly.
3132 @param app Application to configure.
3133 @param wd Current working directory.
3134 @param argv Command line arguments array.
3135 */
3136 static
3137 void
dk3app_find_names(dk3_app_t * app,dkChar const * wd,dkChar const * const * argv)3138 dk3app_find_names(
3139 dk3_app_t *app, dkChar const *wd,
3140 dkChar const * const *argv
3141 )
3142 {
3143 int must_relocate = 0; /* Flag: Must relocate. */
3144 int redres; /* Result from reduce directory. */
3145 #if DK3_HAVE_UMASK
3146 mode_t oldumask; /* Umask before mkdir. */
3147 #endif
3148 dkChar *n_app = NULL; /* Application name. */
3149 dkChar *p = NULL; /* Modify application name. */
3150 dkChar const *q = NULL; /* Installation bin directory. */
3151 dkChar *x = NULL; /* Deal with executable name. */
3152 dkChar buffer[DK3_MAX_PATH]; /* Used to construct file names. */
3153 char pidbuffer[128]; /* Buffer for PID number (8-bit). */
3154 dkChar dkpidbuffer[128]; /* Buffer for PID number. */
3155 size_t tsl = 0; /* Buffer size needed. */
3156
3157 p = dk3str_rchr(argv[0], DK3_CHAR_SEP);
3158 if(p) { p++; } else { p = (dkChar *)(argv[0]); }
3159 n_app = dk3str_dup_app(p, NULL);
3160 if(n_app) {
3161 app->n_app = (dkChar const *)n_app;
3162 p = dk3str_chr(n_app, DK3_CHAR_DOT);
3163 if(p) { *p = DK3_CHAR_0; }
3164 if(dk3sf_find_exec_app(buffer,DK3_SIZEOF(buffer,dkChar),wd,argv[0], NULL)) {
3165 x = dk3str_dup_app(buffer, NULL);
3166 app->n_execfile = x;
3167 if(app->n_execfile) {
3168 p = dk3str_rchr(buffer, DK3_CHAR_SEP);
3169 if(p) {
3170 *p = DK3_CHAR_0;
3171 app->n_bindir = dk3str_dup_app(buffer, NULL);
3172 if(app->n_bindir) {
3173 redres = dk3app_reduce_bindir_name(buffer);
3174 q = dk3inst_get_directory(DK3_INST_BIN);
3175 if(dk3str_fncmp(buffer, q)) {
3176 q = dk3inst_get_directory(DK3_INST_SBIN);
3177 if(dk3str_fncmp(buffer, q)) {
3178 q = dk3inst_get_directory(DK3_INST_LIB);
3179 if(dk3str_fncmp(buffer, q)) {
3180 q = dk3inst_get_directory(DK3_INST_LIBEXEC);
3181 if(dk3str_fncmp(buffer, q)) {
3182 must_relocate = 1;
3183 }
3184 }
3185 }
3186 }
3187 if(must_relocate) {
3188 p = dk3str_rchr(buffer, DK3_CHAR_SEP);
3189 if(p) {
3190 p++;
3191 if(redres) {
3192 *p = DK3_CHAR_0;
3193 tsl = dk3str_len(buffer);
3194 tsl += dk3str_len(dk3app_no_loc[1]);
3195 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3196 dk3str_cpy_not_overlapped(p, dk3app_no_loc[1]);
3197 app->n_etcdir = dk3str_dup_app(buffer, NULL);
3198 if(app->n_etcdir) {
3199 *p = DK3_CHAR_0;
3200 tsl = dk3str_len(buffer);
3201 tsl += dk3str_len(dk3app_no_loc[2]);
3202 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3203 dk3str_cpy_not_overlapped(p, dk3app_no_loc[2]);
3204 app->n_sharedir = dk3str_dup_app(buffer, NULL);
3205 if(app->n_sharedir) {
3206 *p = DK3_CHAR_0;
3207 tsl = dk3str_len(buffer);
3208 tsl += dk3str_len(dk3app_no_loc[3]);
3209 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3210 dk3str_cpy_not_overlapped(p, dk3app_no_loc[3]);
3211 app->n_vardir = dk3str_dup_app(buffer, NULL);
3212 if(!(app->n_vardir)) {
3213 app->de = 9;
3214 }
3215 } else {
3216 app->de = 13;
3217 }
3218 } else {
3219 app->de = 8;
3220 }
3221 } else {
3222 app->de = 12;
3223 }
3224 } else {
3225 app->de = 7;
3226 }
3227 } else {
3228 app->de = 11;
3229 }
3230 } else {
3231 dk3app_copy_bin_to_others(app);
3232 }
3233 } else {
3234 dk3app_copy_bin_to_others(app);
3235 }
3236 } else {
3237 q = dk3inst_get_directory(DK3_INST_SYSCONF);
3238 app->n_etcdir = dk3str_dup_app(q, NULL);
3239 if(app->n_etcdir) {
3240 q = dk3inst_get_directory(DK3_INST_DATAROOT);
3241 app->n_sharedir = dk3str_dup_app(q, NULL);
3242 if(app->n_sharedir) {
3243 q = dk3inst_get_directory(DK3_INST_LOCALSTATE);
3244 app->n_vardir = dk3str_dup_app(q, NULL);
3245 if(!(app->n_vardir)) {
3246 app->de = 9;
3247 }
3248 } else {
3249 app->de = 8;
3250 }
3251 } else {
3252 app->de = 7;
3253 }
3254 }
3255 if(!(app->de)) {
3256 if(dk3sf_get_logname_app(buffer,DK3_SIZEOF(buffer,dkChar),NULL)) {
3257 app->n_logname = dk3str_dup_app(buffer,NULL);
3258 if(!(app->n_logname)) {
3259 app->de = 15;
3260 }
3261 } else {
3262 app->de = 14;
3263 }
3264 }
3265 if(!(app->de)) {
3266 if(dk3sf_get_hostname_app(buffer,DK3_SIZEOF(buffer,dkChar),NULL))
3267 {
3268 app->n_hostname = dk3str_dup_app(buffer, NULL);
3269 if(!(app->n_hostname)) {
3270 app->de = 37;
3271 }
3272 } else {
3273 app->de = 38;
3274 }
3275 }
3276 if(!(app->de)) {
3277 if(dk3sf_get_home_app(buffer,DK3_SIZEOF(buffer,dkChar), NULL)) {
3278 app->n_homedir = dk3str_dup_app(buffer,NULL);
3279 if(!(app->n_homedir)) {
3280 app->de = 17;
3281 }
3282 } else {
3283 app->de = 16;
3284 }
3285 }
3286 if(!(app->de)) {
3287 switch(app->app_type) {
3288 case DK3_APP_TYPE_COMMAND:
3289 case DK3_APP_TYPE_GUI: {
3290 tsl = dk3str_len(app->n_homedir);
3291 tsl += dk3str_len(dk3app_no_loc[4]);
3292 tsl += dk3str_len(dk3app_no_loc[20]);
3293 tsl += dk3str_len(app->n_app);
3294 tsl += dk3str_len(dk3app_no_loc[5]);
3295 (void)dk3ma_um_to_c8_string(
3296 pidbuffer, sizeof(pidbuffer), dk3sf_getpid()
3297 );
3298 if(dk3str_cnv_c8_to_str_app(
3299 dkpidbuffer, DK3_SIZEOF(dkpidbuffer,dkChar),
3300 pidbuffer, NULL
3301 )
3302 )
3303 {
3304 tsl += dk3str_len(dkpidbuffer);
3305 tsl += dk3str_len(dk3app_no_loc[6]);
3306 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3307 dk3str_cpy_not_overlapped(buffer, app->n_homedir);
3308 dk3str_cat(buffer, dk3app_no_loc[4]);
3309 dk3str_correct_filename(buffer);
3310
3311 #if VERSION_BEFORE_20160128
3312 if(dk3sf_mkdir_app(buffer, 0700, NULL)) {
3313 dk3str_cat(buffer, dk3app_no_loc[20]);
3314 dk3str_cat(buffer, app->n_app);
3315 dk3str_cat(buffer, dk3app_no_loc[5]);
3316 dk3str_cat(buffer, dkpidbuffer);
3317 dk3str_cat(buffer, dk3app_no_loc[6]);
3318 dk3str_correct_filename(buffer);
3319 app->n_logfilename = dk3str_dup_app(buffer,NULL);
3320 if(!(app->n_logfilename)) {
3321 app->de = 21;
3322 }
3323 } else {
3324 app->de = 20;
3325 }
3326 #else
3327 /* 2016-01-28
3328 Do not immediately create the log directory
3329 for non-daemon programs.
3330 */
3331 dk3str_cat(buffer, dk3app_no_loc[20]);
3332 dk3str_cat(buffer, app->n_app);
3333 dk3str_cat(buffer, dk3app_no_loc[5]);
3334 dk3str_cat(buffer, dkpidbuffer);
3335 dk3str_cat(buffer, dk3app_no_loc[6]);
3336 dk3str_correct_filename(buffer);
3337 app->n_logfilename = dk3str_dup_app(buffer,NULL);
3338 if(!(app->n_logfilename)) {
3339 app->de = 21;
3340 }
3341 #endif
3342 } else {
3343 app->de = 19;
3344 }
3345 } else {
3346 app->de = 22;
3347 }
3348 } break;
3349 case DK3_APP_TYPE_DAEMON: {
3350 tsl = dk3str_len(app->n_vardir);
3351 tsl += dk3str_len(dk3app_no_loc[4]);
3352 tsl += dk3str_len(dk3app_no_loc[20]);
3353 tsl += dk3str_len(app->n_app);
3354 tsl += dk3str_len(dk3app_no_loc[20]);
3355 tsl += dk3str_len(app->n_app);
3356 tsl += dk3str_len(dk3app_no_loc[6]);
3357 #if DK3_HAVE_UMASK
3358 oldumask = umask(0);
3359 #endif
3360 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3361 dk3str_cpy_not_overlapped(buffer, app->n_vardir);
3362 dk3str_cat(buffer, dk3app_no_loc[4]);
3363
3364 if(dk3sf_mkdir_app(buffer, 0755, NULL)) {
3365 dk3str_cat(buffer, dk3app_no_loc[20]);
3366 dk3str_cat(buffer, app->n_app);
3367
3368 if(dk3sf_mkdir_app(buffer, 0755, NULL)) {
3369 app->cr_log = 1;
3370 dk3str_cat(buffer, dk3app_no_loc[20]);
3371 dk3str_cat(buffer, app->n_app);
3372 dk3str_cat(buffer, dk3app_no_loc[6]);
3373 app->n_logfilename = dk3str_dup_app(buffer, NULL);
3374 if(!(app->n_logfilename)) {
3375 app->de = 21;
3376 }
3377 } else {
3378 app->de = 20;
3379 }
3380 } else {
3381 app->de = 20;
3382 }
3383 } else {
3384 app->de = 19;
3385 }
3386 #if DK3_HAVE_UMASK
3387 umask(oldumask);
3388 #endif
3389 } break;
3390 }
3391 }
3392 if(!(app->de)) {
3393 switch(app->app_type) {
3394 case DK3_APP_TYPE_DAEMON: {
3395 if(app->n_vardir) {
3396 if(app->n_app) {
3397
3398 (void)dk3ma_um_to_c8_string(
3399 pidbuffer, sizeof(pidbuffer), dk3sf_getpid()
3400 );
3401 if(dk3str_cnv_c8_to_str_app(
3402 dkpidbuffer, DK3_SIZEOF(dkpidbuffer,dkChar),
3403 pidbuffer, NULL
3404 )
3405 )
3406 {
3407 tsl = dk3str_len(app->n_vardir);
3408 tsl += dk3str_len(dk3app_no_loc[10]);
3409 tsl += dk3str_len(dk3app_no_loc[20]);
3410 tsl += dk3str_len(app->n_app);
3411 tsl += dk3str_len(dk3app_no_loc[20]);
3412 tsl += dk3str_len(dkpidbuffer);
3413 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3414 dk3str_cpy_not_overlapped(buffer, app->n_vardir);
3415 dk3str_cat(buffer, dk3app_no_loc[10]);
3416 dk3str_correct_filename(buffer);
3417
3418 (void)dk3sf_mkdir_app(buffer,0700,NULL);
3419 dk3str_cat(buffer, dk3app_no_loc[20]);
3420 dk3str_cat(buffer, app->n_app);
3421 dk3str_correct_filename(buffer);
3422
3423 (void)dk3sf_mkdir_app(buffer,0700,NULL);
3424 dk3str_cat(buffer, dk3app_no_loc[20]);
3425 dk3str_cat(buffer, dkpidbuffer);
3426
3427
3428 if(dk3sf_mkdir_app(buffer,0700,NULL)) {
3429 app->cr_tmp = 1;
3430 app->n_tmpdir = dk3str_dup_app(buffer, NULL);
3431 if(!(app->n_tmpdir)) {
3432 app->de = 25;
3433 dk3sf_remove_dir_app(buffer, NULL);
3434 }
3435 } else {
3436 app->de = 26;
3437 }
3438 } else {
3439 app->de = 19;
3440 }
3441 } else {
3442 app->de = 22;
3443 }
3444 } else {
3445 app->de = 24;
3446 }
3447 } else {
3448 app->de = 27;
3449 }
3450 } break;
3451 default: {
3452 if(app->n_homedir) {
3453 if(app->n_app) {
3454 (void)dk3ma_um_to_c8_string(
3455 pidbuffer, sizeof(pidbuffer), dk3sf_getpid()
3456 );
3457 if(dk3str_cnv_c8_to_str_app(
3458 dkpidbuffer, DK3_SIZEOF(dkpidbuffer,dkChar),
3459 pidbuffer, NULL
3460 )
3461 )
3462 {
3463 tsl = dk3str_len(app->n_homedir);
3464 tsl += dk3str_len(dk3app_no_loc[9]);
3465 tsl += dk3str_len(dk3app_no_loc[20]);
3466 tsl += dk3str_len(app->n_app);
3467 tsl += dk3str_len(dk3app_no_loc[5]);
3468 tsl += dk3str_len(dkpidbuffer);
3469 if(tsl < DK3_SIZEOF(buffer,dkChar)) {
3470 dk3str_cpy_not_overlapped(buffer, app->n_homedir);
3471 dk3str_cat(buffer, dk3app_no_loc[9]);
3472 dk3str_correct_filename(buffer);
3473 #if VERSION_BEFORE_20160128
3474
3475 if(dk3sf_mkdir_app(buffer,0700,NULL)) {
3476 dk3str_cat(buffer, dk3app_no_loc[20]);
3477 dk3str_cat(buffer, app->n_app);
3478 dk3str_cat(buffer, dk3app_no_loc[5]);
3479 dk3str_cat(buffer, dkpidbuffer);
3480 dk3str_correct_filename(buffer);
3481 #if VERSION_BEFORE_20150318
3482
3483 if(dk3sf_mkdir_app(buffer,0700,NULL)) {
3484 app->n_tmpdir = dk3str_dup_app(buffer, NULL);
3485 if(!(app->n_tmpdir)) {
3486 app->de = 25;
3487 dk3sf_remove_dir_app(buffer, NULL);
3488 }
3489 } else {
3490 app->de = 26;
3491 }
3492 #else
3493 app->n_tmpdir = dk3str_dup_app(buffer, NULL);
3494 if(!(app->n_tmpdir)) {
3495 app->de = 25;
3496 }
3497 #endif
3498 } else {
3499 app->de = 26;
3500 }
3501 #else
3502 /* if VERSION_BEFORE_20160128 */
3503 dk3str_cat(buffer, dk3app_no_loc[20]);
3504 dk3str_cat(buffer, app->n_app);
3505 dk3str_cat(buffer, dk3app_no_loc[5]);
3506 dk3str_cat(buffer, dkpidbuffer);
3507 dk3str_correct_filename(buffer);
3508 app->n_tmpdir = dk3str_dup_app(buffer, NULL);
3509 if(!(app->n_tmpdir)) {
3510 app->de = 25;
3511 }
3512 #endif
3513 /* if VERSION_BEFORE_20160128 */
3514 } else {
3515 app->de = 19;
3516 }
3517 } else {
3518 app->de = 22;
3519 }
3520 } else {
3521 app->de = 24;
3522 }
3523 } else {
3524 app->de = 23;
3525 }
3526 } break;
3527 }
3528 }
3529 } else {
3530 app->de = 6;
3531 }
3532 } else {
3533 app->de = 5;
3534 }
3535 } else {
3536 app->de = 4;
3537 }
3538 } else {
3539 app->de = 3;
3540 }
3541 } else {
3542 app->de = 2;
3543 }
3544 }
3545
3546
3547
3548 /** Test whether a configuration file name candidate is valid.
3549 @param app Application structure.
3550 @param fn File name.
3551 @param db Destination buffer.
3552 @param sz Size of \a db (number of characters).
3553 @param passno Pass number.
3554 @param verb Flag: Diagnostic messages enabled.
3555 @return 1 on success, 0 on error.
3556 */
3557 static
3558 int
dk3app_check_config_file(dk3_app_t * app,dkChar const * fn,dkChar * db,size_t sz,int passno,int verb)3559 dk3app_check_config_file(
3560 dk3_app_t *app, dkChar const *fn, dkChar *db, size_t sz, int passno, int verb
3561 )
3562 {
3563 int back = 0;
3564 dk3_stat_t stb; /* Stat buffer used to check existance of files. */
3565
3566 if(dk3app_config_name(app, fn, db, sz, passno, verb)) {
3567 if(dk3sf_stat_app(&stb, db, NULL)) {
3568 switch((stb.ft) & (~(DK3_FT_SYMLINK))) {
3569 case DK3_FT_REGULAR: { back = 1; } break;
3570 }
3571 }
3572 if(back) {
3573 /* DEBUG Config file ... found. */
3574 dk3app_log_i3(app, DK3_LL_DEBUG, 152, 153, db);
3575 } else {
3576 /* DEBUG Config file ... not found. */
3577 dk3app_log_i3(app, DK3_LL_DEBUG, 154, 155, db);
3578 }
3579 }
3580 return back;
3581 }
3582
3583
3584
3585 /** Add preference key/value entry to storage.
3586 Check whether an entry for the key already exists.
3587 @param app Application structure for diagnostics, may be NULL.
3588 @param s Storage.
3589 @param i Storage iterator.
3590 @param k Preference key.
3591 @param v Preference value.
3592 */
3593 static
3594 int
dk3app_add_pref(dk3_app_t * app,dk3_sto_t * s,dk3_sto_it_t * i,dkChar const * k,dkChar const * v)3595 dk3app_add_pref(
3596 dk3_app_t *app, dk3_sto_t *s, dk3_sto_it_t *i,
3597 dkChar const *k, dkChar const *v
3598 )
3599 {
3600 int back = 0;
3601 dk3app_pref_t p; /* Preference search. */
3602 dk3app_pref_t *pref = NULL; /* Existing preference for name. */
3603 dkChar *nv = NULL; /* New value string for preference. */
3604
3605 p.k = k; p.v = v;
3606 pref = (dk3app_pref_t *)dk3sto_it_find_like(i, &p, 0);
3607 if(pref) {
3608 nv = dk3str_dup_app(v, NULL);
3609 if(nv) {
3610 dk3_delete(pref->v);
3611 pref->v = nv;
3612 back = 1;
3613 } else {
3614 if(app) {
3615 dk3app_log_i1(app, DK3_LL_ERROR, 9);
3616 }
3617 }
3618 } else {
3619 pref = dk3app_pref_new(k, v);
3620 if(pref) {
3621 if(dk3sto_add(s, pref)) {
3622 back = 1;
3623 } else {
3624 if(app) {
3625 dk3app_log_i1(app, DK3_LL_ERROR, 9);
3626 }
3627 dk3app_pref_delete(pref); pref = NULL;
3628 }
3629 } else {
3630 if(app) {
3631 dk3app_log_i1(app, DK3_LL_ERROR, 9);
3632 }
3633 }
3634 }
3635 return back;
3636 }
3637
3638
3639
3640 /** Save one preference entry.
3641 Do not report problems directly, set app->de instead.
3642 @param app Application structure.
3643 @param pt Preference text.
3644 */
3645 static
3646 void
dk3app_save_one_preference(dk3_app_t * app,dkChar const * pt)3647 dk3app_save_one_preference(dk3_app_t *app, dkChar const *pt)
3648 {
3649 dkChar b[DK3_MAX_PATH]; /* Buffer for input line. */
3650 dkChar *p1 = NULL; /* Value position. */
3651
3652 if(dk3str_len(pt) < DK3_SIZEOF(b,dkChar)) {
3653 dk3str_cpy_not_overlapped(b, pt);
3654 p1 = dk3str_chr(b, dkT('='));
3655 if(p1) {
3656 *(p1++) = dkT('\0');
3657 p1 = dk3str_start(p1, NULL);
3658 if(p1) {
3659 dk3str_chomp(b, NULL);
3660 dk3str_chomp(p1, NULL);
3661 if(!(app->s_cmdprefs)) {
3662 app->s_cmdprefs = dk3sto_open_app(NULL);
3663 if(app->s_cmdprefs) {
3664 dk3sto_set_comp(app->s_cmdprefs, dk3app_compare_pref, 0);
3665 } else {
3666 app->de = 36;
3667 }
3668 }
3669 if(!(app->i_cmdprefs)) {
3670 if(app->s_cmdprefs) {
3671 app->i_cmdprefs = dk3sto_it_open(app->s_cmdprefs);
3672 } else {
3673 app->de = 35;
3674 }
3675 }
3676 if((app->s_cmdprefs) && (app->i_cmdprefs)) {
3677 if(!dk3app_add_pref(NULL,app->s_cmdprefs,app->i_cmdprefs,b,p1)) {
3678 app->de = 33;
3679 }
3680 }
3681 } else {
3682 app->de = 32;
3683 }
3684 } else {
3685 app->de = 32;
3686 }
3687 } else {
3688 app->de = 31;
3689 }
3690 }
3691
3692
3693
3694 /** Set application to silent mode if --/silent=yes was
3695 provided as command line argument.
3696 @param app Application structure.
3697 */
3698 static
3699 void
dk3app_first_set_silent(dk3_app_t * app)3700 dk3app_first_set_silent(dk3_app_t *app)
3701 {
3702 app->ll_stderr = DK3_LL_NONE;
3703 switch(app->app_type) {
3704 case DK3_APP_TYPE_COMMAND: {
3705 app->app_type = DK3_APP_TYPE_SILENT;
3706 } break;
3707 }
3708 }
3709
3710
3711
3712 int
dk3app_first_silence_check(dk3_app_t * app,int argc,dkChar const * const * argv)3713 dk3app_first_silence_check(dk3_app_t *app, int argc, dkChar const * const *argv)
3714 {
3715 int back = 0;
3716 int i; /* Index of current argument. */
3717 dkChar const * const *lfdptr; /* Pointer to traverse arguments. */
3718 dkChar const *ptr; /* Current argument. */
3719 dkChar buffer[2 * DK3_MAX_PATH]; /* Local copy. */
3720 dkChar *p1; /* Option keyword. */
3721 dkChar *p2; /* Option argument. */
3722
3723 lfdptr = argv; lfdptr++; i = 1;
3724 while(i < argc) {
3725 ptr = *lfdptr;
3726 if(*ptr == dkT('-')) {
3727 ptr++;
3728 if(*ptr == dkT('-')) {
3729 ptr++;
3730 if(dk3str_len(ptr) < DK3_SIZEOF(buffer,dkChar)) {
3731 dk3str_cpy_not_overlapped(buffer, ptr);
3732 p1 = dk3str_start(buffer, NULL);
3733 if(p1) {
3734 p2 = dk3str_chr(p1, dkT('='));
3735 if(p2) {
3736 *(p2++) = dkT('\0');
3737 p2 = dk3str_start(p2, NULL);
3738 }
3739 if(dk3str_cmp(dk3app_no_loc[50], p1) == 0) {
3740 if(p2) {
3741 if(dk3str_is_on(p2)) {
3742 back = 1;
3743 if(app) { dk3app_first_set_silent(app); }
3744 }
3745 } else {
3746 back = 1;
3747 if(app) { dk3app_first_set_silent(app); }
3748 }
3749 }
3750 }
3751 } else {
3752 /* ERROR: Too long! */
3753 }
3754 }
3755 }
3756 lfdptr++; i++;
3757 }
3758 return back;
3759 }
3760
3761
3762
3763 /** Save command line arguments for later use.
3764 Don't report errors directly, set app->de instead.
3765 @param app Application structure.
3766 @param argc Number of command line arguments.
3767 @param argv Command line arguments array.
3768 */
3769 static
3770 void
dk3app_save_arguments(dk3_app_t * app,int argc,dkChar const * const * argv)3771 dk3app_save_arguments(dk3_app_t *app, int argc, dkChar const * const *argv)
3772 {
3773 int myargc = 0; /* Number of options used. */
3774 dkChar const **myargv = NULL; /* Private copy of options. */
3775 dkChar const **ptr = NULL; /* Traverse myargv. */
3776 dkChar const * const *sptr = NULL; /* Traverse original argv. */
3777 dkChar const *tptr = NULL; /* String tests in sptr. */
3778 int ispref = 0; /* Flag: Is a preference. */
3779 int i = 0; /* Index of current argv. */
3780
3781 myargv = dk3_new_app(DK3_PCDKCHAR,(argc+1),app);
3782 if(myargv) {
3783 ptr = myargv;
3784 for(i = 0; i < (argc + 1); i++) { *(ptr++) = NULL; }
3785 ptr = myargv; myargc = 0; sptr = argv;
3786 for(i = 0; i < argc; i++) {
3787 tptr = *(sptr++);
3788 ispref = 0;
3789 if(*tptr == DK3_CHAR_MINUS) {
3790 if(tptr[1] == DK3_CHAR_MINUS) {
3791 if(tptr[2] == DK3_CHAR_SLASH) {
3792 ispref = 1;
3793 }
3794 }
3795 }
3796 if(ispref) {
3797 dk3app_save_one_preference(app, &(tptr[2]));
3798 } else {
3799 *ptr = dk3str_dup_app(tptr, NULL);
3800 if(*ptr) {
3801 myargc++;
3802 ptr++;
3803 } else {
3804 app->de = 1;
3805 }
3806 }
3807 }
3808 app->argc = myargc; app->argv = myargv;
3809 }
3810 }
3811
3812
3813
3814 /** Save application group name.
3815 @param app Application structure.
3816 @param gn Group name to save.
3817 */
3818 static
3819 void
dk3app_save_group_name(dk3_app_t * app,dkChar const * gn)3820 dk3app_save_group_name(dk3_app_t *app, dkChar const *gn)
3821 {
3822
3823 app->n_appgroup = dk3str_dup_app(gn,NULL);
3824 if(!(app->n_appgroup)) {
3825 app->de = 18;
3826 }
3827 }
3828
3829
3830
3831 /** Retrieve preferences from a storage.
3832 @param app Application structure for diagnostics, may be NULL.
3833 @param p Storage iterator.
3834 @param k Key (preference name).
3835 @param d Destination buffer.
3836 @param s Size of \a d (number of characters).
3837 @return 1 on success, 0 on error.
3838 */
3839 static
3840 int
dk3app_sto_pref(dk3_app_t * app,dk3_sto_it_t * p,dkChar const * k,dkChar * d,size_t s)3841 dk3app_sto_pref(
3842 dk3_app_t *app, dk3_sto_it_t *p, dkChar const *k, dkChar *d, size_t s)
3843 {
3844 int back = 0;
3845 dk3app_pref_t pr; /* Used for comparisons in search. */
3846 dk3app_pref_t *pref = NULL; /* Entry found. */
3847
3848 if(p) {
3849 pr.k = k; pr.v = NULL;
3850 pref = (dk3app_pref_t *)dk3sto_it_find_like(p, &pr, 0);
3851 if(pref) {
3852 if(pref->v) {
3853 if(dk3str_len(pref->v) < s) {
3854 dk3str_cpy_not_overlapped(d, pref->v);
3855 back = 1;
3856 } else {
3857 if(app) {
3858 /* Destination buffer too short! */
3859 dk3app_log_i1(app, DK3_LL_ERROR, 38);
3860 }
3861 }
3862 }
3863 }
3864 }
3865 return back;
3866 }
3867
3868
3869
3870 /** Find number of entries for a string table file.
3871 @param dv String table value array.
3872 @return Number of entries in array, including final NULL entry.
3873 */
3874 static
3875 size_t
dk3app_mc_array_size(dkChar const * const * dv)3876 dk3app_mc_array_size(dkChar const * const *dv)
3877 {
3878 size_t back = 0;
3879 dkChar const * const *ptr = NULL; /* Traverse the dv array. */
3880
3881 if(dv) {
3882 ptr = dv;
3883 while(*(ptr++)) { back++; }
3884 back++;
3885 }
3886 return back;
3887 }
3888
3889
3890
3891 void
dk3app_squeeze_line(char * lb)3892 dk3app_squeeze_line(char *lb)
3893 {
3894 char *pd = NULL; /* Destination in copy operations. */
3895 char *ps = NULL; /* Source in copy operations. */
3896 char *px = NULL; /* Position to continue. */
3897 ps = lb;
3898
3899 /* Remove trailing newline. */
3900 while(*ps) {
3901 if((*ps == '\r') || (*ps == '\n')) {
3902 *ps = '\0';
3903 } else {
3904 ps++;
3905 }
3906 }
3907 /* Correct escape sequences */
3908 ps = lb;
3909 while(*ps) {
3910 if(*ps == '\\') {
3911 px = pd = ps; ps++;
3912 if(*ps) {
3913 switch(*ps) {
3914 case 't': {
3915 *(pd++) = '\t'; ps++;
3916 dk3str_c8_cpy(pd, ps);
3917 } break;
3918 case 'n': {
3919 *(pd++) = '\n'; ps++;
3920 dk3str_c8_cpy(pd, ps);
3921 } break;
3922 case 'r': {
3923 *(pd++) = '\r'; ps++;
3924 dk3str_c8_cpy(pd, ps);
3925 } break;
3926 default: {
3927 dk3str_c8_cpy(pd, ps);
3928 } break;
3929 }
3930 ps = px; ps++;
3931 }
3932 } else {
3933 ps++;
3934 }
3935 }
3936 }
3937
3938
3939
3940 /** Get message catalog contents.
3941 @param app Application structure.
3942 @param fn File name for message catalog.
3943 @param dv Default values.
3944 @param verb Flag: Diagnostics enabled.
3945 @return Pointer to message array.
3946 */
3947 static
3948 dkChar const * const *
dk3app_my_messages(dk3_app_t * app,dkChar const * fn,dkChar const * const * dv,int verb)3949 dk3app_my_messages(
3950 dk3_app_t *app, dkChar const *fn, dkChar const * const *dv, int verb
3951 )
3952 {
3953 dkChar const * const *back = NULL;
3954 dkChar const *source_file = NULL; /* File name for source file. */
3955 dk3app_mc_t mc; /* Used for comparisons. */
3956 dk3app_mc_t *mcptr = NULL; /* Message catalog. */
3957 int errors_occured = 0; /* Flag: We had errors. */
3958 unsigned long source_line = 0UL; /* Number of source line. */
3959 unsigned long line_number = 0UL; /* NUmber of current line. */
3960 size_t sz_defaults = 0; /* Number entries in default table. */
3961 size_t i = 0; /* Walk through table. */
3962 size_t current_index = 0; /* Index of current entry to process. */
3963 dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */
3964 char lb[4096]; /* Input line (8-bit characters). */
3965 dkChar const **rb = NULL; /* Array of strings to return. */
3966 FILE *fipo; /* Input file. */
3967
3968 if((app) && (fn) && (dv)) {
3969 /* Find array size. */
3970 sz_defaults = dk3app_mc_array_size(dv);
3971 if(sz_defaults) {
3972 if((app->s_mc) && (app->i_mc)) {
3973 mc.n = fn; mc.msg = NULL; mc.f = 0; mc.nmsg = sz_defaults;
3974 mcptr = (dk3app_mc_t *)dk3sto_it_find_like(app->i_mc, &mc, 0);
3975 if(mcptr) {
3976 if(mcptr->nmsg >= sz_defaults) {
3977 back = mcptr->msg;
3978 } else {
3979 errors_occured = 1; /* Too short */
3980 }
3981 } else {
3982 }
3983 } else {
3984 }
3985 if((!(back)) && (errors_occured == 0)) {
3986 if(dk3app_my_find_data_file(app, fn, fnb, DK3_MAX_PATH, verb)) {
3987 source_file = dk3app_get_source_file(app);
3988 source_line = dk3app_get_source_line(app);
3989 dk3app_set_source_file(app, fnb);
3990 dk3app_set_source_line(app, 0UL);
3991 /* UTF8 */ fipo = dk3sf_fopen_app(fnb, dk3app_no_loc[22], (verb ? app : NULL));
3992 if(fipo) {
3993 rb = dk3_new_app(DK3_PCDKCHAR,sz_defaults,(verb ? app : NULL));
3994 if(rb) {
3995 for(i = 0; i < sz_defaults; i++) { rb[i] = NULL; }
3996 current_index = 0;
3997 /* We explicitly used 8-bit characters, the file is UTF-8 */
3998 while(fgets(lb, sizeof(lb), fipo)) {
3999 line_number++;
4000 dk3app_set_source_line(app, line_number);
4001 if(lb[0] != '#') {
4002 dk3app_squeeze_line(lb);
4003 if(current_index < (sz_defaults - 1)) {
4004 #if DK3_CHAR_SIZE > 1
4005 #if DK3_CHAR_SIZE > 2
4006 #error "Can not handle 4-byte characters here!"
4007 #else
4008 rb[current_index] =
4009 (dkChar const *)dk3str_cnvnew_c8u_to_c16_app(
4010 lb, (verb ? app : NULL)
4011 );
4012 if(rb[current_index]) {
4013 current_index++;
4014 } else {
4015 errors_occured = 2;
4016 }
4017 #endif
4018 #else
4019
4020 switch(app->i_encoding) {
4021 case DK3_ENCODING_PLAIN: {
4022 rb[current_index] =
4023 dk3str_cnvnew_c8u_to_c8p_app(lb, (verb ? app : NULL));
4024 if(rb[current_index]) {
4025 current_index++;
4026 } else {
4027 errors_occured = 2;
4028 }
4029 } break;
4030 default: {
4031 rb[current_index] =
4032 dk3str_dup_app(lb, (verb ? app : NULL));
4033 if(rb[current_index]) {
4034 current_index++;
4035 } else {
4036 errors_occured = 2;
4037 }
4038 } break;
4039 }
4040 #endif
4041 }
4042 /* current_index++; */
4043 }
4044 }
4045 dk3app_set_source_line(app, 0UL);
4046 if((current_index >= (sz_defaults - 1)) && (!(errors_occured))) {
4047 if(!(app->s_mc)) {
4048 app->s_mc = dk3sto_open_app(verb ? app : NULL);
4049 if(app->s_mc) {
4050 dk3sto_set_comp(app->s_mc, dk3app_mc_compare, 0);
4051 } else {
4052 }
4053 }
4054 if(!(app->i_mc)) {
4055 if(app->s_mc) {
4056 app->i_mc = dk3sto_it_open(app->s_mc);
4057 } else {
4058 }
4059 }
4060 if((app->s_mc) && (app->i_mc)) {
4061 mcptr =
4062 dk3app_mc_new(fn, rb, sz_defaults, 1, (verb ? app: NULL));
4063 if(mcptr) {
4064 if(dk3sto_add(app->s_mc, mcptr)) {
4065 back = rb;
4066 } else {
4067 dk3app_mc_table_delete(rb, sz_defaults); rb = NULL;
4068 }
4069 } else {
4070 dk3app_mc_table_delete(rb, sz_defaults); rb = NULL;
4071 }
4072 } else {
4073 dk3app_mc_table_delete(rb, sz_defaults); rb = NULL;
4074 }
4075 } else { /* Error occured or not enough strings. */
4076 if(errors_occured) {
4077 if(verb) {
4078 /* Errors while reading file! */
4079 }
4080 } else {
4081 if(verb) {
4082 /* Too few entries in file! */
4083 }
4084 }
4085 dk3app_mc_table_delete(rb, sz_defaults);
4086 rb = NULL;
4087 }
4088 } else {
4089 }
4090 fclose(fipo);
4091 } else {
4092 }
4093 dk3app_set_source_file(app, source_file);
4094 dk3app_set_source_line(app, source_line);
4095 } else {
4096 }
4097 } else {
4098 }
4099 } else {
4100 }
4101 if(!(back)) {
4102 back = dv;
4103 }
4104 } else {
4105 }
4106 return back;
4107 }
4108
4109
4110
4111 /** Read one preferences file.
4112 @param app Application structure.
4113 @param fn File name to process.
4114 @param s Storage to save preference entries.
4115 @param i Iterator through storage.
4116 */
4117 static
4118 void
dk3app_rd_pref_file(dk3_app_t * app,dkChar const * fn,dk3_sto_t * s,dk3_sto_it_t * i)4119 dk3app_rd_pref_file(
4120 dk3_app_t *app, dkChar const *fn, dk3_sto_t *s, dk3_sto_it_t *i
4121 )
4122 {
4123 dkChar buffer[4096];
4124 char bombuf[4];
4125 dkChar *p1 = NULL; /* Preference key (name). */
4126 dkChar *p2 = NULL; /* Preference value. */
4127 dkChar *p3 = NULL; /* Scope attribute value. */
4128 dkChar const *oldsourcename; /* Old source file name. */
4129 FILE *fipo = NULL; /* Input file. */
4130 unsigned long lineno = 0UL; /* Current line number. */
4131 unsigned long oldsourceline; /* Old source line number. */
4132 size_t skb; /* Bytes to skip at start. */
4133 int scope_valid = 1; /* Flag: In a valid scope. */
4134 int last_was_scope = 0; /* Flag: Previous line was scope. */
4135 int scope_action = 0; /* 0=yes, 1=no */
4136 int conditions_ok; /* Flag: All conditions ok. */
4137 int ie = DK3_FILE_ENCODING_ASCII; /* Input encoding. */
4138
4139 skb = 0;
4140 ie = dk3sf_inspect_bom_skip_app(fn, DK3_FILE_ENCODING_ASCII, &skb, NULL);
4141 dk3app_log_i3(app, DK3_LL_DEBUG, 230, 231, fn);
4142 fipo = dk3sf_fopen_app(fn, dk3app_no_loc[22], NULL); /* READ */
4143 if(fipo) {
4144 oldsourcename = dk3app_get_source_file(app);
4145 oldsourceline = dk3app_get_source_line(app);
4146 dk3app_set_source_file(app, fn);
4147 dk3app_set_source_line(app, 0UL);
4148 (void)dk3sf_apply_bom_to_file_app(fipo, ie, NULL);
4149 lineno = 0UL;
4150 if((skb > 0) && (skb <= 4)) { dk3sf_fread_app(bombuf, 1, skb, fipo, NULL); }
4151 while(dk3sf_fgets(buffer, DK3_SIZEOF(buffer,dkChar), fipo)) {
4152 lineno++;
4153 dk3app_set_source_line(app, lineno);
4154 p1 = dk3str_start(buffer, NULL);
4155 if(p1) {
4156 if(*p1 != dkT('#')) {
4157 if(*p1 == dkT('[')) {
4158 if(!last_was_scope) { scope_valid = 0; }
4159 scope_action = 0;
4160 p2 = dk3str_chr(p1, dkT(']'));
4161 if(p2) { *p2 = dkT('\0'); }
4162 p1++;
4163 dk3str_chomp(p1, NULL);
4164 if(*p1 == dkT('-')) { scope_action = 1; p1++; }
4165 p1 = dk3str_start(p1, NULL);
4166 conditions_ok = 1;
4167 while(p1) {
4168 p2 = dk3str_chr(p1, dkT(','));
4169 if(p2) {
4170 *(p2++) = dkT('\0');
4171 p2 = dk3str_start(p2, NULL);
4172 }
4173 p3 = dk3str_chr(p1, dkT('='));
4174 if(p3) {
4175 *(p3++) = dkT('\0');
4176 p3 = dk3str_start(p3, NULL);
4177 if(p3) {
4178 dk3str_chomp(p1, NULL);
4179 dk3str_chomp(p3, NULL);
4180 switch(dk3str_array_index(dk3app_scope_attributes, p1, 0))
4181 {
4182 case 0: { /* user */
4183 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4184 if(app->n_logname) {
4185 #if DK3_ON_WINDOWS || DK3_HAVE_USER_NAMES_CASE_INSENSITIVE
4186 if(dk3str_casecmp(p3, app->n_logname)) {
4187 conditions_ok = 0;
4188 }
4189 #else
4190 if(dk3str_cmp(p3, app->n_logname)) {
4191 conditions_ok = 0;
4192 }
4193 #endif
4194 } else {
4195 conditions_ok = 0;
4196 }
4197 }
4198 } break;
4199 case 1: { /* application */
4200 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4201 if(app->n_app) {
4202 #if DK3_ON_WINDOWS || DK3_HAVE_FNCASEINS
4203 if(dk3str_casecmp(p3, app->n_app)) {
4204 conditions_ok = 0;
4205 }
4206 #else
4207 if(dk3str_cmp(p3, app->n_app)) { conditions_ok = 0; }
4208 #endif
4209 } else { conditions_ok = 0; }
4210 }
4211 } break;
4212 case 2: { /* application-group */
4213 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4214 if(app->n_appgroup) {
4215
4216 #if DK3_ON_WINDOWS || DK3_HAVE_FNCASEINS
4217 if(dk3str_casecmp(p3, app->n_appgroup)) {
4218 conditions_ok = 0;
4219 }
4220 #else
4221 if(dk3str_cmp(p3, app->n_appgroup)) {
4222 conditions_ok = 0;
4223 }
4224 #endif
4225 } else { conditions_ok = 0; }
4226 }
4227 } break;
4228 case 3: { /* host */
4229 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4230 if(app->n_hostname) {
4231 if(dk3str_casecmp(p3, app->n_hostname)) {
4232 conditions_ok = 0;
4233 }
4234 } else { conditions_ok = 0; }
4235 }
4236 } break;
4237 case 4: { /* language */
4238 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4239 if(app->n_language) {
4240 if(dk3str_cmp(p3, app->n_language)) {
4241 conditions_ok = 0;
4242 }
4243 } else { conditions_ok = 0; }
4244 }
4245 } break;
4246 case 5: { /* region */
4247 if(dk3str_cmp(p3, dk3app_no_loc[33])) {
4248 if(app->n_region) {
4249 if(dk3str_cmp(p3, app->n_region)) {
4250 conditions_ok = 0;
4251 }
4252 } else { conditions_ok = 0; }
4253 }
4254 } break;
4255 }
4256 }
4257 }
4258 p1 = p2;
4259 }
4260 last_was_scope = 1;
4261 if(conditions_ok) {
4262 if(scope_action) {
4263 scope_valid = 0;
4264 } else {
4265 scope_valid = 1;
4266 }
4267 }
4268 } else {
4269 last_was_scope = 0;
4270 if(scope_valid) {
4271 dk3str_chomp(p1, NULL);
4272 p2 = dk3str_chr(p1, dkT('='));
4273 if(p2) {
4274 *(p2++) = dkT('\0');
4275 p2 = dk3str_start(p2, NULL);
4276 if(p2) {
4277 dk3str_chomp(p1, NULL);
4278 dk3str_chomp(p2, NULL);
4279 if(!dk3app_add_pref(NULL, s, i, p1, p2)) {
4280 app->de = 33;
4281 }
4282 }
4283 }
4284 }
4285 }
4286 }
4287 }
4288 }
4289 fclose(fipo);
4290 dk3app_set_source_file(app, oldsourcename);
4291 dk3app_set_source_line(app, oldsourceline);
4292 } else {
4293 dk3app_log_i3(app, DK3_LL_DEBUG, 152, 153, fn);
4294 }
4295 }
4296
4297
4298
4299 /** Read all preference files for an application.
4300 @param app Application structure.
4301 */
4302 static
4303 void
dk3app_read_preference_files(dk3_app_t * app)4304 dk3app_read_preference_files(dk3_app_t *app)
4305 {
4306 dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */
4307 int i = 0; /* Pass. */
4308
4309 for(i = 0; i < 16; i++) {
4310 if(dk3app_config_name(app, dk3app_no_loc[21], fnb, DK3_MAX_PATH, i, 0)) {
4311 switch(i) {
4312 case 14: {
4313 if(!(app->s_varprefs)) {
4314 app->s_varprefs = dk3sto_open_app(NULL);
4315 if(app->s_varprefs) {
4316 dk3sto_set_comp(app->s_varprefs, dk3app_compare_pref, 0);
4317 } else {
4318 app->de = 36;
4319 }
4320 }
4321 if(!(app->i_varprefs)) {
4322 if(app->s_varprefs) {
4323 app->i_varprefs = dk3sto_it_open(app->s_varprefs);
4324 if(!(app->i_varprefs)) { app->de = 36; }
4325 }
4326 }
4327 if((app->s_varprefs) && (app->i_varprefs)) {
4328 dk3app_rd_pref_file(app, fnb, app->s_varprefs, app->i_varprefs);
4329 }
4330 } break;
4331 case 12: case 13: case 15: {
4332 if(!(app->s_constprefs)) {
4333 app->s_constprefs = dk3sto_open_app(NULL);
4334 if(app->s_constprefs) {
4335 dk3sto_set_comp(app->s_constprefs, dk3app_compare_pref, 0);
4336 } else {
4337 app->de = 36;
4338 }
4339 }
4340 if(!(app->i_constprefs)) {
4341 if(app->s_constprefs) {
4342 app->i_constprefs = dk3sto_it_open(app->s_constprefs);
4343 if(!(app->i_constprefs)) { app->de = 36; }
4344 }
4345 }
4346 if((app->s_constprefs) && (app->i_constprefs)) {
4347 dk3app_rd_pref_file(app,fnb,app->s_constprefs,app->i_constprefs);
4348 }
4349 } break;
4350 default: {
4351 if(!(app->s_sysprefs)) {
4352 app->s_sysprefs = dk3sto_open_app(NULL);
4353 if(app->s_sysprefs) {
4354 dk3sto_set_comp(app->s_sysprefs, dk3app_compare_pref, 0);
4355 } else { app->de = 36; }
4356 }
4357 if(!(app->i_sysprefs)) {
4358 if(app->s_sysprefs) {
4359 app->i_sysprefs = dk3sto_it_open(app->s_sysprefs);
4360 if(!(app->i_sysprefs)) { app->de = 36; }
4361 }
4362 }
4363 if((app->s_sysprefs) && (app->i_sysprefs)) {
4364 dk3app_rd_pref_file(app, fnb, app->s_sysprefs, app->i_sysprefs);
4365 }
4366 } break;
4367 }
4368 }
4369 }
4370 }
4371
4372
4373
4374 /** Find log level.
4375 @param app Application structure.
4376 @param ind Index of preference name in \a dk3app_no_loc.
4377 @param buffer Buffer for preference value.
4378 @param sz Size of \a buffer (number of characters).
4379 @param dv Default value to use if preference is not set.
4380 @return Log level found in preference or default value.
4381 */
4382 static
4383 int
dk3app_find_ll(dk3_app_t * app,int ind,dkChar * buffer,size_t sz,int dv)4384 dk3app_find_ll(dk3_app_t *app, int ind, dkChar *buffer, size_t sz, int dv)
4385 {
4386 int back = 0;
4387 dkChar *p1 = NULL; /* Value string. */
4388 int i = 0; /* Index search result. */
4389 back = dv;
4390
4391 if(dk3app_get_pref(app, dk3app_no_loc[ind], buffer, sz)) {
4392 p1 = dk3str_start(buffer, NULL);
4393 if(p1) {
4394
4395 dk3str_chomp(p1, NULL);
4396
4397 i = dk3str_array_abbr(dk3app_log_levels, p1, dkT('$'), 0);
4398 if(i >= 0) {
4399 if(i <= DK3_LL_IGNORE) {
4400 back = i;
4401 }
4402 } else {
4403 }
4404 } else {
4405 }
4406 } else {
4407 }
4408 return back;
4409 }
4410
4411
4412
4413 /** Preferences processing at application startup.
4414 @param app Application structure.
4415 */
4416 static
4417 void
dk3app_process_preferences(dk3_app_t * app)4418 dk3app_process_preferences(dk3_app_t *app)
4419 {
4420 dkChar buffer[4096];
4421 dkChar *p1 = NULL; /* Start of language/region/encoding string. */
4422 dkChar *p2 = NULL; /* Encoding, later region. */
4423 dkChar *p3 = NULL; /* Used to convert to lower case. */
4424 dkChar *p4 = NULL; /* New string for region. */
4425 int i; /* Input encoding. */
4426 if(dk3app_get_pref(app,dk3app_no_loc[27],buffer,DK3_SIZEOF(buffer,dkChar)))
4427 {
4428 p1 = dk3str_start(buffer, NULL);
4429 if(p1) {
4430 p2 = dk3str_chr(buffer, dkT('.'));
4431 if(p2) { *p2 = dkT('\0'); }
4432 p2 = dk3str_chr(buffer, dkT('_'));
4433 if(p2) {
4434 *(p2++) = dkT('\0');
4435 p2 = dk3str_start(p2, NULL);
4436 if(p2) {
4437 dk3str_chomp(p2, NULL);
4438 p3 = p2; while(*p3) { *p3 = dk3str_tolower(*p3); p3++; }
4439 }
4440 }
4441 p3 = p1; while(*p3) { *p3 = dk3str_tolower(*p3); p3++; }
4442 dk3str_chomp(p1, NULL);
4443 p3 = dk3str_dup_app(p1, NULL);
4444 p4 = NULL;
4445 if(p2) { p4 = dk3str_dup_app(p2, NULL); }
4446 if(p3) {
4447 dk3_delete(app->n_language);
4448 app->n_language = p3;
4449 }
4450 if(p4) {
4451 dk3_delete(app->n_region);
4452 app->n_region = p4;
4453 }
4454 }
4455 }
4456 app->ll_file = dk3app_find_ll(
4457 app, 28, buffer, DK3_SIZEOF(buffer,dkChar), app->ll_file
4458 );
4459 app->ll_file_keep = dk3app_find_ll(
4460 app, 29, buffer, DK3_SIZEOF(buffer,dkChar), app->ll_file_keep
4461 );
4462 app->ll_stderr = dk3app_find_ll(
4463 app, 30, buffer, DK3_SIZEOF(buffer,dkChar), app->ll_stderr
4464 );
4465 app->ll_tmp_keep = dk3app_find_ll(
4466 app, 31, buffer, DK3_SIZEOF(buffer,dkChar), app->ll_tmp_keep
4467 );
4468 app->i_stdin_input_encoding = dk3app_get_default_stdin_encoding(app);
4469
4470 app->i_file_input_encoding = dk3app_get_default_file_encoding(app);
4471 if(dk3app_get_pref(app,dk3app_no_loc[51],buffer,DK3_SIZEOF(buffer,dkChar)))
4472 {
4473 p1 = dk3str_start(buffer, NULL);
4474 if(p1) {
4475 dk3str_chomp(p1, NULL);
4476 i = dk3enc_get_text_encoding_app(buffer, NULL);
4477 if(i >= 0) {
4478 app->i_file_input_encoding = i;
4479 }
4480 }
4481 }
4482 if(dk3app_get_pref(app,dk3app_no_loc[52],buffer,DK3_SIZEOF(buffer,dkChar)))
4483 {
4484 p1 = dk3str_start(buffer, NULL);
4485 if(p1) {
4486 dk3str_chomp(p1, NULL);
4487 i = dk3enc_get_text_encoding_app(buffer, NULL);
4488 if(i >= 0) {
4489 app->i_stdin_input_encoding = i;
4490
4491 }
4492 }
4493 }
4494
4495 }
4496
4497
4498
4499 /** Create new application.
4500 @param wd Current working directory.
4501 @param argc Number of command line arguments.
4502 @param argv Command line arguments array.
4503 @param gn Application group name.
4504 @param tp Application type.
4505 @return Pointer to new application on success, NULL on error.
4506 */
4507 static
4508 dk3_app_t *
dk3app_open(dkChar const * wd,int argc,dkChar const * const * argv,dkChar const * gn,int tp)4509 dk3app_open(
4510 dkChar const * wd,
4511 int argc, dkChar const * const * argv,
4512 dkChar const *gn,
4513 int tp
4514 )
4515 {
4516 dk3_app_t *back = NULL;
4517
4518 back = dk3_new(dk3_app_t,1);
4519 if(back) {
4520 dk3app_init(back);
4521 switch(tp) {
4522 case DK3_APP_TYPE_DAEMON: {
4523 back->ll_file = DK3_LL_INFO;
4524 } break;
4525 }
4526 back->app_type = tp;
4527 if(!(back->de)) { dk3app_save_group_name(back, gn); }
4528 if(!(back->de)) { dk3app_first_silence_check(back, argc, argv); }
4529 if(!(back->de)) { dk3app_language_and_region(back); }
4530 if(!(back->de)) { dk3app_find_names(back, wd, argv); }
4531 if(!(back->de)) { dk3app_save_arguments(back, argc, argv); }
4532 if(!(back->de)) { dk3app_read_preference_files(back); }
4533 if(!(back->de)) { dk3app_process_preferences(back); }
4534 if(!(back->de)) {
4535 back->msg = dk3app_my_messages(back, dk3app_no_loc[23], dk3app_kw, 0);
4536 }
4537 back->f_readytolog = 1;
4538 if(back->de) {
4539 /* Delayed error occured. Report error, destroy structure. */
4540 switch(back->de) {
4541 case 1: /* Error while saving command line arguments. */
4542 case 2: /* Error while saving application name. */
4543 case 4: /* Error while saving exec file name. */
4544 case 6: /* Error while saving bin directory. */
4545 case 7: /* Error while saving etc directory. */
4546 case 8: /* Error while saving share directory. */
4547 case 9: /* Error while saving var directory. */
4548 case 15: /* Error while saving logname. */
4549 case 17: /* Error while saving home directory. */
4550 case 18: /* Error while saving application group name. */
4551 case 21: /* Error while saving log file name. */
4552 case 25: /* Error while saving temp dir name. */
4553 case 28: /* Error while saving language string. */
4554 case 29: /* Failed to save region! */
4555 case 30: /* Failed to save language! */
4556 case 33: /* Pref */
4557 case 34: /* Pref storage */
4558 case 35: /* Cmd prefs iterator */
4559 case 36: /* Cmd prefs storage */
4560 case 37: /* Store host name */
4561 {
4562 dk3app_log_i1(back, DK3_LL_ERROR, 9);
4563 } break;
4564 case 3: /* Failed to find executable file name. */
4565 {
4566 /* Failed to find executable file name. */
4567 dk3app_log_i1(back, DK3_LL_ERROR, 40);
4568 } break;
4569 case 5: /* Incomplete exec file name. */
4570 {
4571 /* No separator in executable file name! */
4572 dk3app_log_i1(back, DK3_LL_ERROR, 40);
4573 } break;
4574 case 10: /* Program is started from root directory. */
4575 {
4576 /* Too few directories in hierarchy! */
4577 dk3app_log_i1(back, DK3_LL_ERROR, 41);
4578 } break;
4579 case 11: /* Error while creating etc directory name! */
4580 case 12: /* Error while creating share directory name! */
4581 case 13: /* Error while creating var directory name! */
4582 {
4583 /* Name of executable file too long! */
4584 dk3app_log_i1(back, DK3_LL_ERROR, 42);
4585 } break;
4586 case 14: { /* Failed to retrieve log name! */
4587 /* Failed to retrieve log name! */
4588 dk3app_log_i1(back, DK3_LL_ERROR, 43);
4589 } break;
4590 case 16: { /* Failed to retrieve home directory! */
4591 /* Failed to retrieve home directory! */
4592 dk3app_log_i1(back, DK3_LL_ERROR, 44);
4593 } break;
4594 case 19: { /* Log file name too long. */
4595 /* Log file name gets too long! */
4596 dk3app_log_i1(back, DK3_LL_ERROR, 45);
4597 } break;
4598 case 20: {
4599 /* Failed to create log directory! */
4600 dk3app_log_i1(back, DK3_LL_ERROR, 46);
4601 } break;
4602 case 22: {
4603 /* Failed to convert PID to dkChar! */
4604 dk3app_log_i1(back, DK3_LL_ERROR, 47);
4605 } break;
4606 case 23: {
4607 /* Home directory name missing! */
4608 dk3app_log_i1(back, DK3_LL_ERROR, 44);
4609 } break;
4610 case 24: {
4611 /* Application name missing! */
4612 dk3app_log_i1(back, DK3_LL_ERROR, 48);
4613 } break;
4614 case 26: {
4615 /* Name of tmp dir gets too long! */
4616 dk3app_log_i1(back, DK3_LL_ERROR, 49);
4617 } break;
4618 case 27: {
4619 /* var dir name missing! */
4620 dk3app_log_i1(back, DK3_LL_ERROR, 50);
4621 } break;
4622 case 31: {
4623 /* Preference name too long! */
4624 dk3app_log_i1(back, DK3_LL_ERROR, 51);
4625 } break;
4626 case 32: {
4627 /* Not a preference entry! */
4628 dk3app_log_i1(back, DK3_LL_ERROR, 52);
4629 } break;
4630 case 38: {
4631 dk3app_log_i1(back, DK3_LL_ERROR, 131);
4632 } break;
4633 }
4634 dk3app_close(back);
4635 back = NULL;
4636 } else {
4637 dk3app_log_i3(back, DK3_LL_DEBUG, 19, 20, back->n_app);
4638 dk3app_log_i2(
4639 back, DK3_LL_DEBUG, 23,
4640 ((back->n_app) ? back->n_app: ((back->msg) ? back->msg : dk3app_kw)[36])
4641 );
4642 dk3app_log_i2(
4643 back, DK3_LL_DEBUG, 24,
4644 ((back->n_appgroup) ? back->n_appgroup: ((back->msg) ? back->msg : dk3app_kw)[36])
4645 );
4646 dk3app_log_i2(
4647 back, DK3_LL_DEBUG, 25,
4648 ((back->n_execfile) ? back->n_execfile: ((back->msg) ? back->msg : dk3app_kw)[36])
4649 );
4650 dk3app_log_i2(
4651 back, DK3_LL_DEBUG, 26,
4652 ((back->n_bindir) ? back->n_bindir: ((back->msg) ? back->msg : dk3app_kw)[36])
4653 );
4654 dk3app_log_i2(
4655 back, DK3_LL_DEBUG, 27,
4656 ((back->n_etcdir) ? back->n_etcdir: ((back->msg) ? back->msg : dk3app_kw)[36])
4657 );
4658 dk3app_log_i2(
4659 back, DK3_LL_DEBUG, 28,
4660 ((back->n_sharedir) ? back->n_sharedir: ((back->msg) ? back->msg : dk3app_kw)[36])
4661 );
4662 dk3app_log_i2(
4663 back, DK3_LL_DEBUG, 29,
4664 ((back->n_vardir) ? back->n_vardir: ((back->msg) ? back->msg : dk3app_kw)[36])
4665 );
4666 dk3app_log_i2(
4667 back, DK3_LL_DEBUG, 30,
4668 ((back->n_homedir) ? back->n_homedir: ((back->msg) ? back->msg : dk3app_kw)[36])
4669 );
4670 dk3app_log_i2(
4671 back, DK3_LL_DEBUG, 31,
4672 ((back->n_tmpdir) ? back->n_tmpdir: ((back->msg) ? back->msg : dk3app_kw)[36])
4673 );
4674 dk3app_log_i2(
4675 back, DK3_LL_DEBUG, 32,
4676 ((back->n_logname) ? back->n_logname: ((back->msg) ? back->msg : dk3app_kw)[36])
4677 );
4678 dk3app_log_i2(
4679 back, DK3_LL_DEBUG, 132,
4680 ((back->n_hostname) ? back->n_hostname: ((back->msg) ? back->msg : dk3app_kw)[36])
4681 );
4682 dk3app_log_i2(
4683 back, DK3_LL_DEBUG, 33,
4684 ((back->n_logfilename) ? back->n_logfilename: ((back->msg) ? back->msg : dk3app_kw)[36])
4685 );
4686 dk3app_log_i2(
4687 back, DK3_LL_DEBUG, 34,
4688 ((back->n_language) ? back->n_language: ((back->msg) ? back->msg : dk3app_kw)[36])
4689 );
4690 dk3app_log_i2(
4691 back, DK3_LL_DEBUG, 35,
4692 ((back->n_region) ? back->n_region: ((back->msg) ? back->msg : dk3app_kw)[36])
4693 );
4694 }
4695 } else {
4696 if(tp == DK3_APP_TYPE_COMMAND) {
4697 /* ERROR: Not enough memory */
4698 dk3sf_initialize_stderr();
4699 dk3sf_fputs(dk3app_kw[9], stderr);
4700 dk3sf_fputs(dk3app_kw[0], stderr);
4701 fflush(stderr);
4702 }
4703 }
4704 return back;
4705 }
4706
4707
4708
4709 dk3_app_t *
dk3app_open_command(int argc,dkChar const * const * argv,dkChar const * gn)4710 dk3app_open_command(int argc, dkChar const * const * argv, dkChar const *gn)
4711 {
4712 dk3_app_t *back = NULL;
4713 dkChar wd[DK3_MAX_PATH]; /* Current working directory. */
4714 if((argc) && (argv) && (gn)) {
4715 if(dk3sf_getcwd_app(wd, DK3_SIZEOF(wd,dkChar), NULL)) {
4716 back = dk3app_open(wd, argc, argv, gn, DK3_APP_TYPE_COMMAND);
4717 } else {
4718 /* ERROR: Failed to find current working directory. */
4719 if(!dk3app_first_silence_check(NULL, argc, argv)) {
4720 dk3sf_initialize_stderr();
4721 dk3sf_fputs(dk3app_kw[3], stderr);
4722 dk3sf_fputs(dk3app_kw[11], stderr);
4723 dk3sf_fputs(dk3app_kw[8], stderr);
4724 dk3sf_fputs(dk3app_kw[53], stderr);
4725 dk3sf_fputs(dk3app_kw[0], stderr);
4726 fflush(stderr);
4727 }
4728 }
4729 }
4730 return back;
4731 }
4732
4733
4734
4735 dk3_app_t *
dk3app_open_gui(int argc,dkChar const * const * argv,dkChar const * gn)4736 dk3app_open_gui(int argc, dkChar const * const * argv, dkChar const *gn)
4737 {
4738 dk3_app_t *back = NULL;
4739 dkChar wd[DK3_MAX_PATH]; /* Current working directory. */
4740 if((argc) && (argv) && (gn)) {
4741 if(dk3sf_getcwd_app(wd, DK3_SIZEOF(wd,dkChar),NULL)) {
4742 back = dk3app_open(wd, argc, argv, gn, DK3_APP_TYPE_GUI);
4743 } else {
4744 /* ERROR: Failed to find current working directory. */
4745 }
4746 }
4747 return back;
4748 }
4749
4750
4751
4752 dk3_app_t *
dk3app_open_daemon(dkChar const * wd,int argc,dkChar const * const * argv,dkChar const * gn)4753 dk3app_open_daemon(
4754 dkChar const *wd, int argc, dkChar const * const * argv, dkChar const *gn
4755 )
4756 {
4757 dk3_app_t *back = NULL;
4758 if((wd) && (argc) && (argv) && (gn)) {
4759 back = dk3app_open(wd, argc, argv, gn, DK3_APP_TYPE_DAEMON);
4760 }
4761 return back;
4762 }
4763
4764
4765
4766 dk3_app_t *
dk3app_open_silent(int argc,dkChar const * const * argv,dkChar const * gn)4767 dk3app_open_silent(int argc, dkChar const * const * argv, dkChar const *gn)
4768 {
4769 dk3_app_t *back = NULL;
4770 dkChar wd[DK3_MAX_PATH]; /* Current working directory. */
4771 if((argc) && (argv) && (gn)) {
4772 if(dk3sf_getcwd_app(wd, DK3_SIZEOF(wd,dkChar),NULL)) {
4773 back = dk3app_open(wd, argc, argv, gn, DK3_APP_TYPE_SILENT);
4774 } else {
4775 /* ERROR: Failed to find current working directory. */
4776 }
4777 }
4778 return back;
4779 }
4780
4781
4782
4783 dkChar const * const *
dk3app_get_argv(dk3_app_t const * app)4784 dk3app_get_argv(dk3_app_t const *app)
4785 {
4786 dkChar const * const *back = NULL;
4787 if(app) { back = (dkChar const * const *)(app->argv); }
4788 return back;
4789 }
4790
4791
4792
4793 int
dk3app_get_argc(dk3_app_t const * app)4794 dk3app_get_argc(dk3_app_t const *app)
4795 {
4796 int back = 0;
4797 if(app) { back = app->argc; }
4798 return back;
4799 }
4800
4801
4802
4803 dkChar const *
dk3app_get_appname(dk3_app_t const * app)4804 dk3app_get_appname(dk3_app_t const *app)
4805 {
4806 dkChar const *back = NULL;
4807 if(app) {
4808 back = app->n_app;
4809 }
4810 return back;
4811 }
4812
4813
4814
4815 dkChar const *
dk3app_get_execfilename(dk3_app_t const * app)4816 dk3app_get_execfilename(dk3_app_t const *app)
4817 {
4818 dkChar const *back = NULL;
4819 if(app) {
4820 back = app->n_execfile;
4821 }
4822 return back;
4823 }
4824
4825
4826
4827 dkChar const *
dk3app_get_bindir(dk3_app_t const * app)4828 dk3app_get_bindir(dk3_app_t const *app)
4829 {
4830 dkChar const *back = NULL;
4831 if(app) {
4832 back = app->n_bindir;
4833 }
4834 return back;
4835 }
4836
4837
4838
4839 dkChar const *
dk3app_get_etcdir(dk3_app_t const * app)4840 dk3app_get_etcdir(dk3_app_t const *app)
4841 {
4842 dkChar const *back = NULL;
4843 if(app) {
4844 back = app->n_etcdir;
4845 }
4846 return back;
4847 }
4848
4849
4850
4851 dkChar const *
dk3app_get_sharedir(dk3_app_t const * app)4852 dk3app_get_sharedir(dk3_app_t const *app)
4853 {
4854 dkChar const *back = NULL;
4855 if(app) {
4856 back = app->n_sharedir;
4857 }
4858 return back;
4859 }
4860
4861
4862
4863 dkChar const *
dk3app_get_vardir(dk3_app_t const * app)4864 dk3app_get_vardir(dk3_app_t const *app)
4865 {
4866 dkChar const *back = NULL;
4867 if(app) {
4868 back = app->n_vardir;
4869 }
4870 return back;
4871 }
4872
4873
4874
4875 dkChar const *
dk3app_get_logname(dk3_app_t const * app)4876 dk3app_get_logname(dk3_app_t const *app)
4877 {
4878 dkChar const *back = NULL;
4879 if(app) {
4880 back = app->n_logname;
4881 }
4882 return back;
4883 }
4884
4885
4886
4887 dkChar const *
dk3app_get_hostname(dk3_app_t const * app)4888 dk3app_get_hostname(dk3_app_t const *app)
4889 {
4890 dkChar const *back = NULL;
4891 if(app) {
4892 back = app->n_hostname;
4893 }
4894 return back;
4895 }
4896
4897
4898
4899 dkChar const *
dk3app_get_homedir(dk3_app_t const * app)4900 dk3app_get_homedir(dk3_app_t const *app)
4901 {
4902 dkChar const *back = NULL;
4903 if(app) {
4904 back = app->n_homedir;
4905 }
4906 return back;
4907 }
4908
4909
4910
4911 dkChar const *
dk3app_get_appgroup(dk3_app_t const * app)4912 dk3app_get_appgroup(dk3_app_t const *app)
4913 {
4914 dkChar const *back = NULL;
4915 if(app) {
4916 back = app->n_appgroup;
4917 }
4918 return back;
4919 }
4920
4921
4922
4923 int
dk3app_get_temp_file_name(dk3_app_t * app,dkChar * db,size_t sz)4924 dk3app_get_temp_file_name(dk3_app_t *app, dkChar *db, size_t sz)
4925 {
4926 int back = 0;
4927 char fn[16]; /* BUffer for sprintf(). */
4928 dkChar fn2[16]; /* Short file name buffer. */
4929 size_t s = 0; /* Buffer length needed. */
4930
4931 if((app) && (db) && (sz)) {
4932 if(app->n_tmpdir) {
4933 if ((DK3_APP_TYPE_DAEMON != app->app_type) && (0 == app->cr_tmp)) {
4934 dk3app_create_tmp_directory(app);
4935 app->cr_tmp = 1;
4936 }
4937 if(!(app->i_tmpcarry)) {
4938 sprintf(fn, "/%08lx.%03x", app->ul_tmpname, app->u_tmpsuffix);
4939 back = 1;
4940 if ((0UL == app->ul_tmpname) && (0 == app->u_tmpsuffix)) {
4941 if (DK3_APP_TYPE_DAEMON != app->app_type) {
4942
4943
4944 if (0 == dk3sf_mkdir_app(app->n_tmpdir, 0700, NULL)) {
4945 back = 0;
4946 }
4947 }
4948 }
4949 app->u_tmpsuffix += 1U;
4950 if(app->u_tmpsuffix >= 0x1000U) {
4951 app->u_tmpsuffix = 0U;
4952 #if VERSION_BEFORE_20150318
4953 app->ul_tmpname += 1UL;
4954 if(app->ul_tmpname == 0UL) {
4955 app->i_tmpcarry = 1;
4956 back = 0;
4957 /* Too many temporary file names asked! */
4958 dk3app_log_i1(app, DK3_LL_ERROR, 54);
4959 }
4960 #else
4961 /* 2015-03-18 We better check the variable before adding 1.
4962 Unsigned long may be larger than 32 bits.
4963 */
4964 if (0xFFFFFFFFUL > app->ul_tmpname) {
4965 app->ul_tmpname += 1UL;
4966 } else {
4967 app->i_tmpcarry = 1;
4968 back = 0;
4969 /* Too many temporary file names asked! */
4970 dk3app_log_i1(app, DK3_LL_ERROR, 54);
4971 }
4972 #endif
4973 }
4974 if(back) {
4975 back = 0;
4976 if(dk3str_cnv_c8_to_str_app(fn2, 15, fn, app)) {
4977 s = dk3str_len(app->n_tmpdir) + dk3str_len(fn2);
4978 if(s < sz) {
4979 dk3str_cpy_not_overlapped(db, app->n_tmpdir);
4980 dk3str_cat(db, fn2);
4981 dk3str_correct_filename(db);
4982 back = 1;
4983 } else {
4984 /* Destination buffer too small! */
4985 dk3app_log_i1(app, DK3_LL_ERROR, 38);
4986 }
4987 }
4988 }
4989 }
4990 } else {
4991 /* Not directory for temporary files available! */
4992 dk3app_log_i1(app, DK3_LL_ERROR, 55);
4993 }
4994 }
4995 return back;
4996 }
4997
4998
4999
5000 dkChar const *
dk3app_get_language(dk3_app_t const * app)5001 dk3app_get_language(dk3_app_t const *app)
5002 {
5003 dkChar const *back = NULL;
5004 if(app) { back = app->n_language; }
5005 return back;
5006 }
5007
5008
5009
5010 dkChar const *
dk3app_get_region(dk3_app_t const * app)5011 dk3app_get_region(dk3_app_t const *app)
5012 {
5013 dkChar const *back = NULL;
5014 if(app) { back = app->n_region; }
5015 return back;
5016 }
5017
5018
5019
5020 int
dk3app_get_encoding(dk3_app_t const * app)5021 dk3app_get_encoding(dk3_app_t const *app)
5022 {
5023 int back = 0;
5024 if(app) { back = app->i_encoding; }
5025 return back;
5026 }
5027
5028
5029
5030 int
dk3app_get_output_encoding(dk3_app_t const * app)5031 dk3app_get_output_encoding(dk3_app_t const *app)
5032 {
5033 int back = 0;
5034 if(app) { back = app->i_output_encoding; }
5035 return back;
5036 }
5037
5038
5039
5040 int
dk3app_get_input_stdin_encoding(dk3_app_t const * app)5041 dk3app_get_input_stdin_encoding(dk3_app_t const *app)
5042 {
5043 int back = 0;
5044 if(app) { back = app->i_stdin_input_encoding; }
5045 return back;
5046 }
5047
5048
5049
5050 int
dk3app_get_input_file_encoding(dk3_app_t const * app)5051 dk3app_get_input_file_encoding(dk3_app_t const *app)
5052 {
5053 int back = 0;
5054 if(app) { back = app->i_file_input_encoding; }
5055 return back;
5056 }
5057
5058
5059
5060 int
dk3app_set_pref(dk3_app_t * app,dkChar const * k,dkChar const * v)5061 dk3app_set_pref(dk3_app_t *app, dkChar const *k, dkChar const *v)
5062 {
5063 int back = 0;
5064 if((app) && (k) && (v)) {
5065 if(!(app->s_selfprefs)) {
5066 app->s_selfprefs = dk3sto_open_app(app);
5067 if(app->s_selfprefs) {
5068 dk3sto_set_comp(app->s_selfprefs, dk3app_compare_pref, 0);
5069 }
5070 }
5071 if(!(app->i_selfprefs)) {
5072 if(app->s_selfprefs) {
5073 app->i_selfprefs = dk3sto_it_open(app->s_selfprefs);
5074 }
5075 }
5076 if((app->s_selfprefs) && (app->i_selfprefs)) {
5077 back = dk3app_add_pref(app, app->s_selfprefs, app->i_selfprefs, k, v);
5078 app->f_prefschanged = 1;
5079 }
5080 if(!back) {
5081 /* Failed to save preference value! */
5082 dk3app_log_i5(app, DK3_LL_ERROR, 56, 57, 58, k, v);
5083 }
5084 }
5085 return back;
5086 }
5087
5088
5089
5090 int
dk3app_get_pref(dk3_app_t * app,dkChar const * k,dkChar * d,size_t s)5091 dk3app_get_pref(dk3_app_t *app, dkChar const *k, dkChar *d, size_t s)
5092 {
5093 int back = 0;
5094
5095 if((app) && (k) && (d) && (s)) {
5096
5097 back = dk3app_sto_pref(app, app->i_selfprefs, k, d, s);
5098 if(back == 0) {
5099 back = dk3app_sto_pref(app, app->i_cmdprefs, k, d, s);
5100 if(back == 0) {
5101 back = dk3app_sto_pref(app, app->i_varprefs, k, d, s);
5102 if(back == 0) {
5103 back = dk3app_sto_pref(app, app->i_constprefs, k, d, s);
5104 if(back == 0) {
5105 back = dk3app_sto_pref(app, app->i_sysprefs, k, d, s);
5106 }
5107 }
5108 }
5109 }
5110
5111
5112
5113 }
5114 return back;
5115 }
5116
5117
5118
5119 int
dk3app_get_sys_pref(dk3_app_t * app,dkChar const * k,dkChar * d,size_t s)5120 dk3app_get_sys_pref(dk3_app_t *app, dkChar const *k, dkChar *d, size_t s)
5121 {
5122 int back = 0;
5123 if((app) && (k) && (d) && (s)) {
5124 back = dk3app_sto_pref(app, app->i_selfprefs, k, d, s);
5125 if(back == 0) {
5126 back = dk3app_sto_pref(app, app->i_sysprefs, k, d, s);
5127 }
5128 }
5129 return back;
5130 }
5131
5132
5133
5134 /** Check whether the use of system configuration files
5135 is allowed for a file name.
5136 @param app Application structure.
5137 @param fn Short file name.
5138 @return 1 for system config files allowed, 0 for user files only.
5139 */
5140 static
5141 int
dk3app_allow_system_config_files(dk3_app_t * app,dkChar const * fn)5142 dk3app_allow_system_config_files(dk3_app_t *app, dkChar const *fn)
5143 {
5144 int back = 1;
5145 dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */
5146 dkChar il[1024 + DK3_MAX_PATH]; /* Input line buffer. */
5147 char bombuf[4]; /* Buffer to skip BOM. */
5148 dkChar *p1 = NULL; /* Key (entry name). */
5149 dkChar *p2 = NULL; /* Value. */
5150 FILE *fipo = NULL; /* Input file. */
5151 int ie = DK3_FILE_ENCODING_ASCII; /* Input encoding for file. */
5152 int cc = 1; /* Flag: Can continue. */
5153 size_t sz = 0; /* Buffer size needed. */
5154 size_t skb; /* Number of bytes to skip. */
5155 if(app->n_homedir) {
5156 sz = dk3str_len(app->n_homedir);
5157 sz += (2 * dk3str_len(dk3app_no_loc[20]));
5158 sz += dk3str_len(dk3app_no_loc[18]);
5159 sz += dk3str_len(dk3app_no_loc[34]);
5160 if(sz < DK3_SIZEOF(fnb,dkChar)) {
5161 dk3str_cpy_not_overlapped(fnb, app->n_homedir);
5162 dk3str_cat(fnb, dk3app_no_loc[20]);
5163 dk3str_cat(fnb, dk3app_no_loc[18]);
5164 dk3str_cat(fnb, dk3app_no_loc[20]);
5165 dk3str_cat(fnb, dk3app_no_loc[34]);
5166 skb = 0;
5167 ie = dk3sf_inspect_bom_skip_app(fnb, DK3_FILE_ENCODING_ASCII, &skb, NULL);
5168 fipo = dk3sf_fopen_app(fnb, dk3app_no_loc[22], NULL); /* READ */
5169 if(fipo) {
5170 (void)dk3sf_apply_bom_to_file_app(fipo, ie, NULL);
5171 cc = 1;
5172 if((skb > 0) && (skb <= 4)) {
5173 dk3sf_fread_app(bombuf, 1, skb, fipo, NULL);
5174 }
5175 while(cc) {
5176 if(dk3sf_fgets(il, DK3_SIZEOF(il,dkChar), fipo)) {
5177 p1 = dk3str_start(il, NULL);
5178 if(p1) {
5179 if(*p1 != dkT('#')) {
5180 p2 = dk3str_chr(p1, dkT('='));
5181 if(p2) {
5182 *(p2++) = dkT('\0');
5183 p2 = dk3str_start(p2, NULL);
5184 if(p2) {
5185 dk3str_chomp(p2, NULL);
5186 dk3str_normalize(p1, NULL, dkT('-'));
5187 switch(dk3str_array_index(dk3app_conf_file, p1, 0)) {
5188 case 0: { /* use system config files */
5189 if(dk3str_cmp(p2, dk3app_no_loc[33]) == 0) {
5190 back = 1; cc = 0;
5191 } else {
5192 if(dk3str_cmp(p2, fn) == 0) {
5193 back = 1; cc = 0;
5194 }
5195 }
5196 } break;
5197 case 1: { /* ignore system config files */
5198 if(dk3str_cmp(p2, dk3app_no_loc[33]) == 0) {
5199 back = 0; cc = 0;
5200 } else {
5201 if(dk3str_cmp(p2, fn) == 0) {
5202 back = 0; cc = 0;
5203 }
5204 }
5205 } break;
5206 }
5207 }
5208 }
5209 }
5210 }
5211 } else { cc = 0;}
5212 }
5213 fclose(fipo);
5214 }
5215 } else {
5216 /* ERROR: Home directory name too long! */
5217 dk3app_log_i1(app, DK3_LL_ERROR, 194);
5218 }
5219 }
5220 return back;
5221 }
5222
5223
5224
5225 /** Find configuration files for a given name.
5226 @param app Application structure.
5227 @param fn File name.
5228 @param res Flag: Reverse search order.
5229 @param exclu Flag: Exclude user files.
5230 @return Pointer to search result collection on success, NULL on error.
5231 */
5232 static
5233 dk3_search_t *
dk3app_my_find_config_file(dk3_app_t * app,dkChar const * fn,int res,int exclu)5234 dk3app_my_find_config_file(dk3_app_t *app, dkChar const *fn, int res, int exclu)
5235 {
5236 dk3_search_t *back = NULL;
5237 unsigned long items_found = 0; /* Number of items found. */
5238 int error_occured = 0; /* Flag: Error occured. */
5239 int i = 0; /* Current pass number. */
5240 int r = 0; /* Result from check for conf file. */
5241 int max = 0; /* Maximum pass number. */
5242 int min = 0; /* Minimum pass number. */
5243 dkChar buffer[DK3_MAX_PATH]; /* File name buffer. */
5244 if((app) && (fn)) {
5245 back = dk3search_open_app(res, app);
5246 if(back) {
5247 min = 0; max = 16;
5248 if(app->app_type == DK3_APP_TYPE_DAEMON) {
5249 max = 6;
5250 } else {
5251 if(exclu) {
5252 max = 12;
5253 } else {
5254 if(!dk3app_allow_system_config_files(app, fn)) {
5255 min = 12;
5256 /* DEBUG: System config files skipped by user. */
5257 dk3app_log_i1(app, DK3_LL_DEBUG, 195);
5258 }
5259 }
5260 }
5261 for(i = min; i < max; i++) {
5262 r = dk3app_check_config_file(app, fn, buffer, DK3_MAX_PATH, i, 1);
5263 if(r) {
5264 if(dk3search_add(back, buffer)) {
5265 items_found++;
5266 } else {
5267 error_occured = 1;
5268 }
5269 }
5270 }
5271 if(error_occured) {
5272 dk3search_close(back); back = NULL;
5273 } else {
5274 if(items_found == 0UL) {
5275 dk3search_close(back); back = NULL;
5276 }
5277 }
5278 }
5279 }
5280 return back;
5281 }
5282
5283
5284
5285 dk3_search_t *
dk3app_find_config_file(dk3_app_t * app,dkChar const * fn,int exclu)5286 dk3app_find_config_file(dk3_app_t *app, dkChar const *fn, int exclu)
5287 {
5288 dk3_search_t *back = NULL;
5289 if((app) && (fn)) {
5290 back = dk3app_my_find_config_file(app, fn, 0, exclu);
5291 }
5292 return back;
5293 }
5294
5295
5296
5297 dk3_search_t *
dk3app_find_config_file_revers(dk3_app_t * app,dkChar const * fn,int exclu)5298 dk3app_find_config_file_revers(dk3_app_t *app, dkChar const *fn, int exclu)
5299 {
5300 dk3_search_t *back = NULL;
5301 if((app) && (fn)) {
5302 back = dk3app_my_find_config_file(app, fn, 1, exclu);
5303 }
5304 return back;
5305 }
5306
5307
5308
5309 int
dk3app_find_data_file(dk3_app_t * app,dkChar const * fn,dkChar * db,size_t sz)5310 dk3app_find_data_file(dk3_app_t *app, dkChar const *fn, dkChar *db, size_t sz)
5311 {
5312 int back = 0;
5313 if((app) && (fn) && (db) && (sz)) {
5314 back = dk3app_my_find_data_file(app, fn, db, sz, 1);
5315 }
5316 return back;
5317 }
5318
5319
5320
5321 void
dk3app_unconfigure(dk3_app_t * app)5322 dk3app_unconfigure(dk3_app_t *app)
5323 {
5324 if(app) { app->f_unconfigure = 1; }
5325 }
5326
5327
5328
5329 dkChar const * const *
dk3app_messages(dk3_app_t * app,dkChar const * fn,dkChar const * const * dv)5330 dk3app_messages(dk3_app_t *app, dkChar const *fn, dkChar const * const *dv)
5331 {
5332 dkChar const * const *back;
5333
5334 back = dk3app_my_messages(app, fn, dv, 0);
5335
5336 return back;
5337 }
5338
5339
5340
5341 void
dk3app_help(dk3_app_t * app,dkChar const * fn,dkChar const * const * dt)5342 dk3app_help(dk3_app_t *app, dkChar const *fn, dkChar const * const *dt)
5343 {
5344 int had_success = 0; /* Flag: Success. */
5345 dkChar buffer[DK3_MAX_PATH]; /* File name buffer. */
5346 char lb[1024]; /* Input line buffer. */
5347 dkChar db[1024]; /* Output line buffer. */
5348 FILE *fipo = NULL; /* Input file. */
5349 dkChar const * const *ptr = NULL; /* Help text line. */
5350
5351 if((app) && (fn) && (dt)) {
5352 dk3sf_initialize_stdout();
5353 if(dk3app_my_find_data_file(app, fn, buffer, DK3_SIZEOF(buffer,dkChar), 0))
5354 {
5355 fipo = dk3sf_fopen_app(buffer, dk3app_no_loc[22], app); /* UTF-8 */
5356 if(fipo) {
5357 had_success = 1;
5358 while(fgets(lb, sizeof(lb), fipo)) {
5359 #if DK3_CHAR_SIZE == 2
5360 if(dk3str_cnv_c8u_to_c16_app(db, DK3_SIZEOF(db,dkChar), lb, app)) {
5361 dk3sf_fputs(db, stdout);
5362 }
5363 #else
5364 switch(app->i_encoding) {
5365 case DK3_ENCODING_PLAIN: {
5366 if(dk3str_cnv_c8u_to_c8p_app(db, DK3_SIZEOF(db,dkChar), lb, app))
5367 {
5368 fputs(db, stdout);
5369 }
5370 } break;
5371 default: {
5372 fputs(lb, stdout);
5373 } break;
5374 }
5375 #endif
5376 }
5377 fclose(fipo);
5378 }
5379 }
5380 if(!had_success) {
5381 ptr = dt;
5382 while(*ptr) {
5383 dk3sf_fputs(*(ptr++), stdout);
5384 dk3sf_fputc(dkT('\n'), stdout);
5385 }
5386 }
5387 }
5388 }
5389
5390
5391
5392 int
dk3app_get_stderr_log_level(dk3_app_t const * app)5393 dk3app_get_stderr_log_level(dk3_app_t const *app)
5394 {
5395 int back = DK3_LL_ERROR;
5396 if(app) {
5397 back = app->ll_stderr;
5398 }
5399 return back;
5400 }
5401
5402
5403
5404 void
dk3app_set_stderr_log_level(dk3_app_t * app,int ll)5405 dk3app_set_stderr_log_level(dk3_app_t *app, int ll)
5406 {
5407 if(app) {
5408 app->ll_stderr = ll;
5409 }
5410 }
5411
5412
5413
5414 void
dk3app_log_write_error(dk3_app_t * app,int ll,size_t wished,size_t written)5415 dk3app_log_write_error(dk3_app_t *app, int ll, size_t wished, size_t written)
5416 {
5417 dkChar b1[128]; /* Number of bytes wished to write. */
5418 dkChar b2[128]; /* Number of bytes really written. */
5419
5420 if (dk3ma_um_to_string(b1, DK3_SIZEOF(b1,dkChar), (dk3_um_t)wished)) {
5421 if (dk3ma_um_to_string(b2, DK3_SIZEOF(b2,dkChar), (dk3_um_t)written)) {
5422 dk3app_log_i5(app, ll, 170, 171, 172, b2, b1);
5423 }
5424 }
5425 }
5426
5427
5428
5429 void
dk3app_log_fwrite_error(dk3_app_t * app,int ll,size_t wished,size_t written)5430 dk3app_log_fwrite_error(dk3_app_t *app, int ll, size_t wished, size_t written)
5431 {
5432 dkChar b1[128]; /* Number of bytes wished to write. */
5433 dkChar b2[128]; /* Number of bytes really written. */
5434 if (dk3ma_um_to_string(b1, DK3_SIZEOF(b1,dkChar), (dk3_um_t)wished)) {
5435 if (dk3ma_um_to_string(b2, DK3_SIZEOF(b2,dkChar), (dk3_um_t)written)) {
5436 dk3app_log_i5(app, ll, 174, 175, 176, b2, b1);
5437 }
5438 }
5439 }
5440
5441
5442
5443 dkChar const *
dk3app_localized(dk3_app_t const * app,size_t num)5444 dk3app_localized(dk3_app_t const *app, size_t num)
5445 {
5446 dkChar const *back = NULL;
5447 if(app) {
5448 if(app->msg) {
5449 back = (app->msg)[num];
5450 } else {
5451 back = dk3app_kw[num];
5452 }
5453 }
5454 return back;
5455 }
5456
5457
5458
5459 dkChar const *
dk3app_not_localized(size_t num)5460 dk3app_not_localized(size_t num)
5461 {
5462 dkChar const *back = NULL;
5463 back = dk3app_no_loc[num];
5464 return back;
5465 }
5466
5467
5468
5469 int
dk3app_get_pref_bool(dk3_app_t * app,dkChar const * name,int dv)5470 dk3app_get_pref_bool(dk3_app_t *app, dkChar const *name, int dv)
5471 {
5472 int back;
5473 dkChar buffer[256]; /* Buffer for preference value. */
5474 dkChar *p1; /* Start of text. */
5475 back = dv;
5476 if(app) {
5477 if(dk3app_get_pref(app, name, buffer, DK3_SIZEOF(buffer,dkChar))) {
5478 p1 = dk3str_start(buffer, NULL);
5479 if(p1) {
5480 dk3str_chomp(p1, NULL);
5481 if(dk3str_is_bool(p1)) {
5482 back = ((dk3str_is_on(p1)) ? 1 : 0);
5483 }
5484 }
5485 }
5486 }
5487 return back;
5488 }
5489
5490
5491
5492 int
dk3app_get_pref_int(dk3_app_t * app,dkChar const * name,int dv)5493 dk3app_get_pref_int(dk3_app_t *app, dkChar const * name, int dv)
5494 {
5495 int back;
5496 int x;
5497 dkChar buffer[256];
5498 dkChar *p1;
5499
5500 back = dv;
5501 if(app) {
5502 if(dk3app_get_pref(app, name, buffer, DK3_SIZEOF(buffer,dkChar))) {
5503 p1 = dk3str_start(buffer, NULL);
5504 if(p1) {
5505 #if VERSION_BEFORE_20140716
5506 if(dk3sf_sscanf3(p1, dkT("%d"), &x) == 1)
5507 #else
5508 if (0 != dk3ma_i_from_string(&x, p1, NULL))
5509 #endif
5510 {
5511 back = x;
5512 }
5513 }
5514 }
5515 }
5516 return back;
5517 }
5518
5519
5520
5521 #if 0
5522
5523
5524 int
5525 dk3app_get_allowed_prng_types(dk3_app_t *app, dkChar const *il)
5526 {
5527 int back = 0;
5528 dkChar buffer[256];
5529 dkChar *p1 = NULL;
5530 dkChar *p2 = NULL;
5531 int i = 0;
5532 if((app) && (il)) {
5533 if(dk3str_len(il) < DK3_SIZEOF(buffer,dkChar)) {
5534 dk3str_cpy_not_overlapped(buffer, il);
5535 p1 = dk3str_start(buffer, NULL);
5536 while(p1) {
5537 p2 = dk3str_chr(p1, dkT(','));
5538 if(p2) {
5539 *(p2++) = dkT('\0'); p2 = dk3str_start(p2, NULL);
5540 }
5541 i = dk3str_array_index(dk3app_prng_type_names, p1, 0);
5542 switch(i) {
5543 case 0: {
5544 #if DK3_HAVE_OPENSSL_RAND_H
5545 back |= DK3_PRNG_OPENSSL;
5546 #else
5547 /* ERROR: Openssl PRNG not available! */
5548 dk3app_log_i1(app, DK3_LL_ERROR, 192);
5549 #endif
5550 } break;
5551 case 1: {
5552 #if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM
5553 back |= DK3_PRNG_STATE;
5554 #else
5555 /* ERROR: initstate()/setstate()/random() not available. */
5556 dk3app_log_i1(app, DK3_LL_ERROR, 191);
5557 #endif
5558 } break;
5559 case 2: {
5560 #if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48
5561 back |= DK3_PRNG_RAND48;
5562 #else
5563 /* ERROR: lrand48()/lrand48() not available. */
5564 dk3app_log_i1(app, DK3_LL_ERROR, 190);
5565 #endif
5566 } break;
5567 case 3: {
5568 #if DK3_HAVE_RAND && DK3_HAVE_SRAND
5569 back |= DK3_PRNG_SIMPLE;
5570 #else
5571 /* ERROR: srand()/rand() not available! */
5572 dk3app_log_i1(app, DK3_LL_ERROR, 189);
5573 #endif
5574 } break;
5575 default: {
5576 /* Unknown PRNG type name! */
5577 dk3app_log_i3(app, DK3_LL_ERROR, 187, 188, p1);
5578 } break;
5579 }
5580 p1 = p2;
5581 }
5582 } else {
5583 /* ERROR: Line too long for buffer! */
5584 dk3app_log_i1(app, DK3_LL_ERROR, 38);
5585 }
5586 }
5587 return back;
5588 }
5589
5590
5591
5592 /** Find allowed PRNG types using preferences.
5593 @param app Application structure.
5594 @return Or-combination of DK3_PRNG_xxx.
5595 */
5596 static
5597 int
5598 dk3app_rand_find_allowed_types(dk3_app_t *app)
5599 {
5600 int back = DK3_PRNG_ALL;
5601 dkChar buffer[256];
5602
5603 if(dk3app_get_pref(app,dk3app_no_loc[37],buffer,DK3_SIZEOF(buffer,dkChar)))
5604 {
5605 back = dk3app_get_allowed_prng_types(app, buffer);
5606 }
5607
5608 return back;
5609 }
5610
5611
5612
5613 /** Get bytes to seed random number generator.
5614 @param app Application structure.
5615 @param dp Destination buffer pointer.
5616 @param sz Number of bytes required.
5617 @param fn File name for seed file.
5618 @return Number of bytes found.
5619 */
5620 static
5621 size_t
5622 dk3app_read_bytes_from_file(
5623 dk3_app_t *app,
5624 void *dp,
5625 size_t sz,
5626 dkChar const *fn
5627 )
5628 {
5629 size_t back = 0;
5630 FILE *fipo;
5631 fipo = dk3sf_fopen_app(fn, dk3app_no_loc[36], app);
5632 if(fipo) {
5633 back = dk3sf_fread_app(dp, 1, sz, fipo, app);
5634 fclose(fipo);
5635 }
5636 return back;
5637 }
5638
5639
5640
5641
5642 /** Get bytes to seed random number generator.
5643 @param app Application structure.
5644 @param dp Destination buffer pointer.
5645 @param sz Number of bytes required.
5646 @param fn File name for seed file.
5647 @return Number of bytes found.
5648 */
5649 static
5650 size_t
5651 dk3app_get_seed_from_source(dk3_app_t *app,void *dp,size_t sz,dkChar const *fn)
5652 {
5653 size_t back = 0;
5654 dk3_stat_t stb;
5655 int can_use_file = 1;
5656 int mode_denied;
5657
5658 /* DEBUG: Attempting to get seed data from ... */
5659 dk3app_log_i3(app, DK3_LL_DEBUG, 196, 197, fn);
5660 if(dk3sf_stat_app(&stb, fn, NULL)) {
5661 switch((stb.ft) & (~(DK3_FT_SYMLINK))) {
5662 case DK3_FT_DIRECTORY: {
5663 /* Ignore it. */
5664 } break;
5665 case DK3_FT_REGULAR: {
5666 /* Security checks before using the file. */
5667 mode_denied = DK3_FPERM_G_READ
5668 | DK3_FPERM_G_WRITE
5669 | DK3_FPERM_O_READ
5670 | DK3_FPERM_O_WRITE;
5671 if((stb.ft) & DK3_FT_SYMLINK) {
5672 if((stb.ai) & DK3_STAT_AI_USER_DIFFERS) {
5673 can_use_file = 0;
5674 /* WARNING: Symlink owner is not file owner. */
5675 dk3app_log_i3(app, DK3_LL_ERROR, 185, 186, fn);
5676 }
5677 if((stb.perm) & mode_denied) {
5678 can_use_file = 0;
5679 /* WARNING: File not used (permissions). */
5680 dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn);
5681 } else {
5682 if((stb.lperm) & mode_denied) {
5683 can_use_file = 0;
5684 /* WARNING: File not used (permissions). */
5685 dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn);
5686 }
5687 }
5688 } else {
5689 if((stb.perm) & mode_denied) {
5690 can_use_file = 0;
5691 /* WARNING: File not used (permissions). */
5692 dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn);
5693 }
5694 }
5695 if(can_use_file) {
5696 back = dk3app_read_bytes_from_file(app, dp, sz, fn);
5697 }
5698 } break;
5699 default: {
5700 /* Use file. */
5701 back = dk3app_read_bytes_from_file(app, dp, sz, fn);
5702 } break;
5703 }
5704 }
5705 /* DEBUG: Seed data: ... bytes. */
5706 {
5707 char b1[64];
5708 dkChar b2[64];
5709 sprintf(b1, "%lu", (unsigned long)back);
5710 if(dk3str_cnv_c8_to_str_app(b2, DK3_SIZEOF(b2,dkChar), b1, app)) {
5711 dk3app_log_i3(app, DK3_LL_DEBUG, 198, 199, b2);
5712 }
5713 }
5714 return back;
5715 }
5716
5717
5718
5719 /** Get bytes to seed random number generator.
5720 @param app Application structure.
5721 @param dp Destination buffer pointer.
5722 @param sz Number of bytes required.
5723 @param fn File name for seed file.
5724 @param passno Pass number (only 0 uses files).
5725 @return Number of bytes found.
5726 */
5727 static
5728 size_t
5729 dk3app_get_seed_bytes(
5730 dk3_app_t *app,
5731 void *dp,
5732 size_t sz,
5733 dkChar const *fn,
5734 int passno
5735 )
5736 {
5737 size_t back = 0;
5738 dkChar const *p1;
5739 dkChar const *p2;
5740 dkChar const *p3;
5741 dkChar const *p4;
5742 dkChar const *p5;
5743 dkChar *p6;
5744 size_t s;
5745 dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */
5746 if((app) && (dp) && (sz)) {
5747 /* $HOME/.rnd-xxx-application */
5748 if(passno == 0) {
5749 if(dk3app_get_pref_bool(app, dk3app_no_loc[46], 1)) {
5750 p1 = dk3app_get_homedir(app);
5751 p2 = dk3app_no_loc[20];
5752 p3 = fn;
5753 p4 = dk3app_no_loc[5];
5754 p5 = dk3app_get_appname(app);
5755 if((p1) && (p2) && (p3) && (p4) && (p5)) {
5756 s = dk3str_len(p1);
5757 s += dk3str_len(p2);
5758 s += dk3str_len(p3);
5759 s += dk3str_len(p4);
5760 s += dk3str_len(p5);
5761 if(s < DK3_SIZEOF(fnb,dkChar)) {
5762 dk3str_cpy_not_overlapped(fnb, p1);
5763 dk3str_cat(fnb, p2);
5764 dk3str_cat(fnb, p3);
5765 dk3str_cat(fnb, p4);
5766 dk3str_cat(fnb, p5);
5767 back = dk3app_get_seed_from_source(app, dp, sz, fnb);
5768 }
5769 }
5770 }
5771 }
5772 /* EGD socket from environment. */
5773 if(back == 0) {
5774 p1 = dk3sf_getenv(dk3app_no_loc[43]);
5775 if(p1) {
5776 back = dk3app_get_seed_from_source(app, dp, sz, p1);
5777 }
5778 }
5779 /* EGD socket from preferences. */
5780 if(back == 0) {
5781 if(dk3app_get_pref(app, dk3app_no_loc[42], fnb, DK3_SIZEOF(fnb,dkChar)))
5782 {
5783 p6 = dk3str_start(fnb, NULL);
5784 if(p6) {
5785 dk3str_chomp(p6, NULL);
5786 back = dk3app_get_seed_from_source(app, dp, sz, p6);
5787 }
5788 }
5789 }
5790 #if !DK3_ON_WINDOWS
5791 /* /dev/urandom */
5792 if(back == 0) {
5793 back = dk3app_get_seed_from_source(app, dp, sz, dk3app_no_loc[44]);
5794 }
5795 /* /dev/random */
5796 if(back == 0) {
5797 back = dk3app_get_seed_from_source(app, dp, sz, dk3app_no_loc[45]);
5798 }
5799 #endif
5800 }
5801 return back;
5802 }
5803
5804
5805
5806 #if DK3_HAVE_OPENSSL_H
5807 /** Initialize OpenSSL PRNG.
5808 @param app Application structure.
5809 @return 1 on success, 0 on error.
5810 */
5811 static
5812 int
5813 dk3app_init_prng_openssl(dk3_app_t *app)
5814 {
5815 int back = 0;
5816 int cc = 0;
5817 int passno = 0;
5818 size_t sz;
5819 char seedval[DK3_SEED_OPENSSL_BYTES];
5820 do {
5821 cc = 0;
5822 sz =
5823 dk3app_get_seed_bytes(app,seedval,sizeof(seedval),dk3app_no_loc[41],passno);
5824 if(sz > 0) {
5825 cc = 1;
5826 RAND_seed(seedval, sz);
5827 if(RAND_status() == 1) {
5828 cc = 0; back = 1;
5829 }
5830 #if DK3_ON_WINDOWS
5831 if(back == 0) {
5832 RAND_screen();
5833 if(RAND_status() == 1) {
5834 cc = 0; back = 1;
5835 }
5836 }
5837 #endif
5838 passno++;
5839 }
5840 } while(cc);
5841 if(!back) {
5842 /* Warning: Failed to seed OpenSSL PRNG! */
5843 dk3app_log_i1(app, DK3_LL_ERROR, 182);
5844 }
5845 return back;
5846 }
5847 #endif
5848
5849 #if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM
5850 /** Initialize state PRNG.
5851 @param app Application structure.
5852 @return 1 on success, 0 on error.
5853 */
5854 static
5855 int
5856 dk3app_init_prng_state(dk3_app_t *app)
5857 {
5858 int back = 0;
5859 unsigned int seedval = 0;
5860 if(dk3app_get_seed_bytes(
5861 app, (void *)(&seedval), sizeof(unsigned int), dk3app_no_loc[40], 0
5862 )
5863 )
5864 {
5865 srandom(seedval);
5866 back = 1;
5867 }
5868 if(!back) {
5869 /* Warning: Failed to seed random() PRNG! */
5870 dk3app_log_i1(app, DK3_LL_ERROR, 181);
5871 }
5872 return back;
5873 }
5874 #endif
5875
5876 #if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48
5877 /** Initialize lrand48() PRNG.
5878 @param app Application structure.
5879 @return 1 on success, 0 on error.
5880 */
5881 static
5882 int
5883 dk3app_init_prng_rand48(dk3_app_t *app)
5884 {
5885 int back = 0;
5886 long int seedval = 0L;
5887 if(dk3app_get_seed_bytes(
5888 app, (void *)(&seedval), sizeof(long int), dk3app_no_loc[39], 0
5889 )
5890 )
5891 {
5892 srand48(seedval);
5893 back = 1;
5894 }
5895 if(!back) {
5896 /*Warning: Failed to seed lrand48() PRNG! */
5897 dk3app_log_i1(app, DK3_LL_ERROR, 180);
5898 }
5899 return back;
5900 }
5901 #endif
5902
5903 #if DK3_HAVE_RAND && DK3_HAVE_SRAND
5904 /** Initialize simple rand() PRNG.
5905 @param app Application structure.
5906 @return 1 on success, 0 on error.
5907 */
5908 static
5909 int
5910 dk3app_init_prng_simple(dk3_app_t *app)
5911 {
5912 int back = 0;
5913 unsigned int ui;
5914 if(
5915 dk3app_get_seed_bytes(
5916 app, (void *)(&ui), sizeof(unsigned int), dk3app_no_loc[38], 0
5917 )
5918 )
5919 {
5920 srand(ui);
5921 back = 1;
5922 }
5923 if(!back) {
5924 /* Warning: Failed to seed simple PRNG! */
5925 dk3app_log_i1(app, DK3_LL_ERROR, 179);
5926 }
5927 return back;
5928 }
5929 #endif
5930
5931
5932
5933 /** Attempt to initialize a PRNG.
5934 @param app Application structure.
5935 @param il Input line listing allowed PRNGs comma-separated.
5936 @return 1 on success (at least one PRNG usable), 0 on error.
5937 */
5938 int
5939 dk3app_rand_init(dk3_app_t *app, dkChar const *il)
5940 {
5941 int back = 0;
5942 int allowed_types;
5943 if(app) {
5944 if(app->f_rand_initialized) {
5945 back = app->f_rand_success;
5946 } else {
5947 app->f_rand_initialized = 1;
5948 if(il) {
5949 allowed_types = dk3app_get_allowed_prng_types(app, il);
5950 } else {
5951 allowed_types = dk3app_rand_find_allowed_types(app);
5952 }
5953 if(!back) {
5954 if(allowed_types & DK3_PRNG_OPENSSL) {
5955 #if DK3_HAVE_OPENSSL_H
5956 back = dk3app_init_prng_openssl(app);
5957 if(back) {
5958 app->rand_type = DK3_PRNG_OPENSSL;
5959 }
5960 #endif
5961 }
5962 }
5963 if(!back) {
5964 if(allowed_types & DK3_PRNG_STATE) {
5965 #if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM
5966 back = dk3app_init_prng_state(app);
5967 if(back) {
5968 app->rand_type = DK3_PRNG_STATE;
5969 }
5970 #endif
5971 }
5972 }
5973 if(!back) {
5974 if(allowed_types & DK3_PRNG_RAND48) {
5975 #if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48
5976 back = dk3app_init_prng_rand48(app);
5977 if(back) {
5978 app->rand_type = DK3_PRNG_RAND48;
5979 }
5980 #endif
5981 }
5982 }
5983 if(!back) {
5984 if(allowed_types & DK3_PRNG_SIMPLE) {
5985 #if DK3_HAVE_RAND && DK3_HAVE_SRAND
5986 back = dk3app_init_prng_simple(app);
5987 if(back) {
5988 app->rand_type = DK3_PRNG_SIMPLE;
5989 }
5990 #endif
5991 }
5992 }
5993 if(back) {
5994 app->f_rand_success = 1;
5995 }
5996 }
5997 }
5998 if(!back) {
5999 /* ERROR: No PRNG usable! */
6000 dk3app_log_i1(app, DK3_LL_ERROR, 178);
6001 }
6002 return back;
6003 }
6004
6005
6006
6007 /** Get random bytes.
6008 @param app Application structure.
6009 @param db Destination buffer.
6010 @param sz Size of \a db (number of bytes).
6011 @param f_crypto Flag: For cryptographic purposes.
6012 @return Number of bytes written to \a db.
6013 */
6014 static
6015 size_t
6016 dk3app_rand_bytes_internal(dk3_app_t *app, void *db, size_t sz, int f_crypto)
6017 {
6018 size_t back = 0;
6019 unsigned char *ucptr = NULL;
6020 size_t i = 0;
6021 unsigned u = 0;
6022 if((app) && (db) && (sz)) {
6023 ucptr = (unsigned char *)db;
6024 if(!(app->f_rand_initialized)) {
6025 dk3app_rand_init(app, NULL);
6026 }
6027 if(app->f_rand_success) {
6028 switch(app->rand_type) {
6029 case DK3_PRNG_OPENSSL: {
6030 #if DK3_HAVE_OPENSSL_RAND_H
6031 if(f_crypto) {
6032 if(RAND_bytes(ucptr, (int)sz) == 1) {
6033 back = sz;
6034 }
6035 } else {
6036 #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1010000FL
6037 if(RAND_bytes(ucptr, (int)sz) == 1) {
6038 back = sz;
6039 }
6040 #else
6041 if(RAND_pseudo_bytes(ucptr, (int)sz) > -1) {
6042 back = sz;
6043 }
6044 #endif
6045 }
6046 #else
6047 /* BUG: Not available! */
6048 #endif
6049 } break;
6050 case DK3_PRNG_STATE: {
6051 #if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM
6052 long lval;
6053 size_t position;
6054
6055 lval = random() >> 8;
6056 position = 0;
6057 for(i = 0; i < sz; i++) {
6058 *(ucptr++) = (unsigned char)(lval & 0x000000FFL);
6059 position++;
6060 lval = lval >> 8;
6061 if(position >= (sizeof(long) - 1)) {
6062 lval = random() >> 8;
6063 position = 0;
6064 }
6065 }
6066 back = sz;
6067 #else
6068 /* BUG: Not available! */
6069 #endif
6070 } break;
6071 case DK3_PRNG_RAND48: {
6072 #if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48
6073 long lval;
6074 size_t position;
6075
6076 lval = lrand48() >> 8;
6077 position = 0;
6078 for(i = 0; i < sz; i++) {
6079 *(ucptr++) = (unsigned char)(lval & 0x000000FFL);
6080 position++;
6081 lval = lval >> 8;
6082 if(position >= (sizeof(long) - 1)) {
6083 lval = lrand48() >> 8;
6084 position = 0;
6085 }
6086 }
6087 back = sz;
6088 #else
6089 /* BUG: Not available! */
6090 #endif
6091 } break;
6092 default: {
6093 #if DK3_HAVE_RAND && DK3_HAVE_SRAND
6094 for(i = 0; i < sz; i++) {
6095 u = rand();
6096 #if DK3_SIZEOF_INT > 2
6097 #if DK3_SIZEOF_INT > 4
6098 u = u >> 28;
6099 #else
6100 u = u >> 12;
6101 #endif
6102 #else
6103 u = u >> 4;
6104 #endif
6105 u &= 0x00FFU;
6106 *(ucptr++) = (unsigned char)u;
6107 }
6108 back = sz;
6109 #else
6110 /* BUG: Not available! */
6111 #endif
6112 } break;
6113 }
6114 }
6115 }
6116 if(back < sz) {
6117 /* ERROR: Failed to obtain enough random bytes! */
6118 dk3app_log_i1(app, DK3_LL_ERROR, 177);
6119 }
6120 return back;
6121 }
6122
6123
6124 size_t
6125 dk3app_rand_bytes(dk3_app_t *app, void *db, size_t sz)
6126 {
6127 size_t back;
6128 back = dk3app_rand_bytes_internal(app, db, sz, 1);
6129 return back;
6130 }
6131
6132
6133 size_t
6134 dk3app_rand_bytes_non_crypto(dk3_app_t *app, void *db, size_t sz)
6135 {
6136 size_t back;
6137 back = dk3app_rand_bytes_internal(app, db, sz, 0);
6138 return back;
6139 }
6140
6141 #endif
6142
6143
6144
6145 int
dk3app_process_stdin_lines(dk3_app_t * app,void * obj,dk3_line_handler_t * hf,dkChar * buffer,size_t szbuffer,int de)6146 dk3app_process_stdin_lines(
6147 dk3_app_t *app,
6148 void *obj,
6149 dk3_line_handler_t *hf,
6150 dkChar *buffer,
6151 size_t szbuffer,
6152 int de
6153 )
6154 {
6155 int back = 0;
6156 int must_run_directly = 0;
6157 int ie;
6158 FILE *fipo;
6159 dkChar tfn[DK3_MAX_PATH];
6160 char b[4096];
6161 size_t sz;
6162 #if DK3_ON_WINDOWS
6163 int oldmode;
6164 #endif
6165 if((app) && (hf) && (buffer) && (szbuffer)) {
6166 ie = de;
6167 if(ie < 0) { ie = app->i_stdin_input_encoding; }
6168 if(dk3app_get_temp_file_name(app, tfn, DK3_SIZEOF(tfn,dkChar))) {
6169 fipo = dk3sf_fopen_app(tfn, dk3app_no_loc[53], app);
6170 if(fipo) {
6171 #if DK3_ON_WINDOWS
6172 oldmode = _setmode(_fileno(stdin), _O_BINARY);
6173 #endif
6174 while((sz = dk3sf_fread_app(b, 1, sizeof(b), stdin, app)) > 0) {
6175 dk3sf_fwrite_app(b, 1, sz, fipo, app);
6176 }
6177 fclose(fipo);
6178 #if DK3_ON_WINDOWS
6179 _setmode(_fileno(stdin), oldmode);
6180 #endif
6181 /* 2015-08-21
6182 Using ie instead of de.
6183 */
6184 back = dk3stream_process_filename_lines_app(
6185 obj,
6186 hf,
6187 tfn,
6188 buffer,
6189 szbuffer,
6190 dk3app_get_encoding(app),
6191 ie,
6192 app
6193 );
6194 dk3sf_remove_file_app(tfn, app);
6195 } else {
6196 must_run_directly = 1;
6197 }
6198 } else {
6199 must_run_directly = 1;
6200 }
6201 if(must_run_directly) {
6202 #if DK3_ON_WINDOWS
6203 oldmode = _setmode(_fileno(stdin), _O_BINARY);
6204 #endif
6205 back = dk3stream_process_file_lines_app(
6206 obj,
6207 hf,
6208 stdin,
6209 NULL,
6210 buffer,
6211 szbuffer,
6212 dk3app_get_encoding(app),
6213 de,
6214 app
6215 );
6216 #if DK3_ON_WINDOWS
6217 _setmode(_fileno(stdin), oldmode);
6218 #endif
6219 }
6220 }
6221 return back;
6222 }
6223
6224
6225
6226 int
dk3app_process_stdin_chars(dk3_app_t * app,void * obj,dk3_char_handler_t * hf,int de)6227 dk3app_process_stdin_chars(
6228 dk3_app_t *app,
6229 void *obj,
6230 dk3_char_handler_t *hf,
6231 int de
6232 )
6233 {
6234 int back = 0;
6235 int must_run_directly = 0;
6236 int ie;
6237 dkChar tfn[DK3_MAX_PATH];
6238 char b[4096];
6239 FILE *fipo;
6240 size_t sz;
6241 #if DK3_ON_WINDOWS
6242 int oldmode;
6243 #endif
6244
6245 if((app) && (hf)) {
6246 ie = de;
6247 if(ie < 0) {
6248 ie = app->i_stdin_input_encoding;
6249 }
6250 if(dk3app_get_temp_file_name(app, tfn, DK3_SIZEOF(tfn,dkChar))) {
6251 fipo = dk3sf_fopen_app(tfn, dk3app_no_loc[53], app);
6252 if(fipo) {
6253 #if DK3_ON_WINDOWS
6254 oldmode = _setmode(_fileno(stdin), _O_BINARY);
6255 #endif
6256 while((sz = dk3sf_fread_app(b, 1, sizeof(b), stdin, app)) > 0) {
6257 dk3sf_fwrite_app(b, 1, sz, fipo, app);
6258 }
6259 fclose(fipo);
6260 #if DK3_ON_WINDOWS
6261 _setmode(_fileno(stdin), oldmode);
6262 #endif
6263 back = dk3stream_process_filename_chars_app(obj, hf, tfn, ie, app);
6264 dk3sf_remove_file_app(tfn, app);
6265 } else {
6266 must_run_directly = 1;
6267 }
6268 } else {
6269 must_run_directly = 1;
6270 }
6271 if(must_run_directly) {
6272 #if DK3_ON_WINDOWS
6273 oldmode = _setmode(_fileno(stdin), _O_BINARY);
6274 #endif
6275 back = dk3stream_process_file_chars_app(obj, hf, stdin, NULL, ie, app);
6276 #if DK3_ON_WINDOWS
6277 _setmode(_fileno(stdin), oldmode);
6278 #endif
6279 }
6280 }
6281 return back;
6282 }
6283
6284
6285
6286 #if !DK3_ON_WINDOWS
6287 #if DK3_HAVE_SETUID && DK3_HAVE_SETGID && DK3_HAVE_CHOWN
6288 #if DK3_CHAR_SIZE == 1
6289 /** Change owner for one file if the file exists.
6290 @param app Application structure.
6291 @param ul1 File name.
6292 @param ul2 File name suffix.
6293 @param uid New user ID for file ownership.
6294 @param gid New group ID for file ownership.
6295 @return 1 on success (owner modified or file does not exist).
6296 */
6297 static
6298 int
dk3app_change_owner_for_file(dk3_app_t * app,unsigned long ul1,unsigned ul2,uid_t uid,gid_t gid)6299 dk3app_change_owner_for_file(
6300 dk3_app_t *app,
6301 unsigned long ul1,
6302 unsigned ul2,
6303 uid_t uid,
6304 gid_t gid
6305 )
6306 {
6307 dkChar fnb[DK3_MAX_PATH]; /* Full name buffer. */
6308 dkChar smb[32]; /* Small buffer. */
6309 char tmb[32];
6310 dk3_stat_t stb;
6311 int back = 1;
6312
6313 sprintf(tmb, "/%08lx.%03x", ul1, ul2);
6314 if(dk3str_c8_to_str_simple_app(smb,DK3_SIZEOF(smb,dkChar),tmb,app)) {
6315 if(dk3str_len(app->n_tmpdir) < DK3_SIZEOF(fnb,dkChar)) {
6316 dk3str_cpy_not_overlapped(fnb, app->n_tmpdir);
6317 if((dk3str_len(fnb) + dk3str_len(smb)) < DK3_SIZEOF(fnb,dkChar)) {
6318 dk3str_cat(fnb, smb);
6319 dk3str_correct_filename(fnb);
6320 if(dk3sf_stat_app(&stb, fnb, NULL)) {
6321 if(0 != chown(fnb, uid, gid)) {
6322 back = 0;
6323 } else {
6324 }
6325 } else {
6326 /* If there is no such file, there is no need to change owner. */
6327 }
6328 } else {
6329 back = 0;
6330 }
6331 } else {
6332 back = 0;
6333 }
6334 } else {
6335 }
6336
6337 return back;
6338 }
6339
6340 int
dk3app_change_user(dk3_app_t * app,uid_t uid,gid_t gid)6341 dk3app_change_user(dk3_app_t *app, uid_t uid, gid_t gid)
6342 {
6343 FILE *fipo;
6344 unsigned long ul1;
6345 unsigned ul2;
6346 int back = 1;
6347
6348 if((app) && ((uid) || (gid))) {
6349 if(app->n_logfilename) {
6350 if (0 == app->cr_log) {
6351 dk3app_create_log_directory(app);
6352 app->cr_log = 1;
6353 }
6354 fipo = dk3sf_fopen_app(app->n_logfilename, dkT("a"), app);
6355 if(fipo) {
6356 fclose(fipo);
6357 }
6358 if(0 != chown(app->n_logfilename, uid, gid)) {
6359 back = 0;
6360 } else {
6361 }
6362 } else {
6363 }
6364 if(app->n_tmpdir) {
6365 if(0 != chown(app->n_tmpdir, uid, gid)) {
6366 back = 0;
6367 }
6368 if(app->i_tmpcarry) {
6369 for(ul1 = 0UL; ul1 < 0xFFFFFFFFUL; ul1++) {
6370 for(ul2 = 0U; ul2 < 0x00001000U; ul2++) {
6371 if(!dk3app_change_owner_for_file(app, ul1, ul2, uid, gid)) {
6372 back = 0;
6373 }
6374 }
6375 }
6376 for(ul2 = 0U; ul2 < 0x00001000U; ul2++) {
6377 if(!dk3app_change_owner_for_file(app, 0xFFFFFFFFUL, ul2, uid, gid)) {
6378 back = 0;
6379 }
6380 }
6381 } else {
6382 for(ul1 = 0UL; ul1 < app->ul_tmpname; ul1++) {
6383 for(ul2 = 0U; ul2 < 0x00001000U; ul2++) {
6384 if(!dk3app_change_owner_for_file(app, ul1, ul2, uid, gid)) {
6385 back = 0;
6386 }
6387 }
6388 }
6389 for(ul2 = 0U; ul2 < app->u_tmpsuffix; ul2++) {
6390 if(!dk3app_change_owner_for_file(app,app->ul_tmpname,ul2,uid,gid)) {
6391 back = 0;
6392 }
6393 }
6394 }
6395 } else {
6396 }
6397 } else {
6398 }
6399 return back;
6400 }
6401 #endif
6402 #endif
6403 #endif
6404
6405
6406
6407 int
dk3app_get_dir_from_pref(dk3_app_t * app,dkChar const * pn,dkChar * buf,size_t bs,int ch)6408 dk3app_get_dir_from_pref(
6409 dk3_app_t *app,
6410 dkChar const *pn,
6411 dkChar *buf,
6412 size_t bs,
6413 int ch
6414 )
6415 {
6416 int back = 0;
6417 if((app) && (pn) && (buf) && (bs)) {
6418 if(dk3app_get_pref(app, pn, buf, bs)) {
6419 if(ch) {
6420 if(dk3sf_is_dir_app(buf, NULL)) {
6421 back = 1;
6422 } else {
6423 /* ERROR: Directory does not exist! */
6424 dk3app_log_i3(app, DK3_LL_ERROR, 369, 370, pn);
6425 }
6426 } else {
6427 back = 1;
6428 }
6429 }
6430 }
6431 return back;
6432 }
6433
6434
6435
6436 /* vim: set ai sw=2 : */
6437
6438