Merge from Tim - don't reinsert UNIX job if already exists.
[Samba.git] / source / printing / printing.c
blob14f39b858cb7d8bf11cbdb441e1be25fd6774bea
1 #define OLD_NTDOMAIN 1
2 /*
3 Unix SMB/Netbios implementation.
4 Version 3.0
5 printing backend routines
6 Copyright (C) Andrew Tridgell 1992-2000
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 extern int DEBUGLEVEL;
26 /*
27 the printing backend revolves around a tdb database that stores the
28 SMB view of the print queue
30 The key for this database is a jobid - a internally generated number that
31 uniquely identifies a print job
33 reading the print queue involves two steps:
34 - possibly running lpq and updating the internal database from that
35 - reading entries from the database
37 jobids are assigned when a job starts spooling.
40 struct printjob {
41 pid_t pid; /* which process launched the job */
42 int sysjob; /* the system (lp) job number */
43 int fd; /* file descriptor of open file if open */
44 time_t starttime; /* when the job started spooling */
45 int status; /* the status of this job */
46 size_t size; /* the size of the job so far */
47 BOOL spooled; /* has it been sent to the spooler yet? */
48 BOOL smbjob; /* set if the job is a SMB job */
49 fstring filename; /* the filename used to spool the file */
50 fstring jobname; /* the job name given to us by the client */
51 fstring user; /* the user who started the job */
52 fstring qname; /* name of the print queue the job was sent to */
55 /* the open printing.tdb database */
56 static TDB_CONTEXT *tdb;
57 static pid_t local_pid;
59 #define PRINT_MAX_JOBID 10000
60 #define UNIX_JOB_START PRINT_MAX_JOBID
62 #define PRINT_SPOOL_PREFIX "smbprn."
63 #define PRINT_DATABASE_VERSION 2
65 /****************************************************************************
66 initialise the printing backend. Called once at startup.
67 Does not survive a fork
68 ****************************************************************************/
69 BOOL print_backend_init(void)
71 char *sversion = "INFO/version";
73 if (tdb && local_pid == sys_getpid()) return True;
74 tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
75 if (!tdb) {
76 DEBUG(0,("Failed to open printing backend database\n"));
78 local_pid = sys_getpid();
80 /* handle a Samba upgrade */
81 tdb_lock_bystring(tdb, sversion);
82 if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
83 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
84 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
86 tdb_unlock_bystring(tdb, sversion);
88 return nt_printing_init();
91 /****************************************************************************
92 useful function to generate a tdb key
93 ****************************************************************************/
94 static TDB_DATA print_key(int jobid)
96 static int j;
97 TDB_DATA ret;
99 j = jobid;
100 ret.dptr = (void *)&j;
101 ret.dsize = sizeof(j);
102 return ret;
105 /****************************************************************************
106 useful function to find a print job in the database
107 ****************************************************************************/
108 static struct printjob *print_job_find(int jobid)
110 static struct printjob pjob;
111 TDB_DATA ret;
113 ret = tdb_fetch(tdb, print_key(jobid));
114 if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
116 memcpy(&pjob, ret.dptr, sizeof(pjob));
117 free(ret.dptr);
118 return &pjob;
121 /****************************************************************************
122 store a job structure back to the database
123 ****************************************************************************/
124 static BOOL print_job_store(int jobid, struct printjob *pjob)
126 TDB_DATA d;
127 d.dptr = (void *)pjob;
128 d.dsize = sizeof(*pjob);
130 return (0 == tdb_store(tdb, print_key(jobid), d, TDB_REPLACE));
133 /****************************************************************************
134 run a given print command
135 a null terminated list of value/substitute pairs is provided
136 for local substitution strings
137 ****************************************************************************/
138 static int print_run_command(int snum,char *command,
139 char *outfile,
140 ...)
142 pstring syscmd;
143 char *p, *arg;
144 int ret;
145 va_list ap;
147 if (!command || !*command) return -1;
149 if (!VALID_SNUM(snum)) {
150 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
151 return -1;
154 pstrcpy(syscmd, command);
156 va_start(ap, outfile);
157 while ((arg = va_arg(ap, char *))) {
158 char *value = va_arg(ap,char *);
159 pstring_sub(syscmd, arg, value);
161 va_end(ap);
163 p = PRINTERNAME(snum);
164 if (!p || !*p) p = SERVICE(snum);
166 pstring_sub(syscmd, "%p", p);
167 standard_sub_snum(snum,syscmd);
169 ret = smbrun(syscmd,outfile,False);
171 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
172 return ret;
176 /****************************************************************************
177 parse a file name from the system spooler to generate a jobid
178 ****************************************************************************/
179 static int print_parse_jobid(char *fname)
181 int jobid;
183 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
184 fname += strlen(PRINT_SPOOL_PREFIX);
186 jobid = atoi(fname);
187 if (jobid <= 0) return -1;
189 return jobid;
193 /****************************************************************************
194 list a unix job in the print database
195 ****************************************************************************/
196 static void print_unix_job(int snum, print_queue_struct *q)
198 int jobid = q->job + UNIX_JOB_START;
199 struct printjob pj;
201 /* Don't re-insert a unix job if it already exists as it mucks
202 up the timestamp. */
204 if (tdb_exists(tdb, print_key(jobid))) {
205 return;
208 ZERO_STRUCT(pj);
210 pj.pid = (pid_t)-1;
211 pj.sysjob = q->job;
212 pj.fd = -1;
213 pj.starttime = q->time;
214 pj.status = q->status;
215 pj.size = q->size;
216 pj.spooled = True;
217 pj.smbjob = False;
218 fstrcpy(pj.filename, "");
219 fstrcpy(pj.jobname, q->file);
220 fstrcpy(pj.user, q->user);
221 fstrcpy(pj.qname, lp_servicename(snum));
223 print_job_store(jobid, &pj);
227 struct traverse_struct {
228 print_queue_struct *queue;
229 int qcount, snum, maxcount;
232 /* utility fn to delete any jobs that are no longer active */
233 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
235 struct traverse_struct *ts = (struct traverse_struct *)state;
236 struct printjob pjob;
237 int i, jobid;
239 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
240 memcpy(&jobid, key.dptr, sizeof(jobid));
241 memcpy(&pjob, data.dptr, sizeof(pjob));
243 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
244 /* this isn't for the queue we are looking at */
245 return 0;
248 if (!pjob.smbjob) {
249 /* remove a unix job if it isn't in the system queue
250 any more */
251 for (i=0;i<ts->qcount;i++) {
252 if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
254 if (i == ts->qcount) tdb_delete(tdb, key);
255 return 0;
258 /* maybe it hasn't been spooled yet */
259 if (!pjob.spooled) {
260 /* if a job is not spooled and the process doesn't
261 exist then kill it. This cleans up after smbd
262 deaths */
263 if (!process_exists(pjob.pid)) {
264 tdb_delete(tdb, key);
266 return 0;
269 for (i=0;i<ts->qcount;i++) {
270 int qid = print_parse_jobid(ts->queue[i].file);
271 if (jobid == qid) break;
274 if (i == ts->qcount) {
275 /* the job isn't in the system queue - we have to
276 assume it has completed, so delete the database
277 entry */
278 tdb_delete(t, key);
281 return 0;
284 /****************************************************************************
285 check if the print queue has been updated recently enough
286 ****************************************************************************/
287 static void print_cache_flush(int snum)
289 fstring key;
290 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
291 tdb_store_int(tdb, key, -1);
294 /****************************************************************************
295 update the internal database from the system print queue for a queue
296 ****************************************************************************/
297 static void print_queue_update(int snum)
299 char *path = lp_pathname(snum);
300 char *cmd = lp_lpqcommand(snum);
301 char **qlines;
302 pstring tmp_file;
303 int numlines, i, qcount;
304 print_queue_struct *queue = NULL;
305 print_status_struct status;
306 struct printjob *pjob;
307 struct traverse_struct tstruct;
308 fstring keystr;
309 TDB_DATA data, key;
312 * Update the cache time FIRST ! Stops others doing this
313 * if the lpq takes a long time.
316 slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
317 tdb_store_int(tdb, keystr, (int)time(NULL));
319 slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
321 unlink(tmp_file);
322 print_run_command(snum, cmd, tmp_file,
323 NULL);
325 numlines = 0;
326 qlines = file_lines_load(tmp_file, &numlines);
327 unlink(tmp_file);
329 /* turn the lpq output into a series of job structures */
330 qcount = 0;
331 ZERO_STRUCT(status);
332 if (numlines)
333 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
335 if (queue) {
336 for (i=0; i<numlines; i++) {
337 /* parse the line */
338 if (parse_lpq_entry(snum,qlines[i],
339 &queue[qcount],&status,qcount==0)) {
340 qcount++;
344 file_lines_free(qlines);
347 any job in the internal database that is marked as spooled
348 and doesn't exist in the system queue is considered finished
349 and removed from the database
351 any job in the system database but not in the internal database
352 is added as a unix job
354 fill in any system job numbers as we go
356 for (i=0; i<qcount; i++) {
357 int jobid = print_parse_jobid(queue[i].file);
359 if (jobid == -1) {
360 /* assume its a unix print job */
361 print_unix_job(snum, &queue[i]);
362 continue;
365 /* we have an active SMB print job - update its status */
366 pjob = print_job_find(jobid);
367 if (!pjob) {
368 /* err, somethings wrong. Probably smbd was restarted
369 with jobs in the queue. All we can do is treat them
370 like unix jobs. Pity. */
371 print_unix_job(snum, &queue[i]);
372 continue;
375 pjob->sysjob = queue[i].job;
376 pjob->status = queue[i].status;
378 print_job_store(jobid, pjob);
381 /* now delete any queued entries that don't appear in the
382 system queue */
383 tstruct.queue = queue;
384 tstruct.qcount = qcount;
385 tstruct.snum = snum;
387 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
389 safe_free(tstruct.queue);
391 /* store the queue status structure */
392 status.qcount = qcount;
393 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
394 data.dptr = (void *)&status;
395 data.dsize = sizeof(status);
396 key.dptr = keystr;
397 key.dsize = strlen(keystr);
398 tdb_store(tdb, key, data, TDB_REPLACE);
401 * Update the cache time again. We want to do this call
402 * as little as possible...
405 slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
406 tdb_store_int(tdb, keystr, (int)time(NULL));
409 /****************************************************************************
410 check if a jobid is valid. It is valid if it exists in the database
411 ****************************************************************************/
412 BOOL print_job_exists(int jobid)
414 return tdb_exists(tdb, print_key(jobid));
418 /****************************************************************************
419 work out which service a jobid is for
420 note that we have to look up by queue name to ensure that it works for
421 other than the process that started the job
422 ****************************************************************************/
423 int print_job_snum(int jobid)
425 struct printjob *pjob = print_job_find(jobid);
426 if (!pjob) return -1;
428 return lp_servicenumber(pjob->qname);
431 /****************************************************************************
432 give the fd used for a jobid
433 ****************************************************************************/
434 int print_job_fd(int jobid)
436 struct printjob *pjob = print_job_find(jobid);
437 if (!pjob) return -1;
438 /* don't allow another process to get this info - it is meaningless */
439 if (pjob->pid != local_pid) return -1;
440 return pjob->fd;
443 /****************************************************************************
444 give the filename used for a jobid
445 only valid for the process doing the spooling and when the job
446 has not been spooled
447 ****************************************************************************/
448 char *print_job_fname(int jobid)
450 struct printjob *pjob = print_job_find(jobid);
451 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
452 return pjob->filename;
456 /****************************************************************************
457 set the place in the queue for a job
458 ****************************************************************************/
459 BOOL print_job_set_place(int jobid, int place)
461 DEBUG(2,("print_job_set_place not implemented yet\n"));
462 return False;
465 /****************************************************************************
466 set the name of a job. Only possible for owner
467 ****************************************************************************/
468 BOOL print_job_set_name(int jobid, char *name)
470 struct printjob *pjob = print_job_find(jobid);
471 if (!pjob || pjob->pid != local_pid) return False;
473 fstrcpy(pjob->jobname, name);
474 return print_job_store(jobid, pjob);
478 /****************************************************************************
479 delete a print job - don't update queue
480 ****************************************************************************/
481 static BOOL print_job_delete1(int jobid)
483 struct printjob *pjob = print_job_find(jobid);
484 int snum;
486 if (!pjob) return False;
488 snum = print_job_snum(jobid);
490 if (pjob->spooled && pjob->sysjob != -1) {
491 /* need to delete the spooled entry */
492 fstring jobstr;
493 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
494 print_run_command(snum,
495 lp_lprmcommand(snum), NULL,
496 "%j", jobstr,
497 "%T", http_timestring(pjob->starttime),
498 NULL);
501 return True;
504 /****************************************************************************
505 return true if the current user owns the print job
506 ****************************************************************************/
507 static BOOL is_owner(struct current_user *user, int jobid)
509 struct printjob *pjob = print_job_find(jobid);
510 user_struct *vuser;
512 if (!pjob || !user) return False;
514 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
515 return strequal(pjob->user, vuser->user.smb_name);
516 } else {
517 return strequal(pjob->user, uidtoname(user->uid));
521 /****************************************************************************
522 delete a print job
523 ****************************************************************************/
524 BOOL print_job_delete(struct current_user *user, int jobid)
526 int snum = print_job_snum(jobid);
527 BOOL owner;
529 owner = is_owner(user, jobid);
531 /* Check access against security descriptor or whether the user
532 owns their job. */
534 if (!owner &&
535 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
536 DEBUG(3, ("delete denied by security descriptor\n"));
537 return False;
540 if (!print_job_delete1(jobid)) return False;
542 /* force update the database and say the delete failed if the
543 job still exists */
545 print_queue_update(snum);
547 return !print_job_exists(jobid);
551 /****************************************************************************
552 pause a job
553 ****************************************************************************/
554 BOOL print_job_pause(struct current_user *user, int jobid)
556 struct printjob *pjob = print_job_find(jobid);
557 int snum, ret = -1;
558 fstring jobstr;
559 BOOL owner;
562 if (!pjob || !user) return False;
564 if (!pjob->spooled || pjob->sysjob == -1) return False;
566 snum = print_job_snum(jobid);
567 owner = is_owner(user, jobid);
569 if (!owner &&
570 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
571 DEBUG(3, ("pause denied by security descriptor\n"));
572 return False;
575 /* need to pause the spooled entry */
576 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
577 ret = print_run_command(snum,
578 lp_lppausecommand(snum), NULL,
579 "%j", jobstr,
580 NULL);
582 /* force update the database */
583 print_cache_flush(snum);
585 /* how do we tell if this succeeded? */
586 return ret == 0;
589 /****************************************************************************
590 resume a job
591 ****************************************************************************/
592 BOOL print_job_resume(struct current_user *user, int jobid)
594 struct printjob *pjob = print_job_find(jobid);
595 int snum, ret;
596 fstring jobstr;
597 BOOL owner;
599 if (!pjob || !user) return False;
601 if (!pjob->spooled || pjob->sysjob == -1) return False;
603 snum = print_job_snum(jobid);
604 owner = is_owner(user, jobid);
606 if (!is_owner(user, jobid) &&
607 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
608 DEBUG(3, ("resume denied by security descriptor\n"));
609 return False;
612 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
613 ret = print_run_command(snum,
614 lp_lpresumecommand(snum), NULL,
615 "%j", jobstr,
616 NULL);
618 /* force update the database */
619 print_cache_flush(snum);
621 /* how do we tell if this succeeded? */
622 return ret == 0;
625 /****************************************************************************
626 write to a print file
627 ****************************************************************************/
628 int print_job_write(int jobid, const char *buf, int size)
630 int fd;
632 fd = print_job_fd(jobid);
633 if (fd == -1) return -1;
635 return write(fd, buf, size);
638 /****************************************************************************
639 Check if the print queue has been updated recently enough.
640 ****************************************************************************/
642 static BOOL print_cache_expired(int snum)
644 fstring key;
645 time_t t2, t = time(NULL);
646 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
647 t2 = tdb_fetch_int(tdb, key);
648 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
649 return True;
651 return False;
654 /****************************************************************************
655 Determine the number of jobs in a queue.
656 ****************************************************************************/
658 static int print_queue_length(int snum)
660 fstring keystr;
661 TDB_DATA data, key;
662 print_status_struct status;
664 /* make sure the database is up to date */
665 if (print_cache_expired(snum)) print_queue_update(snum);
667 /* also fetch the queue status */
668 ZERO_STRUCTP(&status);
669 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
670 key.dptr = keystr;
671 key.dsize = strlen(keystr);
672 data = tdb_fetch(tdb, key);
673 if (data.dptr) {
674 if (data.dsize == sizeof(status)) {
675 memcpy(&status, data.dptr, sizeof(status));
677 free(data.dptr);
679 return status.qcount;
682 /***************************************************************************
683 start spooling a job - return the jobid
684 ***************************************************************************/
685 int print_job_start(struct current_user *user, int snum, char *jobname)
687 int jobid;
688 char *path;
689 struct printjob pjob;
690 int next_jobid;
691 user_struct *vuser;
693 errno = 0;
695 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
696 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
697 return -1;
700 if (!print_time_access_check(snum)) {
701 DEBUG(3, ("print_job_start: job start denied by time check\n"));
702 return -1;
705 path = lp_pathname(snum);
707 /* see if we have sufficient disk space */
708 if (lp_minprintspace(snum)) {
709 SMB_BIG_UINT dspace, dsize;
710 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
711 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
712 errno = ENOSPC;
713 return -1;
717 /* for autoloaded printers, check that the printcap entry still exists */
718 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
719 errno = ENOENT;
720 return -1;
723 if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
724 errno = ENOSPC;
725 return -1;
728 /* create the database entry */
729 ZERO_STRUCT(pjob);
730 pjob.pid = local_pid;
731 pjob.sysjob = -1;
732 pjob.fd = -1;
733 pjob.starttime = time(NULL);
734 pjob.status = LPQ_QUEUED;
735 pjob.size = 0;
736 pjob.spooled = False;
737 pjob.smbjob = True;
739 fstrcpy(pjob.jobname, jobname);
741 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
742 fstrcpy(pjob.user, vuser->user.smb_name);
743 } else {
744 fstrcpy(pjob.user, uidtoname(user->uid));
747 fstrcpy(pjob.qname, lp_servicename(snum));
749 /* lock the database */
750 tdb_lock_bystring(tdb, "INFO/nextjob");
752 next_jobnum:
753 next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
754 if (next_jobid == -1) next_jobid = 1;
756 for (jobid = next_jobid+1; jobid != next_jobid; ) {
757 if (!print_job_exists(jobid)) break;
758 jobid = (jobid + 1) % PRINT_MAX_JOBID;
759 if (jobid == 0) jobid = 1;
761 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
762 jobid = -1;
763 goto fail;
766 tdb_store_int(tdb, "INFO/nextjob", jobid);
768 /* we have a job entry - now create the spool file
770 we unlink first to cope with old spool files and also to beat
771 a symlink security hole - it allows us to use O_EXCL
772 There may be old spool files owned by other users lying around.
774 slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
775 path, PRINT_SPOOL_PREFIX, jobid);
776 if (unlink(pjob.filename) == -1 && errno != ENOENT) {
777 goto next_jobnum;
779 pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
780 if (pjob.fd == -1) goto fail;
782 print_job_store(jobid, &pjob);
784 tdb_unlock_bystring(tdb, "INFO/nextjob");
787 * If the printer is marked as postscript output a leading
788 * file identifier to ensure the file is treated as a raw
789 * postscript file.
790 * This has a similar effect as CtrlD=0 in WIN.INI file.
791 * tim@fsg.com 09/06/94
793 if (lp_postscript(snum)) {
794 print_job_write(jobid, "%!\n",3);
797 return jobid;
799 fail:
800 if (jobid != -1) {
801 tdb_delete(tdb, print_key(jobid));
804 tdb_unlock_bystring(tdb, "INFO/nextjob");
805 return -1;
808 /****************************************************************************
809 Print a file - called on closing the file. This spools the job.
810 ****************************************************************************/
812 BOOL print_job_end(int jobid)
814 struct printjob *pjob = print_job_find(jobid);
815 int snum;
816 SMB_STRUCT_STAT sbuf;
817 pstring current_directory;
818 pstring print_directory;
819 char *wd, *p, *printer_name;
820 pstring jobname;
822 if (!pjob)
823 return False;
825 if (pjob->spooled || pjob->pid != local_pid)
826 return False;
828 snum = print_job_snum(jobid);
830 if (sys_fstat(pjob->fd, &sbuf) == 0)
831 pjob->size = sbuf.st_size;
833 close(pjob->fd);
834 pjob->fd = -1;
836 if (pjob->size == 0) {
837 /* don't bother spooling empty files */
838 unlink(pjob->filename);
839 tdb_delete(tdb, print_key(jobid));
840 return True;
843 /* we print from the directory path to give the best chance of
844 parsing the lpq output */
845 wd = sys_getwd(current_directory);
846 if (!wd)
847 return False;
849 pstrcpy(print_directory, pjob->filename);
850 p = strrchr(print_directory,'/');
851 if (!p)
852 return False;
853 *p++ = 0;
855 if (chdir(print_directory) != 0)
856 return False;
858 pstrcpy(jobname, pjob->jobname);
859 pstring_sub(jobname, "'", "_");
861 /* send it to the system spooler */
862 print_run_command(snum,
863 lp_printcommand(snum), NULL,
864 "%s", p,
865 "%J", jobname,
866 "%f", p,
867 NULL);
869 chdir(wd);
871 pjob->spooled = True;
872 print_job_store(jobid, pjob);
874 /* force update the database */
875 print_cache_flush(snum);
877 /* Send a printer notify message */
879 printer_name = PRINTERNAME(snum);
881 message_send_all(MSG_PRINTER_NOTIFY, printer_name,
882 strlen(printer_name) + 1);
884 return True;
887 /* utility fn to enumerate the print queue */
888 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
890 struct traverse_struct *ts = (struct traverse_struct *)state;
891 struct printjob pjob;
892 int i, jobid;
894 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
895 memcpy(&jobid, key.dptr, sizeof(jobid));
896 memcpy(&pjob, data.dptr, sizeof(pjob));
898 /* maybe it isn't for this queue */
899 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
901 if (ts->qcount >= ts->maxcount) return 0;
903 i = ts->qcount;
905 ts->queue[i].job = jobid;
906 ts->queue[i].size = pjob.size;
907 ts->queue[i].status = pjob.status;
908 ts->queue[i].priority = 1;
909 ts->queue[i].time = pjob.starttime;
910 fstrcpy(ts->queue[i].user, pjob.user);
911 fstrcpy(ts->queue[i].file, pjob.jobname);
913 ts->qcount++;
915 return 0;
918 struct traverse_count_struct {
919 int snum, count;
922 /* utility fn to count the number of entries in the print queue */
923 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
925 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
926 struct printjob pjob;
927 int jobid;
929 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
930 memcpy(&jobid, key.dptr, sizeof(jobid));
931 memcpy(&pjob, data.dptr, sizeof(pjob));
933 /* maybe it isn't for this queue */
934 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
936 ts->count++;
938 return 0;
941 /* Sort print jobs by submittal time */
943 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
945 /* Silly cases */
947 if (!j1 && !j2) return 0;
948 if (!j1) return -1;
949 if (!j2) return 1;
951 /* Sort on job start time */
953 if (j1->time == j2->time) return 0;
954 return (j1->time > j2->time) ? 1 : -1;
957 /****************************************************************************
958 get a printer queue listing
959 ****************************************************************************/
960 int print_queue_status(int snum,
961 print_queue_struct **queue,
962 print_status_struct *status)
964 struct traverse_struct tstruct;
965 struct traverse_count_struct tsc;
966 fstring keystr;
967 TDB_DATA data, key;
969 /* make sure the database is up to date */
970 if (print_cache_expired(snum)) print_queue_update(snum);
973 * Count the number of entries.
975 tsc.count = 0;
976 tsc.snum = snum;
977 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
979 /* Allocate the queue size. */
980 if (( tstruct.queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*tsc.count))
981 == NULL)
982 return 0;
985 * Fill in the queue.
986 * We need maxcount as the queue size may have changed between
987 * the two calls to tdb_traverse.
989 tstruct.qcount = 0;
990 tstruct.maxcount = tsc.count;
991 tstruct.snum = snum;
993 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
995 /* also fetch the queue status */
996 ZERO_STRUCTP(status);
997 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
998 key.dptr = keystr;
999 key.dsize = strlen(keystr);
1000 data = tdb_fetch(tdb, key);
1001 if (data.dptr) {
1002 if (data.dsize == sizeof(*status)) {
1003 memcpy(status, data.dptr, sizeof(*status));
1005 free(data.dptr);
1008 /* Sort the queue by submission time otherwise they are displayed
1009 in hash order. */
1011 qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1012 QSORT_CAST(printjob_comp));
1014 *queue = tstruct.queue;
1015 return tstruct.qcount;
1019 /****************************************************************************
1020 turn a queue name into a snum
1021 ****************************************************************************/
1022 int print_queue_snum(char *qname)
1024 int snum = lp_servicenumber(qname);
1025 if (snum == -1 || !lp_print_ok(snum)) return -1;
1026 return snum;
1030 /****************************************************************************
1031 pause a queue
1032 ****************************************************************************/
1033 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1035 int ret;
1037 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1038 *errcode = ERROR_ACCESS_DENIED;
1039 return False;
1042 ret = print_run_command(snum, lp_queuepausecommand(snum), NULL,
1043 NULL);
1045 /* force update the database */
1046 print_cache_flush(snum);
1048 /* Send a printer notify message */
1050 if (ret == 0) {
1051 char *printer_name;
1053 printer_name = PRINTERNAME(snum);
1055 message_send_all(MSG_PRINTER_NOTIFY, printer_name,
1056 strlen(printer_name) + 1);
1059 return ret == 0;
1062 /****************************************************************************
1063 resume a queue
1064 ****************************************************************************/
1065 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1067 int ret;
1069 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1070 *errcode = ERROR_ACCESS_DENIED;
1071 return False;
1074 ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
1075 NULL);
1077 /* force update the database */
1078 print_cache_flush(snum);
1080 /* Send a printer notify message */
1082 if (ret == 0) {
1083 char *printer_name;
1085 printer_name = PRINTERNAME(snum);
1087 message_send_all(MSG_PRINTER_NOTIFY, printer_name,
1088 strlen(printer_name) + 1);
1091 return ret == 0;
1094 /****************************************************************************
1095 purge a queue - implemented by deleting all jobs that we can delete
1096 ****************************************************************************/
1097 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1099 print_queue_struct *queue;
1100 print_status_struct status;
1101 char *printer_name;
1102 int njobs, i;
1104 njobs = print_queue_status(snum, &queue, &status);
1105 for (i=0;i<njobs;i++) {
1106 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1107 print_job_delete1(queue[i].job);
1111 print_cache_flush(snum);
1112 safe_free(queue);
1114 /* Send a printer notify message */
1116 printer_name = PRINTERNAME(snum);
1118 message_send_all(MSG_PRINTER_NOTIFY, printer_name,
1119 strlen(printer_name) + 1);
1121 return True;
1123 #undef OLD_NTDOMAIN