Fix for growing printing.tdb by adding check on job creation.
[ira/wip.git] / source3 / 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 2
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         status.qcount = qcount;
385         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
386         data.dptr = (void *)&status;
387         data.dsize = sizeof(status);
388         key.dptr = keystr;
389         key.dsize = strlen(keystr);
390         tdb_store(tdb, key, data, TDB_REPLACE); 
391
392         /*
393          * Update the cache time again. We want to do this call
394          * as little as possible...
395          */
396
397         slprintf(keystr, sizeof(keystr), "CACHE/%s", lp_servicename(snum));
398         tdb_store_int(tdb, keystr, (int)time(NULL));
399 }
400
401 /****************************************************************************
402 check if a jobid is valid. It is valid if it exists in the database
403 ****************************************************************************/
404 BOOL print_job_exists(int jobid)
405 {
406         return tdb_exists(tdb, print_key(jobid));
407 }
408
409
410 /****************************************************************************
411 work out which service a jobid is for
412 note that we have to look up by queue name to ensure that it works for 
413 other than the process that started the job
414 ****************************************************************************/
415 int print_job_snum(int jobid)
416 {
417         struct printjob *pjob = print_job_find(jobid);
418         if (!pjob) return -1;
419
420         return lp_servicenumber(pjob->qname);
421 }
422
423 /****************************************************************************
424 give the fd used for a jobid
425 ****************************************************************************/
426 int print_job_fd(int jobid)
427 {
428         struct printjob *pjob = print_job_find(jobid);
429         if (!pjob) return -1;
430         /* don't allow another process to get this info - it is meaningless */
431         if (pjob->pid != local_pid) return -1;
432         return pjob->fd;
433 }
434
435 /****************************************************************************
436 give the filename used for a jobid
437 only valid for the process doing the spooling and when the job
438 has not been spooled
439 ****************************************************************************/
440 char *print_job_fname(int jobid)
441 {
442         struct printjob *pjob = print_job_find(jobid);
443         if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
444         return pjob->filename;
445 }
446
447
448 /****************************************************************************
449 set the place in the queue for a job
450 ****************************************************************************/
451 BOOL print_job_set_place(int jobid, int place)
452 {
453         DEBUG(2,("print_job_set_place not implemented yet\n"));
454         return False;
455 }
456
457 /****************************************************************************
458 set the name of a job. Only possible for owner
459 ****************************************************************************/
460 BOOL print_job_set_name(int jobid, char *name)
461 {
462         struct printjob *pjob = print_job_find(jobid);
463         if (!pjob || pjob->pid != local_pid) return False;
464
465         fstrcpy(pjob->jobname, name);
466         return print_job_store(jobid, pjob);
467 }
468
469
470 /****************************************************************************
471 delete a print job - don't update queue
472 ****************************************************************************/
473 static BOOL print_job_delete1(int jobid)
474 {
475         struct printjob *pjob = print_job_find(jobid);
476         int snum;
477
478         if (!pjob) return False;
479
480         snum = print_job_snum(jobid);
481
482         if (pjob->spooled && pjob->sysjob != -1) {
483                 /* need to delete the spooled entry */
484                 fstring jobstr;
485                 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
486                 print_run_command(snum, 
487                                   lp_lprmcommand(snum), NULL,
488                                   "%j", jobstr,
489                                   "%T", http_timestring(pjob->starttime),
490                                   NULL);
491         }
492
493         return True;
494 }
495
496 /****************************************************************************
497 return true if the current user owns the print job
498 ****************************************************************************/
499 static BOOL is_owner(struct current_user *user, int jobid)
500 {
501         struct printjob *pjob = print_job_find(jobid);
502         user_struct *vuser;
503
504         if (!pjob || !user) return False;
505
506         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
507                 return strequal(pjob->user, vuser->user.smb_name);
508         } else {
509                 return strequal(pjob->user, uidtoname(user->uid));
510         }
511 }
512
513 /****************************************************************************
514 delete a print job
515 ****************************************************************************/
516 BOOL print_job_delete(struct current_user *user, int jobid)
517 {
518         int snum = print_job_snum(jobid);
519         BOOL owner;
520         
521         if (!user) return False;
522
523         owner = is_owner(user, jobid);
524         
525         /* Check access against security descriptor or whether the user
526            owns their job. */
527
528         if (!owner && 
529             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
530                 DEBUG(3, ("delete denied by security descriptor\n"));
531                 return False;
532         }
533
534         if (!print_job_delete1(jobid)) return False;
535
536         /* force update the database and say the delete failed if the
537            job still exists */
538
539         print_queue_update(snum);
540
541         return !print_job_exists(jobid);
542 }
543
544
545 /****************************************************************************
546 pause a job
547 ****************************************************************************/
548 BOOL print_job_pause(struct current_user *user, int jobid)
549 {
550         struct printjob *pjob = print_job_find(jobid);
551         int snum, ret = -1;
552         fstring jobstr;
553         BOOL owner;
554         
555
556         if (!pjob || !user) return False;
557
558         if (!pjob->spooled || pjob->sysjob == -1) return False;
559
560         snum = print_job_snum(jobid);
561         owner = is_owner(user, jobid);
562
563         if (!owner &&
564             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
565                 DEBUG(3, ("pause denied by security descriptor\n"));
566                 return False;
567         }
568
569         /* need to pause the spooled entry */
570         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
571         ret = print_run_command(snum, 
572                                 lp_lppausecommand(snum), NULL,
573                                 "%j", jobstr,
574                                 NULL);
575
576         /* force update the database */
577         print_cache_flush(snum);
578
579         /* how do we tell if this succeeded? */
580         return ret == 0;
581 }
582
583 /****************************************************************************
584 resume a job
585 ****************************************************************************/
586 BOOL print_job_resume(struct current_user *user, int jobid)
587 {
588         struct printjob *pjob = print_job_find(jobid);
589         int snum, ret;
590         fstring jobstr;
591         BOOL owner;
592         
593         if (!pjob || !user) return False;
594
595         if (!pjob->spooled || pjob->sysjob == -1) return False;
596
597         snum = print_job_snum(jobid);
598         owner = is_owner(user, jobid);
599
600         if (!is_owner(user, jobid) &&
601             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
602                 DEBUG(3, ("resume denied by security descriptor\n"));
603                 return False;
604         }
605
606         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
607         ret = print_run_command(snum, 
608                                 lp_lpresumecommand(snum), NULL,
609                                 "%j", jobstr,
610                                 NULL);
611
612         /* force update the database */
613         print_cache_flush(snum);
614
615         /* how do we tell if this succeeded? */
616         return ret == 0;
617 }
618
619 /****************************************************************************
620 write to a print file
621 ****************************************************************************/
622 int print_job_write(int jobid, const char *buf, int size)
623 {
624         int fd;
625
626         fd = print_job_fd(jobid);
627         if (fd == -1) return -1;
628
629         return write(fd, buf, size);
630 }
631
632 /****************************************************************************
633  Check if the print queue has been updated recently enough.
634 ****************************************************************************/
635
636 static BOOL print_cache_expired(int snum)
637 {
638         fstring key;
639         time_t t2, t = time(NULL);
640         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
641         t2 = tdb_fetch_int(tdb, key);
642         if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
643                 return True;
644         }
645         return False;
646 }
647
648 /****************************************************************************
649  Determine the number of jobs in a queue.
650 ****************************************************************************/
651
652 static int print_queue_length(int snum)
653 {
654         fstring keystr;
655         TDB_DATA data, key;
656         print_status_struct status;
657
658         /* make sure the database is up to date */
659         if (print_cache_expired(snum)) print_queue_update(snum);
660
661         /* also fetch the queue status */
662         ZERO_STRUCTP(&status);
663         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
664         key.dptr = keystr;
665         key.dsize = strlen(keystr);
666         data = tdb_fetch(tdb, key);
667         if (data.dptr) {
668                 if (data.dsize == sizeof(status)) {
669                         memcpy(&status, data.dptr, sizeof(status));
670                 }
671                 free(data.dptr);
672         }
673         return status.qcount;
674 }
675
676 /***************************************************************************
677 start spooling a job - return the jobid
678 ***************************************************************************/
679 int print_job_start(struct current_user *user, int snum, char *jobname)
680 {
681         int jobid;
682         char *path;
683         struct printjob pjob;
684         int next_jobid;
685         user_struct *vuser;
686
687         errno = 0;
688
689         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
690                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
691                 return -1;
692         }
693
694         if (!print_time_access_check(snum)) {
695                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
696                 return -1;
697         }
698
699         path = lp_pathname(snum);
700
701         /* see if we have sufficient disk space */
702         if (lp_minprintspace(snum)) {
703                 SMB_BIG_UINT dspace, dsize;
704                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
705                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
706                         errno = ENOSPC;
707                         return -1;
708                 }
709         }
710
711         /* for autoloaded printers, check that the printcap entry still exists */
712         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
713                 errno = ENOENT;
714                 return -1;
715         }
716
717         if (print_queue_length(snum) > lp_maxprintjobs(snum)) {
718                 errno = ENOSPC;
719                 return -1;
720         }
721
722         /* create the database entry */
723         ZERO_STRUCT(pjob);
724         pjob.pid = local_pid;
725         pjob.sysjob = -1;
726         pjob.fd = -1;
727         pjob.starttime = time(NULL);
728         pjob.status = LPQ_QUEUED;
729         pjob.size = 0;
730         pjob.spooled = False;
731         pjob.smbjob = True;
732
733         fstrcpy(pjob.jobname, jobname);
734
735         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
736                 fstrcpy(pjob.user, vuser->user.smb_name);
737         } else {
738                 fstrcpy(pjob.user, uidtoname(user->uid));
739         }
740
741         fstrcpy(pjob.qname, lp_servicename(snum));
742
743         /* lock the database */
744         tdb_lock_bystring(tdb, "INFO/nextjob");
745
746  next_jobnum:
747         next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
748         if (next_jobid == -1) next_jobid = 1;
749
750         for (jobid = next_jobid+1; jobid != next_jobid; ) {
751                 if (!print_job_exists(jobid)) break;
752                 jobid = (jobid + 1) % PRINT_MAX_JOBID;
753                 if (jobid == 0) jobid = 1;
754         }
755         if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
756                 jobid = -1;
757                 goto fail;
758         }
759
760         tdb_store_int(tdb, "INFO/nextjob", jobid);
761
762         /* we have a job entry - now create the spool file 
763
764            we unlink first to cope with old spool files and also to beat
765            a symlink security hole - it allows us to use O_EXCL 
766            There may be old spool files owned by other users lying around.
767         */
768         slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d", 
769                  path, PRINT_SPOOL_PREFIX, jobid);
770         if (unlink(pjob.filename) == -1 && errno != ENOENT) {
771                 goto next_jobnum;
772         }
773         pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
774         if (pjob.fd == -1) goto fail;
775
776         print_job_store(jobid, &pjob);
777
778         tdb_unlock_bystring(tdb, "INFO/nextjob");
779
780         /*
781          * If the printer is marked as postscript output a leading
782          * file identifier to ensure the file is treated as a raw
783          * postscript file.
784          * This has a similar effect as CtrlD=0 in WIN.INI file.
785          * tim@fsg.com 09/06/94
786          */
787         if (lp_postscript(snum)) {
788                 print_job_write(jobid, "%!\n",3);
789         }
790
791         return jobid;
792
793  fail:
794         if (jobid != -1) {
795                 tdb_delete(tdb, print_key(jobid));
796         }
797
798         tdb_unlock_bystring(tdb, "INFO/nextjob");
799         return -1;
800 }
801
802 /****************************************************************************
803  Print a file - called on closing the file. This spools the job.
804 ****************************************************************************/
805
806 BOOL print_job_end(int jobid)
807 {
808         struct printjob *pjob = print_job_find(jobid);
809         int snum;
810         SMB_STRUCT_STAT sbuf;
811         pstring current_directory;
812         pstring print_directory;
813         char *wd, *p;
814         pstring jobname;
815
816         if (!pjob)
817                 return False;
818
819         if (pjob->spooled || pjob->pid != local_pid)
820                 return False;
821
822         snum = print_job_snum(jobid);
823
824         if (sys_fstat(pjob->fd, &sbuf) == 0)
825                 pjob->size = sbuf.st_size;
826
827         close(pjob->fd);
828         pjob->fd = -1;
829
830         if (pjob->size == 0) {
831                 /* don't bother spooling empty files */
832                 unlink(pjob->filename);
833                 tdb_delete(tdb, print_key(jobid));
834                 return True;
835         }
836
837         /* we print from the directory path to give the best chance of
838            parsing the lpq output */
839         wd = sys_getwd(current_directory);
840         if (!wd)
841                 return False;           
842
843         pstrcpy(print_directory, pjob->filename);
844         p = strrchr(print_directory,'/');
845         if (!p)
846                 return False;
847         *p++ = 0;
848
849         if (chdir(print_directory) != 0)
850                 return False;
851
852         pstrcpy(jobname, pjob->jobname);
853         pstring_sub(jobname, "'", "_");
854
855         /* send it to the system spooler */
856         print_run_command(snum, 
857                           lp_printcommand(snum), NULL,
858                           "%s", p,
859                           "%J", jobname,
860                           "%f", p,
861                           NULL);
862
863         chdir(wd);
864
865         pjob->spooled = True;
866         print_job_store(jobid, pjob);
867
868         /* force update the database */
869         print_cache_flush(snum);
870         
871         return True;
872 }
873
874 /* utility fn to enumerate the print queue */
875 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
876 {
877         struct traverse_struct *ts = (struct traverse_struct *)state;
878         struct printjob pjob;
879         int i, jobid;
880
881         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
882         memcpy(&jobid, key.dptr, sizeof(jobid));
883         memcpy(&pjob,  data.dptr, sizeof(pjob));
884
885         /* maybe it isn't for this queue */
886         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
887
888         if (ts->qcount >= ts->maxcount) return 0;
889
890         i = ts->qcount;
891
892         ts->queue[i].job = jobid;
893         ts->queue[i].size = pjob.size;
894         ts->queue[i].status = pjob.status;
895         ts->queue[i].priority = 1;
896         ts->queue[i].time = pjob.starttime;
897         fstrcpy(ts->queue[i].user, pjob.user);
898         fstrcpy(ts->queue[i].file, pjob.jobname);
899
900         ts->qcount++;
901
902         return 0;
903 }
904
905 struct traverse_count_struct {
906         int snum, count;
907 };
908
909 /* utility fn to count the number of entries in the print queue */
910 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
911 {
912         struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
913         struct printjob pjob;
914         int jobid;
915
916         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
917         memcpy(&jobid, key.dptr, sizeof(jobid));
918         memcpy(&pjob,  data.dptr, sizeof(pjob));
919
920         /* maybe it isn't for this queue */
921         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
922
923         ts->count++;
924
925         return 0;
926 }
927
928 /****************************************************************************
929 get a printer queue listing
930 ****************************************************************************/
931 int print_queue_status(int snum, 
932                        print_queue_struct **queue,
933                        print_status_struct *status)
934 {
935         struct traverse_struct tstruct;
936         struct traverse_count_struct tsc;
937         fstring keystr;
938         TDB_DATA data, key;
939
940         /* make sure the database is up to date */
941         if (print_cache_expired(snum)) print_queue_update(snum);
942         
943         /*
944          * Count the number of entries.
945          */
946         tsc.count = 0;
947         tsc.snum = snum;
948         tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
949
950         /* Allocate the queue size. */
951         if (( tstruct.queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*tsc.count))
952                                 == NULL)
953                 return 0;
954
955         /*
956          * Fill in the queue.
957          * We need maxcount as the queue size may have changed between
958          * the two calls to tdb_traverse.
959          */
960         tstruct.qcount = 0;
961         tstruct.maxcount = tsc.count;
962         tstruct.snum = snum;
963
964         tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
965
966         /* also fetch the queue status */
967         ZERO_STRUCTP(status);
968         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
969         key.dptr = keystr;
970         key.dsize = strlen(keystr);
971         data = tdb_fetch(tdb, key);
972         if (data.dptr) {
973                 if (data.dsize == sizeof(*status)) {
974                         memcpy(status, data.dptr, sizeof(*status));
975                 }
976                 free(data.dptr);
977         }
978
979         *queue = tstruct.queue;
980         return tstruct.qcount;
981 }
982
983
984 /****************************************************************************
985 turn a queue name into a snum
986 ****************************************************************************/
987 int print_queue_snum(char *qname)
988 {
989         int snum = lp_servicenumber(qname);
990         if (snum == -1 || !lp_print_ok(snum)) return -1;
991         return snum;
992 }
993
994
995 /****************************************************************************
996  pause a queue
997 ****************************************************************************/
998 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
999 {
1000         int ret;
1001         
1002         if (!user) return False;
1003         
1004         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1005                 *errcode = ERROR_ACCESS_DENIED;
1006                 return False;
1007         }
1008
1009         ret = print_run_command(snum, lp_queuepausecommand(snum), NULL, 
1010                                 NULL);
1011
1012         /* force update the database */
1013         print_cache_flush(snum);
1014
1015         return ret == 0;
1016 }
1017
1018 /****************************************************************************
1019  resume a queue
1020 ****************************************************************************/
1021 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1022 {
1023         int ret;
1024
1025         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1026                 *errcode = ERROR_ACCESS_DENIED;
1027                 return False;
1028         }
1029
1030         ret = print_run_command(snum, lp_queueresumecommand(snum), NULL, 
1031                                 NULL);
1032
1033         /* force update the database */
1034         print_cache_flush(snum);
1035
1036         return ret == 0;
1037 }
1038
1039 /****************************************************************************
1040  purge a queue - implemented by deleting all jobs that we can delete
1041 ****************************************************************************/
1042 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1043 {
1044         print_queue_struct *queue;
1045         print_status_struct status;
1046         int njobs, i;
1047
1048         njobs = print_queue_status(snum, &queue, &status);
1049         for (i=0;i<njobs;i++) {
1050                 if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
1051                         print_job_delete1(queue[i].job);
1052                 }
1053         }
1054
1055         print_cache_flush(snum);
1056         safe_free(queue);
1057
1058         return True;
1059 }
1060 #undef OLD_NTDOMAIN