/*
 *  Globals of the ZMailer  smtp-server
 *
 */


#define SMTP_COMMAND_ALARM_IVAL 1200 /* 20 minutes.. */
#define SMTP_DATA_TIME_PER_LINE  600 /* 10 minutes of life.. */

/*
 * The smtpserver connects to the router to ask it various questions, like,
 * is this a valid address?  What is the alias expansion of that? etc.
 * This is done through a portal function called "server".  Its only standard
 * argument is a keyword for what we want done.  These are the definitions:
 */

#define	ROUTER_SERVER	"server"	/* name of portal function */

#define	RKEY_INIT	"init"		/* initialize state of server */
#define	RKEY_FROM	"from"		/* mail from address verification */
#define	RKEY_TO		"to"		/* recipient to address verification */
#define	RKEY_VERIFY	"verify"	/* verify this address */
#define	RKEY_EXPAND	"expand"	/* expand this address */

#define SMTPLINESIZE	8192

#include "hostenv.h"
#ifdef HAVE_RESOLVER
# define USE_INET
#endif
#include <stdio.h>
#include "malloc.h"
#include <sys/types.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include "zmsignal.h"
#include <errno.h>
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#else
# include <varargs.h> /* If no  <stdarg.h>,  then presume <varargs.h> ... */
#endif
#include "mail.h"

#include <setjmp.h>

#ifdef  HAVE_WAITPID
# include <sys/wait.h>
#else
# ifdef HAVE_WAIT3
#  include <sys/wait.h> /* Has BSD wait3() */
# else
#  ifdef HAVE_SYS_WAIT_H /* POSIX.1 compatible */
#   include <sys/wait.h>
#  else /* Not POSIX.1 compatible, lets fake it.. */
extern int wait();
#  endif
# endif
#endif

#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif

#include <sys/socket.h>
#include <netinet/in.h>
#ifdef HAVE_NETINET_IN6_H
# include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
# include <netinet6/in6.h>
#endif
#ifdef HAVE_LINUX_IN6_H
# include <linux/in6.h>
#endif

#ifndef	SIGCHLD
#define	SIGCHLD	SIGCLD
#endif	/* SIGCHLD */

#ifndef	MAXHOSTNAMELEN
#define	MAXHOSTNAMELEN 256
#endif	/* MAXHOSTNAMELEN */


#include "zsyslog.h"

#include "policytest.h"

struct smtpconf {
	char	*pattern;
	int	maxloadavg;
	char	*flags;
	struct smtpconf *next;
};

typedef enum {	Null, Hello, Mail, MailOrHello, Recipient,
		RecipientOrData, Data, Send, SendOrMail,
		SendAndMail, Reset, Verify, Expand, Help,
		NoOp, Quit, Turn, Tick, Verbose, DebugIdent,
	        Turnme, BData, DebugMode,
		Hello2, Mail2, Send2, Verify2 /* 8-bit extensions */
} Command;


struct command {
	char	*verb;
	Command	cmd;	
};

extern struct command command_list[];

typedef struct {
	FILE *outfp;	/* stdout */
	int  inputfd;	/* stdin  */
	FILE *mfp;		/* Storage-bound mail-file fp */
	long sizeoptval;	/* "MAIL FROM:<xxx> SIZE=nnn" -value	*/
	long sizeoptsum;
	char myhostname[MAXHOSTNAMELEN+1];
	char rhostname[MAXHOSTNAMELEN+1];
	char *with_protocol; /* = WITH_SMTP */
	char *style;	/* = "ve" */
	Command state;	/* = Hello */
	struct command *carp;
	struct policystate policystate;
	int policyresult, reject_net;
	int rport;
	char ihostaddr[sizeof("[ipv6.ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]")+8];
	union {
	  struct sockaddr_in  v4;
#ifdef AF_INET6
	  struct sockaddr_in6 v6;
#endif
	} raddr;
	union {
	  struct sockaddr_in  v4;
#ifdef AF_INET6
	  struct sockaddr_in6 v6;
#endif
	} localsock;

	int  s_bufread;
	int  s_readout;
	int  s_status;
	char s_buffer[SMTPLINESIZE];

	int  from_box; /* Set when:  MAIL FROM:<>  */
	int  rcpt_count;
	int  sender_ok;
	/* For BDAT -command */
	int bdata_blocknum;
	int mvbstate;

	char ident_username[MAXHOSTNAMELEN+MAXHOSTNAMELEN+2];
	char helobuf[SMTPLINESIZE];

} SmtpState;

#define STYLE(i,c)	(strchr(((i)==NULL ? style : (i)->flags), (c)) != NULL)

#define	WITH_SMTP	"SMTP"
#define	WITH_ESMTP	"ESMTP"
#define	WITH_BSMTP	"BSMTP"

#define HELPMAX 40
extern char *helplines[];

extern long availspace;
extern long maxsize;
extern int  MaxErrorRecipients;
extern int  TcpRcvBufferSize;
extern int  MaxSameIpSource;
extern int  percent_accept;

extern char *progname;
extern int debug, skeptical, checkhelo, ident_flag, verbose;

extern char *style;
extern struct smtpconf *cfinfo;

extern struct smtpconf *readcffile __((char *fname));
extern struct smtpconf *findcf __((char *host));

extern int loadavg_current __((void));
extern long fd_statfs __((int));

extern char *rfc821_domain __((char *s, int strict));
extern char *rfc821_path   __((char *s, int strict));
extern char *rfc821_path2  __((char *s, int strict));
extern char *rfc821_error;
extern char *rfc821_error_ptr;
extern void type821err __(());


extern struct smtpconf *cfhead;

extern char *postoffice; /* Defined at mail.c -- mail_open() and friends */

extern void reporterr __((SmtpState *, long, char*));

extern const char *Copyright;
extern const char *Copyright2;
extern FILE *logfp;
extern int   pid;

extern char *routerprog;
extern int   routerpid;

extern const char *m200;
extern const char *m400;
extern const char *m430;
extern const char *m454;
extern const char *m540;
extern const char *m550;
extern const char *m551;
extern const char *m552;
extern const char *m554;


extern char *strerror __((int));
extern int getmyhostname(), isit42inetd();
extern int getpeername();
extern void detach __((void)), prversion __(());
extern int  killprevious __(());
extern void settrusteduser __(());
extern char *dottedquad __(());
extern char *Version;
extern char *VersionNumb;
extern u_char *rfc822date __((time_t *));

#ifdef USE_TRANSLATION
extern int X_8bit;
extern int X_translation;
extern int X_settrrc;
extern void header_from_mime __((char *, int *, int));
#endif /* USE_TRANSLATION */

extern void killr __((SmtpState *SS, int pid));
extern void typeflush __((SmtpState *));
#if defined(HAVE_STDARG_H) && defined(HAVE_VPRINTF)
extern void type __((SmtpState *, const int code, const char *status, const char *fmt, ...));
#else
extern void type __((/* SmtpState *SS, int code, char *fmt, ... */));
#endif
extern void debug_report __((int, char *, char *));
extern void header_to_mime __((char *, int *, int));
extern void help __((SmtpState *, struct smtpconf *, char *));
extern time_t time __((time_t *));
extern char *router __((SmtpState *,char*, int, char*));
#ifndef MALLOC_TRACE /* turns these into macroes.. */
# ifndef __XMALLOC_H__ /* at ../include/malloc.h */
extern univptr_t emalloc __((size_t));
extern univptr_t erealloc __((void *, size_t));
# endif
#endif
extern void runasrootuser __((void));
extern int runastrusteduser __((void));
extern char **environ;
extern int kill __((pid_t,int));

extern char *rfc822atom __((char *str));
extern char *xtext_string __((char *str));

extern void s_setup __((SmtpState *SS, int fd, FILE *fp));
extern int s_feof __((SmtpState *SS));
extern int s_getc __((SmtpState *SS));
extern int s_hasinput __((SmtpState *SS));

extern int errno;
extern int optind;
extern char *optarg;

#ifndef strchr
extern char *strchr(), *strrchr();
#endif
extern int cistrcmp(), cistrncmp();

#ifndef CISTREQN
# define   CISTREQN(x, y, n)  (cistrncmp((char *)(x), (char *)(y), n) == 0)
#endif
#ifndef CISTREQ
# define   CISTREQ(x, y)  (cistrcmp((char *)(x), (char *)(y)) == 0)
#endif

#ifdef	lint
#undef	putc
#define	putc	fputc
#endif	/* lint */
