/* This file is part of GNU Pies.
   Copyright (C) 2008-2019 Sergey Poznyakoff

   GNU Pies is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   GNU Pies 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Pies.  If not, see <http://www.gnu.org/licenses/>. */

enum prog_type
  {
    TYPE_COMPONENT,
    TYPE_REDIRECTOR,
    TYPE_COMMAND
  };

enum prog_status
  {
    status_stopped,    /* Component is stopped. */
    status_running,    /* Component is running */
    status_listener,   /* Component is an inetd listener */
    status_sleeping,   /* Component is sleeping. An attempt to start it will
			  be made at prog->v.p.timestamp + SLEEPTIME */
    status_stopping,   /* Component is being stopped */
    status_finished,   /* A "once" or "startup" component has finished */
  };

struct conn_class
{
  const char *tag;
  union pies_sockaddr_storage sa_storage;
  size_t sa_len;
  size_t count;
};

struct prog
{
  struct prog *next, *prev;
  enum prog_type type;
  pid_t pid;             /* PID */
  int active :1;         /* The prog is active */
  int wait   :1;         /* Wait for this prog to terminate */
  int stop   :1;         /* Stop this prog */
  union
  {
    struct
    {
      struct component *comp;
      int socket;
      struct prog *redir[2];   /* Pointers to redirectors */
      time_t timestamp;        /* Time of last startup */
      size_t failcount;        /* Number of failed starts since timestamp */
      enum prog_status status; /* Current component status */
      /* If status == status_listener: */
      size_t num_instances;    /* Number of running instances */
      /* If comp->type == pies_comp_inetd && status == status_running */
      struct prog *listener;
      union pies_sockaddr_storage sa_storage;
      size_t sa_len;
      struct conn_class *cclass;
    } p;
    
    struct
    {
      char *tag;
      struct component *comp;
      struct prog *master;
    } r;

    struct
    {
      char *tag;
      char *command;
    } c;
  } v;
};

#define IS_COMPONENT(p) ((p)->type == TYPE_COMPONENT)
#define IS_ACTIVE_COMPONENT(prog) (IS_COMPONENT(prog) && (prog)->active)

struct prog *progman_locate (const char *name);
int progman_foreach (int (*filter) (struct prog *, void *data), void *data);
void prog_stop (struct prog *prog, int sig);
void progman_stop_component (struct prog **prog);

char const *prog_tag (struct prog const *prog);

int prog_activate_listener (struct prog *prog);
void prog_deactivate_listener (struct prog *prog);
