diff options
author | Norbert Preining <norbert@preining.info> | 2020-10-12 03:04:00 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-10-12 03:04:00 +0000 |
commit | 0ce40abb18ec02ec6fd6bcc5f21612c88daa7578 (patch) | |
tree | 416289fe1448873fd8ca33051f50ad85bffa8aaa /support/dktools/rshdown.ctr | |
parent | fdb18507cd80dc17f5a5256153d34668b4f4e61c (diff) |
CTAN sync 202010120303
Diffstat (limited to 'support/dktools/rshdown.ctr')
-rw-r--r-- | support/dktools/rshdown.ctr | 2408 |
1 files changed, 0 insertions, 2408 deletions
diff --git a/support/dktools/rshdown.ctr b/support/dktools/rshdown.ctr deleted file mode 100644 index b6c4c0f4a8..0000000000 --- a/support/dktools/rshdown.ctr +++ /dev/null @@ -1,2408 +0,0 @@ -%% options - -copyright owner = Dirk Krause -copyright year = 2016-xxxx -SPDX-License-Identifier: BSD-3-Clause - - -%% module - -/* - rshdown -s [-n _number_] [-l _port_] [-b] _address_ _port_ _file_ - rshdown [-c _configfile_] - - Either send shutdown packages (-s option used) - or run as daemon in background (no -s option) - and wait for shutdown packages. - - Sending: - - -n _number_ Number of packages to send - - -l _port_ Local port number to use - Default: Same as remote port - - -b Flag: Destination address is a broadcast address - - _address_ Destination address (hostname or IP address) - - _port_ Port number on destination host - - _file_ File containing data to send - - Daemon: - - -c _configfile_ Configuration file. - -*/ - - -#include "dk4conf.h" -#include "dk4types.h" - - -#include <stdio.h> - -#if DK4_HAVE_UNISTD_H -#ifndef UNISTD_H_INCLUDED -#include <unistd.h> -#define UNISTD_H_INCLUDED 1 -#endif -#endif - -#if DK4_HAVE_STDLIB_H -#ifndef STDLIB_H_INCLUDED -#include <stdlib.h> -#define STDLIB_H_INCLUDED 1 -#endif -#endif - -#if (DK4_CHAR_SIZE == 1) \ - && (DK4_HAVE_SIGACTION || DK4_HAVE_SIGSET) \ - && (DK4_HAVE_SETSID || DK4_HAVE_SETPGRP) - -#if DK4_HAVE_MATH_H -#ifndef MATH_H_INCLUDED -#if DK4_ON_WINDOWS -#ifndef _USE_MATH_DEFINES -#define _USE_MATH_DEFINES 1 -#endif -#endif -#include <math.h> -#define MATH_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 - -#if DK4_HAVE_STRING_H -#ifndef STRING_H_INCLUDED -#include <string.h> -#define STRING_H_INCLUDED 1 -#endif -#endif - -#if DK4_HAVE_SYS_TYPES_H -#ifndef SYS_TYPES_H_INCLUDED -#include <sys/types.h> -#define SYS_TYPES_H_INCLUDED 1 -#endif -#endif - -#if DK4_HAVE_SIGNAL_H -#ifndef SIGNAL_H_INCLUDED -#include <signal.h> -#define SIGNAL_H_INCLUDED 1 -#endif -#endif - -#if DK4_HAVE_SYSLOG_H -#ifndef SYSLOG_H_INCLUDED -#include <syslog.h> -#define SYSLOG_H_INCLUDED 1 -#endif -#endif - -#if DK4_HAVE_SYSEXITS_H -#ifndef SYSEXITS_H_INCLUDED -#include <sysexits.h> -#define SYSEXITS_H_INCLUDED 1 -#endif -#endif - -#include "dk4mem.h" -#include "dk4memrs.h" -#include "dk4opt.h" -#include "dk4mai8dus.h" -#include "dk4mai8dii.h" -#include "dk4fopt.h" -#include "dk4fopc8.h" -#include "dk4isadm.h" -#include "dk4sock.h" -#include "dk4inst.h" -#include "dk4str8.h" -#include "dk4mpl.h" -#include "dk4dmt.h" -#include "dk4vers.h" -#include "dk4unused.h" - - - -$!trace-include - - - -#ifndef RSHDOWN_BUFFER_SIZE -/** Buffer size, should not exceed UDP packet size. -*/ -#define RSHDOWN_BUFFER_SIZE 1460 -#endif - - - -/** Path name of data file. -*/ -static char file_name[DK4_MAX_PATH]; - - - -/** Send and receive buffer. -*/ -static char b1[RSHDOWN_BUFFER_SIZE]; - - -/** Buffer for local secret from file in daemon. -*/ -static char b2[sizeof(b1)]; - - -/** Command to execute on packet arrival. -*/ -static char cmd[1024]; - - -/** Allowed sender peer as text. -*/ -static char asender[1024]; - - -/** Options used by the program. -*/ -static dk4_option_t options[] = { - - /* 0 Configuration file. - */ - { { dkT('c'), dkT("config"), DK4_OPT_ARG_STRING }, { NULL }, 0 }, - - /* 1 Send data. - */ - { { dkT('s'), dkT("send"), DK4_OPT_ARG_NONE }, { NULL }, 0 }, - - /* 2 Destination address is a broadcast address. - */ - { { dkT('b'), dkT("broadcast"), DK4_OPT_ARG_NONE }, { NULL }, 0 }, - - /* 3 Number of packets to send. - */ - { { dkT('n'), dkT("number"), DK4_OPT_ARG_UNSIGNED}, { NULL }, 0 }, - - /* 4 Local port number. - */ - { { dkT('l'), dkT("local"), DK4_OPT_ARG_UNSIGNED}, { NULL }, 0}, - - /* 5 Help. - */ - { { dkT('\0'),dkT("help"), DK4_OPT_ARG_NONE}, { NULL }, 0}, - - /* 6 Version. - */ - { { dkT('\0'),dkT("version"), DK4_OPT_ARG_NONE}, { NULL }, 0}, - - /* 7 License - */ - { { dkT('\0'),dkT("license"), DK4_OPT_ARG_NONE}, { NULL }, 0} -}; - - - -/** Help text. -*/ -static const char * const help_text[] = { -$!text - -Remote shutdown sender and recipient - -rshdown [-c config] -rshdown -s [-n number] [-l port] [-b] host port file - --c config Configuration file for recipient (daemon). - --s Send shutdown data packet. --n number Send packet multiple times. --l port Local port to use for sending. --b Prepare socket for broadcast sending. -host Remote host (recipient), host name or IP address. - Option -b is required if you specify a broadcast - address like 255.255.255.255 or 192.0.2.255 here. -port Remote port. -file File containing pre-shared secret (shutdown data). - ---help Show this help text. ---version Show version number. ---license Show license information. - -$!end -}; - - - -/** License conditions text. -*/ -static const char * const license_text[] = { -$!text preprocessor - -This software uses code from the following projects, either directly or as -a library: - -dktools Dirk Krause's tools and libraries. - See http://sourceforge.net/p/dktools/wiki/Home/ - for more information. - -DK tools and libraries license -============================== -Copyright (c) 2015-2016, Dirk Krause -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its - 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 HOLDER 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. - -$!end -}; - - - -/** Version information. -*/ -static const char version_text[] = { DKT_VERSION_C8 }; - - - -/** Default configuration file name. -*/ -static const char def_conf_name[] = { - DK4_INST_DIR_ETC "/rshdown/rshdown.conf" -}; - - - -/** PID file name. -*/ -static const char pid_file_name[] = { - DK4_INST_DIR_SYSTEMD_RUN "/rshdown/rshdown.pid" -}; - - - -/** Key names expected in configuration file. -*/ -static const char * const key_names[] = { -$!string-table -# -# 0 -# -sender -# -# 1 -# -sender port -# -# 2 -# -receiver port -# -# 3 -# -signal -# -# 4 -# -command -# -# 5 -# -file -# -# 6 -# -debug -# -# 7 -# -syslog facility -$!end -}; - - - -/** Signal names. -*/ -static const char * const signal_names[] = { -$!string-table -# 0 1 -sighup -hup -# 2 3 -sigint -int -# 4 5 -sigquit -quit -# 6 7 -sigill -ill -# 8 9 -sigtrap -trap -# 10 11 -sigabrt -abrt -# 12 13 -sigiot -iot -# 14 15 -sigbus -bus -# 16 17 -sigfpe -fpe -# 18 19 -sigkill -kill -# 20 21 -sigusr1 -usr1 -# 22 23 -sigsegv -segv -# 24 25 -sigusr2 -usr2 -# 26 27 -sigpipe -pipe -# 28 29 -sigalrm -alrm -# 30 31 -sigterm -term -# 32 33 -sigstkflt -stkflt -# 34 35 36 37 -sigcld -cld -sigchld -chld -# 38 39 -sigcont -cont -# 40 41 -sigstop -stop -# 42 43 -sigtstp -tstp -# 44 45 -sigttin -ttin -# 46 47 -sigttou -ttou -# 48 49 -sigurg -urg -# 50 51 -sigxcpu -xcpu -# 52 53 -sigxfsz -xfsz -# 54 55 -sigvtalrm -vtalrm -# 56 57 -sigprof -prof -# 58 59 -sigwinch -winch -# 60 61 -sigpoll -poll -# 62 63 -sigio -io -# 64 65 -sigpwr -pwr -# 66 67 -sigsys -sys -$!end -}; - - - -/** Syslog facility names. -*/ -static const char * const syslog_facility_names[] = { -$!string-table -auth -authpriv -cron -daemon -ftp -kern -lpr -mail -news -security -syslog -user -uucp -local0 -local1 -local2 -local3 -local4 -local5 -local6 -local7 -$!end -}; - - -/** Texts used by the program, not localized. -*/ -static const char * const rshdown_kw[] = { -$!string-table -# -# 0 Program name -# -rshdown -# -# 1 -# -: -# -# 2 -# -ERROR: Failed to set broadcast mode on socket!\n -# -# 3 -# -ERROR: Failed to bind local address!\n -# -# 4 5 -# -ERROR: Failed to bind local address: " -"!\n -# -# 6 -# -ERROR: Failed to create socket!\n -# -# 7 8 -# -ERROR: Failed to find address for: " -"!\n -# -# 9 -# -ERROR: Failed to bring socket subsystem up!\n -# -# 10 -# -ERROR: 3 arguments required: host, port and file!\n -# -# 11 12 -# -ERROR: Not a 16 bit unsigned integer: " -"!\n -# -# 13 -# -ERROR: Port number 0 is not allowed!\n -# -# 14 15 -# -ERROR: Failed to open data file:\n" -"!\n -# -# 16 17 -# -ERROR: Failed to read data from file:\n" -"!\n -# -# 18 -# -ERROR: Failed to install signal handlers!\n -# -# 19 -# -ERROR: Failed to restore signal handlers!\n -# -# 20 -# -ERROR: Failed to create child process!\n -# -# 21 -# -Failed to detach from terminal! -# -# 22 -# -Failed to create child process! -# -# 23 24 -# -Failed to install signal handlers! -Failed to restore signal handlers! -# -# 25 -# -Failed to bring socket subsystem up! -# -# 26 -# -Failed to create UDP socket set! -# -# 27 28 -# -ERROR: Local port number too large!\n -ERROR: Local port number must not be 0!\n -# -# 29 30 -# -Failed to set allowed peer: " -"! -# -# 31 32 -# -ERROR: Illegal signal name: " -"!\n -# -# 33 34 -# -ERROR: Sender name too long:\n -"!\n -# -# 35 -# -ERROR: Sender name defined multiple times!\n -# -# 36 -# -ERROR: Signal number must be positive!\n -# -# 37 38 -# -ERROR: Command too long:\n" -"!\n -# -# 39 -# -ERROR: Command defined multiple times!\n -# -# 40 41 -# -ERROR: File name too long:\n" -"!\n -# -# 42 -# -ERROR: File name defined multiple times!\n -# -# 43 -# -ERROR: Unknown key in configuration file!\n -# -# 44 -# -ERROR: Missing value on configuration line!\n -# -# 45 -# -ERROR: No local port specified!\n -# -# 46 -# -ERROR: Signal number or command required!\n -# -# 47 -# -ERROR: No data file specified!\n -# -# 48 49 -# -ERROR: Illegal syslog facility: " -"!\n -# -# 50 -# -Service started. -# -# 51 -# -Initiate shutdown. -# -# 52 -# -Service finished. -# -# 53 54 -# -Packet from " -" discarded, wrong sender address! -# -# 55 56 -# -Packet from " -" discarded, wrong sender port! -# -# 57 58 -# -Packet from " -" discarded, size mismatch! -# -# 59 60 -# -Packet from " -" discarded, data mismatch! -# -# 61 62 -# -Failed to execute command: " -"! -$!end -}; - - -/** Information for daemon tool functions. -*/ -static dk4dmt_t dmt; - - -/** Number of options in the options array. -*/ -static const size_t szoptions = sizeof(options)/sizeof(dk4_option_t); - - - -/** Number of bytes in buffer b1. -*/ -static size_t szb1 = 0; - - - -/** Number of bytes in buffer b2. -*/ -static size_t szb2 = 0; - - - -/** Exit status code. -*/ -static int exval = EXIT_FAILURE; - - - -/** Options: Help (1), version (2), license (4). -*/ -static int hvl = 0; - - - -/** Flag: Additional debug messages. -*/ -static int debug = 0; - - - -#ifdef LOG_DAEMON -/** Syslog facility. -*/ -static int syslogf = LOG_AUTH; -#else -/** Syslog facility. -*/ -static int syslogf = (3<<3); -#endif - - - -/** Signal to send on arrival of shutdown data packet. -*/ -static int signo = -#ifdef SIGPWR -SIGPWR -#else -#ifdef SIGTERM -SIGTERM -#else -15 -#endif -#endif -; - - - -#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; - - - -/** Remote port. -*/ -static unsigned short rp = 0U; - - - -/** Local port. -*/ -static unsigned short lp = 0U; - - -/** Pass pointer through. - Use of this function is recommended by CERT C coding standard - to avoid optimizing out. - @param ptr Pointer to pass through. - @return The ptr argument. -*/ -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 DK4_ARG_UNUSED(signo) ) -{ - DK4_UNUSED_ARG(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 DK4_ARG_UNUSED(signo) ) -{ - DK4_UNUSED_ARG(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 DK4_ARG_UNUSED(signo) ) -{ - DK4_UNUSED_ARG(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 must abort due to signal. - @param dopipe Flag: Check for SIGPIPE too. - @return 1 if we can continue, 0 otherwise. -*/ -static -int -can_continue(void) -{ - int back = 1; - if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } - if (0 != sig_read_atomic(&sig_had_int)) { back = 0; } - return back; -} - - - -/** Write log message to stderr, 1 component. - @param i Text index in rshdown_kw array. -*/ -static -void -log_1(size_t i) -{ - fputs(rshdown_kw[0], stderr); - fputs(rshdown_kw[1], stderr); - fputs(rshdown_kw[i], stderr); - fflush(stderr); -} - - - -/** Write syslog message, 1 component. - @param i Index of text in rshdown_kw array. -*/ -static -void -syslog_1(size_t i) -{ -#if DK4_HAVE_SYSLOG - openlog(rshdown_kw[0], LOG_PID, syslogf); - syslog(LOG_ERR, "%s", rshdown_kw[i]); - closelog(); -#endif -} - - - -/** Write syslog message, 3 components. - @param i1 Index of first component in rshdown_kw array. - @param i2 Index of third component in rshdown_kw array. - @param str Second component. -*/ -static -void -syslog_3(size_t i1, size_t i2, const char *str) -{ -#if DK4_HAVE_SYSLOG - openlog(rshdown_kw[0], LOG_PID, syslogf); - if (NULL != str) { - syslog(LOG_ERR, "%s%s%s", rshdown_kw[i1], str, rshdown_kw[i2]); - } else { - syslog(LOG_ERR, "%s%s", rshdown_kw[i1], rshdown_kw[i2]); - } - closelog(); -#endif -} - - - -/** Write an additional debug message to syslog. - @param i1 Index of first component in rshdown_kw array. - @param i2 Index of third component in rshdown_kw array. - @param sa Socket address, second component. -*/ -static -void -syslog_debug(size_t i1, size_t i2, dk4_sockaddr_storage_t *sa) -{ -#if DK4_HAVE_SYSLOG - char buf[128]; /* Buffer for text respresentation of address */ - int res; /* Operation result from conversion */ - - if (0 != debug) { - res = dk4socket_c8_sockaddr_to_text(buf, sizeof(buf), sa, NULL); - openlog(rshdown_kw[0], LOG_PID, syslogf); - if (DK4_SOCKET_RESULT_SUCCESS == res) { - syslog(LOG_DEBUG, "%s%s%s", rshdown_kw[i1], buf, rshdown_kw[i2]); - } else { - syslog(LOG_DEBUG, "%s%s", rshdown_kw[i1], rshdown_kw[i2]); - } - closelog(); - } -#endif -} - - - -/** Write log message to stderr, 3 components. - @param i1 Index of first component in rshdown_kw array. - @param i2 Index of third component in rshdown_kw array. - @param str Second component. -*/ -static -void -log_3(size_t i1, size_t i2, const char *str) -{ - fputs(rshdown_kw[0], stderr); - fputs(rshdown_kw[1], stderr); - fputs(rshdown_kw[i1], stderr); - if (NULL != str) { fputs(str, stderr); } - fputs(rshdown_kw[i2], stderr); - fflush(stderr); -} - - - -/** Send buffer over network. - @param hn Remote host name or IP address as text. - @param rp Remote port in host representation. - @param lp Local port in host representation. - @param sz Number of bytes in b1. -*/ -static -void -send_network(const char *hn, size_t sz) -{ - char adbuf[128]; /* Address as text */ - dk4_sockaddr_storage_t array[2]; /* Address pair */ - dk4_um_t num = (dk4_um_t)0UL; - size_t szr = 0; /* Rem addr size */ - size_t szl = 0; /* Loc addr size */ - size_t lgt = 0; /* Length sent */ - dk4_socket_t sock = INVALID_SOCKET; - int res = 0; /* Operation result */ - int ip4 = 0; /* IPv4 preferred */ - int af = AF_UNSPEC; - int pf = PF_UNSPEC; - $? "+ send_network" - if (DK4_SOCKET_RESULT_SUCCESS == dk4socket_up(NULL)) { - if (options[2].found) { ip4 = 1; } $? ". socket subsystem up" - res = dk4socket_c8_udp_addresses_numeric(array, hn, rp, lp, ip4, NULL); - if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". addresses ok" - szr = dk4socket_address_size(array); - szl = dk4socket_address_size(&(array[1])); - af = dk4socket_address_family(&(array[1])); - pf = dk4socket_pf_for_af(af); - if ((0 < szr) && (0 < szl) && (AF_UNSPEC != af) && (PF_UNSPEC != pf)) { - sock = dk4socket_open(pf, SOCK_DGRAM, 0, NULL); - if (INVALID_SOCKET != sock) { $? ". socket ok" - exval = EXIT_SUCCESS; - (void)dk4socket_option_set_reuse(sock, 1, NULL); - if (options[2].found) { $? ". prepare for broadcast" - res = dk4socket_option_set_broadcast(sock,1,NULL); - if (DK4_SOCKET_RESULT_SUCCESS != res) { - /* ERROR: Failed to set broadcast mode */ - log_1(2); - exval = EXIT_FAILURE; $? "! broadcast preparation" - } - } - res = dk4socket_bind( - sock, (struct sockaddr *)(&(array[1])), szl, NULL - ); - if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". address bound" - if (0 != options[3].found) { num = options[3].val.u; } - if ((dk4_um_t)0UL == num) { num = (dk4_um_t)1UL; } - while ((0 != can_continue()) && ((dk4_um_t)0UL < num--)) { - lgt = sz; $? ". send attempt" - res = dk4socket_sendto( - sock, b1, &lgt, 0, - (struct sockaddr *)(&(array[0])), szr, - 0L, 0L, NULL - ); - if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". sendto ok" - if (lgt != sz) { exval = EXIT_FAILURE; } - } else { $? "! sendto failed" - exval = EXIT_FAILURE; - } - } - } else { $? "! failed to bind local addr" - /* ERROR: Failed to bind local address */ - res = dk4socket_c8_addr_port_to_text( - adbuf, sizeof(adbuf), - af, (struct sockaddr *)(&(array[1])), szl, NULL - ); - if (DK4_SOCKET_RESULT_SUCCESS == res) { - log_3(4, 5, adbuf); - } else { - log_1(3); - } - } - (void)dk4socket_close(sock, NULL); - } else { $? "! failed to open socket" - /* ERROR: Failed to open socket */ - log_1(6); - } - } else { $? "! something wrong" - if (0 == szr) { $? "! remote address size" - log_3(7, 8, hn); - } - if (0 == szl) { $? "! local address size" - log_3(7, 8, hn); - } - if (AF_UNSPEC == af) { $? "! address family" - log_3(7, 8, hn); - } - if (PF_UNSPEC == pf) { $? "! protocol family" - log_3(7, 8, hn); - } - } - } else { $? "! addresses not found" - /* ERROR: Failed to obtain addresses */ - log_3(7, 8, hn); - } - (void)dk4socket_down(NULL); - } else { $? "! socket subsystem" - /* ERROR: Failed to bring socket subsystem up */ - log_1(9); - } - $? "- send_network" -} - - - -/** Send shutdown data packet. - @param filenames Command line arguments array, - 0=remote host, 1=remote port, 2=filename. - @param szfilenames Number of elements in filenames array. -*/ -static -void -sender_with_signals(const char * const *filenames, size_t szfilenames) -{ - FILE *fipo = NULL; /* Data file */ - const char *ep = NULL; /* End of usefull data pointer */ - size_t lgt = 0; /* Number of bytes in buffer */ - int res = 0; /* Conversion or operation result */ - $? "+ sender_with_signals" - if (3 == szfilenames) { $? ". szfilenames" - res = dk4ma_input_c8_dec_ushort(&rp, filenames[1], &ep, 1, NULL); - if (0 != res) { $? ". port number" - if (0 != rp) { $? ". port number not 0" - lp = rp; - if (0 != options[4].found) { $? ". local port given" - if ((dk4_um_t)0UL < options[4].val.u) { $? ". lp ok" - if ((dk4_um_t)(USHRT_MAX) >= options[4].val.u) { - lp = (unsigned short)(options[4].val.u); $? ". lp ok" - } else { $? "! overflow" - lp = 0; - /* ERROR: Local port number exceeds 16 bit unsigned range */ - log_1(27); - } - } else { $? "! lp 0" - lp = 0; - /* ERROR: Local port number 0 is not allowed */ - log_1(28); - } - } - if (0 != lp) { $? ". can run" - fipo = dk4fopen_c8(filenames[2], "rb", DK4_FOPEN_SC_IS_REGULAR, NULL); - if (NULL != fipo) { $? ". data file opened" - lgt = fread(b1, 1, sizeof(b1), fipo); - fclose(fipo); - if (0 < lgt) { $? ". data from file" - /* Send bytes over network */ - send_network(filenames[0], lgt); - /* Overwrite memory containing data packet */ - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - exval = EXIT_FAILURE; $? "! reset mem failed" - } - } else { $? "! no data from file" - /* ERROR: No data read from file */ - log_3(16, 17, filenames[2]); - } - } else { $? "! data file" - /* ERROR: Failed to open data file */ - log_3(14, 15, filenames[2]); - } - } else { $? "! config" - } - } else { $? "! port number 0" - /* ERROR: Remote port number 0 is not allowed */ - log_1(13); - } - } else { $? "! port number" - /* ERROR: Not a 16 bit unsigned number */ - log_3(11, 12, filenames[1]); - } - } else { $? "! szfilenames" - /* ERROR: Three arguments required - host, port and file */ - log_1(10); - } - $? "- sender_with_signals" -} - - - -/** Send shutdown data packet. - @param filenames Command line arguments array, - 0=remote host, 1=remote port, 2=filename. - @param szfilenames Number of elements in filenames array. -*/ -static -void -sender(const char * const *filenames, size_t szfilenames) -{ - $!trace-init rshdown.deb - $? "+ sender" -#ifdef DK4_HAVE_SIGACTION -#ifdef SIGPIPE - struct sigaction opipe; - struct sigaction npipe; -#endif - struct sigaction oint; - struct sigaction nint; - struct sigaction oterm; - struct sigaction nterm; -#else -#ifdef SIGPIPE - dk4_sig_handler_t *opipe = NULL; -#endif - dk4_sig_handler_t *oterm = NULL; - dk4_sig_handler_t *oint = NULL; -#endif -#ifdef DK4_HAVE_SIGACTION -#ifdef SIGPIPE - int spipe = 0; -#endif - int sint = 0; - int sterm = 0; - int s_f_i = 0; - int s_f_r = 0; -#endif - - /* Set signal handlers - */ -#if DK4_HAVE_SIGACTION -#ifdef SIGPIPE - DK4_MEMRES(&npipe, sizeof(npipe)); - npipe.sa_handler = sig_handler_pipe; - npipe.sa_flags = 0; - if (0 != sigemptyset(&npipe.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { - s_f_i = 1; - goto finished; - } - spipe = 1; -#endif - DK4_MEMRES(&nterm, sizeof(nterm)); - nterm.sa_handler = sig_handler_term; - nterm.sa_flags = 0; - if (0 != sigemptyset(&nterm.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGTERM, &nterm, &oterm)) { - s_f_i = 1; - goto finished; - } - sterm = 1; - DK4_MEMRES(&nint, sizeof(nint)); - nint.sa_handler = sig_handler_int; - nint.sa_flags = 0; - if (0 != sigemptyset(&nint.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&nint.sa_mask, SIGINT)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGINT, &nint, &oint)) { - s_f_i = 1; - goto finished; - } - sint = 1; -#else -#ifdef SIGPIPE - opipe = sigset(SIGPIPE, sig_handler_pipe); -#endif - oint = sigset(SIGINT, sig_handler_int); - oterm = sigset(SIGTERM, sig_handler_term); -#endif - - /* Send the bytes. - */ - sender_with_signals(filenames, szfilenames); - - finished: - - /* Restore signal handlers - */ -#if DK4_HAVE_SIGACTION - if (0 != s_f_i) { - /* ERROR: Failed to install signal handlers */ - log_1(18); - exval = EXIT_FAILURE; - } - if (0 != sint) { - if (0 != sigaction(SIGINT, &oint, NULL)) { - s_f_r = 1; - } - } - if (0 != sterm) { - if (0 != sigaction(SIGTERM, &oterm, NULL)) { - s_f_r = 1; - } - } -#ifdef SIGPIPE - if (0 != spipe) { - if (0 != sigaction(SIGPIPE, &opipe, NULL)) { - s_f_r = 1; - } - } -#endif - if (0 != s_f_r) { - /* ERROR: Failed to restore signal handlers */ - log_1(19); - exval = EXIT_FAILURE; - } -#else - if (NULL != oterm) { sigset(SIGTERM, oterm); } - if (NULL != oint ) { sigset(SIGINT, oint ); } -#ifdef SIGPIPE - if (NULL != opipe) { sigset(SIGPIPE, opipe); } -#endif -#endif - $? "- sender" - $!trace-end -} - - - -/** Run service -*/ -static -void -run_daemon_loop(void) -{ - dk4_allowed_peer_t peer; /* Allowed remote address */ - dk4_sockaddr_storage_t sa; /* Generic socket address */ - fd_set rfds; /* Readable file descriptors */ - dk4_socket_set_t *sset = NULL; /* Set of sockets to read data from */ - struct sockaddr *soa = NULL; /* Minimum socket address */ - struct sockaddr_in *so4 = NULL; /* IPv4 socket address */ -#if DK4_HAVE_STRUCT_SOCKADDR_IN6 - struct sockaddr_in6 *so6 = NULL; /* IPv6 socket address */ -#endif - size_t szsa = 0; /* Size of sa */ - size_t i = 0; /* Traverse socket set */ - dk4_socket_t smax = 0; /* Maximum socket fd number */ - int cc = 1; /* Flag: Can continue */ - int pused = 0; /* Flag: Peer used */ - int res = 0; /* Operation result */ - int ok = 0; /* Flag: Data packet matches file */ - unsigned short frp = 0; /* Found remote port */ - $? "+ run_daemon_loop" - soa = (struct sockaddr *)(&sa); - so4 = (struct sockaddr_in *)(&sa); -#if DK4_HAVE_STRUCT_SOCKADDR_IN6 - so6 = (struct sockaddr_in6 *)(&sa); -#endif - if (DK4_SOCKET_RESULT_SUCCESS == dk4socket_up(NULL)) { - $? ". socket subsystem" - if (0 < strlen(asender)) { $? ". sender specified" - res = dk4socket_c8_get_allowed_peer(&peer, asender, NULL); - if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". peer found" - pused = 1; - } else { $? "! peer not found" - cc = 0; - /* SYSLOG ERROR: Invalid peer name */ - syslog_3(29, 30, asender); - } - } - if (1 == cc) { $? ". no errors yet" - sset = dk4socket_set_udp_directly(lp, 0, 0, NULL); - if (NULL != sset) { $? ". socket set ok" - /* SYSLOG: Started */ -#if DK4_HAVE_SYSLOG - openlog(rshdown_kw[0], LOG_PID, syslogf); - syslog(LOG_INFO, "%s", rshdown_kw[50]); - closelog(); -#endif - do { - if (0 != can_continue()) { - FD_ZERO(&rfds); - smax = -1; - for (i = 0; i < sset->szUsed; i++) { - $? ". socket %d", (sset->pSockets)[i] - FD_SET((sset->pSockets)[i],&rfds); - if (smax < (sset->pSockets)[i]) { smax = (sset->pSockets)[i]; } - } - res = select((1+smax), &rfds, NULL, NULL, NULL); - if (0 != can_continue()) { - if (0 < res) { $? ". data available" - for (i = 0; ((1 == cc) && (i < sset->szUsed)); i++) { - $? ". checking %d", (sset->pSockets)[i] - if (FD_ISSET((sset->pSockets)[i],&rfds)) { - $? ". ready to read" - DK4_MEMRES(&sa, sizeof(sa)); - szb2 = sizeof(b2); - szsa = sizeof(sa); - res = dk4socket_recvfrom( - (sset->pSockets)[i], b2, &szb2, 0, - (struct sockaddr *)(&sa), &szsa, 0L, 0L, NULL - ); - if (0 != can_continue()) { $? ". can continue" - if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". read" - if (0 < szb2) { $? ". %u bytes received", (unsigned)szb2 - ok = 1; - if (0 != pused) { $? ". check peer" - res = dk4socket_allowed_peer_compare(&peer, &sa, 1); - if (0 != res) { $? "! address mismatch" - ok = 0; - /* SYSLOG DEBUG: Address mismatch */ - syslog_debug(53, 54, &sa); - } - } - if (0U != rp) { $? ". check port" - frp = 0; - switch (soa->sa_family) { - case AF_INET : { - frp = dk4socket_ntohs(so4->sin_port); - } break; -#if DK4_HAVE_STRUCT_SOCKADDR_IN6 - case AF_INET6 : { - frp = dk4socket_ntohs(so6->sin6_port); - } break; -#endif - } - if (frp != rp) { $? "! port mismatch" - ok = 0; - /* SYSLOG DEBUG: Port mismatch */ - syslog_debug(55, 56, &sa); - } - } - if (0 != ok) { $? ". peer/port ok" - ok = 0; - if (szb1 == szb2) { $? ". size match" - if (0 == DK4_MEMCMP(b1,b2,szb1)) { - ok = 1; $? ". data matches" - } else { $? "! data mismatch" - /* SYSLOG DEBUG: Data mismatch */ - syslog_debug(59, 60, &sa); - } - } else { $? "! size mismatch" - /* SYSLOG DEBUG: Size mismatch */ - syslog_debug(57, 58, &sa); - } - } - if (0 != ok) { $? ". going to shut down" - /* Shutdown */ - /* SYSLOG: Initiating shutdown */ -#if DK4_HAVE_SYSLOG - openlog(rshdown_kw[0], LOG_PID, syslogf); - syslog(LOG_INFO, "%s", rshdown_kw[51]); - closelog(); -#endif - if (0 < strlen(cmd)) { $? ". command" - if (0 != system(cmd)) { -#if DK4_HAVE_SYSLOG - - openlog(rshdown_kw[0], LOG_PID, syslogf); - syslog( - LOG_ERR, "%s%s%s", - rshdown_kw[61], cmd, rshdown_kw[62] - ); - closelog(); -#endif - } - } else { $? ". signal" - if (0 < signo) { - kill((pid_t)1, signo); - } else { -#ifdef SIGPWR - kill((pid_t)1, SIGPWR); -#else -#ifdef SIGTERM - kill((pid_t)1, SIGTERM); -#else - kill((pid_t)1, 15); -#endif -#endif - } - } - cc = 0; - } - } else { $? "! size is 0" - } - } else { $? "! recvfrom" - } - } else { $? "! signal" - cc = -1; - } - } else { $? ". not ready to read" - } - } - } else { $? ". no fd ready" - } - } else { $? "! signal" - cc = -1; - } - } else { $? "! signal" - cc = -1; - } - } while (1 == cc); $? ". loop finished" - dk4socket_set_close(sset, NULL); - /* SYSLOG: Finished */ -#if DK4_HAVE_SYSLOG - openlog(rshdown_kw[0], LOG_PID, syslogf); - syslog(LOG_INFO, "%s", rshdown_kw[52]); - closelog(); -#endif - } else { $? "! socket set" - /* SYSLOG ERROR: Failed to create socket set */ - syslog_1(26); - } - } else { $? "! previous errors" - } - (void)dk4socket_down(NULL); - } else { $? "! socket subsystem" - /* SYSLOG ERROR: Failed to bring socket subsystem up */ - syslog_1(25); - } - $? "- run_daemon_loop" -} - - - -/** Set signal handlers and run service. -*/ -static -void -run_daemon_with_signals(void) -{ -#ifdef DK4_HAVE_SIGACTION -#ifdef SIGPIPE - struct sigaction opipe; - struct sigaction npipe; -#endif - struct sigaction oint; - struct sigaction nint; - struct sigaction oterm; - struct sigaction nterm; -#else -#ifdef SIGPIPE - dk4_sig_handler_t *opipe = NULL; -#endif - dk4_sig_handler_t *oterm = NULL; - dk4_sig_handler_t *oint = NULL; -#endif -#ifdef DK4_HAVE_SIGACTION -#ifdef SIGPIPE - int spipe = 0; -#endif - int sint = 0; - int sterm = 0; - int s_f_i = 0; - int s_f_r = 0; -#endif - $? "+ run_daemon_with_signals" - /* Set signal handlers - */ -#if DK4_HAVE_SIGACTION -#ifdef SIGPIPE - DK4_MEMRES(&npipe, sizeof(npipe)); - npipe.sa_handler = sig_handler_pipe; - npipe.sa_flags = 0; - if (0 != sigemptyset(&npipe.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { - s_f_i = 1; - goto finished; - } - spipe = 1; -#endif - DK4_MEMRES(&nterm, sizeof(nterm)); - nterm.sa_handler = sig_handler_term; - nterm.sa_flags = 0; - if (0 != sigemptyset(&nterm.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGTERM, &nterm, &oterm)) { - s_f_i = 1; - goto finished; - } - sterm = 1; - DK4_MEMRES(&nint, sizeof(nint)); - nint.sa_handler = sig_handler_int; - nint.sa_flags = 0; - if (0 != sigemptyset(&nint.sa_mask)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaddset(&nint.sa_mask, SIGINT)) { - s_f_i = 1; - goto finished; - } - if (0 != sigaction(SIGINT, &nint, &oint)) { - s_f_i = 1; - goto finished; - } - sint = 1; -#else -#ifdef SIGPIPE - opipe = sigset(SIGPIPE, sig_handler_pipe); -#endif - oint = sigset(SIGINT, sig_handler_int); - oterm = sigset(SIGTERM, sig_handler_term); -#endif - - run_daemon_loop(); - - finished: - - /* Restore signal handlers - */ -#if DK4_HAVE_SIGACTION - if (0 != s_f_i) { - /* ERROR: Failed to install signal handlers */ - syslog_1(23); - dk4dmt_error_sysfct(&dmt); - } - if (0 != sint) { - if (0 != sigaction(SIGINT, &oint, NULL)) { - s_f_r = 1; - } - } - if (0 != sterm) { - if (0 != sigaction(SIGTERM, &oterm, NULL)) { - s_f_r = 1; - } - } -#ifdef SIGPIPE - if (0 != spipe) { - if (0 != sigaction(SIGPIPE, &opipe, NULL)) { - s_f_r = 1; - } - } -#endif - if (0 != s_f_r) { - /* ERROR: Failed to restore signal handlers */ - syslog_1(24); - dk4dmt_error_sysfct(&dmt); - } -#else - if (NULL != oterm) { sigset(SIGTERM, oterm); } - if (NULL != oint ) { sigset(SIGINT, oint ); } -#ifdef SIGPIPE - if (NULL != opipe) { sigset(SIGPIPE, opipe); } -#endif -#endif - $? "- run_daemon_with_signals" -} - - - -/** Retrieve port number from a configuration file line. - @param dest Address of destination variable. - @param pv String containing the port number. - @param a0 Flag: Remote port, 0 allowed for arbitrary ports. - @return 1 on success, 0 on error. -*/ -static -int -set_port_number( - unsigned short *dest, - const char *pv, - int a0 -) -{ - const char *ep = NULL; - int back = 0; - unsigned short us = 0U; - - if (0 != dk4ma_input_c8_dec_ushort(&us, pv, &ep, 1, NULL)) { - if (0U != us) { - *dest = us; - back = 1; - } else { - if (0 != a0) { - *dest = us; - back = 1; - } else { - /* ERROR: Port number 0 not allowed! */ - log_1(28); - } - } - } else { - /* ERROR: Not a 16 bit unsigned number! */ - log_3(11, 12, pv); - } - return back; -} - - - -/** Set the signal number. - @param pv Text containing the number. - @return 1 on success, 0 on error. -*/ -static -int -set_signal_number(const char *pv) -{ - int back = 1; - $? "+ set_signal_number \"%s\"", TR_8STR(pv) - switch ( dk4str8_array_index(signal_names, pv, 0) ) { - case 0 : case 1 : { -#ifdef SIGHUP - signo = SIGHUP; -#else - signo = 1; -#endif - } break; - case 2 : case 3 : { -#ifdef SIGINT - signo = SIGINT; -#else - signo = 2; -#endif - } break; - case 4 : case 5 : { -#ifdef SIGQUIT - signo = SIGQUIT; -#else - signo = 3; -#endif - } break; - case 6 : case 7 : { -#ifdef SIGILL - signo = SIGILL; -#else - signo = 4; -#endif - } break; - case 8 : case 9 : { -#ifdef SIGTRAP - signo = SIGTRAP; -#else - signo = 5; -#endif - } break; - case 10 : case 11 : case 12 : case 13 : { -#ifdef SIGABRT - signo = SIGABRT; -#else -#ifdef SIGIOT - signo = SIGIOT; -#else - signo = 6; -#endif -#endif - } break; - case 14 : case 15 : { -#ifdef SIGBUS - signo = SIGBUS; -#else - signo = 7; -#endif - } break; - case 16 : case 17 : { -#ifdef SIGFPE - signo = SIGFPE; -#else - signo = 8; -#endif - } break; - case 18 : case 19 : { -#ifdef SIGKILL - signo = SIGKILL; -#else - signo = 9; -#endif - } break; - case 20 : case 21 : { -#ifdef SIGUSR1 - signo = SIGUSR1; -#else - signo = 10; -#endif - } break; - case 22 : case 23 : { -#ifdef SIGSEGV - signo = SIGSEGV; -#else - signo = 11; -#endif - } break; - case 24 : case 25 : { -#ifdef SIGUSR2 - signo = SIGUSR2; -#else - signo = 12; -#endif - } break; - case 26 : case 27 : { -#ifdef SIGPIPE - signo = SIGPIPE; -#else - signo = 13; -#endif - } break; - case 28 : case 29 : { -#ifdef SIGALRM - signo = SIGALRM; -#else - signo = 14; -#endif - } break; - case 30 : case 31 : { -#ifdef SIGTERM - signo = SIGTERM; -#else - signo = 15; -#endif - } break; - case 32 : case 33 : { -#ifdef SIGSTKFLT - signo = SIGSTKFLT; -#else - signo = 16; -#endif - } break; - case 34 : case 35 : case 36 : case 37 : { -#ifdef SIGCLD - signo = SIGCLD; -#else -#ifdef SIGCHLD - signo = SIGCHLD; -#else - signo = 17; -#endif -#endif - } break; - case 38 : case 39 : { -#ifdef SIGCONT - signo = SIGCONT; -#else - signo = 18; -#endif - } break; - case 40 : case 41 : { -#ifdef SIGSTOP - signo = SIGSTOP; -#else - signo = 19; -#endif - } break; - case 42 : case 43 : { -#ifdef SIGTSTP - signo = SIGTSTP; -#else - signo = 20; -#endif - } break; - case 44 : case 45 : { -#ifdef SIGTTIN - signo = SIGTTIN; -#else - signo = 21; -#endif - } break; - case 46 : case 47 : { -#ifdef SIGTTOU - signo = SIGTTOU; -#else - signo = 22; -#endif - } break; - case 48 : case 49 : { -#ifdef SIGURG - signo = SIGURG; -#else - signo = 23; -#endif - } break; - case 50 : case 51 : { -#ifdef SIGXCPU - signo = SIGXCPU; -#else - signo = 24; -#endif - } break; - case 52 : case 53 : { -#ifdef SIGXFSZ - signo = SIGXFSZ; -#else - signo = 25; -#endif - } break; - case 54 : case 55 : { -#ifdef SIGVTALRM - signo = SIGVTALRM; -#else - signo = 26; -#endif - } break; - case 56 : case 57 : { -#ifdef SIGPROF - signo = SIGPROF; -#else - signo = 27; -#endif - } break; - case 58 : case 59 : { -#ifdef SIGWINCH - signo = SIGWINCH; -#else - signo = 28; -#endif - } break; - case 60 : case 61 : case 62 : case 63 : { -#ifdef SIGPOLL - signo = SIGPOLL; -#else -#ifdef SIGIO - signo = SIGIO -#else - signo = 29; -#endif -#endif - } break; - case 64 : case 65 : { -#ifdef SIGPWR - signo = SIGPWR; -#else - signo = 30; -#endif - } break; - case 66 : case 67 : { -#ifdef SIGSYS - signo = SIGSYS; -#else - signo = 31; -#endif - } break; - default : { $? "! illegal signal name" - back = 0; - /* ERROR: Illegal signal name */ - log_3(31, 32, pv); - } break; - } $? "- set_signal_number %d", back - return back; -} - - - -/** Set syslog facility. - @param pv Text representation of syslog facility. - @return 1 on success, 0 on error. -*/ -static -int -set_syslog_facility(const char *pv) -{ - int back = 1; - if (NULL != pv) { - switch ( dk4str8_array_index(syslog_facility_names, pv, 0) ) { -#ifdef LOG_AUTH - case 0: { syslogf = LOG_AUTH; } break; -#endif -#ifdef LOG_AUTHPRIV - case 1: { syslogf = LOG_AUTHPRIV; } break; -#endif -#ifdef LOG_CRON - case 2: { syslogf = LOG_CRON; } break; -#endif -#ifdef LOG_DAEMON - case 3: { syslogf = LOG_DAEMON; } break; -#endif -#ifdef LOG_FTP - case 4: { syslogf = LOG_FTP; } break; -#endif -#ifdef LOG_KERN - case 5: { syslogf = LOG_KERN; } break; -#endif -#ifdef LOG_LPR - case 6: { syslogf = LOG_LPR; } break; -#endif -#ifdef LOG_MAIL - case 7: { syslogf = LOG_MAIL; } break; -#endif -#ifdef LOG_NEWS - case 8: { syslogf = LOG_NEWS; } break; -#endif -#ifdef LOG_AUTH - case 9: { syslogf = LOG_AUTH; } break; -#endif -#ifdef LOG_SYSLOG - case 10: { syslogf = LOG_SYSLOG; } break; -#endif -#ifdef LOG_USER - case 11: { syslogf = LOG_USER; } break; -#endif -#ifdef LOG_UUCP - case 12: { syslogf = LOG_UUCP; } break; -#endif -#ifdef LOG_LOCAL0 - case 13: { syslogf = LOG_LOCAL0; } break; -#endif -#ifdef LOG_LOCAL1 - case 14: { syslogf = LOG_LOCAL1; } break; -#endif -#ifdef LOG_LOCAL2 - case 15: { syslogf = LOG_LOCAL2; } break; -#endif -#ifdef LOG_LOCAL3 - case 16: { syslogf = LOG_LOCAL3; } break; -#endif -#ifdef LOG_LOCAL4 - case 17: { syslogf = LOG_LOCAL4; } break; -#endif -#ifdef LOG_LOCAL5 - case 18: { syslogf = LOG_LOCAL5; } break; -#endif -#ifdef LOG_LOCAL6 - case 19: { syslogf = LOG_LOCAL6; } break; -#endif -#ifdef LOG_LOCAL7 - case 20: { syslogf = LOG_LOCAL7; } break; -#endif - default: { - back = 0; - log_3(48, 49, pv); - } break; - } - } - return back; -} - - - -/** Read configuration file. - @return 1 on success, 0 on error. -*/ -static -int -read_config_file(void) -{ - FILE *fipo = NULL; /* Input file to process */ - const char *fn = NULL; /* Input file name */ - const char *ep = NULL; /* End pointer after number */ - char *pk = NULL; /* Pointer to key string */ - char *pv = NULL; /* Pointer to value string */ - dk4_um_t lineno = (dk4_um_t)0UL; /* Current line number */ - int back = 0; - $? "+ read_config_file" - if (0 != options[0].found) { fn = options[0].val.t; } - if (NULL == fn) { fn = def_conf_name; } - fipo = dk4fopen_c8(fn, "r", DK4_FOPEN_SC_IS_REGULAR, NULL); - if (NULL != fipo) { - back = 1; - while( fgets(b1, sizeof(b1), fipo) ) { - lineno++; - pk = dk4str8_start(b1, NULL); - if (NULL != pk) { - if ('#' != *pk) { - pv = dk4str8_chr(pk, '='); - if (NULL != pv) { - *(pv++) = '\0'; - pv = dk4str8_start(pv, NULL); - if (NULL != pv) { - dk4str8_normalize(pk, NULL); - dk4str8_delnl(pv); - switch ( dk4str8_array_index(key_names, pk, 0) ) { - case 0: { /* sender address */ - if (0 == strlen(asender)) { - dk4str8_normalize(pv, NULL); - if (0 == dk4str8_cpy_s(asender,sizeof(asender),pv,NULL)) { - back = 0; $? "! sender too long" - /* ERROR: Sender name too long */ - log_3(33, 34, pv); - } - } else { $? "! redefinition of sender" - back = 0; - /* ERROR: Redefinition of sender */ - log_1(35); - } - } break; - case 1: { /* sender port */ - if (0 == set_port_number(&rp, pv, 1)) { - back = 0; $? "! remote port not numeric" - } - } break; - case 2: { /* local port */ - if (0 == set_port_number(&lp, pv, 0)) { - back = 0; $? "! local port not numeric" - } - } break; - case 3: { /* signal */ - ep = NULL; - if (0 != dk4ma_input_c8_dec_int(&signo, pv, &ep, 1, NULL)) { - if (1 > signo) { - back = 0; $? "! illegal value for signo" - /* ERROR: Signal number must be positive */ - log_1(36); - } - } else { - dk4str8_normalize(pv, NULL); - if (0 == set_signal_number(pv)) { - back = 0; $? "! failed to set signo" - } - } - } break; - case 4: { /* command */ - if (0 == strlen(cmd)) { - if (0 == dk4str8_cpy_s(cmd, sizeof(cmd), pv, NULL)) { - back = 0; - /* ERROR: Command too long! */ - log_3(37, 38, pv); - } - } else { $? "! command redefined" - back = 0; - /* ERROR: Redefinition of command */ - log_1(39); - } - } break; - case 5: { /* file */ - if (0 == strlen(file_name)) { - if (0 == dk4str8_cpy_s(file_name,sizeof(file_name),pv,NULL)) - { - back = 0; - /* ERROR: File name too long! */ - log_3(40, 41, pv); - } - } else { $? "! file name redefined" - back = 0; - /* ERROR: Redefinition of file name */ - log_1(42); - } - } break; - case 6: { - debug = ((dk4str8_is_on(pv)) ? 1 : 0); - } break; - case 7: { - dk4str8_normalize(pv, NULL); - if (0 == set_syslog_facility(pv)) { - back = 0; - } - } break; - default : { $? "! unknown key" - log_1(43); - } break; - } - } else { $? "! missing value" - back = 0; - /* ERROR: Missing value */ - log_1(44); - } - } else { $? "! missing value" - back = 0; - /* ERROR: Missing value */ - log_1(44); - } - } - } - } - fclose(fipo); - if ((0 != back) && (0U == lp)) { - back = 0; $? "! missing local port" - /* ERROR: Local port not specified */ - log_1(45); - } - if (0 != back) { - if ((0 == signo) && (0 == strlen(cmd))) { - back = 0; $? "! command or signo" - /* ERROR: Signal or command required */ - log_1(46); - } - } - if (0 != back) { - if (0 != strlen(file_name)) { - fipo = dk4fopen_c8(file_name, "rb", DK4_FOPEN_SC_IS_REGULAR, NULL); - if (NULL != fipo) { - szb1 = fread(b1, 1, sizeof(b1), fipo); - fclose(fipo); - if (0 == szb1) { - back = 0; $? "! data file contents" - /* ERROR: Failed to read data from file */ - log_3(16, 17, file_name); - } - } else { $? "! open data file" - back = 0; - /* ERROR: Failed to open data file */ - log_3(14, 15, file_name); - } - } else { $? "! data file name" - back = 0; - /* ERROR: No data file specified */ - log_1(47); - } - } - } else { $? "! failed to open conf file" - } $? "- read_config_file %d", back - return back; -} - - -/** Daemon waiting for shutdown data packet. -*/ -static -void -run_as_daemon(void) -{ - pid_t cpid; - - dk4dmt_init(&dmt); - $? "+ run_as_daemon" - /* Preparations before we start. - */ - DK4_MEMRES(cmd, sizeof(cmd)); - DK4_MEMRES(asender, sizeof(asender)); - DK4_MEMRES(file_name, sizeof(file_name)); - if (read_config_file()) { $? ". conf ok" - dk4dmt_set_program(&dmt, rshdown_kw[0]); - dk4dmt_set_pidfile(&dmt, pid_file_name); - dk4dmt_set_syslog_feature(&dmt, syslogf); - if (0 != dk4dmt_parent_before_fork(&dmt)) { - cpid = fork(); - if ((pid_t)0 == cpid) { /* in the child */ - if (0 != dk4dmt_intermediate_before_fork(&dmt)) { - cpid = fork(); - if ((pid_t)0 == cpid) { /* in the child */ - $!trace-init /tmp/rshdown.deb - $? "+ daemon process" - dk4dmt_success(&dmt); - if (0 != dk4dmt_daemon_start(&dmt)) { - run_daemon_with_signals(); - } - dk4dmt_daemon_end(&dmt); - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - if (0 == dk4mem_reset_secure(b2, sizeof(b2), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - $? "- daemon process %d", exval - $!trace-end - } else { - if ((pid_t)(-1) != cpid) { /* intermediate process */ - dk4dmt_success(&dmt); - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - if (0 == dk4mem_reset_secure(b2, sizeof(b2), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - dk4dmt_intermediate_after_fork(&dmt); - } else { /* error */ - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - if (0 == dk4mem_reset_secure(b2, sizeof(b2), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - /* SYSLOG ERROR: Failed to create child process */ - syslog_1(22); - dk4dmt_intermediate_fork_failed(&dmt); - } - } - } else { - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - if (0 == dk4mem_reset_secure(b2, sizeof(b2), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - /* SYSLOG ERROR: Failed to detach */ - syslog_1(21); - } - } else { - if ((pid_t)(-1) != cpid) { /* parent */ - dk4dmt_parent_after_fork(&dmt); - } else { /* error */ - /* ERROR: Failed to create child process */ - dk4dmt_parent_fork_failed(&dmt); - log_1(20); - } - } - } - } - else { - dk4dmt_error_config(&dmt); - } - if (0 == dk4mem_reset_secure(b1, sizeof(b1), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - if (0 == dk4mem_reset_secure(b2, sizeof(b2), NULL)) { - dk4dmt_error_sysfct(&dmt); - } - exval = dk4dmt_get_exit_status(&dmt); - $? "- run_as_daemon" -} - - - -/** Show a text paragraph on standard output. - @param txt Text to show. -*/ -static -void -show_text(const char * const *txt) -{ - if (NULL != txt) { - while (NULL != *txt) { - fputs(*(txt++), stdout); - fputc('\n', stdout); - } - fflush(stdout); - } -} - - - -/** Handle --help, --version, --license options. -*/ -static -void -run_hvl(void) -{ - if (0 != (1 & hvl)) { - show_text(help_text); - } - if (0 != (2 & hvl)) { - fputs(version_text, stdout); - fputc('\n', stdout); - fflush(stdout); - } - if (0 != (4 & hvl)) { - show_text(license_text); - } -} - - - -/** Program entry point. - @param argc - @param argv - @return 0 on success, any other value indicates an error. -*/ -int -main(int argc, char *argv[]) -{ - char *filenames[32]; - size_t szfilenames = 32; /* Array size */ - int res = 0; /* Operation result */ - - $? "+ main" - /* Process command line arguments. - */ - res = dk4opt_process_argv( - options, szoptions, argc, argv, filenames, &szfilenames, 1, 1, NULL - ); - if (0 == res) { $? "! option processing" - goto finished; - } - - /* Check help, version, license. - */ - if (0 != options[5].found) { hvl |= 1; } - if (0 != options[6].found) { hvl |= 2; } - if (0 != options[7].found) { hvl |= 4; } - if (0 != hvl) { - run_hvl(); - goto finished; - } - - /* Either send data or run as daemon to receive data. - */ - if (0 != options[1].found) { $? ". run sender" - sender((const char * const *)filenames, szfilenames); - } else { $? ". run daemon" - run_as_daemon(); - } - - finished: - $? "- main %d", exval - exit(exval); return exval; -} - - -#else - - -/** Program entry point. - @param argc - @param argv - @return 0 on success, any other value indicates an error. -*/ -int -main(int argc, char *argv[]) -{ - fputs("rshdown: ERROR: Build requirements violation!\n", stderr); -#if DK4_CHAR_SIZE > 1 - fputs("Default character size is larger than 1!\n", stderr); -#endif -#if !((DK4_HAVE_SIGACTION) || (DK4_HAVE_SIGSET)) - fputs("Neither sigaction() nor sigset() are available!\n", stderr); -#endif -#if !((DK4_HAVE_SETSID) || (DK4_HAVE_SETPGRP)) - fputs("Neither setsid() nor setpgrp() are available!\n", stderr); -#endif - fflush(stderr); - exit(EXIT_FAILURE); return EXIT_FAILURE; -} - -#endif - - |