1%%	options
2
3copyright owner	=	Dirk Krause
4copyright year	=	2016-xxxx
5SPDX-License-Identifier:	BSD-3-Clause
6
7
8
9%%	module
10
11/*
12	Convert text to database.
13
14	See help_text below.
15*/
16
17#include "dk4conf.h"
18
19#include <stdio.h>
20
21#if DK4_HAVE_STDLIB_H
22#ifndef STDLIB_H_INCLUDED
23#include <stdlib.h>
24#define	STDLIB_H_INCLUDED 1
25#endif
26#endif
27
28#if DK4_HAVE_UNISTD_H
29#ifndef UNISTD_H_INCLUDED
30#include <unistd.h>
31#define	UNISTD_H_INCLUDED 1
32#endif
33#endif
34
35#if DK4_HAVE_PROCESS_H
36#ifndef PROCESS_H_INCLUDED
37#include <process.h>
38#define	PROCESS_H_INCLUDED 1
39#endif
40#endif
41
42#if DK4_HAVE_IO_H
43#ifndef IO_H_INCLUDED
44#include <io.h>
45#define IO_H_INCLUDED 1
46#endif
47#endif
48
49#if DK4_HAVE_FCNTL_H
50#ifndef FCNTL_H_INCLUDED
51#include <fcntl.h>
52#define FCNTL_H_INCLUDED 1
53#endif
54#endif
55
56#if DK4_HAVE_SYS_TYPES_H
57#ifndef SYS_TYPES_H_INCLUDED
58#include <sys/types.h>
59#define SYS_TYPES_H_INCLUDED 1
60#endif
61#endif
62
63#if DK4_HAVE_SIGNAL_H
64#ifndef SIGNAL_H_INCLUDED
65#include <signal.h>
66#define	SIGNAL_H_INCLUDED 1
67#endif
68#endif
69
70#include <libdk4base/dk4const.h>
71#include <libdk4base/dk4mem.h>
72#include <libdk4app/dk4mema.h>
73#include <libdk4base/dk4error.h>
74#include <libdk4dbi/dk4dbi.h>
75#include <libdk4dbi/dk4dbit8.h>
76#include <libdk4dbi/dk4dbitw.h>
77#include <libdk4dbi/dk4dbit.h>
78#include <libdk4dbia/dk4dbia.h>
79#include <libdk4c/dk4fput.h>
80#include <libdk4base/dk4vers.h>
81#include <libdk4app/dk4app.h>
82#include <libdk4app/dk4aopt.h>
83#include <libdk4ma/dk4maasz.h>
84#include <libdk4c/dk4enc.h>
85#include <libdk4c/dk4fopt.h>
86#include <libdk4app/dk4fopda.h>
87#include <libdk4c/dk4tspdk.h>
88#include <libdk4base/dk4strd.h>
89#include <libdk4maiodd/dk4maodd.h>
90#include <libdk4base/dk4mpl.h>
91#include <libdk4c/dk4pathd.h>
92#include <libdk4base/dk4unused.h>
93
94#ifndef	DK4WMAIN_H_INCLUDED
95#include <libdk4base/dk4wmain.h>
96#endif
97
98
99$!trace-include
100
101
102
103static const dkChar * const	help_text[]  = {
104$!text	macro=dkT
105
106dk-t2db - Convert text to simple database
107-----------------------------------------
108
109dk-t2db [<option>] [<file>...] <database>
110
111Options:
112
113-a		--add				Append to existing database.
114-l <size>	--line-size=<size>		Line buffer size.
115-k <size>	--key-buffer-size=<size>	Key buffer size.
116-v <size>	--value-buffer-size=<size>	Value buffer size.
117-i <string>	--input-encoding=<string>	Expected input encoding.
118
119--help						Show short help text.
120--manual					*** SHOW FULL MANUAL ***
121--version					Show version information.
122--license					Show license information.
123
124$!end
125};
126
127
128/**	License conditions.
129*/
130static const dkChar * const	license_text[] = {
131$!text	macro=dkT,preprocessor
132
133This software uses code from the following projects, either directly or as
134a library:
135
136dktools		Dirk Krause's tools and libraries.
137		See http://sourceforge.net/p/dktools/wiki/Home/
138		for more information.
139#if DK4_HAVE_ZLIB_H
140
141zlib		Data compression library.
142		See http://www.zlib.net/ for more information.
143#endif
144#if DK4_HAVE_BZLIB_H
145
146bzip2		Data compression program and library.
147		See http://www.bzip.org/ for more information.
148#endif
149
150All the licenses below apply to the program.
151Licenses for used libraries are shown as found on my Scientific Linux 6.x
152computer in the /usr/share/doc directory on 2015-04-01. Check the project
153homepages of the used libraries for additional information and/or updated
154license terms.
155
156
157DK tools and libraries license
158==============================
159Copyright (c) 2016, Dirk Krause
160All rights reserved.
161
162Redistribution and use in source and binary forms, with or without
163modification, are permitted provided that the following conditions are met:
164
1651. Redistributions of source code must retain the above copyright notice,
166   this list of conditions and the following disclaimer.
1672. Redistributions in binary form must reproduce the above copyright
168   notice, this list of conditions and the following disclaimer in the
169   documentation and/or other materials provided with the distribution.
1703. Neither the name of the copyright holder nor the names of its
171   contributors may be used to endorse or promote products derived from
172   this software without specific prior written permission.
173
174THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
176LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
177A PARTICULAR PURPOSE ARE DISCLAIMED.
178IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
179DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
180(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
181SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
182CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
183LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
184OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
185SUCH DAMAGE.
186#if DK4_HAVE_DB_H		&& (DK4_CHAR_SIZE == 1)
187
188
189Berkeley DB license
190===================
191This package was debianized by Clint Adams <schizo@debian.org> on
192Wed, 25 Jul 2007 20:37:51 +0700
193
194It was downloaded from
195http://www.oracle.com/technology/software/products/berkeley-db/db/index.html
196
197Copyright and license:
198
199The following is the license that applies to this copy of the Berkeley DB
200software.  For a license to use the Berkeley DB software under conditions
201other than those described here, or to purchase support for this software,
202please contact Oracle at berkeleydb-info_us@oracle.com.
203
204=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
205/*
206 * Copyright (c) 1990, 2010 Oracle and/or its affiliates.  All rights reserved.
207 *
208 * Redistribution and use in source and binary forms, with or without
209 * modification, are permitted provided that the following conditions
210 * are met:
211 * 1. Redistributions of source code must retain the above copyright
212 *    notice, this list of conditions and the following disclaimer.
213 * 2. Redistributions in binary form must reproduce the above copyright
214 *    notice, this list of conditions and the following disclaimer in the
215 *    documentation and/or other materials provided with the distribution.
216 * 3. Redistributions in any form must be accompanied by information on
217 *    how to obtain complete source code for the DB software and any
218 *    accompanying software that uses the DB software.  The source code
219 *    must either be included in the distribution or be available for no
220 *    more than the cost of distribution plus a nominal fee, and must be
221 *    freely redistributable under reasonable conditions.  For an
222 *    executable file, complete source code means the source code for all
223 *    modules it contains.  It does not include source code for modules or
224 *    files that typically accompany the major components of the operating
225 *    system on which the executable file runs.
226 *
227 * THIS SOFTWARE IS PROVIDED BY ORACLE ``AS IS'' AND ANY EXPRESS OR
228 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
229 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
230 * NON-INFRINGEMENT, ARE DISCLAIMED.  IN NO EVENT SHALL ORACLE BE LIABLE
231 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
232 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
233 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
234 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
236 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
237 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
238 */
239/*
240 * Copyright (c) 1990, 1993, 1994, 1995
241 *	The Regents of the University of California.  All rights reserved.
242 *
243 * Redistribution and use in source and binary forms, with or without
244 * modification, are permitted provided that the following conditions
245 * are met:
246 * 1. Redistributions of source code must retain the above copyright
247 *    notice, this list of conditions and the following disclaimer.
248 * 2. Redistributions in binary form must reproduce the above copyright
249 *    notice, this list of conditions and the following disclaimer in the
250 *    documentation and/or other materials provided with the distribution.
251 * 3. Neither the name of the University nor the names of its contributors
252 *    may be used to endorse or promote products derived from this software
253 *    without specific prior written permission.
254 *
255 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
256 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
257 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
260 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
264 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265 * SUCH DAMAGE.
266 */
267/*
268 * Copyright (c) 1995, 1996
269 *	The President and Fellows of Harvard University.  All rights reserved.
270 *
271 * Redistribution and use in source and binary forms, with or without
272 * modification, are permitted provided that the following conditions
273 * are met:
274 * 1. Redistributions of source code must retain the above copyright
275 *    notice, this list of conditions and the following disclaimer.
276 * 2. Redistributions in binary form must reproduce the above copyright
277 *    notice, this list of conditions and the following disclaimer in the
278 *    documentation and/or other materials provided with the distribution.
279 * 3. Neither the name of the University nor the names of its contributors
280 *    may be used to endorse or promote products derived from this software
281 *    without specific prior written permission.
282 *
283 * THIS SOFTWARE IS PROVIDED BY HARVARD AND ITS CONTRIBUTORS ``AS IS'' AND
284 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
285 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
286 * ARE DISCLAIMED.  IN NO EVENT SHALL HARVARD OR ITS CONTRIBUTORS BE LIABLE
287 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
288 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
290 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
292 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
293 * SUCH DAMAGE.
294 */
295=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
296/***
297 * ASM: a very small and fast Java bytecode manipulation framework
298 * Copyright (c) 2000-2005 INRIA, France Telecom
299 * All rights reserved.
300 *
301 * Redistribution and use in source and binary forms, with or without
302 * modification, are permitted provided that the following conditions
303 * are met:
304 * 1. Redistributions of source code must retain the above copyright
305 *    notice, this list of conditions and the following disclaimer.
306 * 2. Redistributions in binary form must reproduce the above copyright
307 *    notice, this list of conditions and the following disclaimer in the
308 *    documentation and/or other materials provided with the distribution.
309 * 3. Neither the name of the copyright holders nor the names of its
310 *    contributors may be used to endorse or promote products derived from
311 *    this software without specific prior written permission.
312 *
313 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
314 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
315 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
316 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
317 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
318 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
319 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
320 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
321 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
322 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
323 * THE POSSIBILITY OF SUCH DAMAGE.
324 */
325#endif
326#if DK4_HAVE_ZLIB_H
327
328
329Zlib license
330============
331(C) 1995-2004 Jean-loup Gailly and Mark Adler
332
333This software is provided 'as-is', without any express or implied
334warranty.  In no event will the authors be held liable for any damages
335arising from the use of this software.
336
337Permission is granted to anyone to use this software for any purpose,
338including commercial applications, and to alter it and redistribute it
339freely, subject to the following restrictions:
340
3411. The origin of this software must not be misrepresented; you must not
342   claim that you wrote the original software. If you use this software
343   in a product, an acknowledgment in the product documentation would be
344   appreciated but is not required.
3452. Altered source versions must be plainly marked as such, and must not be
346   misrepresented as being the original software.
3473. This notice may not be removed or altered from any source distribution.
348
349Jean-loup Gailly        Mark Adler
350jloup@gzip.org          madler@alumni.caltech.edu
351#endif
352#if DK4_HAVE_BZLIB_H
353
354
355Bzip2 and libbzip2 library license
356==================================
357This program, "bzip2", the associated library "libbzip2", and all
358documentation, are copyright (C) 1996-2007 Julian R Seward.  All
359rights reserved.
360
361Redistribution and use in source and binary forms, with or without
362modification, are permitted provided that the following conditions
363are met:
364
3651. Redistributions of source code must retain the above copyright
366   notice, this list of conditions and the following disclaimer.
367
3682. The origin of this software must not be misrepresented; you must
369   not claim that you wrote the original software.  If you use this
370   software in a product, an acknowledgment in the product
371   documentation would be appreciated but is not required.
372
3733. Altered source versions must be plainly marked as such, and must
374   not be misrepresented as being the original software.
375
3764. The name of the author may not be used to endorse or promote
377   products derived from this software without specific prior written
378   permission.
379
380THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
381OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
382WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
383ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
384DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
385DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
386GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
387INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
388WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
389NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
390SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391
392Julian Seward, jseward@bzip.org
393bzip2/libbzip2 version 1.0.5 of 10 December 2007
394#endif
395$!end
396};
397
398
399
400/**	Version text.
401*/
402static const dkChar version_text[] = {
403  DKT_VERSION_DK
404#if DK4_HAVE_DB_H		&& (DK4_CHAR_SIZE == 1)
405  dkT(" bdb")
406#endif
407#if DK4_HAVE_NDBM_H		&& (DK4_CHAR_SIZE == 1)
408  dkT(" ndbm")
409#endif
410  dkT(" mem")
411};
412
413
414
415/**	Constant texts used by the module, not localized.
416*/
417const dkChar * const	dk_t2db_kwnl[] = {
418$!string-table	macro=dkT
419#
420#	0	Program group name
421#
422dktools
423#
424#	1	Help text file name
425#
426dk-t2db.txt
427#
428#	2	Error message: Application startup failed!
429#
430ERROR: Application startup failed!\n
431#
432#	3	String table file name
433#
434dk-t2db.str
435#
436#	4 5 6	Preference names for buffer sizes
437#
438line.size
439text-db.key.max-size
440text-db.value.max-size
441#
442#	7	File open mode for binary reading
443#
444rb
445#
446#	8	Path component separator
447#
448\\
449$!end
450};
451
452
453
454/**	Constant string used by the module, replaced by localized
455	texts if available.
456*/
457const dkChar * const	dk_t2db_kw_def[] = {
458$!string-table	macro=dkT
459#
460#	0	Error: Failed to set up signal handlers!
461#
462Failed to set up signal handlers!
463#
464#	1	Error: Failed to restore previous signal handlers!
465#
466Failed to restore previous signal handlers!
467#
468#	2	Default file name to be used for standard input.
469#
470<standard input>
471#
472#	3 4 5	Error: Failed to set database entry "key"="value"!
473#
474Failed to set database entry\n"
475"="
476"!
477#
478#	6 7	Error: Failed to delete database entry "key"!
479#
480Failed to delete database entry\n"
481"!
482#
483#	8 9 10 11 12 13
484#
485Decoding failed!
486Encoding failed!
487Processing failed!
488Further decoding failures!
489Further encoding failures!
490Further processing failures!
491#
492#	14 15 16 17 18 19
493#
494Decoding failed!\n\tByte:
495Encoding failed!\n\tByte:
496Processing failed!\n\tByte:
497,\n\tCharacter:
498,\n\tPosition in line:
499.
500#
501#	20	ERROR: Failed to read from file!
502#
503Failed to read from file!
504#
505#	21	ERROR: Failed to set up text stream processor!
506#
507Failed to set up text stream processor!
508#
509#	22 23	ERROR: Path too long for pattern "..."!
510#
511Path too long for pattern\n"
512"!
513#
514#	24 25	ERROR: No such file "..."!
515#
516No such file:\n"
517"!
518#
519#	26	ERROR: Failed to close database!
520#
521Failed to close database!
522#
523#	27	ERROR: Database name is required!
524#
525Database name is required!
526#
527#	28 29	ERROR: Illegal text encoding "..."!
528#
529Illegal text encoding: "
530"!
531#
532#	30	ERROR: Aborted by signal
533#
534Aborted by signal!
535$!end
536};
537
538
539
540/**	Options.
541*/
542static const dk4_option_specification_t dk_t2db_options[] = {
543  { dkT('a'),	dkT("add"),			DK4_OPT_ARG_NONE	} ,
544  { dkT('R'),	dkT("reset"),			DK4_OPT_ARG_NONE	} ,
545  { dkT('l'),	dkT("line-size"),		DK4_OPT_ARG_SIZE	} ,
546  { dkT('k'),	dkT("key-buffer-size"),		DK4_OPT_ARG_SIZE	} ,
547  { dkT('v'),	dkT("value-buffer-size"),	DK4_OPT_ARG_SIZE	} ,
548  { dkT('i'),	dkT("input-encoding"),		DK4_OPT_ARG_STRING	} ,
549  { dkT('c'),	dkT("comment"),			DK4_OPT_ARG_STRING	}
550};
551
552
553
554/**	Input line buffer.
555*/
556static dkChar		 linebuf[1024];
557
558
559
560/**	Localized or default messages.
561*/
562static const dkChar * const *	dk_t2db_msg	=	dk_t2db_kw_def;
563
564
565
566/**	Pointer to input buffer to use.
567*/
568static dkChar		*pibuf	=	linebuf;
569
570
571
572/**	Allocated input buffer, if necessary.
573*/
574static dkChar		*abuf	=	NULL;
575
576
577
578/**	Application structure.
579*/
580static dk4_app_t	*app	=	NULL;
581
582
583
584/**	String containing the comment character.
585*/
586static const dkChar	*comment	=	NULL;
587
588
589
590
591/**	Number of elements in the dk_t2db_options array.
592*/
593static const size_t dk_t2db_sz_options =
594sizeof(dk_t2db_options)/sizeof(dk4_option_specification_t);
595
596
597
598/**	Input buffer size.
599*/
600static size_t	szpibuf	=	DK4_SIZEOF(linebuf,dkChar);
601
602
603
604/**	Database key size.
605*/
606static size_t	szkey	=	DK4_SIZEOF(linebuf,dkChar) / 2;
607
608
609
610/**	Database value size.
611*/
612static size_t	szval	=	DK4_SIZEOF(linebuf,dkChar) / 2;
613
614
615
616/**	Number of elements in the dk_t2db_msg array.
617*/
618static size_t	dk_t2db_sz_msg =
619(sizeof(dk_t2db_kw_def)/sizeof(DK4_PDKCHAR) - 1);
620
621
622
623/**	Exit status code.
624*/
625static int	exval	=	EXIT_FAILURE;
626
627
628
629/**	Flag: Truncate existing database.
630*/
631static int	truncdb	=	1;
632
633
634
635/**	Expected encoding when processing an input file.
636*/
637static int	efe	=
638#if DK4_ON_WINDOWS
639	DK4_FILE_ENCODING_WIN1252
640#else
641	DK4_FILE_ENCODING_PLAIN
642#endif
643;
644
645
646
647/**	Expected encoding when processing standard input.
648*/
649static int	ese	=
650#if DK4_ON_WINDOWS
651	DK4_FILE_ENCODING_WIN1252
652#else
653	DK4_FILE_ENCODING_PLAIN
654#endif
655;
656
657
658/**	Number of decoding errors already occured.
659*/
660static int	dk_t2db_dec_err	= 0;
661
662
663
664/**	Number of encoding errors already occured.
665*/
666static int	dk_t2db_enc_err	= 0;
667
668
669
670/**	Number of processing errors already occured.
671*/
672static int	dk_t2db_pro_err	= 0;
673
674
675
676/**	Indicator: SIGINT signal received.
677*/
678static
679DK4_VOLATILE
680dk4_sig_atomic_t	sig_had_int	=	0;
681
682
683
684/**	Indicator: SIGTERM signal received.
685*/
686static
687DK4_VOLATILE
688dk4_sig_atomic_t	sig_had_term	=	0;
689
690
691
692/**	Pass a volatile pointer to an atomic integer.
693	This function is necessary as some compilers mis-optimize
694	direct access to volatile variables (at least if you believe
695	one of the coding standards).
696	@param	ptr	Address of atomic integer variable.
697	@return	The unmodified pointer.
698*/
699static
700DK4_VOLATILE
701dk4_sig_atomic_t *
702sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr)
703{
704  return ptr;
705}
706
707
708
709/**	Handler for SIGINT signal.
710	@param	signo	Signal number (always SIGINT, ignored).
711*/
712static
713void
714sig_handler_int(int DK4_ARG_UNUSED(signo) )
715{
716  DK4_UNUSED_ARG(signo)
717  *sig_pass_pointer(&sig_had_int) = 1;
718}
719
720
721
722/**	Handler for SIGTERM signal.
723	@param	signo	Signal number (always SIGTERM, ignored).
724*/
725static
726void
727sig_handler_term(int DK4_ARG_UNUSED(signo) )
728{
729  DK4_UNUSED_ARG(signo)
730  *sig_pass_pointer(&sig_had_term) = 1;
731}
732
733
734
735/**	Read value from volatile atomic type.
736	This function is necessary as some compilers mis-optimize
737	direct access to volatile variables (at least if you believe
738	one of the coding standards).
739	@param	ap	Pointer to volatile atomic variable.
740	@return	Contents of the variable.
741*/
742static
743dk4_sig_atomic_t
744sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap)
745{
746  return (*ap);
747}
748
749
750
751/**	Check whether we can continue or if a signal was received.
752	@param	check_pipe	Flag: Check for occured SIGPIPE signal too.
753	@return	1 if the program can continue, 0 if a signal was received.
754*/
755static
756int
757sig_can_continue(void)
758{
759  int		back = 1;
760  if (0 != sig_read_atomic(&sig_had_int )) { back = 0; }
761  if (0 != sig_read_atomic(&sig_had_term)) { back = 0; }
762  return back;
763}
764
765
766
767static
768void
769dk_t2db_remove_crnl(dkChar *lptr)
770{
771  while (dkT('\0') != *lptr) {
772    if (dkT('\n') == *lptr) {
773      *lptr = dkT('\0');
774    } else {
775      if (dkT('\r') == *lptr) {
776        *lptr = dkT('\0');
777      } else {
778        lptr++;
779      }
780    }
781  }
782}
783
784
785
786/**	Handler function to process one text line.
787	@param	obj	Object to modify.
788	@param	line	Text line to process.
789	@param	lineno	Line number of text line.
790	@param	erp	Error report, may be NULL.
791	@return	One from:
792	- DK4_TSP_RES_OK	for successful processing,
793	- DK4_TSP_RES_ERROR	on errors we can recover from,
794	- DK4_TSP_RES_FATAL	on errors requiring to abort processing.
795*/
796static
797int
798dk_t2db_line_handler(
799  void		*obj,
800  dkChar	*line,
801  dk4_um_t	 DK4_ARG_UNUSED(lineno),
802  dk4_er_t	*erp
803)
804{
805  dk4_er_t	 er;
806  dk4_dbi_t	*dbiptr;
807  dkChar	*p1;
808  dkChar	*p2;
809  int		 back	=	DK4_TSP_RES_OK;
810  int		 must	=	1;			/* Must process line */
811  $? "+ dk_t2db_line_handler \"%!ds\"", line
812  DK4_UNUSED_ARG(lineno)
813  p1 = dk4str_start(line, NULL);
814  if (NULL != p1) {			$? ". have text"
815    if (NULL != comment) {		$? ". have comment \"%!ds\"", comment
816      if (*comment == *p1) {
817        must = 0;			$? ". comment line"
818      }
819#if TRACE_DEBUG
820      else {				$? ". not a comment line"
821      }
822#endif
823    }
824    if (0 != must) {
825      /* Not a comment line */
826      dk_t2db_remove_crnl(p1);
827      dbiptr = (dk4_dbi_t *)obj;
828      dk4error_init(&er);
829      p2 = dk4str_next(p1, NULL);
830      if (NULL != p2) {			$? ". set \"%!ds\"=\"%!ds\"", p1, p2
831        /* Add or change entry */
832        if (0 == dk4dbi_text_set(dbiptr, p1, p2, &er)) {
833	  dk4error_copy(erp, &er);	$? "! failed"
834	  back = DK4_TSP_RES_ERROR;
835	  exval = EXIT_FAILURE;
836	  dk4app_log_5(
837	    app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 3, 4, 5, p1, p2
838	  );
839	}
840      } else {				$? ". delete \"%!ds\"", p1
841        /* Delete entry */
842        if (0 == dk4dbi_text_del(dbiptr, p1, &er)) {
843	  dk4error_copy(erp, &er);	$? "! failed"
844	  back = DK4_TSP_RES_ERROR;
845	  exval = EXIT_FAILURE;
846	  dk4app_log_3(
847	    app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 6, 7, p1
848	  );
849	}
850      }
851    }
852  }
853  $? "- dk_t2db_line_handler %d", back
854  return back;
855}
856
857
858/**	Report an error with position in source line.
859	@param	i1	Index of first message part in array.
860	@param	i2	Index of alternative first message part.
861	@param	bno	Byte processed.
862	@param	lno	Current line number.
863	@param	cno	Current character number.
864	@param	cil	Current character number in line.
865*/
866static
867void
868dk_t2db_report_with_position(
869  size_t		i1,
870  size_t		i2,
871  dk4_um_t		bno,
872  dk4_um_t		lno,
873  dk4_um_t		cno,
874  dk4_um_t		cil
875)
876{
877  dkChar	 b1[8*(1+sizeof(dk4_um_t))];
878  dkChar         b2[8*(1+sizeof(dk4_um_t))];
879  dkChar         b3[8*(1+sizeof(dk4_um_t))];
880  dk4_um_t	 oldlogline			= (dk4_um_t)0UL;
881  int		 allbuffersok			= 0;
882
883  oldlogline =	dk4app_get_log_source_line(app);
884  dk4app_set_log_source_line(app, lno);
885  if (0 != dk4ma_write_decimal_unsigned(b3,DK4_SIZEOF(b3,dkChar),cil,0,NULL)) {
886  if (0 != dk4ma_write_decimal_unsigned(b2,DK4_SIZEOF(b2,dkChar),cno,0,NULL)) {
887  if (0 != dk4ma_write_decimal_unsigned(b1,DK4_SIZEOF(b1,dkChar),bno,0,NULL)) {
888        allbuffersok = 1;
889  }
890  }
891  }
892  if (0 != allbuffersok) {
893    dk4app_log_7(
894      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR,
895      i1, 17, 18, 19, b1, b2, b3
896    );
897  } else {
898    dk4app_log_1(
899      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, i2
900    );
901  }
902  dk4app_set_log_source_line(app, oldlogline);
903}
904
905
906/**	Report errors from encoding/decoding or processing.
907*/
908static
909void
910dk_t2db_report_errors(dk4_er_t *er_en, dk4_er_t *er_pr)
911{
912
913  if (NULL != er_en) {
914    switch (er_en->ec) {
915      case DK4_E_DECODING_FAILED: {
916        switch (dk_t2db_dec_err) {
917	  case 0: case 1: {
918	    dk_t2db_report_with_position(
919	      14, 8,
920	      er_en->dt.fpos.byteno,
921	      er_en->dt.fpos.lineno,
922	      er_en->dt.fpos.charno,
923	      er_en->dt.fpos.charinline
924	    );
925	  } break;
926	  case 2: {
927	    dk4app_log_1(
928	      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 11
929	    );
930	  } break;
931	}
932	if (3 > dk_t2db_dec_err) { dk_t2db_dec_err++; }
933      } break;
934      case DK4_E_ENCODING_FAILED: {
935        switch (dk_t2db_enc_err) {
936	  case 0: case 1: {
937	    dk_t2db_report_with_position(
938	      15, 9,
939	      er_en->dt.fpos.byteno,
940	      er_en->dt.fpos.lineno,
941	      er_en->dt.fpos.charno,
942	      er_en->dt.fpos.charinline
943	    );
944	  } break;
945	  case 2: {
946	    dk4app_log_1(
947	      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 12
948	    );
949	  } break;
950	}
951	if (3 > dk_t2db_enc_err) { dk_t2db_enc_err++; }
952      } break;
953    }
954  }
955  if (NULL != er_pr) {
956    if (DK4_E_NONE != er_pr->ec) {
957      switch (dk_t2db_pro_err) {
958        case 0: case 1: {
959	  dk_t2db_report_with_position(
960	    16, 10,
961	    er_pr->dt.fpos.byteno,
962	    er_pr->dt.fpos.lineno,
963	    er_pr->dt.fpos.charno,
964	    er_pr->dt.fpos.charinline
965	  );
966	} break;
967	case 2: {
968	  dk4app_log_1(
969	    app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 13
970	  );
971	} break;
972      }
973      if (3 > dk_t2db_pro_err) { dk_t2db_pro_err++; }
974    }
975  }
976
977
978}
979
980
981
982/**	Process one input file.
983	@param	dbiptr		Database to modify.
984	@param	infile		Input file to process, must be in binary mode.
985	@param	eie		Expected input encoding.
986*/
987static
988void
989dk_t2db_run_for_file(
990  dk4_dbi_t	*dbiptr,
991  FILE 		*infile,
992  int		 eie
993)
994{
995  dk4_tspdk_t		 tspdk;
996  dk4_er_t		 er_en;
997  dk4_er_t		 er_pr;
998  const dkChar		*oldsourcefile;
999  int			 res;
1000  int			 cc;
1001  int			 c;
1002  unsigned char		 ub;
1003
1004  dk_t2db_dec_err = 0;
1005  dk_t2db_enc_err = 0;
1006  dk_t2db_pro_err = 0;
1007  oldsourcefile = dk4app_get_log_source_file(app);
1008  res = dk4tspdk_setup_line(
1009    &tspdk, dbiptr, dk_t2db_line_handler, pibuf, szpibuf,
1010    dk4app_get_encoding(app), eie, NULL
1011  );
1012  if (0 != res) {
1013    if (DK4_ENCODING_UTF8 == dk4app_get_encoding(app)) {
1014      dk4tspdk_enable_utf8_pass_through(&tspdk, 1);
1015    }
1016    dk4error_init(&er_en);
1017    dk4error_init(&er_pr);
1018    cc = 1;
1019    do {
1020      if (0 != sig_can_continue()) {
1021        c = fgetc(infile);
1022	if (EOF != c) {
1023	  ub = (unsigned char)c;
1024	  switch (dk4tspdk_add_one_byte(&tspdk, ub)) {
1025	    case DK4_TSP_RES_FATAL : {
1026	      cc = -1;
1027	      exval = EXIT_FAILURE;
1028	      dk4tspdk_get_errors(&er_en, &er_pr, &tspdk);
1029	      dk_t2db_report_errors(&er_en, &er_pr);
1030	    } break;
1031	    case DK4_TSP_RES_ERROR : {
1032	      exval = EXIT_FAILURE;
1033	      dk4tspdk_get_errors(&er_en, &er_pr, &tspdk);
1034	      dk_t2db_report_errors(&er_en, &er_pr);
1035	    } break;
1036	  }
1037	} else {
1038	  cc = 0;
1039	  if (0 != ferror(infile)) {
1040	    cc = -1;
1041	    /* ERROR: Failed to read from file */
1042	    dk4app_log_1(
1043	      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 20
1044	    );
1045	    exval = EXIT_FAILURE;
1046	  }
1047	}
1048      } else {
1049        cc = -1;
1050      }
1051    } while (1 == cc);
1052    if (0 == cc) {
1053      switch (dk4tspdk_finish(&tspdk)) {
1054        case DK4_TSP_RES_FATAL : {
1055	  exval = EXIT_FAILURE;
1056	  dk4tspdk_get_errors(&er_en, &er_pr, &tspdk);
1057	  dk_t2db_report_errors(&er_en, &er_pr);
1058	} break;
1059	case DK4_TSP_RES_ERROR : {
1060	  exval = EXIT_FAILURE;
1061	  dk4tspdk_get_errors(&er_en, &er_pr, &tspdk);
1062	  dk_t2db_report_errors(&er_en, &er_pr);
1063	} break;
1064      }
1065    }
1066  } else {
1067    /* ERROR: Failed to set up text stream processor */
1068    dk4app_log_1(
1069      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 21
1070    );
1071    exval = EXIT_FAILURE;
1072  }
1073  dk4app_set_log_source_file(app, oldsourcefile);
1074}
1075
1076
1077
1078/**	Process one input file specified by file name.
1079	@param	dbiptr		Database to modify.
1080	@param	filename	Name of file to process.
1081*/
1082static
1083void
1084dk_t2db_process_name(dk4_dbi_t *dbiptr, const dkChar *filename)
1085{
1086#if DK4_ON_WINDOWS
1087  dkChar	 buf[DK4_MAX_PATH];
1088#endif
1089  FILE *fipo;
1090#if DK4_ON_WINDOWS
1091  dk4_dir_t	*fne;
1092  const dkChar	*expfn;
1093  const dkChar	*expth;
1094  size_t	 szbuf		= DK4_SIZEOF(buf,dkChar);
1095  int		 any_file_found	= 0;
1096  int		 cc;
1097#endif
1098
1099  if (NULL != filename) {
1100#if DK4_ON_WINDOWS
1101    if (0 != dk4path_must_expand(filename)) {
1102      fne = dk4app_fne_open(filename, app);
1103      if (NULL != fne) {
1104        cc = 1;
1105        do {
1106	  if (0 != sig_can_continue()) {
1107	    expfn = dk4dir_next_file(fne);
1108	    if (NULL != expfn) {
1109	      any_file_found = 1;
1110	      expth = dk4dir_get_path(fne);
1111	      if (NULL != expth) {
1112	        if (0 != dk4str_cpy_s(buf, szbuf, expth, NULL)) {
1113		  if (0 != dk4str_cat_s(buf, szbuf, dk_t2db_kwnl[8], NULL)) {
1114		    if (0 != dk4str_cat_s(buf, szbuf, expfn, NULL)) {
1115                      fipo = dk4fopen_app(
1116                        buf, dk_t2db_kwnl[7], DK4_FOPEN_SC_IS_REGULAR, app
1117                      );
1118                      if (NULL != fipo) {
1119                        dk_t2db_run_for_file(dbiptr, fipo, efe);
1120                        fclose(fipo);
1121                      } else {
1122                        exval = EXIT_FAILURE;
1123                      }
1124		    } else {
1125		      /* ERROR: Path too long */
1126		      dk4app_log_3(
1127			app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR,
1128			22, 23, filename
1129		      );
1130		      exval = EXIT_FAILURE;
1131		    }
1132		  } else {
1133		    /* ERROR: Path too long */
1134		    dk4app_log_3(
1135		      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR,
1136		      22, 23, filename
1137		    );
1138		    exval = EXIT_FAILURE;
1139		  }
1140		} else {
1141		  /* ERROR: Path too long */
1142		  dk4app_log_3(
1143		    app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR,
1144		    22, 23, filename
1145		  );
1146		  exval = EXIT_FAILURE;
1147		}
1148	      } else {
1149                fipo = dk4fopen_app(
1150                  expfn, dk_t2db_kwnl[7], DK4_FOPEN_SC_IS_REGULAR, app
1151                );
1152                if (NULL != fipo) {
1153                  dk_t2db_run_for_file(dbiptr, fipo, efe);
1154                  fclose(fipo);
1155                } else {
1156                  exval = EXIT_FAILURE;
1157                }
1158	      }
1159	    } else {
1160	      cc = 0;
1161	    }
1162	  } else {
1163	    cc = -1;
1164	  }
1165	} while (1 == cc);
1166        dk4dir_close(fne);
1167	if (0 == any_file_found) {
1168	  /* ERROR: No such file */
1169	  dk4app_log_3(
1170	    app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR,
1171	    24, 25, filename
1172	  );
1173	  exval = EXIT_FAILURE;
1174	}
1175      } else {
1176        exval = EXIT_FAILURE;
1177      }
1178    } else {
1179#endif
1180      fipo = dk4fopen_app(
1181        filename, dk_t2db_kwnl[7], DK4_FOPEN_SC_IS_REGULAR, app
1182      );
1183      if (NULL != fipo) {
1184        dk_t2db_run_for_file(dbiptr, fipo, efe);
1185        fclose(fipo);
1186      } else {
1187        exval = EXIT_FAILURE;
1188      }
1189#if DK4_ON_WINDOWS
1190    }
1191#endif
1192  }
1193}
1194
1195
1196
1197/**	Run for opened database.
1198	@param	dbiptr	Database to modify.
1199*/
1200static
1201void
1202dk_t2db_run_with_dbi(dk4_dbi_t *dbiptr)
1203{
1204  int	xargc;
1205  int	i;
1206#if DK4_ON_WINDOWS
1207  int	oldmode;
1208#endif
1209
1210  xargc = dk4app_get_argc(app);
1211  if (1 < xargc) {
1212    for (i = 0; ((i < (xargc - 1)) && (0 != sig_can_continue())); i++) {
1213      dk_t2db_process_name(dbiptr, dk4app_get_argv(app, i));
1214    }
1215  } else {
1216#if DK4_ON_WINDOWS
1217    oldmode = _setmode(_fileno(stdin), _O_BINARY);
1218#endif
1219    dk_t2db_run_for_file(dbiptr, stdin, ese);
1220#if DK4_ON_WINDOWS
1221    _setmode(_fileno(stdin), oldmode);
1222#endif
1223  }
1224}
1225
1226
1227
1228/**	Open database and do processing.
1229*/
1230static
1231void
1232dk_t2db_run_with_buffers(void)
1233{
1234  dk4_er_t	 er;
1235  dk4_dbi_t	*dbiptr;
1236  const dkChar	*fn;
1237
1238  fn = dk4app_get_argv(app, (dk4app_get_argc(app)-1));
1239  if ((0 != sig_can_continue()) && (NULL != fn)) {
1240    dbiptr = dk4dbi_open_sizes_app(fn, 1, truncdb, szkey, szval, NULL, app);
1241    if (NULL != dbiptr) {
1242      exval = EXIT_SUCCESS;
1243      dk_t2db_run_with_dbi(dbiptr);
1244      dk4error_init(&er);
1245      if (0 == dk4dbi_close(dbiptr, &er)) {
1246        /* ERROR: Failed to close database */
1247	dk4app_log_1(
1248	  app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 26
1249	);
1250	exval = EXIT_FAILURE;
1251      }
1252    }
1253  }
1254}
1255
1256
1257
1258/**	Process preferences and command line options,
1259	allocate buffer if necessary and do processing.
1260*/
1261static
1262void
1263dk_t2db_normal_run(void)
1264{
1265  dk4_er_t	 er;
1266  const dkChar	*oaptr;
1267  size_t	 i;
1268  int		 enc	= DK4_FILE_ENCODING_PLAIN;
1269  int		 bom	= 0;
1270
1271#if DK4_ON_WINDOWS
1272  enc = DK4_FILE_ENCODING_WIN1252;
1273#endif
1274  /*	Check cmd line arguments, must have at least a database name.
1275  */
1276  if (0 == dk4app_get_argc(app)) {
1277    /* ERROR: Database name required. */
1278    dk4app_log_1(
1279      app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 27
1280    );
1281    goto finished;
1282  }
1283
1284  /*	Process preferences and options.
1285  */
1286  if (0 == dk4app_opt_is_set_short(app, dkT('R'), NULL)) {
1287    if (0 != dk4app_pref_get_size(&i, app, dk_t2db_kwnl[4], 0)) {
1288      szpibuf = i;
1289    }
1290    if (0 != dk4app_pref_get_size(&i, app, dk_t2db_kwnl[5], 0)) {
1291      szkey = i;
1292    }
1293    if (0 != dk4app_pref_get_size(&i, app, dk_t2db_kwnl[6], 0)) {
1294      szval = i;
1295    }
1296  }
1297  if (0 != dk4app_opt_is_set_short(app, dkT('a'), NULL)) {
1298    truncdb = 0;
1299  }
1300  if (0 != dk4app_opt_is_set_short(app, dkT('l'), NULL)) {
1301    if (0 != dk4app_opt_get_size_short(&i, app, dkT('l'), NULL)) {
1302      szpibuf = i;
1303    }
1304  }
1305  if (0 != dk4app_opt_is_set_short(app, dkT('k'), NULL)) {
1306    if (0 != dk4app_opt_get_size_short(&i, app, dkT('k'), NULL)) {
1307      szkey = i;
1308    }
1309  }
1310  if (0 != dk4app_opt_is_set_short(app, dkT('v'), NULL)) {
1311    if (0 != dk4app_opt_get_size_short(&i, app, dkT('v'), NULL)) {
1312      szval = i;
1313    }
1314  }
1315  if (0 != dk4app_opt_is_set_short(app, dkT('i'), NULL)) {
1316    oaptr = dk4app_opt_get_string_ptr_short(app, dkT('i'), NULL);
1317    if (NULL != oaptr) {
1318      if (0 != dk4enc_find(&enc, &bom, oaptr, NULL)) {
1319        efe = ese = enc;
1320      } else {
1321        /* ERROR: Encoding not found */
1322	dk4app_log_3(
1323	  app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 28, 29, oaptr
1324	);
1325	goto finished;
1326      }
1327    }
1328  }
1329  if (0 != dk4app_opt_is_set_short(app, dkT('c'), NULL)) {
1330    $? ". option -c used"
1331    oaptr = dk4app_opt_get_string_ptr_short(app, dkT('c'), NULL);
1332    if (NULL != oaptr) {	$? ". argument found"
1333      comment = oaptr;	$? ". comment=\"%!ds\"", comment
1334    }
1335#if TRACE_DEBUG
1336    else {			$? "! no argument"
1337    }
1338#endif
1339  }
1340  if (0 == szpibuf) { szpibuf = DK4_SIZEOF(linebuf,dkChar); }
1341  if (0 == szkey) { szkey = DK4_SIZEOF(linebuf,dkChar) / 2; }
1342  if (0 == szval) { szval = DK4_SIZEOF(linebuf,dkChar) / 2; }
1343
1344  /*	Calculate key and value buffer size in bytes.
1345  */
1346  dk4error_init(&er);
1347  szkey = dk4ma_size_t_mul(szkey, sizeof(dkChar), &er);
1348  szval = dk4ma_size_t_mul(szval, sizeof(dkChar), &er);
1349  if (DK4_E_NONE != er.ec) {
1350    /* ERROR: Mathematical overflow in size calculation */
1351    dk4app_log_base1(app, DK4_LL_ERROR, 82);
1352    goto finished;
1353  }
1354
1355  /*	Allocate larger buffer if necessary.
1356  */
1357  if (DK4_SIZEOF(linebuf,dkChar) < szpibuf) {
1358    abuf = dk4mem_new_app(dkChar,szpibuf,app);
1359    if (NULL != abuf) {
1360      pibuf = abuf;
1361    } else {
1362      goto finished;
1363    }
1364  }
1365
1366  /*	Now do the processing.
1367  */
1368  dk_t2db_run_with_buffers();
1369
1370  /*	Clean up.
1371  */
1372  finished:
1373  dk4mem_release(abuf) ;
1374}
1375
1376
1377
1378#if	DK4_HAVE_SIGACTION
1379/**	Set signal handlers and run.
1380*/
1381static
1382void
1383dk_t2db_run_with_signal_handlers(void)
1384{
1385  struct sigaction oint;
1386  struct sigaction nint;
1387  struct sigaction oterm;
1388  struct sigaction nterm;
1389  int	 success = 0;
1390
1391  /*	Set up signal handling for SIGINT.
1392  */
1393  DK4_MEMRES(&nint, sizeof(nint));
1394  nint.sa_handler = sig_handler_int;
1395  nint.sa_flags = 0;
1396  if (0 != sigemptyset(&nint.sa_mask)) {
1397    /* ERROR: Failed to set up masked signal set for SIGINT */
1398    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1399    goto finished;
1400  }
1401  if (0 != sigaddset(&nint.sa_mask, SIGINT)) {
1402    /* ERROR: Failed to set up masked signal set for SIGINT */
1403    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1404    goto finished;
1405  }
1406  if (0 != sigaction(SIGINT, &nint, &oint)) {
1407    /* ERROR: Failed to set up signal handler for SIGINT */
1408    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1409    goto finished;
1410  }
1411
1412  /*	Set up signal handling for SIGTERM
1413  */
1414  DK4_MEMRES(&nterm, sizeof(nterm));
1415  nterm.sa_handler = sig_handler_term;
1416  nterm.sa_flags = 0;
1417  if (0 != sigemptyset(&nterm.sa_mask)) {
1418    /* ERROR: Failed to set up masked signal set for SIGTERM */
1419    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1420    goto restore_old_int;
1421  }
1422  if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) {
1423    /* ERROR: Failed to set up masked signal set for SIGTERM */
1424    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1425    goto restore_old_int;
1426  }
1427  if (0 != sigaction(SIGTERM, &nterm, &oterm)) {
1428    /* ERROR: Failed to set up signal handler for SIGTERM */
1429    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 0);
1430    goto restore_old_int;
1431  }
1432
1433  success = 1;
1434  dk_t2db_normal_run();
1435
1436  /*	Restore signal handling for SIGTERM.
1437  */
1438  if (0 != sigaction(SIGTERM, &oterm, NULL)) {
1439    /* ERROR: Failed to restore old SIGTERM settings */
1440    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 1);
1441    success = 0;
1442  }
1443
1444  /*	Restore signal handling for SIGINT.
1445  */
1446  restore_old_int:
1447  if (0 != sigaction(SIGINT, &oint, NULL)) {
1448    /* ERROR: Failed to restore old SIGPIPE settings */
1449    dk4app_log_1(app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 1);
1450    success = 0;
1451  }
1452
1453  /*	Set exit status code if error occured.
1454  */
1455  finished:
1456  if (0 == success) { exval = EXIT_FAILURE; }
1457}
1458#else
1459#if	DK4_HAVE_SIGSET
1460/**	Set signal handlers and run.
1461*/
1462static
1463void
1464dk_t2db_run_with_signal_handlers(void)
1465{
1466  dk4_sig_handler_t	*oldint  = NULL;
1467  dk4_sig_handler_t	*oldterm = NULL;
1468
1469  oldint  = sigset(SIGINT,  sig_handler_int);
1470  oldterm = sigset(SIGTERM, sig_handler_term);
1471  dk_t2db_normal_run();
1472  sigset(SIGTERM, oldterm);
1473  sigset(SIGINT,  oldint);
1474}
1475#else
1476#if	DK4_HAVE_SIGNAL
1477/**	Set signal handlers and run.
1478*/
1479static
1480void
1481dk_t2db_run_with_signal_handlers(void)
1482{
1483  dk4_sig_handler_t	*oldint  = NULL;
1484  dk4_sig_handler_t	*oldterm = NULL;
1485
1486  oldint  = signal(SIGINT,  sig_handler_int);
1487  oldterm = signal(SIGTERM, sig_handler_term);
1488  dk_t2db_normal_run();
1489  signal(SIGTERM, oldterm);
1490  signal(SIGINT,  oldint);
1491}
1492#else
1493/**	Set signal handlers and run.
1494*/
1495static
1496void
1497dk_t2db_run_with_signal_handlers(void)
1498{
1499  dk_t2db_normal_run();
1500}
1501#endif
1502#endif
1503#endif
1504
1505
1506
1507/**	Main function.
1508	@param	argc	Number of command line arguments.
1509	@param	argv	Command line arguments array.
1510	@return	0 on success, all other values indicate errors.
1511*/
1512#if DK4_CHAR_SIZE > 1
1513int wmain(int argc, wchar_t *argv[])
1514#else
1515int main(int argc, char *argv[])
1516#endif
1517{
1518  $!trace-init dk-t2db.deb
1519  $? "+ main"
1520  dk4fput_initialize_stderr();
1521  app = dk4app_open_cmd(
1522    argc, argv,
1523    dk_t2db_options, dk_t2db_sz_options,
1524    dk_t2db_kwnl[0], version_text,
1525    dk_t2db_kwnl[1], help_text, license_text
1526  );
1527  if (NULL != app) {
1528    ese = dk4app_get_stdin_encoding(app);
1529    efe = dk4app_get_file_in_encoding(app);
1530    dk_t2db_sz_msg = dk4app_string_table_size(dk_t2db_kw_def);
1531    dk_t2db_msg    = dk4app_string_table(app, dk_t2db_kwnl[3], dk_t2db_kw_def);
1532    if (0 != dk4app_can_run_normally(app)) {
1533      dk_t2db_run_with_signal_handlers();
1534      if (0 != sig_read_atomic(&sig_had_int)) {
1535        /* ERROR: Aborted by SIGINT */
1536	dk4app_log_1(
1537	  app, dk_t2db_msg, dk_t2db_sz_msg, DK4_LL_ERROR, 30
1538	);
1539	exval = EXIT_FAILURE;
1540      }
1541      if (0 != sig_read_atomic(&sig_had_term)) {
1542        exval = EXIT_FAILURE;
1543      }
1544    } else {
1545      if (0 != dk4app_help_version_license(app)) {
1546        exval = EXIT_SUCCESS;
1547      }
1548    }
1549    dk4app_close(app);
1550  } else {
1551    dk4fputs(dk_t2db_kwnl[2], stderr, NULL);
1552  }
1553  fflush(stderr);
1554  dk4fput_cleanup_stderr();
1555  $? "- main %d", exval
1556  $!trace-end
1557  exit(exval); return exval;
1558}
1559
1560