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.
25 extern int DEBUGLEVEL;
28 the printing backend revolves around a tdb database that stores the
29 SMB view of the print queue
31 The key for this database is a jobid - a internally generated number that
32 uniquely identifies a print job
34 reading the print queue involves two steps:
35 - possibly running lpq and updating the internal database from that
36 - reading entries from the database
38 jobids are assigned when a job starts spooling.
42 pid_t pid; /* which process launched the job */
43 int sysjob; /* the system (lp) job number */
44 int fd; /* file descriptor of open file if open */
45 time_t starttime; /* when the job started spooling */
46 int status; /* the status of this job */
47 size_t size; /* the size of the job so far */
48 BOOL spooled; /* has it been sent to the spooler yet? */
49 BOOL smbjob; /* set if the job is a SMB job */
50 fstring filename; /* the filename used to spool the file */
51 fstring jobname; /* the job name given to us by the client */
52 fstring user; /* the user who started the job */
53 fstring qname; /* name of the print queue the job was sent to */
56 /* the open printing.tdb database */
57 static TDB_CONTEXT *tdb;
58 static pid_t local_pid;
60 #define PRINT_MAX_JOBID 10000
61 #define UNIX_JOB_START PRINT_MAX_JOBID
63 #define PRINT_SPOOL_PREFIX "smbprn."
64 #define PRINT_DATABASE_VERSION 2
66 static int get_queue_status(int, print_status_struct *);
68 /****************************************************************************
69 initialise the printing backend. Called once at startup.
70 Does not survive a fork
71 ****************************************************************************/
72 BOOL print_backend_init(void)
74 char *sversion = "INFO/version";
76 if (tdb && local_pid == sys_getpid()) return True;
77 tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
79 DEBUG(0,("Failed to open printing backend database\n"));
81 local_pid = sys_getpid();
83 /* handle a Samba upgrade */
84 tdb_lock_bystring(tdb, sversion);
85 if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
86 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
87 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
89 tdb_unlock_bystring(tdb, sversion);
91 return nt_printing_init();
94 /****************************************************************************
95 useful function to generate a tdb key
96 ****************************************************************************/
97 static TDB_DATA print_key(int jobid)
103 ret.dptr = (void *)&j;
104 ret.dsize = sizeof(j);
108 /****************************************************************************
109 useful function to find a print job in the database
110 ****************************************************************************/
111 static struct printjob *print_job_find(int jobid)
113 static struct printjob pjob;
116 ret = tdb_fetch(tdb, print_key(jobid));
117 if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
119 memcpy(&pjob, ret.dptr, sizeof(pjob));
124 /****************************************************************************
125 store a job structure back to the database
126 ****************************************************************************/
127 static BOOL print_job_store(int jobid, struct printjob *pjob)
130 d.dptr = (void *)pjob;
131 d.dsize = sizeof(*pjob);
133 return (tdb_store(tdb, print_key(jobid), d, TDB_REPLACE) == 0);
136 /****************************************************************************
137 run a given print command
138 a null terminated list of value/substitute pairs is provided
139 for local substitution strings
140 ****************************************************************************/
141 static int print_run_command(int snum,char *command,
150 if (!command || !*command) return -1;
152 if (!VALID_SNUM(snum)) {
153 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
157 pstrcpy(syscmd, command);
159 va_start(ap, outfile);
160 while ((arg = va_arg(ap, char *))) {
161 char *value = va_arg(ap,char *);
162 pstring_sub(syscmd, arg, value);
166 p = PRINTERNAME(snum);
167 if (!p || !*p) p = SERVICE(snum);
169 pstring_sub(syscmd, "%p", p);
170 standard_sub_snum(snum,syscmd);
172 ret = smbrun(syscmd,outfile,False);
174 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
180 /****************************************************************************
181 parse a file name from the system spooler to generate a jobid
182 ****************************************************************************/
183 static int print_parse_jobid(char *fname)
187 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
188 fname += strlen(PRINT_SPOOL_PREFIX);
191 if (jobid <= 0) return -1;
197 /****************************************************************************
198 list a unix job in the print database
199 ****************************************************************************/
200 static void print_unix_job(int snum, print_queue_struct *q)
202 int jobid = q->job + UNIX_JOB_START;
203 struct printjob pj, *old_pj;
205 /* Preserve the timestamp on an existing unix print job */
207 old_pj = print_job_find(jobid);
214 pj.starttime = old_pj ? old_pj->starttime : q->time;
215 pj.status = q->status;
219 fstrcpy(pj.filename, "");
220 fstrcpy(pj.jobname, q->file);
221 fstrcpy(pj.user, q->user);
222 fstrcpy(pj.qname, lp_servicename(snum));
224 print_job_store(jobid, &pj);
228 struct traverse_struct {
229 print_queue_struct *queue;
230 int qcount, snum, maxcount;
233 /* utility fn to delete any jobs that are no longer active */
234 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
236 struct traverse_struct *ts = (struct traverse_struct *)state;
237 struct printjob pjob;
240 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
241 memcpy(&jobid, key.dptr, sizeof(jobid));
242 memcpy(&pjob, data.dptr, sizeof(pjob));
244 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
245 /* this isn't for the queue we are looking at */
250 /* remove a unix job if it isn't in the system queue
253 for (i=0;i<ts->qcount;i++) {
254 if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
256 if (i == ts->qcount) tdb_delete(tdb, key);
260 /* maybe it hasn't been spooled yet */
262 /* if a job is not spooled and the process doesn't
263 exist then kill it. This cleans up after smbd
265 if (!process_exists(pjob.pid)) {
266 tdb_delete(tdb, key);
271 for (i=0;i<ts->qcount;i++) {
272 int qid = print_parse_jobid(ts->queue[i].file);
273 if (jobid == qid) break;
276 /* The job isn't in the system queue - we have to assume it has
277 completed, so delete the database entry. */
279 if (i == ts->qcount) {
280 time_t cur_t = time(NULL);
282 /* A race can occur between the time a job is spooled and
283 when it appears in the lpq output. This happens when
284 the job is added to printing.tdb when another smbd
285 running print_queue_update() has completed a lpq and
286 is currently traversing the printing tdb and deleting jobs.
287 A workaround is to not delete the job if it has been
288 submitted less than lp_lpqcachetime() seconds ago. */
290 if ((cur_t - pjob.starttime) > lp_lpqcachetime()) {
298 /****************************************************************************
299 check if the print queue has been updated recently enough
300 ****************************************************************************/
301 static void print_cache_flush(int snum)
304 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
305 tdb_store_int(tdb, key, -1);
308 /****************************************************************************
309 update the internal database from the system print queue for a queue
310 ****************************************************************************/
311 static void print_queue_update(int snum)
313 char *path = lp_pathname(snum);
314 char *cmd = lp_lpqcommand(snum);
317 int numlines, i, qcount;
318 print_queue_struct *queue = NULL;
319 print_status_struct status;
320 print_status_struct old_status;
321 struct printjob *pjob;
322 struct traverse_struct tstruct;
323 fstring keystr, printer_name;
326 fstrcpy(printer_name, lp_servicename(snum));
329 * Update the cache time FIRST ! Stops others doing this
330 * if the lpq takes a long time.
333 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
334 tdb_store_int(tdb, keystr, (int)time(NULL));
336 slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
339 print_run_command(snum, cmd, tmp_file, NULL);
342 qlines = file_lines_load(tmp_file, &numlines, True);
345 /* turn the lpq output into a series of job structures */
349 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
352 for (i=0; i<numlines; i++) {
354 if (parse_lpq_entry(snum,qlines[i],
355 &queue[qcount],&status,qcount==0)) {
360 file_lines_free(qlines);
362 DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
363 "s" : "", printer_name));
365 /* Lock the queue for the database update */
367 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
368 tdb_lock_bystring(tdb, keystr);
371 any job in the internal database that is marked as spooled
372 and doesn't exist in the system queue is considered finished
373 and removed from the database
375 any job in the system database but not in the internal database
376 is added as a unix job
378 fill in any system job numbers as we go
380 for (i=0; i<qcount; i++) {
381 int jobid = print_parse_jobid(queue[i].file);
384 /* assume its a unix print job */
385 print_unix_job(snum, &queue[i]);
389 /* we have an active SMB print job - update its status */
390 pjob = print_job_find(jobid);
392 /* err, somethings wrong. Probably smbd was restarted
393 with jobs in the queue. All we can do is treat them
394 like unix jobs. Pity. */
395 print_unix_job(snum, &queue[i]);
399 pjob->sysjob = queue[i].job;
400 pjob->status = queue[i].status;
402 print_job_store(jobid, pjob);
405 /* now delete any queued entries that don't appear in the
407 tstruct.queue = queue;
408 tstruct.qcount = qcount;
411 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
413 safe_free(tstruct.queue);
416 * Get the old print status. We will use this to compare the
417 * number of jobs. If they have changed we need to send a
418 * "changed" message to the smbds.
421 if( qcount != get_queue_status(snum, &old_status)) {
422 DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
423 old_status.qcount, qcount, printer_name ));
424 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
427 /* store the new queue status structure */
428 slprintf(keystr, sizeof(keystr), "STATUS/%s", printer_name);
430 key.dsize = strlen(keystr);
432 status.qcount = qcount;
433 data.dptr = (void *)&status;
434 data.dsize = sizeof(status);
435 tdb_store(tdb, key, data, TDB_REPLACE);
437 /* Unlock for database update */
439 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
440 tdb_unlock_bystring(tdb, keystr);
443 * Update the cache time again. We want to do this call
444 * as little as possible...
447 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
448 tdb_store_int(tdb, keystr, (int)time(NULL));
451 /****************************************************************************
452 check if a jobid is valid. It is valid if it exists in the database
453 ****************************************************************************/
454 BOOL print_job_exists(int jobid)
456 return tdb_exists(tdb, print_key(jobid));
460 /****************************************************************************
461 work out which service a jobid is for
462 note that we have to look up by queue name to ensure that it works for
463 other than the process that started the job
464 ****************************************************************************/
465 int print_job_snum(int jobid)
467 struct printjob *pjob = print_job_find(jobid);
468 if (!pjob) return -1;
470 return lp_servicenumber(pjob->qname);
473 /****************************************************************************
474 give the fd used for a jobid
475 ****************************************************************************/
476 int print_job_fd(int jobid)
478 struct printjob *pjob = print_job_find(jobid);
479 if (!pjob) return -1;
480 /* don't allow another process to get this info - it is meaningless */
481 if (pjob->pid != local_pid) return -1;
485 /****************************************************************************
486 give the filename used for a jobid
487 only valid for the process doing the spooling and when the job
489 ****************************************************************************/
490 char *print_job_fname(int jobid)
492 struct printjob *pjob = print_job_find(jobid);
493 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
494 return pjob->filename;
498 /****************************************************************************
499 set the place in the queue for a job
500 ****************************************************************************/
501 BOOL print_job_set_place(int jobid, int place)
503 DEBUG(2,("print_job_set_place not implemented yet\n"));
507 /****************************************************************************
508 set the name of a job. Only possible for owner
509 ****************************************************************************/
510 BOOL print_job_set_name(int jobid, char *name)
512 struct printjob *pjob = print_job_find(jobid);
513 if (!pjob || pjob->pid != local_pid) return False;
515 fstrcpy(pjob->jobname, name);
516 return print_job_store(jobid, pjob);
520 /****************************************************************************
521 delete a print job - don't update queue
522 ****************************************************************************/
523 static BOOL print_job_delete1(int jobid)
525 struct printjob *pjob = print_job_find(jobid);
528 if (!pjob) return False;
530 snum = print_job_snum(jobid);
532 if (pjob->spooled && pjob->sysjob != -1) {
533 /* need to delete the spooled entry */
535 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
536 print_run_command(snum,
537 lp_lprmcommand(snum), NULL,
539 "%T", http_timestring(pjob->starttime),
546 /****************************************************************************
547 return true if the current user owns the print job
548 ****************************************************************************/
549 static BOOL is_owner(struct current_user *user, int jobid)
551 struct printjob *pjob = print_job_find(jobid);
554 if (!pjob || !user) return False;
556 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
557 return strequal(pjob->user, vuser->user.smb_name);
559 return strequal(pjob->user, uidtoname(user->uid));
563 /****************************************************************************
565 ****************************************************************************/
566 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
568 int snum = print_job_snum(jobid);
572 owner = is_owner(user, jobid);
574 /* Check access against security descriptor or whether the user
578 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
579 DEBUG(3, ("delete denied by security descriptor\n"));
580 *errcode = ERROR_ACCESS_DENIED;
584 if (!print_job_delete1(jobid)) return False;
586 /* force update the database and say the delete failed if the
589 print_queue_update(snum);
591 /* Send a printer notify message */
593 printer_name = PRINTERNAME(snum);
595 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
597 return !print_job_exists(jobid);
601 /****************************************************************************
603 ****************************************************************************/
604 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
606 struct printjob *pjob = print_job_find(jobid);
612 if (!pjob || !user) return False;
614 if (!pjob->spooled || pjob->sysjob == -1) return False;
616 snum = print_job_snum(jobid);
617 owner = is_owner(user, jobid);
620 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
621 DEBUG(3, ("pause denied by security descriptor\n"));
622 *errcode = ERROR_ACCESS_DENIED;
626 /* need to pause the spooled entry */
627 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
628 ret = print_run_command(snum,
629 lp_lppausecommand(snum), NULL,
634 *errcode = ERROR_INVALID_PARAMETER;
638 /* force update the database */
639 print_cache_flush(snum);
641 /* Send a printer notify message */
643 printer_name = PRINTERNAME(snum);
645 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
647 /* how do we tell if this succeeded? */
652 /****************************************************************************
654 ****************************************************************************/
655 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
657 struct printjob *pjob = print_job_find(jobid);
663 if (!pjob || !user) return False;
665 if (!pjob->spooled || pjob->sysjob == -1) return False;
667 snum = print_job_snum(jobid);
668 owner = is_owner(user, jobid);
670 if (!is_owner(user, jobid) &&
671 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
672 DEBUG(3, ("resume denied by security descriptor\n"));
673 *errcode = ERROR_ACCESS_DENIED;
677 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
678 ret = print_run_command(snum,
679 lp_lpresumecommand(snum), NULL,
684 *errcode = ERROR_INVALID_PARAMETER;
688 /* force update the database */
689 print_cache_flush(snum);
691 /* Send a printer notify message */
693 printer_name = PRINTERNAME(snum);
695 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
700 /****************************************************************************
701 write to a print file
702 ****************************************************************************/
703 int print_job_write(int jobid, const char *buf, int size)
707 fd = print_job_fd(jobid);
708 if (fd == -1) return -1;
710 return write(fd, buf, size);
713 /****************************************************************************
714 Check if the print queue has been updated recently enough.
715 ****************************************************************************/
717 static BOOL print_cache_expired(int snum)
720 time_t t2, t = time(NULL);
722 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
723 t2 = tdb_fetch_int(tdb, key);
724 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
725 DEBUG(3, ("print cache expired\n"));
731 /****************************************************************************
732 Get the queue status - do not update if db is out of date.
733 ****************************************************************************/
735 static int get_queue_status(int snum, print_status_struct *status)
740 ZERO_STRUCTP(status);
741 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
743 key.dsize = strlen(keystr);
744 data = tdb_fetch(tdb, key);
746 if (data.dsize == sizeof(print_status_struct)) {
747 memcpy(status, data.dptr, sizeof(print_status_struct));
751 return status->qcount;
754 /****************************************************************************
755 Determine the number of jobs in a queue.
756 ****************************************************************************/
758 static int print_queue_length(int snum)
760 print_status_struct status;
762 /* make sure the database is up to date */
763 if (print_cache_expired(snum)) print_queue_update(snum);
765 /* also fetch the queue status */
766 return get_queue_status(snum, &status);
769 /***************************************************************************
770 start spooling a job - return the jobid
771 ***************************************************************************/
772 int print_job_start(struct current_user *user, int snum, char *jobname)
776 struct printjob pjob;
782 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
783 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
787 if (!print_time_access_check(snum)) {
788 DEBUG(3, ("print_job_start: job start denied by time check\n"));
792 path = lp_pathname(snum);
794 /* see if we have sufficient disk space */
795 if (lp_minprintspace(snum)) {
796 SMB_BIG_UINT dspace, dsize;
797 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
798 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
804 /* for autoloaded printers, check that the printcap entry still exists */
805 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
810 if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
815 /* create the database entry */
817 pjob.pid = local_pid;
820 pjob.starttime = time(NULL);
821 pjob.status = LPQ_QUEUED;
823 pjob.spooled = False;
826 fstrcpy(pjob.jobname, jobname);
828 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
829 fstrcpy(pjob.user, vuser->user.smb_name);
831 fstrcpy(pjob.user, uidtoname(user->uid));
834 fstrcpy(pjob.qname, lp_servicename(snum));
836 /* lock the database */
837 tdb_lock_bystring(tdb, "INFO/nextjob");
840 next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
841 if (next_jobid == -1) next_jobid = 1;
843 for (jobid = next_jobid+1; jobid != next_jobid; ) {
844 if (!print_job_exists(jobid)) break;
845 jobid = (jobid + 1) % PRINT_MAX_JOBID;
846 if (jobid == 0) jobid = 1;
848 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
853 tdb_store_int(tdb, "INFO/nextjob", jobid);
855 /* we have a job entry - now create the spool file
857 we unlink first to cope with old spool files and also to beat
858 a symlink security hole - it allows us to use O_EXCL
859 There may be old spool files owned by other users lying around.
861 slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
862 path, PRINT_SPOOL_PREFIX, jobid);
863 if (unlink(pjob.filename) == -1 && errno != ENOENT) {
866 pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
867 if (pjob.fd == -1) goto fail;
869 print_job_store(jobid, &pjob);
871 tdb_unlock_bystring(tdb, "INFO/nextjob");
874 * If the printer is marked as postscript output a leading
875 * file identifier to ensure the file is treated as a raw
877 * This has a similar effect as CtrlD=0 in WIN.INI file.
878 * tim@fsg.com 09/06/94
880 if (lp_postscript(snum)) {
881 print_job_write(jobid, "%!\n",3);
888 tdb_delete(tdb, print_key(jobid));
891 tdb_unlock_bystring(tdb, "INFO/nextjob");
895 /****************************************************************************
896 Print a file - called on closing the file. This spools the job.
897 ****************************************************************************/
899 BOOL print_job_end(int jobid)
901 struct printjob *pjob = print_job_find(jobid);
903 SMB_STRUCT_STAT sbuf;
904 pstring current_directory;
905 pstring print_directory;
906 char *wd, *p, *printer_name;
912 if (pjob->spooled || pjob->pid != local_pid)
915 snum = print_job_snum(jobid);
917 if (sys_fstat(pjob->fd, &sbuf) == 0)
918 pjob->size = sbuf.st_size;
923 if (pjob->size == 0) {
924 /* don't bother spooling empty files */
925 unlink(pjob->filename);
926 tdb_delete(tdb, print_key(jobid));
930 /* we print from the directory path to give the best chance of
931 parsing the lpq output */
932 wd = sys_getwd(current_directory);
936 pstrcpy(print_directory, pjob->filename);
937 p = strrchr(print_directory,'/');
942 if (chdir(print_directory) != 0)
945 pstrcpy(jobname, pjob->jobname);
946 pstring_sub(jobname, "'", "_");
948 /* send it to the system spooler */
949 print_run_command(snum,
950 lp_printcommand(snum), NULL,
958 pjob->spooled = True;
959 print_job_store(jobid, pjob);
961 /* force update the database */
962 print_cache_flush(snum);
964 /* Send a printer notify message */
966 printer_name = PRINTERNAME(snum);
968 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
973 /* utility fn to enumerate the print queue */
974 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
976 struct traverse_struct *ts = (struct traverse_struct *)state;
977 struct printjob pjob;
980 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
981 memcpy(&jobid, key.dptr, sizeof(jobid));
982 memcpy(&pjob, data.dptr, sizeof(pjob));
984 /* maybe it isn't for this queue */
985 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
987 if (ts->qcount >= ts->maxcount) return 0;
991 ts->queue[i].job = jobid;
992 ts->queue[i].size = pjob.size;
993 ts->queue[i].status = pjob.status;
994 ts->queue[i].priority = 1;
995 ts->queue[i].time = pjob.starttime;
996 fstrcpy(ts->queue[i].user, pjob.user);
997 fstrcpy(ts->queue[i].file, pjob.jobname);
1004 struct traverse_count_struct {
1008 /* utility fn to count the number of entries in the print queue */
1009 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1011 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1012 struct printjob pjob;
1015 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1016 memcpy(&jobid, key.dptr, sizeof(jobid));
1017 memcpy(&pjob, data.dptr, sizeof(pjob));
1019 /* maybe it isn't for this queue */
1020 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1027 /* Sort print jobs by submittal time */
1029 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1033 if (!j1 && !j2) return 0;
1037 /* Sort on job start time */
1039 if (j1->time == j2->time) return 0;
1040 return (j1->time > j2->time) ? 1 : -1;
1043 /****************************************************************************
1044 get a printer queue listing
1045 ****************************************************************************/
1046 int print_queue_status(int snum,
1047 print_queue_struct **queue,
1048 print_status_struct *status)
1050 struct traverse_struct tstruct;
1051 struct traverse_count_struct tsc;
1055 /* make sure the database is up to date */
1056 if (print_cache_expired(snum)) print_queue_update(snum);
1061 * Fetch the queue status. We must do this first, as there may
1062 * be no jobs in the queue.
1064 ZERO_STRUCTP(status);
1065 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1067 key.dsize = strlen(keystr);
1068 data = tdb_fetch(tdb, key);
1070 if (data.dsize == sizeof(*status)) {
1071 memcpy(status, data.dptr, sizeof(*status));
1077 * Now, fetch the print queue information. We first count the number
1078 * of entries, and then only retrieve the queue if necessary.
1083 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1088 /* Allocate the queue size. */
1089 if ((tstruct.queue = (print_queue_struct *)
1090 malloc(sizeof(print_queue_struct)*tsc.count))
1095 * Fill in the queue.
1096 * We need maxcount as the queue size may have changed between
1097 * the two calls to tdb_traverse.
1100 tstruct.maxcount = tsc.count;
1101 tstruct.snum = snum;
1103 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1105 /* Sort the queue by submission time otherwise they are displayed
1108 qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1109 QSORT_CAST(printjob_comp));
1111 *queue = tstruct.queue;
1112 return tstruct.qcount;
1116 /****************************************************************************
1117 turn a queue name into a snum
1118 ****************************************************************************/
1119 int print_queue_snum(char *qname)
1121 int snum = lp_servicenumber(qname);
1122 if (snum == -1 || !lp_print_ok(snum)) return -1;
1127 /****************************************************************************
1129 ****************************************************************************/
1130 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1135 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1136 *errcode = ERROR_ACCESS_DENIED;
1140 ret = print_run_command(snum, lp_queuepausecommand(snum), NULL,
1144 *errcode = ERROR_INVALID_PARAMETER;
1148 /* force update the database */
1149 print_cache_flush(snum);
1151 /* Send a printer notify message */
1153 printer_name = PRINTERNAME(snum);
1155 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1160 /****************************************************************************
1162 ****************************************************************************/
1163 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1168 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1169 *errcode = ERROR_ACCESS_DENIED;
1173 ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
1177 *errcode = ERROR_INVALID_PARAMETER;
1181 /* force update the database */
1182 print_cache_flush(snum);
1184 /* Send a printer notify message */
1186 printer_name = PRINTERNAME(snum);
1188 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1193 /****************************************************************************
1194 purge a queue - implemented by deleting all jobs that we can delete
1195 ****************************************************************************/
1196 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1198 print_queue_struct *queue;
1199 print_status_struct status;
1203 njobs = print_queue_status(snum, &queue, &status);
1204 for (i=0;i<njobs;i++) {
1205 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1206 print_job_delete1(queue[i].job);
1210 print_cache_flush(snum);
1213 /* Send a printer notify message */
1215 printer_name = PRINTERNAME(snum);
1217 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);