diff options
Diffstat (limited to 'support/dktools/dk-recv.c')
-rw-r--r-- | support/dktools/dk-recv.c | 1226 |
1 files changed, 1226 insertions, 0 deletions
diff --git a/support/dktools/dk-recv.c b/support/dktools/dk-recv.c new file mode 100644 index 0000000000..6ff288b381 --- /dev/null +++ b/support/dktools/dk-recv.c @@ -0,0 +1,1226 @@ +/* + 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: dk-recv.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. +*/ + +/** @file dk-recv.c The dk-recv module. +*/ + + +#line 10 "dk-recv.ctr" + +#include "dk4conf.h" + +#if DK4_HAVE_MATH_H +#ifndef MATH_H_INCLUDED +#include <math.h> +#define MATH_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_ERRNO_H +#ifndef ERRNO_H_INCLUDED +#include <errno.h> +#define ERRNO_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_IO_H +#ifndef IO_H_INCLUDED +#include <io.h> +#define IO_H_INCLUDED 1 +#endif +#endif + +#if DK4_HAVE_FCNTL_H +#ifndef FCNTL_H_INCLUDED +#include <fcntl.h> +#define FCNTL_H_INCLUDED 1 +#endif +#endif + +#include "dk4sock.h" +#include "dk4socka.h" +#include "dk4fput.h" +#include "dk4vers.h" +#include "dk4aopt.h" +#include "dk4numco.h" +#include "dk4fopda.h" +#include "dk4isadm.h" +#include "dk4fdwre.h" +#include "dk4mpl.h" +#include "dk4mem.h" +#include "dk4mema.h" +#include "dk4strd.h" +#include "dk4pathd.h" + + + + + +#line 59 "dk-recv.ctr" + + + +/** Default help text, shown if no localized help text is found. +*/ +static const dkChar * const dk_recv_help_text[] = { +dkT(""), +dkT("Receive data from a dk-send process."), +dkT(""), +dkT("dk-recv [<options>] <host> <port> [<file>]"), +dkT(""), +dkT("Arguments:"), +dkT("host\t\tSender host to connect to (name or IP)."), +dkT("port\t\tPort number to connect to."), +dkT("file\t\tOutput file to create. Default: Write to standard output."), +dkT(""), +dkT("Options:"), +dkT("-t\t\tTell peer to start transmission."), +dkT("-l <port>\tLocal port number to bind."), +dkT("-c <int>\tTimeout for connect attempt."), +dkT(""), +dkT("--help\t\tShow this short help text."), +dkT("--manual\t*** SHOW FULL MANUAL. ***"), +dkT("--version\tShow version information."), +dkT("--license\tShow license information."), +dkT(""), +NULL + + +#line 87 "dk-recv.ctr" +}; + + + +/** License text. +*/ +static const dkChar * const dk_recv_license_text[] = { +dkT("This software uses code from the following projects, either directly or as"), +dkT("a library:"), +dkT(""), +dkT("dktools\t\tDirk Krause's tools and libraries."), +dkT("\t\tSee http://dktools.sourceforge.net/ for more information."), +#if DK4_HAVE_ZLIB_H +dkT(""), +dkT("zlib\t\tData compression library."), +dkT("\t\tSee http://www.zlib.net/ for more information."), +#endif +#if DK4_HAVE_BZLIB_H +dkT(""), +dkT("bzip2\t\tData compression program and library."), +dkT("\t\tSee http://www.bzip.org/ for more information."), +#endif +dkT(""), +dkT("All the licenses below apply to the program."), +dkT("Licenses for used libraries are shown as found on my Scientific Linux 6.x"), +dkT("computer in the /usr/share/doc directory on 2015-04-01. Check the project"), +dkT("homepages of the used libraries for additional information and/or updated"), +dkT("license terms."), +dkT(""), +dkT(""), +dkT("DK tools and libraries license"), +dkT("=============================="), +dkT("Copyright (c) 2015-2016, Dirk Krause"), +dkT("All rights reserved."), +dkT(""), +dkT("Redistribution and use in source and binary forms, with or without"), +dkT("modification, are permitted provided that the following conditions are met:"), +dkT(""), +dkT("* Redistributions of source code must retain the above copyright notice,"), +dkT(" this list of conditions and the following disclaimer."), +dkT("* Redistributions in binary form must reproduce the above copyright"), +dkT(" notice, this list of conditions and the following disclaimer in the"), +dkT(" documentation and/or other materials provided with the distribution."), +dkT("* Neither the name of the Dirk Krause nor the names of contributors may be"), +dkT(" used to endorse or promote products derived from this software without"), +dkT(" specific prior written permission."), +dkT(""), +dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""), +dkT("AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), +dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), +dkT("ARE DISCLAIMED."), +dkT(""), +dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,"), +dkT("INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,"), +dkT("BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"), +dkT("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY"), +dkT("OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), +dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,"), +dkT("EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), +#if DK4_HAVE_ZLIB_H +dkT(""), +dkT(""), +dkT("Zlib license"), +dkT("============"), +dkT("(C) 1995-2004 Jean-loup Gailly and Mark Adler"), +dkT(""), +dkT("This software is provided 'as-is', without any express or implied"), +dkT("warranty. In no event will the authors be held liable for any damages"), +dkT("arising from the use of this software."), +dkT(""), +dkT("Permission is granted to anyone to use this software for any purpose,"), +dkT("including commercial applications, and to alter it and redistribute it"), +dkT("freely, subject to the following restrictions:"), +dkT(""), +dkT("1. The origin of this software must not be misrepresented; you must not"), +dkT(" claim that you wrote the original software. If you use this software"), +dkT(" in a product, an acknowledgment in the product documentation would be"), +dkT(" appreciated but is not required."), +dkT("2. Altered source versions must be plainly marked as such, and must not be"), +dkT(" misrepresented as being the original software."), +dkT("3. This notice may not be removed or altered from any source distribution."), +dkT(""), +dkT("Jean-loup Gailly Mark Adler"), +dkT("jloup@gzip.org madler@alumni.caltech.edu"), +#endif +#if DK4_HAVE_BZLIB_H +dkT(""), +dkT(""), +dkT("Bzip2 and libbzip2 library license"), +dkT("=================================="), +dkT("This program, \"bzip2\", the associated library \"libbzip2\", and all"), +dkT("documentation, are copyright (C) 1996-2007 Julian R Seward. All"), +dkT("rights reserved."), +dkT(""), +dkT("Redistribution and use in source and binary forms, with or without"), +dkT("modification, are permitted provided that the following conditions"), +dkT("are met:"), +dkT(""), +dkT("1. Redistributions of source code must retain the above copyright"), +dkT(" notice, this list of conditions and the following disclaimer."), +dkT(""), +dkT("2. The origin of this software must not be misrepresented; you must "), +dkT(" not claim that you wrote the original software. If you use this "), +dkT(" software in a product, an acknowledgment in the product "), +dkT(" documentation would be appreciated but is not required."), +dkT(""), +dkT("3. Altered source versions must be plainly marked as such, and must"), +dkT(" not be misrepresented as being the original software."), +dkT(""), +dkT("4. The name of the author may not be used to endorse or promote "), +dkT(" products derived from this software without specific prior written "), +dkT(" permission."), +dkT(""), +dkT("THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS"), +dkT("OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED"), +dkT("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), +dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY"), +dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"), +dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE"), +dkT("GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"), +dkT("INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,"), +dkT("WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), +dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS"), +dkT("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), +dkT(""), +dkT("Julian Seward, jseward@bzip.org"), +dkT("bzip2/libbzip2 version 1.0.5 of 10 December 2007"), +#endif +dkT(""), +NULL + + +#line 218 "dk-recv.ctr" +}; + + + +/** Constant texts used by the program, not localized. +*/ +static const dkChar * const dk_recv_kwnl[] = { +/* 0 */ +dkT("dktools"), + +/* 1 */ +dkT("dk-recv.txt"), + +/* 2 */ +dkT("dk-recv.str"), + +/* 3 */ +dkT("\\"), + +/* 4 */ +dkT("wb"), + +NULL + + +#line 247 "dk-recv.ctr" +}; + + + +/** Constant texts used by the program, replaced by localized + versions if found. +*/ +static const dkChar * const dk_recv_kw_def[] = { +/* 0 */ +dkT("Failed to set up signal handlers!"), + +/* 1 */ +dkT("Failed to restore signal handlers!"), + +/* 2 */ +dkT("stdin"), + +/* 3 */ +dkT("Failed to close file!"), + +/* 4 */ +dkT("Timeout too large!"), + +/* 5 */ +dkT("Timeout must not be negative!"), + +/* 6 */ +dkT("Timeout value not found!"), + +/* 7 */ +dkT("Wrong number of arguments!\n\thost port [filename]"), + +/* 8 */ +dkT("Interrupted by SIGINT signal!"), + +/* 9 */ +dkT("Interrupted by SIGTERM signal!"), + +/* 10 */ +dkT("Interrupted by SIGPIPE signal!"), + +NULL + + +#line 292 "dk-recv.ctr" +}; + + + +/** Options used by the program. +*/ +static const dk4_option_specification_t dk_recv_options[] = { + + /* I am the last client, server can start transmissin now. + */ + { dkT('t'), dkT("transmission"), DK4_OPT_ARG_NONE }, + + /* Bind a certain local port number. + */ + { dkT('l'), dkT("local-port"), DK4_OPT_ARG_STRING }, + + /* Use a timeout when connecting to the server. + */ + { dkT('c'), dkT("connect-timeout"), DK4_OPT_ARG_DOUBLE } +}; + + + +/** Array of localized texts, loaded in the main() function. + Usable as long as the app pointer below is usable. +*/ +static const dkChar * const *dk_recv_kw_loc = NULL; + + + +/** Local port number to use. +*/ +static const dkChar *dk_recv_portno = NULL; + + + +/** Application structure for diagnostics. +*/ +static dk4_app_t *app = NULL; + + + +/** Number of elements in the dk_recv_options array. +*/ +static const size_t dk_recv_sz_options = +sizeof(dk_recv_options)/sizeof(dk4_option_specification_t); + + + +/** Number of elements in the dk_recv_kw_def array. +*/ +static const size_t dk_recv_sz_def = +sizeof(dk_recv_kw_def)/sizeof(DK4_PCDKCHAR) - 1; + + + +/** Number of elements in the dk_recv_kw_def array. +*/ +static size_t dk_recv_sz_loc = +sizeof(dk_recv_kw_def)/sizeof(DK4_PCDKCHAR) - 1; + + + +/** Seconds for timeout. +*/ +static long dk_recv_timeout_secs = 0L; + + + +/** Microseconds for timeout. +*/ +static long dk_recv_timeout_usecs = 0L; + + + +/** Exit status code. +*/ +static int exval = EXIT_FAILURE; + + + +/** Flag send to server: Start transmission immediately. +*/ +static unsigned char start_transmission = 0x00; + + + +#ifdef SIGPIPE +/** Indicator: SIGPIPE signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_pipe = 0; +#endif + +/** Indicator: SIGINT signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_int = 0; + +/** Indicator: SIGTERM signal received. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t sig_had_term = 0; + + + +/** Pass a volatile pointer to an atomic integer. + This function is necessary as some compilers mis-optimize + direct access to volatile variables (at least if you believe + one of the coding standards). + @param ptr Address of atomic integer variable. + @return The unmodified pointer. +*/ +static +DK4_VOLATILE +dk4_sig_atomic_t * +sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr) +{ + return ptr; +} + + + +#ifdef SIGPIPE +/** Handler for SIGPIPE signal. + @param signo Signal number (always SIGPIPE, ignored). +*/ +static +void +sig_handler_pipe(int signo) +{ + *sig_pass_pointer(&sig_had_pipe) = 1; +} +#endif + +/** Handler for SIGINT signal. + @param signo Signal number (always SIGINT, ignored). +*/ +static +void +sig_handler_int(int signo) +{ + *sig_pass_pointer(&sig_had_int) = 1; +} + +/** Handler for SIGTERM signal. + @param signo Signal number (always SIGTERM, ignored). +*/ +static +void +sig_handler_term(int signo) +{ + *sig_pass_pointer(&sig_had_term) = 1; +} + +/** Read value from volatile atomic type. + This function is necessary as some compilers mis-optimize + direct access to volatile variables (at least if you believe + one of the coding standards). + @param ap Pointer to volatile atomic variable. + @return Contents of the variable. +*/ +static +dk4_sig_atomic_t +sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap) +{ + return (*ap); +} + +/** Check whether we can continue or if a signal was received. + @param check_pipe Flag: Check for occured SIGPIPE signal too. + @return 1 if the program can continue, 0 if a signal was received. +*/ +static +int +sig_can_continue(int check_pipe) +{ + int back = 1; +#ifdef SIGPIPE + if (0 != check_pipe) { + if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; } + } +#endif + if (0 != sig_read_atomic(&sig_had_int )) { back = 0; } + if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } + return back; +} + + + +#if 0 + +/* + 2016-01-02: + Removed - replaced by sig_can_continue(1) - after profiling. +*/ + +/** Check whether we can continue. + @return 1 for yes, 0 for no. +*/ +static +int +dk_recv_can_continue(void) +{ + int back = 1; + if (0 == sig_can_continue(1)) { + back = 0; + } + return back; +} + +#endif +/* if 0 */ + + + +/** Data buffer +*/ +#if DK4_SIZEOF_SIZE_T > 2 +static char bu[1048576]; +#else +static char bu[16384]; +#endif + +/** Run for hostname, port specification and real file name + (wildcards * and ? resolved on Windows). + @param hostname Host to connect to (name or address). + @param portspec Port to connect to (number or service name). + @param filename File name to write, may be NULL (stdout). +*/ +static +void +dk_recv_run_with_real_file_name( + const dkChar *hostname, + const dkChar *portspec, + const dkChar *filename +) +{ +#if 0 + /* 2016-01-06: + Buffer size increased, do not use stack. + */ + char bu[1460]; /* Data buffer */ +#endif + FILE *fipo = NULL; /* Output file */ + size_t sz = 0; /* Buffer sizes */ + size_t wrb = 0; /* Bytes written */ + dk4_socket_t sock = INVALID_SOCKET; /* Client socket */ +#if DK4_ON_WINDOWS + int oldmode= _O_TEXT; /* File mode stdout */ +#endif + int cc = 1; /* Flag: Can continue */ + int first = 1; /* Flag: First pass */ + int res = 0; /* Operation result */ + int we = 0; /* Flag: Write error */ + int tests = 0; + + + +#line 553 "dk-recv.ctr" + /* Check for signals. + */ + if (0 == sig_can_continue(1)) { + goto finished; + } + +#line 558 "dk-recv.ctr" + + /* Bring socket subsystem up (Windows). + */ + if (DK4_SOCKET_RESULT_SUCCESS != dk4socket_up_app(app)) { + /* ERROR: Failed to bring socket subsystem up, already reported */ + goto finished; + } + +#line 565 "dk-recv.ctr" + + /* Open TCP client socket. + */ + sock = dk4socket_tcp_client_for_host_service_app( + hostname, portspec, dk_recv_portno, + dk_recv_timeout_secs, dk_recv_timeout_usecs, app + ); + if (INVALID_SOCKET == sock) { + /* ERROR: Failed to create socket, already reported */ + goto tcpip_down; + } + +#line 576 "dk-recv.ctr" + if (0 == sig_can_continue(1)) { + goto close_socket; + } + +#line 579 "dk-recv.ctr" + + /* Send start-of-transmission byte and shutdown socket for writing. + */ + sz = 1; + res = dk4socket_send_app(sock, &start_transmission, &sz, 0, 0L, 0L, app); + if (DK4_SOCKET_RESULT_SUCCESS != res) { + goto close_socket; + } + +#line 587 "dk-recv.ctr" + if (0 == sig_can_continue(1)) { + goto close_socket; + } + +#line 590 "dk-recv.ctr" + res = dk4socket_shutdown_app(sock, DK4_SOCKET_SHUT_WRITE, app); + if (DK4_SOCKET_RESULT_SUCCESS != res) { + goto close_socket; + } + +#line 594 "dk-recv.ctr" + if (0 == sig_can_continue(1)) { + goto close_socket; + } + +#line 597 "dk-recv.ctr" + + /* Indicate success so far. + */ + exval = EXIT_SUCCESS; + + /* Now receive data. + */ + do { + if (0 != sig_can_continue(1)) { + +#line 606 "dk-recv.ctr" + sz = sizeof(bu); + res = dk4socket_recv_app(sock, bu, &sz, 0, 0L, 0L, app); + if (DK4_SOCKET_RESULT_SUCCESS == res) { + if (0 < sz) { + +#line 610 "dk-recv.ctr" + if (0 != sig_can_continue(1)) { + if (0 != first) { + +#line 612 "dk-recv.ctr" + first = 0; + if (NULL != filename) { + +#line 614 "dk-recv.ctr" + tests = DK4_FOPEN_SC_USER; + if (0 != dk4isadmin()) { tests = DK4_FOPEN_SC_PRIVILEGED; } + fipo = dk4fopen_app(filename, dk_recv_kwnl[4], tests, app); + if (NULL == fipo) { + +#line 618 "dk-recv.ctr" + exval = EXIT_FAILURE; + } + } else { + +#line 621 "dk-recv.ctr" + /* MODE FOR WINDOWS */ +#if DK4_ON_WINDOWS + oldmode = _setmode(_fileno(stdout), _O_BINARY); +#endif + fipo = stdout; + } + } + if (NULL != fipo) { + +#line 629 "dk-recv.ctr" + if (0 == we) { + +#line 630 "dk-recv.ctr" + errno = 0; + +#line 631 "dk-recv.ctr" + wrb = fwrite(bu, 1, sz, fipo); + if (wrb != sz) { + +#line 633 "dk-recv.ctr" + we = 1; + exval = EXIT_FAILURE; + /* ERROR: Write attempt failed */ + dk4fd_write_error_msg( + app, + ((filename) ? (filename) : (dk_recv_kw_def[2])), + errno + ); + } + } + } + } else { + +#line 645 "dk-recv.ctr" + cc = -1; + } + } else { + +#line 648 "dk-recv.ctr" + cc = 0; + } + } else { + +#line 651 "dk-recv.ctr" + cc = -1; + } + } else { + +#line 654 "dk-recv.ctr" + cc = -1; + } + } while (1 == cc); + + /* Cleanup + */ + if (0 == first) { + +#line 661 "dk-recv.ctr" + if (NULL != filename) { + +#line 662 "dk-recv.ctr" + if (NULL != fipo) { + +#line 663 "dk-recv.ctr" + if (0 != fclose(fipo)) { + +#line 664 "dk-recv.ctr" + /* ERROR: Failed to close file */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 3); + exval = EXIT_FAILURE; + } + } + } else { + +#line 670 "dk-recv.ctr" + if (0 != fflush(stdout)) { + +#line 671 "dk-recv.ctr" + exval = EXIT_FAILURE; + } +#if DK4_ON_WINDOWS + _setmode(_fileno(stdout), oldmode); +#endif + } + } + + /* Close socket if open. + */ + close_socket: + if (INVALID_SOCKET != sock) { + +#line 683 "dk-recv.ctr" + dk4socket_close_app(sock, app); + } + + /* Shut socket subsystem down (Windows). + */ + tcpip_down: + dk4socket_down_app(app); + +#line 690 "dk-recv.ctr" + + finished: ; + + +#line 693 "dk-recv.ctr" +} + + + +#if DK4_ON_WINDOWS +/** Expand file name and run for host, port and file name. + @param hostname Host name or address to connect to. + @param portspec Remote port to connect to. + @param filename File name pattern to expand. +*/ +static +void +dk_recv_expand_file_name( + const dkChar *hostname, + const dkChar *portspec, + const dkChar *filename +) +{ + dkChar buf[DK4_MAX_PATH]; + dk4_dir_t *fne; + const dkChar *pt; + const dkChar *fn; + size_t szbuf; + int copied; + + fne = dk4app_fne_open(filename, app); + if (NULL != fne) { + fn = dk4dir_next_file(fne); + if (NULL != fn) { + pt = dk4dir_get_path(fne); + if (NULL == dk4dir_next_file(fne)) { + if (NULL != pt) { + szbuf = DK4_SIZEOF(buf, dkChar); + copied = 0; + if (0 != dk4str_cpy_s(buf, szbuf, pt, NULL)) { + if (0 != dk4str_cat_s(buf, szbuf, dk_recv_kwnl[3], NULL)) { + if (0 != dk4str_cat_s(buf, szbuf, fn, NULL)) { + copied = 1; + dk_recv_run_with_real_file_name(hostname, portspec, buf); + } + } + } + if (0 == copied) { + /* ERROR: Path too long */ + dk4app_log_base3(app, DK4_LL_ERROR, 100, 105, filename); + } + } else { + dk_recv_run_with_real_file_name(hostname, portspec, fn); + } + } else { + /* ERROR: Not a unique file name */ + dk4app_log_base3(app, DK4_LL_ERROR, 100, 106, filename); + } + } else { + /* ERROR: No such file */ + dk4app_log_base3(app, DK4_LL_ERROR, 100, 107, filename); + } + dk4dir_close(fne); + } +} +#endif + + + +/** Run for given host, port and file name. + @param hostname Host name or address to connect to. + @param portspec Remote port to connect to. + @param filename File name to write to, may be NULL (stdout). +*/ +static +void +dk_recv_run_for_arguments( + const dkChar *hostname, + const dkChar *portspec, + const dkChar *filename +) +{ +#if DK4_ON_WINDOWS + if (0 != dk4path_must_expand(filename)) { + dk_recv_expand_file_name(hostname, portspec, filename); + } else { +#endif + dk_recv_run_with_real_file_name(hostname, portspec, filename); +#if DK4_ON_WINDOWS + } +#endif +} + + + +/** Process options, retrieve command line arguments and run + for given host, port and optionally file name. +*/ +static +void +dk_recv_normal_run(void) +{ + double timeout; + double d1; + double d2; + int xargc; + int canrun; + + +#line 796 "dk-recv.ctr" + canrun = 1; + /* Timeout specified? + */ + if (0 != dk4app_opt_is_set_short(app, dkT('t'), NULL)) { + start_transmission = 0x01; + } + /* Local port number specified? + */ + if (0 != dk4app_opt_is_set_short(app, dkT('l'), NULL)) { + dk_recv_portno = dk4app_opt_get_string_ptr_short(app, dkT('l'), NULL); + } + /* Connection timeout specified? + */ + if (0 != dk4app_opt_is_set_short(app, dkT('c'), NULL)) { + if (0 != dk4app_opt_get_double_short(&timeout, app, dkT('c'), NULL)) { + if (0.0 <= timeout) { + d1 = floor(timeout); + d2 = timeout - d1; + d2 = 1000000.0 * d2; + if ((double)(LONG_MAX) >= d1) { + dk_recv_timeout_secs = (long)d1; + dk_recv_timeout_usecs = (long)d2; + } else { + canrun = 0; + /* ERROR: Timeout too large */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 4); + } + } else { + /* Warning: Can not use a negative timeout */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_WARNING, 5); + } + } else { + canrun = 0; + /* No timeout value found ! */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 6); + } + } + if (0 != canrun) { + xargc = dk4app_get_argc(app); + switch (xargc) { + case 2: { + dk_recv_run_for_arguments( + dk4app_get_argv(app, 0), + dk4app_get_argv(app, 1), + NULL + ); + } break; + case 3: { + dk_recv_run_for_arguments( + dk4app_get_argv(app, 0), + dk4app_get_argv(app, 1), + dk4app_get_argv(app, 2) + ); + } break; + default : { + /* ERROR: Wrong number of arguments */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 7); + } break; + } + } + + +#line 857 "dk-recv.ctr" +} + + + +#if DK4_HAVE_SIGACTION +/** Set signal handlers and run. +*/ +static +void +dk_recv_run_with_signal_handlers(void) +{ +#ifdef SIGPIPE + struct sigaction opipe; +#endif + struct sigaction oint; +#ifdef SIGPIPE + struct sigaction npipe; +#endif + struct sigaction nint; + struct sigaction oterm; + struct sigaction nterm; + int success = 0; + +#ifdef SIGPIPE + /* Set up signal handling for SIGPIPE. + */ + DK4_MEMRES(&npipe, sizeof(npipe)); + npipe.sa_handler = sig_handler_pipe; + npipe.sa_flags = 0; + if (0 != sigemptyset(&npipe.sa_mask)) { + /* ERROR: Failed to set up masked signal set for SIGPIPE */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto finished; + } + if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { + /* ERROR: Failed to set up masked signal set for SIGPIPE */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto finished; + } + if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { + /* ERROR: Failed to set up signal handler for SIGPIPE */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto finished; + } +#endif + + /* Set up signal handling for SIGINT. + */ + DK4_MEMRES(&nint, sizeof(nint)); + nint.sa_handler = sig_handler_int; + nint.sa_flags = 0; + if (0 != sigemptyset(&nint.sa_mask)) { + /* ERROR: Failed to set up masked signal set for SIGINT */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_pipe; + } + if (0 != sigaddset(&nint.sa_mask, SIGINT)) { + /* ERROR: Failed to set up masked signal set for SIGINT */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_pipe; + } + if (0 != sigaction(SIGINT, &nint, &oint)) { + /* ERROR: Failed to set up signal handler for SIGINT */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_pipe; + } + + /* Set up signal handling for SIGTERM + */ + DK4_MEMRES(&nterm, sizeof(nterm)); + nterm.sa_handler = sig_handler_term; + nterm.sa_flags = 0; + if (0 != sigemptyset(&nterm.sa_mask)) { + /* ERROR: Failed to set up masked signal set for SIGTERM */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_int; + } + if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { + /* ERROR: Failed to set up masked signal set for SIGTERM */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_int; + } + if (0 != sigaction(SIGTERM, &nterm, &oterm)) { + /* ERROR: Failed to set up signal handler for SIGTERM */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0); + goto restore_old_int; + } + + success = 1; + dk_recv_normal_run(); + + /* Restore signal handling for SIGTERM. + */ + if (0 != sigaction(SIGTERM, &oterm, NULL)) { + /* ERROR: Failed to restore old SIGTERM settings */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1); + success = 0; + } + + /* Restore signal handling for SIGINT. + */ + restore_old_int: + if (0 != sigaction(SIGINT, &oint, NULL)) { + /* ERROR: Failed to restore old SIGPIPE settings */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1); + success = 0; + } + +#ifdef SIGPIPE + /* Restore signal handling for SIGPIPE. + */ + restore_old_pipe: + if (0 != sigaction(SIGPIPE, &opipe, NULL)) { + /* ERROR: Failed to restore old SIGPIPE settings */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1); + success = 0; + } +#endif + + /* Set exit status code if error occured. + */ + finished: + if (0 == success) { exval = EXIT_FAILURE; } +} +#else +#if DK4_HAVE_SIGSET +/** Set signal handlers and run. +*/ +static +void +dk_recv_run_with_signal_handlers(void) +{ +#ifdef SIGPIPE + dk4_sig_handler_t *oldpipe = NULL; +#endif + dk4_sig_handler_t *oldint = NULL; + dk4_sig_handler_t *oldterm = NULL; + +#ifdef SIGPIPE + oldpipe = sigset(SIGPIPE, sig_handler_pipe); +#endif + oldint = sigset(SIGINT, sig_handler_int); + oldterm = sigset(SIGTERM, sig_handler_term); + dk_recv_normal_run(); + sigset(SIGTERM, oldterm); + sigset(SIGINT, oldint); +#ifdef SIGPIPE + sigset(SIGPIPE, oldpipe); +#endif +} +#else +#if DK4_HAVE_SIGNAL +/** Set signal handlers and run. +*/ +static +void +dk_recv_run_with_signal_handlers(void) +{ +#ifdef SIGPIPE + dk4_sig_handler_t *oldpipe = NULL; +#endif + dk4_sig_handler_t *oldint = NULL; + dk4_sig_handler_t *oldterm = NULL; + +#ifdef SIGPIPE + oldpipe = signal(SIGPIPE, sig_handler_pipe); +#endif + oldint = signal(SIGINT, sig_handler_int); + oldterm = signal(SIGTERM, sig_handler_term); + dk_recv_normal_run(); + signal(SIGTERM, oldterm); + signal(SIGINT, oldint); +#ifdef SIGPIPE + signal(SIGPIPE, oldpipe); +#endif +} +#else +/** Set signal handlers and run. +*/ +static +void +dk_recv_run_with_signal_handlers(void) +{ + dk_recv_normal_run(); +} +#endif +#endif +#endif + + + +/** Main function. + @param argc Number of command line arguments. + @param argv Command line arguments array. + @return 0 on success, all other values indicate errors. +*/ +#if DK4_CHAR_SIZE > 1 +int wmain(int argc, wchar_t *argv[]) +#else +int main(int argc, char *argv[]) +#endif +{ + + +#line 1060 "dk-recv.ctr" + + +#line 1061 "dk-recv.ctr" + dk4fput_initialize_stderr(); + app = dk4app_open_cmd( + argc, argv, dk_recv_options, dk_recv_sz_options, + dk_recv_kwnl[0], DKT_VERSION_DK, + dk_recv_kwnl[1], dk_recv_help_text, dk_recv_license_text + ); + if (NULL != app) { + +#line 1068 "dk-recv.ctr" + dk_recv_sz_loc = dk4app_string_table_size(dk_recv_kw_def); + dk_recv_kw_loc = dk4app_string_table(app, dk_recv_kwnl[2], dk_recv_kw_def); + dk_recv_sz_loc = dk4app_string_table_size(dk_recv_kw_loc); + if (0 != dk4app_can_run_normally(app)) { + dk_recv_run_with_signal_handlers(); + } else { + if (0 != dk4app_help_version_license(app)) { + exval = EXIT_SUCCESS; + } + } + if (0 != sig_read_atomic(&sig_had_int )) { + /* Interrupted by SIGINT */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 8); + } + if (0 != sig_read_atomic(&sig_had_term)) { + /* Interrupted by SIGTERM */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 9); + } +#if defined(SIGPIPE) + if (0 != sig_read_atomic(&sig_had_pipe)) { + /* Interrupted by SIGPIPE */ + dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 10); + } +#endif + dk4app_close(app); app = NULL; + } else { + +#line 1094 "dk-recv.ctr" + } + fflush(stderr); + dk4fput_cleanup_stderr(); + if (0 != sig_read_atomic(&sig_had_int )) { + exval = EXIT_FAILURE; + } + if (0 != sig_read_atomic(&sig_had_term)) { + exval = EXIT_FAILURE; + } +#if defined(SIGPIPE) + if (0 != sig_read_atomic(&sig_had_pipe)) { + exval = EXIT_FAILURE; + } +#endif + + +#line 1109 "dk-recv.ctr" + + +#line 1110 "dk-recv.ctr" + exit(exval); return exval; +} + |