/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4appop.ctr */ /* Copyright (C) 2015-2017, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #line 10 "dk4appop.ctr" /** @file Open and close dk4_app_t structure. */ #ifndef DK4APP_H_INCLUDED #include "dk4app.h" #endif #ifndef DK4STT_H_INCLUDED #include "dk4stt.h" #endif #ifndef DK4CONST_H_INCLUDED #include "dk4const.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4STR8_H_INCLUDED #include "dk4str8.h" #endif #ifndef DK4STRW_H_INCLUDED #include "dk4strw.h" #endif #ifndef DK4STRD_H_INCLUDED #include "dk4strd.h" #endif #ifndef DK4ENC_H_INCLUDED #include "dk4enc.h" #endif #ifndef DK4LOC_H_INCLUDED #include "dk4loc.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4EXEPD_H_INCLUDED #include "dk4exepd.h" #endif #ifndef DK4MAO8D_H_INCLUDED #include "dk4mao8d.h" #endif #ifndef DK4INST_H_INCLUDED #include "dk4inst.h" #endif #ifndef DK4PREF_H_INCLUDED #include "dk4pref.h" #endif #ifndef DK4USER_H_INCLUDED #include "dk4user.h" #endif #ifndef DK4FS_H_INCLUDED #include "dk4fs.h" #endif #ifndef DK4STRMR_H_INCLUDED #include "dk4strmr.h" #endif #ifndef DK4TSPDK_H_INCLUDED #include "dk4tspdk.h" #endif #ifndef DK4FPUT_H_INCLUDED #include "dk4fput.h" #endif #ifndef DK4HNAMED_H_INCLUDED #include "dk4hnamed.h" #endif #ifndef DK4MAIDDDI_H_INCLUDED #include "dk4maidddi.h" #endif #ifndef DK4MAIDDDU_H_INCLUDED #include "dk4maidddu.h" #endif #ifndef DK4MAIDDSZ_H_INCLUDED #include "dk4maiddsz.h" #endif #ifndef DK4MAIDDBL_H_INCLUDED #include "dk4maiddbl.h" #endif #ifndef DK4MAODD_H_INCLUDED #include "dk4maodd.h" #endif #ifndef DK4NUML_H_INCLUDED #include "dk4numl.h" #endif #ifndef DK4STO_H_INCLUDED #include "dk4sto.h" #endif #ifndef DK4APPI_C_INCLUDED #include "dk4appi.c" #endif #ifndef DK4PATHD_H_INCLUDED #include "dk4pathd.h" #endif #ifndef DK4STATD_H_INCLUDED #include "dk4statd.h" #endif #ifndef DK4STAT_H_INCLUDED #include "dk4stat.h" #endif #ifndef DK4REC21_H_INCLUDED #include "dk4rec21.h" #endif #ifndef DK4TIME_H_INCLUDED #include "dk4time.h" #endif #ifndef DK4TIMEDK_H_INCLUDED #include "dk4timedk.h" #endif #ifndef DK4GETPID_H_INCLUDED #include "dk4getpid.h" #endif #ifndef DK4APPMKDH_H_INCLUDED #include "dk4appmkdh.h" #endif #ifndef DK4DELFILE_H_INCLUDED #include "dk4delfile.h" #endif #ifdef __cplusplus extern "C" { #endif /** Log at application startup. @param app Application structure. */ void dk4app_log_startup_debug(dk4_app_t *app); #ifdef __cplusplus } #endif #line 181 "dk4appop.ctr" static const dkChar * const dk4app_open_long_opt[] = { /* 0 */ dkT("help"), /* 1 */ dkT("version"), /* 2 */ dkT("license"), /* 3 */ dkT("quiet"), /* 4 */ dkT("manual"), NULL #line 207 "dk4appop.ctr" }; static const dkChar * const dk4app_open_scope_names[] = { /* 0 */ dkT("user"), /* 1 */ dkT("application"), /* 2 */ dkT("application-group"), /* 3 */ dkT("host"), /* 4 */ dkT("windows"), /* 5 */ dkT("non-windows"), /* 6 */ dkT("language"), /* 7 */ dkT("region"), NULL #line 246 "dk4appop.ctr" }; /** Non localized 8 bit char keywords used by this module. */ static const char * const dk4app_open_c8_kw[] = { /* 0 */ "ERROR: Not enough memory!", /* 1 */ "ERROR: Not enough memory, failed to allocate ", /* 2 */ " bytes!", NULL #line 258 "dk4appop.ctr" }; /** Non localized dkChar keywords used by this module. */ static const dkChar * const dk4app_open_kw[] = { /* 0 */ dkT("--quiet"), /* 1 */ dkT("bin"), /* 2 */ dkT("sbin"), /* 3 */ dkT("etc"), /* 4 */ dkT("share"), /* 5 */ dkT("lib"), /* 6 */ dkT("var"), /* 7 */ dkT("libexec"), /* 8 */ dkT("dk4pref.conf"), /* 9 */ dkT("/log"), /* 10 */ dkT("/"), /* 11 */ dkT("-"), /* 12 */ dkT(".log"), /* 13 */ dkT("/tmp"), /* 14 */ dkT("dk3pref.conf"), /* 15 */ dkT("*"), NULL #line 313 "dk4appop.ctr" }; /** Character used as separator between path name components. */ static const dkChar dk4app_filename_sep[] = #if DK4_HAVE_BACKSLASH_AS_SEP dkT("\\") #else dkT("/") #endif ; #if DK4_ON_WINDOWS /** File name suffixes for executable files on Windows systems. */ static const dkChar * const dk4app_exe_file_suffixes[] = { /* 0 */ dkT(".exe"), /* 1 */ dkT(".com"), /* 2 */ dkT(".dll"), /* 3 */ dkT(".sys"), /* 4 */ dkT(".cpl"), NULL #line 340 "dk4appop.ctr" }; #endif /** Initialize an application structure after allocating the memory. @param ptr Structure to initialize. */ static void dk4app_open_initialize(dk4_app_t *ptr) { #line 353 "dk4appop.ctr" ptr->s_opt_all = NULL; ptr->i_opt_all = NULL; ptr->s_opt_short = NULL; ptr->i_opt_short = NULL; ptr->s_opt_long = NULL; ptr->i_opt_long = NULL; ptr->s_pref_self = NULL; ptr->s_pref_cmd = NULL; ptr->s_pref_user = NULL; ptr->s_pref_sys = NULL; ptr->s_stt = NULL; ptr->i_pref_self = NULL; ptr->i_pref_cmd = NULL; ptr->i_pref_user = NULL; ptr->i_pref_sys = NULL; ptr->i_stt = NULL; ptr->msg_base = NULL; ptr->msg_debug = NULL; ptr->help_text = NULL; ptr->lic_text = NULL; ptr->my_argv = NULL; ptr->vers_text = NULL; ptr->help_file_name = NULL; ptr->user_name = NULL; ptr->host_name = NULL; ptr->user_home = NULL; ptr->language = NULL; ptr->region = NULL; ptr->prog_name = NULL; ptr->group_name = NULL; ptr->dir_bin = NULL; ptr->dir_etc = NULL; ptr->dir_share = NULL; ptr->dir_lib = NULL; ptr->dir_var = NULL; ptr->dir_tmp = NULL; ptr->log_file_name = NULL; ptr->source_file_name = NULL; ptr->source_file_line = (dk4_um_t)0UL; ptr->timer_stderr = (dk4_time_t)0UL; ptr->timer_file = (dk4_time_t)0UL; ptr->sz_msg_base = 0; ptr->sz_msg_debug = 0; ptr->have_stderr_time = 0; ptr->have_file_time = 0; ptr->have_file_opened = 0; ptr->have_stderr_init = 0; ptr->my_argc = 0; ptr->ll_stderr = DK4_LL_WARNING; ptr->ll_file = DK4_LL_NONE; ptr->ll_file_keep = DK4_LL_NONE; ptr->ll_found = DK4_LL_IGNORE; ptr->log_stderr_time = 1; ptr->log_file_time = 1; ptr->log_enabled = 0; ptr->encoding = ptr->enc_in_std = ptr->enc_in_file = ptr->enc_out_std = ptr->enc_out_file = DK4_FILE_ENCODING_ASCII; ptr->hvl_cmd = 0; ptr->have_self_pref = 0; ptr->fast_close = 0; ptr->tmp_dir_used = 0; #line 418 "dk4appop.ctr" } /** Check command line arguments for --quiet option. @param argc Number of command line arguments. @param argv Command line arguments array. @return 1 if --quiet was found, 0 otherwise. */ static int dk4app_open_silence_check(int argc, dkChar **argv) { size_t i; /* Traverse arguments list */ int back = 0; /* Function result */ #line 434 "dk4appop.ctr" for (i = 1; i < (size_t)argc; i++) { if (0 == dk4str_cmp(argv[i], dk4app_open_kw[0])) { back = 1; } } #line 439 "dk4appop.ctr" return back; } /** Find language, region, and encoding. Set app->error_found if any error occures. @param app Application structure to set up. */ static void dk4app_open_find_language_region(dk4_app_t *app, dk4_app_error_t *ae) { dkChar lbuf[16]; dkChar rbuf[16]; int enc = DK4_ENCODING_ASCII; int res; #line 457 "dk4appop.ctr" lbuf[0] = dkT('\0'); rbuf[0] = dkT('\0'); res = dk4loc_get_settings( lbuf, DK4_SIZEOF(lbuf,dkChar), rbuf, DK4_SIZEOF(rbuf,dkChar), &enc, NULL ); if (0 != res) { #line 464 "dk4appop.ctr" if (0 < dk4str_len(lbuf)) { app->language = dk4str_dup(lbuf, NULL); if (NULL == app->language) { ae->error_found = E_MEMORY; } } if (0 < dk4str_len(rbuf)) { app->region = dk4str_dup(rbuf, NULL); if (NULL == app->region) { ae->error_found = E_MEMORY; } } app->encoding = app->enc_in_std = app->enc_in_file = app->enc_out_std = app->enc_out_file = enc; #if DK4_CHAR_SIZE > 1 /* Multi-byte input (UTF-16, C32) typically has a BOM at start */ app->enc_in_std = DK4_FILE_ENCODING_ASCII; app->enc_in_file = DK4_FILE_ENCODING_ASCII; #endif } else { ae->error_found = E_LOCALE; } #line 489 "dk4appop.ctr" } /** Report errors occured in initialization. @param app Application structure to report errors for. */ static void dk4app_open_report_error(dk4_app_t *app, dk4_app_error_t *ae) { /* !!!!! */ switch (ae->error_found) { case E_LOCALE: { } break; case E_MEMORY: { } break; case E_EXEFILE: { } break; case E_EXECNAME_TOO_LONG: { } break; case E_NO_DIR_IN_EXENAME: { } break; case E_EMPTY_OPTION_SPEC: { } break; case E_OPTION_LONG_SPEC_MULT: { } break; case E_OPTION_SHORT_SPEC_MULT: { } break; case E_USER_NAME_NOT_FOUND: { } break; case E_USER_HOME_NOT_FOUND: { } break; case E_LOG_FILE_NAME: { } break; } } /** Check whether a dynamically allocated string is not NULL. @param app Application to set up. @param dirname String to test. */ static void dk4app_open_check_directory_name(dk4_app_error_t *ae, dkChar *dirname) { #line 538 "dk4appop.ctr" if (NULL == dirname) { if (0 == ae->error_found) { #line 540 "dk4appop.ctr" ae->error_found = E_MEMORY; } } #line 543 "dk4appop.ctr" } /** The bin directory is the one compiled into the dk4inst module, so retrieve etc, lib, share and var from the dk4inst module too. @param app Application structure to set up. */ static void dk4app_open_find_exec_from_inst(dk4_app_t *app, dk4_app_error_t *ae) { #line 557 "dk4appop.ctr" app->dir_etc = dk4str_dup(dk4inst_get_directory(1), NULL); app->dir_share = dk4str_dup(dk4inst_get_directory(2), NULL); app->dir_lib = dk4str_dup(dk4inst_get_directory(6), NULL); app->dir_var = dk4str_dup(dk4inst_get_directory(3), NULL); dk4app_open_check_directory_name(ae, app->dir_etc); dk4app_open_check_directory_name(ae, app->dir_share); dk4app_open_check_directory_name(ae, app->dir_lib); dk4app_open_check_directory_name(ae, app->dir_var); #line 566 "dk4appop.ctr" } /** Create one new directory name replacing the final path component. @param app Application structure to set up. @param buf Buffer containing old directory name, changed to the new directory name. @param szbuf Size of buffer. @param p1 Pointer to first position to modify in buffer. @param nn New final component name. @return String copy of new directory name in dynamically allocated memory. */ static dkChar * dk4app_open_find_exec_replace_one( dk4_app_t *app, dk4_app_error_t *ae, dkChar *buf, size_t szbuf, dkChar *p1, dkChar const *nn ) { dkChar *back = NULL; #line 593 "dk4appop.ctr" *p1 = dkT('\0'); if (0 != dk4str_cat_s(buf, szbuf, nn, NULL)) { back = dk4str_dup(buf, NULL); if (NULL == back) { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { if (0 == ae->error_found) { ae->error_found = E_EXECNAME_TOO_LONG; } } #line 606 "dk4appop.ctr" return back; } /** Create directory names by replacing the final bin or sbin component by etc, lib, share and var. @param app Application structure to set up. @param buf Buffer for directory name. @param szbuf Size of buffer. @param p1 Pointer to first character to modify. */ static void dk4app_open_find_exec_replace_final( dk4_app_t *app, dk4_app_error_t *ae, dkChar *buf, size_t szbuf, dkChar *p1 ) { #line 629 "dk4appop.ctr" app->dir_etc = dk4app_open_find_exec_replace_one( app, ae, buf, szbuf, p1, dk4app_open_kw[3] ); app->dir_share = dk4app_open_find_exec_replace_one( app, ae, buf, szbuf, p1, dk4app_open_kw[4] ); app->dir_lib = dk4app_open_find_exec_replace_one( app, ae, buf, szbuf, p1, dk4app_open_kw[5] ); app->dir_var = dk4app_open_find_exec_replace_one( app, ae, buf, szbuf, p1, dk4app_open_kw[6] ); #line 642 "dk4appop.ctr" } /** Check whether the path is below the libexec directory compiled into the dk4inst module. @param buf Buffer to check. @return 1 if the path is below the libexec directory, 0 otherwise. */ static int dk4app_open_is_dkinst_libexec(dkChar *buf) { size_t sz; int back = 0; #line 658 "dk4appop.ctr" sz = dk4str_len(dk4inst_get_directory(10)); if (0 < sz) { if (dk4str_len(buf) > sz) { if (buf[sz] == dk4app_filename_sep[0]) { buf[sz] = dkT('\0'); if (0 == dk4str_pathcmp(buf, dk4inst_get_directory(10))) { back = 1; } else { buf[sz] = dk4app_filename_sep[0]; } } } } #line 671 "dk4appop.ctr" return back; } /** Check if there is any libexec component in the path. Cut path to part before libexec if found. @param buf Buffer containing the directory. @param szbuf Buffer size. @return 1 on success (libexec found), 0 otherwise. */ static int dk4app_open_is_any_libexec(dkChar *buf, size_t szbuf) { dkChar mybuf[DK4_MAX_PATH]; dkChar *p1; dkChar *p2; int back = 0; #line 691 "dk4appop.ctr" if (0 != dk4str_cpy_s(mybuf, DK4_SIZEOF(mybuf,dkChar), buf, NULL)) { p1 = dk4str_rchr(mybuf, dk4app_filename_sep[0]); while ((0 == back) && (NULL != p1)) { p2 = p1; p2++; if (0 == dk4str_pathcmp(p2, dk4app_open_kw[7])) { back = 1; *p1 = dkT('\0'); dk4str_cpy_s(buf, szbuf, mybuf, NULL); p1 = NULL; } else { *p1 = dkT('\0'); p1 = dk4str_rchr(mybuf, dk4app_filename_sep[0]); } } } #line 707 "dk4appop.ctr" return back; } static void dk4app_open_find_copy_bindir(dk4_app_t *app, dk4_app_error_t *ae) { #line 717 "dk4appop.ctr" if (NULL != app->dir_bin) { app->dir_etc = dk4str_dup(app->dir_bin, NULL); app->dir_share = dk4str_dup(app->dir_bin, NULL); app->dir_lib = dk4str_dup(app->dir_bin, NULL); app->dir_var = dk4str_dup(app->dir_bin, NULL); } dk4app_open_check_directory_name(ae, app->dir_etc); dk4app_open_check_directory_name(ae, app->dir_share); dk4app_open_check_directory_name(ae, app->dir_lib); dk4app_open_check_directory_name(ae, app->dir_var); #line 728 "dk4appop.ctr" } /** Find executable file for process and derive program name and directories from it. @param app Application structure to set up. @param arg0 First command line word. */ static void dk4app_open_find_executable( dk4_app_t *app, dk4_app_error_t *ae, const dkChar *arg0 ) { dkChar buf[DK4_MAX_PATH]; dkChar *p1; size_t const szbuf = DK4_SIZEOF(buf,dkChar); #line 749 "dk4appop.ctr" if (0 != dk4execpath(buf, szbuf, arg0, NULL)) { p1 = dk4str_rchr(buf, dk4app_filename_sep[0]); if (NULL != p1) { *(p1++) = dkT('\0'); if (0 < dk4str_len(buf)) { /* Save program name */ app->prog_name = dk4str_dup(p1, NULL); if (NULL == app->prog_name) { ae->error_found = E_MEMORY; } else { #if DK4_ON_WINDOWS /* Remove .exe suffix */ p1 = dk4path_get_suffix(app->prog_name, NULL); if (NULL != p1) { if (-1 < dk4str_array_index(dk4app_exe_file_suffixes, p1, 0)) { *p1 = dkT('\0'); } } #endif } #line 770 "dk4appop.ctr" /* Save bindir name */ app->dir_bin = dk4str_dup(buf, NULL); #line 773 "dk4appop.ctr" if (NULL == app->dir_bin) { ae->error_found = E_MEMORY; } /* Find other directories */ if (0 == dk4str_pathcmp(buf, dk4inst_get_directory(4))) { #line 777 "dk4appop.ctr" /* In .../bin, use directories from dk4inst */ dk4app_open_find_exec_from_inst(app, ae); } else { if (0 == dk4str_pathcmp(buf, dk4inst_get_directory(5))) { #line 782 "dk4appop.ctr" /* In .../sbin, use directories from dk4inst */ dk4app_open_find_exec_from_inst(app, ae); } else { if (dk4app_open_is_dkinst_libexec(buf)) { #line 787 "dk4appop.ctr" /* In .../libexec/..., use directories from dk4inst */ dk4app_open_find_exec_from_inst(app, ae); } else { p1 = dk4str_rchr(buf, dk4app_filename_sep[0]); if (NULL != p1) { p1++; if (0 == dk4str_pathcmp(p1, dk4app_open_kw[1])) { #line 795 "dk4appop.ctr" /* Replace final path component by etc, lib... */ dk4app_open_find_exec_replace_final( app, ae, buf, szbuf, p1 ); } else { if (0 == dk4str_pathcmp(p1, dk4app_open_kw[2])) { #line 802 "dk4appop.ctr" /* Replace final path component by etc, lib... */ dk4app_open_find_exec_replace_final( app, ae, buf, szbuf, p1 ); } else { if (dk4app_open_is_any_libexec(buf,szbuf)) { /* We can securely append the separator and the finalizer as the dk4app_open_is_any_libexec() function cutted a libexec string from the path. */ #line 814 "dk4appop.ctr" p1 = buf; while(dkT('\0') != *p1) { p1++; } *(p1++) = dk4app_filename_sep[0]; *p1 = dkT('\0'); dk4app_open_find_exec_replace_final( app, ae, buf, szbuf, p1 ); } else { #line 822 "dk4appop.ctr" dk4app_open_find_copy_bindir(app, ae); } } } } else { #line 827 "dk4appop.ctr" dk4app_open_find_copy_bindir(app, ae); } } } } #line 833 "dk4appop.ctr" #line 834 "dk4appop.ctr" #line 835 "dk4appop.ctr" #line 836 "dk4appop.ctr" } else { #line 837 "dk4appop.ctr" ae->error_found = E_EXECNAME_TOO_LONG; } } else { #line 840 "dk4appop.ctr" ae->error_found = E_NO_DIR_IN_EXENAME; } } else { #line 843 "dk4appop.ctr" ae->error_found = E_EXEFILE; } #line 846 "dk4appop.ctr" } static void dk4app_close_prefeferences(dk4_sto_t *s, dk4_sto_it_t *i) { dk4_pref_t *prefptr; if (NULL != i) { dk4sto_it_reset(i); do { prefptr = (dk4_pref_t *)dk4sto_it_next(i); if (NULL != prefptr) { dk4pref_close(prefptr); } } while(NULL != prefptr); dk4sto_it_close(i); } if (NULL != s) { dk4sto_close(s); } } int dk4app_close(dk4_app_t *app) { dk4_option_t *optptr; dk4_string_table_t *ptrstt; int back = 0; #line 879 "dk4appop.ctr" if (NULL != app) { /* Remove temporary files */ if (0 == app->fast_close) { if ((NULL != app->dir_tmp) && (0 != app->tmp_dir_used)) { (void)dk4app_del_tree(app->dir_tmp, app); } } #if 0 /* Write preferences back to file */ if ((0 != app->have_self_pref) && (0 == app->fast_close)) { /* Originally intended: Write self-set preferences back to file. 2015-04-17: Design decision not to write back. Preferences are read-only in version 4. For GUI programs there are mechanisms in wxWidgets to save configuration changes. */ } #endif /* The base and debug messages are read from string tables, so the arrays are freed when freeing the string tables. */ app->msg_base = NULL; app->msg_debug = NULL; app->source_file_name = NULL; back = 1; /* Disable logging */ app->log_enabled = 0; /* Delete log file unless there is a reason to keep it */ if (NULL != app->log_file_name) { if ((app->ll_found <= app->ll_file) && (0 != app->have_file_opened)) { if (app->ll_file_keep < app->ll_found) { (void)dk4delete_file(app->log_file_name, NULL); } } } /* Release memory for log file */ dk4mem_release(app->log_file_name); /* Release memory for directories */ app->help_text = NULL; app->lic_text = NULL; dk4mem_release(app->dir_tmp); dk4mem_release(app->dir_var); dk4mem_release(app->dir_lib); dk4mem_release(app->dir_share); dk4mem_release(app->dir_etc); dk4mem_release(app->dir_bin); dk4mem_release(app->group_name); dk4mem_release(app->prog_name); /* Release memory for language and region */ dk4mem_release(app->region); dk4mem_release(app->language); dk4mem_release(app->vers_text); dk4mem_release(app->help_file_name); dk4mem_release(app->host_name); dk4mem_release(app->user_home); dk4mem_release(app->user_name); #if TRACE_DEBUG { int i; if ((0 < app->my_argc) && (NULL != app->my_argv)) { for (i = 0; i < app->my_argc; i++) { #line 943 "dk4appop.ctr" } } } #endif dk4mem_release(app->my_argv); /* Release string tables */ if (NULL != app->s_stt) { if (NULL != app->i_stt) { dk4sto_it_reset(app->i_stt); do { ptrstt = (dk4_string_table_t *)dk4sto_it_next(app->i_stt); if (NULL != ptrstt) { dk4stt_close(ptrstt); } } while (NULL != ptrstt); dk4sto_it_close(app->i_stt); } dk4sto_close(app->s_stt); } app->s_stt = NULL; app->i_stt = NULL; /* Release options All options in s_opt_long and s_opt_short are also in s_opt_all. They are deleted later, so we can simply close the storages here. */ if (NULL != app->i_opt_long) { dk4sto_it_close(app->i_opt_long); } app->i_opt_long = NULL; if (NULL != app->i_opt_short) { dk4sto_it_close(app->i_opt_short); } app->i_opt_short = NULL; if (NULL != app->s_opt_long) { dk4sto_close(app->s_opt_long); } app->s_opt_long = NULL; if (NULL != app->s_opt_short) { dk4sto_close(app->s_opt_short); } app->s_opt_short = NULL; dk4app_close_prefeferences(app->s_pref_sys, app->i_pref_sys); dk4app_close_prefeferences(app->s_pref_user, app->i_pref_user); dk4app_close_prefeferences(app->s_pref_cmd, app->i_pref_cmd); dk4app_close_prefeferences(app->s_pref_self, app->i_pref_self); app->s_pref_self = NULL; app->s_pref_cmd = NULL; app->s_pref_user = NULL; app->s_pref_sys = NULL; app->i_pref_self = NULL; app->i_pref_cmd = NULL; app->i_pref_user = NULL; app->i_pref_sys = NULL; if (NULL != app->i_opt_all) { dk4sto_it_reset(app->i_opt_all); do { optptr = (dk4_option_t *)dk4sto_it_next(app->i_opt_all); if (NULL != optptr) { dk4opt_close(optptr); } } while(NULL != optptr) ; dk4sto_it_close(app->i_opt_all); } app->i_opt_all = NULL; if (NULL != app->s_opt_all) { dk4sto_close(app->s_opt_all); } app->s_opt_all = NULL; /* Release memory for app structure itself */ dk4mem_free(app); } #line 1005 "dk4appop.ctr" return back; } /** Process the options specification. @param app Application to set up. @param ae Application error structure. @param optspec The option specification. @param szoptspec Size of the optspec array. */ static void dk4app_open_process_optspec( dk4_app_t *app, dk4_app_error_t *ae, const dk4_option_specification_t *optspec, size_t szoptspec ) { dk4_option_t *optptr; #line 1027 "dk4appop.ctr" while(szoptspec--) { if ((NULL != optspec->longopt) || (dkT('\0') != optspec->c)) { optptr = dk4opt_open(optspec, NULL); if (NULL != optptr) { if (0 != dk4sto_add(app->s_opt_all, optptr, NULL)) { if (NULL != optspec->longopt) { if (NULL == dk4sto_it_find_like(app->i_opt_long,optspec->longopt,3)) { if (0 == dk4sto_add(app->s_opt_long, optptr, NULL)) { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } szoptspec = 0; } } else { #line 1042 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_OPTION_LONG_SPEC_MULT; ae->longopt = optspec->longopt; } szoptspec = 0; } } if (dkT('\0') != optspec->c) { if (NULL == dk4sto_it_find_like(app->i_opt_short,&(optspec->c),1)) { if (0 == dk4sto_add(app->s_opt_short, optptr, NULL)) { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } szoptspec = 0; } } else { #line 1059 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_OPTION_SHORT_SPEC_MULT; ae->longopt = optspec->longopt; } szoptspec = 0; } } } else { #line 1067 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_MEMORY; } szoptspec = 0; dk4opt_close(optptr); optptr = NULL; } } else { #line 1072 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_MEMORY; } szoptspec = 0; } } else { #line 1076 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_EMPTY_OPTION_SPEC; } szoptspec = 0; } optspec++; } #line 1081 "dk4appop.ctr" } /** Create and prepare the storage containers for command line options. @param app Application to set up. @param ae Application error structure. @param optspec The option specification. @param szoptspec Size of the optspec array. */ static void dk4app_open_create_options_storages( dk4_app_t *app, dk4_app_error_t *ae, const dk4_option_specification_t *optspec, size_t szoptspec ) { #line 1101 "dk4appop.ctr" if ((NULL != optspec) && (0 < szoptspec)) { app->s_opt_all = dk4sto_open(NULL); if (NULL != app->s_opt_all) { app->s_opt_long = dk4sto_open(NULL); if (NULL != app->s_opt_long) { dk4sto_set_comp(app->s_opt_long, dk4option_compare, 2); app->s_opt_short = dk4sto_open(NULL); if (NULL != app->s_opt_short) { dk4sto_set_comp(app->s_opt_short, dk4option_compare, 0); app->i_opt_all = dk4sto_it_open(app->s_opt_all, NULL); if (NULL != app->i_opt_all) { app->i_opt_long = dk4sto_it_open(app->s_opt_long, NULL); if (NULL != app->i_opt_long) { app->i_opt_short = dk4sto_it_open(app->s_opt_short, NULL); if (NULL != app->i_opt_short) { dk4app_open_process_optspec(app, ae, optspec, szoptspec); } else { #line 1118 "dk4appop.ctr" ae->error_found = E_MEMORY; } } else { #line 1121 "dk4appop.ctr" ae->error_found = E_MEMORY; } } else { #line 1124 "dk4appop.ctr" ae->error_found = E_MEMORY; } } else { #line 1127 "dk4appop.ctr" ae->error_found = E_MEMORY; } } else { #line 1130 "dk4appop.ctr" ae->error_found = E_MEMORY; } } else { #line 1133 "dk4appop.ctr" ae->error_found = E_MEMORY; } } #line 1136 "dk4appop.ctr" } /** Create storage containers for preferences. @param app Application to set up. @param ae Error storage for setup. */ static void dk4app_open_create_pref_storages( dk4_app_t *app, dk4_app_error_t *ae ) { app->s_pref_sys = dk4sto_open(NULL); if (NULL != app->s_pref_sys) { app->s_pref_user = dk4sto_open(NULL); if (NULL != app->s_pref_user) { app->s_pref_cmd = dk4sto_open(NULL); if (NULL != app->s_pref_cmd) { app->s_pref_self = dk4sto_open(NULL); if (NULL != app->s_pref_self) { dk4sto_set_comp(app->s_pref_sys, dk4pref_compare, 0); dk4sto_set_comp(app->s_pref_user, dk4pref_compare, 0); dk4sto_set_comp(app->s_pref_cmd, dk4pref_compare, 0); dk4sto_set_comp(app->s_pref_self, dk4pref_compare, 0); app->i_pref_sys = dk4sto_it_open(app->s_pref_sys, NULL); app->i_pref_user = dk4sto_it_open(app->s_pref_user, NULL); app->i_pref_cmd = dk4sto_it_open(app->s_pref_cmd, NULL); app->i_pref_self = dk4sto_it_open(app->s_pref_self, NULL); if ((NULL == app->i_pref_sys) || (NULL == app->i_pref_user)) { ae->error_found = E_MEMORY; } if ((NULL == app->i_pref_cmd) || (NULL == app->i_pref_self)) { ae->error_found = E_MEMORY; } } else { ae->error_found = E_MEMORY; } } else { ae->error_found = E_MEMORY; } } else { ae->error_found = E_MEMORY; } } else { ae->error_found = E_MEMORY; } } /** Create storage container for string tables. @param app Application to set up. @param ae Error storage for setup. */ static void dk4app_open_create_stt_storage( dk4_app_t *app, dk4_app_error_t *ae ) { app->s_stt = dk4sto_open(NULL); if (NULL != app->s_stt) { dk4sto_set_comp(app->s_stt, dk4stt_compare, 0); app->i_stt = dk4sto_it_open(app->s_stt, NULL); if (NULL == app->i_stt) { ae->error_found = E_MEMORY; } } else { ae->error_found = E_MEMORY; } } /** Attempt to find users login name and home directory. On Linux/Unix the effective user name and home directory is searched. @param app Application to set up. @param ae Application opening error structure. */ static void dk4app_open_find_user_name_and_home(dk4_app_t *app, dk4_app_error_t *ae) { dkChar buf[DK4_MAX_PATH]; dk4_er_t er; #line 1226 "dk4appop.ctr" dk4error_init(&er); if (0 != dk4user_get_logname(buf, DK4_SIZEOF(buf,dkChar), 1, &er)) { app->user_name = dk4str_dup(buf, &er); if (NULL != app->user_name) { if (0 != dk4user_get_homedir(buf, DK4_SIZEOF(buf,dkChar), 1, &er)) { app->user_home = dk4str_dup(buf, &er); if (NULL == app->user_home) { ae->error_found = E_MEMORY; } } else { ae->error_found = E_USER_HOME_NOT_FOUND; } } else { ae->error_found = E_MEMORY; } } else { ae->error_found = E_USER_NAME_NOT_FOUND; } #line 1245 "dk4appop.ctr" #line 1246 "dk4appop.ctr" #line 1247 "dk4appop.ctr" } /** Preference reader structure. */ typedef struct { dk4_app_t *app; /**< Application to set up. */ dk4_app_error_t *ae; /**< Application error structure. */ dk4_sto_t *st; /**< Storage for preferences. */ dk4_sto_it_t *it; /**< Storage iterator. */ int insc; /**< Flag: In current scope. */ int lasc; /**< Flag: Previous line was scope line. */ int co3; /**< Flag: DK tools 3 compatibility. */ } dk4_app_pref_rd_t; /** Initialize preference reader structure for start of file. @param ptr Preference reader structure. */ static void dk4app_open_pref_reader_init_for_one_file(dk4_app_pref_rd_t *ptr) { ptr->insc = 1; ptr->lasc = 0; ptr->co3 = 0; } /** Check one scope line entry. @param app Application. @param ae Application open error structure. @param pn Pointer to entry name. @param pv Pointer to entry value. @return 1 if condition is true, 0 otherwise. */ static int dk4app_open_check_one_scope_entry( dk4_app_t *app, dk4_app_error_t *ae, const dkChar *pn, const dkChar *pv ) { int back = 0; #line 1297 "dk4appop.ctr" switch (dk4str_array_index(dk4app_open_scope_names, pn, 0)) { case 0: { if ((NULL != pv) && (NULL != app->user_name)) { #line 1301 "dk4appop.ctr" #if DK4_HAVE_CASE_INSENSITIVE_USERNAMES if (0 == dk4str_casecmp(pv, app->user_name)) #else if (0 == dk4str_cmp(pv, app->user_name)) #endif { back = 1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; case 1: { if ((NULL != pv) && (NULL != app->prog_name)) { #line 1320 "dk4appop.ctr" #if DK4_HAVE_CASE_INSENSITIVE_PATHNAMES if (0 == dk4str_casecmp(pv, app->prog_name)) #else if (0 == dk4str_cmp(pv, app->prog_name)) #endif { back = 1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; case 2: { #line 1337 "dk4appop.ctr" if ((NULL != pv) && (NULL != app->group_name)) { #line 1339 "dk4appop.ctr" #if DK4_HAVE_CASE_INSENSITIVE_PATHNAMES if (0 == dk4str_casecmp(pv, app->group_name)) #else if (0 == dk4str_cmp(pv, app->group_name)) #endif { back = 1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; case 3: { #line 1356 "dk4appop.ctr" if ((NULL != pv) && (NULL != app->host_name)) { #line 1358 "dk4appop.ctr" if (0 == dk4str_casecmp(pv, app->host_name)) { back = 1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; case 4: { #line 1368 "dk4appop.ctr" if (NULL != pv) { #if DK4_ON_WINDOWS if (0 != dk4str_is_on(pv)) { back = 1; } #else if (0 == dk4str_is_on(pv)) { back = 1; } #endif } else { #if DK4_ON_WINDOWS back = 1; #endif } } break; case 5: { #line 1385 "dk4appop.ctr" if (NULL != pv) { #if DK4_ON_WINDOWS if (0 == dk4str_is_on(pv)) { back = 1; } #else if (0 != dk4str_is_on(pv)) { back = 1; } #endif } else { #if DK4_ON_WINDOWS back = 0; #else back = 1; #endif } } break; case 6 : { #line 1404 "dk4appop.ctr" if ((NULL != pv) && (NULL != app->language)) { if (0 == dk4str_casecmp(pv, app->language)) { back =1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; case 7 : { #line 1415 "dk4appop.ctr" if ((NULL != pv) && (NULL != app->region)) { if (0 == dk4str_casecmp(pv, app->region)) { back =1; } else { if (0 == dk4str_cmp(pv, dk4app_open_kw[15])) { back = 1; } } } } break; default: { #line 1426 "dk4appop.ctr" if (0 == dk4str_len(pn)) { #line 1427 "dk4appop.ctr" back = 1; } } break; } #line 1431 "dk4appop.ctr" return back; } /** Add one preference to storages. @param app Application to configure. @param ae Application open error structure. @param st Storage. @param it Iterator for storage. @param pn Preference name. @param pv Preference value. */ static void dk4app_open_add_preference( dk4_app_t *app, dk4_app_error_t *ae, dk4_sto_t *st, dk4_sto_it_t *it, const dkChar *pn, const dkChar *pv ) { dk4_pref_t *prefptr; dkChar *npv; #line 1458 "dk4appop.ctr" prefptr = dk4sto_it_find_like(it, pn, 1); if (NULL != prefptr) { #line 1460 "dk4appop.ctr" npv = dk4str_dup(pv, NULL); if (NULL != npv) { #if 0 dk4mem_release(prefptr->value); #endif /* 2016-12-10 Sanitize memory before releasing it. */ dk4str_release_sanitized(prefptr->value); prefptr->value = npv; } else { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { #line 1473 "dk4appop.ctr" prefptr = dk4pref_open(pn, pv, NULL); if (NULL != prefptr) { if (0 == dk4sto_add(st, (void *)prefptr, NULL)) { dk4pref_close(prefptr); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } dk4app_pref_apply(app, ae, pn, pv); #line 1485 "dk4appop.ctr" } /** Modify a preference value from DK tools 3 to 4 syntax. Change "/print/ps/level" to "print.ps.level". @param Preference name pointer. */ static void dk4app_open_modify_prefname_3_to_4(dkChar *pn) { if (NULL != pn) { if (dkT('/') == *pn) { dk4str_cpy_to_left(pn, &(pn[1])); while (dkT('\0') != *pn) { if (dkT('/') == *pn) { *pn = dkT('.'); } pn++; } } } } /** Process one input line. @param obj Preferences reader object. @param line Current line to process. @param lineno Line number. @param erp Error report, may be NULL. @return DK4_TSP_RES_OK if processing succeeded, DK4_TSP_RES_ERROR on errors (can continue), DK4_TSP_RES_FATAL on fatal errors (can not continue). */ static int dk4app_open_pref_line_handler( void *obj, dkChar *line, dk4_um_t lineno, dk4_er_t *erp ) { dkChar *p1; /* Name text */ dkChar *p2; /* Next text */ dkChar *pv; /* Value text */ dk4_app_pref_rd_t *ptr; /* Reader structure */ int back = DK4_TSP_RES_OK; /* Function result */ int isneg = 0; /* Flag: Exclude scope */ int ok; /* Flag: No test failed yet */ #line 1540 "dk4appop.ctr" dk4str_delnl(line); ptr = (dk4_app_pref_rd_t *)obj; p1 = dk4str_start(line, NULL); if (NULL != p1) { if (dkT('#') != *p1) { #line 1545 "dk4appop.ctr" if (dkT('[' == *p1)) { #line 1546 "dk4appop.ctr" if (0 == ptr->lasc) { #line 1547 "dk4appop.ctr" ptr->insc = 0; } else { #line 1549 "dk4appop.ctr" } p2 = dk4str_chr(p1, dkT(']')); if (NULL != p2) { #line 1552 "dk4appop.ctr" *p2 = dkT('\0'); } p1++; if (dkT('-') == *p1) { #line 1556 "dk4appop.ctr" isneg = 1; p1++; } ok = 1; while (NULL != p1) { p2 = dk4str_chr(p1, dkT(',')); if (NULL != p2) { *(p2++) = dkT('\0'); p2 = dk4str_start(p2, NULL); } pv = dk4str_chr(p1, dkT('=')); if (NULL != pv) { *(pv++) = dkT('\0'); pv = dk4str_start(pv, NULL); } dk4str_normalize(p1, NULL); if (NULL != pv) { dk4str_rtwh(pv, NULL); } if (0 == dk4app_open_check_one_scope_entry(ptr->app,ptr->ae,p1,pv)) { ok = 0; } p1 = p2; } if (1 == ok) { #line 1573 "dk4appop.ctr" if (0 != isneg) { ptr->insc = 0; #line 1575 "dk4appop.ctr" } else { ptr->insc = 1; #line 1577 "dk4appop.ctr" } } else { #line 1579 "dk4appop.ctr" } ptr->lasc = 1; } else { #line 1582 "dk4appop.ctr" if (ptr->insc) { #line 1583 "dk4appop.ctr" p2 = dk4str_chr(p1, dkT('=')); if (NULL != p2) { *(p2++) = dkT('\0'); p2 = dk4str_start(p2, NULL); } if ((NULL != p1) && (NULL != p2)) { dk4str_normalize(p1, NULL); dk4str_rtwh(p2, NULL); if (0 < ptr->co3) { #line 1589 "dk4appop.ctr" dk4app_open_modify_prefname_3_to_4(p1); #line 1591 "dk4appop.ctr" } else { #line 1592 "dk4appop.ctr" } dk4app_open_add_preference(ptr->app,ptr->ae,ptr->st,ptr->it,p1,p2); } } else { #line 1596 "dk4appop.ctr" } ptr->lasc = 0; } } else { #line 1600 "dk4appop.ctr" } } else { #line 1602 "dk4appop.ctr" } #line 1603 "dk4appop.ctr" return back; } /** Read all preferences files in increasing order. Cumulative operation, redefinitions possible. @param app Application to configure. @param ae Application opening error structure. */ static void dk4app_open_read_preference_files(dk4_app_t *app, dk4_app_error_t *ae) { char ib[4096]; /* Input buffer */ dkChar il[1024]; /* Input line */ dkChar fnb[DK4_MAX_PATH]; /* File name buffer */ dk4_tspdk_t tsp; /* Text stream processor */ dk4_er_t er; /* Error report */ dk4_app_pref_rd_t rdobj; /* Reader object */ dk4_stream_t *istrm; /* Input stream */ size_t rb; /* Bytes read from stream */ int pn; /* Pass number */ int res; /* Result from path construct */ int cc; /* Flag: Can continue */ #line 1629 "dk4appop.ctr" rdobj.app = app; rdobj.ae = ae; for (pn = 0; ((0 == ae->error_found) && (pn <= DK4_FS_CONF_MAX)); pn++) { if (DK4_FS_CONF_SYS_MAX >= pn) { rdobj.st = app->s_pref_sys; rdobj.it = app->i_pref_sys; } else { rdobj.st = app->s_pref_user; rdobj.it = app->i_pref_user; } #if DK4_HAVE_COMPATDKTOOLS3 dk4error_init(&er); res = dk4fs_config_compat_one( fnb, DK4_SIZEOF(fnb,dkChar), dk4app_open_kw[14], app->dir_share, app->dir_etc, app->user_home, app->prog_name, app->group_name, pn, 1, 1, &er ); if (0 != res) { #line 1648 "dk4appop.ctr" istrm = dk4stream_open_file_reader(fnb, &er); if (NULL != istrm) { #line 1650 "dk4appop.ctr" dk4app_open_pref_reader_init_for_one_file(&rdobj); rdobj.co3 = 1; res = dk4tspdk_setup_line( &tsp, &rdobj, dk4app_open_pref_line_handler, il, DK4_SIZEOF(il,dkChar), app->encoding, app->enc_in_file, &er ); if (0 != res) { #line 1658 "dk4appop.ctr" res = DK4_TSP_RES_OK; do { cc = 0; rb = sizeof(ib); if (0 != dk4stream_read(ib, &rb, istrm, &er)) { if (0 < rb) { cc = 1; res = dk4tspdk_add_bytes(&tsp, (const unsigned char *)ib, rb); if (DK4_TSP_RES_FATAL == res) { cc = 0; } } } } while(0 != cc); if (DK4_TSP_RES_FATAL != res) { #if VERSION_BEFORE_20150821 res = dk4tspdk_finish(&tsp); #else dk4tspdk_finish(&tsp); #endif } } else { #line 1680 "dk4appop.ctr" } dk4stream_close(istrm, NULL); } else { #line 1683 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_PREF_FILE_OPEN; } } } #endif dk4error_init(&er); res = dk4fs_config_one( fnb, DK4_SIZEOF(fnb,dkChar), dk4app_open_kw[8], app->dir_share, app->dir_etc, app->user_home, app->prog_name, app->group_name, pn, 1, &er ); if (0 != res) { #line 1695 "dk4appop.ctr" istrm = dk4stream_open_file_reader(fnb, &er); if (NULL != istrm) { #line 1697 "dk4appop.ctr" dk4app_open_pref_reader_init_for_one_file(&rdobj); res = dk4tspdk_setup_line( &tsp, &rdobj, dk4app_open_pref_line_handler, il, DK4_SIZEOF(il,dkChar), app->encoding, app->enc_in_file, &er ); if (0 != res) { #line 1704 "dk4appop.ctr" res = DK4_TSP_RES_OK; do { cc = 0; rb = sizeof(ib); if (0 != dk4stream_read(ib, &rb, istrm, &er)) { if (0 < rb) { cc = 1; res = dk4tspdk_add_bytes(&tsp, (const unsigned char *)ib, rb); if (DK4_TSP_RES_FATAL == res) { cc = 0; } } } } while(0 != cc); if (DK4_TSP_RES_FATAL != res) { #if VERSION_BEFORE_20150821 res = dk4tspdk_finish(&tsp); #else dk4tspdk_finish(&tsp); #endif } } else { #line 1726 "dk4appop.ctr" } dk4stream_close(istrm, NULL); } else { #line 1729 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_PREF_FILE_OPEN; } } } } #line 1733 "dk4appop.ctr" } /** Find host name for computer. @param app Application to set up. @param ae Application opening error structure. */ static void dk4app_open_find_host_name(dk4_app_t *app, dk4_app_error_t *ae) { dkChar buf[256]; if (0 != dk4hostname(buf, DK4_SIZEOF(buf,dkChar), NULL)) { app->host_name = dk4str_dup(buf, NULL); if (NULL == app->host_name) { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { if (0 == ae->error_found) { ae->error_found = E_HOST_NAME_NOT_FOUND; } } } /** Check whether an option specification was given and processed successfully. @param app Application to set up. @return 1 if option specification given, 0 otherwise. */ static int dk4app_open_options_check(dk4_app_t *app) { int back = 0; if ((NULL != app->s_opt_all) && (NULL != app->i_opt_all)) { if ((NULL != app->s_opt_short) && (NULL != app->i_opt_short)) { if ((NULL != app->s_opt_long) && (NULL != app->i_opt_long)) { back = 1; } } } return back; } /** Check for --help --version --license. @param app Application to set up. @param ae Application open error structure. @param arg Argument to process. @return 1 if the option needs no further processing, 0 otherwise. */ static int dk4app_open_check_long_opt(dk4_app_t *app, dk4_app_error_t *ae, dkChar *arg) { int back = 0; switch (dk4str_array_index(dk4app_open_long_opt, arg, 1)) { case 0: { /* help */ app->hvl_cmd |= DK4_APP_CMD_HELP; back = 1; } break; case 1: { /* version */ app->hvl_cmd |= DK4_APP_CMD_VERSION; back = 1; } break; case 2: { /* license */ app->hvl_cmd = DK4_APP_CMD_LICENSE; back = 1; } break; case 3: { back = 1; } break; case 4: { app->hvl_cmd |= DK4_APP_CMD_MANUAL; back = 1; } break; } return back; } /** Construct log file name, create log directory. @param app Application to set up. @param ae Application open error structure. */ static void dk4app_open_prepare_file_logging(dk4_app_t *app, dk4_app_error_t *ae) { dkChar fnb[DK4_MAX_PATH]; /* File name buffer */ dkChar dktb[32]; /* Date as dkChar text */ dkChar pidb[32]; /* Buffer for PID */ dkChar pi2b[32]; /* Buffer for padded PID */ dkChar tb[32]; /* Date as text */ dkChar *ptr; dk4_time_t timer; /* Current time */ dk4_pid_t pid; /* Process ID */ size_t sz; /* Size of fnb */ size_t szdktb; /* Size of dktb */ size_t sl; /* String length */ size_t pl; /* Padded length */ int ok = 0; #line 1839 "dk4appop.ctr" sz = DK4_SIZEOF(fnb,dkChar); dk4time_get(&timer); if (dk4str_cpy_s(fnb, sz, app->user_home, NULL)) { if (dk4str_cat_s(fnb, sz, dk4app_open_kw[9], NULL)) { dk4path_correct_sep(fnb); #if VERSION_BEFORE_20160127 ok = dk4app_mkdir_hierarchy(fnb, 1, app); #else ok = 1; #endif if (0 < ok) { ok = 0; if (dk4str_cat_s(fnb, sz, dk4app_open_kw[10], NULL)) { if (dk4str_cat_s(fnb, sz, app->prog_name, NULL)) { if (dk4time_as_text(tb, DK4_SIZEOF(tb,dkChar), &timer, NULL)) { szdktb = DK4_SIZEOF(dktb,dkChar); if (dk4str_cpy_s(dktb, szdktb, tb, NULL)) { ptr = dktb; while (dkT('\0') != *ptr) { if (dkT(':') == *ptr) { *ptr = dkT('-'); } if (dkT(' ') == *ptr) { *ptr = dkT('-'); } ptr++; } pid = dk4getpid(); ok = dk4ma_write_decimal_unsigned( pidb, DK4_SIZEOF(pidb,dkChar), (dk4_um_t)pid, 0, NULL ); if (0 != ok) { for (sl = 0; sl < DK4_SIZEOF(pi2b,dkChar); sl++) { pi2b[sl] = dkT('0'); } pi2b[DK4_SIZEOF(pi2b,dkChar)-1] = dkT('\0'); sl = dk4str_len(pidb); pl = dk4numlength(sizeof(dk4_pid_t), 0); if (sl < pl) { ok = dk4str_cpy_s( &(pi2b[pl - sl]), (DK4_SIZEOF(pi2b,dkChar) - (pl - sl)), pidb, NULL ); } else { ok = dk4str_cpy_s(pi2b,DK4_SIZEOF(pi2b,dkChar),pidb,NULL); } if (0 != ok) { ok = 0; if (dk4str_cat_s(fnb, sz, dk4app_open_kw[11], NULL)) { if (dk4str_cat_s(fnb, sz, dktb, NULL)) { if (dk4str_cat_s(fnb, sz, dk4app_open_kw[11], NULL)) { if (dk4str_cat_s(fnb, sz, pi2b, NULL)) { if (dk4str_cat_s(fnb,sz,dk4app_open_kw[12],NULL)) { app->log_file_name = dk4str_dup(fnb,NULL); if (NULL != app->log_file_name) { dk4path_correct_sep(app->log_file_name); ok = 1; #line 1894 "dk4appop.ctr" } } } } } } } if (0 != ok) { ok = 0; (void)dk4str_cpy_s(fnb, sz, app->user_home, NULL); (void)dk4str_cat_s(fnb, sz, dk4app_open_kw[13], NULL); (void)dk4str_cat_s(fnb, sz, dk4app_open_kw[10], NULL); (void)dk4str_cat_s(fnb, sz, app->prog_name, NULL); (void)dk4str_cat_s(fnb, sz, dk4app_open_kw[11], NULL); (void)dk4str_cat_s(fnb, sz, dktb, NULL); (void)dk4str_cat_s(fnb, sz, dk4app_open_kw[11], NULL); (void)dk4str_cat_s(fnb, sz, pi2b, NULL); dk4path_correct_sep(fnb); app->dir_tmp = dk4str_dup(fnb, NULL); if (NULL != app->dir_tmp) { #if VERSION_BEFORE_20160127 ok = dk4app_mkdir_hierarchy(app->dir_tmp, 0, app); #else ok = 1; #endif #line 1920 "dk4appop.ctr" } } } } } } } } } } if (0 == ok) { /* ERROR: Failed to construct log file name */ ae->error_found = E_LOG_FILE_NAME; } #line 1935 "dk4appop.ctr" } /** Process command line arguments. Save all non-option arguments in my_argc and my_argv if an option specification available, all arguments otherwise. @param app Application to set up. @param ae Application open error structure. @param argc Number of command line arguments. @param argv Command line arguments array. */ static void dk4app_open_process_argc_argv( dk4_app_t *app, dk4_app_error_t *ae, int argc, dkChar **argv ) { dkChar b[DK4_MAX_PATH + 128]; /* Private copy */ dkChar *argptr; /* Current option to process. */ dkChar *pv; /* Option value pointer */ dkChar *opv; /* Original option value pointer */ const dkChar *endptr; /* First char after value */ dk4_option_t *ospec; /* Option specification */ dk4_pref_t *prefptr; /* Preference */ double dval; /* Double value */ dk4_um_t uval; /* Unsigned integer value */ dk4_im_t ival; /* Integer value */ size_t szval; /* Size argument */ int i; /* Current option index to process */ int argsused; /* used elements in my_argv */ int res; /* Numeric conversion result */ int must_add; /* Flag: Must add to list */ int oi; /* Output index */ #line 1973 "dk4appop.ctr" if (0 < argc) { #line 1974 "dk4appop.ctr" app->my_argv = dk4mem_new(DK4_PDKCHAR,argc,NULL); if (NULL != app->my_argv) { #line 1976 "dk4appop.ctr" for (i = 0; i < argc; i++) { (app->my_argv)[i] = NULL; } if (dk4app_open_options_check(app)) { #line 1978 "dk4appop.ctr" argsused = 0; for (i = 1; i < argc; i++) { argptr = argv[i]; #line 1981 "dk4appop.ctr" if (dkT('-') == *argptr) { #line 1982 "dk4appop.ctr" if (dkT('-') == argptr[1]) { #line 1983 "dk4appop.ctr" if (0 == dk4app_open_check_long_opt(app, ae, &(argptr[2]))) { if (0 != dk4str_cpy_s(b,DK4_SIZEOF(b,dkChar),&(argptr[2]),NULL)) { #line 1987 "dk4appop.ctr" opv = NULL; pv = dk4str_chr(b, dkT('=')); if (NULL != pv) { *(pv++) = dkT('\0'); pv = dk4str_start(pv, NULL); } if (NULL != pv) { opv = dk4str_chr(&(argptr[2]), dkT('=')); if (NULL != opv) { opv = dk4str_start(++opv, NULL); } } ospec = dk4sto_it_find_like( app->i_opt_long, (void *)b, 3 ); #line 2000 "dk4appop.ctr" if (NULL != ospec) { #line 2001 "dk4appop.ctr" ospec->found = 1; switch ((ospec->spec).argtype) { case DK4_OPT_ARG_BOOL: case DK4_OPT_ARG_SIZE: case DK4_OPT_ARG_INT: case DK4_OPT_ARG_UNSIGNED: case DK4_OPT_ARG_DOUBLE: case DK4_OPT_ARG_STRING: { #line 2009 "dk4appop.ctr" if (NULL == opv) { #line 2010 "dk4appop.ctr" if ((1 + i) < argc) { #line 2011 "dk4appop.ctr" opv = argv[++i]; } } if (NULL != opv) { #line 2015 "dk4appop.ctr" switch ((ospec->spec).argtype) { case DK4_OPT_ARG_BOOL: { (ospec->val).b = 0; if (dk4str_is_bool(opv)) { #line 2019 "dk4appop.ctr" (ospec->val).b = dk4str_is_on(opv); } else { #line 2021 "dk4appop.ctr" /* ERROR: Not a boolean argument */ dk4app_log_base5( app, DK4_LL_ERROR, 33, 14, 15, b, opv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_SIZE: { (ospec->val).s = 0; szval = 0; endptr = NULL; res = dk4ma_input_dk_dec_size_t( &szval, opv, &endptr, 1, NULL ); if (0 != res) { #line 2039 "dk4appop.ctr" (ospec->val).s = szval; } else { #line 2041 "dk4appop.ctr" /* ERROR: Not a size specification */ dk4app_log_base7( app, DK4_LL_ERROR, 32, 17, 154, 18, b, endptr, opv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_INT: { ival = (dk4_im_t)0L; (ospec->val).i = (dk4_im_t)0L; endptr = NULL; res = dk4ma_input_dk_dec_dk4_im_t( &ival, opv, &endptr, 1, NULL ); if (0 != res) { #line 2059 "dk4appop.ctr" (ospec->val).i = ival; } else { #line 2061 "dk4appop.ctr" /* ERROR: Not an integer value */ dk4app_log_base7( app, DK4_LL_ERROR, 31, 20, 154, 21, b, endptr, opv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_UNSIGNED: { uval = (dk4_um_t)0UL; (ospec->val).u = (dk4_um_t)0UL; endptr = NULL; res = dk4ma_input_dk_dec_dk4_um_t( &uval, opv, &endptr, 1, NULL ); if (0 != res) { #line 2079 "dk4appop.ctr" (ospec->val).u = uval; } else { #line 2081 "dk4appop.ctr" /* ERROR: Not an unsigned integer value */ dk4app_log_base7( app, DK4_LL_ERROR, 30, 23, 154, 24, b, endptr, opv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_DOUBLE: { #line 2092 "dk4appop.ctr" dval = 0.0; (ospec->val).d = 0.0; endptr = NULL; res = dk4ma_input_dk_double( &dval, opv, &endptr, 1, NULL ); if (0 != res) { #line 2099 "dk4appop.ctr" (ospec->val).d = dval; } else { #line 2101 "dk4appop.ctr" dk4app_log_base7( app, DK4_LL_ERROR, 29, 26, 154, 27, b, endptr, opv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_STRING: { #line 2111 "dk4appop.ctr" (ospec->val).t = opv; } break; } } else { #line 2115 "dk4appop.ctr" /* ERROR: Option requires argument */ dk4app_log_base3( app, DK4_LL_ERROR, 28, 12, b ); if (0 == ae->error_found) { ae->error_found = E_OPT_REQUIRES_ARG; } } } break; } } else { #line 2126 "dk4appop.ctr" /* Handle preference */ if (NULL != pv) { #line 2128 "dk4appop.ctr" prefptr = dk4sto_it_find_like(app->i_pref_cmd, b, 1); if (NULL != prefptr) { #line 2130 "dk4appop.ctr" opv = dk4str_dup(pv, NULL); if (NULL != opv) { #line 2132 "dk4appop.ctr" #if 0 dk4mem_release(prefptr->value); #endif /* 2016-12-10 Sanitize memory. */ dk4str_release_sanitized(prefptr->value); prefptr->value = opv; } else { #line 2140 "dk4appop.ctr" /* ERROR: Failed to save preference value */ dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { #line 2149 "dk4appop.ctr" prefptr = dk4pref_open(b, pv, NULL); if (NULL != prefptr) { #line 2151 "dk4appop.ctr" if (0 != dk4sto_add(app->s_pref_cmd, prefptr, NULL)) { #line 2153 "dk4appop.ctr" } else { #line 2154 "dk4appop.ctr" /* ERROR: Failed to save preference value */ dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); dk4pref_close(prefptr); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { #line 2165 "dk4appop.ctr" /* ERROR: Failed to save preference value */ dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } dk4app_pref_apply(app, ae, b, pv); } else { #line 2177 "dk4appop.ctr" /* ERROR: Missing preference value */ dk4app_log_base3(app, DK4_LL_ERROR, 37, 38, b); if (0 == ae->error_found) { ae->error_found = E_OPT_REQUIRES_ARG; } } } } else { #line 2185 "dk4appop.ctr" /* ERROR: Option too long! */ dk4app_log_base3(app, DK4_LL_ERROR, 39, 40, argptr); if (0 == ae->error_found) { ae->error_found = E_OPTION_TOO_LONG; } } } } else { #line 2193 "dk4appop.ctr" ospec = dk4sto_it_find_like( app->i_opt_short, (void *)(&(argptr[1])), 1 ); if (NULL != ospec) { #line 2197 "dk4appop.ctr" ospec->found = 1; pv = NULL; switch ((ospec->spec).argtype) { case DK4_OPT_ARG_BOOL: case DK4_OPT_ARG_SIZE: case DK4_OPT_ARG_INT: case DK4_OPT_ARG_UNSIGNED: case DK4_OPT_ARG_DOUBLE: case DK4_OPT_ARG_STRING: { #line 2206 "dk4appop.ctr" pv = dk4str_start(&(argptr[2]), NULL); if (NULL == pv) { #line 2208 "dk4appop.ctr" if ((1 + i) < argc) { #line 2209 "dk4appop.ctr" pv = argv[++i]; } } if (NULL != pv) { switch ((ospec->spec).argtype) { case DK4_OPT_ARG_BOOL: { (ospec->val).b = 0; if (dk4str_is_bool(pv)) { #line 2217 "dk4appop.ctr" (ospec->val).b = dk4str_is_on(pv); } else { #line 2219 "dk4appop.ctr" /* ERROR: Not a boolean argument */ dk4app_log_base5( app, DK4_LL_ERROR, 13, 14, 15, argptr, pv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_SIZE: { (ospec->val).s = 0; szval = 0; endptr = NULL; res = dk4ma_input_dk_dec_size_t( &szval, pv, &endptr, 1, NULL ); if (0 != res) { #line 2237 "dk4appop.ctr" (ospec->val).s = szval; } else { #line 2239 "dk4appop.ctr" /* ERROR: Not a size specification */ dk4app_log_base7( app, DK4_LL_ERROR, 16, 17, 154, 18, argptr, endptr, pv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_INT: { ival = (dk4_im_t)0L; (ospec->val).i = (dk4_im_t)0L; endptr = NULL; res = dk4ma_input_dk_dec_dk4_im_t( &ival, pv, &endptr, 1, NULL ); if (0 != res) { #line 2257 "dk4appop.ctr" (ospec->val).i = ival; } else { #line 2259 "dk4appop.ctr" /* ERROR: Not an integer value */ dk4app_log_base7( app, DK4_LL_ERROR, 19, 20, 154, 21, argptr, endptr, pv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_UNSIGNED: { uval = (dk4_um_t)0UL; (ospec->val).u = (dk4_um_t)0UL; endptr = NULL; res = dk4ma_input_dk_dec_dk4_um_t( &uval, pv, &endptr, 1, NULL ); if (0 != res) { #line 2277 "dk4appop.ctr" (ospec->val).u = uval; } else { #line 2279 "dk4appop.ctr" /* ERROR: Not an unsigned integer value */ dk4app_log_base7( app, DK4_LL_ERROR, 22, 23, 154, 24, argptr, endptr, pv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_DOUBLE: { #line 2290 "dk4appop.ctr" dval = 0.0; (ospec->val).d = 0.0; endptr = NULL; res = dk4ma_input_dk_double( &dval, pv, &endptr, 1, NULL ); if (0 != res) { #line 2297 "dk4appop.ctr" (ospec->val).d = dval; } else { #line 2299 "dk4appop.ctr" dk4app_log_base7( app, DK4_LL_ERROR, 25, 26, 154, 27, argptr, endptr, pv ); if (0 == ae->error_found) { ae->error_found = E_INVALID_OPTION_ARG; } } } break; case DK4_OPT_ARG_STRING: { #line 2309 "dk4appop.ctr" (ospec->val).t = pv; } break; } } else { #line 2313 "dk4appop.ctr" /* ERROR: Option requires argument */ dk4app_log_base3( app, DK4_LL_ERROR, 11, 12, argptr ); if (0 == ae->error_found) { ae->error_found = E_OPT_REQUIRES_ARG; } } } break; } } else { #line 2324 "dk4appop.ctr" /* ERROR: Unexpected option */ dk4app_log_base3(app, DK4_LL_ERROR, 9, 10, argptr); if (0 == ae->error_found) { ae->error_found = E_UNEXPECTED_OPTION; } } } } else { #line 2332 "dk4appop.ctr" (app->my_argv)[argsused++] = argptr; } } app->my_argc = argsused; } else { #line 2337 "dk4appop.ctr" oi = 0; for (i = 0; (i + 1) < argc; i++) { must_add = 1; if (dkT('-') == (argv[i + 1])[0]) { if (dkT('-') == (argv[i + 1])[1]) { if (0 == dk4app_open_check_long_opt(app, ae, &((argv[i+1])[2]))) { /* Treat all long options as preferences. */ must_add = dk4str_cpy_s( b, DK4_SIZEOF(b,dkChar), &((argv[i + 1])[2]), NULL ); if (0 != must_add) { opv = NULL; pv = dk4str_chr(b, dkT('=')); if (NULL != pv) { *(pv++) = dkT('\0'); pv = dk4str_start(pv, NULL); } if (NULL != pv) { opv = dk4str_chr(&((argv[i + 1])[2]), dkT('=')); if (NULL != opv) { opv = dk4str_start(++opv, NULL); } #ifdef __clang_analyzer__ /* 2015-08-21 / 2016-01-20 Static code analysis by clang complains opv is set but not used later. Probably true. */ (void)opv; #endif } if (NULL != pv) { prefptr = dk4sto_it_find_like(app->i_pref_cmd, b, 1); if (NULL != prefptr) { opv = dk4str_dup(pv, NULL); if (NULL != opv) { #if 0 dk4mem_release(prefptr->value); #endif /* 2016-12-10 Sanitize memory. */ dk4str_release_sanitized(prefptr->value); prefptr->value = opv; } else { dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { prefptr = dk4pref_open(b, pv, NULL); if (NULL != prefptr) { if (0 == dk4sto_add(app->s_pref_cmd, prefptr, NULL)) { dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); dk4pref_close(prefptr); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { dk4app_log_base5( app, DK4_LL_ERROR, 34, 35, 36, b, pv ); if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } dk4app_pref_apply(app, ae, b, pv); } else { dk4app_log_base3(app, DK4_LL_ERROR, 37, 38, b); if (0 == ae->error_found) { ae->error_found = E_OPT_REQUIRES_ARG; } } } else { /* ERROR: Option too long! */ dk4app_log_base3(app, DK4_LL_ERROR, 39, 40, argv[i + 1]); if (0 == ae->error_found) { ae->error_found = E_OPTION_TOO_LONG; } } } must_add = 0; } } if (0 != must_add) { (app->my_argv)[oi++] = argv[i + 1]; } } app->my_argc = oi; #line 2430 "dk4appop.ctr" } } else { #line 2432 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } else { #line 2435 "dk4appop.ctr" if (0 == ae->error_found) { ae->error_found = E_ARGC; } } #line 2437 "dk4appop.ctr" } /** Keep private copies of version text, help file name, help text and license text. @param app @param ae @param version @param helpfile @param helptext @param lictext */ static void dk4app_open_save_names( dk4_app_t *app, dk4_app_error_t *ae, const dkChar *version, const dkChar *helpfile, const dkChar * const *helptext, const dkChar * const *lictext ) { int ok = 0; if (NULL != version) { if (NULL != helpfile) { if (NULL != helptext) { if (NULL != lictext) { ok = 1; app->help_text = helptext; app->lic_text = lictext; app->vers_text = dk4str_dup(version, NULL); app->help_file_name = dk4str_dup(helpfile, NULL); if ((NULL == app->vers_text) || (NULL == app->help_file_name)) { if (0 == ae->error_found) { ae->error_found = E_MEMORY; } } } } } } if (0 == ok) { if (0 == ae->error_found) { ae->error_found = E_BUG_ARGUMENTS; } } } /** Open an application structure for a command line program. @param argc Number of command line arguments. @param argv Command line arguments array. @param optspec Option specification, may be NULL. @param szoptspec Number of elements in optspec. @param groupname Program group name. @param version Version number string. @param helpfile Help file name. @param helptext Default help text. @param lictext License conditions text. @param enablog Flag: Enable logging. @return Pointer to dk4_app_t structure on success, NULL on error. */ static dk4_app_t * dk4app_open_internally( int argc, dkChar **argv, const dk4_option_specification_t *optspec, size_t szoptspec, const dkChar *groupname, const dkChar *version, const dkChar *helpfile, const dkChar * const *helptext, const dkChar * const *lictext, int enablog ) { dk4_app_error_t ae; /* Error during startup */ dk4_app_t *back = NULL; /* Function result */ int quiet = 0; /* Flag: Run quiet */ #line 2518 "dk4appop.ctr" DK4_MEMRES(&ae, sizeof(dk4_app_error_t)); ae.error_found = 0; if (NULL != groupname) { if ((0 < argc) && (NULL != argv)) { quiet = dk4app_open_silence_check(argc, argv); back = dk4mem_new(dk4_app_t,1,NULL); if (NULL != back) { /* Set all members to reasonable default */ dk4app_open_initialize(back); back->group_name = dk4str_dup(groupname, NULL); if (NULL == back->group_name) { ae.error_found = E_MEMORY; } if (0 == ae.error_found) { dk4app_open_save_names( back, &ae, version, helpfile, helptext, lictext ); } /* Find host name */ if (0 == ae.error_found) { dk4app_open_find_host_name(back, &ae); } /* Find user name and home directory */ if (0 == ae.error_found) { dk4app_open_find_user_name_and_home(back, &ae); } /* Find language and region */ if (0 == ae.error_found) { dk4app_open_find_language_region(back, &ae); } /* Find executable path name and derive directory names from it */ if (0 == ae.error_found) { dk4app_open_find_executable(back, &ae, argv[0]); } /* Create option storage from option specification */ if (0 == ae.error_found) { dk4app_open_create_options_storages( back, &ae, optspec, szoptspec ); } /* Create preferences storage */ if (0 == ae.error_found) { dk4app_open_create_pref_storages(back, &ae); } /* Create string table storage */ if (0 == ae.error_found) { dk4app_open_create_stt_storage(back, &ae); } /* Read preference files */ if (0 == ae.error_found) { dk4app_open_read_preference_files(back, &ae); } /* Construct log file name, create log directory */ if ((0 != enablog) && (0 == quiet) && (0 == ae.error_found)) { dk4app_open_prepare_file_logging(back, &ae); } /* Enable logging if not switched to silent mode */ if ((0 != enablog) && (0 == quiet) && (0 == ae.error_found)) { back->log_enabled = 1; } /* We must be able to log, if there are errors */ if (0 == ae.error_found) { /* Process command line arguments, search for options */ dk4app_open_process_argc_argv(back, &ae, argc, argv); } /* If there were serious errors, destroy the structure */ if (ae.error_found) { dk4app_open_report_error(back, &ae); dk4app_close(back); back = NULL; } } else { #line 2605 "dk4appop.ctr" if (0 == quiet) { char buf[64]; int res; res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), (dk4_um_t)sizeof(dk4_app_t), 0, NULL ); if (0 != res) { fputs(dk4app_open_c8_kw[1], stderr); fputs(buf, stderr); fputs(dk4app_open_c8_kw[2], stderr); } else { fputs(dk4app_open_c8_kw[0], stderr); } fputc('\n', stderr); fflush(stderr); } } } else { #line 2623 "dk4appop.ctr" } } else { #line 2625 "dk4appop.ctr" } if (NULL != back) { #line 2627 "dk4appop.ctr" if (0 != dk4app_log_do(back, DK4_LL_DEBUG)) { #line 2628 "dk4appop.ctr" (void)dk4app_log_debug_texts(back, NULL); dk4app_log_startup_debug(back); } } #line 2632 "dk4appop.ctr" return back; } dk4_app_t * dk4app_open_cmd( int argc, dkChar **argv, const dk4_option_specification_t *optspec, size_t szoptspec, const dkChar *groupname, const dkChar *version, const dkChar *helpfile, const dkChar * const *helptext, const dkChar * const *lictext ) { dk4_app_t *back; back = dk4app_open_internally( argc, argv, optspec, szoptspec, groupname, version, helpfile, helptext, lictext, 1 ); return back; } dk4_app_t * dk4app_open_silent( int argc, dkChar **argv, const dk4_option_specification_t *optspec, size_t szoptspec, const dkChar *groupname, const dkChar *version, const dkChar *helpfile, const dkChar * const *helptext, const dkChar * const *lictext ) { dk4_app_t *back; back = dk4app_open_internally( argc, argv, optspec, szoptspec, groupname, version, helpfile, helptext, lictext, 0 ); return back; } void dk4app_set_fast_close(dk4_app_t *app) { if (NULL != app) { app->fast_close = 1; } }