2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
5 * This is the PrintQueue class for handling various queue functions
9 #include <wvtimeoutstream.h>
11 #include <sys/types.h>
13 #include "localqueue.h"
16 const unsigned int MAX_JOBS
= 1000;
18 PrintQueue
* PrintQueue::new_queue(WvStringParm name
, const UniConf cfg
,
21 WvString
sectionname("queues/%s", name
);
22 const UniConf section
= cfg
[sectionname
];
23 PrintQueue
* queue
= 0;
26 /* We're not in charge of queue aliases, shouldn't happen. */
27 if (section
["alias"].exists())
33 if (section
["device"].exists())
35 queue
= new PrintQueueLocal(name
, cfg
, log
);
39 if (section
["lpdserver"].exists() || section
["remotehost"].exists())
41 queue
= new PrintQueueLPD(name
, cfg
, log
);
57 PrintQueue::PrintQueue(WvStringParm _name
, const UniConf _cfg
, WvLog
&_log
):
58 last(0), filter_callback(0), userdata(0), cfg(_cfg
), log(_log
),
59 active(0), name(_name
), lpq_crap()
63 append(&activelist
, false);
65 log(WvLog::Debug
, "Setting up queue %s in %s\n", name
, spool
);
68 void PrintQueue::reconfig()
70 WvString
sectionname("queues/%s", name
);
74 spool
= cfg
["spooldir"].getme("/var/spool/wvprint");
75 spool
= WvString("%s/%s", spool
, name
);
78 filter
= cfg
[sectionname
]["filter"].getme("");
81 bool PrintQueue::pre_select(SelectInfo
& si
)
83 if (active
&& (activelist
.count() == 0))
85 log(WvLog::Debug
, "it seems there was a problem printing job %s\n",
88 activelist
.append(new WvTimeoutStream(5000), true);
91 return (!active
&& !jobs
.isempty() && (activelist
.count() == 0) && jobs
.first()->is_complete()) || WvIStreamList::pre_select(si
);
94 void PrintQueue::execute()
96 WvIStreamList::execute();
98 if (jobs
.isempty() || active
|| activelist
.count())
101 print_job(jobs
.first());
104 activelist
.append(new WvTimeoutStream(5000), true);
107 PrintJob
* PrintQueue::new_job()
109 PrintJobList::Iter
i(jobs
);
111 unsigned short next
= last
+ 1;
113 /* Here, we try to create the spool directory, because we try to be
114 * helpful, but we don't try too hard. We let errors be logged when
115 * the directory is actually used, so the user can correct them and
116 * try again without needing to restart the daemon.
120 /* If there are too many jobs in the queue, we just puke, hoping
122 if (jobs
.count() >= 999)
125 if (next
== MAX_JOBS
)
128 /* Despite how evil this looks, we are going through the job list
129 * looking for a "free" slot for this job
134 if (i
->get_id() == next
)
138 if (next
== MAX_JOBS
)
145 job
= new PrintJob(log
, *this, last
, spool
);
147 jobs
.append(job
, true);
152 bool PrintQueue::cancel(unsigned short id
, WvStringParm agent
)
154 PrintJobList::Iter
i(jobs
);
160 if (i().get_id() == id
)
169 if ((strcmp(agent
, i().username
) == 0) || (strcmp(agent
, "root") == 0))
171 if (i
.ptr() == active
)
174 append(&activelist
, false);
178 log(WvLog::Info
, "job %s on queue %s canceled by %s\n", id
, name
, agent
);
179 jobs
.unlink(i
.ptr());
181 /* Kill off the active stream */
186 log(WvLog::Warning
, "user %s tried to cancel job %s on queue %s owned by another user\n", agent
, id
, name
);
191 log(WvLog::Warning
, "trying to cancel non-existent job %s on queue %s\n", id
, name
);
196 unsigned int PrintQueue::get_active_id() const
198 return active
? active
->get_id() : 0;
201 size_t PrintQueue::job_count() const
206 void PrintQueue::callback_pipe(WvStream
& s
, void*)
208 WvPipe
& pipe
= static_cast<WvPipe
&>(s
);
212 len
= pipe
.read(buf
, sizeof(buf
));
214 log(WvLog::Debug
, "callback_pipe actually read some bytes from the pipe, that's strange...");
220 if (pipe
.child_exited())
222 if (pipe
.child_killed())
224 log(WvLog::Error
, "filter for job %s killed with signal %s\n", active
->get_id(), pipe
.exit_status());
228 if (pipe
.exit_status())
230 log(WvLog::Debug
, strerror(pipe
.exit_status()));
231 log(WvLog::Error
, "filter for job %s exited with return code %s\n", active
->get_id(), pipe
.exit_status());
239 log(WvLog::Error
, "pipe is not ok, but child is still alive?");
242 if (!! filter_callback
)
243 filter_callback(ok
, userdata
);
247 void PrintQueue::callback_forward(WvStream
& s
, void*)
252 len
= s
.read(buf
, sizeof(buf
));
253 s
.read_requires_writable
->write(buf
, len
);
256 if (!! filter_callback
)
257 filter_callback(true, userdata
);
260 void PrintQueue::do_filter(WvFile
* in
, bool auto_delete
,
261 WvFDStream
& out
, const PrintFilterCallback
& _cb
, void* _userdata
)
263 if (!active
|| !in
->isok() || !out
.isok() || !_cb
)
266 filter_callback
= _cb
;
267 userdata
= _userdata
;
272 const char *args
[] = {0, 0};
274 args
[0] = filter
.edit();
276 pipe
= new WvPipe(args
[0], args
, false, false, false,
277 in
->getrfd(), out
.getwfd());
285 pipe
->setcallback(WvStreamCallback(this, &PrintQueue::callback_pipe
), 0);
286 activelist
.append(pipe
, true);
291 log(WvLog::Error
, "there is a problem with the print filter (%s): %s\n", filter
, pipe
->errstr());
297 log(WvLog::Debug
, "No filter defined for %s\n", name
);
299 in
->read_requires_writable
= &out
;
301 in
->setcallback(WvStreamCallback(this, &PrintQueue::callback_forward
), 0);
303 activelist
.append(in
, auto_delete
);
307 bool PrintQueue::increase_priority(unsigned int job_id
)
309 PrintJobList::Iter
i(jobs
);
311 while (i
.next() && i().get_id() != job_id
)
314 if (i().get_id() == job_id
)
316 PrintJob
*tempjob
= new PrintJob(*i
);
318 jobs
.prepend(tempjob
, true);