/*
 * userv - daemon.h
 * definitions used in the daemon's source code
 *
 * userv is copyright Ian Jackson and other contributors.
 * See README for full authorship information.
 *
 * This 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 userv; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DAEMON_H
#define DAEMON_H

#include <sys/types.h>

#define RESET_CONFIGURATION " \n\
  cd ~/                       \n\
  reject                      \n\
  no-set-environment          \n\
  suppress-args               \n\
  allow-fd 0 read             \n\
  allow-fd 1-2 write          \n\
  reject-fd 3-                \n\
  disconnect-hup              \n\
  include-lookup-quote-new    \n\
"

#ifndef SYSTEMCONFIGDIR
# ifdef DEBUG
#  define SYSTEMCONFIGDIR             "slash-etc"
# else
#  define SYSTEMCONFIGDIR             "/etc"
# endif
#endif

#ifndef DEFAULTPATH_USER
# define DEFAULTPATH_USER "/usr/local/bin:/bin:/usr/bin"
#endif

#ifndef DEFAULTPATH_ROOT
# define DEFAULTPATH_ROOT "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
#endif
  
#ifndef SETENVIRONMENT
# define SETENVIRONMENT "environment"
#endif

#define USERRCFILE                  "rc"
#define SYSTEMUSERVCONFIGDIR        "userv"
#define SHELLLIST                   "shells"
#define SYSTEMRCFILEDEFAULT         "system.default"
#define SYSTEMRCFILEOVERRIDE        "system.override"
#define NONEINCLUDELOOKUP           ":none"
#define DEFAULTINCLUDELOOKUP        ":default"
#define EMPTYINCLUDELOOKUP          ":empty"

#define USERCONFIGDIRBASE           SYSTEMUSERVCONFIGDIR
#define USERCONFIGDIR               "." USERCONFIGDIRBASE
#define USERUSERVCONFIGPATH         "~/" USERCONFIGDIR
#define USERRCFILEPATH              USERUSERVCONFIGPATH "/" USERRCFILE
#define SYSTEMUSERVCONFIGPATH       SYSTEMCONFIGDIR "/" SYSTEMUSERVCONFIGDIR
#define SYSTEMRCFILEDEFAULTPATH     SYSTEMUSERVCONFIGPATH "/" SYSTEMRCFILEDEFAULT
#define SYSTEMRCFILEOVERRIDEPATH    SYSTEMUSERVCONFIGPATH "/" SYSTEMRCFILEOVERRIDE
#define SHELLLISTPATH               SYSTEMCONFIGDIR "/" SHELLLIST
#define SETENVIRONMENTPATH          SYSTEMCONFIGDIR "/" SETENVIRONMENT

#define USERVD_LOGIDENT "uservd"
#define USERVDCHECK_LOGIDENT "uservd/check"
#define USERVD_LOGFACILITY LOG_DAEMON
#define DEFUSERLOGFACILITY LOG_USER
#define DEFUSERLOGLEVEL LOG_ERR

#define TOPLEVEL_CONFIGURATION "                   \n\
  reset                                            \n\
  user-rcfile " USERRCFILEPATH "                   \n\
  errors-to-stderr                                 \n\
  _include-sysconfig " SYSTEMRCFILEDEFAULTPATH "   \n\
  if grep service-user-shell " SHELLLISTPATH "     \n\
    errors-push                                    \n\
      catch-quit                                   \n\
        _include-user-rcfile                       \n\
      hctac                                        \n\
    srorre                                         \n\
  fi                                               \n\
  _include-sysconfig " SYSTEMRCFILEOVERRIDEPATH "  \n\
  quit                                             \n\
"

#define TOPLEVEL_OVERRIDDEN_CONFIGURATION "        \n\
  reset                                            \n\
  errors-to-stderr                                 \n\
  _include-client-config                           \n\
  quit                                             \n\
"

#define USERVD_MYSELF_CHECK 3600
#define USERVD_MYSELF_TIMEOUT 60
#define USERVD_CHECKFORK_RETRY 60
#define MAX_INCLUDE_NEST 40
#define MAX_ERRMSG_LEN (MAX_ERRMSG_STRING-1024)
#define ERRMSG_RESERVE_ERRNO 128

int parse_string(const char *string, const char *descrip, int isinternal);
int parseerrprint(const char *fmt, ...) PRINTFFORMAT(1,2);
void ensurelogopen(int wantfacility);
void ensurefdarray(int fd);
const char *printtoken(int token);
void senderrmsgstderr(const char *errmsg);
void disconnect(int exitstatus) NONRETURNING;

void always_dumpparameter(const char *parm, char **values);
void always_dumpexecsettings(void);

void debug_dumprequest(pid_t mypid);
void debug_dumpexecsettings(void);
void debug_dumpparameter(const char *parm, char **values);
pid_t nondebug_fork(void);
const char *nondebug_serviceuserdir(const char *ifnondebug);

typedef void builtinserviceexec_fnt(const char *const *args);
builtinserviceexec_fnt NONRETURNING bisexec_environment, bisexec_parameter;
builtinserviceexec_fnt NONRETURNING bisexec_version, bisexec_help;
builtinserviceexec_fnt NONRETURNING bisexec_toplevel, bisexec_override, bisexec_reset;
builtinserviceexec_fnt NONRETURNING bisexec_execute, bisexec_shutdown;
extern const char *const builtinservicehelpstrings[];

void execservice(const int synchsocket[], int clientfd) NONRETURNING;
void servicerequest(int sfd) NONRETURNING;
int synchread(int fd, int ch);
const char *defaultpath(void);

struct fdstate {
  int iswrite; /* 0 or 1; -1 if not open */
  int realfd, holdfd; /* -1 if not open */
  int wantstate;
  /* tokv_word_requirefd, tokv_word_allowfd, tokv_nullfd, tokv_word_rejectfd
   * (all of which have tokt_wantfdstate set) */
  int wantrw; /* tokv_word_read, tokv_word_write, 0 for either/both */
};

struct keyvaluepair { char *key, *value; };

extern pid_t overlordpid;
extern struct request_msg request_mbuf;
extern struct keyvaluepair *defvararray;
extern struct fdstate *fdarray; /* indexed by nominal fd */
extern int fdarraysize, fdarrayused;
extern int restfdwantstate, restfdwantrw;
extern int service_ngids;
extern char **argarray;
extern char *serviceuser, *service, *loginname, *cwd;
extern char *overridedata, *userrcfile;
extern char *serviceuser_dir, *serviceuser_shell, *callinguser_shell;
extern gid_t *calling_gids, *service_gids;
extern uid_t serviceuser_uid;
extern const char **calling_groups, **service_groups;
extern char *execpath, **execargs;
extern int execute; /* One of the execution modes tokt_execmode */
extern int setenvironment, suppressargs, disconnecthup;
extern builtinserviceexec_fnt *execbuiltin;
extern int syslogopenfacility;

#endif
