Remove more pstring. Unify talloc_sub functions to make
[ira/wip.git] / source3 / printing / printing.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    printing backend routines
5    Copyright (C) Andrew Tridgell 1992-2000
6    Copyright (C) Jeremy Allison 2002
7    
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 3 of the License, or
11    (at your option) any later version.
12    
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.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "printing.h"
24
25 extern SIG_ATOMIC_T got_sig_term;
26 extern SIG_ATOMIC_T reload_after_sighup;
27 extern struct current_user current_user;
28 extern userdom_struct current_user_info;
29
30 /* Current printer interface */
31 static bool remove_from_jobs_changed(const char* sharename, uint32 jobid);
32
33 /* 
34    the printing backend revolves around a tdb database that stores the
35    SMB view of the print queue 
36    
37    The key for this database is a jobid - a internally generated number that
38    uniquely identifies a print job
39
40    reading the print queue involves two steps:
41      - possibly running lpq and updating the internal database from that
42      - reading entries from the database
43
44    jobids are assigned when a job starts spooling. 
45 */
46
47 static TDB_CONTEXT *rap_tdb;
48 static uint16 next_rap_jobid;
49 struct rap_jobid_key {
50         fstring sharename;
51         uint32  jobid;
52 };
53
54 /***************************************************************************
55  Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
56  bit RPC jobids.... JRA.
57 ***************************************************************************/
58
59 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
60 {
61         uint16 rap_jobid;
62         TDB_DATA data, key;
63         struct rap_jobid_key jinfo;
64         uint8 buf[2];
65
66         DEBUG(10,("pjobid_to_rap: called.\n"));
67
68         if (!rap_tdb) {
69                 /* Create the in-memory tdb. */
70                 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
71                 if (!rap_tdb)
72                         return 0;
73         }
74
75         ZERO_STRUCT( jinfo );
76         fstrcpy( jinfo.sharename, sharename );
77         jinfo.jobid = jobid;
78         key.dptr = (uint8 *)&jinfo;
79         key.dsize = sizeof(jinfo);
80
81         data = tdb_fetch(rap_tdb, key);
82         if (data.dptr && data.dsize == sizeof(uint16)) {
83                 rap_jobid = SVAL(data.dptr, 0);
84                 SAFE_FREE(data.dptr);
85                 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
86                         (unsigned int)jobid, (unsigned int)rap_jobid));
87                 return rap_jobid;
88         }
89         SAFE_FREE(data.dptr);
90         /* Not found - create and store mapping. */
91         rap_jobid = ++next_rap_jobid;
92         if (rap_jobid == 0)
93                 rap_jobid = ++next_rap_jobid;
94         SSVAL(buf,0,rap_jobid);
95         data.dptr = buf;
96         data.dsize = sizeof(rap_jobid);
97         tdb_store(rap_tdb, key, data, TDB_REPLACE);
98         tdb_store(rap_tdb, data, key, TDB_REPLACE);
99
100         DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
101                 (unsigned int)jobid, (unsigned int)rap_jobid));
102         return rap_jobid;
103 }
104
105 bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
106 {
107         TDB_DATA data, key;
108         uint8 buf[2];
109
110         DEBUG(10,("rap_to_pjobid called.\n"));
111
112         if (!rap_tdb)
113                 return False;
114
115         SSVAL(buf,0,rap_jobid);
116         key.dptr = buf;
117         key.dsize = sizeof(rap_jobid);
118         data = tdb_fetch(rap_tdb, key);
119         if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) ) 
120         {
121                 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
122                 fstrcpy( sharename, jinfo->sharename );
123                 *pjobid = jinfo->jobid;
124                 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
125                         (unsigned int)*pjobid, (unsigned int)rap_jobid));
126                 SAFE_FREE(data.dptr);
127                 return True;
128         }
129
130         DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
131                 (unsigned int)rap_jobid));
132         SAFE_FREE(data.dptr);
133         return False;
134 }
135
136 static void rap_jobid_delete(const char* sharename, uint32 jobid)
137 {
138         TDB_DATA key, data;
139         uint16 rap_jobid;
140         struct rap_jobid_key jinfo;
141         uint8 buf[2];
142
143         DEBUG(10,("rap_jobid_delete: called.\n"));
144
145         if (!rap_tdb)
146                 return;
147
148         ZERO_STRUCT( jinfo );
149         fstrcpy( jinfo.sharename, sharename );
150         jinfo.jobid = jobid;
151         key.dptr = (uint8 *)&jinfo;
152         key.dsize = sizeof(jinfo);
153
154         data = tdb_fetch(rap_tdb, key);
155         if (!data.dptr || (data.dsize != sizeof(uint16))) {
156                 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
157                         (unsigned int)jobid ));
158                 SAFE_FREE(data.dptr);
159                 return;
160         }
161
162         DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
163                 (unsigned int)jobid ));
164
165         rap_jobid = SVAL(data.dptr, 0);
166         SAFE_FREE(data.dptr);
167         SSVAL(buf,0,rap_jobid);
168         data.dptr = buf;
169         data.dsize = sizeof(rap_jobid);
170         tdb_delete(rap_tdb, key);
171         tdb_delete(rap_tdb, data);
172 }
173
174 static int get_queue_status(const char* sharename, print_status_struct *);
175
176 /****************************************************************************
177  Initialise the printing backend. Called once at startup before the fork().
178 ****************************************************************************/
179
180 bool print_backend_init(struct messaging_context *msg_ctx)
181 {
182         const char *sversion = "INFO/version";
183         int services = lp_numservices();
184         int snum;
185
186         unlink(lock_path("printing.tdb"));
187         mkdir(lock_path("printing"),0755);
188
189         /* handle a Samba upgrade */
190
191         for (snum = 0; snum < services; snum++) {
192                 struct tdb_print_db *pdb;
193                 if (!lp_print_ok(snum))
194                         continue;
195
196                 pdb = get_print_db_byname(lp_const_servicename(snum));
197                 if (!pdb)
198                         continue;
199                 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
200                         DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
201                         release_print_db(pdb);
202                         return False;
203                 }
204                 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
205                         tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
206                         tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
207                 }
208                 tdb_unlock_bystring(pdb->tdb, sversion);
209                 release_print_db(pdb);
210         }
211
212         close_all_print_db(); /* Don't leave any open. */
213
214         /* do NT print initialization... */
215         return nt_printing_init(msg_ctx);
216 }
217
218 /****************************************************************************
219  Shut down printing backend. Called once at shutdown to close the tdb.
220 ****************************************************************************/
221
222 void printing_end(void)
223 {
224         close_all_print_db(); /* Don't leave any open. */
225 }
226
227 /****************************************************************************
228  Retrieve the set of printing functions for a given service.  This allows 
229  us to set the printer function table based on the value of the 'printing'
230  service parameter.
231  
232  Use the generic interface as the default and only use cups interface only
233  when asked for (and only when supported)
234 ****************************************************************************/
235
236 static struct printif *get_printer_fns_from_type( enum printing_types type )
237 {
238         struct printif *printer_fns = &generic_printif;
239
240 #ifdef HAVE_CUPS
241         if ( type == PRINT_CUPS ) {
242                 printer_fns = &cups_printif;
243         }
244 #endif /* HAVE_CUPS */
245
246 #ifdef HAVE_IPRINT
247         if ( type == PRINT_IPRINT ) {
248                 printer_fns = &iprint_printif;
249         }
250 #endif /* HAVE_IPRINT */
251
252         printer_fns->type = type;
253         
254         return printer_fns;
255 }
256
257 static struct printif *get_printer_fns( int snum )
258 {
259         return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
260 }
261
262
263 /****************************************************************************
264  Useful function to generate a tdb key.
265 ****************************************************************************/
266
267 static TDB_DATA print_key(uint32 jobid)
268 {
269         static uint32 j;
270         TDB_DATA ret;
271
272         SIVAL(&j, 0, jobid);
273         ret.dptr = (uint8 *)&j;
274         ret.dsize = sizeof(j);
275         return ret;
276 }
277
278 /***********************************************************************
279  unpack a pjob from a tdb buffer 
280 ***********************************************************************/
281  
282 int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
283 {
284         int     len = 0;
285         int     used;
286         uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
287         uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
288
289         if ( !buf || !pjob )
290                 return -1;
291                 
292         len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
293                                 &pjpid,
294                                 &pjsysjob,
295                                 &pjfd,
296                                 &pjstarttime,
297                                 &pjstatus,
298                                 &pjsize,
299                                 &pjpage_count,
300                                 &pjspooled,
301                                 &pjsmbjob,
302                                 pjob->filename,
303                                 pjob->jobname,
304                                 pjob->user,
305                                 pjob->queuename);
306                                 
307         if ( len == -1 )
308                 return -1;
309                 
310         if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 )
311                 return -1;
312         
313         len += used;
314
315         pjob->pid = pjpid;
316         pjob->sysjob = pjsysjob;
317         pjob->fd = pjfd;
318         pjob->starttime = pjstarttime;
319         pjob->status = pjstatus;
320         pjob->size = pjsize;
321         pjob->page_count = pjpage_count;
322         pjob->spooled = pjspooled;
323         pjob->smbjob = pjsmbjob;
324         
325         return len;
326
327 }
328
329 /****************************************************************************
330  Useful function to find a print job in the database.
331 ****************************************************************************/
332
333 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
334 {
335         static struct printjob  pjob;
336         TDB_DATA                ret;
337         struct tdb_print_db     *pdb = get_print_db_byname(sharename);
338         
339         DEBUG(10,("print_job_find: looking up job %u for share %s\n",
340                         (unsigned int)jobid, sharename ));
341
342         if (!pdb) {
343                 return NULL;
344         }
345
346         ret = tdb_fetch(pdb->tdb, print_key(jobid));
347         release_print_db(pdb);
348
349         if (!ret.dptr) {
350                 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
351                 return NULL;
352         }
353         
354         if ( pjob.nt_devmode ) {
355                 free_nt_devicemode( &pjob.nt_devmode );
356         }
357                 
358         ZERO_STRUCT( pjob );
359         
360         if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
361                 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
362                 SAFE_FREE(ret.dptr);
363                 return NULL;
364         }
365         
366         SAFE_FREE(ret.dptr);
367
368         DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
369                         (int)pjob.sysjob, (unsigned int)jobid ));
370
371         return &pjob;
372 }
373
374 /* Convert a unix jobid to a smb jobid */
375
376 static uint32 sysjob_to_jobid_value;
377
378 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
379                                TDB_DATA data, void *state)
380 {
381         struct printjob *pjob;
382         int *sysjob = (int *)state;
383
384         if (!data.dptr || data.dsize == 0)
385                 return 0;
386
387         pjob = (struct printjob *)data.dptr;
388         if (key.dsize != sizeof(uint32))
389                 return 0;
390
391         if (*sysjob == pjob->sysjob) {
392                 uint32 jobid = IVAL(key.dptr,0);
393
394                 sysjob_to_jobid_value = jobid;
395                 return 1;
396         }
397
398         return 0;
399 }
400
401 /****************************************************************************
402  This is a *horribly expensive call as we have to iterate through all the
403  current printer tdb's. Don't do this often ! JRA.
404 ****************************************************************************/
405
406 uint32 sysjob_to_jobid(int unix_jobid)
407 {
408         int services = lp_numservices();
409         int snum;
410
411         sysjob_to_jobid_value = (uint32)-1;
412
413         for (snum = 0; snum < services; snum++) {
414                 struct tdb_print_db *pdb;
415                 if (!lp_print_ok(snum))
416                         continue;
417                 pdb = get_print_db_byname(lp_const_servicename(snum));
418                 if (!pdb) {
419                         continue;
420                 }
421                 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
422                 release_print_db(pdb);
423                 if (sysjob_to_jobid_value != (uint32)-1)
424                         return sysjob_to_jobid_value;
425         }
426         return (uint32)-1;
427 }
428
429 /****************************************************************************
430  Send notifications based on what has changed after a pjob_store.
431 ****************************************************************************/
432
433 static struct {
434         uint32 lpq_status;
435         uint32 spoolss_status;
436 } lpq_to_spoolss_status_map[] = {
437         { LPQ_QUEUED, JOB_STATUS_QUEUED },
438         { LPQ_PAUSED, JOB_STATUS_PAUSED },
439         { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
440         { LPQ_PRINTING, JOB_STATUS_PRINTING },
441         { LPQ_DELETING, JOB_STATUS_DELETING },
442         { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
443         { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
444         { LPQ_PRINTED, JOB_STATUS_PRINTED },
445         { LPQ_DELETED, JOB_STATUS_DELETED },
446         { LPQ_BLOCKED, JOB_STATUS_BLOCKED },
447         { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
448         { -1, 0 }
449 };
450
451 /* Convert a lpq status value stored in printing.tdb into the
452    appropriate win32 API constant. */
453
454 static uint32 map_to_spoolss_status(uint32 lpq_status)
455 {
456         int i = 0;
457
458         while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
459                 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
460                         return lpq_to_spoolss_status_map[i].spoolss_status;
461                 i++;
462         }
463
464         return 0;
465 }
466
467 static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
468                               struct printjob *new_data)
469 {
470         bool new_job = False;
471
472         if (!old_data)
473                 new_job = True;
474
475         /* Job attributes that can't be changed.  We only send
476            notification for these on a new job. */
477
478         /* ACHTUNG!  Due to a bug in Samba's spoolss parsing of the 
479            NOTIFY_INFO_DATA buffer, we *have* to send the job submission 
480            time first or else we'll end up with potential alignment 
481            errors.  I don't think the systemtime should be spooled as 
482            a string, but this gets us around that error.   
483            --jerry (i'll feel dirty for this) */
484  
485         if (new_job) {
486                 notify_job_submitted(sharename, jobid, new_data->starttime);
487                 notify_job_username(sharename, jobid, new_data->user);
488         }
489
490         if (new_job || !strequal(old_data->jobname, new_data->jobname))
491                 notify_job_name(sharename, jobid, new_data->jobname);
492
493         /* Job attributes of a new job or attributes that can be
494            modified. */
495
496         if (new_job || !strequal(old_data->jobname, new_data->jobname))
497                 notify_job_name(sharename, jobid, new_data->jobname);
498
499         if (new_job || old_data->status != new_data->status)
500                 notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));
501
502         if (new_job || old_data->size != new_data->size)
503                 notify_job_total_bytes(sharename, jobid, new_data->size);
504
505         if (new_job || old_data->page_count != new_data->page_count)
506                 notify_job_total_pages(sharename, jobid, new_data->page_count);
507 }
508
509 /****************************************************************************
510  Store a job structure back to the database.
511 ****************************************************************************/
512
513 static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
514 {
515         TDB_DATA                old_data, new_data;
516         bool                    ret = False;
517         struct tdb_print_db     *pdb = get_print_db_byname(sharename);
518         uint8                   *buf = NULL;
519         int                     len, newlen, buflen;
520         
521
522         if (!pdb)
523                 return False;
524
525         /* Get old data */
526
527         old_data = tdb_fetch(pdb->tdb, print_key(jobid));
528
529         /* Doh!  Now we have to pack/unpack data since the NT_DEVICEMODE was added */
530
531         newlen = 0;
532         
533         do {
534                 len = 0;
535                 buflen = newlen;
536                 len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
537                                 (uint32)pjob->pid,
538                                 (uint32)pjob->sysjob,
539                                 (uint32)pjob->fd,
540                                 (uint32)pjob->starttime,
541                                 (uint32)pjob->status,
542                                 (uint32)pjob->size,
543                                 (uint32)pjob->page_count,
544                                 (uint32)pjob->spooled,
545                                 (uint32)pjob->smbjob,
546                                 pjob->filename,
547                                 pjob->jobname,
548                                 pjob->user,
549                                 pjob->queuename);
550
551                 len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
552         
553                 if (buflen != len) {
554                         buf = (uint8 *)SMB_REALLOC(buf, len);
555                         if (!buf) {
556                                 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
557                                 goto done;
558                         }
559                         newlen = len;
560                 }
561         } while ( buflen != len );
562                 
563         
564         /* Store new data */
565
566         new_data.dptr = buf;
567         new_data.dsize = len;
568         ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
569
570         release_print_db(pdb);
571
572         /* Send notify updates for what has changed */
573
574         if ( ret ) {
575                 struct printjob old_pjob;
576
577                 if ( old_data.dsize )
578                 {
579                         if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
580                         {
581                                 pjob_store_notify( sharename, jobid, &old_pjob , pjob );
582                                 free_nt_devicemode( &old_pjob.nt_devmode );
583                         }
584                 }
585                 else {
586                         /* new job */
587                         pjob_store_notify( sharename, jobid, NULL, pjob );
588                 }
589         }
590
591 done:
592         SAFE_FREE( old_data.dptr );
593         SAFE_FREE( buf );
594
595         return ret;
596 }
597
598 /****************************************************************************
599  Remove a job structure from the database.
600 ****************************************************************************/
601
602 void pjob_delete(const char* sharename, uint32 jobid)
603 {
604         struct printjob *pjob;
605         uint32 job_status = 0;
606         struct tdb_print_db *pdb;
607
608         pdb = get_print_db_byname( sharename );
609
610         if (!pdb)
611                 return;
612
613         pjob = print_job_find( sharename, jobid );
614
615         if (!pjob) {
616                 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
617                                         (unsigned int)jobid));
618                 release_print_db(pdb);
619                 return;
620         }
621
622         /* We must cycle through JOB_STATUS_DELETING and
623            JOB_STATUS_DELETED for the port monitor to delete the job
624            properly. */
625         
626         job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
627         notify_job_status(sharename, jobid, job_status);
628         
629         /* Remove from printing.tdb */
630
631         tdb_delete(pdb->tdb, print_key(jobid));
632         remove_from_jobs_changed(sharename, jobid);
633         release_print_db( pdb );
634         rap_jobid_delete(sharename, jobid);
635 }
636
637 /****************************************************************************
638  Parse a file name from the system spooler to generate a jobid.
639 ****************************************************************************/
640
641 static uint32 print_parse_jobid(char *fname)
642 {
643         int jobid;
644
645         if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0)
646                 return (uint32)-1;
647         fname += strlen(PRINT_SPOOL_PREFIX);
648
649         jobid = atoi(fname);
650         if (jobid <= 0)
651                 return (uint32)-1;
652
653         return (uint32)jobid;
654 }
655
656 /****************************************************************************
657  List a unix job in the print database.
658 ****************************************************************************/
659
660 static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid)
661 {
662         struct printjob pj, *old_pj;
663
664         if (jobid == (uint32)-1) 
665                 jobid = q->job + UNIX_JOB_START;
666
667         /* Preserve the timestamp on an existing unix print job */
668
669         old_pj = print_job_find(sharename, jobid);
670
671         ZERO_STRUCT(pj);
672
673         pj.pid = (pid_t)-1;
674         pj.sysjob = q->job;
675         pj.fd = -1;
676         pj.starttime = old_pj ? old_pj->starttime : q->time;
677         pj.status = q->status;
678         pj.size = q->size;
679         pj.spooled = True;
680         fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
681         if (jobid < UNIX_JOB_START) {
682                 pj.smbjob = True;
683                 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
684         } else {
685                 pj.smbjob = False;
686                 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
687         }
688         fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
689         fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
690
691         pjob_store(sharename, jobid, &pj);
692 }
693
694
695 struct traverse_struct {
696         print_queue_struct *queue;
697         int qcount, snum, maxcount, total_jobs;
698         const char *sharename;
699         time_t lpq_time;
700         const char *lprm_command;
701         struct printif *print_if;
702 };
703
704 /****************************************************************************
705  Utility fn to delete any jobs that are no longer active.
706 ****************************************************************************/
707
708 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
709 {
710         struct traverse_struct *ts = (struct traverse_struct *)state;
711         struct printjob pjob;
712         uint32 jobid;
713         int i = 0;
714
715         if (  key.dsize != sizeof(jobid) )
716                 return 0;
717                 
718         jobid = IVAL(key.dptr, 0);
719         if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
720                 return 0;
721         free_nt_devicemode( &pjob.nt_devmode );
722
723
724         if (!pjob.smbjob) {
725                 /* remove a unix job if it isn't in the system queue any more */
726
727                 for (i=0;i<ts->qcount;i++) {
728                         uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
729                         if (jobid == u_jobid)
730                                 break;
731                 }
732                 if (i == ts->qcount) {
733                         DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
734                                                 (unsigned int)jobid ));
735                         pjob_delete(ts->sharename, jobid);
736                         return 0;
737                 } 
738
739                 /* need to continue the the bottom of the function to
740                    save the correct attributes */
741         }
742
743         /* maybe it hasn't been spooled yet */
744         if (!pjob.spooled) {
745                 /* if a job is not spooled and the process doesn't
746                    exist then kill it. This cleans up after smbd
747                    deaths */
748                 if (!process_exists_by_pid(pjob.pid)) {
749                         DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
750                                                 (unsigned int)jobid, (unsigned int)pjob.pid ));
751                         pjob_delete(ts->sharename, jobid);
752                 } else
753                         ts->total_jobs++;
754                 return 0;
755         }
756
757         /* this check only makes sense for jobs submitted from Windows clients */
758         
759         if ( pjob.smbjob ) {
760                 for (i=0;i<ts->qcount;i++) {
761                         uint32 curr_jobid;
762
763                         if ( pjob.status == LPQ_DELETED )
764                                 continue;
765
766                         curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
767
768                         if (jobid == curr_jobid) {
769
770                                 /* try to clean up any jobs that need to be deleted */
771
772                                 if ( pjob.status == LPQ_DELETING ) {
773                                         int result;
774
775                                         result = (*(ts->print_if->job_delete))( 
776                                                 ts->sharename, ts->lprm_command, &pjob );
777
778                                         if ( result != 0 ) {
779                                                 /* if we can't delete, then reset the job status */
780                                                 pjob.status = LPQ_QUEUED;
781                                                 pjob_store(ts->sharename, jobid, &pjob);
782                                         }
783                                         else {
784                                                 /* if we deleted the job, the remove the tdb record */
785                                                 pjob_delete(ts->sharename, jobid);
786                                                 pjob.status = LPQ_DELETED;
787                                         }
788                                                 
789                                 }
790
791                                 break;
792                         }
793                 }
794         }
795         
796         /* The job isn't in the system queue - we have to assume it has
797            completed, so delete the database entry. */
798
799         if (i == ts->qcount) {
800
801                 /* A race can occur between the time a job is spooled and
802                    when it appears in the lpq output.  This happens when
803                    the job is added to printing.tdb when another smbd
804                    running print_queue_update() has completed a lpq and
805                    is currently traversing the printing tdb and deleting jobs.
806                    Don't delete the job if it was submitted after the lpq_time. */
807
808                 if (pjob.starttime < ts->lpq_time) {
809                         DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
810                                                 (unsigned int)jobid,
811                                                 (unsigned int)pjob.starttime,
812                                                 (unsigned int)ts->lpq_time ));
813                         pjob_delete(ts->sharename, jobid);
814                 } else
815                         ts->total_jobs++;
816                 return 0;
817         }
818
819         /* Save the pjob attributes we will store. 
820            FIXME!!! This is the only place where queue->job 
821            represents the SMB jobid      --jerry */
822
823         ts->queue[i].job = jobid;               
824         ts->queue[i].size = pjob.size;
825         ts->queue[i].page_count = pjob.page_count;
826         ts->queue[i].status = pjob.status;
827         ts->queue[i].priority = 1;
828         ts->queue[i].time = pjob.starttime;
829         fstrcpy(ts->queue[i].fs_user, pjob.user);
830         fstrcpy(ts->queue[i].fs_file, pjob.jobname);
831
832         ts->total_jobs++;
833
834         return 0;
835 }
836
837 /****************************************************************************
838  Check if the print queue has been updated recently enough.
839 ****************************************************************************/
840
841 static void print_cache_flush(const char *sharename)
842 {
843         fstring key;
844         struct tdb_print_db *pdb = get_print_db_byname(sharename);
845
846         if (!pdb)
847                 return;
848         slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
849         tdb_store_int32(pdb->tdb, key, -1);
850         release_print_db(pdb);
851 }
852
853 /****************************************************************************
854  Check if someone already thinks they are doing the update.
855 ****************************************************************************/
856
857 static pid_t get_updating_pid(const char *sharename)
858 {
859         fstring keystr;
860         TDB_DATA data, key;
861         pid_t updating_pid;
862         struct tdb_print_db *pdb = get_print_db_byname(sharename);
863
864         if (!pdb)
865                 return (pid_t)-1;
866         slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
867         key = string_tdb_data(keystr);
868
869         data = tdb_fetch(pdb->tdb, key);
870         release_print_db(pdb);
871         if (!data.dptr || data.dsize != sizeof(pid_t)) {
872                 SAFE_FREE(data.dptr);
873                 return (pid_t)-1;
874         }
875
876         updating_pid = IVAL(data.dptr, 0);
877         SAFE_FREE(data.dptr);
878
879         if (process_exists_by_pid(updating_pid))
880                 return updating_pid;
881
882         return (pid_t)-1;
883 }
884
885 /****************************************************************************
886  Set the fact that we're doing the update, or have finished doing the update
887  in the tdb.
888 ****************************************************************************/
889
890 static void set_updating_pid(const fstring sharename, bool updating)
891 {
892         fstring keystr;
893         TDB_DATA key;
894         TDB_DATA data;
895         pid_t updating_pid = sys_getpid();
896         uint8 buffer[4];
897         
898         struct tdb_print_db *pdb = get_print_db_byname(sharename);
899
900         if (!pdb)
901                 return;
902
903         slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
904         key = string_tdb_data(keystr);
905         
906         DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n", 
907                 updating ? "" : "not ",
908                 sharename ));
909
910         if ( !updating ) {
911                 tdb_delete(pdb->tdb, key);
912                 release_print_db(pdb);
913                 return;
914         }
915         
916         SIVAL( buffer, 0, updating_pid);
917         data.dptr = buffer;
918         data.dsize = 4;         /* we always assume this is a 4 byte value */
919
920         tdb_store(pdb->tdb, key, data, TDB_REPLACE);    
921         release_print_db(pdb);
922 }
923
924 /****************************************************************************
925  Sort print jobs by submittal time.
926 ****************************************************************************/
927
928 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
929 {
930         /* Silly cases */
931
932         if (!j1 && !j2)
933                 return 0;
934         if (!j1)
935                 return -1;
936         if (!j2)
937                 return 1;
938
939         /* Sort on job start time */
940
941         if (j1->time == j2->time)
942                 return 0;
943         return (j1->time > j2->time) ? 1 : -1;
944 }
945
946 /****************************************************************************
947  Store the sorted queue representation for later portmon retrieval.
948  Skip deleted jobs
949 ****************************************************************************/
950
951 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
952 {
953         TDB_DATA data;
954         int max_reported_jobs = lp_max_reported_jobs(pts->snum);
955         print_queue_struct *queue = pts->queue;
956         size_t len;
957         size_t i;
958         unsigned int qcount;
959
960         if (max_reported_jobs && (max_reported_jobs < pts->qcount))
961                 pts->qcount = max_reported_jobs;
962         qcount = 0;
963
964         /* Work out the size. */
965         data.dsize = 0;
966         data.dsize += tdb_pack(NULL, 0, "d", qcount);
967
968         for (i = 0; i < pts->qcount; i++) {
969                 if ( queue[i].status == LPQ_DELETED )
970                         continue;
971
972                 qcount++;
973                 data.dsize += tdb_pack(NULL, 0, "ddddddff",
974                                 (uint32)queue[i].job,
975                                 (uint32)queue[i].size,
976                                 (uint32)queue[i].page_count,
977                                 (uint32)queue[i].status,
978                                 (uint32)queue[i].priority,
979                                 (uint32)queue[i].time,
980                                 queue[i].fs_user,
981                                 queue[i].fs_file);
982         }
983
984         if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
985                 return;
986
987         len = 0;
988         len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
989         for (i = 0; i < pts->qcount; i++) {
990                 if ( queue[i].status == LPQ_DELETED )
991                         continue;
992
993                 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
994                                 (uint32)queue[i].job,
995                                 (uint32)queue[i].size,
996                                 (uint32)queue[i].page_count,
997                                 (uint32)queue[i].status,
998                                 (uint32)queue[i].priority,
999                                 (uint32)queue[i].time,
1000                                 queue[i].fs_user,
1001                                 queue[i].fs_file);
1002         }
1003
1004         tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1005                   TDB_REPLACE);
1006         SAFE_FREE(data.dptr);
1007         return;
1008 }
1009
1010 static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
1011 {
1012         TDB_DATA data;
1013
1014         ZERO_STRUCT(data);
1015
1016         data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
1017         if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1018                 SAFE_FREE(data.dptr);
1019                 ZERO_STRUCT(data);
1020         }
1021
1022         return data;
1023 }
1024
1025 static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
1026 {
1027         unsigned int i;
1028         unsigned int job_count = data.dsize / 4;
1029
1030         for (i = 0; i < job_count; i++) {
1031                 uint32 ch_jobid;
1032
1033                 ch_jobid = IVAL(data.dptr, i*4);
1034                 if (ch_jobid == jobid)
1035                         remove_from_jobs_changed(sharename, jobid);
1036         }
1037 }
1038
1039 /****************************************************************************
1040  Check if the print queue has been updated recently enough.
1041 ****************************************************************************/
1042
1043 static bool print_cache_expired(const char *sharename, bool check_pending)
1044 {
1045         fstring key;
1046         time_t last_qscan_time, time_now = time(NULL);
1047         struct tdb_print_db *pdb = get_print_db_byname(sharename);
1048         bool result = False;
1049
1050         if (!pdb)
1051                 return False;
1052
1053         snprintf(key, sizeof(key), "CACHE/%s", sharename);
1054         last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1055
1056         /*
1057          * Invalidate the queue for 3 reasons.
1058          * (1). last queue scan time == -1.
1059          * (2). Current time - last queue scan time > allowed cache time.
1060          * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1061          * This last test picks up machines for which the clock has been moved
1062          * forward, an lpq scan done and then the clock moved back. Otherwise
1063          * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1064          */
1065
1066         if (last_qscan_time == ((time_t)-1) 
1067                 || (time_now - last_qscan_time) >= lp_lpqcachetime() 
1068                 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) 
1069         {
1070                 uint32 u;
1071                 time_t msg_pending_time;
1072
1073                 DEBUG(4, ("print_cache_expired: cache expired for queue %s " 
1074                         "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", 
1075                         sharename, (int)last_qscan_time, (int)time_now, 
1076                         (int)lp_lpqcachetime() ));
1077
1078                 /* check if another smbd has already sent a message to update the 
1079                    queue.  Give the pending message one minute to clear and 
1080                    then send another message anyways.  Make sure to check for 
1081                    clocks that have been run forward and then back again. */
1082
1083                 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1084
1085                 if ( check_pending 
1086                         && tdb_fetch_uint32( pdb->tdb, key, &u ) 
1087                         && (msg_pending_time=u) > 0
1088                         && msg_pending_time <= time_now 
1089                         && (time_now - msg_pending_time) < 60 ) 
1090                 {
1091                         DEBUG(4,("print_cache_expired: message already pending for %s.  Accepting cache\n",
1092                                 sharename));
1093                         goto done;
1094                 }
1095                 
1096                 result = True;
1097         }
1098
1099 done:
1100         release_print_db(pdb);
1101         return result;
1102 }
1103
1104 /****************************************************************************
1105  main work for updating the lpq cahe for a printer queue
1106 ****************************************************************************/
1107
1108 static void print_queue_update_internal( const char *sharename, 
1109                                          struct printif *current_printif,
1110                                          char *lpq_command, char *lprm_command )
1111 {
1112         int i, qcount;
1113         print_queue_struct *queue = NULL;
1114         print_status_struct status;
1115         print_status_struct old_status;
1116         struct printjob *pjob;
1117         struct traverse_struct tstruct;
1118         TDB_DATA data, key;
1119         TDB_DATA jcdata;
1120         fstring keystr, cachestr;
1121         struct tdb_print_db *pdb = get_print_db_byname(sharename);
1122
1123         if (!pdb) {
1124                 return;
1125         }
1126         
1127         DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1128                 sharename, current_printif->type, lpq_command));
1129
1130         /*
1131          * Update the cache time FIRST ! Stops others even
1132          * attempting to get the lock and doing this
1133          * if the lpq takes a long time.
1134          */
1135          
1136         slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1137         tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1138
1139         /* get the current queue using the appropriate interface */
1140         ZERO_STRUCT(status);
1141
1142         qcount = (*(current_printif->queue_get))(sharename, 
1143                 current_printif->type, 
1144                 lpq_command, &queue, &status);
1145
1146         DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n", 
1147                 qcount, (qcount != 1) ? "s" : "", sharename));
1148
1149         /* Sort the queue by submission time otherwise they are displayed
1150            in hash order. */
1151
1152         qsort(queue, qcount, sizeof(print_queue_struct),
1153                 QSORT_CAST(printjob_comp));
1154
1155         /*
1156           any job in the internal database that is marked as spooled
1157           and doesn't exist in the system queue is considered finished
1158           and removed from the database
1159
1160           any job in the system database but not in the internal database 
1161           is added as a unix job
1162
1163           fill in any system job numbers as we go
1164         */
1165
1166         jcdata = get_jobs_changed_data(pdb);
1167
1168         for (i=0; i<qcount; i++) {
1169                 uint32 jobid = print_parse_jobid(queue[i].fs_file);
1170
1171                 if (jobid == (uint32)-1) {
1172                         /* assume its a unix print job */
1173                         print_unix_job(sharename, &queue[i], jobid);
1174                         continue;
1175                 }
1176
1177                 /* we have an active SMB print job - update its status */
1178                 pjob = print_job_find(sharename, jobid);
1179                 if (!pjob) {
1180                         /* err, somethings wrong. Probably smbd was restarted
1181                            with jobs in the queue. All we can do is treat them
1182                            like unix jobs. Pity. */
1183                         print_unix_job(sharename, &queue[i], jobid);
1184                         continue;
1185                 }
1186
1187                 pjob->sysjob = queue[i].job;
1188
1189                 /* don't reset the status on jobs to be deleted */
1190
1191                 if ( pjob->status != LPQ_DELETING )
1192                         pjob->status = queue[i].status;
1193
1194                 pjob_store(sharename, jobid, pjob);
1195
1196                 check_job_changed(sharename, jcdata, jobid);
1197         }
1198
1199         SAFE_FREE(jcdata.dptr);
1200
1201         /* now delete any queued entries that don't appear in the
1202            system queue */
1203         tstruct.queue = queue;
1204         tstruct.qcount = qcount;
1205         tstruct.snum = -1;
1206         tstruct.total_jobs = 0;
1207         tstruct.lpq_time = time(NULL);
1208         tstruct.sharename = sharename;
1209         tstruct.lprm_command = lprm_command;
1210         tstruct.print_if = current_printif;
1211
1212         tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1213
1214         /* Store the linearised queue, max jobs only. */
1215         store_queue_struct(pdb, &tstruct);
1216
1217         SAFE_FREE(tstruct.queue);
1218
1219         DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1220                                 sharename, tstruct.total_jobs ));
1221
1222         tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1223
1224         get_queue_status(sharename, &old_status);
1225         if (old_status.qcount != qcount)
1226                 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1227                                         old_status.qcount, qcount, sharename));
1228
1229         /* store the new queue status structure */
1230         slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1231         key = string_tdb_data(keystr);
1232
1233         status.qcount = qcount;
1234         data.dptr = (uint8 *)&status;
1235         data.dsize = sizeof(status);
1236         tdb_store(pdb->tdb, key, data, TDB_REPLACE);    
1237
1238         /*
1239          * Update the cache time again. We want to do this call
1240          * as little as possible...
1241          */
1242
1243         slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1244         tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1245
1246         /* clear the msg pending record for this queue */
1247
1248         snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1249
1250         if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1251                 /* log a message but continue on */
1252
1253                 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1254                         sharename));
1255         }
1256
1257         release_print_db( pdb );
1258
1259         return;
1260 }
1261
1262 /****************************************************************************
1263  Update the internal database from the system print queue for a queue.
1264  obtain a lock on the print queue before proceeding (needed when mutiple
1265  smbd processes maytry to update the lpq cache concurrently).
1266 ****************************************************************************/
1267
1268 static void print_queue_update_with_lock( const char *sharename, 
1269                                           struct printif *current_printif,
1270                                           char *lpq_command, char *lprm_command )
1271 {
1272         fstring keystr;
1273         struct tdb_print_db *pdb;
1274
1275         DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1276         pdb = get_print_db_byname(sharename);
1277         if (!pdb)
1278                 return;
1279
1280         if ( !print_cache_expired(sharename, False) ) {
1281                 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1282                 release_print_db(pdb);
1283                 return;
1284         }
1285         
1286         /*
1287          * Check to see if someone else is doing this update.
1288          * This is essentially a mutex on the update.
1289          */
1290
1291         if (get_updating_pid(sharename) != -1) {
1292                 release_print_db(pdb);
1293                 return;
1294         }
1295
1296         /* Lock the queue for the database update */
1297
1298         slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1299         /* Only wait 10 seconds for this. */
1300         if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1301                 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1302                 release_print_db(pdb);
1303                 return;
1304         }
1305
1306         /*
1307          * Ensure that no one else got in here.
1308          * If the updating pid is still -1 then we are
1309          * the winner.
1310          */
1311
1312         if (get_updating_pid(sharename) != -1) {
1313                 /*
1314                  * Someone else is doing the update, exit.
1315                  */
1316                 tdb_unlock_bystring(pdb->tdb, keystr);
1317                 release_print_db(pdb);
1318                 return;
1319         }
1320
1321         /*
1322          * We're going to do the update ourselves.
1323          */
1324
1325         /* Tell others we're doing the update. */
1326         set_updating_pid(sharename, True);
1327
1328         /*
1329          * Allow others to enter and notice we're doing
1330          * the update.
1331          */
1332
1333         tdb_unlock_bystring(pdb->tdb, keystr);
1334
1335         /* do the main work now */
1336         
1337         print_queue_update_internal( sharename, current_printif, 
1338                 lpq_command, lprm_command );
1339         
1340         /* Delete our pid from the db. */
1341         set_updating_pid(sharename, False);
1342         release_print_db(pdb);
1343 }
1344
1345 /****************************************************************************
1346 this is the receive function of the background lpq updater
1347 ****************************************************************************/
1348 static void print_queue_receive(struct messaging_context *msg,
1349                                 void *private_data,
1350                                 uint32_t msg_type,
1351                                 struct server_id server_id,
1352                                 DATA_BLOB *data)
1353 {
1354         fstring sharename;
1355         pstring lpqcommand, lprmcommand;
1356         int printing_type;
1357         size_t len;
1358
1359         len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1360                 sharename,
1361                 &printing_type,
1362                 lpqcommand,
1363                 lprmcommand );
1364
1365         if ( len == -1 ) {
1366                 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1367                 return;
1368         }
1369
1370         print_queue_update_with_lock(sharename, 
1371                 get_printer_fns_from_type((enum printing_types)printing_type),
1372                 lpqcommand, lprmcommand );
1373
1374         return;
1375 }
1376
1377 static pid_t background_lpq_updater_pid = -1;
1378
1379 /****************************************************************************
1380 main thread of the background lpq updater
1381 ****************************************************************************/
1382 void start_background_queue(void)
1383 {
1384         DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1385         background_lpq_updater_pid = sys_fork();
1386
1387         if (background_lpq_updater_pid == -1) {
1388                 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1389                 exit(1);
1390         }
1391
1392         if(background_lpq_updater_pid == 0) {
1393                 /* Child. */
1394                 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1395
1396                 claim_connection( NULL, "smbd lpq backend",
1397                         FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
1398
1399                 if (!locking_init(0)) {
1400                         exit(1);
1401                 }
1402
1403                 messaging_register(smbd_messaging_context(), NULL,
1404                                    MSG_PRINTER_UPDATE, print_queue_receive);
1405                 
1406                 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1407                 while (1) {
1408                         pause();
1409                         
1410                         /* check for some essential signals first */
1411                         
1412                         if (got_sig_term) {
1413                                 exit_server_cleanly(NULL);
1414                         }
1415
1416                         if (reload_after_sighup) {
1417                                 change_to_root_user();
1418                                 DEBUG(1,("Reloading services after SIGHUP\n"));
1419                                 reload_services(False);
1420                                 reload_after_sighup = 0;
1421                         }
1422                         
1423                         /* now check for messages */
1424                         
1425                         DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
1426                         message_dispatch(smbd_messaging_context());
1427
1428                         /* process any pending print change notify messages */
1429
1430                         print_notify_send_messages(smbd_messaging_context(),
1431                                                    0);
1432                 }
1433         }
1434 }
1435
1436 /****************************************************************************
1437 update the internal database from the system print queue for a queue
1438 ****************************************************************************/
1439
1440 static void print_queue_update(int snum, bool force)
1441 {
1442         fstring key;
1443         fstring sharename;
1444         char *lpqcommand = NULL;
1445         char *lprmcommand = NULL;
1446         uint8 *buffer = NULL;
1447         size_t len = 0;
1448         size_t newlen;
1449         struct tdb_print_db *pdb;
1450         int type;
1451         struct printif *current_printif;
1452         TALLOC_CTX *ctx = talloc_tos();
1453
1454         fstrcpy( sharename, lp_const_servicename(snum));
1455
1456         /* don't strip out characters like '$' from the printername */
1457
1458         lpqcommand = talloc_string_sub2(ctx,
1459                         lp_lpqcommand(snum),
1460                         "%p",
1461                         PRINTERNAME(snum),
1462                         false, false, false);
1463         if (!lpqcommand) {
1464                 return;
1465         }
1466         lpqcommand = talloc_sub_advanced(ctx,
1467                         lp_servicename(snum),
1468                         current_user_info.unix_name,
1469                         "",
1470                         current_user.ut.gid,
1471                         get_current_username(),
1472                         current_user_info.domain,
1473                         lpqcommand);
1474         if (!lpqcommand) {
1475                 return;
1476         }
1477
1478         pstrcpy( lprmcommand, lp_lprmcommand(snum));
1479         lprmcommand = talloc_string_sub2(ctx,
1480                         lp_lprmcommand(snum),
1481                         "%p",
1482                         PRINTERNAME(snum),
1483                         false, false, false);
1484         if (!lprmcommand) {
1485                 return;
1486         }
1487         lprmcommand = talloc_sub_advanced(ctx,
1488                         lp_servicename(snum),
1489                         current_user_info.unix_name,
1490                         "",
1491                         current_user.ut.gid,
1492                         get_current_username(),
1493                         current_user_info.domain,
1494                         lprmcommand);
1495         if (!lprmcommand) {
1496                 return;
1497         }
1498
1499         /*
1500          * Make sure that the background queue process exists.
1501          * Otherwise just do the update ourselves
1502          */
1503
1504         if ( force || background_lpq_updater_pid == -1 ) {
1505                 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1506                 current_printif = get_printer_fns( snum );
1507                 print_queue_update_with_lock( sharename, current_printif, lpqcommand, lprmcommand );
1508
1509                 return;
1510         }
1511
1512         type = lp_printing(snum);
1513
1514         /* get the length */
1515
1516         len = tdb_pack( NULL, 0, "fdPP",
1517                 sharename,
1518                 type,
1519                 lpqcommand,
1520                 lprmcommand );
1521
1522         buffer = SMB_XMALLOC_ARRAY( uint8, len );
1523
1524         /* now pack the buffer */
1525         newlen = tdb_pack( buffer, len, "fdPP",
1526                 sharename,
1527                 type,
1528                 lpqcommand,
1529                 lprmcommand );
1530
1531         SMB_ASSERT( newlen == len );
1532
1533         DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1534                 "type = %d, lpq command = [%s] lprm command = [%s]\n", 
1535                 sharename, type, lpqcommand, lprmcommand ));
1536
1537         /* here we set a msg pending record for other smbd processes 
1538            to throttle the number of duplicate print_queue_update msgs
1539            sent.  */
1540
1541         pdb = get_print_db_byname(sharename);
1542         if (!pdb) {
1543                 SAFE_FREE(buffer);
1544                 return;
1545         }
1546
1547         snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1548
1549         if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1550                 /* log a message but continue on */
1551
1552                 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1553                         sharename));
1554         }
1555
1556         release_print_db( pdb );
1557
1558         /* finally send the message */
1559         
1560         messaging_send_buf(smbd_messaging_context(),
1561                            pid_to_procid(background_lpq_updater_pid),
1562                            MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1563
1564         SAFE_FREE( buffer );
1565
1566         return;
1567 }
1568
1569 /****************************************************************************
1570  Create/Update an entry in the print tdb that will allow us to send notify
1571  updates only to interested smbd's. 
1572 ****************************************************************************/
1573
1574 bool print_notify_register_pid(int snum)
1575 {
1576         TDB_DATA data;
1577         struct tdb_print_db *pdb = NULL;
1578         TDB_CONTEXT *tdb = NULL;
1579         const char *printername;
1580         uint32 mypid = (uint32)sys_getpid();
1581         bool ret = False;
1582         size_t i;
1583
1584         /* if (snum == -1), then the change notify request was
1585            on a print server handle and we need to register on
1586            all print queus */
1587            
1588         if (snum == -1) 
1589         {
1590                 int num_services = lp_numservices();
1591                 int idx;
1592                 
1593                 for ( idx=0; idx<num_services; idx++ ) {
1594                         if (lp_snum_ok(idx) && lp_print_ok(idx) )
1595                                 print_notify_register_pid(idx);
1596                 }
1597                 
1598                 return True;
1599         }
1600         else /* register for a specific printer */
1601         {
1602                 printername = lp_const_servicename(snum);
1603                 pdb = get_print_db_byname(printername);
1604                 if (!pdb)
1605                         return False;
1606                 tdb = pdb->tdb;
1607         }
1608
1609         if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1610                 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
1611                                         printername));
1612                 if (pdb)
1613                         release_print_db(pdb);
1614                 return False;
1615         }
1616
1617         data = get_printer_notify_pid_list( tdb, printername, True );
1618
1619         /* Add ourselves and increase the refcount. */
1620
1621         for (i = 0; i < data.dsize; i += 8) {
1622                 if (IVAL(data.dptr,i) == mypid) {
1623                         uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
1624                         SIVAL(data.dptr, i+4, new_refcount);
1625                         break;
1626                 }
1627         }
1628
1629         if (i == data.dsize) {
1630                 /* We weren't in the list. Realloc. */
1631                 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
1632                 if (!data.dptr) {
1633                         DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
1634                                                 printername));
1635                         goto done;
1636                 }
1637                 data.dsize += 8;
1638                 SIVAL(data.dptr,data.dsize - 8,mypid);
1639                 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
1640         }
1641
1642         /* Store back the record. */
1643         if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1644                 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1645 list for printer %s\n", printername));
1646                 goto done;
1647         }
1648
1649         ret = True;
1650
1651  done:
1652
1653         tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1654         if (pdb)
1655                 release_print_db(pdb);
1656         SAFE_FREE(data.dptr);
1657         return ret;
1658 }
1659
1660 /****************************************************************************
1661  Update an entry in the print tdb that will allow us to send notify
1662  updates only to interested smbd's. 
1663 ****************************************************************************/
1664
1665 bool print_notify_deregister_pid(int snum)
1666 {
1667         TDB_DATA data;
1668         struct tdb_print_db *pdb = NULL;
1669         TDB_CONTEXT *tdb = NULL;
1670         const char *printername;
1671         uint32 mypid = (uint32)sys_getpid();
1672         size_t i;
1673         bool ret = False;
1674
1675         /* if ( snum == -1 ), we are deregister a print server handle
1676            which means to deregister on all print queues */
1677            
1678         if (snum == -1) 
1679         {
1680                 int num_services = lp_numservices();
1681                 int idx;
1682                 
1683                 for ( idx=0; idx<num_services; idx++ ) {
1684                         if ( lp_snum_ok(idx) && lp_print_ok(idx) )
1685                                 print_notify_deregister_pid(idx);
1686                 }
1687                 
1688                 return True;
1689         }
1690         else /* deregister a specific printer */
1691         {
1692                 printername = lp_const_servicename(snum);
1693                 pdb = get_print_db_byname(printername);
1694                 if (!pdb)
1695                         return False;
1696                 tdb = pdb->tdb;
1697         }
1698
1699         if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
1700                 DEBUG(0,("print_notify_register_pid: Failed to lock \
1701 printer %s database\n", printername));
1702                 if (pdb)
1703                         release_print_db(pdb);
1704                 return False;
1705         }
1706
1707         data = get_printer_notify_pid_list( tdb, printername, True );
1708
1709         /* Reduce refcount. Remove ourselves if zero. */
1710
1711         for (i = 0; i < data.dsize; ) {
1712                 if (IVAL(data.dptr,i) == mypid) {
1713                         uint32 refcount = IVAL(data.dptr, i+4);
1714
1715                         refcount--;
1716
1717                         if (refcount == 0) {
1718                                 if (data.dsize - i > 8)
1719                                         memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
1720                                 data.dsize -= 8;
1721                                 continue;
1722                         }
1723                         SIVAL(data.dptr, i+4, refcount);
1724                 }
1725
1726                 i += 8;
1727         }
1728
1729         if (data.dsize == 0)
1730                 SAFE_FREE(data.dptr);
1731
1732         /* Store back the record. */
1733         if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
1734                 DEBUG(0,("print_notify_register_pid: Failed to update pid \
1735 list for printer %s\n", printername));
1736                 goto done;
1737         }
1738
1739         ret = True;
1740
1741   done:
1742
1743         tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
1744         if (pdb)
1745                 release_print_db(pdb);
1746         SAFE_FREE(data.dptr);
1747         return ret;
1748 }
1749
1750 /****************************************************************************
1751  Check if a jobid is valid. It is valid if it exists in the database.
1752 ****************************************************************************/
1753
1754 bool print_job_exists(const char* sharename, uint32 jobid)
1755 {
1756         struct tdb_print_db *pdb = get_print_db_byname(sharename);
1757         bool ret;
1758
1759         if (!pdb)
1760                 return False;
1761         ret = tdb_exists(pdb->tdb, print_key(jobid));
1762         release_print_db(pdb);
1763         return ret;
1764 }
1765
1766 /****************************************************************************
1767  Give the fd used for a jobid.
1768 ****************************************************************************/
1769
1770 int print_job_fd(const char* sharename, uint32 jobid)
1771 {
1772         struct printjob *pjob = print_job_find(sharename, jobid);
1773         if (!pjob)
1774                 return -1;
1775         /* don't allow another process to get this info - it is meaningless */
1776         if (pjob->pid != sys_getpid())
1777                 return -1;
1778         return pjob->fd;
1779 }
1780
1781 /****************************************************************************
1782  Give the filename used for a jobid.
1783  Only valid for the process doing the spooling and when the job
1784  has not been spooled.
1785 ****************************************************************************/
1786
1787 char *print_job_fname(const char* sharename, uint32 jobid)
1788 {
1789         struct printjob *pjob = print_job_find(sharename, jobid);
1790         if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
1791                 return NULL;
1792         return pjob->filename;
1793 }
1794
1795
1796 /****************************************************************************
1797  Give the filename used for a jobid.
1798  Only valid for the process doing the spooling and when the job
1799  has not been spooled.
1800 ****************************************************************************/
1801
1802 NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
1803 {
1804         struct printjob *pjob = print_job_find(sharename, jobid);
1805         
1806         if ( !pjob )
1807                 return NULL;
1808                 
1809         return pjob->nt_devmode;
1810 }
1811
1812 /****************************************************************************
1813  Set the place in the queue for a job.
1814 ****************************************************************************/
1815
1816 bool print_job_set_place(const char *sharename, uint32 jobid, int place)
1817 {
1818         DEBUG(2,("print_job_set_place not implemented yet\n"));
1819         return False;
1820 }
1821
1822 /****************************************************************************
1823  Set the name of a job. Only possible for owner.
1824 ****************************************************************************/
1825
1826 bool print_job_set_name(const char *sharename, uint32 jobid, char *name)
1827 {
1828         struct printjob *pjob;
1829
1830         pjob = print_job_find(sharename, jobid);
1831         if (!pjob || pjob->pid != sys_getpid())
1832                 return False;
1833
1834         fstrcpy(pjob->jobname, name);
1835         return pjob_store(sharename, jobid, pjob);
1836 }
1837
1838 /***************************************************************************
1839  Remove a jobid from the 'jobs changed' list.
1840 ***************************************************************************/
1841
1842 static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
1843 {
1844         struct tdb_print_db *pdb = get_print_db_byname(sharename);
1845         TDB_DATA data, key;
1846         size_t job_count, i;
1847         bool ret = False;
1848         bool gotlock = False;
1849
1850         if (!pdb) {
1851                 return False;
1852         }
1853
1854         ZERO_STRUCT(data);
1855
1856         key = string_tdb_data("INFO/jobs_changed");
1857
1858         if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
1859                 goto out;
1860
1861         gotlock = True;
1862
1863         data = tdb_fetch(pdb->tdb, key);
1864
1865         if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
1866                 goto out;
1867
1868         job_count = data.dsize / 4;
1869         for (i = 0; i < job_count; i++) {
1870                 uint32 ch_jobid;
1871
1872                 ch_jobid = IVAL(data.dptr, i*4);
1873                 if (ch_jobid == jobid) {
1874                         if (i < job_count -1 )
1875                                 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
1876                         data.dsize -= 4;
1877                         if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
1878                                 goto out;
1879                         break;
1880                 }
1881         }
1882
1883         ret = True;
1884   out:
1885
1886         if (gotlock)
1887                 tdb_chainunlock(pdb->tdb, key);
1888         SAFE_FREE(data.dptr);
1889         release_print_db(pdb);
1890         if (ret)
1891                 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
1892         else
1893                 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
1894         return ret;
1895 }
1896
1897 /****************************************************************************
1898  Delete a print job - don't update queue.
1899 ****************************************************************************/
1900
1901 static bool print_job_delete1(int snum, uint32 jobid)
1902 {
1903         const char* sharename = lp_const_servicename(snum);
1904         struct printjob *pjob = print_job_find(sharename, jobid);
1905         int result = 0;
1906         struct printif *current_printif = get_printer_fns( snum );
1907
1908         if (!pjob)
1909                 return False;
1910
1911         /*
1912          * If already deleting just return.
1913          */
1914
1915         if (pjob->status == LPQ_DELETING)
1916                 return True;
1917
1918         /* Hrm - we need to be able to cope with deleting a job before it
1919            has reached the spooler.  Just mark it as LPQ_DELETING and 
1920            let the print_queue_update() code rmeove the record */
1921            
1922
1923         if (pjob->sysjob == -1) {
1924                 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
1925         }
1926
1927         /* Set the tdb entry to be deleting. */
1928
1929         pjob->status = LPQ_DELETING;
1930         pjob_store(sharename, jobid, pjob);
1931
1932         if (pjob->spooled && pjob->sysjob != -1) 
1933         {
1934                 result = (*(current_printif->job_delete))(
1935                         PRINTERNAME(snum),
1936                         lp_lprmcommand(snum), 
1937                         pjob);
1938
1939                 /* Delete the tdb entry if the delete succeeded or the job hasn't
1940                    been spooled. */
1941
1942                 if (result == 0) {
1943                         struct tdb_print_db *pdb = get_print_db_byname(sharename);
1944                         int njobs = 1;
1945
1946                         if (!pdb)
1947                                 return False;
1948                         pjob_delete(sharename, jobid);
1949                         /* Ensure we keep a rough count of the number of total jobs... */
1950                         tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
1951                         release_print_db(pdb);
1952                 }
1953         }
1954
1955         remove_from_jobs_changed( sharename, jobid );
1956
1957         return (result == 0);
1958 }
1959
1960 /****************************************************************************
1961  Return true if the current user owns the print job.
1962 ****************************************************************************/
1963
1964 static bool is_owner(struct current_user *user, const char *servicename,
1965                      uint32 jobid)
1966 {
1967         struct printjob *pjob = print_job_find(servicename, jobid);
1968         user_struct *vuser;
1969
1970         if (!pjob || !user)
1971                 return False;
1972
1973         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
1974                 return strequal(pjob->user, vuser->user.smb_name);
1975         } else {
1976                 return strequal(pjob->user, uidtoname(user->ut.uid));
1977         }
1978 }
1979
1980 /****************************************************************************
1981  Delete a print job.
1982 ****************************************************************************/
1983
1984 bool print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
1985 {
1986         const char* sharename = lp_const_servicename( snum );
1987         struct printjob *pjob;
1988         bool    owner;
1989         char    *fname;
1990
1991         *errcode = WERR_OK;
1992                 
1993         owner = is_owner(user, lp_const_servicename(snum), jobid);
1994         
1995         /* Check access against security descriptor or whether the user
1996            owns their job. */
1997
1998         if (!owner && 
1999             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
2000                 DEBUG(3, ("delete denied by security descriptor\n"));
2001                 *errcode = WERR_ACCESS_DENIED;
2002
2003                 /* BEGIN_ADMIN_LOG */
2004                 sys_adminlog( LOG_ERR, 
2005                               "Permission denied-- user not allowed to delete, \
2006 pause, or resume print job. User name: %s. Printer name: %s.",
2007                               uidtoname(user->ut.uid), PRINTERNAME(snum) );
2008                 /* END_ADMIN_LOG */
2009
2010                 return False;
2011         }
2012
2013         /* 
2014          * get the spooled filename of the print job
2015          * if this works, then the file has not been spooled
2016          * to the underlying print system.  Just delete the 
2017          * spool file & return.
2018          */
2019          
2020         if ( (fname = print_job_fname( sharename, jobid )) != NULL )
2021         {
2022                 /* remove the spool file */
2023                 DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname ));
2024                 if ( unlink( fname ) == -1 ) {
2025                         *errcode = map_werror_from_unix(errno);
2026                         return False;
2027                 }
2028         }
2029         
2030         if (!print_job_delete1(snum, jobid)) {
2031                 *errcode = WERR_ACCESS_DENIED;
2032                 return False;
2033         }
2034
2035         /* force update the database and say the delete failed if the
2036            job still exists */
2037
2038         print_queue_update(snum, True);
2039         
2040         pjob = print_job_find(sharename, jobid);
2041         if ( pjob && (pjob->status != LPQ_DELETING) )
2042                 *errcode = WERR_ACCESS_DENIED;
2043
2044         return (pjob == NULL );
2045 }
2046
2047 /****************************************************************************
2048  Pause a job.
2049 ****************************************************************************/
2050
2051 bool print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
2052 {
2053         const char* sharename = lp_const_servicename(snum);
2054         struct printjob *pjob;
2055         int ret = -1;
2056         struct printif *current_printif = get_printer_fns( snum );
2057
2058         pjob = print_job_find(sharename, jobid);
2059         
2060         if (!pjob || !user) {
2061                 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2062                         (unsigned int)jobid ));
2063                 return False;
2064         }
2065
2066         if (!pjob->spooled || pjob->sysjob == -1) {
2067                 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2068                         (int)pjob->sysjob, (unsigned int)jobid ));
2069                 return False;
2070         }
2071
2072         if (!is_owner(user, lp_const_servicename(snum), jobid) &&
2073             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
2074                 DEBUG(3, ("pause denied by security descriptor\n"));
2075
2076                 /* BEGIN_ADMIN_LOG */
2077                 sys_adminlog( LOG_ERR, 
2078                         "Permission denied-- user not allowed to delete, \
2079 pause, or resume print job. User name: %s. Printer name: %s.",
2080                                 uidtoname(user->ut.uid), PRINTERNAME(snum) );
2081                 /* END_ADMIN_LOG */
2082
2083                 *errcode = WERR_ACCESS_DENIED;
2084                 return False;
2085         }
2086
2087         /* need to pause the spooled entry */
2088         ret = (*(current_printif->job_pause))(snum, pjob);
2089
2090         if (ret != 0) {
2091                 *errcode = WERR_INVALID_PARAM;
2092                 return False;
2093         }
2094
2095         /* force update the database */
2096         print_cache_flush(lp_const_servicename(snum));
2097
2098         /* Send a printer notify message */
2099
2100         notify_job_status(sharename, jobid, JOB_STATUS_PAUSED);
2101
2102         /* how do we tell if this succeeded? */
2103
2104         return True;
2105 }
2106
2107 /****************************************************************************
2108  Resume a job.
2109 ****************************************************************************/
2110
2111 bool print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
2112 {
2113         const char *sharename = lp_const_servicename(snum);
2114         struct printjob *pjob;
2115         int ret;
2116         struct printif *current_printif = get_printer_fns( snum );
2117
2118         pjob = print_job_find(sharename, jobid);
2119         
2120         if (!pjob || !user) {
2121                 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2122                         (unsigned int)jobid ));
2123                 return False;
2124         }
2125
2126         if (!pjob->spooled || pjob->sysjob == -1) {
2127                 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2128                         (int)pjob->sysjob, (unsigned int)jobid ));
2129                 return False;
2130         }
2131
2132         if (!is_owner(user, lp_const_servicename(snum), jobid) &&
2133             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
2134                 DEBUG(3, ("resume denied by security descriptor\n"));
2135                 *errcode = WERR_ACCESS_DENIED;
2136
2137                 /* BEGIN_ADMIN_LOG */
2138                 sys_adminlog( LOG_ERR, 
2139                          "Permission denied-- user not allowed to delete, \
2140 pause, or resume print job. User name: %s. Printer name: %s.",
2141                         uidtoname(user->ut.uid), PRINTERNAME(snum) );
2142                 /* END_ADMIN_LOG */
2143                 return False;
2144         }
2145
2146         ret = (*(current_printif->job_resume))(snum, pjob);
2147
2148         if (ret != 0) {
2149                 *errcode = WERR_INVALID_PARAM;
2150                 return False;
2151         }
2152
2153         /* force update the database */
2154         print_cache_flush(lp_const_servicename(snum));
2155
2156         /* Send a printer notify message */
2157
2158         notify_job_status(sharename, jobid, JOB_STATUS_QUEUED);
2159
2160         return True;
2161 }
2162
2163 /****************************************************************************
2164  Write to a print file.
2165 ****************************************************************************/
2166
2167 ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
2168 {
2169         const char* sharename = lp_const_servicename(snum);
2170         int return_code;
2171         struct printjob *pjob;
2172
2173         pjob = print_job_find(sharename, jobid);
2174
2175         if (!pjob)
2176                 return -1;
2177         /* don't allow another process to get this info - it is meaningless */
2178         if (pjob->pid != sys_getpid())
2179                 return -1;
2180
2181         return_code = write_data_at_offset(pjob->fd, buf, size, pos);
2182
2183         if (return_code>0) {
2184                 pjob->size += size;
2185                 pjob_store(sharename, jobid, pjob);
2186         }
2187         return return_code;
2188 }
2189
2190 /****************************************************************************
2191  Get the queue status - do not update if db is out of date.
2192 ****************************************************************************/
2193
2194 static int get_queue_status(const char* sharename, print_status_struct *status)
2195 {
2196         fstring keystr;
2197         TDB_DATA data;
2198         struct tdb_print_db *pdb = get_print_db_byname(sharename);
2199         int len;
2200
2201         if (status) {
2202                 ZERO_STRUCTP(status);
2203         }
2204
2205         if (!pdb)
2206                 return 0;
2207
2208         if (status) {
2209                 fstr_sprintf(keystr, "STATUS/%s", sharename);
2210                 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2211                 if (data.dptr) {
2212                         if (data.dsize == sizeof(print_status_struct))
2213                                 /* this memcpy is ok since the status struct was 
2214                                    not packed before storing it in the tdb */
2215                                 memcpy(status, data.dptr, sizeof(print_status_struct));
2216                         SAFE_FREE(data.dptr);
2217                 }
2218         }
2219         len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2220         release_print_db(pdb);
2221         return (len == -1 ? 0 : len);
2222 }
2223
2224 /****************************************************************************
2225  Determine the number of jobs in a queue.
2226 ****************************************************************************/
2227
2228 int print_queue_length(int snum, print_status_struct *pstatus)
2229 {
2230         const char* sharename = lp_const_servicename( snum );
2231         print_status_struct status;
2232         int len;
2233
2234         ZERO_STRUCT( status );
2235  
2236         /* make sure the database is up to date */
2237         if (print_cache_expired(lp_const_servicename(snum), True))
2238                 print_queue_update(snum, False);
2239  
2240         /* also fetch the queue status */
2241         memset(&status, 0, sizeof(status));
2242         len = get_queue_status(sharename, &status);
2243
2244         if (pstatus)
2245                 *pstatus = status;
2246
2247         return len;
2248 }
2249
2250 /***************************************************************************
2251  Allocate a jobid. Hold the lock for as short a time as possible.
2252 ***************************************************************************/
2253
2254 static bool allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
2255 {
2256         int i;
2257         uint32 jobid;
2258
2259         *pjobid = (uint32)-1;
2260
2261         for (i = 0; i < 3; i++) {
2262                 /* Lock the database - only wait 20 seconds. */
2263                 if (tdb_lock_bystring_with_timeout(pdb->tdb, "INFO/nextjob", 20) == -1) {
2264                         DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename));
2265                         return False;
2266                 }
2267
2268                 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2269                         if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) {
2270                                 DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n",
2271                                         sharename));
2272                                 return False;
2273                         }
2274                         jobid = 0;
2275                 }
2276
2277                 jobid = NEXT_JOBID(jobid);
2278
2279                 if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) {
2280                         DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n"));
2281                         tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2282                         return False;
2283                 }
2284
2285                 /* We've finished with the INFO/nextjob lock. */
2286                 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2287                                 
2288                 if (!print_job_exists(sharename, jobid))
2289                         break;
2290         }
2291
2292         if (i > 2) {
2293                 DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n",
2294                         sharename));
2295                 /* Probably full... */
2296                 errno = ENOSPC;
2297                 return False;
2298         }
2299
2300         /* Store a dummy placeholder. */
2301         {
2302                 TDB_DATA dum;
2303                 dum.dptr = NULL;
2304                 dum.dsize = 0;
2305                 if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
2306                         DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n",
2307                                 jobid ));
2308                         return False;
2309                 }
2310         }
2311
2312         *pjobid = jobid;
2313         return True;
2314 }
2315
2316 /***************************************************************************
2317  Append a jobid to the 'jobs changed' list.
2318 ***************************************************************************/
2319
2320 static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
2321 {
2322         TDB_DATA data;
2323         uint32 store_jobid;
2324
2325         SIVAL(&store_jobid, 0, jobid);
2326         data.dptr = (uint8 *)&store_jobid;
2327         data.dsize = 4;
2328
2329         DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
2330
2331         return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
2332                            data) == 0);
2333 }
2334
2335 /***************************************************************************
2336  Start spooling a job - return the jobid.
2337 ***************************************************************************/
2338
2339 uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
2340 {
2341         uint32 jobid;
2342         char *path;
2343         struct printjob pjob;
2344         user_struct *vuser;
2345         const char *sharename = lp_const_servicename(snum);
2346         struct tdb_print_db *pdb = get_print_db_byname(sharename);
2347         int njobs;
2348
2349         errno = 0;
2350
2351         if (!pdb)
2352                 return (uint32)-1;
2353
2354         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
2355                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
2356                 release_print_db(pdb);
2357                 return (uint32)-1;
2358         }
2359
2360         if (!print_time_access_check(lp_servicename(snum))) {
2361                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
2362                 release_print_db(pdb);
2363                 return (uint32)-1;
2364         }
2365
2366         path = lp_pathname(snum);
2367
2368         /* see if we have sufficient disk space */
2369         if (lp_minprintspace(snum)) {
2370                 SMB_BIG_UINT dspace, dsize;
2371                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
2372                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
2373                         DEBUG(3, ("print_job_start: disk space check failed.\n"));
2374                         release_print_db(pdb);
2375                         errno = ENOSPC;
2376                         return (uint32)-1;
2377                 }
2378         }
2379
2380         /* for autoloaded printers, check that the printcap entry still exists */
2381         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) {
2382                 DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
2383                 release_print_db(pdb);
2384                 errno = ENOENT;
2385                 return (uint32)-1;
2386         }
2387
2388         /* Insure the maximum queue size is not violated */
2389         if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
2390                 DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n",
2391                         sharename, njobs, lp_maxprintjobs(snum) ));
2392                 release_print_db(pdb);
2393                 errno = ENOSPC;
2394                 return (uint32)-1;
2395         }
2396
2397         DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n",
2398                 sharename, njobs, lp_maxprintjobs(snum) ));
2399
2400         if (!allocate_print_jobid(pdb, snum, sharename, &jobid))
2401                 goto fail;
2402
2403         /* create the database entry */
2404         
2405         ZERO_STRUCT(pjob);
2406         
2407         pjob.pid = sys_getpid();
2408         pjob.sysjob = -1;
2409         pjob.fd = -1;
2410         pjob.starttime = time(NULL);
2411         pjob.status = LPQ_SPOOLING;
2412         pjob.size = 0;
2413         pjob.spooled = False;
2414         pjob.smbjob = True;
2415         pjob.nt_devmode = nt_devmode;
2416         
2417         fstrcpy(pjob.jobname, jobname);
2418
2419         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
2420                 fstrcpy(pjob.user, lp_printjob_username(snum));
2421                 standard_sub_basic(vuser->user.smb_name, vuser->user.domain, 
2422                                    pjob.user, sizeof(pjob.user)-1);
2423                 /* ensure NULL termination */ 
2424                 pjob.user[sizeof(pjob.user)-1] = '\0'; 
2425         } else {
2426                 fstrcpy(pjob.user, uidtoname(user->ut.uid));
2427         }
2428
2429         fstrcpy(pjob.queuename, lp_const_servicename(snum));
2430
2431         /* we have a job entry - now create the spool file */
2432         slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", 
2433                  path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
2434         pjob.fd = smb_mkstemp(pjob.filename);
2435
2436         if (pjob.fd == -1) {
2437                 if (errno == EACCES) {
2438                         /* Common setup error, force a report. */
2439                         DEBUG(0, ("print_job_start: insufficient permissions \
2440 to open spool file %s.\n", pjob.filename));
2441                 } else {
2442                         /* Normal case, report at level 3 and above. */
2443                         DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename));
2444                         DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno)));
2445                 }
2446                 goto fail;
2447         }
2448
2449         pjob_store(sharename, jobid, &pjob);
2450
2451         /* Update the 'jobs changed' entry used by print_queue_status. */
2452         add_to_jobs_changed(pdb, jobid);
2453
2454         /* Ensure we keep a rough count of the number of total jobs... */
2455         tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
2456
2457         release_print_db(pdb);
2458
2459         return jobid;
2460
2461  fail:
2462         if (jobid != -1)
2463                 pjob_delete(sharename, jobid);
2464
2465         release_print_db(pdb);
2466
2467         DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
2468         return (uint32)-1;
2469 }
2470
2471 /****************************************************************************
2472  Update the number of pages spooled to jobid
2473 ****************************************************************************/
2474
2475 void print_job_endpage(int snum, uint32 jobid)
2476 {
2477         const char* sharename = lp_const_servicename(snum);
2478         struct printjob *pjob;
2479
2480         pjob = print_job_find(sharename, jobid);
2481         if (!pjob)
2482                 return;
2483         /* don't allow another process to get this info - it is meaningless */
2484         if (pjob->pid != sys_getpid())
2485                 return;
2486
2487         pjob->page_count++;
2488         pjob_store(sharename, jobid, pjob);
2489 }
2490
2491 /****************************************************************************
2492  Print a file - called on closing the file. This spools the job.
2493  If normal close is false then we're tearing down the jobs - treat as an
2494  error.
2495 ****************************************************************************/
2496
2497 bool print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
2498 {
2499         const char* sharename = lp_const_servicename(snum);
2500         struct printjob *pjob;
2501         int ret;
2502         SMB_STRUCT_STAT sbuf;
2503         struct printif *current_printif = get_printer_fns( snum );
2504
2505         pjob = print_job_find(sharename, jobid);
2506
2507         if (!pjob)
2508                 return False;
2509
2510         if (pjob->spooled || pjob->pid != sys_getpid())
2511                 return False;
2512
2513         if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
2514                                 (sys_fstat(pjob->fd, &sbuf) == 0)) {
2515                 pjob->size = sbuf.st_size;
2516                 close(pjob->fd);
2517                 pjob->fd = -1;
2518         } else {
2519
2520                 /* 
2521                  * Not a normal close or we couldn't stat the job file,
2522                  * so something has gone wrong. Cleanup.
2523                  */
2524                 close(pjob->fd);
2525                 pjob->fd = -1;
2526                 DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid ));
2527                 goto fail;
2528         }
2529
2530         /* Technically, this is not quite right. If the printer has a separator
2531          * page turned on, the NT spooler prints the separator page even if the
2532          * print job is 0 bytes. 010215 JRR */
2533         if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
2534                 /* don't bother spooling empty files or something being deleted. */
2535                 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
2536                         pjob->filename, pjob->size ? "deleted" : "zero length" ));
2537                 unlink(pjob->filename);
2538                 pjob_delete(sharename, jobid);
2539                 return True;
2540         }
2541
2542         pjob->smbjob = jobid;
2543
2544         ret = (*(current_printif->job_submit))(snum, pjob);
2545
2546         if (ret)
2547                 goto fail;
2548
2549         /* The print job has been sucessfully handed over to the back-end */
2550         
2551         pjob->spooled = True;
2552         pjob->status = LPQ_QUEUED;
2553         pjob_store(sharename, jobid, pjob);
2554         
2555         /* make sure the database is up to date */
2556         if (print_cache_expired(lp_const_servicename(snum), True))
2557                 print_queue_update(snum, False);
2558         
2559         return True;
2560
2561 fail:
2562
2563         /* The print job was not succesfully started. Cleanup */
2564         /* Still need to add proper error return propagation! 010122:JRR */
2565         unlink(pjob->filename);
2566         pjob_delete(sharename, jobid);
2567         return False;
2568 }
2569
2570 /****************************************************************************
2571  Get a snapshot of jobs in the system without traversing.
2572 ****************************************************************************/
2573
2574 static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
2575 {
2576         TDB_DATA data, cgdata;
2577         print_queue_struct *queue = NULL;
2578         uint32 qcount = 0;
2579         uint32 extra_count = 0;
2580         int total_count = 0;
2581         size_t len = 0;
2582         uint32 i;
2583         int max_reported_jobs = lp_max_reported_jobs(snum);
2584         bool ret = False;
2585         const char* sharename = lp_servicename(snum);
2586
2587         /* make sure the database is up to date */
2588         if (print_cache_expired(lp_const_servicename(snum), True))
2589                 print_queue_update(snum, False);
2590  
2591         *pcount = 0;
2592         *ppqueue = NULL;
2593
2594         ZERO_STRUCT(data);
2595         ZERO_STRUCT(cgdata);
2596
2597         /* Get the stored queue data. */
2598         data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
2599         
2600         if (data.dptr && data.dsize >= sizeof(qcount))
2601                 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
2602                 
2603         /* Get the changed jobs list. */
2604         cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
2605         if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
2606                 extra_count = cgdata.dsize/4;
2607
2608         DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
2609
2610         /* Allocate the queue size. */
2611         if (qcount == 0 && extra_count == 0)
2612                 goto out;
2613
2614         if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
2615                 goto out;
2616
2617         /* Retrieve the linearised queue data. */
2618
2619         for( i  = 0; i < qcount; i++) {
2620                 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
2621                 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
2622                                 &qjob,
2623                                 &qsize,
2624                                 &qpage_count,
2625                                 &qstatus,
2626                                 &qpriority,
2627                                 &qtime,
2628                                 queue[i].fs_user,
2629                                 queue[i].fs_file);
2630                 queue[i].job = qjob;
2631                 queue[i].size = qsize;
2632                 queue[i].page_count = qpage_count;
2633                 queue[i].status = qstatus;
2634                 queue[i].priority = qpriority;
2635                 queue[i].time = qtime;
2636         }
2637
2638         total_count = qcount;
2639
2640         /* Add in the changed jobids. */
2641         for( i  = 0; i < extra_count; i++) {
2642                 uint32 jobid;
2643                 struct printjob *pjob;
2644
2645                 jobid = IVAL(cgdata.dptr, i*4);
2646                 DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
2647                 pjob = print_job_find(lp_const_servicename(snum), jobid);
2648                 if (!pjob) {
2649                         DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
2650                         remove_from_jobs_changed(sharename, jobid);
2651                         continue;
2652                 }
2653
2654                 queue[total_count].job = jobid;
2655                 queue[total_count].size = pjob->size;
2656                 queue[total_count].page_count = pjob->page_count;
2657                 queue[total_count].status = pjob->status;
2658                 queue[total_count].priority = 1;
2659                 queue[total_count].time = pjob->starttime;
2660                 fstrcpy(queue[total_count].fs_user, pjob->user);
2661                 fstrcpy(queue[total_count].fs_file, pjob->jobname);
2662                 total_count++;
2663         }
2664
2665         /* Sort the queue by submission time otherwise they are displayed
2666            in hash order. */
2667
2668         qsort(queue, total_count, sizeof(print_queue_struct), QSORT_CAST(printjob_comp));
2669
2670         DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
2671
2672         if (max_reported_jobs && total_count > max_reported_jobs)
2673                 total_count = max_reported_jobs;
2674
2675         *ppqueue = queue;
2676         *pcount = total_count;
2677
2678         ret = True;
2679
2680   out:
2681
2682         SAFE_FREE(data.dptr);
2683         SAFE_FREE(cgdata.dptr);
2684         return ret;
2685 }
2686
2687 /****************************************************************************
2688  Get a printer queue listing.
2689  set queue = NULL and status = NULL if you just want to update the cache
2690 ****************************************************************************/
2691
2692 int print_queue_status(int snum, 
2693                        print_queue_struct **ppqueue,
2694                        print_status_struct *status)
2695 {
2696         fstring keystr;
2697         TDB_DATA data, key;
2698         const char *sharename;
2699         struct tdb_print_db *pdb;
2700         int count = 0;
2701
2702         /* make sure the database is up to date */
2703
2704         if (print_cache_expired(lp_const_servicename(snum), True))
2705                 print_queue_update(snum, False);
2706
2707         /* return if we are done */
2708         if ( !ppqueue || !status )
2709                 return 0;
2710
2711         *ppqueue = NULL;
2712         sharename = lp_const_servicename(snum);
2713         pdb = get_print_db_byname(sharename);
2714
2715         if (!pdb)
2716                 return 0;
2717
2718         /*
2719          * Fetch the queue status.  We must do this first, as there may
2720          * be no jobs in the queue.
2721          */
2722
2723         ZERO_STRUCTP(status);
2724         slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
2725         key = string_tdb_data(keystr);
2726
2727         data = tdb_fetch(pdb->tdb, key);
2728         if (data.dptr) {
2729                 if (data.dsize == sizeof(*status)) {
2730                         /* this memcpy is ok since the status struct was 
2731                            not packed before storing it in the tdb */
2732                         memcpy(status, data.dptr, sizeof(*status));
2733                 }
2734                 SAFE_FREE(data.dptr);
2735         }
2736
2737         /*
2738          * Now, fetch the print queue information.  We first count the number
2739          * of entries, and then only retrieve the queue if necessary.
2740          */
2741
2742         if (!get_stored_queue_info(pdb, snum, &count, ppqueue)) {
2743                 release_print_db(pdb);
2744                 return 0;
2745         }
2746
2747         release_print_db(pdb);
2748         return count;
2749 }
2750
2751 /****************************************************************************
2752  Pause a queue.
2753 ****************************************************************************/
2754
2755 bool print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
2756 {
2757         int ret;
2758         struct printif *current_printif = get_printer_fns( snum );
2759         
2760         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2761                 *errcode = WERR_ACCESS_DENIED;
2762                 return False;
2763         }
2764         
2765
2766         become_root();
2767                 
2768         ret = (*(current_printif->queue_pause))(snum);
2769
2770         unbecome_root();
2771                 
2772         if (ret != 0) {
2773                 *errcode = WERR_INVALID_PARAM;
2774                 return False;
2775         }
2776
2777         /* force update the database */
2778         print_cache_flush(lp_const_servicename(snum));
2779
2780         /* Send a printer notify message */
2781
2782         notify_printer_status(snum, PRINTER_STATUS_PAUSED);
2783
2784         return True;
2785 }
2786
2787 /****************************************************************************
2788  Resume a queue.
2789 ****************************************************************************/
2790
2791 bool print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
2792 {
2793         int ret;
2794         struct printif *current_printif = get_printer_fns( snum );
2795
2796         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
2797                 *errcode = WERR_ACCESS_DENIED;
2798                 return False;
2799         }
2800         
2801         become_root();
2802                 
2803         ret = (*(current_printif->queue_resume))(snum);
2804
2805         unbecome_root();
2806                 
2807         if (ret != 0) {
2808                 *errcode = WERR_INVALID_PARAM;
2809                 return False;
2810         }
2811
2812         /* make sure the database is up to date */
2813         if (print_cache_expired(lp_const_servicename(snum), True))
2814                 print_queue_update(snum, True);
2815
2816         /* Send a printer notify message */
2817
2818         notify_printer_status(snum, PRINTER_STATUS_OK);
2819
2820         return True;
2821 }
2822
2823 /****************************************************************************
2824  Purge a queue - implemented by deleting all jobs that we can delete.
2825 ****************************************************************************/
2826
2827 bool print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
2828 {
2829         print_queue_struct *queue;
2830         print_status_struct status;
2831         int njobs, i;
2832         bool can_job_admin;
2833
2834         /* Force and update so the count is accurate (i.e. not a cached count) */
2835         print_queue_update(snum, True);
2836         
2837         can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
2838         njobs = print_queue_status(snum, &queue, &status);
2839         
2840         if ( can_job_admin )
2841                 become_root();
2842
2843         for (i=0;i<njobs;i++) {
2844                 bool owner = is_owner(user, lp_const_servicename(snum), queue[i].job);
2845
2846                 if (owner || can_job_admin) {
2847                         print_job_delete1(snum, queue[i].job);
2848                 }
2849         }
2850         
2851         if ( can_job_admin )
2852                 unbecome_root();
2853
2854         /* update the cache */
2855         print_queue_update( snum, True );
2856
2857         SAFE_FREE(queue);
2858
2859         return True;
2860 }