/*
 * Copyright © 2002  Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * priv_impl.h
 * Header file for the implimentation bits of privman.  Things common
 * between the server and the client halves.
 *
 * $Id: priv_impl.h,v 1.22 2003/04/10 00:25:52 dougk Exp $
 */


/* Global variables */

extern int              privmand_fd;

extern pid_t            child_pid;

extern config_t        *config;

/* The first byte of a command message.  What is this command? */
enum commands {
    CMD_OPEN                    = 'o',
    CMD_UNLINK                  = 'u',
    CMD_BIND                    = 'b',

    CMD_PAM_START               = 'p',
    CMD_PAM_AUTHENTICATE        = 'a',
    CMD_PAM_ACCT_MGMT           = 'm',
    CMD_PAM_END                 = 'P',
    CMD_PAM_SETCRED		= 'c',
    CMD_PAM_OPEN_SESSION        = 's',
    CMD_PAM_CLOSE_SESSION       = 'S',
    CMD_PAM_GET_ITEM            = 'i',
    CMD_PAM_SET_ITEM            = 'I',
    CMD_PAM_GETENV              = 'e',
    CMD_PAM_PUTENV              = 'E',
    CMD_PAM_CHAUTHTOK           = 't',
    CMD_PAM_FAIL_DELAY          = 'D',

    CMD_FORK                    = 'f',
    CMD_EXIT                    = 'x',  /* This process going away. */
    CMD_DAEMON                  = 'd',
    CMD_WAIT4                   = '4',

    CMD_POPEN                   = 'k',
    CMD_PCLOSE                  = 'K',

    CMD_RERUN_AS                = 'R',
    CMD_RESPAWN_AS              = 'r',

    CMD_CUSTOM_INFO             = 'n',
    CMD_CUSTOM_CAP              = 'C'
};

/* Virtual structure of the command message:
 * {
 *      int             command;
 *      byte            command_specific_data[];
 * }
 *
 * Virtual structure of the repsonce:
 * {
 *     int              privman_rc;
 *                      // < 0, errno = -privman_rc; return -1;
 *                      // > 0, command_specific return (PAM mostly)
 *                      // = 0, success.
 *     byte             command_specific_data[];
 * }
 */

/* Convience message functions to help with this:
 */

static __inline__ 
void msg_init(message_t *msg, enum commands cmd) {
    msg_clear(msg);
    msg_addInt(msg, cmd);
}

static __inline__ 
void msg_initResponce(message_t *msg, int rc) {
    msg_clear(msg);
    msg_addInt(msg, rc);
}


/* Factor out some of the common error handling */
static __inline__ void boom(const char *where) __attribute((__noreturn__));
static __inline__ void boom(const char *where)
{
    syslog(LOG_ERR, "%s: %m", where);
    /* Only one of the two processes should exit().  The other should
     * _exit().  To allow atexit() et. all to work for the client
     * processes, the parent will use _exit().
     */
    if (child_pid == 0)
        exit(-1);
    else
        _exit(-1);
}

static __inline__
void msg_recvmsg(message_t *msg, int fd, const char *boommsg) {
    int n = msg_recvmsg(msg, fd);
    if (n < 0)
        boom(boommsg);
}

static __inline__
void msg_sendmsg(message_t *msg, int fd, const char *boommsg) {
    int n = msg_sendmsg(msg, fd);
    if (n < 0)
        boom(boommsg);
}

static __inline__
void msg_addArgv(message_t *msg, char * const argv[]) {
    int i;
    for (i = 0; argv != NULL && argv[i] != NULL; ++i)
        ;
    msg_addInt(msg, i);
    for (i = 0; argv != NULL && argv[i] != NULL; ++i)
        msg_addString(msg, argv[i]);
}

static __inline__
char ** msg_getArgv(message_t *msg) {
    char **retval;
    int i;
    int argc;
   
    argc = msg_getInt(msg);
    retval = (char**)malloc(sizeof(char*) * (argc+1));

    for (i = 0; i < argc ; ++i) {
        if ((retval[i] = msg_getAllocStr(msg, 4096)) == NULL)
            boom("msg_getArgv, bad arg string");
    }
    retval[i] = NULL; /* Null terminate the array */

    return retval;
}



/* Codes for messages back to the client.  Do you need to run the
 * conversion function?
 */
enum privman_responces {
    PRIV_NONE           = 0, /* Nothing to do here.             */
    PRIV_PAM_RC         = 1, /* Standard Pam return code        */
    PRIV_PAM_RUN_CONV,       /* Run the PAM conversion function */

    PRIV_SET_COE             /* Set Close-on-exec               */
};

/* The server control function */
void privman_serv_init(void);

void priv_sep_init(void (*servfn)(void),
        void (*childfn)(char * const*), char *const childfn_arg[],
        const char *user, const char *root);

void setup_child(void (*fnptr)(char * const *), char * const args[],
        const char *user, const char *root);

/* Defines for wait4.  Wait4 has three possible output values, 
 * the return value, which is always used, int *status, and
 * rusage *rusage.  Lets only ask for the last two if the caller
 * cares.
 */
#define WANTS_STATUS    1
#define WANTS_RUSAGE    2

#ifdef __cplusplus
/* The maps that hold custom methods.  Typedefed for iterator reasons. */
typedef std::map<int,char *(*)(char * const *)> info_fn_map_t;
typedef std::map<int,int   (*)(char * const *)>  cap_fn_map_t;

extern info_fn_map_t info_fn_map;
extern  cap_fn_map_t  cap_fn_map;
#endif



syntax highlighted by Code2HTML, v. 0.9.1