2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
14 PrintJobInfoCallback cb
;
20 buffer(), filename(), file(0), tmp(false) {}
28 class WvTCPConnGC
: public WvTCPConn
33 WvTCPConnGC(WvStringParm _addr
, LpdRequest
* _req
):
34 WvTCPConn(_addr
), req(_req
) {}
35 virtual ~WvTCPConnGC() {
41 PrintQueueLPD::PrintQueueLPD(WvStringParm _name
, const UniConf _cfg
,
43 PrintQueue(_name
, _cfg
, _log
)
45 WvString
sectionname("queues/%s", name
);
46 remotePrinter
= Unknown
;
48 if (cfg
[sectionname
]["lpdserver"].exists())
50 if (cfg
[sectionname
]["networkprinter"].getme(0))
51 remotePrinter
= Network
;
53 remotePrinter
= NetIntegrator
;
56 if (cfg
[sectionname
].exists() &&
57 ((remotePrinter
== Network
) || (remotePrinter
== NetIntegrator
)))
59 if (cfg
[sectionname
]["queue"].exists())
60 remotequeue
= cfg
[sectionname
]["queue"].getme(name
);
62 remotequeue
= WvString("lp");
64 serveraddr
= cfg
[sectionname
]["lpdserver"].getme(0);
68 log(WvLog::Error
, "LPD queue %s does not have a server\n", _name
);
72 if (!strchr(serveraddr
, ':'))
73 serveraddr
.append(":printer");
75 else if (remotePrinter
== Unknown
)
77 /* error here, this shouldn't happen, we should know what type
78 of remote server we're using */
79 log(WvLog::Error
, "Uknown remote server type! (%s)\n", _name
);
83 log(WvLog::Debug
, "Set up LPD bounce queue %s, to queue %s on %s\n",
84 name
, remotequeue
, serveraddr
);
87 void PrintQueueLPD::callback_filter(bool ok
, void* userdata
)
89 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
96 req
->file
= new WvFile(req
->filename
, O_RDONLY
);
97 if (!req
->file
->isok())
99 log(WvLog::Error
, "there is a problem reading the spool file %s (%s)\n", req
->filename
, req
->file
->errstr());
104 conn
= new WvTCPConnGC(serveraddr
, req
);
106 log(WvLog::Debug
, "sending off job %s to queue %s on LPD server %s\n", active
->get_id(), remotequeue
, serveraddr
);
108 /* remote queues may have different names than our named remote queue, so
109 assume that it's going to be lp@<hostname> */
110 conn
->print("\2%s\n", remotequeue
);
113 conn
->setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_job
), req
);
114 activelist
.append(conn
, true);
120 void PrintQueueLPD::callback_submit_job(WvStream
&s
, void* userdata
)
122 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
125 if (s
.alarm_was_ticking
)
128 "connection to queue %s of LPD server %s timed out\n",
129 remotequeue
, serveraddr
);
138 log(WvLog::Debug
, "receive printer job command accepted\n");
140 req
->buffer
= WvString("H%s\n"
157 active
->spoolInfo
->filename
);
159 s
.print("\2%s cfA%03s%s\n", req
->buffer
.len(), active
->get_id(), active
->hostname
);
161 s
.setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_control
), req
);
166 "LPD server %s (queue %s) refused our job %s\n",
167 serveraddr
, remotequeue
, active
->get_id());
173 void PrintQueueLPD::callback_submit_control(WvStream
&s
, void* userdata
)
175 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
178 if (s
.alarm_was_ticking
)
181 "connection to queue %s of LPD server %s timed out\n",
182 remotequeue
, serveraddr
);
191 log(WvLog::Debug
, "receive control file command accepted\n");
192 s
.print(req
->buffer
);
195 s
.setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_data
), req
);
200 "LPD server %s (queue %s) refused our job %s (control file)\n",
201 serveraddr
, remotequeue
, active
->get_id());
207 void PrintQueueLPD::callback_submit_data(WvStream
&s
, void* userdata
)
209 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
213 if (s
.alarm_was_ticking
)
216 "connection to queue %s of LPD server %s timed out\n",
217 remotequeue
, serveraddr
);
226 log(WvLog::Debug
, "control file accepted\n");
228 if (stat(req
->filename
, &si
) == -1)
230 log(WvLog::Error
, "error getting %s information: %s\n", req
->filename
, strerror(errno
));
235 s
.print("\3%s dfA%03s%s\n", si
.st_size
, active
->get_id(), active
->hostname
);
237 s
.setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_ack_data
), req
);
243 "LPD server %s (queue %s) refused our job %s (control file)\n",
244 serveraddr
, remotequeue
, active
->get_id());
250 void PrintQueueLPD::callback_submit_ack_data(WvStream
&s
, void* userdata
)
252 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
255 if (s
.alarm_was_ticking
)
258 "connection to queue %s of LPD server %s timed out\n",
259 remotequeue
, serveraddr
);
268 log(WvLog::Debug
, "receive data file command accepted\n");
271 s
.force_select(false, true);
272 s
.setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_send_data
), req
);
277 "LPD server %s (queue %s) refused our job %s\n",
278 serveraddr
, remotequeue
, active
->get_id());
284 void PrintQueueLPD::callback_submit_send_data(WvStream
&s
, void* userdata
)
286 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
290 if (s
.alarm_was_ticking
)
293 "connection to queue %s of LPD server %s timed out\n",
294 remotequeue
, serveraddr
);
300 len
= req
->file
->read(buf
, sizeof(buf
));
304 if (!req
->file
->isok())
307 s
.undo_force_select(false, true);
308 s
.setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_submit_send_data_fin
), req
);
313 void PrintQueueLPD::callback_submit_send_data_fin(WvStream
&s
, void* userdata
)
317 if (s
.alarm_was_ticking
)
320 "connection to queue %s of LPD server %s timed out\n",
321 remotequeue
, serveraddr
);
340 void PrintQueueLPD::print_job(PrintJob
* job
)
345 if (active
|| activelist
.count())
350 req
= new struct LpdRequest
;
352 in
= new WvFile(active
->get_file(), O_RDONLY
);
355 log(WvLog::Error
, "there is a problem reading the spool file %s (%s)\n", job
->get_file(), in
->errstr());
363 req
->filename
= WvString("%s/%03s-tmp", spool
, active
->get_id());
366 tmp
= new WvFile(req
->filename
, O_CREAT
|O_WRONLY
|O_TRUNC
);
369 log(WvLog::Error
, "there is a problem writing the temporary file %s (%s)\n", req
->filename
, tmp
->errstr());
377 do_filter(in
, true, *tmp
, PrintFilterCallback(this, &PrintQueueLPD::callback_filter
), req
);
381 req
->filename
= active
->get_file();
382 callback_filter(true, req
);
386 void PrintQueueLPD::callback_lpq(WvStream
&s
, void* userdata
)
388 LpdRequest
* req
= static_cast<LpdRequest
*>(userdata
);
394 req
->buffer
.append("%s\n", str
);
397 if (s
.alarm_was_ticking
)
399 req
->buffer
.append("\nconnection timed out");
400 log(WvLog::Warning
, req
->buffer
);
406 lpq_crap
= req
->buffer
;
411 void PrintQueueLPD::foreach(const PrintJobInfoCallback
& cb
)
413 PrintJobList::Iter
i(jobs
);
417 LpdRequest
* req
= new LpdRequest
;
418 WvTCPConn
* conn
= new WvTCPConnGC(serveraddr
, req
);
421 req
->buffer
= "\nRemote LPD queue status:\n";
423 log(WvLog::Debug
, "the server address is %s\n", *conn
->src());
425 if (!jobs
.isempty() && jobs
.first() == active
)
433 if (i().is_complete())
435 info
.position
= pos
++;
436 info
.id
= i().get_id();
437 info
.username
= i().username
;
438 info
.filename
= i().spoolInfo
->filename
;
440 if (stat(i().get_file(), &si
) == -1)
442 log(WvLog::Error
, "error getting %s information: %s\n", i().get_file(), strerror(errno
));
446 info
.size
= si
.st_size
;
452 /* The callback will take care of calling cb(0) at the appropriate
454 conn
->print("\3%s\n", remotequeue
);
456 conn
->setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_lpq
), req
);
460 void PrintQueueLPD::callback_lprm(WvStream
&s
, void* userdata
)
464 if (s
.alarm_was_ticking
)
466 log(WvLog::Warning
, "lprm connection to queue %s on LPD server %s timed out\n", remotequeue
, serveraddr
);
471 if (s
.read(buf
, sizeof(buf
)))
475 log(WvLog::Debug2
, "lprm connection to queue %s on LPD server %s finished\n", remotequeue
, serveraddr
);
478 bool PrintQueueLPD::cancel(unsigned short id
, WvStringParm agent
)
480 bool found
= PrintQueue::cancel(id
, agent
);
485 conn
= new WvTCPConn(serveraddr
);
486 conn
->print("\5%s %s %s\n", remotequeue
, agent
, id
);
488 conn
->setcallback(WvStreamCallback(this, &PrintQueueLPD::callback_lprm
), 0);
495 bool PrintQueueLPD::isok() const
497 return serveraddr
&& PrintQueue::isok();