Experimental IRC client, daemon and bot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

797 lines
21KB

  1. /*
  2. * kike.c: the experimental IRC daemon
  3. *
  4. * Copyright (c) 2014, Přemysl Janouch <p.janouch@gmail.com>
  5. * All rights reserved.
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  14. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  16. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  17. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. *
  19. */
  20. #define PROGRAM_NAME "kike"
  21. #define PROGRAM_VERSION "alpha"
  22. #include "common.c"
  23. // --- Configuration (application-specific) ------------------------------------
  24. static struct config_item g_config_table[] =
  25. {
  26. { "server_name", NULL, "Server name" },
  27. { "bind_host", NULL, "Address of the IRC server" },
  28. { "bind_port", "6667", "Port of the IRC server" },
  29. { "ssl_cert", NULL, "Server SSL certificate (PEM)" },
  30. { "ssl_key", NULL, "Server SSL private key (PEM)" },
  31. { "max_connections", NULL, "Maximum client connections" },
  32. { NULL, NULL, NULL }
  33. };
  34. // --- Signals -----------------------------------------------------------------
  35. static int g_signal_pipe[2]; ///< A pipe used to signal... signals
  36. /// Program termination has been requested by a signal
  37. static volatile sig_atomic_t g_termination_requested;
  38. static void
  39. sigterm_handler (int signum)
  40. {
  41. (void) signum;
  42. g_termination_requested = true;
  43. int original_errno = errno;
  44. if (write (g_signal_pipe[1], "t", 1) == -1)
  45. soft_assert (errno == EAGAIN);
  46. errno = original_errno;
  47. }
  48. static void
  49. setup_signal_handlers (void)
  50. {
  51. if (pipe (g_signal_pipe) == -1)
  52. {
  53. print_fatal ("pipe: %s", strerror (errno));
  54. exit (EXIT_FAILURE);
  55. }
  56. set_cloexec (g_signal_pipe[0]);
  57. set_cloexec (g_signal_pipe[1]);
  58. // So that the pipe cannot overflow; it would make write() block within
  59. // the signal handler, which is something we really don't want to happen.
  60. // The same holds true for read().
  61. set_blocking (g_signal_pipe[0], false);
  62. set_blocking (g_signal_pipe[1], false);
  63. signal (SIGPIPE, SIG_IGN);
  64. struct sigaction sa;
  65. sa.sa_flags = SA_RESTART;
  66. sigemptyset (&sa.sa_mask);
  67. sa.sa_handler = sigterm_handler;
  68. if (sigaction (SIGINT, &sa, NULL) == -1
  69. || sigaction (SIGTERM, &sa, NULL) == -1)
  70. {
  71. print_error ("sigaction: %s", strerror (errno));
  72. exit (EXIT_FAILURE);
  73. }
  74. }
  75. // --- Application data --------------------------------------------------------
  76. enum
  77. {
  78. IRC_USER_MODE_INVISIBLE = (1 << 0),
  79. IRC_USER_MODE_RX_WALLOPS = (1 << 1),
  80. IRC_USER_MODE_RESTRICTED = (1 << 2),
  81. IRC_USER_MODE_OPERATOR = (1 << 3),
  82. IRC_USER_MODE_RX_SERVER_NOTICES = (1 << 4)
  83. };
  84. struct connection
  85. {
  86. struct connection *next; ///< The next link in a chain
  87. struct connection *prev; ///< The previous link in a chain
  88. struct server_context *ctx; ///< Server context
  89. int socket_fd; ///< The TCP socket
  90. struct str read_buffer; ///< Unprocessed input
  91. struct str write_buffer; ///< Output yet to be sent out
  92. unsigned initialized : 1; ///< Has any data been received yet?
  93. unsigned ssl_rx_want_tx : 1; ///< SSL_read() wants to write
  94. unsigned ssl_tx_want_rx : 1; ///< SSL_write() wants to read
  95. SSL_CTX *ssl_ctx; ///< SSL context
  96. SSL *ssl; ///< SSL connection
  97. char *nickname; ///< IRC nickname (main identifier)
  98. char *username; ///< IRC username
  99. char *fullname; ///< IRC fullname (e-mail)
  100. char *hostname; ///< Hostname shown to the network
  101. unsigned mode; ///< User's mode
  102. char *away_message; ///< Away message
  103. };
  104. static void
  105. connection_init (struct connection *self)
  106. {
  107. memset (self, 0, sizeof *self);
  108. self->socket_fd = -1;
  109. str_init (&self->read_buffer);
  110. str_init (&self->write_buffer);
  111. }
  112. static void
  113. connection_free (struct connection *self)
  114. {
  115. if (!soft_assert (self->socket_fd == -1))
  116. xclose (self->socket_fd);
  117. if (self->ssl_ctx)
  118. SSL_CTX_free (self->ssl_ctx);
  119. if (self->ssl)
  120. SSL_free (self->ssl);
  121. str_free (&self->read_buffer);
  122. str_free (&self->write_buffer);
  123. free (self->nickname);
  124. free (self->username);
  125. free (self->fullname);
  126. free (self->hostname);
  127. free (self->away_message);
  128. }
  129. enum
  130. {
  131. IRC_CHAN_MODE_INVITE_ONLY = (1 << 0),
  132. IRC_CHAN_MODE_MODERATED = (1 << 1),
  133. IRC_CHAN_MODE_NO_OUTSIDE_MSGS = (1 << 2),
  134. IRC_CHAN_MODE_SECRET = (1 << 3),
  135. IRC_CHAN_MODE_PRIVATE = (1 << 4),
  136. IRC_CHAN_MODE_PROTECTED_TOPIC = (1 << 5),
  137. IRC_CHAN_MODE_QUIET = (1 << 6)
  138. };
  139. struct channel
  140. {
  141. struct server_context *ctx; ///< Server context
  142. char *name; ///< Channel name
  143. unsigned modes; ///< Channel modes
  144. char *key; ///< Channel key
  145. long user_limit; ///< User limit or -1
  146. struct str_vector ban_list; ///< Ban list
  147. struct str_vector exception_list; ///< Exceptions from bans
  148. struct str_vector invite_list; ///< Exceptions from +I
  149. };
  150. static void
  151. channel_init (struct channel *self)
  152. {
  153. memset (self, 0, sizeof *self);
  154. str_vector_init (&self->ban_list);
  155. str_vector_init (&self->exception_list);
  156. str_vector_init (&self->invite_list);
  157. }
  158. static void
  159. channel_free (struct channel *self)
  160. {
  161. free (self->name);
  162. free (self->key);
  163. str_vector_free (&self->ban_list);
  164. str_vector_free (&self->exception_list);
  165. str_vector_free (&self->invite_list);
  166. }
  167. struct server_context
  168. {
  169. struct str_map config; ///< Server configuration
  170. int listen_fd; ///< Listening socket FD
  171. struct connection *clients; ///< Client connections
  172. struct str_map users; ///< Maps nicknames to connections
  173. struct str_map channels; ///< Maps channel names to data
  174. struct poller poller; ///< Manages polled description
  175. bool polling; ///< The event loop is running
  176. };
  177. static void
  178. server_context_init (struct server_context *self)
  179. {
  180. str_map_init (&self->config);
  181. self->config.free = free;
  182. load_config_defaults (&self->config, g_config_table);
  183. self->listen_fd = -1;
  184. self->clients = NULL;
  185. str_map_init (&self->users);
  186. // TODO: set channel_free() as the free function?
  187. str_map_init (&self->channels);
  188. poller_init (&self->poller);
  189. self->polling = false;
  190. }
  191. static void
  192. server_context_free (struct server_context *self)
  193. {
  194. str_map_free (&self->config);
  195. if (self->listen_fd != -1)
  196. xclose (self->listen_fd);
  197. // TODO: terminate the connections properly before this is called
  198. struct connection *link, *tmp;
  199. for (link = self->clients; link; link = tmp)
  200. {
  201. tmp = link->next;
  202. connection_free (link);
  203. free (link);
  204. }
  205. str_map_free (&self->users);
  206. str_map_free (&self->channels);
  207. poller_free (&self->poller);
  208. }
  209. // --- Main program ------------------------------------------------------------
  210. static size_t network_error_domain_tag;
  211. #define NETWORK_ERROR (error_resolve_domain (&network_error_domain_tag))
  212. enum
  213. {
  214. NETWORK_ERROR_INVALID_CONFIGURATION,
  215. NETWORK_ERROR_FAILED
  216. };
  217. static bool
  218. irc_autodetect_ssl (struct connection *conn)
  219. {
  220. // Trivial SSL/TLS autodetection. The first block of data returned by
  221. // recv() must be at least three bytes long for this to work reliably,
  222. // but that should not pose a problem in practice.
  223. //
  224. // SSL2: 1xxx xxxx | xxxx xxxx | <1>
  225. // (message length) (client hello)
  226. // SSL3/TLS: <22> | <3> | xxxx xxxx
  227. // (handshake)| (protocol version)
  228. //
  229. // Such byte sequences should never occur at the beginning of regular IRC
  230. // communication, which usually begins with USER/NICK/PASS/SERVICE.
  231. char buf[3];
  232. start:
  233. switch (recv (conn->socket_fd, buf, sizeof buf, MSG_PEEK))
  234. {
  235. case 3:
  236. if ((buf[0] & 0x80) && buf[2] == 1)
  237. return true;
  238. case 2:
  239. if (buf[0] == 22 && buf[1] == 3)
  240. return true;
  241. break;
  242. case 1:
  243. if (buf[0] == 22)
  244. return true;
  245. break;
  246. case 0:
  247. break;
  248. default:
  249. if (errno == EINTR)
  250. goto start;
  251. }
  252. return false;
  253. }
  254. static int
  255. irc_ssl_verify_callback (int verify_ok, X509_STORE_CTX *ctx)
  256. {
  257. (void) verify_ok;
  258. (void) ctx;
  259. // We only want to provide additional privileges based on the client's
  260. // certificate, so let's not terminate the connection because of a failure.
  261. return 1;
  262. }
  263. static bool
  264. irc_initialize_ssl (struct connection *conn)
  265. {
  266. struct server_context *ctx = conn->ctx;
  267. conn->ssl_ctx = SSL_CTX_new (SSLv23_server_method ());
  268. if (!conn->ssl_ctx)
  269. goto error_ssl_1;
  270. SSL_CTX_set_verify (conn->ssl_ctx,
  271. SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, irc_ssl_verify_callback);
  272. // XXX: maybe we should call SSL_CTX_set_options() for some workarounds
  273. conn->ssl = SSL_new (conn->ssl_ctx);
  274. if (!conn->ssl)
  275. goto error_ssl_2;
  276. const char *ssl_cert = str_map_find (&ctx->config, "ssl_cert");
  277. if (ssl_cert
  278. && !SSL_CTX_use_certificate_chain_file (conn->ssl_ctx, ssl_cert))
  279. {
  280. // XXX: perhaps we should read the file ourselves for better messages
  281. print_error ("%s: %s", "setting the SSL client certificate failed",
  282. ERR_error_string (ERR_get_error (), NULL));
  283. }
  284. const char *ssl_key = str_map_find (&ctx->config, "ssl_key");
  285. if (ssl_key
  286. && !SSL_use_PrivateKey_file (conn->ssl, ssl_key, SSL_FILETYPE_PEM))
  287. {
  288. // XXX: perhaps we should read the file ourselves for better messages
  289. print_error ("%s: %s", "setting the SSL private key failed",
  290. ERR_error_string (ERR_get_error (), NULL));
  291. }
  292. // TODO: SSL_check_private_key(conn->ssl)? It is has probably already been
  293. // checked by SSL_use_PrivateKey_file() above.
  294. SSL_set_accept_state (conn->ssl);
  295. if (!SSL_set_fd (conn->ssl, conn->socket_fd))
  296. goto error_ssl_3;
  297. // Gah, spare me your awkward semantics, I just want to push data!
  298. // XXX: do we want SSL_MODE_AUTO_RETRY as well? I guess not.
  299. SSL_set_mode (conn->ssl,
  300. SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
  301. return true;
  302. error_ssl_3:
  303. SSL_free (conn->ssl);
  304. conn->ssl = NULL;
  305. error_ssl_2:
  306. SSL_CTX_free (conn->ssl_ctx);
  307. conn->ssl_ctx = NULL;
  308. error_ssl_1:
  309. // XXX: these error strings are really nasty; also there could be
  310. // multiple errors on the OpenSSL stack.
  311. print_error ("%s: %s", "could not initialize SSL",
  312. ERR_error_string (ERR_get_error (), NULL));
  313. return false;
  314. }
  315. static void
  316. connection_abort (struct connection *conn, const char *reason)
  317. {
  318. // TODO: send a QUIT message with `reason' || "Client exited"
  319. (void) reason;
  320. // TODO: do further cleanup if the client has successfully registered
  321. struct server_context *ctx = conn->ctx;
  322. ssize_t i = poller_find_by_fd (&ctx->poller, conn->socket_fd);
  323. if (i != -1)
  324. poller_remove_at_index (&ctx->poller, i);
  325. xclose (conn->socket_fd);
  326. conn->socket_fd = -1;
  327. connection_free (conn);
  328. LIST_UNLINK (ctx->clients, conn);
  329. free (conn);
  330. }
  331. static void
  332. irc_process_message (const struct irc_message *msg,
  333. const char *raw, void *user_data)
  334. {
  335. struct connection *conn = user_data;
  336. // TODO
  337. }
  338. static bool
  339. irc_try_read (struct connection *conn)
  340. {
  341. // TODO
  342. return false;
  343. }
  344. static bool
  345. irc_try_read_ssl (struct connection *conn)
  346. {
  347. if (conn->ssl_tx_want_rx)
  348. return true;
  349. struct str *buf = &conn->read_buffer;
  350. conn->ssl_rx_want_tx = false;
  351. while (true)
  352. {
  353. str_ensure_space (buf, 512);
  354. int n_read = SSL_read (conn->ssl, buf->str + buf->len,
  355. buf->alloc - buf->len - 1 /* null byte */);
  356. const char *error_info = NULL;
  357. switch (xssl_get_error (conn->ssl, n_read, &error_info))
  358. {
  359. case SSL_ERROR_NONE:
  360. buf->str[buf->len += n_read] = '\0';
  361. // TODO: discard characters above the 512 character limit
  362. irc_process_buffer (buf, irc_process_message, conn);
  363. continue;
  364. case SSL_ERROR_ZERO_RETURN:
  365. connection_abort (conn, NULL);
  366. return false;
  367. case SSL_ERROR_WANT_READ:
  368. return true;
  369. case SSL_ERROR_WANT_WRITE:
  370. conn->ssl_rx_want_tx = true;
  371. return false;
  372. case XSSL_ERROR_TRY_AGAIN:
  373. continue;
  374. default:
  375. print_debug ("%s: %s: %s", __func__, "SSL_read", error_info);
  376. connection_abort (conn, error_info);
  377. return false;
  378. }
  379. }
  380. }
  381. static bool
  382. irc_try_write (struct connection *conn)
  383. {
  384. // TODO
  385. return false;
  386. }
  387. static bool
  388. irc_try_write_ssl (struct connection *conn)
  389. {
  390. if (conn->ssl_rx_want_tx)
  391. return true;
  392. struct str *buf = &conn->write_buffer;
  393. conn->ssl_tx_want_rx = false;
  394. while (buf->len)
  395. {
  396. int n_written = SSL_write (conn->ssl, buf->str, buf->len);
  397. const char *error_info = NULL;
  398. switch (xssl_get_error (conn->ssl, n_written, &error_info))
  399. {
  400. case SSL_ERROR_NONE:
  401. str_remove_slice (buf, 0, n_written);
  402. continue;
  403. case SSL_ERROR_ZERO_RETURN:
  404. connection_abort (conn, NULL);
  405. return false;
  406. case SSL_ERROR_WANT_WRITE:
  407. return true;
  408. case SSL_ERROR_WANT_READ:
  409. conn->ssl_tx_want_rx = true;
  410. return false;
  411. case XSSL_ERROR_TRY_AGAIN:
  412. continue;
  413. default:
  414. print_debug ("%s: %s: %s", __func__, "SSL_write", error_info);
  415. connection_abort (conn, error_info);
  416. return false;
  417. }
  418. }
  419. return true;
  420. }
  421. static void
  422. on_irc_client_ready (const struct pollfd *pfd, void *user_data)
  423. {
  424. // XXX: check/load `ssl_cert' and `ssl_key' earlier?
  425. struct connection *conn = user_data;
  426. if (!conn->initialized)
  427. {
  428. hard_assert (pfd->events == POLLIN);
  429. // XXX: what with the error from irc_initialize_ssl()?
  430. if (irc_autodetect_ssl (conn) && !irc_initialize_ssl (conn))
  431. {
  432. connection_abort (conn, NULL);
  433. return;
  434. }
  435. conn->initialized = true;
  436. }
  437. // FIXME: aborting a connection inside try_read() will fuck things up
  438. int new_events = 0;
  439. if (conn->ssl)
  440. {
  441. // Reads may want to write, writes may want to read, poll() may
  442. // return unexpected things in `revents'... let's try both
  443. irc_try_read_ssl (conn) && irc_try_write_ssl (conn);
  444. new_events |= POLLIN;
  445. if (conn->write_buffer.len || conn->ssl_rx_want_tx)
  446. new_events |= POLLOUT;
  447. // While we're waiting for an opposite event, we ignore the original
  448. if (conn->ssl_rx_want_tx) new_events &= ~POLLIN;
  449. if (conn->ssl_tx_want_rx) new_events &= ~POLLOUT;
  450. }
  451. else
  452. {
  453. irc_try_read (conn) && irc_try_write (conn);
  454. new_events |= POLLIN;
  455. if (conn->write_buffer.len)
  456. new_events |= POLLOUT;
  457. }
  458. hard_assert (new_events != 0);
  459. if (pfd->events != new_events)
  460. poller_set (&conn->ctx->poller, conn->socket_fd, new_events,
  461. (poller_dispatcher_func) on_irc_client_ready, conn);
  462. }
  463. static void
  464. on_irc_connection_available (const struct pollfd *pfd, void *user_data)
  465. {
  466. (void) pfd;
  467. struct server_context *ctx = user_data;
  468. // TODO: stop accepting new connections when `max_connections' is reached
  469. while (true)
  470. {
  471. // XXX: `struct sockaddr_storage' is not the most portable thing
  472. struct sockaddr_storage peer;
  473. socklen_t peer_len = sizeof peer;
  474. int fd = accept (ctx->listen_fd, (struct sockaddr *) &peer, &peer_len);
  475. if (fd == -1)
  476. {
  477. if (errno == EAGAIN)
  478. break;
  479. if (errno == EINTR)
  480. continue;
  481. if (errno == ECONNABORTED)
  482. continue;
  483. // TODO: handle resource exhaustion (EMFILE, ENFILE) specially
  484. // (stop accepting new connections and wait until we close some).
  485. print_fatal ("%s: %s", "accept", strerror (errno));
  486. // FIXME: handle this better, bring the server down cleanly.
  487. exit (EXIT_FAILURE);
  488. }
  489. char host[NI_MAXHOST] = "unknown", port[NI_MAXSERV] = "unknown";
  490. int err = getnameinfo ((struct sockaddr *) &peer, peer_len,
  491. host, sizeof host, port, sizeof port, AI_NUMERICSERV);
  492. if (err)
  493. print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
  494. print_debug ("accepted connection from %s:%s", host, port);
  495. struct connection *conn = xmalloc (sizeof *conn);
  496. connection_init (conn);
  497. conn->socket_fd = fd;
  498. conn->hostname = xstrdup (host);
  499. LIST_PREPEND (ctx->clients, conn);
  500. // TODO: set a timeout on the socket, something like 3 minutes, then we
  501. // should terminate the connection.
  502. poller_set (&ctx->poller, conn->socket_fd, POLLIN,
  503. (poller_dispatcher_func) on_irc_client_ready, conn);
  504. }
  505. }
  506. static bool
  507. irc_listen (struct server_context *ctx, struct error **e)
  508. {
  509. const char *bind_host = str_map_find (&ctx->config, "bind_host");
  510. const char *bind_port = str_map_find (&ctx->config, "bind_port");
  511. hard_assert (bind_port != NULL); // We have a default value for this
  512. struct addrinfo gai_hints, *gai_result, *gai_iter;
  513. memset (&gai_hints, 0, sizeof gai_hints);
  514. gai_hints.ai_socktype = SOCK_STREAM;
  515. gai_hints.ai_flags = AI_PASSIVE;
  516. int err = getaddrinfo (bind_host, bind_port, &gai_hints, &gai_result);
  517. if (err)
  518. {
  519. error_set (e, NETWORK_ERROR, NETWORK_ERROR_FAILED, "%s: %s: %s",
  520. "network setup failed", "getaddrinfo", gai_strerror (err));
  521. return false;
  522. }
  523. int sockfd;
  524. char real_host[NI_MAXHOST], real_port[NI_MAXSERV];
  525. for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
  526. {
  527. sockfd = socket (gai_iter->ai_family,
  528. gai_iter->ai_socktype, gai_iter->ai_protocol);
  529. if (sockfd == -1)
  530. continue;
  531. set_cloexec (sockfd);
  532. int yes = 1;
  533. soft_assert (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE,
  534. &yes, sizeof yes) != -1);
  535. soft_assert (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR,
  536. &yes, sizeof yes) != -1);
  537. real_host[0] = real_port[0] = '\0';
  538. err = getnameinfo (gai_iter->ai_addr, gai_iter->ai_addrlen,
  539. real_host, sizeof real_host, real_port, sizeof real_port,
  540. NI_NUMERICHOST | NI_NUMERICSERV);
  541. if (err)
  542. print_debug ("%s: %s", "getnameinfo", gai_strerror (err));
  543. if (bind (sockfd, gai_iter->ai_addr, gai_iter->ai_addrlen))
  544. print_error ("bind() to %s:%s failed: %s",
  545. real_host, real_port, strerror (errno));
  546. else if (listen (sockfd, 16 /* arbitrary number */))
  547. print_error ("listen() at %s:%s failed: %s",
  548. real_host, real_port, strerror (errno));
  549. else
  550. break;
  551. xclose (sockfd);
  552. }
  553. freeaddrinfo (gai_result);
  554. if (!gai_iter)
  555. {
  556. error_set (e, NETWORK_ERROR, NETWORK_ERROR_FAILED,
  557. "network setup failed");
  558. return false;
  559. }
  560. ctx->listen_fd = sockfd;
  561. poller_set (&ctx->poller, ctx->listen_fd, POLLIN,
  562. (poller_dispatcher_func) on_irc_connection_available, ctx);
  563. print_status ("listening at %s:%s", real_host, real_port);
  564. return true;
  565. }
  566. static void
  567. on_signal_pipe_readable (const struct pollfd *fd, struct server_context *ctx)
  568. {
  569. char *dummy;
  570. (void) read (fd->fd, &dummy, 1);
  571. #if 0
  572. // TODO
  573. if (g_termination_requested && !ctx->quitting)
  574. {
  575. initiate_quit (ctx);
  576. }
  577. #endif
  578. }
  579. static void
  580. print_usage (const char *program_name)
  581. {
  582. fprintf (stderr,
  583. "Usage: %s [OPTION]...\n"
  584. "Experimental IRC server.\n"
  585. "\n"
  586. " -d, --debug run in debug mode (do not daemonize)\n"
  587. " -h, --help display this help and exit\n"
  588. " -V, --version output version information and exit\n"
  589. " --write-default-cfg [filename]\n"
  590. " write a default configuration file and exit\n",
  591. program_name);
  592. }
  593. int
  594. main (int argc, char *argv[])
  595. {
  596. const char *invocation_name = argv[0];
  597. struct error *e = NULL;
  598. static struct option opts[] =
  599. {
  600. { "debug", no_argument, NULL, 'd' },
  601. { "help", no_argument, NULL, 'h' },
  602. { "version", no_argument, NULL, 'V' },
  603. { "write-default-cfg", optional_argument, NULL, 'w' },
  604. { NULL, 0, NULL, 0 }
  605. };
  606. while (1)
  607. {
  608. int c, opt_index;
  609. c = getopt_long (argc, argv, "dhV", opts, &opt_index);
  610. if (c == -1)
  611. break;
  612. switch (c)
  613. {
  614. case 'd':
  615. g_debug_mode = true;
  616. break;
  617. case 'h':
  618. print_usage (invocation_name);
  619. exit (EXIT_SUCCESS);
  620. case 'V':
  621. printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
  622. exit (EXIT_SUCCESS);
  623. case 'w':
  624. {
  625. char *filename = write_default_config (optarg, g_config_table, &e);
  626. if (!filename)
  627. {
  628. print_fatal ("%s", e->message);
  629. error_free (e);
  630. exit (EXIT_FAILURE);
  631. }
  632. print_status ("configuration written to `%s'", filename);
  633. free (filename);
  634. exit (EXIT_SUCCESS);
  635. }
  636. default:
  637. print_fatal ("error in options");
  638. exit (EXIT_FAILURE);
  639. }
  640. }
  641. print_status (PROGRAM_NAME " " PROGRAM_VERSION " starting");
  642. setup_signal_handlers ();
  643. SSL_library_init ();
  644. atexit (EVP_cleanup);
  645. SSL_load_error_strings ();
  646. // XXX: ERR_load_BIO_strings()? Anything else?
  647. atexit (ERR_free_strings);
  648. struct server_context ctx;
  649. server_context_init (&ctx);
  650. if (!read_config_file (&ctx.config, &e))
  651. {
  652. print_fatal ("error loading configuration: %s", e->message);
  653. error_free (e);
  654. exit (EXIT_FAILURE);
  655. }
  656. poller_set (&ctx.poller, g_signal_pipe[0], POLLIN,
  657. (poller_dispatcher_func) on_signal_pipe_readable, &ctx);
  658. if (!irc_listen (&ctx, &e))
  659. {
  660. print_error ("%s", e->message);
  661. error_free (e);
  662. exit (EXIT_FAILURE);
  663. }
  664. // TODO: daemonize
  665. ctx.polling = true;
  666. while (ctx.polling)
  667. poller_run (&ctx.poller);
  668. server_context_free (&ctx);
  669. return EXIT_SUCCESS;
  670. }