/**************************************************************************
 * LPRng IFHP Filter
 * Copyright 1994-1999 Patrick Powell, San Diego, CA <papowell@astart.com>
 **************************************************************************/
/**** HEADER *****
$Id: ifhp.h,v 1.47 2004/09/30 23:24:41 papowell Exp papowell $
 **** ENDHEADER ****/

#ifndef _IFHP_H_
#define _IFHP_H_ 1

#ifndef EXTERN
# define EXTERN extern
# define DEFINE(X)
#endif

/*****************************************************************
 * get the portability information and configuration 
 *****************************************************************/

#include "portable.h"
#include "safemalloc.h"
#include "safestrutil.h"
#include "perlobj.h"
#include "debug.h"
#include "errormsg.h"
#include "patchlevel.h"
#include "globmatch.h"
#include "open_device.h"
#include "plp_snprintf.h"
#include "stty.h"
#include "checkcode.h"
#include "accounting.h"

/*****************************************************************
 * Global variables and routines that will be common to all programs
 *****************************************************************/

/*
 * data types and #defines
 */

/* maximum recursion depth */
#define MAX_DEPTH 10

/*
 * struct value - used to set and get values for variables
 */

struct keyvalue{
	char *varname;	/* variable name */
    char *key; /* name of the key */
    char **var; /* variable to set */
    int kind; /* type of variable */
#define INTV 0
#define STRV 1
#define FLGV 2
	char *defval;	/* default value, if any */
};

/*
 * dynamically controlled byte array for IO purposes 
 */
struct std_buffer {
	char *buf;		/* buffer */
	int end;		/* end of buffer */
	int start;		/* start of buffer */
	int max;		/* maximum size */
};

typedef void (*Wr_out)(char *);
typedef	int (*Builtin_func)(char *, char*, char *, Wr_out);

#ifndef ISNULL
#define ISNULL(X) ((X==0) || ((cval(X))==0))
#endif

#ifndef SMALLBUFFER
# define SMALLBUFFER 1024
#endif
#ifndef LARGEBUFFER
# define LARGEBUFFER (1024*4)
#endif
#define OUTBUFFER (1024*10)

int Peek_char DEFINE( = -1);

/* get the character value at a char * location */

/* EXIT CODES */

#define JFAIL    32    /* failed - retry later */
#define JABORT   33    /* aborted - do not try again, but keep job */
#define JREMOVE  34    /* failed - remove job */
#define JHOLD    37    /* hold this job */
#define JNOSPOOL 38    /* no spooling to this queue */
#define JNOPRINT 39    /* no printing from this queue  */
#define JSIGNAL  40    /* killed by unrecognized signal */
#define JFAILNORETRY 41 /* no retry on failure */
#define JSUSP    42     /* process suspended successfully */
#define JTIMEOUT 43     /* timeout */
#define JWRERR   44     /* write error */
#define JRDERR   45     /* read error  */
#define JCHILD   46     /* no children */
#define JNOWAIT  47     /* no wait status */

/* from 1 - 31 are signal terminations */

/*
 * Constant Strings
 */

EXTERN char *UNKNOWN DEFINE( = "UNKNOWN");
EXTERN char *PCL DEFINE( = "PCL");
EXTERN char *HPGL2 DEFINE( = "HPGL2");
EXTERN char *PS DEFINE( = "POSTSCRIPT");
EXTERN char *TEXT DEFINE( = "TEXT");
EXTERN char *RAW DEFINE( = "RAW");
EXTERN char *PJL DEFINE( = "PJL");
EXTERN char *FILTER DEFINE( = "FILTER");
EXTERN char *MSG DEFINE( = "MSG");

#define GLYPHSIZE 15
 struct glyph{
    int ch, x, y;   /* baseline location relative to x and y position */
    char bits[GLYPHSIZE];
};

 struct font{
    int height; /* height from top to bottom */
    int width;  /* width in pixels */
    int above;  /* max height above baseline */
    struct glyph *glyph;    /* glyphs */
};

EXTERN char *InputFile DEFINE( = "-" );

/*
 * setup values
 */

EXTERN OBJ *Zopts, *Topts, *Unsorted_Zopts, *Unsorted_Topts,
	*Raw, *Model, *Printcap, *Index, *Entries, *Devstatus, *Pjl_only, *Pjl_except,	/* option variables */
	*Pjl_options_set, *Pjl_show_values,
	*Pjl_vars_set, *Pjl_vars_except,
	*Pcl_vars_set, *Pcl_vars_except, *Pcl_papersize_codes,
	*User_opts, *Pjl_user_opts, *Pcl_user_opts, *Ps_user_opts,
	*Pjl_error_codes, *Pjl_quiet_codes, *Pjl_alert_codes, *Setvals,
	*Ignore, *Translate, *Status_fields;

EXTERN OBJ **Var_list[]
#ifdef DEF
 = {
	&Zopts, &Topts, &Unsorted_Zopts, &Unsorted_Topts,
	&Raw, &Model, &Printcap, &Index, &Entries,  &Devstatus, &Pjl_only, &Pjl_except,	/* option variables */
	&Pjl_options_set, &Pjl_show_values,
	&Pjl_vars_set, &Pjl_vars_except,
	&Pcl_vars_set, &Pcl_vars_except, &Pcl_papersize_codes,
	&User_opts, &Pjl_user_opts, &Pcl_user_opts, &Ps_user_opts,
	&Pjl_error_codes, &Pjl_quiet_codes, &Pjl_alert_codes, &Setvals,
	&Ignore, &Translate, &Status_fields,
	0
}
#endif
;

EXTERN char *Loweropts[26];	/* lower case options */
EXTERN char *Upperopts[26];	/* upper case options */
EXTERN char **Envp;			/* environment variables */
EXTERN char **Argv;			/* parms variables */
EXTERN int Argc;			/* we have the number of variables */
EXTERN time_t Start_time;     /* start time of program */
EXTERN char RemoteIPAddr[256];

EXTERN int
	Appsocket,	/* accounting fd */
	Autodetect,	/* let printer autodetect type */
	Close_appsocket, /* close the appsocket connection */
	Crlf,		/* only do CRLF */
	Dev_retries,	/* number of retries on open */
	Dev_sleep DEFINE(=1000),	/* wait between retries in Millisec */
	Errorcode,		/* exit value */
	Foomatic DEFINE(=1),	/* enable foomatic conversion */
	Force_conversion,	/* force conversion by file utility */
	Force_processing,	/* force processing by ifhp */
	Force_status,	/* even if device is not socket or tty, allow status */
	Full_time,		/* use Full_time format */
	Ignore_eof,			/* ignore eof on input */
	Initial_timeout,	/* initial timeout on first write */
	Logall,		/* log all information back from printer */
	Max_fd,			/* maximum fd opened */
	Max_status_size DEFINE(=8),	/* status file max size */
	Min_status_size DEFINE(=2),	/* status file min size */
	No_udp_monitor,		/* do not use udp monitor */
	Null_pad_count,		/* null padding on PJL ENTER command */
	OF_Mode,			/* running in OF mode */
	Pagecount_end DEFINE(=1),	/* pagecount at end */
	Pagecount_interval,	/* pagecount polling interval */
	Pagecount_poll,	/* pagecount times to poll (default is 1) */
	Pagecount_poll_end,		/* pagecount times to poll */
	Pagecount_poll_start,	/* pagecount times to poll */
	Pagecount_start DEFINE(=1),	/* pagecount at start */
	Pagecount_timeout,	/* pagecount */
	Pcl,		/* has PCL support */
	Pcl_eoj DEFINE(=1),	/* PCL eoj */
	Pcl_eoj_at_end DEFINE(=1),/* PCL eoj at start */
	Pcl_eoj_at_start DEFINE(=1),/* PCL eoj at start */
	Pjl,		/* has PJL support */
	Pjl_console,	/* use the PJL Console */
	Pjl_display_size,	/* use the PJL Console */
	Pjl_enter,	/* use the PJL ENTER command */
 	Pjl_waitend_byjobname,	/* wait for the specific job name string with the
 				   end of job string */
	Poll_for_status,	/* poll for status */
	Ps,			/* has PostScript support */
	Ps_ctrl_t,			/* end status indications from PostScript ctrl_T status */
	Ps_eoj DEFINE(=1),	/* PS eoj */
	Ps_eoj_at_end DEFINE(=1),	/* PS eoj at end */
	Ps_eoj_at_start DEFINE(=1),	/* PS eoj at start */
	Psonly,	/* only recognizes PostScript */
 	Hpgl2,		/* has HPGL2 support - added by Samuel Lown @ CERN */
	Qms,	/* QMS printer */
	Quiet,		/* suppress printer status messages */
	Remove_pjl_at_start,	/* remove PJL from start of file */
	Reopen_for_job,	/* open the device read/write */
	Send_job_rw_timeout, /* send job rw operation timeout */
	Shutdown_appsocket,		/* shutdown when appsocket */
	Status,		/* any type of status - off = write only */
	Status_fd DEFINE(=-2),	/* status reporting to remote site */
	Sync_interval,	/* sync interval */
	Sync_timeout,	/* sync timeout */
	Snmp_monitor,		/* use snmp monitor */
	Snmp_wait_after_close DEFINE(=1),	/* use snmp monitor */
	Snmp_fd,			/* read status from snmp monitor */
	Tbcp,		/* supports Postscript TBCP */
	Text,		/* supports test files */
	Trace_on_stderr, /* puts out trace on stderr as well */
	Ustatus_on, /* Ustatus was sent, need to send USTATUSOFF */
	Wait_for_banner,	/* wait for banner page to be completed */
	Waitend_ctrl_t_interval,	/* wait between sending CTRL T */
	Waitend_interval,	/* wait between sending end status requests */
	Waitend_timeout;	/* total time to wait for job */

EXTERN char 
	*Accounting_info DEFINE(="AnPR"),
	*Accountfile,		/* accounting file */
	*Accounting_script,	/* accounting script to use */
	*Config_file,	/* config file list */
	*Device,		/* device to open */
	*End_status,	/* status file */
	*Foomatic_rip,	/* foomatic rip */
	*Model_id,		/* printer model */
	*Pagecount,		/* pagecount */
	*Name,			/* program name */
	*Pjl_ready_msg,		/* ready message for console */
	*Pjl_done_msg,		/* done message for console */
	*Ppd_file,			/* PPD file */
	*Remove_ctrl,	/* remove these control chars */
	*Statusfile,	/* status file */
	*Status_ignore,	/* ignore these status entries */
	*Status_translate,	/* ignore these status entries */
	*Stty_args,		/* if device is tty, stty values */
	*Snmp_dev,	/* SNMP device */
	*Snmp_program,	/* SNMP program */
	*Snmp_status_fields,	/* SNMP status fields */
	*Snmp_sync_status,	/* SNMP sync status */
	*Snmp_end_status,	/* SNMP end status */
	*Sync,			/* synchronize printer */
	*Waitend;		/* wait for end using sync */

/*
 * set by routines
 */
EXTERN char
	*Ps_pagecount_code,		/* how to do pagecount */
	*Ps_status_code;		/* how to get status */

extern struct keyvalue Valuelist[], Builtin_values[];

#include <setjmp.h>

EXTERN int Alarm_timed_out;                                     /* flag */
EXTERN int Timeout_pending;

#if defined(HAVE_SIGLONGJMP)
EXTERN sigjmp_buf Timeout_env;
#  define Set_timeout() (sigsetjmp(Timeout_env,1)==0)
#else
EXTERN jmp_buf Timeout_env;
#  define Set_timeout() (setjmp(Timeout_env)==0)
#endif


#if defined DMALLOC
#	include <dmalloc.h>
#endif

/* PROTOTYPES */
void cleanup(int sig);
void usage();
void getargs( int argc, char **argv );
void Fix_special_user_opts( char *name, OBJ *opts, OBJ *unsorted_opts,
	 char *line );
void Init_outbuf();
void Put_outbuf_str( char *s );
void Put_outbuf_len( char *s, int len );
void Init_inbuf();
void Put_inbuf_len( char *str, int len );
void Get_inbuf_str(void);
void Pr_status( char *str );
void Check_device_status( char *line, int infovar );
void Initialize_parms( OBJ *list, struct keyvalue *valuelist );
void Dump_parms( char *title, struct keyvalue *v );
void Process_job( int do_pagecount, int pagecount_ps, int pagecount_pjl,
	char *pagecount_prog, int pagecount_snmp );
void Start_of_job( int *startpagecounter, int do_pagecount, int pagecount_ps,
	int pagecount_pjl, int nested_job, char *pagecount_prog, int pagecount_snmp );
void End_of_job( int *startpagecounter, int do_pagecount, int pagecount_ps,
	int pagecount_pjl, int wait_for_end, int nested_job, int banner_page,
	char *pagecount_prog, int pagecount_snmp );
int Find_in_list( OBJ *list, const char *str );
void Put_pjl( char *s );
void Put_pcl( char *s );
void Put_ps( char *s );
void Put_fixed( char *s );
int Get_nonblock_io( int fd );
void Set_nonblock_io( int fd );
void Set_block_io( int fd );
plp_sigfunc_t plp_signal (int signo, plp_sigfunc_t func);
plp_sigfunc_t plp_signal_break (int signo, plp_sigfunc_t func);
void plp_block_all_signals ( plp_block_mask *oblock );
void plp_unblock_all_signals ( plp_block_mask *oblock );
void plp_set_signal_mask ( plp_block_mask *in, plp_block_mask *out );
void plp_unblock_one_signal ( int sig, plp_block_mask *oblock );
void plp_block_one_signal( int sig, plp_block_mask *oblock );
void plp_sigpause( void );
void Set_timeout_signal_handler( int timeout, plp_sigfunc_t handler );
void Set_timeout_alarm( int timeout );
void Set_timeout_break( int timeout );
void Clear_timeout( void );
int Write_fd_len_timeout( int timeout, int fd, const char *msg, int len );
int Write_read_timeout( int len, char *buffer, int timeout );
int Read_status_timeout( int timeout );
int Resolve_key_val( char *prefix, char *id,
	OBJ *values, Wr_out routine, int depth, int maxdepth );
int Is_flag( char *s, int *v );
void Resolve_list( char *prefix, OBJ *list, OBJ *values, Wr_out routine, int depth, int maxdepth );
void Resolve_user_opts( char *prefix, OBJ *only,
	OBJ *list, OBJ *values, Wr_out routine );
char *Fix_option_str( char *str, int remove_ws, int trim, int one_line );
char *Find_sub_value( int c, char *id, int strval);
int Builtin( char* prefix, char *id, char *value, Wr_out routine);
const char *Decode_status (plp_status_t *status);
int plp_usleep( int i );
void Strip_leading_spaces ( char **vp );
int Font_download( char* prefix, char *id, char *value, Wr_out routine);
void Pjl_job();
void Pjl_eoj(char *name);
void Pjl_console_msg( int start );
int Pjl_setvar(char *prefix, char*id, char *value, Wr_out routine);
int Pcl_setvar(char *prefix, char*id, char *value, Wr_out routine );
void Do_sync( int sync_timeout, int sync_interval, int pagecount_pjl );
void Do_waitend( int waitend_timeout, int waitend_interval,
	int waitend_ctrl_t_interval, int banner );
int Check_pagecount( int *use_ps_v, int *use_pjl_v, char **use_prog_v, int *use_snmp_v );
int Do_pagecount( int pagecount_timeout, int pagecount_interval, int pagecount_poll,
	 int use_ps, int use_pjl, char *use_prog, int use_snmp );
int Current_pagecounter( int pagecount_timeout, int use_pjl, int use_ps, int use_snmp );
void Send_job();
void URL_decode( char *s );
int Process_OF_mode(void);
void close_on_exec( int n );
void Set_max_fd( int n );
void Use_file_util(char *pgm, char *value, int value_len );
int Make_tempfile( void );
void Make_stdin_file();
char * Set_mode_lang( char *s );
int Fd_readable( int fd, int *poll_for_status );
void Init_job( char *language );
void Term_job( char *language );
int Filter_file( char *pgm, char *title, int fd_stdin, int fd_stdout,
	char *errbuffer, int len_errbuffer );
void Write_error_msg( int fd, char *id );
OBJ * Split_cmd_line_OBJ( OBJ *l, char *s );
void Make_model_index( OBJ *input, OBJ *index, OBJ *entries );
OBJ *Make_new_model_entry( char *key, OBJ *index, OBJ *entries,
	OBJ *items, OBJ *strval );
void Select_model_info( OBJ *model, OBJ *index, OBJ *entries, char *id, int level, int maxlevel );
int Get_prog_status( OBJ *devstatus, char *pgm, int timeout );

#endif
