/* Copyright (c) 2000-2010, 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: * 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 Dirk Krause 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 dklogger.c Dklogger program. */ #ifndef MAX_SERVERS /** Maximum number of remote hosts to log to. */ #define MAX_SERVERS 16 #endif #include #if DK_HAVE_STDLIB_H #include #endif #if DK_HAVE_PROCESS_H #include #endif #include #include #include #include #include #include #include #include #include "dktools-version.h" #line 66 "dklogger.ctr" /** Remote host description. */ typedef struct { unsigned long addr; /**< IP4 address. */ unsigned short portno; /**< Port number. */ } remote_host; /** Array for remote hosts. */ static remote_host rh[MAX_SERVERS]; /** Number of configured remote hosts. */ static int rh_used = 0; /** System configuration directory. */ static char sysconfdir[] = { DK_SYSCONFDIR }; /** Application group name. */ static char packagename[] = { "dktools" }; /** Message text array. */ static char *dklogger_str[11]; /** Default message texts if localized texts not found. */ static dk_string_finder_t dklogger_find[] = { { "/m/01", &(dklogger_str[0]), "Host \"" }, { "/m/02", &(dklogger_str[1]), "\" unknown!" }, { "/m/03", &(dklogger_str[2]), "Failed to start socket!" }, { "/m/04", &(dklogger_str[3]), "Failed to obtain socket!" }, { "/m/05", &(dklogger_str[4]), "Missing message text!" }, { "/m/06", &(dklogger_str[5]), "No destination host!" }, { "/m/07", &(dklogger_str[6]), "No command line arguments!" }, { "/m/08", &(dklogger_str[7]), "TCP/IP unavailable!" }, { "/m/09", &(dklogger_str[8]), "" }, { "/m/10", &(dklogger_str[9]), "Current configuration:" }, { "/m/11", &(dklogger_str[10]), "Default syslog feature and priority" }, { NULL, NULL, NULL } }; /** Exit status. */ static int exval = 0; /** Application. */ static dk_app_t *app = NULL; /** Flag: Arguments used. */ static int argsused = 0; /** Pointer to array of command line arguments. */ static char **arguments = NULL; /** Pointer to one command line argument. */ typedef char *CPTR; /** Priority. */ static int the_priority = ((16<<3)+5); /** Pointer to priority string buffer. */ static char *pref_prio_buffer = NULL; /** Priority string. */ static char *prio_string = NULL; /** Preference key for priority. */ static char pk_syslog_priority[] = { "/syslog/priority" }; /** Get configuration. */ static void get_config DK_P0() { int lfd; char keybuffer[32]; char valbuffer[256]; char *ptr; unsigned short us; unsigned u; dk_ip_addr_t ipaddr; char *errmsg[4]; if(dkapp_get_pref(app, pk_syslog_priority, valbuffer, sizeof(valbuffer), 0)) { pref_prio_buffer = dkstr_dup(valbuffer); prio_string = pref_prio_buffer; } rh_used = 0; for(lfd = 1; lfd <= MAX_SERVERS; lfd++) { sprintf(keybuffer, "/syslog/host/%03d/destination", lfd); if(dkapp_get_pref(app, keybuffer, valbuffer, sizeof(valbuffer), 0)) { ptr = dkstr_chr(valbuffer, ':'); if(ptr) { *(ptr++) = '\0'; } if(dktcpipaddr_set_ip_byname(&ipaddr, valbuffer, NULL)) { rh[rh_used].addr = ipaddr.ip4.sin.sin_addr.s_addr; us = 514; if(ptr) { if(sscanf(ptr, "%u", &u) == 1) { us = (unsigned short)u; } } rh[rh_used++].portno = htons(us); } else { errmsg[0] = dklogger_str[0]; errmsg[1] = valbuffer; errmsg[2] = dklogger_str[1]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 3); } } else { lfd = MAX_SERVERS + 1; } } } /** Release configuration buffer. */ static void release_config DK_P0() { if(pref_prio_buffer) { dk_delete(pref_prio_buffer); pref_prio_buffer = NULL; } } /** Send a message. @param msgbuf Buffer containing the message to send. */ static void send_the_message DK_P1(char *, msgbuf) { dk_tcpip_t *sock; dk_ip_addr_t *addr; size_t lgt; int i; char *errmsg[4]; sock = dktcpip_new(); if(sock) { dktcpip_set_reuse(sock, 1); addr = dktcpip_get_addr(sock, DK_IP_ADDR_LOCAL_WISHED); dktcpip_addr_set_port(addr, 0, 0); dktcpipaddr_set_ip_any(addr); dktcpip_set_connectionless(sock, 1); addr = dktcpip_get_addr(sock, DK_IP_ADDR_REMOTE_WISHED); if(dktcpip_up(sock)) { lgt = strlen(msgbuf); for(i = 0; i < rh_used; i++) { (addr->ip4).sin.sin_addr.s_addr = rh[i].addr; dktcpip_addr_set_port(addr, rh[i].portno, rh[i].portno); dktcpip_write(sock, msgbuf, &lgt); } exval = 1; dktcpip_down(sock); } else { errmsg[0] = dklogger_str[2]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } dktcpip_delete(sock); sock = NULL; } else { errmsg[0] = dklogger_str[3]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } } /** Default help text if dklogger.txt is not found. */ static char *help_text[] = { "dklogger ", "dklogger -p . ", "", "Example:", "dklogger -p auth.notice User joe logged in.", NULL }; /** Text to show version number and used libraries. */ static char *version_text[] = { "", "dklogger (part of the dktools collection, version " VERSNUMB ")", "Copyright (C) 2002-2010 - Dipl.-Ing. D. Krause", "http://dktools.sourceforge.net/", "", "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 copyright 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 Dirk Krause nor the names of other 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.", NULL }; /** Long options. */ static char *long_options[] = { /* 00 */ "h$elp", /* 01 */ "v$ersion", /* 02 */ "c$onfigure", /* 03 */ "u$nconfigure", /* 04 */ "r$eset", /* 05 */ "s$how-configuration", /* 06 */ "p$riority", NULL }; /** Text containing three spaces. */ static char three_spaces[] = { " " }; /** Show configuration. */ static void show_conf DK_P0() { dkapp_stdout(app, dklogger_str[9]); fputc('\n', stdout); fputs("-p", stdout); fputs(three_spaces, stdout); if(prio_string) { dkapp_stdout(app, prio_string); } else { dkapp_stdout(app, dklogger_str[8]); } fputs(three_spaces, stdout); dkapp_stdout(app, dklogger_str[10]); fputc('\n', stdout); } /** The main() function of the dklogger program. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ #if DK_HAVE_PROTO int main(int argc, char *argv[]) #else int main(argc,argv) int argc; char *argv[]; #endif { int helponly, versiononly; int xargc, lfd; char *msgbuf, *optarg, *thisarg, **xargv, **argptr; int priofound; int do_conf, do_unconf, do_showconf; size_t sz; char *errmsg[4]; #line 378 "dklogger.ctr" app = dkapp_open_ext1(argc,argv,packagename, sysconfdir, 0, 0); do_conf = do_unconf = do_showconf = 0; if(app) { dkapp_find_multi(app, dklogger_find, "dklogger"); if(dktcpip_start()) { get_config(); helponly = versiononly = 0; xargc = dkapp_get_argc(app); xargv = dkapp_get_argv(app); argptr = xargv; lfd = 0; argptr++; lfd++; if(xargc) { arguments = dk_new(CPTR,xargc); if(arguments) { for(argsused = 0; argsused < xargc; argsused++) { arguments[argsused] = NULL; } argsused = 0; priofound = 0; while(lfd < xargc) { thisarg = *argptr; if(*thisarg == '-') { thisarg++; switch(*thisarg) { case '-' : { thisarg++; optarg = dkstr_chr(thisarg, '='); if(optarg) { *(optarg++) = '\0'; } switch(dkstr_array_abbr(long_options, thisarg, '$', 1)) { case 0: { helponly = 1; } break; case 1: { versiononly = 1; } break; case 2: { do_conf = 1; } break; case 3: { do_conf = do_unconf = 1; } break; case 4: { prio_string = NULL; priofound = 0; } break; case 5: { do_showconf = 1; } break; case 6: { prio_string = optarg; if(optarg) priofound = 1; } break; } } break; case 'v' : { versiononly = 1; } break; case 'h' : { helponly = 1; } break; case 'p' : { thisarg++; if(!(*thisarg)) { if((lfd+1) < argc) { argptr++; lfd++; thisarg = *argptr; } } if(*thisarg) { if(!priofound) { prio_string = thisarg; priofound = 1; } } } break; case 'c': { do_conf = 1; } break; case 'u': { do_unconf = do_conf = 1; } break; case 'C': { do_showconf = 1; } break; case 'r': { prio_string = NULL; priofound = 0; } break; } } else { arguments[argsused++] = thisarg; } lfd++; argptr++; } if(helponly || versiononly || do_conf || do_showconf) { if(versiononly || helponly) { char **ptr; ptr = version_text; while(*ptr) { printf("%s\n", *(ptr++)); } printf("\nLibraries used:\n\n"); ptr = dklic_get(); while(*ptr) { fputs(*(ptr++), stdout); fputc('\n', stdout); } fputc('\n', stdout); if(helponly) { dkapp_help(app, "dklogger.txt", help_text); } } else { if(do_unconf) { dkapp_unconfigure(app); } else { if(do_conf) { if(prio_string) { dkapp_set_pref(app, pk_syslog_priority, prio_string); } else { dkapp_set_pref(app, pk_syslog_priority, ""); } } show_conf(); } } } else { /* if(helponly || versiononly) */ if(rh_used) { if(argsused) { sz = 0; for(lfd = 0; lfd < argsused; lfd++) { sz += strlen(arguments[lfd]); } sz += argsused; /* space before each string */ sz += 13; /* and finalizing byte */ msgbuf = dk_new(char,sz); if(msgbuf) { the_priority = dkslsupp_get_code(prio_string); sprintf(msgbuf, "<%d>", the_priority); for(lfd = 0; lfd < argsused; lfd++) { strcat(msgbuf, " "); strcat(msgbuf, arguments[lfd]); } send_the_message(msgbuf); dk_delete(msgbuf); msgbuf = NULL; } else { /* if(msgbuf) */ dkapp_err_memory(app,1,sz); } /* if(msgbuf) */ } else { /* if(argsused) */ errmsg[0] = dklogger_str[4]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } /* if(argsused) */ } else { /* if(rh_used) */ errmsg[0] = dklogger_str[5]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } /* if(rh_used) */ } /* if(helponly || versiononly) */ dk_delete(arguments); arguments = NULL; } else { /* if(arguments) */ dkapp_err_memory(app,sizeof(CPTR),xargc); } /* if(arguments) */ } else { /* if(xargc) */ errmsg[0] = dklogger_str[6]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } /* if(xargc) */ release_config(); (void)dktcpip_end(); } else { /* if(dktcpip_start()) */ errmsg[0] = dklogger_str[7]; dkapp_log_msg(app, DK_LOG_LEVEL_ERROR, errmsg, 1); } /* if(dktcpip_start()) */ dkapp_close(app); app = NULL; } else { fprintf(stderr, "Failed to initialize application!\n"); fflush(stderr); } exval = (exval ? 0 : 1); #line 551 "dklogger.ctr" exit(exval); return exval; }