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 /****************************************************************************
67 initialise the printing backend. Called once at startup.
68 Does not survive a fork
69 ****************************************************************************/
70 BOOL print_backend_init(void)
72 char *sversion = "INFO/version";
74 if (tdb && local_pid == sys_getpid()) return True;
75 tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
77 DEBUG(0,("Failed to open printing backend database\n"));
79 local_pid = sys_getpid();
81 /* handle a Samba upgrade */
82 tdb_lock_bystring(tdb, sversion);
83 if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
84 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
85 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
87 tdb_unlock_bystring(tdb, sversion);
89 return nt_printing_init();
92 /****************************************************************************
93 useful function to generate a tdb key
94 ****************************************************************************/
95 static TDB_DATA print_key(int jobid)
101 ret.dptr = (void *)&j;
102 ret.dsize = sizeof(j);
106 /****************************************************************************
107 useful function to find a print job in the database
108 ****************************************************************************/
109 static struct printjob *print_job_find(int jobid)
111 static struct printjob pjob;
114 ret = tdb_fetch(tdb, print_key(jobid));
115 if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
117 memcpy(&pjob, ret.dptr, sizeof(pjob));
122 /****************************************************************************
123 store a job structure back to the database
124 ****************************************************************************/
125 static BOOL print_job_store(int jobid, struct printjob *pjob)
128 d.dptr = (void *)pjob;
129 d.dsize = sizeof(*pjob);
131 return (tdb_store(tdb, print_key(jobid), d, TDB_REPLACE) == 0);
134 /****************************************************************************
135 run a given print command
136 a null terminated list of value/substitute pairs is provided
137 for local substitution strings
138 ****************************************************************************/
139 static int print_run_command(int snum,char *command,
148 if (!command || !*command) return -1;
150 if (!VALID_SNUM(snum)) {
151 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
155 pstrcpy(syscmd, command);
157 va_start(ap, outfile);
158 while ((arg = va_arg(ap, char *))) {
159 char *value = va_arg(ap,char *);
160 pstring_sub(syscmd, arg, value);
164 p = PRINTERNAME(snum);
165 if (!p || !*p) p = SERVICE(snum);
167 pstring_sub(syscmd, "%p", p);
168 standard_sub_snum(snum,syscmd);
170 ret = smbrun(syscmd,outfile,False);
172 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
178 /****************************************************************************
179 parse a file name from the system spooler to generate a jobid
180 ****************************************************************************/
181 static int print_parse_jobid(char *fname)
185 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
186 fname += strlen(PRINT_SPOOL_PREFIX);
189 if (jobid <= 0) return -1;
195 /****************************************************************************
196 list a unix job in the print database
197 ****************************************************************************/
198 static void print_unix_job(int snum, print_queue_struct *q)
200 int jobid = q->job + UNIX_JOB_START;
201 struct printjob pj, *old_pj;
203 /* Preserve the timestamp on an existing unix print job */
205 old_pj = print_job_find(jobid);
212 pj.starttime = old_pj ? old_pj->starttime : q->time;
213 pj.status = q->status;
217 fstrcpy(pj.filename, "");
218 fstrcpy(pj.jobname, q->file);
219 fstrcpy(pj.user, q->user);
220 fstrcpy(pj.qname, lp_servicename(snum));
222 print_job_store(jobid, &pj);
226 struct traverse_struct {
227 print_queue_struct *queue;
228 int qcount, snum, maxcount;
231 /* utility fn to delete any jobs that are no longer active */
232 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
234 struct traverse_struct *ts = (struct traverse_struct *)state;
235 struct printjob pjob;
238 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
239 memcpy(&jobid, key.dptr, sizeof(jobid));
240 memcpy(&pjob, data.dptr, sizeof(pjob));
242 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
243 /* this isn't for the queue we are looking at */
248 /* 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 /* The job isn't in the system queue - we have to assume it has
275 completed, so delete the database entry. */
277 if (i == ts->qcount) {
278 time_t cur_t = time(NULL);
280 /* A race can occur between the time a job is spooled and
281 when it appears in the lpq output. This happens when
282 the job is added to printing.tdb when another smbd
283 running print_queue_update() has completed a lpq and
284 is currently traversing the printing tdb and deleting jobs.
285 A workaround is to not delete the job if it has been
286 submitted less than lp_lpqcachetime() seconds ago. */
288 if ((cur_t - pjob.starttime) > lp_lpqcachetime()) {
296 /****************************************************************************
297 check if the print queue has been updated recently enough
298 ****************************************************************************/
299 static void print_cache_flush(int snum)
302 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
303 tdb_store_int(tdb, key, -1);
306 /****************************************************************************
307 update the internal database from the system print queue for a queue
308 ****************************************************************************/
309 static void print_queue_update(int snum)
311 char *path = lp_pathname(snum);
312 char *cmd = lp_lpqcommand(snum);
315 int numlines, i, qcount;
316 print_queue_struct *queue = NULL;
317 print_status_struct status;
318 struct printjob *pjob;
319 struct traverse_struct tstruct;
320 fstring keystr, printer_name;
323 fstrcpy(printer_name, lp_servicename(snum));
326 * Update the cache time FIRST ! Stops others doing this
327 * if the lpq takes a long time.
330 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
331 tdb_store_int(tdb, keystr, (int)time(NULL));
333 slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
336 print_run_command(snum, cmd, tmp_file, NULL);
339 qlines = file_lines_load(tmp_file, &numlines);
342 /* turn the lpq output into a series of job structures */
346 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
349 for (i=0; i<numlines; i++) {
351 if (parse_lpq_entry(snum,qlines[i],
352 &queue[qcount],&status,qcount==0)) {
357 file_lines_free(qlines);
359 DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
360 "s" : "", printer_name));
362 /* Lock the queue for the database update */
364 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
365 tdb_lock_bystring(tdb, keystr);
368 any job in the internal database that is marked as spooled
369 and doesn't exist in the system queue is considered finished
370 and removed from the database
372 any job in the system database but not in the internal database
373 is added as a unix job
375 fill in any system job numbers as we go
377 for (i=0; i<qcount; i++) {
378 int jobid = print_parse_jobid(queue[i].file);
381 /* assume its a unix print job */
382 print_unix_job(snum, &queue[i]);
386 /* we have an active SMB print job - update its status */
387 pjob = print_job_find(jobid);
389 /* err, somethings wrong. Probably smbd was restarted
390 with jobs in the queue. All we can do is treat them
391 like unix jobs. Pity. */
392 print_unix_job(snum, &queue[i]);
396 pjob->sysjob = queue[i].job;
397 pjob->status = queue[i].status;
399 print_job_store(jobid, pjob);
402 /* now delete any queued entries that don't appear in the
404 tstruct.queue = queue;
405 tstruct.qcount = qcount;
408 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
410 safe_free(tstruct.queue);
412 /* store the queue status structure */
413 status.qcount = qcount;
414 slprintf(keystr, sizeof(keystr), "STATUS/%s", printer_name);
415 data.dptr = (void *)&status;
416 data.dsize = sizeof(status);
418 key.dsize = strlen(keystr);
419 tdb_store(tdb, key, data, TDB_REPLACE);
421 /* Unlock for database update */
423 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
424 tdb_unlock_bystring(tdb, keystr);
427 * Update the cache time again. We want to do this call
428 * as little as possible...
431 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
432 tdb_store_int(tdb, keystr, (int)time(NULL));
435 /****************************************************************************
436 check if a jobid is valid. It is valid if it exists in the database
437 ****************************************************************************/
438 BOOL print_job_exists(int jobid)
440 return tdb_exists(tdb, print_key(jobid));
444 /****************************************************************************
445 work out which service a jobid is for
446 note that we have to look up by queue name to ensure that it works for
447 other than the process that started the job
448 ****************************************************************************/
449 int print_job_snum(int jobid)
451 struct printjob *pjob = print_job_find(jobid);
452 if (!pjob) return -1;
454 return lp_servicenumber(pjob->qname);
457 /****************************************************************************
458 give the fd used for a jobid
459 ****************************************************************************/
460 int print_job_fd(int jobid)
462 struct printjob *pjob = print_job_find(jobid);
463 if (!pjob) return -1;
464 /* don't allow another process to get this info - it is meaningless */
465 if (pjob->pid != local_pid) return -1;
469 /****************************************************************************
470 give the filename used for a jobid
471 only valid for the process doing the spooling and when the job
473 ****************************************************************************/
474 char *print_job_fname(int jobid)
476 struct printjob *pjob = print_job_find(jobid);
477 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
478 return pjob->filename;
482 /****************************************************************************
483 set the place in the queue for a job
484 ****************************************************************************/
485 BOOL print_job_set_place(int jobid, int place)
487 DEBUG(2,("print_job_set_place not implemented yet\n"));
491 /****************************************************************************
492 set the name of a job. Only possible for owner
493 ****************************************************************************/
494 BOOL print_job_set_name(int jobid, char *name)
496 struct printjob *pjob = print_job_find(jobid);
497 if (!pjob || pjob->pid != local_pid) return False;
499 fstrcpy(pjob->jobname, name);
500 return print_job_store(jobid, pjob);
504 /****************************************************************************
505 delete a print job - don't update queue
506 ****************************************************************************/
507 static BOOL print_job_delete1(int jobid)
509 struct printjob *pjob = print_job_find(jobid);
512 if (!pjob) return False;
514 snum = print_job_snum(jobid);
516 if (pjob->spooled && pjob->sysjob != -1) {
517 /* need to delete the spooled entry */
519 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
520 print_run_command(snum,
521 lp_lprmcommand(snum), NULL,
523 "%T", http_timestring(pjob->starttime),
530 /****************************************************************************
531 return true if the current user owns the print job
532 ****************************************************************************/
533 static BOOL is_owner(struct current_user *user, int jobid)
535 struct printjob *pjob = print_job_find(jobid);
538 if (!pjob || !user) return False;
540 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
541 return strequal(pjob->user, vuser->user.smb_name);
543 return strequal(pjob->user, uidtoname(user->uid));
547 /****************************************************************************
549 ****************************************************************************/
550 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
552 int snum = print_job_snum(jobid);
556 owner = is_owner(user, jobid);
558 /* Check access against security descriptor or whether the user
562 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
563 DEBUG(3, ("delete denied by security descriptor\n"));
564 *errcode = ERROR_ACCESS_DENIED;
568 if (!print_job_delete1(jobid)) return False;
570 /* force update the database and say the delete failed if the
573 print_queue_update(snum);
575 /* Send a printer notify message */
577 printer_name = PRINTERNAME(snum);
579 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
581 return !print_job_exists(jobid);
585 /****************************************************************************
587 ****************************************************************************/
588 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
590 struct printjob *pjob = print_job_find(jobid);
596 if (!pjob || !user) return False;
598 if (!pjob->spooled || pjob->sysjob == -1) return False;
600 snum = print_job_snum(jobid);
601 owner = is_owner(user, jobid);
604 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
605 DEBUG(3, ("pause denied by security descriptor\n"));
606 *errcode = ERROR_ACCESS_DENIED;
610 /* need to pause the spooled entry */
611 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
612 ret = print_run_command(snum,
613 lp_lppausecommand(snum), NULL,
618 *errcode = ERROR_INVALID_PARAMETER;
622 /* force update the database */
623 print_cache_flush(snum);
625 /* Send a printer notify message */
627 printer_name = PRINTERNAME(snum);
629 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
631 /* how do we tell if this succeeded? */
636 /****************************************************************************
638 ****************************************************************************/
639 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
641 struct printjob *pjob = print_job_find(jobid);
647 if (!pjob || !user) return False;
649 if (!pjob->spooled || pjob->sysjob == -1) return False;
651 snum = print_job_snum(jobid);
652 owner = is_owner(user, jobid);
654 if (!is_owner(user, jobid) &&
655 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
656 DEBUG(3, ("resume denied by security descriptor\n"));
657 *errcode = ERROR_ACCESS_DENIED;
661 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
662 ret = print_run_command(snum,
663 lp_lpresumecommand(snum), NULL,
668 *errcode = ERROR_INVALID_PARAMETER;
672 /* force update the database */
673 print_cache_flush(snum);
675 /* Send a printer notify message */
677 printer_name = PRINTERNAME(snum);
679 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
684 /****************************************************************************
685 write to a print file
686 ****************************************************************************/
687 int print_job_write(int jobid, const char *buf, int size)
691 fd = print_job_fd(jobid);
692 if (fd == -1) return -1;
694 return write(fd, buf, size);
697 /****************************************************************************
698 Check if the print queue has been updated recently enough.
699 ****************************************************************************/
701 static BOOL print_cache_expired(int snum)
704 time_t t2, t = time(NULL);
706 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
707 t2 = tdb_fetch_int(tdb, key);
708 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
709 DEBUG(3, ("print cache expired\n"));
715 /****************************************************************************
716 Determine the number of jobs in a queue.
717 ****************************************************************************/
719 static int print_queue_length(int snum)
723 print_status_struct status;
725 /* make sure the database is up to date */
726 if (print_cache_expired(snum)) print_queue_update(snum);
728 /* also fetch the queue status */
729 ZERO_STRUCTP(&status);
730 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
732 key.dsize = strlen(keystr);
733 data = tdb_fetch(tdb, key);
735 if (data.dsize == sizeof(status)) {
736 memcpy(&status, data.dptr, sizeof(status));
740 return status.qcount;
743 /***************************************************************************
744 start spooling a job - return the jobid
745 ***************************************************************************/
746 int print_job_start(struct current_user *user, int snum, char *jobname)
750 struct printjob pjob;
756 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
757 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
761 if (!print_time_access_check(snum)) {
762 DEBUG(3, ("print_job_start: job start denied by time check\n"));
766 path = lp_pathname(snum);
768 /* see if we have sufficient disk space */
769 if (lp_minprintspace(snum)) {
770 SMB_BIG_UINT dspace, dsize;
771 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
772 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
778 /* for autoloaded printers, check that the printcap entry still exists */
779 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
784 if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
789 /* create the database entry */
791 pjob.pid = local_pid;
794 pjob.starttime = time(NULL);
795 pjob.status = LPQ_QUEUED;
797 pjob.spooled = False;
800 fstrcpy(pjob.jobname, jobname);
802 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
803 fstrcpy(pjob.user, vuser->user.smb_name);
805 fstrcpy(pjob.user, uidtoname(user->uid));
808 fstrcpy(pjob.qname, lp_servicename(snum));
810 /* lock the database */
811 tdb_lock_bystring(tdb, "INFO/nextjob");
814 next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
815 if (next_jobid == -1) next_jobid = 1;
817 for (jobid = next_jobid+1; jobid != next_jobid; ) {
818 if (!print_job_exists(jobid)) break;
819 jobid = (jobid + 1) % PRINT_MAX_JOBID;
820 if (jobid == 0) jobid = 1;
822 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
827 tdb_store_int(tdb, "INFO/nextjob", jobid);
829 /* we have a job entry - now create the spool file
831 we unlink first to cope with old spool files and also to beat
832 a symlink security hole - it allows us to use O_EXCL
833 There may be old spool files owned by other users lying around.
835 slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
836 path, PRINT_SPOOL_PREFIX, jobid);
837 if (unlink(pjob.filename) == -1 && errno != ENOENT) {
840 pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
841 if (pjob.fd == -1) goto fail;
843 print_job_store(jobid, &pjob);
845 tdb_unlock_bystring(tdb, "INFO/nextjob");
848 * If the printer is marked as postscript output a leading
849 * file identifier to ensure the file is treated as a raw
851 * This has a similar effect as CtrlD=0 in WIN.INI file.
852 * tim@fsg.com 09/06/94
854 if (lp_postscript(snum)) {
855 print_job_write(jobid, "%!\n",3);
862 tdb_delete(tdb, print_key(jobid));
865 tdb_unlock_bystring(tdb, "INFO/nextjob");
869 /****************************************************************************
870 Print a file - called on closing the file. This spools the job.
871 ****************************************************************************/
873 BOOL print_job_end(int jobid)
875 struct printjob *pjob = print_job_find(jobid);
877 SMB_STRUCT_STAT sbuf;
878 pstring current_directory;
879 pstring print_directory;
880 char *wd, *p, *printer_name;
886 if (pjob->spooled || pjob->pid != local_pid)
889 snum = print_job_snum(jobid);
891 if (sys_fstat(pjob->fd, &sbuf) == 0)
892 pjob->size = sbuf.st_size;
897 if (pjob->size == 0) {
898 /* don't bother spooling empty files */
899 unlink(pjob->filename);
900 tdb_delete(tdb, print_key(jobid));
904 /* we print from the directory path to give the best chance of
905 parsing the lpq output */
906 wd = sys_getwd(current_directory);
910 pstrcpy(print_directory, pjob->filename);
911 p = strrchr(print_directory,'/');
916 if (chdir(print_directory) != 0)
919 pstrcpy(jobname, pjob->jobname);
920 pstring_sub(jobname, "'", "_");
922 /* send it to the system spooler */
923 print_run_command(snum,
924 lp_printcommand(snum), NULL,
932 pjob->spooled = True;
933 print_job_store(jobid, pjob);
935 /* force update the database */
936 print_cache_flush(snum);
938 /* Send a printer notify message */
940 printer_name = PRINTERNAME(snum);
942 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
947 /* utility fn to enumerate the print queue */
948 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
950 struct traverse_struct *ts = (struct traverse_struct *)state;
951 struct printjob pjob;
954 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
955 memcpy(&jobid, key.dptr, sizeof(jobid));
956 memcpy(&pjob, data.dptr, sizeof(pjob));
958 /* maybe it isn't for this queue */
959 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
961 if (ts->qcount >= ts->maxcount) return 0;
965 ts->queue[i].job = jobid;
966 ts->queue[i].size = pjob.size;
967 ts->queue[i].status = pjob.status;
968 ts->queue[i].priority = 1;
969 ts->queue[i].time = pjob.starttime;
970 fstrcpy(ts->queue[i].user, pjob.user);
971 fstrcpy(ts->queue[i].file, pjob.jobname);
978 struct traverse_count_struct {
982 /* utility fn to count the number of entries in the print queue */
983 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
985 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
986 struct printjob pjob;
989 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
990 memcpy(&jobid, key.dptr, sizeof(jobid));
991 memcpy(&pjob, data.dptr, sizeof(pjob));
993 /* maybe it isn't for this queue */
994 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1001 /* Sort print jobs by submittal time */
1003 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1007 if (!j1 && !j2) return 0;
1011 /* Sort on job start time */
1013 if (j1->time == j2->time) return 0;
1014 return (j1->time > j2->time) ? 1 : -1;
1017 /****************************************************************************
1018 get a printer queue listing
1019 ****************************************************************************/
1020 int print_queue_status(int snum,
1021 print_queue_struct **queue,
1022 print_status_struct *status)
1024 struct traverse_struct tstruct;
1025 struct traverse_count_struct tsc;
1029 /* make sure the database is up to date */
1030 if (print_cache_expired(snum)) print_queue_update(snum);
1035 * Count the number of entries.
1039 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1044 /* Allocate the queue size. */
1045 if ((tstruct.queue = (print_queue_struct *)
1046 malloc(sizeof(print_queue_struct)*tsc.count))
1051 * Fill in the queue.
1052 * We need maxcount as the queue size may have changed between
1053 * the two calls to tdb_traverse.
1056 tstruct.maxcount = tsc.count;
1057 tstruct.snum = snum;
1059 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1061 /* also fetch the queue status */
1062 ZERO_STRUCTP(status);
1063 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1065 key.dsize = strlen(keystr);
1066 data = tdb_fetch(tdb, key);
1068 if (data.dsize == sizeof(*status)) {
1069 memcpy(status, data.dptr, sizeof(*status));
1074 /* Sort the queue by submission time otherwise they are displayed
1077 qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1078 QSORT_CAST(printjob_comp));
1080 *queue = tstruct.queue;
1081 return tstruct.qcount;
1085 /****************************************************************************
1086 turn a queue name into a snum
1087 ****************************************************************************/
1088 int print_queue_snum(char *qname)
1090 int snum = lp_servicenumber(qname);
1091 if (snum == -1 || !lp_print_ok(snum)) return -1;
1096 /****************************************************************************
1098 ****************************************************************************/
1099 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1104 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1105 *errcode = ERROR_ACCESS_DENIED;
1109 ret = print_run_command(snum, lp_queuepausecommand(snum), NULL,
1113 *errcode = ERROR_INVALID_PARAMETER;
1117 /* force update the database */
1118 print_cache_flush(snum);
1120 /* Send a printer notify message */
1122 printer_name = PRINTERNAME(snum);
1124 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1129 /****************************************************************************
1131 ****************************************************************************/
1132 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1137 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1138 *errcode = ERROR_ACCESS_DENIED;
1142 ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
1146 *errcode = ERROR_INVALID_PARAMETER;
1150 /* force update the database */
1151 print_cache_flush(snum);
1153 /* Send a printer notify message */
1155 printer_name = PRINTERNAME(snum);
1157 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1162 /****************************************************************************
1163 purge a queue - implemented by deleting all jobs that we can delete
1164 ****************************************************************************/
1165 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1167 print_queue_struct *queue;
1168 print_status_struct status;
1172 njobs = print_queue_status(snum, &queue, &status);
1173 for (i=0;i<njobs;i++) {
1174 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1175 print_job_delete1(queue[i].job);
1179 print_cache_flush(snum);
1182 /* Send a printer notify message */
1184 printer_name = PRINTERNAME(snum);
1186 message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);