/* vim: set shiftwidth=4 tabstop=8 softtabstop=4: */
/* $Id: sptconn.h,v 1.11 2003/10/11 14:18:39 shinra Exp $ */

#ifndef SPTCONN_H
#define SPTCONN_H

/*
 * No major/minor version, nor compatibility info
 */
#define SPT_PROTO_VERSION 3

enum {
    MSG_RESULT = 0,
    MSG_CONNECT = 1,
    MSG_PROTO_VIOLATION = 2,
    MSG_INIT_TTY = 3,
    MSG_RELEASE_TTY = 4,
    MSG_LOGIN_UTMP = 5,
    MSG_LOGOUT_UTMP = 6,
    MSG_LOGIN_WTMP = 7,
    MSG_LOGOUT_WTMP = 8,
    MSG_UPDATE_LASTLOG = 9,
    MSG_DISCONNECT = 10,
};

enum {
    ERR_NONE = 0,
    ERR_UNKNOWN = 1,
    /* MSG_CONNECT */
    ERR_VERSION_MISMATCH = 2,
    ERR_WRONG_INST = 10,    /* no root privilege, etc */
    ERR_INVAL_PTY = 11,
    ERR_UNKNOWN_PTYTYPE = 12,
    /* MSG_GET_TTY/MSG_RELEASE_TTY */
    ERR_CHOWN_FAIL = 20,
    /* MSG_LOGIN_UTMP family */
    ERR_UTMP_FAIL = 30,
    /* MSG_DISCONNECT */
    ERR_CLEANUP_FAIL = 40,	/* cleanup failure */
};

enum {
    PTYTYPE_SVR4 = 0,
    PTYTYPE_BSD = 1,
    PTYTYPE_PTC = 2,
    PTYTYPE_CLONE = 3,
    PTYTYPE_SGI4 = 4,
    PTYTYPE_NUMERIC = 5,
    PTYTYPE_CYGWIN = 6,
    PTYTYPE_CRAY = 7,
};

typedef struct {
    spt_uint32_t version;
    const char *ttyname;
    spt_uint32_t ptytype;
} msg_connect;
typedef struct {
    const char *host;
    spt_int32_t pid;	/* really sufficient? */
} msg_utmp;

typedef union {
    spt_int32_t mu_int;
    const char *mu_str;
    msg_connect mu_connect;
    msg_utmp mu_utmp;
} msgunion;
typedef struct {
    spt_int32_t msgtype;
    msgunion mu;
} msgunion_with_type;


#define MSGPROC(name) \
    int name(void *arg, spt_int32_t msgtype, const msgunion *pmu)
typedef struct connection_tag connection;
typedef MSGPROC((*msgproc));

typedef struct {
    spt_int32_t msgtype;
    msgproc proc;
} dispatch_table_item;

typedef struct {
    size_t n_items;
    const dispatch_table_item *items;
    msgproc defproc;
    void *arg;
} dispatch_table;

extern int spt_p_send_void(connection *pconn, spt_int32_t msgtype);
extern int spt_p_send_int(
	connection *pconn, spt_int32_t msgtype, spt_int32_t val);
extern int spt_p_send_str(
	connection *pconn, spt_int32_t msgtype, const char *str);
extern int spt_p_send_connect(
	connection *pconn, const msg_connect *pmsgconn);

#define spt_p_send_result(pconn, res) \
    spt_p_send_int(pconn, MSG_RESULT, res)

extern int spt_p_create_conn(
	connection **ppconn, const dispatch_table *table, int fd);
extern void spt_p_destroy_conn(connection *pconn);
extern int spt_p_do_read(connection *pconn);
extern int spt_p_send_msg(connection *pconn, const msgunion_with_type *pmsg);

#endif /* SPTCONN_H */
