Hylafax Mailing List Archives
|
[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
Re: [hylafax-users] multiport modem and user based grouping
* Lee Howard <faxguy@xxxxxxxxxxxxxxxx> [060112 11:38]:
> Attached is a patch that will give you this feature. It should apply to
> most recent versions of HylaFAX. If you desire it in a tarball it is in
> 4.2.5.1 which can be found at:
>
> http://hylafax.sourceforge.net/news/4.2.5.1.php
>
> The feature basically adds an "owner" option to DestControls.
> Documentation can be seen in 'man destctrls' and here:
>
> http://hylafax.sourceforge.net/man/destctrls.php
>
> But, basically by adding an "owner" field to the DestControls entry you
> will restrict the application of that entry to apply only to jobs
> submitted by that owner (hfaxd login username). So, for example
> DestControls entries of:
>
> .* owner=omer modem=ttyS0
> .* owner=lee modem=ttyS1
>
> This would make all jobs submitted by "omer" be sent through modem ttyS0
> and all jobs submitted by "lee" be sent through modem ttyS1.
I've attached the start of another approach to gaining this
functionality, but in a bit more generic.
The intention is to make a "jobcontrls", similar to destcontrols.
The idea is that you can control jobs (same as destcontrols) based on a
match of any (or no) job parameters.
This version currently only supports dest, owner, and client, but can
easily be extended to include almost any user-specifiable job parameter.
Any, or none of the 3 fields can be matched, and all are regex matches.
This patch slightly changes the format of the destcontrols file (with
the thought that this could grow into a jobcontrol file, or such,
possibly with a backwards compatible destcontrols parser ). The file
format is:
[dest=<dest regex>] [owner=<owner_regex>] [client=<client_regex>] action=...
So, basically, instead of just the single "destination regex", you can
specify regex for other input fields, somehting like:
dest=911 RejectNotice="No 911"
owner=aidan client=ifax RejectNotice=reject-aidan-remote
owner=aidan client=localhost RejectNotice=reject-aidan-LOCAL
dest=+1215 client=localhost Modem=localgroup
I have a few concerns with the format of this file. I don't really like
the "overloading" of both input fields and output fields with the =
sign. A possible format could be a white-space separated file:
<dest_regex> <owner_regex> <client_regex> <action1> [ [<action2] ... ]
but this doesn't lead to a very extendable format, and makes adding (or
removing) fields problematic.
Thoughts, comments?
a.
--
Aidan Van Dyk aidan@xxxxxxxx
Senior Software Developer +1 215 438-4638 x8103
iFAX Solutions, Inc. http://www.ifax.com/
===== faxd/DestControl.c++ 1.10 vs edited =====
--- 1.10/faxd/DestControl.c++ 2004-04-21 12:30:45 -04:00
+++ edited/faxd/DestControl.c++ 2006-03-14 14:08:15 -05:00
@@ -42,12 +42,41 @@
#define isDefined(b) (defined & b)
#define setDefined(b) (defined |= b)
+
+static bool IsREmatch (RE* p, const fxStr& m)
+{
+ if (p)
+ return p->Find(m);
+ return true;
+}
+
+static bool IsREerror (RE* p)
+{
+ if (p)
+ return p->getErrorCode() > REG_NOMATCH;
+ return false;
+}
+
const DestControlInfo DestControlInfo::defControlInfo;
-DestControlInfo::DestControlInfo() : pattern("") { defined = 0; }
-DestControlInfo::DestControlInfo(const char* re) : pattern(re) { defined = 0; }
+DestControlInfo::DestControlInfo()
+{
+ defined = 0;
+}
+
+#ifdef AIDAN
+DestControlInfo::DestControlInfo(const char* d, const char* o)
+ : dest(d)
+ , owner(o)
+{
+ defined = 0;
+}
+#endif
+
DestControlInfo::DestControlInfo(const DestControlInfo& other)
- : pattern(other.pattern)
+ : dest(other.dest)
+ , owner(other.owner)
+ , client(other.client)
, rejectNotice(other.rejectNotice)
, modem(other.modem)
, tod(other.tod)
@@ -71,7 +100,15 @@
void
DestControlInfo::parseEntry(const char* tag, const char* value, bool quoted)
{
- if (streq(tag, "rejectnotice")) {
+ if (streq(tag, "destination")) {
+ dest = new RE(value);
+ } else if (streq(tag, "dest")) {
+ dest = new RE(value);
+ } else if (streq(tag, "owner")) {
+ owner = new RE(value);
+ } else if (streq(tag, "client")) {
+ client = new RE(value);
+ } else if (streq(tag, "rejectnotice")) {
rejectNotice = value;
} else if (streq(tag, "modem")) {
modem = value;
@@ -100,6 +137,7 @@
vres = getNumber(value);
setDefined(DCI_VRES);
} else {
+ logError(" - appending as args");
if( args != "" )
args.append('\0');
const char* quote = quoted ? "\"" : "";
@@ -203,7 +241,7 @@
}
const DestControlInfo&
-DestControl::operator[](const fxStr& canon)
+DestControl::find (const fxStr& f_dest, const fxStr& f_owner, const fxStr& f_client)
{
struct stat sb;
if (Sys::stat(filename, sb) == 0 && sb.st_mtime > lastModTime) {
@@ -213,7 +251,9 @@
}
for (u_int i = 0, n = info.length(); i < n; i++) {
DestControlInfo& dci = info[i];
- if (dci.pattern.Find(canon))
+ if (IsREmatch(dci.dest, f_dest)
+ && IsREmatch(dci.owner, f_owner)
+ && IsREmatch(dci.client, f_client) )
return (dci);
}
return (DestControlInfo::defControlInfo);
@@ -269,26 +309,8 @@
for (;;) {
if (!readLine(fp, line, sizeof (line)-1))
return (false);
- char* cp;
- for (cp = line; *cp && !isspace(*cp); cp++)
- ;
- if (*cp == '\0')
- continue;
- if (cp == line) {
- parseError("Missing regular expression.");
- skipEntry(fp, line, sizeof (line)-1);
- return (true);
- }
- *cp++ = '\0';
- DestControlInfo dci(line);
- if (dci.pattern.getErrorCode() > REG_NOMATCH) {
- RE& re = dci.pattern;
- fxStr emsg;
- re.getError(emsg);
- parseError("Bad regular expression: %s: " | emsg, re.pattern());
- skipEntry(fp, line, sizeof (line)-1);
- return (true);
- }
+ DestControlInfo dci;
+ char* cp = line;
for (;;) {
while (isspace(*cp))
cp++;
@@ -343,6 +365,30 @@
*cp++ = '\0';
if (tag[0] != '\0')
dci.parseEntry(tag, value, quoted);
+ }
+ if (IsREerror(dci.dest) ) {
+ RE& re = *dci.dest;
+ fxStr emsg;
+ re.getError(emsg);
+ parseError("Bad destination regular expression: %s: " | emsg, re.pattern());
+ skipEntry(fp, line, sizeof (line)-1);
+ return (true);
+ }
+ if (IsREerror(dci.owner) ) {
+ RE& re = *dci.owner;
+ fxStr emsg;
+ re.getError(emsg);
+ parseError("Bad owner regular expression: %s: " | emsg, re.pattern());
+ skipEntry(fp, line, sizeof (line)-1);
+ return (true);
+ }
+ if (IsREerror(dci.client) ) {
+ RE& re = *dci.client;
+ fxStr emsg;
+ re.getError(emsg);
+ parseError("Bad client regular expression: %s: " | emsg, re.pattern());
+ skipEntry(fp, line, sizeof (line)-1);
+ return (true);
}
}
}
===== faxd/DestControl.h 1.7 vs edited =====
--- 1.7/faxd/DestControl.h 2004-04-21 12:30:45 -04:00
+++ edited/faxd/DestControl.h 2006-03-14 14:08:34 -05:00
@@ -40,7 +40,12 @@
*/
class DestControlInfo {
private:
- RE pattern; // destination pattern
+ /* Match fields */
+ REPtr dest; // destination pattern
+ REPtr owner; // owner pattern
+ REPtr client; // client pattern
+
+ /* Control fields */
u_long defined; // parameters that were defined
u_int maxConcurrentCalls; // max number of parallel calls
u_int maxSendPages; // max pages in a send job
@@ -58,11 +63,14 @@
friend class DestControl;
public:
- DestControlInfo(const char* regex);
+#ifdef AIDAN
+ DestControlInfo(const char* dest = "", const char* owner = "");
+#endif
DestControlInfo();
DestControlInfo(const DestControlInfo& other);
~DestControlInfo();
+
int compare(const DestControlInfo*) const;
void parseEntry(const char* tag, const char* value, bool quoted);
@@ -102,6 +110,7 @@
void setFilename(const char* filename);
- const DestControlInfo& operator[](const fxStr&);
+// const DestControlInfo& operator[](const fxStr&);
+ const DestControlInfo& find (const fxStr& canon, const fxStr& owner, const fxStr& client);
};
#endif /* _DestControl_ */
===== faxd/faxQueueApp.c++ 1.70 vs edited =====
--- 1.70/faxd/faxQueueApp.c++ 2005-10-27 17:53:07 -04:00
+++ edited/faxd/faxQueueApp.c++ 2006-03-14 14:09:02 -05:00
@@ -232,6 +232,11 @@
closedir(dir);
}
+const DestControlInfo&
+faxQueueApp::getDCI(const Job& j, const FaxRequest*r)
+{
+ return destCtrls.find(j.dest, r->owner, r->client);
+}
/*
* Process a job. Prepare it for transmission and
* pass it on to the thread that does the actual
@@ -442,8 +447,8 @@
setDead(job);
}
}
- if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], destCtrls[targetjob->dest]);
- else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, destCtrls[targetjob->dest]);
+ if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], getDCI(*targetjob, targetjob->breq));
+ else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, getDCI(*targetjob, targetjob->breq));
else {
/*
* This destination was marked as called, but all jobs to this
@@ -2188,17 +2193,20 @@
* ready for processing.
*/
Job* jb;
- const DestControlInfo& dci = destCtrls[job.dest];
u_int n = 1;
- while (isOKToCall(di, dci, n) && (jb = di.nextBlocked())) {
- setReadyToRun(*jb);
- if (!di.supportsBatching()) n++;
+ while (jb = di.nextBlocked()) {
FaxRequest* req = readRequest(*jb);
- if (req) {
+ if (! req)
+ continue;
+ const DestControlInfo& dci = getDCI(job, req);
+ if (isOKToCall(di, dci, n) )
+ {
+ setReadyToRun(*jb);
+ if (!di.supportsBatching()) n++;
req->notice = "";
updateRequest(*req, *jb);
- delete req;
}
+ delete req;
}
}
@@ -2291,7 +2299,7 @@
* Do per-destination processing and checking.
*/
DestInfo& di = destJobs[job.dest];
- const DestControlInfo& dci = destCtrls[job.dest];
+ const DestControlInfo& dci = getDCI(job, req);
/*
* Constrain the maximum number of times the phone
* will be dialed and/or the number of attempts that
===== faxd/faxQueueApp.h 1.20 vs edited =====
--- 1.20/faxd/faxQueueApp.h 2005-09-27 15:03:09 -04:00
+++ edited/faxd/faxQueueApp.h 2006-03-14 14:06:30 -05:00
@@ -174,6 +174,7 @@
void startTimeout(long ms);
void stopTimeout(const char* whichdir);
const fxStr& pickCmd(const FaxRequest& req);
+ const DestControlInfo& getDCI(const Job& job, const FaxRequest* req);
// FIFO-related stuff
void childStatus(pid_t, int); // Dispatcher hook
int inputReady(int); // Dispatcher hook
Attachment:
signature.asc
Description: Digital signature