Fixes to periodically scan printing.tdb in idle time and occasionally
[samba.git] / source / printing / printing.c
1 #define OLD_NTDOMAIN 1
2 /* 
3    Unix SMB/Netbios implementation.
4    Version 3.0
5    printing backend routines
6    Copyright (C) Andrew Tridgell 1992-2000
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 extern int DEBUGLEVEL;
25
26 /* 
27    the printing backend revolves around a tdb database that stores the
28    SMB view of the print queue 
29    
30    The key for this database is a jobid - a internally generated number that
31    uniquely identifies a print job
32
33    reading the print queue involves two steps:
34      - possibly running lpq and updating the internal database from that
35      - reading entries from the database
36
37    jobids are assigned when a job starts spooling. 
38 */
39
40 struct printjob {
41         pid_t pid; /* which process launched the job */
42         int sysjob; /* the system (lp) job number */
43         int fd; /* file descriptor of open file if open */
44         time_t starttime; /* when the job started spooling */
45         int status; /* the status of this job */
46         size_t size; /* the size of the job so far */
47         BOOL spooled; /* has it been sent to the spooler yet? */
48         BOOL smbjob; /* set if the job is a SMB job */
49         fstring filename; /* the filename used to spool the file */
50         fstring jobname; /* the job name given to us by the client */
51         fstring user; /* the user who started the job */
52         fstring qname; /* name of the print queue the job was sent to */
53 };
54
55 /* the open printing.tdb database */
56 static TDB_CONTEXT *tdb;
57 static pid_t local_pid;
58
59 #define PRINT_MAX_JOBID 10000
60 #define UNIX_JOB_START PRINT_MAX_JOBID
61
62 #define PRINT_SPOOL_PREFIX "smbprn."
63 #define PRINT_DATABASE_VERSION 1
64
65 /****************************************************************************
66 initialise the printing backend. Called once at startup. 
67 Does not survive a fork
68 ****************************************************************************/
69 BOOL print_backend_init(void)
70 {
71         char *sversion = "INFO/version";
72
73         if (tdb && local_pid == sys_getpid()) return True;
74         tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
75         if (!tdb) {
76                 DEBUG(0,("Failed to open printing backend database\n"));
77         }
78         local_pid = sys_getpid();
79
80         /* handle a Samba upgrade */
81         tdb_lock_bystring(tdb, sversion);
82         if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
83                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
84                 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
85         }
86         tdb_unlock_bystring(tdb, sversion);
87
88         return nt_printing_init();
89 }
90
91 /****************************************************************************
92 useful function to generate a tdb key
93 ****************************************************************************/
94 static TDB_DATA print_key(int jobid)
95 {
96         static int j;
97         TDB_DATA ret;
98
99         j = jobid;
100         ret.dptr = (void *)&j;
101         ret.dsize = sizeof(j);
102         return ret;
103 }
104
105 /****************************************************************************
106 useful function to find a print job in the database
107 ****************************************************************************/
108 static struct printjob *print_job_find(int jobid)
109 {
110         static struct printjob pjob;
111         TDB_DATA ret;
112
113         ret = tdb_fetch(tdb, print_key(jobid));
114         if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
115
116         memcpy(&pjob, ret.dptr, sizeof(pjob));
117         free(ret.dptr);
118         return &pjob;
119 }
120
121 /****************************************************************************
122 store a job structure back to the database
123 ****************************************************************************/
124 static BOOL print_job_store(int jobid, struct printjob *pjob)
125 {
126         TDB_DATA d;
127         d.dptr = (void *)pjob;
128         d.dsize = sizeof(*pjob);
129         return (0 == tdb_store(tdb, print_key(jobid), d, TDB_REPLACE));
130 }
131
132 /****************************************************************************
133 run a given print command 
134 a null terminated list of value/substitute pairs is provided
135 for local substitution strings
136 ****************************************************************************/
137 static int print_run_command(int snum,char *command, 
138                              char *outfile,
139                              ...)
140 {
141         pstring syscmd;
142         char *p, *arg;
143         int ret;
144         va_list ap;
145
146         if (!command || !*command) return -1;
147
148         if (!VALID_SNUM(snum)) {
149                 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
150                 return -1;
151         }
152
153         pstrcpy(syscmd, command);
154
155         va_start(ap, outfile);
156         while ((arg = va_arg(ap, char *))) {
157                 char *value = va_arg(ap,char *);
158                 pstring_sub(syscmd, arg, value);
159         }
160         va_end(ap);
161   
162         p = PRINTERNAME(snum);
163         if (!p || !*p) p = SERVICE(snum);
164   
165         pstring_sub(syscmd, "%p", p);
166         standard_sub_snum(snum,syscmd);
167   
168         ret = smbrun(syscmd,outfile,False);
169
170         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
171         return ret;
172 }
173
174
175 /****************************************************************************
176 parse a file name from the system spooler to generate a jobid
177 ****************************************************************************/
178 static int print_parse_jobid(char *fname)
179 {
180         int jobid;
181
182         if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
183         fname += strlen(PRINT_SPOOL_PREFIX);
184
185         jobid = atoi(fname);
186         if (jobid <= 0) return -1;
187
188         return jobid;
189 }
190
191
192 /****************************************************************************
193 list a unix job in the print database
194 ****************************************************************************/
195 static void print_unix_job(int snum, print_queue_struct *q)
196 {
197         int jobid = q->job + UNIX_JOB_START;
198         struct printjob pj;
199
200         ZERO_STRUCT(pj);
201
202         pj.pid = (pid_t)-1;
203         pj.sysjob = q->job;
204         pj.fd = -1;
205         pj.starttime = q->time;
206         pj.status = q->status;
207         pj.size = q->size;
208         pj.spooled = True;
209         pj.smbjob = False;
210         fstrcpy(pj.filename, "");
211         fstrcpy(pj.jobname, q->file);
212         fstrcpy(pj.user, q->user);
213         fstrcpy(pj.qname, lp_servicename(snum));
214
215         print_job_store(jobid, &pj);
216 }
217
218
219 struct traverse_struct {
220         print_queue_struct *queue;
221         int qcount, snum, maxcount;
222 };
223
224 /* utility fn to delete any jobs that are no longer active */
225 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
226 {
227         struct traverse_struct *ts = (struct traverse_struct *)state;
228         struct printjob pjob;
229         int i, jobid;
230
231         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
232         memcpy(&jobid, key.dptr, sizeof(jobid));
233         memcpy(&pjob,  data.dptr, sizeof(pjob));
234
235         if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
236                 /* this isn't for the queue we are looking at */
237                 return 0;
238         }
239
240         if (!pjob.smbjob) {
241                 /* remove a unix job if it isn't in the system queue
242                    any more */
243                 for (i=0;i<ts->qcount;i++) {
244                         if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
245                 }
246                 if (i == ts->qcount) tdb_delete(tdb, key);
247                 return 0;
248         }
249
250         /* maybe it hasn't been spooled yet */
251         if (!pjob.spooled) {
252                 /* if a job is not spooled and the process doesn't
253                    exist then kill it. This cleans up after smbd
254                    deaths */
255                 if (!process_exists(pjob.pid)) {
256                         tdb_delete(tdb, key);
257                 }
258                 return 0;
259         }
260
261         for (i=0;i<ts->qcount;i++) {
262                 int qid = print_parse_jobid(ts->queue[i].file);
263                 if (jobid == qid) break;
264         }
265         
266         if (i == ts->qcount) {
267                 /* the job isn't in the system queue - we have to
268                    assume it has completed, so delete the database
269                    entry */
270                 tdb_delete(t, key);
271         }
272
273         return 0;
274 }
275
276 /****************************************************************************
277 check if the print queue has been updated recently enough
278 ****************************************************************************/
279 static void print_cache_flush(int snum)
280 {
281         fstring key;
282         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
283         tdb_store_int(tdb, key, -1);
284 }
285
286 /****************************************************************************
287 update the internal database from the system print queue for a queue
288 ****************************************************************************/
289 static void print_queue_update(int snum)
290 {
291         char *path = lp_pathname(snum);
292         char *cmd = lp_lpqcommand(snum);
293         char **qlines;
294         pstring tmp_file;
295         int numlines, i, qcount;
296         print_queue_struct *queue = NULL;
297         print_status_struct status;
298         struct printjob *pjob;
299         struct traverse_struct tstruct;
300         fstring keystr;
301         TDB_DATA data, key;
302  
303         /*
304          * Update the cache time FIRST ! Stops others doing this
305          * if the lpq takes a long time.
306          */
307
308         slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
309         tdb_store_int(tdb, keystr, (int)time(NULL));
310
311         slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
312
313         unlink(tmp_file);
314         print_run_command(snum, cmd, tmp_file,
315                           NULL);
316
317         numlines = 0;
318         qlines = file_lines_load(tmp_file, &numlines);
319         unlink(tmp_file);
320
321         /* turn the lpq output into a series of job structures */
322         qcount = 0;
323         ZERO_STRUCT(status);
324         if (numlines)
325                 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
326
327         if (queue) {
328                 for (i=0; i<numlines; i++) {
329                         /* parse the line */
330                         if (parse_lpq_entry(snum,qlines[i],
331                                             &queue[qcount],&status,qcount==0)) {
332                                 qcount++;
333                         }
334                 }               
335         }
336         file_lines_free(qlines);
337
338         /*
339           any job in the internal database that is marked as spooled
340           and doesn't exist in the system queue is considered finished
341           and removed from the database
342
343           any job in the system database but not in the internal database 
344           is added as a unix job
345
346           fill in any system job numbers as we go
347         */
348         for (i=0; i<qcount; i++) {
349                 int jobid = print_parse_jobid(queue[i].file);
350
351                 if (jobid == -1) {
352                         /* assume its a unix print job */
353                         print_unix_job(snum, &queue[i]);
354                         continue;
355                 }
356
357                 /* we have an active SMB print job - update its status */
358                 pjob = print_job_find(jobid);
359                 if (!pjob) {
360                         /* err, somethings wrong. Probably smbd was restarted
361                            with jobs in the queue. All we can do is treat them
362                            like unix jobs. Pity. */
363                         print_unix_job(snum, &queue[i]);
364                         continue;
365                 }
366
367                 pjob->sysjob = queue[i].job;
368                 pjob->status = queue[i].status;
369
370                 print_job_store(jobid, pjob);
371         }
372
373         /* now delete any queued entries that don't appear in the
374            system queue */
375         tstruct.queue = queue;
376         tstruct.qcount = qcount;
377         tstruct.snum = snum;
378
379         tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
380
381         safe_free(tstruct.queue);
382
383         /* store the queue status structure */
384         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
385         data.dptr = (void *)&status;
386         data.dsize = sizeof(status);
387         key.dptr = keystr;
388         key.dsize = strlen(keystr);
389         tdb_store(tdb, key, data, TDB_REPLACE); 
390
391         /*
392          * Update the cache time again. We want to do this call
393          * as little as possible...
394          */
395
396         slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
397         tdb_store_int(tdb, keystr, (int)time(NULL));
398 }
399
400 /****************************************************************************
401 check if a jobid is valid. It is valid if it exists in the database
402 ****************************************************************************/
403 BOOL print_job_exists(int jobid)
404 {
405         return tdb_exists(tdb, print_key(jobid));
406 }
407
408
409 /****************************************************************************
410 work out which service a jobid is for
411 note that we have to look up by queue name to ensure that it works for 
412 other than the process that started the job
413 ****************************************************************************/
414 int print_job_snum(int jobid)
415 {
416         struct printjob *pjob = print_job_find(jobid);
417         if (!pjob) return -1;
418
419         return lp_servicenumber(pjob->qname);
420 }
421
422 /****************************************************************************
423 give the fd used for a jobid
424 ****************************************************************************/
425 int print_job_fd(int jobid)
426 {
427         struct printjob *pjob = print_job_find(jobid);
428         if (!pjob) return -1;
429         /* don't allow another process to get this info - it is meaningless */
430         if (pjob->pid != local_pid) return -1;
431         return pjob->fd;
432 }
433
434 /****************************************************************************
435 give the filename used for a jobid
436 only valid for the process doing the spooling and when the job
437 has not been spooled
438 ****************************************************************************/
439 char *print_job_fname(int jobid)
440 {
441         struct printjob *pjob = print_job_find(jobid);
442         if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
443         return pjob->filename;
444 }
445
446
447 /****************************************************************************
448 set the place in the queue for a job
449 ****************************************************************************/
450 BOOL print_job_set_place(int jobid, int place)
451 {
452         DEBUG(2,("print_job_set_place not implemented yet\n"));
453         return False;
454 }
455
456 /****************************************************************************
457 set the name of a job. Only possible for owner
458 ****************************************************************************/
459 BOOL print_job_set_name(int jobid, char *name)
460 {
461         struct printjob *pjob = print_job_find(jobid);
462         if (!pjob || pjob->pid != local_pid) return False;
463
464         fstrcpy(pjob->jobname, name);
465         return print_job_store(jobid, pjob);
466 }
467
468
469 /****************************************************************************
470 delete a print job - don't update queue
471 ****************************************************************************/
472 static BOOL print_job_delete1(int jobid)
473 {
474         struct printjob *pjob = print_job_find(jobid);
475         int snum;
476
477         if (!pjob) return False;
478
479         snum = print_job_snum(jobid);
480
481         if (pjob->spooled && pjob->sysjob != -1) {
482                 /* need to delete the spooled entry */
483                 fstring jobstr;
484                 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
485                 print_run_command(snum, 
486                                   lp_lprmcommand(snum), NULL,
487                                   "%j", jobstr,
488                                   "%T", http_timestring(pjob->starttime),
489                                   NULL);
490         }
491
492         return True;
493 }
494
495 /****************************************************************************
496 return true if the current user owns the print job
497 ****************************************************************************/
498 static BOOL is_owner(struct current_user *user, int jobid)
499 {
500         struct printjob *pjob = print_job_find(jobid);
501         user_struct *vuser;
502
503         if (!pjob || !user) return False;
504
505         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
506                 return strequal(pjob->user, vuser->user.smb_name);
507         } else {
508                 return strequal(pjob->user, uidtoname(user->uid));
509         }
510 }
511
512 /****************************************************************************
513 delete a print job
514 ****************************************************************************/
515 BOOL print_job_delete(struct current_user *user, int jobid)
516 {
517         int snum = print_job_snum(jobid);
518         BOOL owner;
519         
520         if (!user) return False;
521
522         owner = is_owner(user, jobid);
523         
524         /* Check access against security descriptor or whether the user
525            owns their job. */
526
527         if (!owner && 
528             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
529                 DEBUG(3, ("delete denied by security descriptor\n"));
530                 return False;
531         }
532
533         if (!print_job_delete1(jobid)) return False;
534
535         /* force update the database and say the delete failed if the
536            job still exists */
537
538         print_queue_update(snum);
539
540         return !print_job_exists(jobid);
541 }
542
543
544 /****************************************************************************
545 pause a job
546 ****************************************************************************/
547 BOOL print_job_pause(struct current_user *user, int jobid)
548 {
549         struct printjob *pjob = print_job_find(jobid);
550         int snum, ret = -1;
551         fstring jobstr;
552         BOOL owner;
553         
554
555         if (!pjob || !user) return False;
556
557         if (!pjob->spooled || pjob->sysjob == -1) return False;
558
559         snum = print_job_snum(jobid);
560         owner = is_owner(user, jobid);
561
562         if (!owner &&
563             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
564                 DEBUG(3, ("pause denied by security descriptor\n"));
565                 return False;
566         }
567
568         /* need to pause the spooled entry */
569         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
570         ret = print_run_command(snum, 
571                                 lp_lppausecommand(snum), NULL,
572                                 "%j", jobstr,
573                                 NULL);
574
575         /* force update the database */
576         print_cache_flush(snum);
577
578         /* how do we tell if this succeeded? */
579         return ret == 0;
580 }
581
582 /****************************************************************************
583 resume a job
584 ****************************************************************************/
585 BOOL print_job_resume(struct current_user *user, int jobid)
586 {
587         struct printjob *pjob = print_job_find(jobid);
588         int snum, ret;
589         fstring jobstr;
590         BOOL owner;
591         
592         if (!pjob || !user) return False;
593
594         if (!pjob->spooled || pjob->sysjob == -1) return False;
595
596         snum = print_job_snum(jobid);
597         owner = is_owner(user, jobid);
598
599         if (!is_owner(user, jobid) &&
600             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
601                 DEBUG(3, ("resume denied by security descriptor\n"));
602                 return False;
603         }
604
605         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
606         ret = print_run_command(snum, 
607                                 lp_lpresumecommand(snum), NULL,
608                                 "%j", jobstr,
609                                 NULL);
610
611         /* force update the database */
612         print_cache_flush(snum);
613
614         /* how do we tell if this succeeded? */
615         return ret == 0;
616 }
617
618 /****************************************************************************
619 write to a print file
620 ****************************************************************************/
621 int print_job_write(int jobid, const char *buf, int size)
622 {
623         int fd;
624
625         fd = print_job_fd(jobid);
626         if (fd == -1) return -1;
627
628         return write(fd, buf, size);
629 }
630
631
632 /***************************************************************************
633 start spooling a job - return the jobid
634 ***************************************************************************/
635 int print_job_start(struct current_user *user, int snum, char *jobname)
636 {
637         int jobid;
638         char *path;
639         struct printjob pjob;
640         int next_jobid;
641         user_struct *vuser;
642
643         errno = 0;
644
645         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
646                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
647                 return -1;
648         }
649
650         if (!print_time_access_check(snum)) {
651                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
652                 return -1;
653         }
654
655         path = lp_pathname(snum);
656
657         /* see if we have sufficient disk space */
658         if (lp_minprintspace(snum)) {
659                 SMB_BIG_UINT dspace, dsize;
660                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
661                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
662                         errno = ENOSPC;
663                         return -1;
664                 }
665         }
666
667         /* for autoloaded printers, check that the printcap entry still exists */
668         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
669                 errno = ENOENT;
670                 return -1;
671         }
672
673         /* create the database entry */
674         ZERO_STRUCT(pjob);
675         pjob.pid = local_pid;
676         pjob.sysjob = -1;
677         pjob.fd = -1;
678         pjob.starttime = time(NULL);
679         pjob.status = LPQ_QUEUED;
680         pjob.size = 0;
681         pjob.spooled = False;
682         pjob.smbjob = True;
683
684         fstrcpy(pjob.jobname, jobname);
685
686         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
687                 fstrcpy(pjob.user, vuser->user.smb_name);
688         } else {
689                 fstrcpy(pjob.user, uidtoname(user->uid));
690         }
691
692         fstrcpy(pjob.qname, lp_servicename(snum));
693
694         /* lock the database */
695         tdb_lock_bystring(tdb, "INFO/nextjob");
696
697  next_jobnum:
698         next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
699         if (next_jobid == -1) next_jobid = 1;
700
701         for (jobid = next_jobid+1; jobid != next_jobid; ) {
702                 if (!print_job_exists(jobid)) break;
703                 jobid = (jobid + 1) % PRINT_MAX_JOBID;
704                 if (jobid == 0) jobid = 1;
705         }
706         if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
707                 jobid = -1;
708                 goto fail;
709         }
710
711         tdb_store_int(tdb, "INFO/nextjob", jobid);
712
713         /* we have a job entry - now create the spool file 
714
715            we unlink first to cope with old spool files and also to beat
716            a symlink security hole - it allows us to use O_EXCL 
717            There may be old spool files owned by other users lying around.
718         */
719         slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d", 
720                  path, PRINT_SPOOL_PREFIX, jobid);
721         if (unlink(pjob.filename) == -1 && errno != ENOENT) {
722                 goto next_jobnum;
723         }
724         pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
725         if (pjob.fd == -1) goto fail;
726
727         print_job_store(jobid, &pjob);
728
729         tdb_unlock_bystring(tdb, "INFO/nextjob");
730
731         /*
732          * If the printer is marked as postscript output a leading
733          * file identifier to ensure the file is treated as a raw
734          * postscript file.
735          * This has a similar effect as CtrlD=0 in WIN.INI file.
736          * tim@fsg.com 09/06/94
737          */
738         if (lp_postscript(snum)) {
739                 print_job_write(jobid, "%!\n",3);
740         }
741
742         return jobid;
743
744  fail:
745         if (jobid != -1) {
746                 tdb_delete(tdb, print_key(jobid));
747         }
748
749         tdb_unlock_bystring(tdb, "INFO/nextjob");
750         return -1;
751 }
752
753 /****************************************************************************
754  Print a file - called on closing the file. This spools the job.
755 ****************************************************************************/
756
757 BOOL print_job_end(int jobid)
758 {
759         struct printjob *pjob = print_job_find(jobid);
760         int snum;
761         SMB_STRUCT_STAT sbuf;
762         pstring current_directory;
763         pstring print_directory;
764         char *wd, *p;
765         pstring jobname;
766
767         if (!pjob)
768                 return False;
769
770         if (pjob->spooled || pjob->pid != local_pid)
771                 return False;
772
773         snum = print_job_snum(jobid);
774
775         if (sys_fstat(pjob->fd, &sbuf) == 0)
776                 pjob->size = sbuf.st_size;
777
778         close(pjob->fd);
779         pjob->fd = -1;
780
781         if (pjob->size == 0) {
782                 /* don't bother spooling empty files */
783                 unlink(pjob->filename);
784                 tdb_delete(tdb, print_key(jobid));
785                 return True;
786         }
787
788         /* we print from the directory path to give the best chance of
789            parsing the lpq output */
790         wd = sys_getwd(current_directory);
791         if (!wd)
792                 return False;           
793
794         pstrcpy(print_directory, pjob->filename);
795         p = strrchr(print_directory,'/');
796         if (!p)
797                 return False;
798         *p++ = 0;
799
800         if (chdir(print_directory) != 0)
801                 return False;
802
803         pstrcpy(jobname, pjob->jobname);
804         pstring_sub(jobname, "'", "_");
805
806         /* send it to the system spooler */
807         print_run_command(snum, 
808                           lp_printcommand(snum), NULL,
809                           "%s", p,
810                           "%J", jobname,
811                           "%f", p,
812                           NULL);
813
814         chdir(wd);
815
816         pjob->spooled = True;
817         print_job_store(jobid, pjob);
818
819         /* force update the database */
820         print_cache_flush(snum);
821         
822         return True;
823 }
824
825 /****************************************************************************
826  Check if the print queue has been updated recently enough.
827 ****************************************************************************/
828
829 static BOOL print_cache_expired(int snum)
830 {
831         fstring key;
832         time_t t2, t = time(NULL);
833         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
834         t2 = tdb_fetch_int(tdb, key);
835         if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
836                 return True;
837         }
838         return False;
839 }
840
841 /* utility fn to enumerate the print queue */
842 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
843 {
844         struct traverse_struct *ts = (struct traverse_struct *)state;
845         struct printjob pjob;
846         int i, jobid;
847
848         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
849         memcpy(&jobid, key.dptr, sizeof(jobid));
850         memcpy(&pjob,  data.dptr, sizeof(pjob));
851
852         /* maybe it isn't for this queue */
853         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
854
855         if (ts->qcount >= ts->maxcount) return 0;
856
857         i = ts->qcount;
858
859         ts->queue[i].job = jobid;
860         ts->queue[i].size = pjob.size;
861         ts->queue[i].status = pjob.status;
862         ts->queue[i].priority = 1;
863         ts->queue[i].time = pjob.starttime;
864         fstrcpy(ts->queue[i].user, pjob.user);
865         fstrcpy(ts->queue[i].file, pjob.jobname);
866
867         ts->qcount++;
868
869         return 0;
870 }
871
872 struct traverse_count_struct {
873         int snum, count;
874 };
875
876 /* utility fn to count the number of entries in the print queue */
877 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
878 {
879         struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
880         struct printjob pjob;
881         int jobid;
882
883         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
884         memcpy(&jobid, key.dptr, sizeof(jobid));
885         memcpy(&pjob,  data.dptr, sizeof(pjob));
886
887         /* maybe it isn't for this queue */
888         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
889
890         ts->count++;
891
892         return 0;
893 }
894
895 /****************************************************************************
896 get a printer queue listing
897 ****************************************************************************/
898 int print_queue_status(int snum, 
899                        print_queue_struct **queue,
900                        print_status_struct *status)
901 {
902         struct traverse_struct tstruct;
903         struct traverse_count_struct tsc;
904         fstring keystr;
905         TDB_DATA data, key;
906
907         /* make sure the database is up to date */
908         if (print_cache_expired(snum)) print_queue_update(snum);
909         
910         /*
911          * Count the number of entries.
912          */
913         tsc.count = 0;
914         tsc.snum = snum;
915         tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
916
917         /* Allocate the queue size. */
918         if (( tstruct.queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*tsc.count))
919                                 == NULL)
920                 return 0;
921
922         /*
923          * Fill in the queue.
924          * We need maxcount as the queue size may have changed between
925          * the two calls to tdb_traverse.
926          */
927         tstruct.qcount = 0;
928         tstruct.maxcount = tsc.count;
929         tstruct.snum = snum;
930
931         tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
932
933         /* also fetch the queue status */
934         ZERO_STRUCTP(status);
935         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
936         key.dptr = keystr;
937         key.dsize = strlen(keystr);
938         data = tdb_fetch(tdb, key);
939         if (data.dptr) {
940                 if (data.dsize == sizeof(*status)) {
941                         memcpy(status, data.dptr, sizeof(*status));
942                 }
943                 free(data.dptr);
944         }
945
946         *queue = tstruct.queue;
947         return tstruct.qcount;
948 }
949
950
951 /****************************************************************************
952 turn a queue name into a snum
953 ****************************************************************************/
954 int print_queue_snum(char *qname)
955 {
956         int snum = lp_servicenumber(qname);
957         if (snum == -1 || !lp_print_ok(snum)) return -1;
958         return snum;
959 }
960
961
962 /****************************************************************************
963  pause a queue
964 ****************************************************************************/
965 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
966 {
967         int ret;
968         
969         if (!user) return False;
970         
971         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
972                 *errcode = ERROR_ACCESS_DENIED;
973                 return False;
974         }
975
976         ret = print_run_command(snum, lp_queuepausecommand(snum), NULL, 
977                                 NULL);
978
979         /* force update the database */
980         print_cache_flush(snum);
981
982         return ret == 0;
983 }
984
985 /****************************************************************************
986  resume a queue
987 ****************************************************************************/
988 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
989 {
990         int ret;
991
992         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
993                 *errcode = ERROR_ACCESS_DENIED;
994                 return False;
995         }
996
997         ret = print_run_command(snum, lp_queueresumecommand(snum), NULL, 
998                                 NULL);
999
1000         /* force update the database */
1001         print_cache_flush(snum);
1002
1003         return ret == 0;
1004 }
1005
1006 /****************************************************************************
1007  purge a queue - implemented by deleting all jobs that we can delete
1008 ****************************************************************************/
1009 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1010 {
1011         print_queue_struct *queue;
1012         print_status_struct status;
1013         int njobs, i;
1014
1015         njobs = print_queue_status(snum, &queue, &status);
1016         for (i=0;i<njobs;i++) {
1017                 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1018                         print_job_delete1(queue[i].job);
1019                 }
1020         }
1021
1022         print_cache_flush(snum);
1023         safe_free(queue);
1024
1025         return True;
1026 }
1027
1028 /****************************************************************************
1029  Periodically run a status on all the queues to ensure the tdb doesn't grow.
1030  Note that this will have no effect if the client is doing its own status
1031  queries. This code is here to clean up jobs submitted by non-Windows printer
1032  clients (eg. smbclient) that never do a status check.
1033 ****************************************************************************/
1034
1035 void process_print_queue(time_t t)
1036 {
1037         static time_t last_check_time;
1038         int services = lp_numservices();
1039         print_queue_struct *queue;
1040         print_status_struct status;
1041         int snum;
1042
1043         if ((t != (time_t)-1) && ((t - last_check_time) < lp_lpqcachetime()))
1044                 return;
1045
1046         last_check_time = t;
1047
1048         for (snum = 0; snum < services; snum++) {
1049                 if (lp_snum_ok(snum) && lp_print_ok(snum) && lp_browseable(snum)) {
1050                         (void)print_queue_status(snum, &queue,&status);
1051                         safe_free(queue);
1052                 }
1053         }
1054 }
1055 #undef OLD_NTDOMAIN