HEAD: removed mrwise debug crud from uniclientgen.cc.
[wvapps.git] / wvprint / queue.cc
blob53ccea4e22065dda2a9415d9fbb137ab869c9d00
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
5 * This is the PrintQueue class for handling various queue functions
6 * under WvPrint.
7 */
8 #include <wvpipe.h>
9 #include <wvtimeoutstream.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include "queue.h"
13 #include "localqueue.h"
14 #include "lpdqueue.h"
16 const unsigned int MAX_JOBS = 1000;
18 PrintQueue* PrintQueue::new_queue(WvStringParm name, const UniConf cfg,
19 WvLog& log)
21 WvString sectionname("queues/%s", name);
22 const UniConf section = cfg[sectionname];
23 PrintQueue* queue = 0;
25 do {
26 /* We're not in charge of queue aliases, shouldn't happen. */
27 if (section["alias"].exists())
29 queue = 0;
30 break;
33 if (section["device"].exists())
35 queue = new PrintQueueLocal(name, cfg, log);
36 break;
39 if (section["lpdserver"].exists() || section["remotehost"].exists())
41 queue = new PrintQueueLPD(name, cfg, log);
42 break;
44 } while (0);
46 if (queue)
48 if (!queue->isok())
50 RELEASE(queue);
54 return queue;
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()
61 reconfig();
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);
72 if (!spool)
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",
86 active->get_id());
87 active = 0;
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())
99 return;
101 print_job(jobs.first());
103 if (!active)
104 activelist.append(new WvTimeoutStream(5000), true);
107 PrintJob* PrintQueue::new_job()
109 PrintJobList::Iter i(jobs);
110 PrintJob *job;
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.
118 mkdir(spool, 0755);
120 /* If there are too many jobs in the queue, we just puke, hoping
121 it'll get better. */
122 if (jobs.count() >= 999)
123 return NULL;
125 if (next == MAX_JOBS)
126 next = 1;
128 /* Despite how evil this looks, we are going through the job list
129 * looking for a "free" slot for this job
131 i.rewind();
132 while (i.next())
134 if (i->get_id() == next)
136 i.rewind();
137 ++next;
138 if (next == MAX_JOBS)
139 next = 1;
143 last = next;
145 job = new PrintJob(log, *this, last, spool);
147 jobs.append(job, true);
149 return job;
152 bool PrintQueue::cancel(unsigned short id, WvStringParm agent)
154 PrintJobList::Iter i(jobs);
155 bool found = false;
157 i.rewind();
158 while (i.next())
160 if (i().get_id() == id)
162 found = true;
163 break;
167 if (found)
169 if ((strcmp(agent, i().username) == 0) || (strcmp(agent, "root") == 0))
171 if (i.ptr() == active)
173 zap();
174 append(&activelist, false);
175 active = 0;
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 */
182 activelist.zap();
184 else
186 log(WvLog::Warning, "user %s tried to cancel job %s on queue %s owned by another user\n", agent, id, name);
187 found = false;
190 else
191 log(WvLog::Warning, "trying to cancel non-existent job %s on queue %s\n", id, name);
193 return found;
196 unsigned int PrintQueue::get_active_id() const
198 return active ? active->get_id() : 0;
201 size_t PrintQueue::job_count() const
203 return jobs.count();
206 void PrintQueue::callback_pipe(WvStream& s, void*)
208 WvPipe& pipe = static_cast<WvPipe&>(s);
209 char buf[1];
210 size_t len;
212 len = pipe.read(buf, sizeof(buf));
213 if (len)
214 log(WvLog::Debug, "callback_pipe actually read some bytes from the pipe, that's strange...");
216 if (!pipe.isok())
218 bool ok = false;
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());
226 else
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());
233 else
234 ok = true;
237 else
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*)
249 char buf[1024];
250 size_t len;
252 len = s.read(buf, sizeof(buf));
253 s.read_requires_writable->write(buf, len);
255 if (!s.isok())
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)
264 return;
266 filter_callback = _cb;
267 userdata = _userdata;
269 if (!!filter)
271 WvPipe* pipe;
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());
279 in->close();
280 if (auto_delete)
281 RELEASE(in);
283 if (pipe->isok())
285 pipe->setcallback(WvStreamCallback(this, &PrintQueue::callback_pipe), 0);
286 activelist.append(pipe, true);
287 out.close();
289 else
291 log(WvLog::Error, "there is a problem with the print filter (%s): %s\n", filter, pipe->errstr());
292 RELEASE(pipe);
295 else
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);
310 i.rewind();
311 while (i.next() && i().get_id() != job_id)
314 if (i().get_id() == job_id)
316 PrintJob *tempjob = new PrintJob(*i);
317 jobs.unlink(&(*i));
318 jobs.prepend(tempjob, true);
320 else
321 return false;
323 return true;