/*
 * userv - common.h
 * definitions shared between client and daemon
 *
 * 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 COMMON_H
#define COMMON_H

#define COPYRIGHT(indent,nl)						      \
 indent "Copyright 1996-2021 Ian Jackson; copyright 2000 Ben Harris;"      nl \
 indent "Copyright 2021 Genome Research Limited apropos work by"           nl \
 indent "Matthew Vernon."                                                  nl \
 indent "there is NO WARRANTY; type `userv --copyright' for details."      nl

#define PCSUMSIZE 16

static const unsigned char protocolchecksumversion[PCSUMSIZE]= {
#include "pcsum.h"
};

#ifndef VARDIR
# define VARDIR "/var/run/userv"
#endif

#ifndef RENDEZVOUS
# define RENDEZVOUS "socket"
#endif

#ifndef RENDEZVOUSPATH
# define RENDEZVOUSPATH VARDIR "/" RENDEZVOUS
#endif

#ifndef PIPEFORMAT
# define PIPEFORMAT "%lx.%lx.%x"
# define PIPEPATTERN "[0-9a-f]*.[0-9a-f]*.*[0-9a-f]"
# define PIPEFORMATEXTEND ((int)(sizeof(unsigned long)*2*2+(int)sizeof(int)*2+3))
# define PIPEMAXLEN ((int)(sizeof(PIPEFORMAT)+PIPEFORMATEXTEND))
#endif

#ifndef PIPEPATHFORMAT
# define PIPEPATHFORMAT VARDIR "/" PIPEFORMAT
# define PIPEPATHMAXLEN ((int)(sizeof(PIPEPATHFORMAT)+PIPEFORMATEXTEND))
#endif

#define MAX_ALLOW_FD 1024
#define MAX_GENERAL_STRING (1024*1024)
#define MAX_OVERRIDE_LEN MAX_GENERAL_STRING
#define MAX_ERRMSG_STRING 4096
#define MAX_ARGSDEFVAR 4096
#define MAX_GIDS 1024

#ifdef DEBUG
# define BASE_MAGIC 0x5deb7567UL /* "\x5d\xebug" */
#else
# define BASE_MAGIC 0x755e7276UL /* "u\x5erv" */
#endif

enum {
  OPENING_MAGIC= BASE_MAGIC+1,
  REQUEST_MAGIC,
  REQUEST_END_MAGIC,
  PROGRESS_MAGIC,
  PROGRESS_ERRMSG_END_MAGIC,
  EVENT_MAGIC
};

struct opening_msg {
  unsigned long magic;
  unsigned char protocolchecksumversion[PCSUMSIZE];
  pid_t overlordpid, serverpid;
};

struct request_msg {
  unsigned long magic;
  pid_t clientpid; /* or -1 if no service is required and this was a version check */
  int serviceuserlen;
  int servicelen;
  int loginnamelen, spoofed; /* spoofed is 0 or 1 */
  int cwdlen, overridelen;
  uid_t callinguid;
  int ngids, nreadfds, nwritefds, nargs, nvars;
  /* Followed by:
   *   serviceuserlen bytes for the service user (unterminated)
   *   servicelen bytes for the service (unterminated)
   *   loginnamelen bytes for the login name (unterminated)
   *   cwdlen bytes for the cwd (unterminated)
   *   overridelen bytes for the override data (with extra \n but unterminated),
   *    or nothing if overridelen==-1
   *   ngids gid_ts for the primary group and supplementary groups
   *   nreadfds and then nwritefds ints for the file descriptors
   *   for each of the nargs arguments
   *    an int for the string length
   *    that many characters (unterminated)
   *   for each for the nvars variable keys
   *    an int for the key length
   *    that many characters (unterminated)
   *    an int for the value length
   *    that many characters (unterminated)
   *   one unsigned long, endmagic;
   */
};

struct progress_msg {
  unsigned long magic;
  enum { pt_ok, pt_errmsg, pt_failed, pt_terminated } type;
  union {
    struct { int messagelen; } errmsg;
    struct { int status; } terminated;
  } data;
  /* follwed by variable-length part:
   *  for ok, failed, terminated: nothing
   *  for errmsg: messagelen bytes for the error message (unterminated, no \n)
   *              unsigned long PROGRESS_ERRMSG_END_MAGIC
   */
};

struct event_msg {
  unsigned long magic;
  enum { et_confirm, et_closereadfd, et_disconnect } type;
  union {
    struct { int fd; } closereadfd;
  } data;
};

#endif
