3 Unix SMB/Netbios implementation.
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.
24 extern int DEBUGLEVEL
;
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.
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);
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
)
100 ret
.dptr
= (void *)&j
;
101 ret
.dsize
= sizeof(j
);
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
;
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
));
121 /****************************************************************************
122 store a job structure back to the database
123 ****************************************************************************/
124 static BOOL
print_job_store(int jobid
, struct printjob
*pjob
)
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
,
147 if (!command
|| !*command
) return -1;
149 if (!VALID_SNUM(snum
)) {
150 DEBUG(0,("Invalid snum %d for command %s\n", snum
, command
));
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
);
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
));
176 /****************************************************************************
177 parse a file name from the system spooler to generate a jobid
178 ****************************************************************************/
179 static int print_parse_jobid(char *fname
)
183 if (strncmp(fname
,PRINT_SPOOL_PREFIX
,strlen(PRINT_SPOOL_PREFIX
)) != 0) return -1;
184 fname
+= strlen(PRINT_SPOOL_PREFIX
);
187 if (jobid
<= 0) return -1;
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
;
201 /* Don't re-insert a unix job if it already exists as it mucks
204 if (tdb_exists(tdb
, print_key(jobid
))) {
213 pj
.starttime
= q
->time
;
214 pj
.status
= q
->status
;
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
;
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 */
249 /* remove a unix job if it isn't in the system queue
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
);
258 /* maybe it hasn't been spooled yet */
260 /* if a job is not spooled and the process doesn't
261 exist then kill it. This cleans up after smbd
263 if (!process_exists(pjob
.pid
)) {
264 tdb_delete(tdb
, key
);
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
284 /****************************************************************************
285 check if the print queue has been updated recently enough
286 ****************************************************************************/
287 static void print_cache_flush(int snum
)
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
);
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
;
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
);
322 print_run_command(snum
, cmd
, tmp_file
,
326 qlines
= file_lines_load(tmp_file
, &numlines
);
329 /* turn the lpq output into a series of job structures */
333 queue
= (print_queue_struct
*)malloc(sizeof(print_queue_struct
)*(numlines
+1));
336 for (i
=0; i
<numlines
; i
++) {
338 if (parse_lpq_entry(snum
,qlines
[i
],
339 &queue
[qcount
],&status
,qcount
==0)) {
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
);
360 /* assume its a unix print job */
361 print_unix_job(snum
, &queue
[i
]);
365 /* we have an active SMB print job - update its status */
366 pjob
= print_job_find(jobid
);
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
]);
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
383 tstruct
.queue
= queue
;
384 tstruct
.qcount
= qcount
;
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
);
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;
443 /****************************************************************************
444 give the filename used for a jobid
445 only valid for the process doing the spooling and when the job
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"));
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
);
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 */
493 slprintf(jobstr
, sizeof(jobstr
), "%d", pjob
->sysjob
);
494 print_run_command(snum
,
495 lp_lprmcommand(snum
), NULL
,
497 "%T", http_timestring(pjob
->starttime
),
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
);
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
);
517 return strequal(pjob
->user
, uidtoname(user
->uid
));
521 /****************************************************************************
523 ****************************************************************************/
524 BOOL
print_job_delete(struct current_user
*user
, int jobid
)
526 int snum
= print_job_snum(jobid
);
529 owner
= is_owner(user
, jobid
);
531 /* Check access against security descriptor or whether the user
535 !print_access_check(user
, snum
, JOB_ACCESS_ADMINISTER
)) {
536 DEBUG(3, ("delete denied by security descriptor\n"));
540 if (!print_job_delete1(jobid
)) return False
;
542 /* force update the database and say the delete failed if the
545 print_queue_update(snum
);
547 return !print_job_exists(jobid
);
551 /****************************************************************************
553 ****************************************************************************/
554 BOOL
print_job_pause(struct current_user
*user
, int jobid
)
556 struct printjob
*pjob
= print_job_find(jobid
);
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
);
570 !print_access_check(user
, snum
, JOB_ACCESS_ADMINISTER
)) {
571 DEBUG(3, ("pause denied by security descriptor\n"));
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
,
582 /* force update the database */
583 print_cache_flush(snum
);
585 /* how do we tell if this succeeded? */
589 /****************************************************************************
591 ****************************************************************************/
592 BOOL
print_job_resume(struct current_user
*user
, int jobid
)
594 struct printjob
*pjob
= print_job_find(jobid
);
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"));
612 slprintf(jobstr
, sizeof(jobstr
), "%d", pjob
->sysjob
);
613 ret
= print_run_command(snum
,
614 lp_lpresumecommand(snum
), NULL
,
618 /* force update the database */
619 print_cache_flush(snum
);
621 /* how do we tell if this succeeded? */
625 /****************************************************************************
626 write to a print file
627 ****************************************************************************/
628 int print_job_write(int jobid
, const char *buf
, int size
)
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
)
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()) {
654 /****************************************************************************
655 Determine the number of jobs in a queue.
656 ****************************************************************************/
658 static int print_queue_length(int snum
)
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
));
671 key
.dsize
= strlen(keystr
);
672 data
= tdb_fetch(tdb
, key
);
674 if (data
.dsize
== sizeof(status
)) {
675 memcpy(&status
, data
.dptr
, sizeof(status
));
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
)
689 struct printjob pjob
;
695 if (!print_access_check(user
, snum
, PRINTER_ACCESS_USE
)) {
696 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
700 if (!print_time_access_check(snum
)) {
701 DEBUG(3, ("print_job_start: job start denied by time check\n"));
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
)) {
717 /* for autoloaded printers, check that the printcap entry still exists */
718 if (lp_autoloaded(snum
) && !pcap_printername_ok(lp_servicename(snum
), NULL
)) {
723 if (print_queue_length(snum
) > lp_maxprintjobs(snum
)) {
728 /* create the database entry */
730 pjob
.pid
= local_pid
;
733 pjob
.starttime
= time(NULL
);
734 pjob
.status
= LPQ_QUEUED
;
736 pjob
.spooled
= False
;
739 fstrcpy(pjob
.jobname
, jobname
);
741 if ((vuser
= get_valid_user_struct(user
->vuid
)) != NULL
) {
742 fstrcpy(pjob
.user
, vuser
->user
.smb_name
);
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");
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
)) {
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
) {
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
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);
801 tdb_delete(tdb
, print_key(jobid
));
804 tdb_unlock_bystring(tdb
, "INFO/nextjob");
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
);
816 SMB_STRUCT_STAT sbuf
;
817 pstring current_directory
;
818 pstring print_directory
;
819 char *wd
, *p
, *printer_name
;
825 if (pjob
->spooled
|| pjob
->pid
!= local_pid
)
828 snum
= print_job_snum(jobid
);
830 if (sys_fstat(pjob
->fd
, &sbuf
) == 0)
831 pjob
->size
= sbuf
.st_size
;
836 if (pjob
->size
== 0) {
837 /* don't bother spooling empty files */
838 unlink(pjob
->filename
);
839 tdb_delete(tdb
, print_key(jobid
));
843 /* we print from the directory path to give the best chance of
844 parsing the lpq output */
845 wd
= sys_getwd(current_directory
);
849 pstrcpy(print_directory
, pjob
->filename
);
850 p
= strrchr(print_directory
,'/');
855 if (chdir(print_directory
) != 0)
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
,
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);
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
;
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;
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
);
918 struct traverse_count_struct
{
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
;
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;
941 /* Sort print jobs by submittal time */
943 static int printjob_comp(print_queue_struct
*j1
, print_queue_struct
*j2
)
947 if (!j1
&& !j2
) return 0;
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
;
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.
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
))
986 * We need maxcount as the queue size may have changed between
987 * the two calls to tdb_traverse.
990 tstruct
.maxcount
= tsc
.count
;
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
));
999 key
.dsize
= strlen(keystr
);
1000 data
= tdb_fetch(tdb
, key
);
1002 if (data
.dsize
== sizeof(*status
)) {
1003 memcpy(status
, data
.dptr
, sizeof(*status
));
1008 /* Sort the queue by submission time otherwise they are displayed
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;
1030 /****************************************************************************
1032 ****************************************************************************/
1033 BOOL
print_queue_pause(struct current_user
*user
, int snum
, int *errcode
)
1037 if (!print_access_check(user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
1038 *errcode
= ERROR_ACCESS_DENIED
;
1042 ret
= print_run_command(snum
, lp_queuepausecommand(snum
), NULL
,
1045 /* force update the database */
1046 print_cache_flush(snum
);
1048 /* Send a printer notify message */
1053 printer_name
= PRINTERNAME(snum
);
1055 message_send_all(MSG_PRINTER_NOTIFY
, printer_name
,
1056 strlen(printer_name
) + 1);
1062 /****************************************************************************
1064 ****************************************************************************/
1065 BOOL
print_queue_resume(struct current_user
*user
, int snum
, int *errcode
)
1069 if (!print_access_check(user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
1070 *errcode
= ERROR_ACCESS_DENIED
;
1074 ret
= print_run_command(snum
, lp_queueresumecommand(snum
), NULL
,
1077 /* force update the database */
1078 print_cache_flush(snum
);
1080 /* Send a printer notify message */
1085 printer_name
= PRINTERNAME(snum
);
1087 message_send_all(MSG_PRINTER_NOTIFY
, printer_name
,
1088 strlen(printer_name
) + 1);
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
;
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
);
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);