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