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 /* Convert script args to unix-codepage */
173 dos_to_unix(syscmd, True);
174 ret = smbrun(syscmd,outfile,False);
176 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
182 /****************************************************************************
183 parse a file name from the system spooler to generate a jobid
184 ****************************************************************************/
185 static int print_parse_jobid(char *fname)
189 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
190 fname += strlen(PRINT_SPOOL_PREFIX);
193 if (jobid <= 0) return -1;
199 /****************************************************************************
200 list a unix job in the print database
201 ****************************************************************************/
202 static void print_unix_job(int snum, print_queue_struct *q)
204 int jobid = q->job + UNIX_JOB_START;
205 struct printjob pj, *old_pj;
207 /* Preserve the timestamp on an existing unix print job */
209 old_pj = print_job_find(jobid);
216 pj.starttime = old_pj ? old_pj->starttime : q->time;
217 pj.status = q->status;
221 fstrcpy(pj.filename, "");
222 fstrcpy(pj.jobname, q->file);
223 fstrcpy(pj.user, q->user);
224 fstrcpy(pj.qname, lp_servicename(snum));
226 print_job_store(jobid, &pj);
230 struct traverse_struct {
231 print_queue_struct *queue;
232 int qcount, snum, maxcount;
235 /* utility fn to delete any jobs that are no longer active */
236 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
238 struct traverse_struct *ts = (struct traverse_struct *)state;
239 struct printjob pjob;
242 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
243 memcpy(&jobid, key.dptr, sizeof(jobid));
244 memcpy(&pjob, data.dptr, sizeof(pjob));
246 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
247 /* this isn't for the queue we are looking at */
252 /* remove a unix job if it isn't in the system queue
255 for (i=0;i<ts->qcount;i++) {
256 if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
258 if (i == ts->qcount) tdb_delete(tdb, key);
262 /* maybe it hasn't been spooled yet */
264 /* if a job is not spooled and the process doesn't
265 exist then kill it. This cleans up after smbd
267 if (!process_exists(pjob.pid)) {
268 tdb_delete(tdb, key);
273 for (i=0;i<ts->qcount;i++) {
274 int qid = print_parse_jobid(ts->queue[i].file);
275 if (jobid == qid) break;
278 /* The job isn't in the system queue - we have to assume it has
279 completed, so delete the database entry. */
281 if (i == ts->qcount) {
282 time_t cur_t = time(NULL);
284 /* A race can occur between the time a job is spooled and
285 when it appears in the lpq output. This happens when
286 the job is added to printing.tdb when another smbd
287 running print_queue_update() has completed a lpq and
288 is currently traversing the printing tdb and deleting jobs.
289 A workaround is to not delete the job if it has been
290 submitted less than lp_lpqcachetime() seconds ago. */
292 if ((cur_t - pjob.starttime) > lp_lpqcachetime()) {
300 /****************************************************************************
301 check if the print queue has been updated recently enough
302 ****************************************************************************/
303 static void print_cache_flush(int snum)
306 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
307 tdb_store_int(tdb, key, -1);
310 /****************************************************************************
311 update the internal database from the system print queue for a queue
312 ****************************************************************************/
313 static void print_queue_update(int snum)
315 char *path = lp_pathname(snum);
316 char *cmd = lp_lpqcommand(snum);
319 int numlines, i, qcount;
320 print_queue_struct *queue = NULL;
321 print_status_struct status;
322 print_status_struct old_status;
323 struct printjob *pjob;
324 struct traverse_struct tstruct;
325 fstring keystr, printer_name;
328 fstrcpy(printer_name, lp_servicename(snum));
331 * Update the cache time FIRST ! Stops others doing this
332 * if the lpq takes a long time.
335 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
336 tdb_store_int(tdb, keystr, (int)time(NULL));
338 slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
341 print_run_command(snum, cmd, tmp_file, NULL);
344 qlines = file_lines_load(tmp_file, &numlines, True);
347 /* turn the lpq output into a series of job structures */
351 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
354 for (i=0; i<numlines; i++) {
356 if (parse_lpq_entry(snum,qlines[i],
357 &queue[qcount],&status,qcount==0)) {
362 file_lines_free(qlines);
364 DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
365 "s" : "", printer_name));
367 /* Lock the queue for the database update */
369 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
370 tdb_lock_bystring(tdb, keystr);
373 any job in the internal database that is marked as spooled
374 and doesn't exist in the system queue is considered finished
375 and removed from the database
377 any job in the system database but not in the internal database
378 is added as a unix job
380 fill in any system job numbers as we go
382 for (i=0; i<qcount; i++) {
383 int jobid = print_parse_jobid(queue[i].file);
386 /* assume its a unix print job */
387 print_unix_job(snum, &queue[i]);
391 /* we have an active SMB print job - update its status */
392 pjob = print_job_find(jobid);
394 /* err, somethings wrong. Probably smbd was restarted
395 with jobs in the queue. All we can do is treat them
396 like unix jobs. Pity. */
397 print_unix_job(snum, &queue[i]);
401 pjob->sysjob = queue[i].job;
402 pjob->status = queue[i].status;
404 print_job_store(jobid, pjob);
407 /* now delete any queued entries that don't appear in the
409 tstruct.queue = queue;
410 tstruct.qcount = qcount;
413 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
415 safe_free(tstruct.queue);
418 * Get the old print status. We will use this to compare the
419 * number of jobs. If they have changed we need to send a
420 * "changed" message to the smbds.
423 if( qcount != get_queue_status(snum, &old_status)) {
424 DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
425 old_status.qcount, qcount, printer_name ));
426 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
429 /* store the new queue status structure */
430 slprintf(keystr, sizeof(keystr), "STATUS/%s", printer_name);
432 key.dsize = strlen(keystr);
434 status.qcount = qcount;
435 data.dptr = (void *)&status;
436 data.dsize = sizeof(status);
437 tdb_store(tdb, key, data, TDB_REPLACE);
439 /* Unlock for database update */
441 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
442 tdb_unlock_bystring(tdb, keystr);
445 * Update the cache time again. We want to do this call
446 * as little as possible...
449 slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
450 tdb_store_int(tdb, keystr, (int)time(NULL));
453 /****************************************************************************
454 check if a jobid is valid. It is valid if it exists in the database
455 ****************************************************************************/
456 BOOL print_job_exists(int jobid)
458 return tdb_exists(tdb, print_key(jobid));
462 /****************************************************************************
463 work out which service a jobid is for
464 note that we have to look up by queue name to ensure that it works for
465 other than the process that started the job
466 ****************************************************************************/
467 int print_job_snum(int jobid)
469 struct printjob *pjob = print_job_find(jobid);
470 if (!pjob) return -1;
472 return lp_servicenumber(pjob->qname);
475 /****************************************************************************
476 give the fd used for a jobid
477 ****************************************************************************/
478 int print_job_fd(int jobid)
480 struct printjob *pjob = print_job_find(jobid);
481 if (!pjob) return -1;
482 /* don't allow another process to get this info - it is meaningless */
483 if (pjob->pid != local_pid) return -1;
487 /****************************************************************************
488 give the filename used for a jobid
489 only valid for the process doing the spooling and when the job
491 ****************************************************************************/
492 char *print_job_fname(int jobid)
494 struct printjob *pjob = print_job_find(jobid);
495 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
496 return pjob->filename;
500 /****************************************************************************
501 set the place in the queue for a job
502 ****************************************************************************/
503 BOOL print_job_set_place(int jobid, int place)
505 DEBUG(2,("print_job_set_place not implemented yet\n"));
509 /****************************************************************************
510 set the name of a job. Only possible for owner
511 ****************************************************************************/
512 BOOL print_job_set_name(int jobid, char *name)
514 struct printjob *pjob = print_job_find(jobid);
515 if (!pjob || pjob->pid != local_pid) return False;
517 fstrcpy(pjob->jobname, name);
518 return print_job_store(jobid, pjob);
522 /****************************************************************************
523 delete a print job - don't update queue
524 ****************************************************************************/
525 static BOOL print_job_delete1(int jobid)
527 struct printjob *pjob = print_job_find(jobid);
530 if (!pjob) return False;
532 snum = print_job_snum(jobid);
534 if (pjob->spooled && pjob->sysjob != -1) {
535 /* need to delete the spooled entry */
537 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
538 print_run_command(snum,
539 lp_lprmcommand(snum), NULL,
541 "%T", http_timestring(pjob->starttime),
548 /****************************************************************************
549 return true if the current user owns the print job
550 ****************************************************************************/
551 static BOOL is_owner(struct current_user *user, int jobid)
553 struct printjob *pjob = print_job_find(jobid);
556 if (!pjob || !user) return False;
558 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
559 return strequal(pjob->user, vuser->user.smb_name);
561 return strequal(pjob->user, uidtoname(user->uid));
565 /****************************************************************************
567 ****************************************************************************/
568 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
570 int snum = print_job_snum(jobid);
574 owner = is_owner(user, jobid);
576 /* Check access against security descriptor or whether the user
580 !print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
581 DEBUG(3, ("delete denied by security descriptor\n"));
582 *errcode = ERROR_ACCESS_DENIED;
586 if (!print_job_delete1(jobid)) return False;
588 /* force update the database and say the delete failed if the
591 print_queue_update(snum);
593 /* Send a printer notify message */
595 printer_name = PRINTERNAME(snum);
597 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
599 return !print_job_exists(jobid);
603 /****************************************************************************
605 ****************************************************************************/
606 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
608 struct printjob *pjob = print_job_find(jobid);
614 if (!pjob || !user) return False;
616 if (!pjob->spooled || pjob->sysjob == -1) return False;
618 snum = print_job_snum(jobid);
619 owner = is_owner(user, jobid);
622 !print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
623 DEBUG(3, ("pause denied by security descriptor\n"));
624 *errcode = ERROR_ACCESS_DENIED;
628 /* need to pause the spooled entry */
629 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
630 ret = print_run_command(snum,
631 lp_lppausecommand(snum), NULL,
636 *errcode = ERROR_INVALID_PARAMETER;
640 /* force update the database */
641 print_cache_flush(snum);
643 /* Send a printer notify message */
645 printer_name = PRINTERNAME(snum);
647 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
649 /* how do we tell if this succeeded? */
654 /****************************************************************************
656 ****************************************************************************/
657 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
659 struct printjob *pjob = print_job_find(jobid);
665 if (!pjob || !user) return False;
667 if (!pjob->spooled || pjob->sysjob == -1) return False;
669 snum = print_job_snum(jobid);
670 owner = is_owner(user, jobid);
672 if (!is_owner(user, jobid) &&
673 !print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
674 DEBUG(3, ("resume denied by security descriptor\n"));
675 *errcode = ERROR_ACCESS_DENIED;
679 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
680 ret = print_run_command(snum,
681 lp_lpresumecommand(snum), NULL,
686 *errcode = ERROR_INVALID_PARAMETER;
690 /* force update the database */
691 print_cache_flush(snum);
693 /* Send a printer notify message */
695 printer_name = PRINTERNAME(snum);
697 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
702 /****************************************************************************
703 write to a print file
704 ****************************************************************************/
705 int print_job_write(int jobid, const char *buf, int size)
709 fd = print_job_fd(jobid);
710 if (fd == -1) return -1;
712 return write(fd, buf, size);
715 /****************************************************************************
716 Check if the print queue has been updated recently enough.
717 ****************************************************************************/
719 static BOOL print_cache_expired(int snum)
722 time_t t2, t = time(NULL);
724 slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
725 t2 = tdb_fetch_int(tdb, key);
726 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
727 DEBUG(3, ("print cache expired\n"));
733 /****************************************************************************
734 Get the queue status - do not update if db is out of date.
735 ****************************************************************************/
737 static int get_queue_status(int snum, print_status_struct *status)
742 ZERO_STRUCTP(status);
743 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
745 key.dsize = strlen(keystr);
746 data = tdb_fetch(tdb, key);
748 if (data.dsize == sizeof(print_status_struct)) {
749 memcpy(status, data.dptr, sizeof(print_status_struct));
753 return status->qcount;
756 /****************************************************************************
757 Determine the number of jobs in a queue.
758 ****************************************************************************/
760 static int print_queue_length(int snum)
762 print_status_struct status;
764 /* make sure the database is up to date */
765 if (print_cache_expired(snum)) print_queue_update(snum);
767 /* also fetch the queue status */
768 return get_queue_status(snum, &status);
771 /***************************************************************************
772 start spooling a job - return the jobid
773 ***************************************************************************/
774 int print_job_start(struct current_user *user, int snum, char *jobname)
778 struct printjob pjob;
784 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
785 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
789 if (!print_time_access_check(snum)) {
790 DEBUG(3, ("print_job_start: job start denied by time check\n"));
794 path = lp_pathname(snum);
796 /* see if we have sufficient disk space */
797 if (lp_minprintspace(snum)) {
798 SMB_BIG_UINT dspace, dsize;
799 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
800 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
806 /* for autoloaded printers, check that the printcap entry still exists */
807 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
812 if (lp_maxprintjobs(snum) && print_queue_length(snum) > lp_maxprintjobs(snum)) {
817 /* create the database entry */
819 pjob.pid = local_pid;
822 pjob.starttime = time(NULL);
823 pjob.status = LPQ_QUEUED;
825 pjob.spooled = False;
828 fstrcpy(pjob.jobname, jobname);
830 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
831 fstrcpy(pjob.user, vuser->user.smb_name);
833 fstrcpy(pjob.user, uidtoname(user->uid));
836 fstrcpy(pjob.qname, lp_servicename(snum));
838 /* lock the database */
839 tdb_lock_bystring(tdb, "INFO/nextjob");
842 next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
843 if (next_jobid == -1) next_jobid = 1;
845 for (jobid = next_jobid+1; jobid != next_jobid; ) {
846 if (!print_job_exists(jobid)) break;
847 jobid = (jobid + 1) % PRINT_MAX_JOBID;
848 if (jobid == 0) jobid = 1;
850 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
855 tdb_store_int(tdb, "INFO/nextjob", jobid);
857 /* we have a job entry - now create the spool file
859 we unlink first to cope with old spool files and also to beat
860 a symlink security hole - it allows us to use O_EXCL
861 There may be old spool files owned by other users lying around.
863 slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
864 path, PRINT_SPOOL_PREFIX, jobid);
865 if (unlink(pjob.filename) == -1 && errno != ENOENT) {
868 pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
869 if (pjob.fd == -1) goto fail;
871 print_job_store(jobid, &pjob);
873 tdb_unlock_bystring(tdb, "INFO/nextjob");
876 * If the printer is marked as postscript output a leading
877 * file identifier to ensure the file is treated as a raw
879 * This has a similar effect as CtrlD=0 in WIN.INI file.
880 * tim@fsg.com 09/06/94
882 if (lp_postscript(snum)) {
883 print_job_write(jobid, "%!\n",3);
890 tdb_delete(tdb, print_key(jobid));
893 tdb_unlock_bystring(tdb, "INFO/nextjob");
897 /****************************************************************************
898 Print a file - called on closing the file. This spools the job.
899 ****************************************************************************/
901 BOOL print_job_end(int jobid)
903 struct printjob *pjob = print_job_find(jobid);
905 SMB_STRUCT_STAT sbuf;
906 pstring current_directory;
907 pstring print_directory;
908 char *wd, *p, *printer_name;
914 if (pjob->spooled || pjob->pid != local_pid)
917 snum = print_job_snum(jobid);
919 if (sys_fstat(pjob->fd, &sbuf) == 0)
920 pjob->size = sbuf.st_size;
925 if (pjob->size == 0) {
926 /* don't bother spooling empty files */
927 unlink(pjob->filename);
928 tdb_delete(tdb, print_key(jobid));
932 /* we print from the directory path to give the best chance of
933 parsing the lpq output */
934 wd = sys_getwd(current_directory);
938 pstrcpy(print_directory, pjob->filename);
939 p = strrchr(print_directory,'/');
944 if (chdir(print_directory) != 0)
947 pstrcpy(jobname, pjob->jobname);
948 pstring_sub(jobname, "'", "_");
950 /* send it to the system spooler */
951 print_run_command(snum,
952 lp_printcommand(snum), NULL,
960 pjob->spooled = True;
961 print_job_store(jobid, pjob);
963 /* force update the database */
964 print_cache_flush(snum);
966 /* Send a printer notify message */
968 printer_name = PRINTERNAME(snum);
970 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
975 /* utility fn to enumerate the print queue */
976 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
978 struct traverse_struct *ts = (struct traverse_struct *)state;
979 struct printjob pjob;
982 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
983 memcpy(&jobid, key.dptr, sizeof(jobid));
984 memcpy(&pjob, data.dptr, sizeof(pjob));
986 /* maybe it isn't for this queue */
987 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
989 if (ts->qcount >= ts->maxcount) return 0;
993 ts->queue[i].job = jobid;
994 ts->queue[i].size = pjob.size;
995 ts->queue[i].status = pjob.status;
996 ts->queue[i].priority = 1;
997 ts->queue[i].time = pjob.starttime;
998 fstrcpy(ts->queue[i].user, pjob.user);
999 fstrcpy(ts->queue[i].file, pjob.jobname);
1006 struct traverse_count_struct {
1010 /* utility fn to count the number of entries in the print queue */
1011 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1013 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1014 struct printjob pjob;
1017 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1018 memcpy(&jobid, key.dptr, sizeof(jobid));
1019 memcpy(&pjob, data.dptr, sizeof(pjob));
1021 /* maybe it isn't for this queue */
1022 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1029 /* Sort print jobs by submittal time */
1031 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1035 if (!j1 && !j2) return 0;
1039 /* Sort on job start time */
1041 if (j1->time == j2->time) return 0;
1042 return (j1->time > j2->time) ? 1 : -1;
1045 /****************************************************************************
1046 get a printer queue listing
1047 ****************************************************************************/
1048 int print_queue_status(int snum,
1049 print_queue_struct **queue,
1050 print_status_struct *status)
1052 struct traverse_struct tstruct;
1053 struct traverse_count_struct tsc;
1057 /* make sure the database is up to date */
1058 if (print_cache_expired(snum)) print_queue_update(snum);
1063 * Fetch the queue status. We must do this first, as there may
1064 * be no jobs in the queue.
1066 ZERO_STRUCTP(status);
1067 slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1069 key.dsize = strlen(keystr);
1070 data = tdb_fetch(tdb, key);
1072 if (data.dsize == sizeof(*status)) {
1073 memcpy(status, data.dptr, sizeof(*status));
1079 * Now, fetch the print queue information. We first count the number
1080 * of entries, and then only retrieve the queue if necessary.
1085 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1090 /* Allocate the queue size. */
1091 if ((tstruct.queue = (print_queue_struct *)
1092 malloc(sizeof(print_queue_struct)*tsc.count))
1097 * Fill in the queue.
1098 * We need maxcount as the queue size may have changed between
1099 * the two calls to tdb_traverse.
1102 tstruct.maxcount = tsc.count;
1103 tstruct.snum = snum;
1105 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1107 /* Sort the queue by submission time otherwise they are displayed
1110 qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1111 QSORT_CAST(printjob_comp));
1113 *queue = tstruct.queue;
1114 return tstruct.qcount;
1118 /****************************************************************************
1119 turn a queue name into a snum
1120 ****************************************************************************/
1121 int print_queue_snum(char *qname)
1123 int snum = lp_servicenumber(qname);
1124 if (snum == -1 || !lp_print_ok(snum)) return -1;
1129 /****************************************************************************
1131 ****************************************************************************/
1132 BOOL print_queue_pause(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_queuepausecommand(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(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1162 /****************************************************************************
1164 ****************************************************************************/
1165 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1170 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1171 *errcode = ERROR_ACCESS_DENIED;
1175 ret = print_run_command(snum, lp_queueresumecommand(snum), NULL,
1179 *errcode = ERROR_INVALID_PARAMETER;
1183 /* force update the database */
1184 print_cache_flush(snum);
1186 /* Send a printer notify message */
1188 printer_name = PRINTERNAME(snum);
1190 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1195 /****************************************************************************
1196 purge a queue - implemented by deleting all jobs that we can delete
1197 ****************************************************************************/
1198 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1200 print_queue_struct *queue;
1201 print_status_struct status;
1205 njobs = print_queue_status(snum, &queue, &status);
1206 for (i=0;i<njobs;i++) {
1207 if (print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1208 print_job_delete1(queue[i].job);
1212 print_cache_flush(snum);
1215 /* Send a printer notify message */
1217 printer_name = PRINTERNAME(snum);
1219 message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);