#define MAXSAME 16
#define MAXSAMECHAR 1024

/* status of a destination*/
typedef enum {
       d_undefined,    /* address has not been matched*/
       d_pipe,         /* repl1|repl2 == delivery command, rep*/
       d_cat,          /* repl1 == mail file */
       d_translate,    /* repl1 == translation command*/
       d_alias,        /* repl1 == translation*/
       d_auth,         /* repl1 == command to authorize*/
       d_syntax,       /* addr contains illegal characters*/
       d_unknown,      /* addr does not match a rewrite rule*/
       d_loop,         /* addressing loop*/
       d_eloop,        /* external addressing loop*/
       d_noforward,    /* forwarding not allowed*/
       d_badmbox,      /* mailbox badly formatted*/
       d_resource,     /* ran out of something we needed*/
       d_pipeto,       /* pipe to from a mailbox*/
} d_status;

/* a destination*/
typedef struct dest dest;
struct dest {
       dest    *next;          /* for chaining*/
       dest    *same;          /* dests with same cmd*/
       dest    *parent;        /* destination we're a translation of*/
       String  *addr;          /* destination address*/
       String  *repl1;         /* substitution field 1*/
       String  *repl2;         /* substitution field 2*/
       int     pstat;          /* process status*/
       d_status status;        /* delivery status*/
       int     authorized;     /* non-zero if we have been authorized*/
       int     nsame;          /* number of same dests chained to this entry*/
       int     nchar;          /* number of characters in the command*/
};

typedef struct message message;
struct message {
       String  *sender;
       String  *replyaddr;
       String  *date;
       String  *body;
       String  *to;
       int     size;
       int     fd;             /* if >= 0, the file the message is stored in*/
       String  *havefrom;
       String  *havesender;
       String  *havereplyto;
       char    havedate;
       char    havemime;
       String  *havesubject;
       char    rfc822headers;
       char    *boundary;      /* bondary marker for attachments */
       char    haveto;
       char    bulk;           /* if Precedence: Bulk in header */
       char    received;       /* number of received lines */
};

extern  int     rmail;
extern  int     onatty;
extern  char    *thissys;
extern  char    *altthissys;
extern  int     debug;
extern  int     nosummary;
extern  int     flagn;
extern  int     flagx;

extern void     authorize(dest*);
extern int      cat_mail(dest*, message*);
extern dest     *up_bind(dest*, message*, int);
extern int      ok_to_forward(char*);
extern dest     *d_new(String*);
extern void     d_free(dest*);
extern dest     *d_rm(dest**);
extern void     d_insert(dest**, dest*);
extern dest     *d_rm_same(dest**);
extern void     d_same_insert(dest**, dest*);
extern String   *d_to(dest*);
extern dest     *s_to_dest(String*, dest*);
extern void     gateway(message*);
extern dest     *expand_local(dest*);
extern void     logdelivery(dest*, char*, message*);
extern void     loglist(dest*, message*, char*);
extern void     logrefusal(dest*, message*, char*);
extern int      default_from(message*);
extern message  *m_new(void);
extern void     m_free(message*);
extern message  *m_read(Biobuf*, int, int);
extern int      m_get(message*, vlong, char**);
extern int      m_print(message*, Biobuf*, char*, int);
extern int      m_bprint(message*, Biobuf*);
extern String   *rule_parse(String*, char*, int*);
extern int      getrules(void);
extern int      rewrite(dest*, message*);
extern void     dumprules(void);
extern void     regerror(char*);
extern dest     *translate(dest*);
extern char*    skipequiv(char*);
extern int      refuse(dest*, message*, char*, int, int);