Changes from APPLIANCE_HEAD:
[garming/samba-autobuild/.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
25 extern int DEBUGLEVEL;
26
27 /* 
28    the printing backend revolves around a tdb database that stores the
29    SMB view of the print queue 
30    
31    The key for this database is a jobid - a internally generated number that
32    uniquely identifies a print job
33
34    reading the print queue involves two steps:
35      - possibly running lpq and updating the internal database from that
36      - reading entries from the database
37
38    jobids are assigned when a job starts spooling. 
39 */
40
41 struct printjob {
42         pid_t pid; /* which process launched the job */
43         int sysjob; /* the system (lp) job number */
44         int fd; /* file descriptor of open file if open */
45         time_t starttime; /* when the job started spooling */
46         int status; /* the status of this job */
47         size_t size; /* the size of the job so far */
48         BOOL spooled; /* has it been sent to the spooler yet? */
49         BOOL smbjob; /* set if the job is a SMB job */
50         fstring filename; /* the filename used to spool the file */
51         fstring jobname; /* the job name given to us by the client */
52         fstring user; /* the user who started the job */
53         fstring qname; /* name of the print queue the job was sent to */
54 };
55
56 /* the open printing.tdb database */
57 static TDB_CONTEXT *tdb;
58 static pid_t local_pid;
59
60 #define PRINT_MAX_JOBID 10000
61 #define UNIX_JOB_START PRINT_MAX_JOBID
62
63 #define PRINT_SPOOL_PREFIX "smbprn."
64 #define PRINT_DATABASE_VERSION 2
65
66 static int get_queue_status(int, print_status_struct *);
67
68 /****************************************************************************
69 initialise the printing backend. Called once at startup. 
70 Does not survive a fork
71 ****************************************************************************/
72 BOOL print_backend_init(void)
73 {
74         char *sversion = "INFO/version";
75
76         if (tdb && local_pid == sys_getpid()) return True;
77         tdb = tdb_open(lock_path("printing.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
78         if (!tdb) {
79                 DEBUG(0,("Failed to open printing backend database\n"));
80         }
81         local_pid = sys_getpid();
82
83         /* handle a Samba upgrade */
84         tdb_lock_bystring(tdb, sversion);
85         if (tdb_fetch_int(tdb, sversion) != PRINT_DATABASE_VERSION) {
86                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
87                 tdb_store_int(tdb, sversion, PRINT_DATABASE_VERSION);
88         }
89         tdb_unlock_bystring(tdb, sversion);
90
91         return nt_printing_init();
92 }
93
94 /****************************************************************************
95 useful function to generate a tdb key
96 ****************************************************************************/
97 static TDB_DATA print_key(int jobid)
98 {
99         static int j;
100         TDB_DATA ret;
101
102         j = jobid;
103         ret.dptr = (void *)&j;
104         ret.dsize = sizeof(j);
105         return ret;
106 }
107
108 /****************************************************************************
109 useful function to find a print job in the database
110 ****************************************************************************/
111 static struct printjob *print_job_find(int jobid)
112 {
113         static struct printjob pjob;
114         TDB_DATA ret;
115
116         ret = tdb_fetch(tdb, print_key(jobid));
117         if (!ret.dptr || ret.dsize != sizeof(pjob)) return NULL;
118
119         memcpy(&pjob, ret.dptr, sizeof(pjob));
120         free(ret.dptr);
121         return &pjob;
122 }
123
124 /****************************************************************************
125 store a job structure back to the database
126 ****************************************************************************/
127 static BOOL print_job_store(int jobid, struct printjob *pjob)
128 {
129         TDB_DATA d;
130         d.dptr = (void *)pjob;
131         d.dsize = sizeof(*pjob);
132
133         return (tdb_store(tdb, print_key(jobid), d, TDB_REPLACE) == 0);
134 }
135
136 /****************************************************************************
137 run a given print command 
138 a null terminated list of value/substitute pairs is provided
139 for local substitution strings
140 ****************************************************************************/
141 static int print_run_command(int snum,char *command, 
142                              char *outfile,
143                              ...)
144 {
145         pstring syscmd;
146         char *p, *arg;
147         int ret;
148         va_list ap;
149
150         if (!command || !*command) return -1;
151
152         if (!VALID_SNUM(snum)) {
153                 DEBUG(0,("Invalid snum %d for command %s\n", snum, command));
154                 return -1;
155         }
156
157         pstrcpy(syscmd, command);
158
159         va_start(ap, outfile);
160         while ((arg = va_arg(ap, char *))) {
161                 char *value = va_arg(ap,char *);
162                 pstring_sub(syscmd, arg, value);
163         }
164         va_end(ap);
165   
166         p = PRINTERNAME(snum);
167   
168         pstring_sub(syscmd, "%p", p);
169         standard_sub_snum(snum,syscmd);
170
171         /* Convert script args to unix-codepage */
172         dos_to_unix(syscmd, True);
173         ret = smbrun(syscmd,outfile,False);
174
175         DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
176
177         return ret;
178 }
179
180
181 /****************************************************************************
182 parse a file name from the system spooler to generate a jobid
183 ****************************************************************************/
184 static int print_parse_jobid(char *fname)
185 {
186         int jobid;
187
188         if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) return -1;
189         fname += strlen(PRINT_SPOOL_PREFIX);
190
191         jobid = atoi(fname);
192         if (jobid <= 0) return -1;
193
194         return jobid;
195 }
196
197
198 /****************************************************************************
199 list a unix job in the print database
200 ****************************************************************************/
201 static void print_unix_job(int snum, print_queue_struct *q)
202 {
203         int jobid = q->job + UNIX_JOB_START;
204         struct printjob pj, *old_pj;
205
206         /* Preserve the timestamp on an existing unix print job */
207
208         old_pj = print_job_find(jobid);
209
210         ZERO_STRUCT(pj);
211
212         pj.pid = (pid_t)-1;
213         pj.sysjob = q->job;
214         pj.fd = -1;
215         pj.starttime = old_pj ? old_pj->starttime : q->time;
216         pj.status = q->status;
217         pj.size = q->size;
218         pj.spooled = True;
219         pj.smbjob = False;
220         fstrcpy(pj.filename, "");
221         fstrcpy(pj.jobname, q->file);
222         fstrcpy(pj.user, q->user);
223         fstrcpy(pj.qname, lp_servicename(snum));
224
225         print_job_store(jobid, &pj);
226 }
227
228
229 struct traverse_struct {
230         print_queue_struct *queue;
231         int qcount, snum, maxcount, total_jobs;
232 };
233
234 /* utility fn to delete any jobs that are no longer active */
235 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
236 {
237         struct traverse_struct *ts = (struct traverse_struct *)state;
238         struct printjob pjob;
239         int i, jobid;
240
241         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
242         memcpy(&jobid, key.dptr, sizeof(jobid));
243         memcpy(&pjob,  data.dptr, sizeof(pjob));
244
245         if (strcmp(lp_servicename(ts->snum), pjob.qname)) {
246                 /* this isn't for the queue we are looking at */
247                 ts->total_jobs++;
248                 return 0;
249         }
250
251         if (!pjob.smbjob) {
252                 /* remove a unix job if it isn't in the system queue any more */
253
254                 for (i=0;i<ts->qcount;i++) {
255                         if (jobid == ts->queue[i].job + UNIX_JOB_START) break;
256                 }
257                 if (i == ts->qcount)
258                         tdb_delete(tdb, key);
259                 else
260                         ts->total_jobs++;
261                 return 0;
262         }
263
264         /* maybe it hasn't been spooled yet */
265         if (!pjob.spooled) {
266                 /* if a job is not spooled and the process doesn't
267                    exist then kill it. This cleans up after smbd
268                    deaths */
269                 if (!process_exists(pjob.pid))
270                         tdb_delete(tdb, key);
271                 else
272                         ts->total_jobs++;
273                 return 0;
274         }
275
276         for (i=0;i<ts->qcount;i++) {
277                 int qid = print_parse_jobid(ts->queue[i].file);
278                 if (jobid == qid) break;
279         }
280         
281         /* The job isn't in the system queue - we have to assume it has
282            completed, so delete the database entry. */
283
284         if (i == ts->qcount) {
285                 time_t cur_t = time(NULL);
286
287                 /* A race can occur between the time a job is spooled and
288                    when it appears in the lpq output.  This happens when
289                    the job is added to printing.tdb when another smbd
290                    running print_queue_update() has completed a lpq and
291                    is currently traversing the printing tdb and deleting jobs.
292                    A workaround is to not delete the job if it has been 
293                    submitted less than lp_lpqcachetime() seconds ago. */
294
295                 if ((cur_t - pjob.starttime) > lp_lpqcachetime())
296                         tdb_delete(t, key);
297                 else
298                         ts->total_jobs++;
299         }
300         else
301                 ts->total_jobs++;
302
303         return 0;
304 }
305
306 /****************************************************************************
307 check if the print queue has been updated recently enough
308 ****************************************************************************/
309 static void print_cache_flush(int snum)
310 {
311         fstring key;
312         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
313         dos_to_unix(key, True);                /* Convert key to unix-codepage */
314         tdb_store_int(tdb, key, -1);
315 }
316
317 /****************************************************************************
318 update the internal database from the system print queue for a queue
319 ****************************************************************************/
320 static void print_queue_update(int snum)
321 {
322         char *path = lp_pathname(snum);
323         char *cmd = lp_lpqcommand(snum);
324         char **qlines;
325         pstring tmp_file;
326         int numlines, i, qcount;
327         print_queue_struct *queue = NULL;
328         print_status_struct status;
329         print_status_struct old_status;
330         struct printjob *pjob;
331         struct traverse_struct tstruct;
332         fstring keystr, printer_name;
333         TDB_DATA data, key;
334               
335         /* Convert printer name (i.e. share name) to unix-codepage for all of the 
336          * following tdb key generation */
337         fstrcpy(printer_name, lp_servicename(snum));
338         dos_to_unix(printer_name, True);
339         
340         /*
341          * Update the cache time FIRST ! Stops others doing this
342          * if the lpq takes a long time.
343          */
344
345         slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
346         tdb_store_int(tdb, keystr, (int)time(NULL));
347
348         slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
349
350         unlink(tmp_file);
351         print_run_command(snum, cmd, tmp_file, NULL);
352
353         numlines = 0;
354         qlines = file_lines_load(tmp_file, &numlines, True);
355         unlink(tmp_file);
356
357         /* turn the lpq output into a series of job structures */
358         qcount = 0;
359         ZERO_STRUCT(status);
360         if (numlines)
361                 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
362
363         if (queue) {
364                 for (i=0; i<numlines; i++) {
365                         /* parse the line */
366                         if (parse_lpq_entry(snum,qlines[i],
367                                             &queue[qcount],&status,qcount==0)) {
368                                 qcount++;
369                         }
370                 }               
371         }
372         file_lines_free(qlines);
373
374         DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
375                 "s" : "", printer_name));
376
377         /* Lock the queue for the database update */
378
379         slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
380         tdb_lock_bystring(tdb, keystr);
381
382         /*
383           any job in the internal database that is marked as spooled
384           and doesn't exist in the system queue is considered finished
385           and removed from the database
386
387           any job in the system database but not in the internal database 
388           is added as a unix job
389
390           fill in any system job numbers as we go
391         */
392         for (i=0; i<qcount; i++) {
393                 int jobid = print_parse_jobid(queue[i].file);
394
395                 if (jobid == -1) {
396                         /* assume its a unix print job */
397                         print_unix_job(snum, &queue[i]);
398                         continue;
399                 }
400
401                 /* we have an active SMB print job - update its status */
402                 pjob = print_job_find(jobid);
403                 if (!pjob) {
404                         /* err, somethings wrong. Probably smbd was restarted
405                            with jobs in the queue. All we can do is treat them
406                            like unix jobs. Pity. */
407                         print_unix_job(snum, &queue[i]);
408                         continue;
409                 }
410
411                 pjob->sysjob = queue[i].job;
412                 pjob->status = queue[i].status;
413
414                 print_job_store(jobid, pjob);
415         }
416
417         /* now delete any queued entries that don't appear in the
418            system queue */
419         tstruct.queue = queue;
420         tstruct.qcount = qcount;
421         tstruct.snum = snum;
422         tstruct.total_jobs = 0;
423
424         tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
425
426         safe_free(tstruct.queue);
427
428         tdb_store_int(tdb, "INFO/total_jobs", tstruct.total_jobs);
429
430         /*
431          * Get the old print status. We will use this to compare the
432          * number of jobs. If they have changed we need to send a
433          * "changed" message to the smbds.
434          */
435
436         if( qcount != get_queue_status(snum, &old_status)) {
437                 DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
438                                 old_status.qcount, qcount, printer_name ));
439                 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
440         }
441
442         /* store the new queue status structure */
443         slprintf(keystr, sizeof(keystr), "STATUS/%s", printer_name);
444     key.dptr = keystr;
445         key.dsize = strlen(keystr);
446
447         status.qcount = qcount;
448         data.dptr = (void *)&status;
449         data.dsize = sizeof(status);
450         tdb_store(tdb, key, data, TDB_REPLACE); 
451
452         /* Unlock for database update */
453
454         slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
455         tdb_unlock_bystring(tdb, keystr);
456
457         /*
458          * Update the cache time again. We want to do this call
459          * as little as possible...
460          */
461
462         slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
463         tdb_store_int(tdb, keystr, (int)time(NULL));
464 }
465
466 /****************************************************************************
467 check if a jobid is valid. It is valid if it exists in the database
468 ****************************************************************************/
469 BOOL print_job_exists(int jobid)
470 {
471         return tdb_exists(tdb, print_key(jobid));
472 }
473
474
475 /****************************************************************************
476 work out which service a jobid is for
477 note that we have to look up by queue name to ensure that it works for 
478 other than the process that started the job
479 ****************************************************************************/
480 int print_job_snum(int jobid)
481 {
482         struct printjob *pjob = print_job_find(jobid);
483         if (!pjob) return -1;
484
485         return lp_servicenumber(pjob->qname);
486 }
487
488 /****************************************************************************
489 give the fd used for a jobid
490 ****************************************************************************/
491 int print_job_fd(int jobid)
492 {
493         struct printjob *pjob = print_job_find(jobid);
494         if (!pjob) return -1;
495         /* don't allow another process to get this info - it is meaningless */
496         if (pjob->pid != local_pid) return -1;
497         return pjob->fd;
498 }
499
500 /****************************************************************************
501 give the filename used for a jobid
502 only valid for the process doing the spooling and when the job
503 has not been spooled
504 ****************************************************************************/
505 char *print_job_fname(int jobid)
506 {
507         struct printjob *pjob = print_job_find(jobid);
508         if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
509         return pjob->filename;
510 }
511
512
513 /****************************************************************************
514 set the place in the queue for a job
515 ****************************************************************************/
516 BOOL print_job_set_place(int jobid, int place)
517 {
518         DEBUG(2,("print_job_set_place not implemented yet\n"));
519         return False;
520 }
521
522 /****************************************************************************
523 set the name of a job. Only possible for owner
524 ****************************************************************************/
525 BOOL print_job_set_name(int jobid, char *name)
526 {
527         struct printjob *pjob = print_job_find(jobid);
528         if (!pjob || pjob->pid != local_pid) return False;
529
530         fstrcpy(pjob->jobname, name);
531         return print_job_store(jobid, pjob);
532 }
533
534
535 /****************************************************************************
536 delete a print job - don't update queue
537 ****************************************************************************/
538 static BOOL print_job_delete1(int jobid)
539 {
540         struct printjob *pjob = print_job_find(jobid);
541         int snum, result = 0;
542
543         if (!pjob) return False;
544
545         snum = print_job_snum(jobid);
546
547         /* Hrm - we need to be able to cope with deleting a job before it
548            has reached the spooler. */
549
550         if (pjob->sysjob == -1) {
551                 DEBUG(5, ("attempt to delete job %d not seen by lpr\n",
552                           jobid));
553         }
554
555         if (pjob->spooled && pjob->sysjob != -1) {
556                 fstring jobstr;
557                 
558                 /* need to delete the spooled entry */
559                 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
560                 result = print_run_command(
561                         snum, 
562                         lp_lprmcommand(snum), NULL,
563                         "%j", jobstr,
564                         "%T", http_timestring(pjob->starttime),
565                         NULL);
566         }
567
568         /* Delete the tdb entry if the delete suceeded or the job hasn't
569            been spooled. */
570
571         if (result == 0) {
572                 tdb_delete(tdb, print_key(jobid));
573         }
574
575         return (result == 0);
576 }
577
578 /****************************************************************************
579 return true if the current user owns the print job
580 ****************************************************************************/
581 static BOOL is_owner(struct current_user *user, int jobid)
582 {
583         struct printjob *pjob = print_job_find(jobid);
584         user_struct *vuser;
585
586         if (!pjob || !user) return False;
587
588         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
589                 return strequal(pjob->user, vuser->user.smb_name);
590         } else {
591                 return strequal(pjob->user, uidtoname(user->uid));
592         }
593 }
594
595 /****************************************************************************
596 delete a print job
597 ****************************************************************************/
598 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
599 {
600         int snum = print_job_snum(jobid);
601         char *printer_name;
602         BOOL owner;
603         
604         owner = is_owner(user, jobid);
605         
606         /* Check access against security descriptor or whether the user
607            owns their job. */
608
609         if (!owner && 
610             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
611                 DEBUG(3, ("delete denied by security descriptor\n"));
612                 *errcode = ERROR_ACCESS_DENIED;
613                 return False;
614         }
615
616         if (!print_job_delete1(jobid)) return False;
617
618         /* force update the database and say the delete failed if the
619            job still exists */
620
621         print_queue_update(snum);
622
623         /* Send a printer notify message */
624
625         printer_name = PRINTERNAME(snum);
626
627         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
628
629         return !print_job_exists(jobid);
630 }
631
632
633 /****************************************************************************
634 pause a job
635 ****************************************************************************/
636 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
637 {
638         struct printjob *pjob = print_job_find(jobid);
639         int snum, ret = -1;
640         char *printer_name;
641         fstring jobstr;
642         BOOL owner;
643         
644         if (!pjob || !user) return False;
645
646         if (!pjob->spooled || pjob->sysjob == -1) return False;
647
648         snum = print_job_snum(jobid);
649         owner = is_owner(user, jobid);
650
651         if (!owner &&
652             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
653                 DEBUG(3, ("pause denied by security descriptor\n"));
654                 *errcode = ERROR_ACCESS_DENIED;
655                 return False;
656         }
657
658         /* need to pause the spooled entry */
659         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
660         ret = print_run_command(snum, 
661                                 lp_lppausecommand(snum), NULL,
662                                 "%j", jobstr,
663                                 NULL);
664
665         if (ret != 0) {
666                 *errcode = ERROR_INVALID_PARAMETER;
667                 return False;
668         }
669
670         /* force update the database */
671         print_cache_flush(snum);
672
673         /* Send a printer notify message */
674
675         printer_name = PRINTERNAME(snum);
676
677         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
678
679         /* how do we tell if this succeeded? */
680
681         return True;
682 }
683
684 /****************************************************************************
685 resume a job
686 ****************************************************************************/
687 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
688 {
689         struct printjob *pjob = print_job_find(jobid);
690         char *printer_name;
691         int snum, ret;
692         fstring jobstr;
693         BOOL owner;
694         
695         if (!pjob || !user) return False;
696
697         if (!pjob->spooled || pjob->sysjob == -1) return False;
698
699         snum = print_job_snum(jobid);
700         owner = is_owner(user, jobid);
701
702         if (!is_owner(user, jobid) &&
703             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
704                 DEBUG(3, ("resume denied by security descriptor\n"));
705                 *errcode = ERROR_ACCESS_DENIED;
706                 return False;
707         }
708
709         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
710         ret = print_run_command(snum, 
711                                 lp_lpresumecommand(snum), NULL,
712                                 "%j", jobstr,
713                                 NULL);
714
715         if (ret != 0) {
716                 *errcode = ERROR_INVALID_PARAMETER;
717                 return False;
718         }
719
720         /* force update the database */
721         print_cache_flush(snum);
722
723         /* Send a printer notify message */
724
725         printer_name = PRINTERNAME(snum);
726
727         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
728
729         return True;
730 }
731
732 /****************************************************************************
733 write to a print file
734 ****************************************************************************/
735 int print_job_write(int jobid, const char *buf, int size)
736 {
737         int fd;
738
739         fd = print_job_fd(jobid);
740         if (fd == -1) return -1;
741
742         return write(fd, buf, size);
743 }
744
745 /****************************************************************************
746  Check if the print queue has been updated recently enough.
747 ****************************************************************************/
748
749 static BOOL print_cache_expired(int snum)
750 {
751         fstring key;
752         time_t t2, t = time(NULL);
753
754         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
755         dos_to_unix(key, True);                /* Convert key to unix-codepage */
756         t2 = tdb_fetch_int(tdb, key);
757         if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
758                 DEBUG(3, ("print cache expired\n"));
759                 return True;
760         }
761         return False;
762 }
763
764 /****************************************************************************
765  Get the queue status - do not update if db is out of date.
766 ****************************************************************************/
767 static int get_queue_status(int snum, print_status_struct *status)
768 {
769         fstring keystr;
770         TDB_DATA data, key;
771
772         ZERO_STRUCTP(status);
773         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
774         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
775         key.dptr = keystr;
776         key.dsize = strlen(keystr);
777         data = tdb_fetch(tdb, key);
778         if (data.dptr) {
779                 if (data.dsize == sizeof(print_status_struct)) {
780                         memcpy(status, data.dptr, sizeof(print_status_struct));
781                 }
782                 free(data.dptr);
783         }
784         return status->qcount;
785 }
786
787 /****************************************************************************
788  Determine the number of jobs in a queue.
789 ****************************************************************************/
790 static int print_queue_length(int snum)
791 {
792         print_status_struct status;
793
794         /* make sure the database is up to date */
795         if (print_cache_expired(snum)) print_queue_update(snum);
796
797         /* also fetch the queue status */
798         return get_queue_status(snum, &status);
799 }
800
801 /****************************************************************************
802  Determine the number of jobs in all queues.
803 ****************************************************************************/
804 static int get_total_jobs(int snum)
805 {
806         int total_jobs;
807
808         /* make sure the database is up to date */
809         if (print_cache_expired(snum)) print_queue_update(snum);
810
811         total_jobs = tdb_fetch_int(tdb, "INFO/total_jobs");
812         if (total_jobs >0)
813                 return total_jobs;
814         else
815                 return 0;
816 }
817
818 /***************************************************************************
819 start spooling a job - return the jobid
820 ***************************************************************************/
821 int print_job_start(struct current_user *user, int snum, char *jobname)
822 {
823         int jobid;
824         char *path;
825         struct printjob pjob;
826         int next_jobid;
827         user_struct *vuser;
828
829         errno = 0;
830
831         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
832                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
833                 return -1;
834         }
835
836         if (!print_time_access_check(snum)) {
837                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
838                 return -1;
839         }
840
841         path = lp_pathname(snum);
842
843         /* see if we have sufficient disk space */
844         if (lp_minprintspace(snum)) {
845                 SMB_BIG_UINT dspace, dsize;
846                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
847                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
848                         errno = ENOSPC;
849                         return -1;
850                 }
851         }
852
853         /* for autoloaded printers, check that the printcap entry still exists */
854         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
855                 errno = ENOENT;
856                 return -1;
857         }
858
859         /* Insure the maximum queue size is not violated */
860         if (lp_maxprintjobs(snum) && print_queue_length(snum) > lp_maxprintjobs(snum)) {
861                 errno = ENOSPC;
862                 return -1;
863         }
864
865         /* Insure the maximum print jobs in the system is not violated */
866         if (lp_totalprintjobs() && get_total_jobs(snum) > lp_totalprintjobs()) {
867                 errno = ENOSPC;
868                 return -1;
869         }
870
871         /* create the database entry */
872         ZERO_STRUCT(pjob);
873         pjob.pid = local_pid;
874         pjob.sysjob = -1;
875         pjob.fd = -1;
876         pjob.starttime = time(NULL);
877         pjob.status = LPQ_QUEUED;
878         pjob.size = 0;
879         pjob.spooled = False;
880         pjob.smbjob = True;
881
882         fstrcpy(pjob.jobname, jobname);
883
884         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
885                 fstrcpy(pjob.user, vuser->user.smb_name);
886         } else {
887                 fstrcpy(pjob.user, uidtoname(user->uid));
888         }
889
890         fstrcpy(pjob.qname, lp_servicename(snum));
891
892         /* lock the database */
893         tdb_lock_bystring(tdb, "INFO/nextjob");
894
895  next_jobnum:
896         next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
897         if (next_jobid == -1) next_jobid = 1;
898
899         for (jobid = next_jobid+1; jobid != next_jobid; ) {
900                 if (!print_job_exists(jobid)) break;
901                 jobid = (jobid + 1) % PRINT_MAX_JOBID;
902                 if (jobid == 0) jobid = 1;
903         }
904         if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
905                 jobid = -1;
906                 goto fail;
907         }
908
909         tdb_store_int(tdb, "INFO/nextjob", jobid);
910
911         /* we have a job entry - now create the spool file 
912
913            we unlink first to cope with old spool files and also to beat
914            a symlink security hole - it allows us to use O_EXCL 
915            There may be old spool files owned by other users lying around.
916         */
917         slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d", 
918                  path, PRINT_SPOOL_PREFIX, jobid);
919         if (unlink(pjob.filename) == -1 && errno != ENOENT) {
920                 goto next_jobnum;
921         }
922         pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
923         if (pjob.fd == -1) goto fail;
924
925         print_job_store(jobid, &pjob);
926
927         tdb_unlock_bystring(tdb, "INFO/nextjob");
928
929         /*
930          * If the printer is marked as postscript output a leading
931          * file identifier to ensure the file is treated as a raw
932          * postscript file.
933          * This has a similar effect as CtrlD=0 in WIN.INI file.
934          * tim@fsg.com 09/06/94
935          */
936         if (lp_postscript(snum)) {
937                 print_job_write(jobid, "%!\n",3);
938         }
939
940         return jobid;
941
942  fail:
943         if (jobid != -1) {
944                 tdb_delete(tdb, print_key(jobid));
945         }
946
947         tdb_unlock_bystring(tdb, "INFO/nextjob");
948         return -1;
949 }
950
951 /****************************************************************************
952  Print a file - called on closing the file. This spools the job.
953  If normal close is false then we're tearing down the jobs - treat as an
954  error.
955 ****************************************************************************/
956
957 BOOL print_job_end(int jobid, BOOL normal_close)
958 {
959         struct printjob *pjob = print_job_find(jobid);
960         int snum, ret;
961         SMB_STRUCT_STAT sbuf;
962         pstring current_directory;
963         pstring print_directory;
964         char *wd, *p;
965         pstring jobname;
966
967         if (!pjob)
968                 return False;
969
970         if (pjob->spooled || pjob->pid != local_pid)
971                 return False;
972
973         snum = print_job_snum(jobid);
974
975         if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
976                 pjob->size = sbuf.st_size;
977                 close(pjob->fd);
978                 pjob->fd = -1;
979         } else {
980
981                 /* 
982                  * Not a normal close or we couldn't stat the job file,
983                  * so something has gone wrong. Cleanup.
984                  */
985
986                 unlink(pjob->filename);
987                 tdb_delete(tdb, print_key(jobid));
988                 return False;
989         }
990         
991         if (pjob->size == 0) {
992                 /* don't bother spooling empty files */
993                 unlink(pjob->filename);
994                 tdb_delete(tdb, print_key(jobid));
995                 return True;
996         }
997
998         /* we print from the directory path to give the best chance of
999            parsing the lpq output */
1000         wd = sys_getwd(current_directory);
1001         if (!wd)
1002                 return False;           
1003
1004         pstrcpy(print_directory, pjob->filename);
1005         p = strrchr(print_directory,'/');
1006         if (!p)
1007                 return False;
1008         *p++ = 0;
1009
1010         if (chdir(print_directory) != 0)
1011                 return False;
1012
1013         pstrcpy(jobname, pjob->jobname);
1014         pstring_sub(jobname, "'", "_");
1015
1016         /* send it to the system spooler */
1017         ret = print_run_command(snum, 
1018                           lp_printcommand(snum), NULL,
1019                           "%s", p,
1020                           "%J", jobname,
1021                           "%f", p,
1022                           NULL);
1023
1024         chdir(wd);
1025
1026         if (ret == 0) {
1027                 /* The print job has been sucessfully handed over to the back-end */
1028                 
1029                 pjob->spooled = True;
1030                 print_job_store(jobid, pjob);
1031                 
1032                 /* make sure the database is up to date */
1033                 if (print_cache_expired(snum)) print_queue_update(snum);
1034                 
1035                 return True;
1036         } else {
1037                 /* The print job was not succesfully started. Cleanup */
1038                 /* Still need to add proper error return propagation! 010122:JRR */
1039                 unlink(pjob->filename);
1040                 tdb_delete(tdb, print_key(jobid));
1041                 return False;
1042         }
1043 }
1044
1045 /* utility fn to enumerate the print queue */
1046 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1047 {
1048         struct traverse_struct *ts = (struct traverse_struct *)state;
1049         struct printjob pjob;
1050         int i, jobid;
1051
1052         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1053         memcpy(&jobid, key.dptr, sizeof(jobid));
1054         memcpy(&pjob,  data.dptr, sizeof(pjob));
1055
1056         /* maybe it isn't for this queue */
1057         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1058
1059         if (ts->qcount >= ts->maxcount) return 0;
1060
1061         i = ts->qcount;
1062
1063         ts->queue[i].job = jobid;
1064         ts->queue[i].size = pjob.size;
1065         ts->queue[i].status = pjob.status;
1066         ts->queue[i].priority = 1;
1067         ts->queue[i].time = pjob.starttime;
1068         fstrcpy(ts->queue[i].user, pjob.user);
1069         fstrcpy(ts->queue[i].file, pjob.jobname);
1070
1071         ts->qcount++;
1072
1073         return 0;
1074 }
1075
1076 struct traverse_count_struct {
1077         int snum, count;
1078 };
1079
1080 /* utility fn to count the number of entries in the print queue */
1081 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1082 {
1083         struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1084         struct printjob pjob;
1085         int jobid;
1086
1087         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1088         memcpy(&jobid, key.dptr, sizeof(jobid));
1089         memcpy(&pjob,  data.dptr, sizeof(pjob));
1090
1091         /* maybe it isn't for this queue */
1092         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1093
1094         ts->count++;
1095
1096         return 0;
1097 }
1098
1099 /* Sort print jobs by submittal time */
1100
1101 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1102 {
1103         /* Silly cases */
1104
1105         if (!j1 && !j2) return 0;
1106         if (!j1) return -1;
1107         if (!j2) return 1;
1108
1109         /* Sort on job start time */
1110
1111         if (j1->time == j2->time) return 0;
1112         return (j1->time > j2->time) ? 1 : -1;
1113 }
1114
1115 /****************************************************************************
1116 get a printer queue listing
1117 ****************************************************************************/
1118 int print_queue_status(int snum, 
1119                        print_queue_struct **queue,
1120                        print_status_struct *status)
1121 {
1122         struct traverse_struct tstruct;
1123         struct traverse_count_struct tsc;
1124         fstring keystr;
1125         TDB_DATA data, key;
1126
1127         /* make sure the database is up to date */
1128         if (print_cache_expired(snum)) print_queue_update(snum);
1129
1130         *queue = NULL;
1131         
1132         /*
1133          * Fetch the queue status.  We must do this first, as there may
1134          * be no jobs in the queue.
1135          */
1136         ZERO_STRUCTP(status);
1137         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1138         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
1139         key.dptr = keystr;
1140         key.dsize = strlen(keystr);
1141         data = tdb_fetch(tdb, key);
1142         if (data.dptr) {
1143                 if (data.dsize == sizeof(*status)) {
1144                         memcpy(status, data.dptr, sizeof(*status));
1145                 }
1146                 free(data.dptr);
1147         }
1148
1149         /*
1150          * Now, fetch the print queue information.  We first count the number
1151          * of entries, and then only retrieve the queue if necessary.
1152          */
1153         tsc.count = 0;
1154         tsc.snum = snum;
1155         
1156         tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1157
1158         if (tsc.count == 0)
1159                 return 0;
1160
1161         /* Allocate the queue size. */
1162         if ((tstruct.queue = (print_queue_struct *)
1163              malloc(sizeof(print_queue_struct)*tsc.count))
1164                                 == NULL)
1165                 return 0;
1166
1167         /*
1168          * Fill in the queue.
1169          * We need maxcount as the queue size may have changed between
1170          * the two calls to tdb_traverse.
1171          */
1172         tstruct.qcount = 0;
1173         tstruct.maxcount = tsc.count;
1174         tstruct.snum = snum;
1175
1176         tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1177
1178         /* Sort the queue by submission time otherwise they are displayed
1179            in hash order. */
1180
1181         qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1182               QSORT_CAST(printjob_comp));
1183
1184         *queue = tstruct.queue;
1185         return tstruct.qcount;
1186 }
1187
1188
1189 /****************************************************************************
1190 turn a queue name into a snum
1191 ****************************************************************************/
1192 int print_queue_snum(char *qname)
1193 {
1194         int snum = lp_servicenumber(qname);
1195         if (snum == -1 || !lp_print_ok(snum)) return -1;
1196         return snum;
1197 }
1198
1199
1200 /****************************************************************************
1201  pause a queue
1202 ****************************************************************************/
1203 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1204 {
1205         char *printer_name;
1206         int ret;
1207         
1208         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1209                 *errcode = ERROR_ACCESS_DENIED;
1210                 return False;
1211         }
1212
1213         ret = print_run_command(snum, lp_queuepausecommand(snum), NULL, 
1214                                 NULL);
1215
1216         if (ret != 0) {
1217                 *errcode = ERROR_INVALID_PARAMETER;
1218                 return False;
1219         }
1220
1221         /* force update the database */
1222         print_cache_flush(snum);
1223
1224         /* Send a printer notify message */
1225
1226         printer_name = PRINTERNAME(snum);
1227
1228         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1229
1230         return True;
1231 }
1232
1233 /****************************************************************************
1234  resume a queue
1235 ****************************************************************************/
1236 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1237 {
1238         char *printer_name;
1239         int ret;
1240
1241         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1242                 *errcode = ERROR_ACCESS_DENIED;
1243                 return False;
1244         }
1245
1246         ret = print_run_command(snum, lp_queueresumecommand(snum), NULL, 
1247                                 NULL);
1248
1249         if (ret != 0) {
1250                 *errcode = ERROR_INVALID_PARAMETER;
1251                 return False;
1252         }
1253
1254         /* make sure the database is up to date */
1255         if (print_cache_expired(snum)) print_queue_update(snum);
1256
1257         /* Send a printer notify message */
1258
1259         printer_name = PRINTERNAME(snum);
1260
1261         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1262
1263         return True;
1264 }
1265
1266 /****************************************************************************
1267  purge a queue - implemented by deleting all jobs that we can delete
1268 ****************************************************************************/
1269 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1270 {
1271         print_queue_struct *queue;
1272         print_status_struct status;
1273         char *printer_name;
1274         int njobs, i;
1275         BOOL can_job_admin;
1276
1277         /* Force and update so the count is accurate (i.e. not a cached count) */
1278         print_queue_update(snum);
1279         
1280         can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
1281         njobs = print_queue_status(snum, &queue, &status);
1282
1283         for (i=0;i<njobs;i++) {
1284                 BOOL owner = is_owner(user, queue[i].job);
1285
1286                 if (owner || can_job_admin) {
1287                         print_job_delete1(queue[i].job);
1288                 }
1289         }
1290
1291         safe_free(queue);
1292
1293         /* Send a printer notify message */
1294
1295         printer_name = PRINTERNAME(snum);
1296
1297         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1298
1299         return True;
1300 }
1301 #undef OLD_NTDOMAIN