File: HylaFAXServer.h

package info (click to toggle)
hylafax 1%3A4.2.1-5sarge3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 6,788 kB
  • ctags: 7,523
  • sloc: sh: 15,597; ansic: 13,040; makefile: 1,772; cpp: 864
file content (614 lines) | stat: -rw-r--r-- 23,462 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
/*	$Id: HylaFAXServer.h,v 1.11 2004/11/23 18:05:02 lhoward Exp $ */
/*
 * Copyright (c) 1995-1996 Sam Leffler
 * Copyright (c) 1995-1996 Silicon Graphics, Inc.
 * HylaFAX is a trademark of Silicon Graphics
 *
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Sam Leffler and Silicon Graphics.
 * 
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 * 
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 * OF THIS SOFTWARE.
 */
#ifndef _HylaFAXServer_
#define	_HylaFAXServer_

#include "FaxConfig.h"
#include "IOHandler.h"
#include "Dictionary.h"
#include "StrArray.h"
#include "FaxRequest.h"
#include "FaxRecvInfo.h"
#include "manifest.h"
#include "FileCache.h"
#include "Trace.h"
#include "Trigger.h"
#include "SystemLog.h"

#include "config.h"

#ifdef HAVE_PAM
extern "C" {
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <grp.h>
}
#endif // HAVE_PAM

#include <sys/types.h>
#include <sys/socket.h>
#include <dirent.h>

#include <setjmp.h>
#include <errno.h>

/*
 * In-memory copy of a job description file.
 */
struct Job : public FaxRequest {
    time_t	lastmod;		// last file modify time, for updates
    bool	queued;			// for SNPP

    Job(const fxStr& qf, int fd = -1);
    ~Job();

    bool checkDocument(const char* pathname);
};
fxDECLARE_StrKeyDictionary(JobDict, Job*)

/*
 * Received facsimile information.
 */
struct RecvInfo : public FaxRecvInfo {
    bool	beingReceived;		// currently being received
    time_t	recvTime;		// time receive operation started

    RecvInfo();
    RecvInfo(const char* qfile);
    ~RecvInfo();
};
fxDECLARE_StrKeyDictionary(RecvInfoDict, RecvInfo*)

#ifdef T_USER
#undef T_USER				// XXX FreeBSD defines this
#endif

/*
 * Parser tokens; also used to identify protocol commands/operations.
 */
enum Token {
    /*
     * Syntactic items.
     */
    T_SP,	T_CRLF,		T_COMMA,	T_STRING,	T_NUMBER,
    T_NIL,	T_LEXERR,
    /*
     * Commands.
     */
    T_ABOR,	 T_ACCT,	T_ADDMODEM,	T_ADDUSER,	T_ADMIN,
    T_ALLO,	 T_ANSWER,	T_APPE,		T_CHMOD,	T_CHOWN,
    T_CONFIG,	 T_CWD, 	T_CDUP,		T_DELE,		T_DELUSER,
    T_DELMODEM,	 T_DISABLE,	T_ENABLE,	T_FILEFMT,	T_FORM,
    T_HELP,	 T_IDLE,	T_JDELE,	T_JGDELE,	T_JGINTR,
    T_JGKILL,	 T_JGNEW,	T_JGPARM,	T_JGREST,	T_JGRP,
    T_JGSUB,	 T_JGSUSP,	T_JGWAIT,	T_JINTR,	T_JKILL,
    T_JNEW,	 T_JOB,		T_JOBFMT,	T_JPARM,	T_JREST,
    T_JSUB,	 T_JSUSP,	T_JWAIT,	T_LIST,	 	T_MDTM,
    T_MODE,	 T_MODEMFMT,	T_NLST,		T_NOOP,		T_PASS,
    T_PASV,	 T_PORT,	T_PWD,		T_QUIT,		T_RCVFMT,
    T_REIN,	 T_REST,	T_RETP,		T_RETR,		T_RNFR,
    T_RNTO,	 T_SHUT,	T_SITE,		T_SIZE,		T_STAT,
    T_STOR,	 T_STOT,	T_STOU,		T_STRU,		T_SYST,
    T_TRIGGER,	 T_TYPE,	T_TZONE,	T_USER,		T_VRFY,
    /*
     * Job state parameters.
     */
    T_ACCTINFO,	 T_BEGBR,	T_BEGST,	T_CHOPTHRESH,	T_CLIENT,
    T_COMMENTS,	 T_COMMID,	T_COVER,	T_DATAFORMAT,	T_DIALSTRING,
    T_DOCUMENT,	 T_DONEOP,	T_EXTERNAL,	T_FROM_COMPANY,	T_FROM_LOCATION,
    T_FROM_USER, T_FROM_VOICE,	T_GROUPID,	T_HRES,		T_JOBID,
    T_JOBINFO,	 T_JOBTYPE,	T_LASTTIME,	T_MAXDIALS,	T_MAXPAGES,
    T_MAXTRIES,	 T_MINBR,	T_MODEM,	T_NDIALS,	T_NOTIFY,
    T_NOTIFYADDR,T_NPAGES,	T_NTRIES,	T_OWNER,	T_PAGECHOP,
    T_PAGELENGTH,T_PAGEWIDTH,	T_PASSWD,	T_POLL,		T_REGARDING,
    T_RETRYTIME, T_SCHEDPRI,	T_SENDTIME,	T_STATE,	T_STATUS,
    T_SUBADDR,	 T_TAGLINE,	T_TOTDIALS,	T_TOTPAGES,	T_TOTTRIES,
    T_TO_COMPANY,T_TO_LOCATION,	T_TO_USER,	T_TO_VOICE,	T_USE_CONTCOVER,
    T_USE_ECM,	 T_USE_TAGLINE,	T_USE_XVRES,	T_USRKEY,	T_VRES,
    /*
     * SNPP tokens.
     */
    T_2WAY,	 T_ACKREAD,	T_ALERT,	T_CALLERID,	T_COVERAGE,
    T_DATA,	 T_EXPTAG,	T_HOLDUNTIL,	T_JQUEUE,	T_KTAG,
    T_LEVEL,	 T_LOGIN,	T_MCRESPONSE,	T_MESSAGE,	T_MSTATUS,
    T_NOQUEUEING,T_PAGER,	T_PING,		T_RTYPE,	T_SEND,
    T_SUBJECT
};

struct tab {			// protocol command table entry
    const char*	name;
    Token token;
    bool checklogin;	// if true, must be logged in first
    bool implemented;	// false if command is not implemented
    const char*	help;
};

class SpoolDir;

struct stat;
typedef struct tiff TIFF;
class JobExt;
class ModemExt;
class ModemConfig;
class IDCache;

extern const char* fmtTime(time_t t);

/*
 * An instance of a fax server process.
 */
class HylaFAXServer : public SystemLog, public FaxConfig, public IOHandler {
public:
    struct stringtag {
        const char*	 name;
        fxStr HylaFAXServer::* p;
        const char*	 def;		// NULL is shorthand for ""
    };
    struct numbertag {
        const char*	 name;
        u_int HylaFAXServer::*p;
        u_int		 def;
    };
protected:
    u_int	state;
#define	S_LOGGEDIN	0x0001		// client is logged in
#define	S_PRIVILEGED	0x0002		// client has administrative privileges
#define	S_LREPLIES	0x0004		// using continuation msgs in replies
#define	S_WAITFIFO	0x0008		// waiting on response to FIFO msg
#define	S_USEGMT	0x0010		// process times in GMT or local TZ
#define	S_WAITPASS	0x0020		// had user command, waiting for passwd
#define	S_TRANSFER	0x0040		// actively transferring data
#define	S_WAITDATA	0x0080		// scanner is waiting for data
#define	S_WAITTRIG	0x0100		// trigger is active
#define	S_LOGTRIG	0x0200		// write trigger events to data conn
#define	S_CHECKGID	0x0400		// check if file GID is set correctly
#define	S_SETGID	0x0800		// must explicitly force GID on files
    u_int	tracingLevel;		// server tracing control flags
    fxStr	logFacility;		// name of syslog facility for logging
    fxStr	userAccessFile;		// user access control file
    fxStr	xferfaxLogFile;		// log file for data transfers
    fxStr	faxContact;		// email account for inquiries
    fxStr	systemType;		// system ID string returned for SYST
    fxStr	faxqFIFOName;		// faxq FIFO name
    fxStr	clientFIFOName;		// client FIFO name
    int		faxqFd;			// faxq FIFO open descriptor
    int		clientFd;		// client FIFO open descriptor
    fxStr	fifoResponse;		// response received to FIFO msg
    u_int	idleTimeout;		// client inactivity timeout
    u_int	maxIdleTimeout;		// upper bound on idle timeout
    int		data;			// current data connection (socket)
    int		pdata;			// passive mode data connect (socket)
    fxStr	hostname;		// name of machine server is running on
    fxStr	hostaddr;		// primary address for hostname
    fxStr	remotehost;		// name of peer's machine
    fxStr	remoteaddr;		// address of peer's machine
    fxStr	autospout;		// text to send with next reply
    fxStr	shutdownFile;		// file with shutdown information
    fxStr	shutdownMsg;		// text of shutdown message
    time_t	lastModTime;		// last mod. time of shutdown file
    time_t	lastTime;		// time of last shutdown notification
    time_t	discTime;		// time to disconnect service
    time_t	denyTime;		// time to deny service
    /*
     * User authentication and login-related state.
     */
    fxStr	passwd;			// encrypted user password
    fxStr	adminwd;		// encrypted passwd for admin privileges
    u_int	uid;			// client's ID
    u_int	loginAttempts;		// number of failed login attempts
    u_int	maxLoginAttempts;	// login failures before server exits
    u_int	adminAttempts;		// number of failed admin attempts
    u_int	maxAdminAttempts;	// admin failures before server exits
    fxStr	the_user;		// name of user
	fxStr   admingroup;			// name of local user group that is allowed
								// to administer the fax server
    IDCache*	idcache;		// fax UID -> name mapping table
    /*
     * File and file-transfer related state.
     */
    off_t	restart_point;		// file offset for restarting transfers
    jmp_buf	urgcatch;		// throw location for transfer interrupt
    off_t	file_size;		// size of file being transferred
    off_t	byte_count;		// amount of data currently sent
    int		xferfaxlog;		// open transfer log file
    int		mode;			// data transfer mode
    int		form;			// data transfer format
    int		type;			// data transfer type
    int		stru;			// file structure
    SpoolDir*	cwd;			// current working directory
    fxStrArray	tempFiles;		// files created with STOT
    fxStr	fileFormat;		// format string for directory listings
    TIFF*	cachedTIFF;		// cached open TIFF file
    /*
     * Parser-related state.
     */
    Token	pushedToken;		// lexical token push back
    fxStr	tokenBody;		// string body of current lexical token
    char	cbuf[512];		// current input line
    int		cpos;			// position in cbuf
    int		ctrlFlags;		// file descriptor flags for control
    int		recvCC;			// amount of data remaining in recvBuf
    int		recvNext;		// next byte for scanner
    char	recvBuf[1024];		// input data buffer
    u_int	consecutiveBadCmds;	// # consecutive invalid control cmds
    u_int	maxConsecutiveBadCmds;	// max # before forced disconnect
    /*
     * Job-related state.
     */
    Job		defJob;			// default job state information
    JobDict	jobs;			// non-default jobs
    Job*	curJob;			// current job
    fxStr	jobFormat;		// job status format string
    /*
     * Receive queue-related state.
     */
    RecvInfoDict recvq;			// cache of info about received fax
    fxStr	recvFormat;		// received fax status format string
    /*
     * Trigger-related state.
     */
    fxStr	trigSpec;		// specification for active trigger
    u_int	tid;			// current active trigger ID
    /*
     * Modem-related state.
     */
    fxStr	modemFormat;		// modem status format string

    static gid_t faxuid;		// system gid of fax user = our uid
#if HAS_TM_ZONE
    const char*	tzname[2];		// local timezone name
#endif
    time_t	gmtoff;			// time_t offset btwn GMT and local time

    void userCmd(const char* name);	// USER
    void adminCmd(const char* name);	// ADMIN
    void passCmd(const char* passwd);	// PASS
    void statusCmd(void);		// STAT

    void formCmd(const char* name);	// FORM
    void formHelpCmd(void);		// FORM
    void typeCmd(const char* name);	// TYPE
    void modeCmd(const char* name);	// MODE
    void struCmd(const char* name);	// STRU
    void deleCmd(const char* name);	// DELE
    void mdtmCmd(const char* name);	// MDTM
    void cwdCmd(const char *path);	// CWD
    void pwdCmd(void);			// PWD
    void retrieveCmd(const char* name);	// RETR
    void retrievePageCmd(const char* name);// RETP
    void listCmd(const char* name);	// LIST
    void nlstCmd(const char* name);	// NLST
    void storeCmd(const char*, const char*);// STOR+APPE
    void storeUniqueCmd(bool isTemp);	// STOU+STOT
    void statFileCmd(const char* name);	// STAT
    void chownCmd(const char*, const char*);// CHOWN
    void chmodCmd(const char*, u_int);	// CHMOD

    virtual void passiveCmd(void) = 0;	// PASV: depends on transport
    virtual void portCmd(void) = 0;	// PORT: depends on transport

    void triggerCmd(const char*, ...);	// TRIGGER

    /*
     * Administrative commands (experimental).
     */
    void abortCallCmd(const char*);
    void addUserCmd(const char* spec, const char* pass, const char* apass);
    void delUserCmd(const char* spec);
    void answerCallCmd(const char* modem, const char* how);
    void disableModemCmd(const char* modem, const char* reason);
    void enableModemCmd(const char* mode);
    void shutCmd(const struct tm& when, const char* reason);
    void addModemCmd(const char* modem);
    void delModemCmd(const char* modem);
    void configQueryCmd(const char* where);
    void configCmd(const char* where, const char* info);

    virtual void initServer(void);
    bool readShutdownFile(void);
    bool isShutdown(bool quiet);
    void fatal(const char *fmt, ...);
    void reply(int code, const char* fmt, ...);
    void vreply(int code, const char* fmt, va_list ap);
    void lreply(int code, const char* fmt, ...);
    void vlreply(int code, const char* fmt, va_list ap);
    void perror_reply(int code, const char* string, int errnum);
    void ack(int code, const char*);
    void printTransferStatus(FILE* fd);
    struct tm* cvtTime(const time_t&) const;
    void setFileOwner(const char* filename);

    void loginRefused(const char* why);
	bool pamCheck(const char* user=NULL, const char* pass=NULL);
	bool pamIsAdmin(const char* user=NULL);
    bool checkUser(const char*);
    bool checkuser(FILE*, const char *name);
    bool checkuser(const char *name);
    void login(void);
    void end_login(void);
    virtual void dologout(int status);
    const char* fixPathname(const char* file);
    const char* userName(u_int uid);
    bool userID(const char*, u_int& id);
    void fillIDCache(void);

    bool cvtPasswd(const char* type, const char* pass, fxStr& result);
    bool findUser(FILE* db, const char* user, u_int& newuid);
    bool addUser(FILE* db, const char* user, u_int uid,
	const char* upass, const char* apass);
    bool deleteUser(FILE* db, const char* user);

    /*
     * Configuration file support.
     */
    static stringtag strings[];
    static numbertag numbers[];

    void resetConfig();
    void setupConfig();
    void configError(const char* fmt, ...);
    void configTrace(const char* fmt, ...);
    bool setConfigItem(const char* tag, const char* value);

    bool restartSend(FILE* fd, off_t marker);

    static SpoolDir dirs[];

    void dirSetup(void);
    static SpoolDir* dirLookup(const char* path);
    static SpoolDir* dirLookup(ino_t ino);
    SpoolDir* dirAccess(const char* path);
    SpoolDir* fileAccess(const char* path, int op, struct stat&);
    bool fileVisible(const SpoolDir&, const char*, const struct stat&);

    static bool isVisibleRecvQFile(const char*, const struct stat&);
    void listRecvQ(FILE* fd, const SpoolDir& sd, DIR* dir);
    void listRecvQFile(FILE*, const SpoolDir&, const char*, const struct stat&);

    static bool isVisibleSendQFile(const char*, const struct stat&);
    void listSendQ(FILE* fd, const SpoolDir& sd, DIR* dir);
    void listSendQFile(FILE*, const SpoolDir&, const char*, const struct stat&);
    void nlstSendQ(FILE* fd, const SpoolDir& sd, DIR* dir);
    void nlstSendQFile(FILE*, const SpoolDir&, const char*, const struct stat&);

    void listStatus(FILE* fd, const SpoolDir& sd, DIR* dir);
    void listStatusFile(FILE*, const SpoolDir&, const char*, const struct stat&);
    void nlstStatus(FILE* fd, const SpoolDir& sd, DIR* dir);

    static bool isVisibletrue(const char*, const struct stat&);
    static bool isVisibleDocQFile(const char*, const struct stat&);
    static bool isVisibleRootFile(const char*, const struct stat&);

    void listDirectory(FILE* fd, const SpoolDir& sd, DIR* dir);
    void listUnixFile(FILE*, const SpoolDir&, const char*, const struct stat&);
    void makeProt(const struct stat& sb, bool withGrp, char prot[10]);
    void Fprintf(FILE*, const char* fmt, const char*, const struct stat&);

    void nlstDirectory(FILE* fd, const SpoolDir& sd, DIR* dir);
    void nlstUnixFile(FILE*, const SpoolDir&, const char*, const struct stat&);

    virtual FILE* openDataConn(const char* mode, int& code) = 0;
    static const char* dataConnMsg(int code);
    virtual void closeDataConn(FILE*);

    bool sendData(FILE* fdin, FILE* fdout);
    bool sendIData(int fdin, int fdout);
    bool sendZData(int fdin, int fdout);
    bool recvData(FILE* instr, FILE* outstr);
    bool recvIData(int fdin, int fdout);
    bool recvZData(int fdin, int fdout);

    TIFF* openTIFF(const char* name);
    bool sendTIFFData(TIFF* tif, FILE* fdout);
    bool sendTIFFHeader(TIFF* tif, int fdout);
    bool sendITIFFData(TIFF* tif, int fdout);

    void logTransfer(const char*, const SpoolDir&, const char*, time_t);

    virtual int parse(void);
    bool cmd(Token t);
    bool site_cmd(Token t);
    bool param_cmd(Token t);
    bool string_param(fxStr&, const char* what = NULL);
    bool number_param(long&);
    bool boolean_param(bool&);
    bool file_param(fxStr& pathname);
    bool pwd_param(fxStr& s);
    bool timespec_param(int ndigits, time_t& t);
    bool pathname_param(fxStr& pathname);
    bool job_param(fxStr& jid);
    bool jgrp_param(fxStr& jgid);
    bool pathname(fxStr& s);
    bool CRLF();
    bool SPACE();
    bool COMMA();
    bool TIMESPEC(u_int len, time_t& result);
    bool BOOLEAN(bool& b);
    bool STRING(fxStr& s, const char* what = NULL);
    bool NUMBER(long& n);
    bool checkNUMBER(const char* s);
    bool opt_CRLF();
    bool opt_STRING(fxStr& s);
    bool multi_STRING(fxStr& s);
    static u_int twodigits(const char* cp, u_int range);
    static u_int fourdigits(const char* cp);
    virtual void syntaxError(const char* msg);

    virtual void netStatus(FILE*) = 0;	// depends on transport
    virtual bool hostPort() = 0;	// depends on transport

    int getChar(bool waitForInput);
    void pushCmdData(const char* data, int n);
    bool getCmdLine(char* s, int n, bool waitForInput = false);
    void pushToken(Token t);
    Token nextToken(void);
    bool checkToken(Token);
    bool getToken(Token, const char*);
    void helpCmd(const tab* ctab, const char* s);
    void logcmd(Token t, const char* fmt = NULL, ...);
    void cmdFailure(Token t, const char* why);
    bool checklogin(Token);
    bool checkadmin(Token);

    static const char* version;

    virtual const char* cmdToken(Token t);
    virtual const char* siteToken(Token t);
    static const char* parmToken(Token t);

    bool initClientFIFO(fxStr& emsg);
    int FIFOInput(int fd);
    void FIFOMessage(const char* cp, u_int len);
    bool sendModem(const char* modem, fxStr& emsg, const char* fmt ...);
    bool sendQueuerMsg(fxStr& emsg, const fxStr& msg);
    bool sendQueuer(fxStr& emsg, const char* fmt ...);
    bool sendQueuerACK(fxStr& emsg, const char* fmt, ...);
    bool vsendQueuerACK(fxStr& emsg, const char* fmt, va_list ap);

    bool newTrigger(fxStr& emsg, const char* fmt, ...);
    bool vnewTrigger(fxStr& emsg, const char* fmt, va_list ap);
    bool loadTrigger(fxStr& emsg);
    bool cancelTrigger(fxStr& emsg);
    void triggerEvent(const TriggerMsgHeader& h, const char* data);
    void logEventMsg(const TriggerMsgHeader&h, fxStr& msg);
    void logJobEventMsg(const TriggerMsgHeader&, const JobExt&);
    void logSendEventMsg(const TriggerMsgHeader&, const JobExt&, const char*);
    void logModemEventMsg(const TriggerMsgHeader&,
	const ModemExt&, const char*);
    void logRecvEventMsg(const TriggerMsgHeader&,
	const FaxRecvInfo&, const char*);

    virtual void initDefaultJob(void);
    void parmBotch(Token t);
    bool checkAccess(const Job& job, Token t, u_int op);
    bool checkParm(Job&, Token t, u_int op);
    bool checkJobState(Job*);
    void replyJobParamValue(Job&, int code, Token t);
    void replyBoolean(int code, bool b);
    bool setValue(u_short& v, const char* value, const char* what,
	const char* valNames[], u_int nValNames);
    void flushPreparedDocuments(Job& job);
    bool setJobParameter(Job&, Token t, const fxStr& value);
    bool setJobParameter(Job&, Token t, u_short value);
    bool setJobParameter(Job&, Token t, time_t value);
    bool setJobParameter(Job&, Token t, bool b);
    bool setJobParameter(Job&, Token t, float value);
    bool docType(const char* docname, FaxSendOp& op);
    bool checkAddDocument(Job&, Token type, const char* docname, FaxSendOp&);
    void addCoverDocument(Job&, const char* docname);
    void addDocument(Job&, const char* docname);
    void addPollOp(Job&, const char* sep, const char* pwd);
    void newJobCmd(void);
    bool newJob(fxStr& emsg);
    Job* findJob(const char* jobid, fxStr& emsg);
    Job* findJobInMemmory(const char* jobid);
    Job* findJobOnDisk(const char* jobid, fxStr& emsg);
    bool updateJobFromDisk(Job& job);
    void replyCurrentJob(const char* leader);
    void setCurrentJob(const char* jobid);
    Job* preJobCmd(const char* op, const char* jobid, fxStr& emsg);
    void operateOnJob(const char* jobid, const char* what, const char* op);
    void deleteJob(const char* jobid);
    void killJob(const char* jobid);
    void replyBadJob(const Job& job, Token t);
    void resetJob(const char* jobid);
    void interruptJob(const char* jobid);
    void suspendJob(const char* jobid);
    void submitJob(const char* jobid);
    void waitForJob(const char* jobid);
    bool updateJobOnDisk(Job& req, fxStr& emsg);
    bool lockJob(Job& job, int how, fxStr& emsg);
    bool lockJob(Job& job, int how);
    void unlockJob(Job& job);
#ifdef OLDPROTO_SUPPORT
    void readJobs(void);
#endif
    void purgeJobs(void);
    void jstatCmd(const Job&);
    void jstatLine(Token t, const char* fmt ...);

    const char* compactTime(time_t t);
    void Jprintf(FILE* fd, const char* fmt, const Job& job);

    u_int getJobNumber(fxStr&);
    u_int getDocumentNumber(fxStr&);

    bool getRecvDocStatus(RecvInfo& ri);
    RecvInfo* getRecvInfo(const fxStr& qfile, const struct stat& sb);
    const char* compactRecvTime(time_t t);
    void Rprintf(FILE*, const char*, const RecvInfo&, const struct stat&);

    void getServerStatus(const char* fileName, fxStr& status);
    void Mprintf(FILE*, const char*, const ModemConfig&);
public:
    HylaFAXServer();
    virtual ~HylaFAXServer();

    static void setupPermissions(void);
    static void closeAllBut(int fd);
    static void closeAllDispatched();

    static void sanitize(fxStr& s);
    static void canonModem(fxStr& s);
    static void canonDevID(fxStr& s);

    virtual void open(void);
    virtual void close(void);

    virtual int inputReady(int);
    void timerExpired(long, long);
};
inline void HylaFAXServer::pushToken(Token t)		{ pushedToken = t; }

/*
 * Directories in the spooling area are treated
 * specially to hide implementation details and
 * privileged information that clients have no
 * business seeing.  Also we implement an access
 * control system that is built on top of the
 * normal UNIX protection mechanisms.
 */ 
struct SpoolDir {
    const char*	pathname;
    bool adminOnly;	// accessible by unprivileged clients
    bool storAble;	// unprivileged clients may STOR files
    bool deleAble;	// unprivileged clients may DELE files
    ino_t ino;		// directory inode number
    bool (*isVisibleFile)(const char*, const struct stat&);
    void (HylaFAXServer::*listDirectory)(FILE*, const SpoolDir&, DIR*);
    void (HylaFAXServer::*listFile)(FILE*, const SpoolDir&,
        const char*, const struct stat&);
    void (HylaFAXServer::*nlstDirectory)(FILE*, const SpoolDir&, DIR*);
    void (HylaFAXServer::*nlstFile)(FILE*, const SpoolDir&,
        const char*, const struct stat&);
    void (HylaFAXServer::*delFile)(const SpoolDir&, const char*);
    void (HylaFAXServer::*retrFile)(const SpoolDir&, const char*);
    void (HylaFAXServer::*storFile)(const SpoolDir&, const char*);
};

#define	IS(x)	((state & (S_##x)) != 0)

#endif /* _HylaFAXServer_ */