2 Unix SMB/Netbios implementation.
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* Current printer interface */
25 struct printif *current_printif = &generic_printif;
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.
41 /* the open printing.tdb database */
42 static TDB_CONTEXT *tdb;
43 static pid_t local_pid;
45 static int get_queue_status(int, print_status_struct *);
47 /****************************************************************************
48 Initialise the printing backend. Called once at startup.
49 Does not survive a fork
50 ****************************************************************************/
52 BOOL print_backend_init(void)
54 char *sversion = "INFO/version";
56 if (tdb && local_pid == sys_getpid()) return True;
57 tdb = tdb_open_log(lock_path("printing.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
59 DEBUG(0,("print_backend_init: Failed to open printing backend database. Error = [%s]\n",
63 local_pid = sys_getpid();
65 /* handle a Samba upgrade */
66 tdb_lock_bystring(tdb, sversion);
67 if (tdb_fetch_int32(tdb, sversion) != PRINT_DATABASE_VERSION) {
68 tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
69 tdb_store_int32(tdb, sversion, PRINT_DATABASE_VERSION);
71 tdb_unlock_bystring(tdb, sversion);
73 /* select the appropriate printing interface... */
75 if (strcmp(lp_printcapname(), "cups") == 0)
76 current_printif = &cups_printif;
77 #endif /* HAVE_CUPS */
79 /* do NT print initialization... */
80 return nt_printing_init();
83 /****************************************************************************
84 useful function to generate a tdb key
85 ****************************************************************************/
86 static TDB_DATA print_key(int jobid)
92 ret.dptr = (void *)&j;
93 ret.dsize = sizeof(j);
97 /****************************************************************************
98 useful function to find a print job in the database
99 ****************************************************************************/
100 static struct printjob *print_job_find(int jobid)
102 static struct printjob pjob;
105 ret = tdb_fetch(tdb, print_key(jobid));
106 if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
108 memcpy(&pjob, ret.dptr, sizeof(pjob));
113 /****************************************************************************
114 store a job structure back to the database
115 ****************************************************************************/
116 static BOOL print_job_store(int jobid, struct printjob *pjob)
119 d.dptr = (void *)pjob;
120 d.dsize = sizeof(*pjob);
122 return (tdb_store(tdb, print_key(jobid), d, TDB_REPLACE) == 0);
125 /****************************************************************************
126 parse a file name from the system spooler to generate a jobid
127 ****************************************************************************/
128 static int print_parse_jobid(char *fname)
132 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
133 fname += strlen(PRINT_SPOOL_PREFIX);
136 if (jobid <= 0) return -1;
142 /****************************************************************************
143 list a unix job in the print database
144 ****************************************************************************/
145 static void print_unix_job(int snum, print_queue_struct *q)
147 int jobid = q->job + UNIX_JOB_START;
148 struct printjob pj, *old_pj;
150 /* Preserve the timestamp on an existing unix print job */
152 old_pj = print_job_find(jobid);
159 pj.starttime = old_pj ? old_pj->starttime : q->time;
160 pj.status = q->status;
164 fstrcpy(pj.filename, "");
165 fstrcpy(pj.jobname, q->file);
166 fstrcpy(pj.user, q->user);
167 fstrcpy(pj.qname, lp_servicename(snum));
169 print_job_store(jobid, &pj);
173 struct traverse_struct {
174 print_queue_struct *queue;
175 int qcount, snum, maxcount, total_jobs;
178 /* utility fn to delete any jobs that are no longer active */
179 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
181 struct traverse_struct *ts = (struct traverse_struct *)state;
182 struct printjob pjob;
185 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
186 memcpy(&jobid, key.dptr, sizeof(jobid));
187 memcpy(&pjob, data.dptr, sizeof(pjob));
189 if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
190 /* this isn't for the queue we are looking at */
196 /* remove a unix job if it isn't in the system queue any more */
198 for (i=0;i<ts->qcount;i++) {
199 if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
202 tdb_delete(tdb, key);
208 /* maybe it hasn't been spooled yet */
210 /* if a job is not spooled and the process doesn't
211 exist then kill it. This cleans up after smbd
213 if (!process_exists(pjob.pid))
214 tdb_delete(tdb, key);
220 for (i=0;i<ts->qcount;i++) {
221 int qid = print_parse_jobid(ts->queue[i].file);
222 if (jobid == qid) break;
225 /* The job isn't in the system queue - we have to assume it has
226 completed, so delete the database entry. */
228 if (i == ts->qcount) {
229 time_t cur_t = time(NULL);
231 /* A race can occur between the time a job is spooled and
232 when it appears in the lpq output. This happens when
233 the job is added to printing.tdb when another smbd
234 running print_queue_update() has completed a lpq and
235 is currently traversing the printing tdb and deleting jobs.
236 A workaround is to not delete the job if it has been
237 submitted less than lp_lpqcachetime() seconds ago. */
239 if ((cur_t - pjob.starttime) > lp_lpqcachetime())
251 * Send PRINTER NOTIFY to all processes.
253 void broadcast_printer_notify(const char *printer_name)
256 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name,
257 strlen(printer_name) + 1, False, NULL);
260 /****************************************************************************
261 check if the print queue has been updated recently enough
262 ****************************************************************************/
263 static void print_cache_flush(int snum)
266 slprintf(key, sizeof(key)-1, "CACHE/%s", lp_servicename(snum));
267 tdb_store_int32(tdb, key, -1);
270 /****************************************************************************
271 Check if someone already thinks they are doing the update.
272 ****************************************************************************/
274 static pid_t get_updating_pid(fstring printer_name)
280 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name);
282 key.dsize = strlen(keystr);
284 data = tdb_fetch(tdb, key);
285 if (!data.dptr || data.dsize != sizeof(pid_t))
288 memcpy(&updating_pid, data.dptr, sizeof(pid_t));
291 if (process_exists(updating_pid))
297 /****************************************************************************
298 Set the fact that we're doing the update, or have finished doing the update
300 ****************************************************************************/
302 static void set_updating_pid(fstring printer_name, BOOL delete)
307 pid_t updating_pid = getpid();
309 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name);
311 key.dsize = strlen(keystr);
314 tdb_delete(tdb, key);
318 data.dptr = (void *)&updating_pid;
319 data.dsize = sizeof(pid_t);
321 tdb_store(tdb, key, data, TDB_REPLACE);
324 /****************************************************************************
325 update the internal database from the system print queue for a queue in the background
326 ****************************************************************************/
328 static void print_queue_update_background(int snum)
331 print_queue_struct *queue = NULL;
332 print_status_struct status;
333 print_status_struct old_status;
334 struct printjob *pjob;
335 struct traverse_struct tstruct;
336 fstring keystr, printer_name, cachestr;
339 fstrcpy(printer_name, lp_servicename(snum));
342 * Check to see if someone else is doing this update.
343 * This is essentially a mutex on the update.
346 if (get_updating_pid(printer_name) != -1)
349 /* Lock the queue for the database update */
351 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
352 tdb_lock_bystring(tdb, keystr);
355 * Ensure that no one else got in here.
356 * If the updating pid is still -1 then we are
360 if (get_updating_pid(printer_name) != -1) {
362 * Someone else is doing the update, exit.
364 tdb_unlock_bystring(tdb, keystr);
369 * We're going to do the update ourselves.
372 /* Tell others we're doing the update. */
373 set_updating_pid(printer_name, False);
376 * Allow others to enter and notice we're doing
380 tdb_unlock_bystring(tdb, keystr);
383 * Update the cache time FIRST ! Stops others even
384 * attempting to get the lock and doing this
385 * if the lpq takes a long time.
388 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", printer_name);
389 tdb_store_int32(tdb, cachestr, (int)time(NULL));
391 /* get the current queue using the appropriate interface */
394 qcount = (*(current_printif->queue_get))(snum, &queue, &status);
396 DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
397 "s" : "", printer_name));
400 any job in the internal database that is marked as spooled
401 and doesn't exist in the system queue is considered finished
402 and removed from the database
404 any job in the system database but not in the internal database
405 is added as a unix job
407 fill in any system job numbers as we go
409 for (i=0; i<qcount; i++) {
410 int jobid = print_parse_jobid(queue[i].file);
413 /* assume its a unix print job */
414 print_unix_job(snum, &queue[i]);
418 /* we have an active SMB print job - update its status */
419 pjob = print_job_find(jobid);
421 /* err, somethings wrong. Probably smbd was restarted
422 with jobs in the queue. All we can do is treat them
423 like unix jobs. Pity. */
424 print_unix_job(snum, &queue[i]);
428 pjob->sysjob = queue[i].job;
429 pjob->status = queue[i].status;
431 print_job_store(jobid, pjob);
434 /* now delete any queued entries that don't appear in the
436 tstruct.queue = queue;
437 tstruct.qcount = qcount;
439 tstruct.total_jobs = 0;
441 tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
443 safe_free(tstruct.queue);
445 tdb_store_int32(tdb, "INFO/total_jobs", tstruct.total_jobs);
448 * Get the old print status. We will use this to compare the
449 * number of jobs. If they have changed we need to send a
450 * "changed" message to the smbds.
453 if( qcount != get_queue_status(snum, &old_status)) {
454 DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
455 old_status.qcount, qcount, printer_name ));
456 broadcast_printer_notify(printer_name);
459 /* store the new queue status structure */
460 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printer_name);
462 key.dsize = strlen(keystr);
464 status.qcount = qcount;
465 data.dptr = (void *)&status;
466 data.dsize = sizeof(status);
467 tdb_store(tdb, key, data, TDB_REPLACE);
470 * Update the cache time again. We want to do this call
471 * as little as possible...
474 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", printer_name);
475 tdb_store_int32(tdb, keystr, (int)time(NULL));
477 /* Delete our pid from the db. */
478 set_updating_pid(printer_name, True);
481 /****************************************************************************
482 this is the receive function of the background lpq updater
483 ****************************************************************************/
484 static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t len)
488 print_queue_update_background(snum);
491 static pid_t background_lpq_updater_pid;
493 /****************************************************************************
494 main thread of the background lpq updater
495 ****************************************************************************/
496 void start_background_queue(void)
498 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
499 background_lpq_updater_pid = sys_fork();
501 if (background_lpq_updater_pid == -1) {
502 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
506 if(background_lpq_updater_pid == 0) {
508 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
510 claim_connection(NULL,"smbd lpq backend",MAXSTATUS,False);
512 if (!locking_init(0)) {
516 if (!print_backend_init()) {
520 message_register(MSG_PRINTER_UPDATE, print_queue_receive);
522 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
525 DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
531 /****************************************************************************
532 update the internal database from the system print queue for a queue
533 ****************************************************************************/
534 static void print_queue_update(int snum)
536 message_send_pid(background_lpq_updater_pid, MSG_PRINTER_UPDATE, &snum, sizeof(snum), False);
539 /****************************************************************************
540 check if a jobid is valid. It is valid if it exists in the database
541 ****************************************************************************/
542 BOOL print_job_exists(int jobid)
544 return tdb_exists(tdb, print_key(jobid));
548 /****************************************************************************
549 work out which service a jobid is for
550 note that we have to look up by queue name to ensure that it works for
551 other than the process that started the job
552 ****************************************************************************/
553 int print_job_snum(int jobid)
555 struct printjob *pjob = print_job_find(jobid);
556 if (!pjob) return -1;
558 return lp_servicenumber(pjob->qname);
561 /****************************************************************************
562 give the fd used for a jobid
563 ****************************************************************************/
564 int print_job_fd(int jobid)
566 struct printjob *pjob = print_job_find(jobid);
567 if (!pjob) return -1;
568 /* don't allow another process to get this info - it is meaningless */
569 if (pjob->pid != local_pid) return -1;
573 /****************************************************************************
574 give the filename used for a jobid
575 only valid for the process doing the spooling and when the job
577 ****************************************************************************/
578 char *print_job_fname(int jobid)
580 struct printjob *pjob = print_job_find(jobid);
581 if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
582 return pjob->filename;
586 /****************************************************************************
587 set the place in the queue for a job
588 ****************************************************************************/
589 BOOL print_job_set_place(int jobid, int place)
591 DEBUG(2,("print_job_set_place not implemented yet\n"));
595 /****************************************************************************
596 set the name of a job. Only possible for owner
597 ****************************************************************************/
598 BOOL print_job_set_name(int jobid, char *name)
600 struct printjob *pjob = print_job_find(jobid);
601 if (!pjob || pjob->pid != local_pid) return False;
603 fstrcpy(pjob->jobname, name);
604 return print_job_store(jobid, pjob);
608 /****************************************************************************
609 delete a print job - don't update queue
610 ****************************************************************************/
611 static BOOL print_job_delete1(int jobid)
613 struct printjob *pjob = print_job_find(jobid);
614 int snum, result = 0;
616 if (!pjob) return False;
619 * If already deleting just return.
622 if (pjob->status == LPQ_DELETING)
625 snum = print_job_snum(jobid);
627 /* Hrm - we need to be able to cope with deleting a job before it
628 has reached the spooler. */
630 if (pjob->sysjob == -1) {
631 DEBUG(5, ("attempt to delete job %d not seen by lpr\n",
635 /* Set the tdb entry to be deleting. */
637 pjob->status = LPQ_DELETING;
638 print_job_store(jobid, pjob);
640 if (pjob->spooled && pjob->sysjob != -1)
641 result = (*(current_printif->job_delete))(snum, pjob);
643 /* Delete the tdb entry if the delete suceeded or the job hasn't
647 tdb_delete(tdb, print_key(jobid));
650 return (result == 0);
653 /****************************************************************************
654 return true if the current user owns the print job
655 ****************************************************************************/
656 static BOOL is_owner(struct current_user *user, int jobid)
658 struct printjob *pjob = print_job_find(jobid);
661 if (!pjob || !user) return False;
663 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
664 return strequal(pjob->user, vuser->user.smb_name);
666 return strequal(pjob->user, uidtoname(user->uid));
670 /****************************************************************************
672 ****************************************************************************/
673 BOOL print_job_delete(struct current_user *user, int jobid, WERROR *errcode)
675 int snum = print_job_snum(jobid);
679 owner = is_owner(user, jobid);
681 /* Check access against security descriptor or whether the user
685 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
686 DEBUG(3, ("delete denied by security descriptor\n"));
687 *errcode = WERR_ACCESS_DENIED;
691 if (!print_job_delete1(jobid)) return False;
693 /* force update the database and say the delete failed if the
696 print_queue_update(snum);
698 /* Send a printer notify message */
700 printer_name = PRINTERNAME(snum);
702 broadcast_printer_notify(printer_name);
704 return !print_job_exists(jobid);
708 /****************************************************************************
710 ****************************************************************************/
711 BOOL print_job_pause(struct current_user *user, int jobid, WERROR *errcode)
713 struct printjob *pjob = print_job_find(jobid);
717 if (!pjob || !user) return False;
719 if (!pjob->spooled || pjob->sysjob == -1) return False;
721 snum = print_job_snum(jobid);
723 if (!is_owner(user, jobid) &&
724 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
725 DEBUG(3, ("pause denied by security descriptor\n"));
726 *errcode = WERR_ACCESS_DENIED;
730 /* need to pause the spooled entry */
731 ret = (*(current_printif->job_pause))(snum, pjob);
734 *errcode = WERR_INVALID_PARAM;
738 /* force update the database */
739 print_cache_flush(snum);
741 /* Send a printer notify message */
743 printer_name = PRINTERNAME(snum);
745 broadcast_printer_notify(printer_name);
747 /* how do we tell if this succeeded? */
752 /****************************************************************************
754 ****************************************************************************/
755 BOOL print_job_resume(struct current_user *user, int jobid, WERROR *errcode)
757 struct printjob *pjob = print_job_find(jobid);
761 if (!pjob || !user) return False;
763 if (!pjob->spooled || pjob->sysjob == -1) return False;
765 snum = print_job_snum(jobid);
767 if (!is_owner(user, jobid) &&
768 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
769 DEBUG(3, ("resume denied by security descriptor\n"));
770 *errcode = WERR_ACCESS_DENIED;
774 ret = (*(current_printif->job_resume))(snum, pjob);
777 *errcode = WERR_INVALID_PARAM;
781 /* force update the database */
782 print_cache_flush(snum);
784 /* Send a printer notify message */
786 printer_name = PRINTERNAME(snum);
788 broadcast_printer_notify(printer_name);
793 /****************************************************************************
794 write to a print file
795 ****************************************************************************/
796 int print_job_write(int jobid, const char *buf, int size)
800 fd = print_job_fd(jobid);
801 if (fd == -1) return -1;
803 return write(fd, buf, size);
806 /****************************************************************************
807 Check if the print queue has been updated recently enough.
808 ****************************************************************************/
810 static BOOL print_cache_expired(int snum)
813 time_t t2, t = time(NULL);
815 slprintf(key, sizeof(key)-1, "CACHE/%s", lp_servicename(snum));
816 t2 = tdb_fetch_int32(tdb, key);
817 if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
818 DEBUG(3, ("print cache expired for queue %s \
819 (last_cache = %d, time now = %d, qcachetime = %d)\n", lp_servicename(snum),
820 (int)t2, (int)t, (int)lp_lpqcachetime() ));
826 /****************************************************************************
827 Get the queue status - do not update if db is out of date.
828 ****************************************************************************/
829 static int get_queue_status(int snum, print_status_struct *status)
834 ZERO_STRUCTP(status);
835 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", lp_servicename(snum));
837 key.dsize = strlen(keystr);
838 data = tdb_fetch(tdb, key);
840 if (data.dsize == sizeof(print_status_struct)) {
841 memcpy(status, data.dptr, sizeof(print_status_struct));
845 return status->qcount;
848 /****************************************************************************
849 Determine the number of jobs in a queue.
850 ****************************************************************************/
852 int print_queue_length(int snum, print_status_struct *pstatus)
854 print_status_struct status;
857 /* make sure the database is up to date */
858 if (print_cache_expired(snum))
859 print_queue_update(snum);
861 /* also fetch the queue status */
862 memset(&status, 0, sizeof(status));
863 len = get_queue_status(snum, &status);
869 /****************************************************************************
870 Determine the number of jobs in all queues.
871 ****************************************************************************/
872 static int get_total_jobs(int snum)
876 /* make sure the database is up to date */
877 if (print_cache_expired(snum)) print_queue_update(snum);
879 total_jobs = tdb_fetch_int32(tdb, "INFO/total_jobs");
886 /***************************************************************************
887 start spooling a job - return the jobid
888 ***************************************************************************/
889 int print_job_start(struct current_user *user, int snum, char *jobname)
893 struct printjob pjob;
900 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
901 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
905 if (!print_time_access_check(snum)) {
906 DEBUG(3, ("print_job_start: job start denied by time check\n"));
910 path = lp_pathname(snum);
912 /* see if we have sufficient disk space */
913 if (lp_minprintspace(snum)) {
914 SMB_BIG_UINT dspace, dsize;
915 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
916 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
917 DEBUG(3, ("print_job_start: disk space check failed.\n"));
923 /* for autoloaded printers, check that the printcap entry still exists */
924 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
925 DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_servicename(snum) ));
930 /* Insure the maximum queue size is not violated */
931 if (lp_maxprintjobs(snum) && (njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
932 DEBUG(3, ("print_job_start: number of jobs (%d) larger than max printjobs per queue (%d).\n",
933 njobs, lp_maxprintjobs(snum) ));
938 /* Insure the maximum print jobs in the system is not violated */
939 if (lp_totalprintjobs() && get_total_jobs(snum) > lp_totalprintjobs()) {
940 DEBUG(3, ("print_job_start: number of jobs (%d) larger than max printjobs per system (%d).\n",
941 njobs, lp_totalprintjobs() ));
946 /* create the database entry */
948 pjob.pid = local_pid;
951 pjob.starttime = time(NULL);
952 pjob.status = LPQ_SPOOLING;
954 pjob.spooled = False;
957 fstrcpy(pjob.jobname, jobname);
959 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
960 fstrcpy(pjob.user, vuser->user.smb_name);
962 fstrcpy(pjob.user, uidtoname(user->uid));
965 fstrcpy(pjob.qname, lp_servicename(snum));
967 /* lock the database */
968 tdb_lock_bystring(tdb, "INFO/nextjob");
970 next_jobid = tdb_fetch_int32(tdb, "INFO/nextjob");
971 if (next_jobid == -1)
974 for (jobid = NEXT_JOBID(next_jobid); jobid != next_jobid; jobid = NEXT_JOBID(jobid)) {
975 if (!print_job_exists(jobid))
978 if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
979 DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or print_job_store failed.\n",
980 jobid, next_jobid ));
985 tdb_store_int32(tdb, "INFO/nextjob", jobid);
987 /* we have a job entry - now create the spool file */
988 slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.6d.XXXXXX",
989 path, PRINT_SPOOL_PREFIX, jobid);
990 pjob.fd = smb_mkstemp(pjob.filename);
993 if (errno == EACCES) {
994 /* Common setup error, force a report. */
995 DEBUG(0, ("print_job_start: insufficient permissions \
996 to open spool file %s.\n", pjob.filename));
998 /* Normal case, report at level 3 and above. */
999 DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename));
1000 DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno)));
1005 print_job_store(jobid, &pjob);
1007 tdb_unlock_bystring(tdb, "INFO/nextjob");
1010 * If the printer is marked as postscript output a leading
1011 * file identifier to ensure the file is treated as a raw
1013 * This has a similar effect as CtrlD=0 in WIN.INI file.
1014 * tim@fsg.com 09/06/94
1016 if (lp_postscript(snum)) {
1017 print_job_write(jobid, "%!\n",3);
1024 tdb_delete(tdb, print_key(jobid));
1027 tdb_unlock_bystring(tdb, "INFO/nextjob");
1029 DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
1033 /****************************************************************************
1034 Print a file - called on closing the file. This spools the job.
1035 If normal close is false then we're tearing down the jobs - treat as an
1037 ****************************************************************************/
1039 BOOL print_job_end(int jobid, BOOL normal_close)
1041 struct printjob *pjob = print_job_find(jobid);
1043 SMB_STRUCT_STAT sbuf;
1048 if (pjob->spooled || pjob->pid != local_pid)
1051 snum = print_job_snum(jobid);
1053 if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
1054 pjob->size = sbuf.st_size;
1060 * Not a normal close or we couldn't stat the job file,
1061 * so something has gone wrong. Cleanup.
1065 DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid ));
1069 /* Technically, this is not quit right. If the printer has a separator
1070 * page turned on, the NT spooler prints the separator page even if the
1071 * print job is 0 bytes. 010215 JRR */
1072 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
1073 /* don't bother spooling empty files or something being deleted. */
1074 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
1075 pjob->filename, pjob->size ? "deleted" : "zero length" ));
1076 unlink(pjob->filename);
1077 tdb_delete(tdb, print_key(jobid));
1081 ret = (*(current_printif->job_submit))(snum, pjob);
1086 /* The print job has been sucessfully handed over to the back-end */
1088 pjob->spooled = True;
1089 pjob->status = LPQ_QUEUED;
1090 print_job_store(jobid, pjob);
1092 /* make sure the database is up to date */
1093 if (print_cache_expired(snum))
1094 print_queue_update(snum);
1100 /* The print job was not succesfully started. Cleanup */
1101 /* Still need to add proper error return propagation! 010122:JRR */
1102 unlink(pjob->filename);
1103 tdb_delete(tdb, print_key(jobid));
1107 /* utility fn to enumerate the print queue */
1108 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1110 struct traverse_struct *ts = (struct traverse_struct *)state;
1111 struct printjob pjob;
1114 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1115 memcpy(&jobid, key.dptr, sizeof(jobid));
1116 memcpy(&pjob, data.dptr, sizeof(pjob));
1118 /* maybe it isn't for this queue */
1119 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1121 if (ts->qcount >= ts->maxcount) return 0;
1125 ts->queue[i].job = jobid;
1126 ts->queue[i].size = pjob.size;
1127 ts->queue[i].status = pjob.status;
1128 ts->queue[i].priority = 1;
1129 ts->queue[i].time = pjob.starttime;
1130 fstrcpy(ts->queue[i].user, pjob.user);
1131 fstrcpy(ts->queue[i].file, pjob.jobname);
1138 struct traverse_count_struct {
1142 /* utility fn to count the number of entries in the print queue */
1143 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1145 struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1146 struct printjob pjob;
1149 if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1150 memcpy(&jobid, key.dptr, sizeof(jobid));
1151 memcpy(&pjob, data.dptr, sizeof(pjob));
1153 /* maybe it isn't for this queue */
1154 if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1161 /* Sort print jobs by submittal time */
1163 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1167 if (!j1 && !j2) return 0;
1171 /* Sort on job start time */
1173 if (j1->time == j2->time) return 0;
1174 return (j1->time > j2->time) ? 1 : -1;
1177 /****************************************************************************
1178 get a printer queue listing
1179 ****************************************************************************/
1180 int print_queue_status(int snum,
1181 print_queue_struct **queue,
1182 print_status_struct *status)
1184 struct traverse_struct tstruct;
1185 struct traverse_count_struct tsc;
1189 /* make sure the database is up to date */
1190 if (print_cache_expired(snum)) print_queue_update(snum);
1195 * Fetch the queue status. We must do this first, as there may
1196 * be no jobs in the queue.
1198 ZERO_STRUCTP(status);
1199 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", lp_servicename(snum));
1201 key.dsize = strlen(keystr);
1202 data = tdb_fetch(tdb, key);
1204 if (data.dsize == sizeof(*status)) {
1205 memcpy(status, data.dptr, sizeof(*status));
1211 * Now, fetch the print queue information. We first count the number
1212 * of entries, and then only retrieve the queue if necessary.
1217 tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1222 /* Allocate the queue size. */
1223 if ((tstruct.queue = (print_queue_struct *)
1224 malloc(sizeof(print_queue_struct)*tsc.count))
1229 * Fill in the queue.
1230 * We need maxcount as the queue size may have changed between
1231 * the two calls to tdb_traverse.
1234 tstruct.maxcount = tsc.count;
1235 tstruct.snum = snum;
1237 tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1239 /* Sort the queue by submission time otherwise they are displayed
1242 qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1243 QSORT_CAST(printjob_comp));
1245 *queue = tstruct.queue;
1246 return tstruct.qcount;
1250 /****************************************************************************
1251 turn a queue name into a snum
1252 ****************************************************************************/
1253 int print_queue_snum(char *qname)
1255 int snum = lp_servicenumber(qname);
1256 if (snum == -1 || !lp_print_ok(snum)) return -1;
1261 /****************************************************************************
1263 ****************************************************************************/
1264 BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
1269 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1270 *errcode = WERR_ACCESS_DENIED;
1274 ret = (*(current_printif->queue_pause))(snum);
1277 *errcode = WERR_INVALID_PARAM;
1281 /* force update the database */
1282 print_cache_flush(snum);
1284 /* Send a printer notify message */
1286 printer_name = PRINTERNAME(snum);
1288 broadcast_printer_notify(printer_name);
1293 /****************************************************************************
1295 ****************************************************************************/
1296 BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
1301 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1302 *errcode = WERR_ACCESS_DENIED;
1306 ret = (*(current_printif->queue_resume))(snum);
1309 *errcode = WERR_INVALID_PARAM;
1313 /* make sure the database is up to date */
1314 if (print_cache_expired(snum)) print_queue_update(snum);
1316 /* Send a printer notify message */
1318 printer_name = PRINTERNAME(snum);
1320 broadcast_printer_notify(printer_name);
1325 /****************************************************************************
1326 purge a queue - implemented by deleting all jobs that we can delete
1327 ****************************************************************************/
1328 BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
1330 print_queue_struct *queue;
1331 print_status_struct status;
1336 /* Force and update so the count is accurate (i.e. not a cached count) */
1337 print_queue_update(snum);
1339 can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
1340 njobs = print_queue_status(snum, &queue, &status);
1342 for (i=0;i<njobs;i++) {
1343 BOOL owner = is_owner(user, queue[i].job);
1345 if (owner || can_job_admin) {
1346 print_job_delete1(queue[i].job);
1352 /* Send a printer notify message */
1354 printer_name = PRINTERNAME(snum);
1356 broadcast_printer_notify(printer_name);