[BACK]Return to acopm.c CVS log [TXT][DIR] Up to [local] / acopm / src

Annotation of acopm/src/acopm.c, Revision 1.1.1.1

1.1       bountyht    1: /*
                      2:  * Copyright (C) 2017 Aaron M. D. Jones <aaronmdjones@gmail.com>
                      3:  *
                      4:  * Redistribution and use in source and binary forms, with or without
                      5:  * modification, are permitted provided that the following
                      6:  * conditions are met:
                      7:  *
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  *
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * 3. Neither the name of the copyright holder nor the names of its
                     16:  *    contributors may be used to endorse or promote products derived from
                     17:  *    this software without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                     20:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
                     22:  * PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  *
                     24:  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
                     25:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     29:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     30:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     31:  * POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: #include "acopm-common.h"
                     35:
                     36: #include <assert.h> /* assert() */
                     37: #include <errno.h> /* errno */
                     38: #include <inttypes.h> /* PRIu16 */
                     39: #include <string.h> /* strerror() */
                     40: #include <strings.h> /* strcasecmp() */
                     41: #include <unistd.h> /* getuid(), geteuid() */
                     42:
                     43: #include "acopm.h" /* EVENT_LOG_* */
                     44: #include "check.h" /* acopm_check_user() */
                     45: #include "config.h" /* acopm_config_parse() */
                     46: #include "daemon.h" /* acopm_daemonise() */
                     47: #include "exec.h" /* acopm_exec_*() */
                     48: #include "options.h" /* acopm_parse_options(), ACOPM_OPT_* */
                     49: #include "signal.h" /* acopm_sighandle_*() */
                     50: #include "vars.h" /* global variable definitions */
                     51:
                     52: #include "irc/client.h" /* acopm_irc_*() */
                     53: #include "dnsbl/client.h" /* acopm_dnsbl_*() */
                     54: #include "proxy/client.h" /* acopm_proxy_*(), ACOPM_PROXY_TYPE_NONE */
                     55: #include "utils/log.h" /* acopm_log_*() */
                     56: #include "utils/misc.h" /* acopm_rng_*() */
                     57: #include "utils/siphash24.h" /* acopm_siphash24_setkey() */
                     58:
                     59: static char **argv_saved = NULL;
                     60: static int main_result = EXIT_FAILURE;
                     61:
                     62: static const char *const defconfig = ACOPM_CONFIG_FILE_DEFAULT;
                     63:
                     64: static inline bool acopm_attr_inline
                     65: acopm_siphash24_init(void)
                     66: {
                     67:        (void) acopm_log_debug("%s: initialising hash subsystem", __func__);
                     68:
                     69:        unsigned char sipkey24[SIPHASH24_KEY_LENGTH];
                     70:        if (! acopm_rng_buf(sipkey24, sizeof sipkey24))
                     71:                return false;
                     72:
                     73:        return acopm_siphash24_setkey(sipkey24);
                     74: }
                     75:
                     76: static void
                     77: acopm_connect_cb(struct acopm_irc_client *const restrict client, const char *const restrict nickname,
                     78:                  const char *const restrict address)
                     79: {
                     80:        assert(client == acopm_irc_client);
                     81:
                     82:        (void) client;
                     83:        (void) acopm_check_user(nickname, address);
                     84: }
                     85:
                     86: static void
                     87: acopm_command_cb(struct acopm_irc_client *const restrict client, const size_t argc, char **const restrict argv)
                     88: {
                     89:        if ((argc == 1 || argc == 2) && strcasecmp(argv[0], "EXIT") == 0)
                     90:        {
                     91:                main_result = EXIT_SUCCESS;
                     92:
                     93:                if (argc == 2)
                     94:                {
                     95:                        char *endptr = NULL;
                     96:                        const unsigned long int code = strtoul(argv[1], &endptr, 10);
                     97:
                     98:                        assert(endptr != NULL);
                     99:
                    100:                        if (code <= INT_MAX && endptr && ! *endptr)
                    101:                                main_result = (int) code;
                    102:                        else
                    103:                                (void) acopm_irc_log(client, "Exit code '%s' invalid, using %d", argv[1], main_result);
                    104:                }
                    105:
                    106:                (void) event_base_loopbreak(ev_base);
                    107:                return;
                    108:        }
                    109:
                    110:        if (argc == 1 && strcasecmp(argv[0], "PING") == 0)
                    111:        {
                    112:                (void) acopm_irc_log(client, "PONG");
                    113:                return;
                    114:        }
                    115: }
                    116:
                    117: static void acopm_attr_noreturn
                    118: acopm_restart_cb(void)
                    119: {
                    120:        (void) acopm_log_notice("Restarting");
                    121:        (void) execvp(argv_saved[0], argv_saved);
                    122:        (void) acopm_log_critical("%s: execvp: %s", __func__, strerror(errno));
                    123:        exit(1);
                    124: }
                    125:
                    126: static void acopm_attr_noreturn
                    127: acopm_event_crit_cb(const int err)
                    128: {
                    129:        (void) acopm_log_critical("%s: libevent has failed with fatal error %d", __func__, err);
                    130:
                    131:        acopm_restart_cb();
                    132: }
                    133:
                    134: static void
                    135: acopm_event_vlog_cb(const int ret, const char *const restrict msg)
                    136: {
                    137:        switch (ret)
                    138:        {
                    139:                case EVENT_LOG_ERR:
                    140:                        (void) acopm_log_error("%s: libevent: %s (%d)", __func__, msg, ret);
                    141:                        return;
                    142:
                    143:                case EVENT_LOG_WARN:
                    144:                        (void) acopm_log_warning("%s: libevent: %s (%d)", __func__, msg, ret);
                    145:                        return;
                    146:
                    147:                case EVENT_LOG_MSG:
                    148:                        (void) acopm_log_info("%s: libevent: %s (%d)", __func__, msg, ret);
                    149:                        return;
                    150:
                    151:                case EVENT_LOG_DEBUG:
                    152:                        (void) acopm_log_debug("%s: libevent: %s (%d)", __func__, msg, ret);
                    153:                        return;
                    154:        }
                    155: }
                    156:
                    157: static inline bool acopm_attr_inline
                    158: acopm_evloop_init(void)
                    159: {
                    160:        (void) acopm_log_debug("%s: initialising event loop", __func__);
                    161:
                    162:        if (! (ev_base = event_base_new()))
                    163:        {
                    164:                (void) acopm_log_critical("%s: event_base_new: %s", __func__, strerror(errno));
                    165:                return false;
                    166:        }
                    167:
                    168:        (void) event_set_fatal_callback(acopm_event_crit_cb);
                    169:        (void) event_set_log_callback(acopm_event_vlog_cb);
                    170:
                    171:        return true;
                    172: }
                    173:
                    174: static inline void acopm_attr_inline
                    175: acopm_evloop_free(void)
                    176: {
                    177:        if (! ev_base)
                    178:                return;
                    179:
                    180:        (void) acopm_log_debug("%s: destroying event loop", __func__);
                    181:        (void) event_base_free(ev_base);
                    182:        ev_base = NULL;
                    183: }
                    184:
                    185: int
                    186: main(const int argc, char **const restrict argv)
                    187: {
                    188:        if (! acopm_log_init())
                    189:                goto end;
                    190:
                    191:        switch (acopm_parse_options(argc, argv))
                    192:        {
                    193:                case ACOPM_OPT_PARSE_CONTINUE:
                    194:                        break;
                    195:
                    196:                case ACOPM_OPT_PARSE_EXIT_SUCCESS:
                    197:                        return EXIT_SUCCESS;
                    198:
                    199:                case ACOPM_OPT_PARSE_EXIT_FAILURE:
                    200:                        return EXIT_FAILURE;
                    201:        }
                    202:
                    203:        if ((getuid() == ((uid_t) 0)) || (geteuid() == ((uid_t) 0)))
                    204:        {
                    205:                (void) fprintf(stderr, "%s: do NOT run me as root!\n", argv[0]);
                    206:                return EXIT_FAILURE;
                    207:        }
                    208:
                    209:        argv_saved = argv;
                    210:
                    211: #if defined(PACKAGE_NAME) && defined(PACKAGE_VERSION)
                    212:        (void) acopm_log_info("This is %s version %s starting up", PACKAGE_NAME, PACKAGE_VERSION);
                    213: #endif
                    214:
                    215:        if (! *config_file && ! acopm_strset_buf(config_file, defconfig))
                    216:                (void) acopm_log_warning("%s: config file '%s' too long, truncated (BUG)", __func__, defconfig);
                    217:
                    218:        if (! acopm_evloop_init())
                    219:                goto end;
                    220:        if (! acopm_sighandle_init())
                    221:                goto end;
                    222:        if (! acopm_rng_init())
                    223:                goto end;
                    224:        if (! acopm_siphash24_init())
                    225:                goto end;
                    226:        if (! acopm_check_init())
                    227:                goto end;
                    228:        if (! (acopm_irc_client = acopm_irc_new(ev_base, acopm_connect_cb, acopm_command_cb, acopm_restart_cb)))
                    229:                goto end;
                    230:        if (! (acopm_dnsbl_client = acopm_dnsbl_new(ev_base)))
                    231:                goto end;
                    232:        if (! (acopm_proxy_client = acopm_proxy_new(ev_base)))
                    233:                goto end;
                    234:        if (! acopm_config_parse())
                    235:                goto end;
                    236:        if (! acopm_exec_init())
                    237:                goto end;
                    238:        if (! acopm_irc_connect(acopm_irc_client))
                    239:                goto end;
                    240:        if (! acopm_daemonise())
                    241:                goto end;
                    242:
                    243:        (void) acopm_log_info("Entering event loop");
                    244:        (void) event_base_dispatch(ev_base);
                    245:
                    246:        if (main_result == EXIT_SUCCESS)
                    247:                (void) acopm_log_info("Leaving event loop");
                    248:        else
                    249:                (void) acopm_log_warning("Leaving event loop");
                    250:
                    251: end:
                    252:        (void) acopm_exec_free();
                    253:
                    254:        if (acopm_proxy_client)
                    255:                (void) acopm_proxy_free(acopm_proxy_client);
                    256:
                    257:        if (acopm_dnsbl_client)
                    258:                (void) acopm_dnsbl_free(acopm_dnsbl_client);
                    259:
                    260:        if (acopm_irc_client)
                    261:                (void) acopm_irc_free(acopm_irc_client);
                    262:
                    263:        (void) acopm_check_free();
                    264:        (void) acopm_rng_free();
                    265:        (void) acopm_sighandle_free();
                    266:        (void) acopm_evloop_free();
                    267:        (void) acopm_log_free();
                    268:
                    269:        return main_result;
                    270: }

CVSweb