/*
 * Yet another daemon library especially designed to be used
 * with libsxmp based daemons.
 *
 * (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
 *
 * libsxmp is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libsxmp is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <dlfcn.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>

#include <tdata/usrtc.h>
#include <sexpr/sexp.h>

#include <ydaemon/ydaemon.h>

int yd_mainloop(yd_context_t *ctx)
{
  usrtc_node_t *node = NULL;
  yd_mod_t *mod;

  /* we will locked here */
  pthread_mutex_lock(&ctx->looplock);

  /* if we're here ... somebody decide to end the loop */
  yd_mod_ctx_wrlock(ctx);
  for(node = usrtc_last(ctx->modules); ;node = usrtc_prev(ctx->modules, node)) {
    mod = (yd_mod_t *)usrtc_node_getdata(node);
    mod->shutdown(ctx);

    /* for() */
    if(node == usrtc_first(ctx->modules)) break;
  }
  yd_mod_ctx_unlock(ctx);

  return 0;
}

void yd_mainloop_exit(yd_context_t *ctx)
{
  pthread_mutex_unlock(&ctx->looplock);

  return;
}

/*
 * daemon workout
 */

void yddaemon(yd_context_t *ctx)
{
  pid_t pid;
  ydc_conf_val_t *rval;

  /* fork the first time to detach the controlling terminal
   * and avoid to be a group leader.
   */
  pid = fork();
  if(pid < 0) exit(EXIT_FAILURE); /* something goes wrong ... */
  if(pid > 0) exit(EXIT_SUCCESS); /* parent can take a rest */

  /* try to become a session leader */
  if(setsid() < 0) exit(EXIT_FAILURE); /* something goes wrong ... */

  /* ignore fucking signals */
  signal(SIGCHLD, SIG_IGN);
  signal(SIGHUP, SIG_IGN);
  signal(SIGPIPE, SIG_IGN);

  /* fork the second time, to avoid be a session leader - the goal is
   * regain a terminal control never.
   */
  pid = fork();
  if(pid < 0) exit(EXIT_FAILURE); /* something goes wrong ... */
  if(pid > 0) exit(EXIT_SUCCESS); /* parent can take a rest */

  /* reset mask */
  umask(0);

  /* change working directory to root */
  //  chdir("/");
#if 0
  /* test and change if set */
  if(!ydc_conf_get_val(ctx->zvalues, "daemon/workingdir", &rval)) {
    if(rval->type == STRING) chdir((const char *)rval->value);
  }
#endif

  /* let's a deal */
  fclose(stdin);
  fclose(stderr);
  fclose(stdout);

  /* if oe - mean we allowing to write a lof file thru standard prints ... */
  stdin = fopen("/dev/null", "r");
#if 0
  if(ctx->logcontext->se && !ydc_conf_get_val(ctx->zvalues, "daemon/logfile", &rval)) {
    if(rval->type == STRING) {
      stdout = fopen((char *)rval->value, "a");
      stderr = fopen((char *)rval->value, "a");
    }
  } else {
#endif
    stdout = fopen("/dev/null", "a");
    stderr = fopen("/dev/null", "a");
#if 0
  }
#endif
  ctx->daemon = 1;

  return;
}