1 /*
2 Copyright (C) 2015-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: dk-blks.ctr
12 */
13
14
15 /** @file dk-blks.c The dk-blks program.
16 the help_text array below shows details.
17 */
18
19
20
21 #include "dk4conf.h"
22
23 #include <stdio.h>
24 #if DK4_HAVE_STDLIB_H
25 #ifndef STDLIB_H_INCLUDED
26 #include <stdlib.h>
27 #define STDLIB_H_INCLUDED 1
28 #endif
29 #endif
30
31 #if DK4_HAVE_IO_H
32 #ifndef IO_H_INCLUDED
33 #include <io.h>
34 #define IO_H_INCLUDED 1
35 #endif
36 #endif
37
38 #if DK4_HAVE_UNISTD_H
39 #ifndef UNISTD_H_INCLUDED
40 #include <unistd.h>
41 #define UNISTD_H_INCLUDED 1
42 #endif
43 #endif
44
45 #if DK4_HAVE_PROCESS_H
46 #ifndef PROCESS_H_INCLUDED
47 #include <process.h>
48 #define PROCESS_H_INCLUDED 1
49 #endif
50 #endif
51
52 #if DK4_HAVE_SYS_TYPES_H
53 #ifndef SYS_TYPES_H_INCLUDED
54 #include <sys/types.h>
55 #define SYS_TYPES_H_INCLUDED 1
56 #endif
57 #endif
58
59 #if DK4_HAVE_SIGNAL_H
60 #ifndef SIGNAL_H_INCLUDED
61 #include <signal.h>
62 #define SIGNAL_H_INCLUDED 1
63 #endif
64 #endif
65
66 #if DK4_HAVE_ERRNO_H
67 #ifndef ERRNO_H_INCLUDED
68 #include <errno.h>
69 #define ERRNO_H_INCLUDED 1
70 #endif
71 #endif
72
73 #if DK4_HAVE_FCNTL_H
74 #ifndef FCNTL_H_INCLUDED
75 #include <fcntl.h>
76 #define FCNTL_H_INCLUDED 1
77 #endif
78 #endif
79
80 #if DK4_HAVE_STRING_H
81 #ifndef STRING_H_INCLUDED
82 #include <string.h>
83 #define STRING_H_INCLUDED 1
84 #endif
85 #endif
86
87 #include <libdk4base/dk4types.h>
88 #include <libdk4base/dk4const.h>
89 #include <libdk4base/dk4vers.h>
90 #include <libdk4app/dk4app.h>
91 #include <libdk4app/dk4aopt.h>
92 #include <libdk4base/dk4mem.h>
93 #include <libdk4app/dk4mema.h>
94 #include <libdk4base/dk4memrs.h>
95 #include <libdk4base/dk4numco.h>
96 #include <libdk4app/dk4fdrde.h>
97 #include <libdk4app/dk4fdwre.h>
98 #include <libdk4base/dk4unused.h>
99
100 #ifndef DK4WMAIN_H_INCLUDED
101 #include <libdk4base/dk4wmain.h>
102 #endif
103
104
105
106
107
108
109 #ifndef DK_BLKS_DEFAULT_BLOCK_SIZE
110 /** Default suitable for hard disks.
111 */
112 #define DK_BLKS_DEFAULT_BLOCK_SIZE 4096
113 #endif
114
115
116
117 /** Default help text, shown if help text file is not found.
118 */
119 static const dkChar * const help_text[] = {
120 dkT(""),
121 dkT("Create sequence of fixed size blocks."),
122 dkT(""),
123 dkT("dk-blks [<options>]"),
124 dkT(""),
125 dkT("Options:"),
126 dkT("-b <size>\tBlock size, positive integer number."),
127 dkT("\t\tYou can append `k', `m', `g', or `t' for multiples of 1024"),
128 dkT("\t\tor powers of it (i.e. 4k = 4096 bytes, 1m = 1048576 bytes...)."),
129 dkT(""),
130 dkT("--help\t\tShow this short help text."),
131 dkT("--manual\t*** SHOW FULL MANUAL. ***"),
132 dkT("--version\tShow version information."),
133 dkT("--license\tShow license information."),
134 dkT(""),
135 dkT("http://sourceforge.net/p/dktools/wiki/dk-blks/"),
136 dkT(""),
137 NULL
138
139 };
140
141
142 /** License conditions.
143 */
144 static const dkChar * const license_text[] = {
145 dkT("This software uses code from the following projects, either directly or as"),
146 dkT("a library:"),
147 dkT(""),
148 dkT("dktools\t\tDirk Krause's tools and libraries."),
149 dkT("\t\tSee http://sourceforge.net/p/dktools/wiki/Home/"),
150 dkT("\t\tfor more information."),
151 #if DK4_HAVE_ZLIB_H
152 dkT(""),
153 dkT("zlib\t\tData compression library."),
154 dkT("\t\tSee http://www.zlib.net/ for more information."),
155 #endif
156 #if DK4_HAVE_BZLIB_H
157 dkT(""),
158 dkT("bzip2\t\tData compression program and library."),
159 dkT("\t\tSee http://www.bzip.org/ for more information."),
160 #endif
161 dkT(""),
162 dkT("All the licenses below apply to the program."),
163 dkT("Licenses for used libraries are shown as found on my Scientific Linux 6.x"),
164 dkT("computer in the /usr/share/doc directory on 2015-04-01. Check the project"),
165 dkT("homepages of the used libraries for additional information and/or updated"),
166 dkT("license terms."),
167 dkT(""),
168 dkT(""),
169 dkT("DK tools and libraries license"),
170 dkT("=============================="),
171 dkT("Copyright (c) 2015-2016, Dirk Krause"),
172 dkT("All rights reserved."),
173 dkT(""),
174 dkT("Redistribution and use in source and binary forms, with or without"),
175 dkT("modification, are permitted provided that the following conditions are met:"),
176 dkT(""),
177 dkT("1. Redistributions of source code must retain the above copyright notice,"),
178 dkT(" this list of conditions and the following disclaimer."),
179 dkT("2. Redistributions in binary form must reproduce the above copyright"),
180 dkT(" notice, this list of conditions and the following disclaimer in the"),
181 dkT(" documentation and/or other materials provided with the distribution."),
182 dkT("3. Neither the name of the copyright holder nor the names of its"),
183 dkT(" contributors may be used to endorse or promote products derived from"),
184 dkT(" this software without specific prior written permission."),
185 dkT(""),
186 dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"),
187 dkT("``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT"),
188 dkT("LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR"),
189 dkT("A PARTICULAR PURPOSE ARE DISCLAIMED."),
190 dkT("IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY"),
191 dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES"),
192 dkT("(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR"),
193 dkT("SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER"),
194 dkT("CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT"),
195 dkT("LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY"),
196 dkT("OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF"),
197 dkT("SUCH DAMAGE."),
198 dkT(""),
199 #if DK4_HAVE_ZLIB_H
200 dkT(""),
201 dkT(""),
202 dkT("Zlib license"),
203 dkT("============"),
204 dkT("(C) 1995-2004 Jean-loup Gailly and Mark Adler"),
205 dkT(""),
206 dkT("This software is provided 'as-is', without any express or implied"),
207 dkT("warranty. In no event will the authors be held liable for any damages"),
208 dkT("arising from the use of this software."),
209 dkT(""),
210 dkT("Permission is granted to anyone to use this software for any purpose,"),
211 dkT("including commercial applications, and to alter it and redistribute it"),
212 dkT("freely, subject to the following restrictions:"),
213 dkT(""),
214 dkT("1. The origin of this software must not be misrepresented; you must not"),
215 dkT(" claim that you wrote the original software. If you use this software"),
216 dkT(" in a product, an acknowledgment in the product documentation would be"),
217 dkT(" appreciated but is not required."),
218 dkT("2. Altered source versions must be plainly marked as such, and must not be"),
219 dkT(" misrepresented as being the original software."),
220 dkT("3. This notice may not be removed or altered from any source distribution."),
221 dkT(""),
222 dkT("Jean-loup Gailly Mark Adler"),
223 dkT("jloup@gzip.org madler@alumni.caltech.edu"),
224 #endif
225 #if DK4_HAVE_BZLIB_H
226 dkT(""),
227 dkT(""),
228 dkT("Bzip2 and libbzip2 library license"),
229 dkT("=================================="),
230 dkT("This program, \"bzip2\", the associated library \"libbzip2\", and all"),
231 dkT("documentation, are copyright (C) 1996-2007 Julian R Seward. All"),
232 dkT("rights reserved."),
233 dkT(""),
234 dkT("Redistribution and use in source and binary forms, with or without"),
235 dkT("modification, are permitted provided that the following conditions"),
236 dkT("are met:"),
237 dkT(""),
238 dkT("1. Redistributions of source code must retain the above copyright"),
239 dkT(" notice, this list of conditions and the following disclaimer."),
240 dkT(""),
241 dkT("2. The origin of this software must not be misrepresented; you must "),
242 dkT(" not claim that you wrote the original software. If you use this "),
243 dkT(" software in a product, an acknowledgment in the product "),
244 dkT(" documentation would be appreciated but is not required."),
245 dkT(""),
246 dkT("3. Altered source versions must be plainly marked as such, and must"),
247 dkT(" not be misrepresented as being the original software."),
248 dkT(""),
249 dkT("4. The name of the author may not be used to endorse or promote "),
250 dkT(" products derived from this software without specific prior written "),
251 dkT(" permission."),
252 dkT(""),
253 dkT("THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS"),
254 dkT("OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED"),
255 dkT("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"),
256 dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY"),
257 dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"),
258 dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE"),
259 dkT("GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"),
260 dkT("INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,"),
261 dkT("WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"),
262 dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS"),
263 dkT("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."),
264 dkT(""),
265 dkT("Julian Seward, jseward@bzip.org"),
266 dkT("bzip2/libbzip2 version 1.0.5 of 10 December 2007"),
267 #endif
268 dkT(""),
269 NULL
270
271 };
272
273
274
275 /** Options used by program.
276 */
277 static const dk4_option_specification_t options[] = {
278 { dkT('b'), dkT("block-size"), DK4_OPT_ARG_SIZE }
279 };
280
281 /** Number of elements in options array.
282 */
283 static const size_t sz_options =
284 sizeof(options)/sizeof(dk4_option_specification_t);
285
286
287
288 /** Keywords used by the program, not localized.
289 */
290 static const dkChar * const kwnl[] = {
291 /* 0 */
292 dkT("dktools"),
293
294 /* 1 */
295 dkT("dk-blks.txt"),
296
297 /* 2 */
298 dkT("dk-blks.str"),
299
300 /* 3 */
301 dkT("stdin"),
302
303 /* 4 */
304 dkT("stdout"),
305
306 NULL
307
308 };
309
310
311
312 /** Constant texts used by the program, replaced by localized texts
313 if available.
314 */
315 static const dkChar * const kw_def[] = {
316 /* 0 */
317 dkT("Write operation partially failed!"),
318
319 /* 1 */
320 dkT("Failed to cleanup buffer!"),
321
322 /* 2 */
323 dkT("Block size too large!"),
324
325 /* 3 */
326 dkT("Block size must not be 0!"),
327
328 /* 4 */
329 dkT("Failed to set up signal handlers!"),
330
331 /* 5 */
332 dkT("Failed to restore signal handlers!"),
333
334 /* 6 */
335 dkT("Signal SIGPIPE received, write operation failed!"),
336
337 /* 7 */
338 dkT("Signal SIGINT received, program aborted!"),
339
340 /* 8 */
341 dkT("Unexpected command line argument \""),
342
343 /* 9 */
344 dkT("\" ignored!"),
345
346 NULL
347
348 };
349
350
351
352 /** Message texts, localized texts are used if available.
353 */
354 static const dkChar * const *dk_blks_msg = kw_def;
355
356
357
358 /** Number of elements in dk_blks_msg array.
359 */
360 static size_t sz_msg =
361 sizeof(kw_def)/sizeof(DK4_PCDKCHAR) - 1;
362
363
364
365 /** Exit status code.
366 */
367 static int exval = EXIT_FAILURE;
368
369
370
371 /** Application structure.
372 */
373 static dk4_app_t *app = NULL;
374
375
376
377 /** Input buffer for buffer sizes up to DK_BLKS_DEFAULT_BLOCK_SIZE.
378 */
379 static char default_input_buffer[DK_BLKS_DEFAULT_BLOCK_SIZE];
380
381
382
383 /** Output buffer for buffer sizes up to DK_BLKS_DEFAULT_BLOCK_SIZE.
384 */
385 static char default_output_buffer[sizeof(default_input_buffer)];
386
387
388
389 #ifdef RW_MAX
390 #undef RW_MAX
391 #endif
392
393 #if DK4_ON_WINDOWS
394 /** Maximum number of bytes for read or write operation.
395 */
396 #define RW_MAX (INT_MAX)
397 #else
398 /** Maximum number of bytes for read or write operation.
399 */
400 #define RW_MAX ((SIZE_MAX) / 2U)
401 #endif
402
403
404
405 #ifdef SIGPIPE
406 /** Indicator: SIGPIPE signal received.
407 */
408 static
409 DK4_VOLATILE
410 dk4_sig_atomic_t sig_had_pipe = 0;
411 #endif
412
413 /** Indicator: SIGINT signal received.
414 */
415 static
416 DK4_VOLATILE
417 dk4_sig_atomic_t sig_had_int = 0;
418
419 /** Indicator: SIGTERM signal received.
420 */
421 static
422 DK4_VOLATILE
423 dk4_sig_atomic_t sig_had_term = 0;
424
425 static
426 DK4_VOLATILE
427 dk4_sig_atomic_t *
sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t * ptr)428 sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr)
429 {
430 return ptr;
431 }
432
433 #ifdef SIGPIPE
434 /** Handler for SIGPIPE signal.
435 @param signo Signal number (always SIGPIPE, ignored).
436 */
437 static
438 void
sig_handler_pipe(int DK4_ARG_UNUSED (signo))439 sig_handler_pipe(int DK4_ARG_UNUSED(signo) )
440 {
441 DK4_UNUSED_ARG(signo)
442 *sig_pass_pointer(&sig_had_pipe) = 1;
443 }
444 #endif
445
446 /** Handler for SIGINT signal.
447 @param signo Signal number (always SIGINT, ignored).
448 */
449 static
450 void
sig_handler_int(int DK4_ARG_UNUSED (signo))451 sig_handler_int(int DK4_ARG_UNUSED(signo) )
452 {
453 DK4_UNUSED_ARG(signo)
454 *sig_pass_pointer(&sig_had_int) = 1;
455 }
456
457 /** Handler for SIGTERM signal.
458 @param signo Signal number (always SIGTERM, ignored).
459 */
460 static
461 void
sig_handler_term(int DK4_ARG_UNUSED (signo))462 sig_handler_term(int DK4_ARG_UNUSED(signo) )
463 {
464 DK4_UNUSED_ARG(signo)
465 *sig_pass_pointer(&sig_had_term) = 1;
466 }
467
468 /** Read value from volatile atomic type.
469 This function is necessary as some compilers mis-optimize
470 direct access to volatile variables (at least if you believe
471 one of the coding standards).
472 @param ap Pointer to volatile atomic variable.
473 @return Contents of the variable.
474 */
475 static
476 dk4_sig_atomic_t
sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t * ap)477 sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap)
478 {
479 return (*ap);
480 }
481
482 /** Check whether we can continue or if a signal was received.
483 @param check_pipe Flag: Check for occured SIGPIPE signal too.
484 @return 1 if the program can continue, 0 if a signal was received.
485 */
486 static
487 int
sig_can_continue(int check_pipe)488 sig_can_continue(
489 #ifdef SIGPIPE
490 int check_pipe
491 #else
492 int DK4_ARG_UNUSED(check_pipe)
493 #endif
494 )
495 {
496 int back = 1;
497 #ifndef SIGPIPE
498 DK4_UNUSED_ARG(check_pipe)
499 #else
500 if (0 != check_pipe) {
501 if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; }
502 }
503 #endif
504 if (0 != sig_read_atomic(&sig_had_int )) { back = 0; }
505 if (0 != sig_read_atomic(&sig_had_term)) { back = 0; }
506 return back;
507 }
508
509
510
511 static
512 void
dk_blks_transfer(char * ib,char * ob,size_t bs)513 dk_blks_transfer(char *ib, char *ob, size_t bs)
514 {
515 int cc = 1; /* Flag: Can continue */
516 size_t irdb = 0; /* Bytes in input buffer */
517 size_t iused = 0; /* Input bytes used */
518 size_t oused = 0; /* Output bytes used */
519 size_t iavail; /* Input bytes available */
520 size_t oavail; /* Output bytes available */
521 size_t bcp; /* Bytes to copy */
522 #if DK4_ON_WINDOWS
523 int rdres; /* Number of bytes read */
524 int wrres; /* Number of bytes written */
525 #else
526 ssize_t rdres; /* Number of bytes read */
527 ssize_t wrres; /* Number of bytes written */
528 #endif
529 dk4_sig_atomic_t shp; /* Had pipe */
530
531 /* Process input
532 */
533 exval = EXIT_SUCCESS;
534 do {
535 if (1 == sig_can_continue(0)) {
536 errno = 0;
537 #if DK4_ON_WINDOWS
538 rdres = _read(0, ib, (unsigned)bs);
539 #else
540 rdres = read(0, ib, bs);
541 #endif
542 if (0 < rdres) {
543 irdb = (size_t)rdres;
544 iused = 0;
545 while(iused < irdb) {
546 /* Find number of bytes we can add to output buffer */
547 iavail = irdb - iused;
548 oavail = bs - oused;
549 if (iavail < oavail) {
550 bcp = iavail;
551 } else {
552 bcp = oavail;
553 }
554 /* Add bytes to output buffer */
555 DK4_MEMCPY(&(ob[oused]), &(ib[iused]), bcp);
556 /* Increased number of used bytes for both input and output */
557 oused += bcp;
558 iused += bcp;
559 /* Flush output buffer when full */
560 if (oused >= bs) {
561 #ifdef SIGPIPE
562 shp = sig_read_atomic(&sig_had_pipe);
563 #else
564 shp = 0;
565 #endif
566 if (0 == shp) {
567 errno = 0;
568 #if DK4_ON_WINDOWS
569 wrres = _write(1, ob, (unsigned)bs);
570 #else
571 wrres = write(1, ob, bs);
572 #endif
573 if (0 <= wrres) {
574 if (((size_t)wrres) < bs) {
575 /* ERROR: Not all bytes written */
576 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 0);
577 exval = EXIT_FAILURE;
578 cc = -1;
579 }
580 } else {
581 /* ERROR Write attempt failed */
582 dk4fd_write_error_msg(app, kwnl[4], errno);
583 exval = EXIT_FAILURE;
584 cc = -1;
585 }
586 }
587 oused = 0;
588 }
589 }
590 } else {
591 if (0 == rdres) {
592 cc = 0;
593 } else {
594 /* ERROR: Read operation failed */
595 dk4fd_read_error_msg(app, kwnl[3], errno);
596 cc = 0;
597 exval = EXIT_FAILURE;
598 }
599 }
600 #if DK4_ON_WINDOWS
601 if (_eof(0)) {
602 cc = 0;
603 }
604 #endif
605 } else {
606 cc = -1;
607 }
608 } while (1 == cc);
609
610 /* Flush output buffer */
611 if (0 == cc) {
612 if (0 < oused) {
613 #ifdef SIGPIPE
614 shp = sig_read_atomic(&sig_had_pipe);
615 #else
616 shp = 0;
617 #endif
618 if (0 == shp) {
619 errno = 0;
620 #if DK4_ON_WINDOWS
621 wrres = _write(1, ob, (unsigned)oused);
622 #else
623 wrres = write(1, ob, oused);
624 #endif
625 if (0 <= wrres) {
626 if (((size_t)wrres) < oused) {
627 /* ERROR: Not all bytes written */
628 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 0);
629 exval = EXIT_FAILURE;
630 }
631 } else {
632 /* ERROR: Write attempt failed */
633 dk4fd_write_error_msg(app, kwnl[4], errno);
634 exval = EXIT_FAILURE;
635 }
636 }
637 }
638 }
639
640 /* Finally zero-fill used buffers.
641 */
642 if (0 == dk4mem_reset_secure(ib, bs, NULL)) {
643 /* ERROR: Secure memory reset failed */
644 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 1);
645 exval = EXIT_FAILURE;
646 }
647 if (0 == dk4mem_reset_secure(ob, bs, NULL)) {
648 /* ERROR: Secure memory reset failed */
649 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 1);
650 exval = EXIT_FAILURE;
651 }
652
653
654 }
655
656
657
658 static
659 void
dk_blks_with_buffers(char * ib,char * ob,size_t bs)660 dk_blks_with_buffers(char *ib, char *ob, size_t bs)
661 {
662 #if DK4_ON_WINDOWS
663 int oldinmode = 0;
664 int oldoutmode = 0;
665 #endif
666 if ((dk4_um_t)RW_MAX >= (dk4_um_t)bs) {
667 #if DK4_ON_WINDOWS
668 oldinmode = _setmode(0, _O_BINARY);
669 oldoutmode = _setmode(1, _O_BINARY);
670 #endif
671 dk_blks_transfer(ib, ob, bs);
672 #if DK4_ON_WINDOWS
673 _setmode(1, oldoutmode);
674 _setmode(0, oldinmode);
675 #endif
676 } else {
677 /* ERROR: Block size too large */
678 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 2);
679 }
680 }
681
682
683
684 /** Run normally.
685 */
686 static
687 void
dk_blks_normal_run(void)688 dk_blks_normal_run(void)
689 {
690 char *myib;
691 char *myob;
692 size_t mybs = DK_BLKS_DEFAULT_BLOCK_SIZE;
693 int res = 0;
694
695 if (0 != dk4app_opt_is_set_short(app, dkT('b'), NULL)) {
696 res = dk4app_opt_get_size_short(&mybs, app, dkT('b'), NULL);
697 if (0 == res) {
698 mybs = DK_BLKS_DEFAULT_BLOCK_SIZE;
699 }
700 }
701 if ((0 < mybs) && (mybs <= DK_BLKS_DEFAULT_BLOCK_SIZE)) {
702 dk_blks_with_buffers(
703 default_input_buffer,
704 default_output_buffer,
705 mybs
706 );
707 } else {
708 if (0 < mybs) {
709 myib = (char *)dk4mem_calloc_app(1, mybs, app);
710 if (NULL != myib) {
711 myob = (char *)dk4mem_calloc_app(1, mybs, app);
712 if (NULL != myob) {
713 dk_blks_with_buffers(myib, myob, mybs);
714 dk4mem_free(myob);
715 }
716 dk4mem_free(myib);
717 }
718 } else {
719 /* ERROR: Illegal block size */
720 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 3);
721 }
722 }
723
724 }
725
726
727
728 #if DK4_HAVE_SIGACTION
729 /** Set signal handlers and run.
730 */
731 static
732 void
run_with_signals(void)733 run_with_signals(void)
734 {
735 #ifdef SIGPIPE
736 struct sigaction opipe;
737 #endif
738 struct sigaction oint;
739 struct sigaction oterm;
740 #ifdef SIGPIPE
741 struct sigaction npipe;
742 #endif
743 struct sigaction nint;
744 struct sigaction nterm;
745 int success = 0;
746
747 #ifdef SIGPIPE
748 /* Set up signal handling for SIGPIPE.
749 */
750 DK4_MEMRES(&npipe, sizeof(npipe));
751 npipe.sa_handler = sig_handler_pipe;
752 npipe.sa_flags = 0;
753 if (0 != sigemptyset(&npipe.sa_mask)) {
754 /* ERROR: Failed to set up masked signal set for SIGPIPE */
755 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
756 goto finished;
757 }
758 if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) {
759 /* ERROR: Failed to set up masked signal set for SIGPIPE */
760 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
761 goto finished;
762 }
763 if (0 != sigaction(SIGPIPE, &npipe, &opipe)) {
764 /* ERROR: Failed to set up signal handler for SIGPIPE */
765 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
766 goto finished;
767 }
768 #endif
769
770 /* Set up signal handling for SIGINT.
771 */
772 DK4_MEMRES(&nint, sizeof(nint));
773 nint.sa_handler = sig_handler_int;
774 nint.sa_flags = 0;
775 if (0 != sigemptyset(&nint.sa_mask)) {
776 /* ERROR: Failed to set up masked signal set for SIGINT */
777 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
778 goto restore_old_pipe;
779 }
780 if (0 != sigaddset(&nint.sa_mask, SIGINT)) {
781 /* ERROR: Failed to set up masked signal set for SIGINT */
782 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
783 goto restore_old_pipe;
784 }
785 if (0 != sigaction(SIGINT, &nint, &oint)) {
786 /* ERROR: Failed to set up signal handler for SIGINT */
787 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
788 goto restore_old_pipe;
789 }
790
791 /* Set up signal handling for SIGTERM
792 */
793 DK4_MEMRES(&nterm, sizeof(nterm));
794 nterm.sa_handler = sig_handler_term;
795 nterm.sa_flags = 0;
796 if (0 != sigemptyset(&nterm.sa_mask)) {
797 /* ERROR: Failed to set up masked signal set for SIGTERM */
798 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
799 goto restore_old_int;
800 }
801 if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) {
802 /* ERROR: Failed to set up masked signal set for SIGTERM */
803 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
804 goto restore_old_int;
805 }
806 if (0 != sigaction(SIGTERM, &nterm, &oterm)) {
807 /* ERROR: Failed to set up signal handler for SIGTERM */
808 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 4);
809 goto restore_old_int;
810 }
811
812 success = 1;
813 dk_blks_normal_run();
814
815 /* Restore signal handling for SIGTERM.
816 */
817 if (0 != sigaction(SIGTERM, &oterm, NULL)) {
818 /* ERROR: Failed to restore old SIGTERM settings */
819 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 5);
820 success = 0;
821 }
822
823 /* Restore signal handling for SIGINT.
824 */
825 restore_old_int:
826 if (0 != sigaction(SIGINT, &oint, NULL)) {
827 /* ERROR: Failed to restore old SIGPIPE settings */
828 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 5);
829 success = 0;
830 }
831
832 #ifdef SIGPIPE
833 /* Restore signal handling for SIGPIPE.
834 */
835 restore_old_pipe:
836 if (0 != sigaction(SIGPIPE, &opipe, NULL)) {
837 /* ERROR: Failed to restore old SIGPIPE settings */
838 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 5);
839 success = 0;
840 }
841 #endif
842
843 /* Set exit status code if error occured.
844 */
845 finished:
846 if (0 == success) { exval = EXIT_FAILURE; }
847 }
848 #else
849 #if DK4_HAVE_SIGSET
850 /** Set signal handlers and run.
851 */
852 static
853 void
run_with_signals(void)854 run_with_signals(void)
855 {
856 #ifdef SIGPIPE
857 dk4_sig_handler_t *oldpipe = NULL;
858 #endif
859 dk4_sig_handler_t *oldint = NULL;
860 dk4_sig_handler_t *oldterm = NULL;
861
862 #ifdef SIGPIPE
863 oldpipe = sigset(SIGPIPE, sig_handler_pipe);
864 #endif
865 oldint = sigset(SIGINT, sig_handler_int);
866 oldterm = sigset(SIGTERM, sig_handler_term);
867 dk_blks_normal_run();
868 sigset(SIGTERM, oldterm);
869 sigset(SIGINT, oldint);
870 #ifdef SIGPIPE
871 sigset(SIGPIPE, oldpipe);
872 #endif
873 }
874 #else
875 #if DK4_HAVE_SIGNAL
876 /** Set signal handlers and run.
877 */
878 static
879 void
run_with_signals(void)880 run_with_signals(void)
881 {
882 #ifdef SIGPIPE
883 dk4_sig_handler_t *oldpipe = NULL;
884 #endif
885 dk4_sig_handler_t *oldint = NULL;
886 dk4_sig_handler_t *oldterm = NULL;
887
888 #ifdef SIGPIPE
889 oldpipe = signal(SIGPIPE, sig_handler_pipe);
890 #endif
891 oldint = signal(SIGINT, sig_handler_int);
892 oldterm = signal(SIGTERM, sig_handler_term);
893 dk_blks_normal_run();
894 signal(SIGTERM, oldterm);
895 signal(SIGINT, oldint);
896 #ifdef SIGPIPE
897 signal(SIGPIPE, oldpipe);
898 #endif
899 }
900 #else
901 /** Set signal handlers and run.
902 */
903 static
904 void
run_with_signals(void)905 run_with_signals(void)
906 {
907 dk_blks_normal_run();
908 }
909 #endif
910 #endif
911 #endif
912
913
914 /** Main function.
915 @param argc Number of command line arguments.
916 @param argv Command line arguments array.
917 @return 0 on success, all other values indicate errors.
918 */
919 #if DK4_CHAR_SIZE > 1
wmain(int argc,wchar_t * argv[])920 int wmain(int argc, wchar_t *argv[])
921 #else
922 int main(int argc, char *argv[])
923 #endif
924 {
925 dkChar const *xargv;
926 int xargc;
927 int i;
928
929
930 app = dk4app_open_cmd(
931 argc, argv, options, sz_options, kwnl[0], DKT_VERSION_DK,
932 kwnl[1], help_text, license_text
933 );
934 if (NULL != app) {
935 sz_msg = dk4app_string_table_size(kw_def);
936 dk_blks_msg = dk4app_string_table(app, kwnl[2], kw_def);
937 if (0 != dk4app_can_run_normally(app)) {
938 run_with_signals();
939 xargc = dk4app_get_argc(app);
940 if (0 < xargc) {
941 for (i = 0; i < xargc; i++) {
942 xargv = dk4app_get_argv(app, i);
943 if (NULL != xargv) {
944 dk4app_log_3(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 8, 9, xargv);
945 exval = EXIT_FAILURE;
946 }
947 }
948 }
949 #ifdef SIGPIPE
950 if (0 != sig_read_atomic(&sig_had_pipe)) {
951 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 6);
952 exval = EXIT_FAILURE;
953 }
954 #endif
955 if (0 != sig_read_atomic(&sig_had_int)) {
956 dk4app_log_1(app, dk_blks_msg, sz_msg, DK4_LL_ERROR, 7);
957 exval = EXIT_FAILURE;
958 }
959 } else {
960 if (0 != dk4app_help_version_license(app)) {
961 exval = EXIT_SUCCESS;
962 }
963 }
964 dk4app_close(app); app = NULL;
965 } else {
966 }
967
968
969 exit(exval); return exval;
970 }
971
972