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;
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                 return 0;
248         }
249
250         if (!pjob.smbjob) {
251                 /* remove a unix job if it isn't in the system queue
252                    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) tdb_delete(tdb, key);
258                 return 0;
259         }
260
261         /* maybe it hasn't been spooled yet */
262         if (!pjob.spooled) {
263                 /* if a job is not spooled and the process doesn't
264                    exist then kill it. This cleans up after smbd
265                    deaths */
266                 if (!process_exists(pjob.pid)) {
267                         tdb_delete(tdb, key);
268                 }
269                 return 0;
270         }
271
272         for (i=0;i<ts->qcount;i++) {
273                 int qid = print_parse_jobid(ts->queue[i].file);
274                 if (jobid == qid) break;
275         }
276         
277         /* The job isn't in the system queue - we have to assume it has
278            completed, so delete the database entry. */
279
280         if (i == ts->qcount) {
281                 time_t cur_t = time(NULL);
282
283                 /* A race can occur between the time a job is spooled and
284                    when it appears in the lpq output.  This happens when
285                    the job is added to printing.tdb when another smbd
286                    running print_queue_update() has completed a lpq and
287                    is currently traversing the printing tdb and deleting jobs.
288                    A workaround is to not delete the job if it has been 
289                    submitted less than lp_lpqcachetime() seconds ago. */
290
291                 if ((cur_t - pjob.starttime) > lp_lpqcachetime()) {
292                         tdb_delete(t, key);
293                 }
294         }
295
296         return 0;
297 }
298
299 /****************************************************************************
300 check if the print queue has been updated recently enough
301 ****************************************************************************/
302 static void print_cache_flush(int snum)
303 {
304         fstring key;
305         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
306         dos_to_unix(key, True);                /* Convert key to unix-codepage */
307         tdb_store_int(tdb, key, -1);
308 }
309
310 /****************************************************************************
311 update the internal database from the system print queue for a queue
312 ****************************************************************************/
313 static void print_queue_update(int snum)
314 {
315         char *path = lp_pathname(snum);
316         char *cmd = lp_lpqcommand(snum);
317         char **qlines;
318         pstring tmp_file;
319         int numlines, i, qcount;
320         print_queue_struct *queue = NULL;
321         print_status_struct status;
322         print_status_struct old_status;
323         struct printjob *pjob;
324         struct traverse_struct tstruct;
325         fstring keystr, printer_name;
326         TDB_DATA data, key;
327               
328         /* Convert printer name (i.e. share name) to unix-codepage for all of the 
329          * following tdb key generation */
330         fstrcpy(printer_name, lp_servicename(snum));
331         dos_to_unix(printer_name, True);
332         
333         /*
334          * Update the cache time FIRST ! Stops others doing this
335          * if the lpq takes a long time.
336          */
337
338         slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
339         tdb_store_int(tdb, keystr, (int)time(NULL));
340
341         slprintf(tmp_file, sizeof(tmp_file), "%s/smblpq.%d", path, local_pid);
342
343         unlink(tmp_file);
344         print_run_command(snum, cmd, tmp_file, NULL);
345
346         numlines = 0;
347         qlines = file_lines_load(tmp_file, &numlines, True);
348         unlink(tmp_file);
349
350         /* turn the lpq output into a series of job structures */
351         qcount = 0;
352         ZERO_STRUCT(status);
353         if (numlines)
354                 queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1));
355
356         if (queue) {
357                 for (i=0; i<numlines; i++) {
358                         /* parse the line */
359                         if (parse_lpq_entry(snum,qlines[i],
360                                             &queue[qcount],&status,qcount==0)) {
361                                 qcount++;
362                         }
363                 }               
364         }
365         file_lines_free(qlines);
366
367         DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ?
368                 "s" : "", printer_name));
369
370         /* Lock the queue for the database update */
371
372         slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
373         tdb_lock_bystring(tdb, keystr);
374
375         /*
376           any job in the internal database that is marked as spooled
377           and doesn't exist in the system queue is considered finished
378           and removed from the database
379
380           any job in the system database but not in the internal database 
381           is added as a unix job
382
383           fill in any system job numbers as we go
384         */
385         for (i=0; i<qcount; i++) {
386                 int jobid = print_parse_jobid(queue[i].file);
387
388                 if (jobid == -1) {
389                         /* assume its a unix print job */
390                         print_unix_job(snum, &queue[i]);
391                         continue;
392                 }
393
394                 /* we have an active SMB print job - update its status */
395                 pjob = print_job_find(jobid);
396                 if (!pjob) {
397                         /* err, somethings wrong. Probably smbd was restarted
398                            with jobs in the queue. All we can do is treat them
399                            like unix jobs. Pity. */
400                         print_unix_job(snum, &queue[i]);
401                         continue;
402                 }
403
404                 pjob->sysjob = queue[i].job;
405                 pjob->status = queue[i].status;
406
407                 print_job_store(jobid, pjob);
408         }
409
410         /* now delete any queued entries that don't appear in the
411            system queue */
412         tstruct.queue = queue;
413         tstruct.qcount = qcount;
414         tstruct.snum = snum;
415
416         tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
417
418         safe_free(tstruct.queue);
419
420         /*
421          * Get the old print status. We will use this to compare the
422          * number of jobs. If they have changed we need to send a
423          * "changed" message to the smbds.
424          */
425
426         if( qcount != get_queue_status(snum, &old_status)) {
427                 DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
428                                 old_status.qcount, qcount, printer_name ));
429                 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
430         }
431
432         /* store the new queue status structure */
433         slprintf(keystr, sizeof(keystr), "STATUS/%s", printer_name);
434     key.dptr = keystr;
435         key.dsize = strlen(keystr);
436
437         status.qcount = qcount;
438         data.dptr = (void *)&status;
439         data.dsize = sizeof(status);
440         tdb_store(tdb, key, data, TDB_REPLACE); 
441
442         /* Unlock for database update */
443
444         slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
445         tdb_unlock_bystring(tdb, keystr);
446
447         /*
448          * Update the cache time again. We want to do this call
449          * as little as possible...
450          */
451
452         slprintf(keystr, sizeof(keystr), "CACHE/%s", printer_name);
453         tdb_store_int(tdb, keystr, (int)time(NULL));
454 }
455
456 /****************************************************************************
457 check if a jobid is valid. It is valid if it exists in the database
458 ****************************************************************************/
459 BOOL print_job_exists(int jobid)
460 {
461         return tdb_exists(tdb, print_key(jobid));
462 }
463
464
465 /****************************************************************************
466 work out which service a jobid is for
467 note that we have to look up by queue name to ensure that it works for 
468 other than the process that started the job
469 ****************************************************************************/
470 int print_job_snum(int jobid)
471 {
472         struct printjob *pjob = print_job_find(jobid);
473         if (!pjob) return -1;
474
475         return lp_servicenumber(pjob->qname);
476 }
477
478 /****************************************************************************
479 give the fd used for a jobid
480 ****************************************************************************/
481 int print_job_fd(int jobid)
482 {
483         struct printjob *pjob = print_job_find(jobid);
484         if (!pjob) return -1;
485         /* don't allow another process to get this info - it is meaningless */
486         if (pjob->pid != local_pid) return -1;
487         return pjob->fd;
488 }
489
490 /****************************************************************************
491 give the filename used for a jobid
492 only valid for the process doing the spooling and when the job
493 has not been spooled
494 ****************************************************************************/
495 char *print_job_fname(int jobid)
496 {
497         struct printjob *pjob = print_job_find(jobid);
498         if (!pjob || pjob->spooled || pjob->pid != local_pid) return NULL;
499         return pjob->filename;
500 }
501
502
503 /****************************************************************************
504 set the place in the queue for a job
505 ****************************************************************************/
506 BOOL print_job_set_place(int jobid, int place)
507 {
508         DEBUG(2,("print_job_set_place not implemented yet\n"));
509         return False;
510 }
511
512 /****************************************************************************
513 set the name of a job. Only possible for owner
514 ****************************************************************************/
515 BOOL print_job_set_name(int jobid, char *name)
516 {
517         struct printjob *pjob = print_job_find(jobid);
518         if (!pjob || pjob->pid != local_pid) return False;
519
520         fstrcpy(pjob->jobname, name);
521         return print_job_store(jobid, pjob);
522 }
523
524
525 /****************************************************************************
526 delete a print job - don't update queue
527 ****************************************************************************/
528 static BOOL print_job_delete1(int jobid)
529 {
530         struct printjob *pjob = print_job_find(jobid);
531         int snum;
532
533         if (!pjob) return False;
534
535         snum = print_job_snum(jobid);
536
537         /* Hrm - we need to be able to cope with deleting a job before it
538            has reached the spooler. */
539
540         if (pjob->sysjob == -1) {
541                 DEBUG(5, ("attempt to delete job %d not seen by lpr\n",
542                           jobid));
543         }
544
545         if (pjob->spooled && pjob->sysjob != -1) {
546                 /* need to delete the spooled entry */
547                 fstring jobstr;
548                 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
549                 print_run_command(snum, 
550                                   lp_lprmcommand(snum), NULL,
551                                   "%j", jobstr,
552                                   "%T", http_timestring(pjob->starttime),
553                                   NULL);
554         }
555
556         return True;
557 }
558
559 /****************************************************************************
560 return true if the current user owns the print job
561 ****************************************************************************/
562 static BOOL is_owner(struct current_user *user, int jobid)
563 {
564         struct printjob *pjob = print_job_find(jobid);
565         user_struct *vuser;
566
567         if (!pjob || !user) return False;
568
569         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
570                 return strequal(pjob->user, vuser->user.smb_name);
571         } else {
572                 return strequal(pjob->user, uidtoname(user->uid));
573         }
574 }
575
576 /****************************************************************************
577 delete a print job
578 ****************************************************************************/
579 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
580 {
581         int snum = print_job_snum(jobid);
582         char *printer_name;
583         BOOL owner;
584         
585         owner = is_owner(user, jobid);
586         
587         /* Check access against security descriptor or whether the user
588            owns their job. */
589
590         if (!owner && 
591             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
592                 DEBUG(3, ("delete denied by security descriptor\n"));
593                 *errcode = ERROR_ACCESS_DENIED;
594                 return False;
595         }
596
597         if (!print_job_delete1(jobid)) return False;
598
599         /* force update the database and say the delete failed if the
600            job still exists */
601
602         print_queue_update(snum);
603
604         /* Send a printer notify message */
605
606         printer_name = PRINTERNAME(snum);
607
608         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
609
610         return !print_job_exists(jobid);
611 }
612
613
614 /****************************************************************************
615 pause a job
616 ****************************************************************************/
617 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
618 {
619         struct printjob *pjob = print_job_find(jobid);
620         int snum, ret = -1;
621         char *printer_name;
622         fstring jobstr;
623         BOOL owner;
624         
625         if (!pjob || !user) return False;
626
627         if (!pjob->spooled || pjob->sysjob == -1) return False;
628
629         snum = print_job_snum(jobid);
630         owner = is_owner(user, jobid);
631
632         if (!owner &&
633             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
634                 DEBUG(3, ("pause denied by security descriptor\n"));
635                 *errcode = ERROR_ACCESS_DENIED;
636                 return False;
637         }
638
639         /* need to pause the spooled entry */
640         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
641         ret = print_run_command(snum, 
642                                 lp_lppausecommand(snum), NULL,
643                                 "%j", jobstr,
644                                 NULL);
645
646         if (ret != 0) {
647                 *errcode = ERROR_INVALID_PARAMETER;
648                 return False;
649         }
650
651         /* force update the database */
652         print_cache_flush(snum);
653
654         /* Send a printer notify message */
655
656         printer_name = PRINTERNAME(snum);
657
658         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
659
660         /* how do we tell if this succeeded? */
661
662         return True;
663 }
664
665 /****************************************************************************
666 resume a job
667 ****************************************************************************/
668 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
669 {
670         struct printjob *pjob = print_job_find(jobid);
671         char *printer_name;
672         int snum, ret;
673         fstring jobstr;
674         BOOL owner;
675         
676         if (!pjob || !user) return False;
677
678         if (!pjob->spooled || pjob->sysjob == -1) return False;
679
680         snum = print_job_snum(jobid);
681         owner = is_owner(user, jobid);
682
683         if (!is_owner(user, jobid) &&
684             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
685                 DEBUG(3, ("resume denied by security descriptor\n"));
686                 *errcode = ERROR_ACCESS_DENIED;
687                 return False;
688         }
689
690         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
691         ret = print_run_command(snum, 
692                                 lp_lpresumecommand(snum), NULL,
693                                 "%j", jobstr,
694                                 NULL);
695
696         if (ret != 0) {
697                 *errcode = ERROR_INVALID_PARAMETER;
698                 return False;
699         }
700
701         /* force update the database */
702         print_cache_flush(snum);
703
704         /* Send a printer notify message */
705
706         printer_name = PRINTERNAME(snum);
707
708         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
709
710         return True;
711 }
712
713 /****************************************************************************
714 write to a print file
715 ****************************************************************************/
716 int print_job_write(int jobid, const char *buf, int size)
717 {
718         int fd;
719
720         fd = print_job_fd(jobid);
721         if (fd == -1) return -1;
722
723         return write(fd, buf, size);
724 }
725
726 /****************************************************************************
727  Check if the print queue has been updated recently enough.
728 ****************************************************************************/
729
730 static BOOL print_cache_expired(int snum)
731 {
732         fstring key;
733         time_t t2, t = time(NULL);
734
735         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
736         dos_to_unix(key, True);                /* Convert key to unix-codepage */
737         t2 = tdb_fetch_int(tdb, key);
738         if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
739                 DEBUG(3, ("print cache expired\n"));
740                 return True;
741         }
742         return False;
743 }
744
745 /****************************************************************************
746  Get the queue status - do not update if db is out of date.
747 ****************************************************************************/
748
749 static int get_queue_status(int snum, print_status_struct *status)
750 {
751         fstring keystr;
752         TDB_DATA data, key;
753
754         ZERO_STRUCTP(status);
755         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
756         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
757         key.dptr = keystr;
758         key.dsize = strlen(keystr);
759         data = tdb_fetch(tdb, key);
760         if (data.dptr) {
761                 if (data.dsize == sizeof(print_status_struct)) {
762                         memcpy(status, data.dptr, sizeof(print_status_struct));
763                 }
764                 free(data.dptr);
765         }
766         return status->qcount;
767 }
768
769 /****************************************************************************
770  Determine the number of jobs in a queue.
771 ****************************************************************************/
772
773 static int print_queue_length(int snum)
774 {
775         print_status_struct status;
776
777         /* make sure the database is up to date */
778         if (print_cache_expired(snum)) print_queue_update(snum);
779
780         /* also fetch the queue status */
781         return get_queue_status(snum, &status);
782 }
783
784 /***************************************************************************
785 start spooling a job - return the jobid
786 ***************************************************************************/
787 int print_job_start(struct current_user *user, int snum, char *jobname)
788 {
789         int jobid;
790         char *path;
791         struct printjob pjob;
792         int next_jobid;
793         user_struct *vuser;
794
795         errno = 0;
796
797         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
798                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
799                 return -1;
800         }
801
802         if (!print_time_access_check(snum)) {
803                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
804                 return -1;
805         }
806
807         path = lp_pathname(snum);
808
809         /* see if we have sufficient disk space */
810         if (lp_minprintspace(snum)) {
811                 SMB_BIG_UINT dspace, dsize;
812                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
813                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
814                         errno = ENOSPC;
815                         return -1;
816                 }
817         }
818
819         /* for autoloaded printers, check that the printcap entry still exists */
820         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
821                 errno = ENOENT;
822                 return -1;
823         }
824
825         if (lp_maxprintjobs(snum) && print_queue_length(snum) > lp_maxprintjobs(snum)) {
826                 errno = ENOSPC;
827                 return -1;
828         }
829
830         /* create the database entry */
831         ZERO_STRUCT(pjob);
832         pjob.pid = local_pid;
833         pjob.sysjob = -1;
834         pjob.fd = -1;
835         pjob.starttime = time(NULL);
836         pjob.status = LPQ_QUEUED;
837         pjob.size = 0;
838         pjob.spooled = False;
839         pjob.smbjob = True;
840
841         fstrcpy(pjob.jobname, jobname);
842
843         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
844                 fstrcpy(pjob.user, vuser->user.smb_name);
845         } else {
846                 fstrcpy(pjob.user, uidtoname(user->uid));
847         }
848
849         fstrcpy(pjob.qname, lp_servicename(snum));
850
851         /* lock the database */
852         tdb_lock_bystring(tdb, "INFO/nextjob");
853
854  next_jobnum:
855         next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
856         if (next_jobid == -1) next_jobid = 1;
857
858         for (jobid = next_jobid+1; jobid != next_jobid; ) {
859                 if (!print_job_exists(jobid)) break;
860                 jobid = (jobid + 1) % PRINT_MAX_JOBID;
861                 if (jobid == 0) jobid = 1;
862         }
863         if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
864                 jobid = -1;
865                 goto fail;
866         }
867
868         tdb_store_int(tdb, "INFO/nextjob", jobid);
869
870         /* we have a job entry - now create the spool file 
871
872            we unlink first to cope with old spool files and also to beat
873            a symlink security hole - it allows us to use O_EXCL 
874            There may be old spool files owned by other users lying around.
875         */
876         slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d", 
877                  path, PRINT_SPOOL_PREFIX, jobid);
878         if (unlink(pjob.filename) == -1 && errno != ENOENT) {
879                 goto next_jobnum;
880         }
881         pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
882         if (pjob.fd == -1) goto fail;
883
884         print_job_store(jobid, &pjob);
885
886         tdb_unlock_bystring(tdb, "INFO/nextjob");
887
888         /*
889          * If the printer is marked as postscript output a leading
890          * file identifier to ensure the file is treated as a raw
891          * postscript file.
892          * This has a similar effect as CtrlD=0 in WIN.INI file.
893          * tim@fsg.com 09/06/94
894          */
895         if (lp_postscript(snum)) {
896                 print_job_write(jobid, "%!\n",3);
897         }
898
899         return jobid;
900
901  fail:
902         if (jobid != -1) {
903                 tdb_delete(tdb, print_key(jobid));
904         }
905
906         tdb_unlock_bystring(tdb, "INFO/nextjob");
907         return -1;
908 }
909
910 /****************************************************************************
911  Print a file - called on closing the file. This spools the job.
912 ****************************************************************************/
913
914 BOOL print_job_end(int jobid)
915 {
916         struct printjob *pjob = print_job_find(jobid);
917         int snum, ret;
918         SMB_STRUCT_STAT sbuf;
919         pstring current_directory;
920         pstring print_directory;
921         char *wd, *p;
922         pstring jobname;
923
924         if (!pjob)
925                 return False;
926
927         if (pjob->spooled || pjob->pid != local_pid)
928                 return False;
929
930         snum = print_job_snum(jobid);
931
932         if (sys_fstat(pjob->fd, &sbuf) == 0) {
933                 pjob->size = sbuf.st_size;
934                 close(pjob->fd);
935                 pjob->fd = -1;
936         } else {
937                 /* Couldn't stat the job file, so something has gone wrong. Cleanup */
938                 unlink(pjob->filename);
939                 tdb_delete(tdb, print_key(jobid));
940                 return False;
941         }
942         
943         if (pjob->size == 0) {
944                 /* don't bother spooling empty files */
945                 unlink(pjob->filename);
946                 tdb_delete(tdb, print_key(jobid));
947                 return True;
948         }
949
950         /* we print from the directory path to give the best chance of
951            parsing the lpq output */
952         wd = sys_getwd(current_directory);
953         if (!wd)
954                 return False;           
955
956         pstrcpy(print_directory, pjob->filename);
957         p = strrchr(print_directory,'/');
958         if (!p)
959                 return False;
960         *p++ = 0;
961
962         if (chdir(print_directory) != 0)
963                 return False;
964
965         pstrcpy(jobname, pjob->jobname);
966         pstring_sub(jobname, "'", "_");
967
968         /* send it to the system spooler */
969         ret = print_run_command(snum, 
970                           lp_printcommand(snum), NULL,
971                           "%s", p,
972                           "%J", jobname,
973                           "%f", p,
974                           NULL);
975
976         chdir(wd);
977
978         if (ret == 0) {
979                 /* The print job has been sucessfully handed over to the back-end */
980                 
981                 pjob->spooled = True;
982                 print_job_store(jobid, pjob);
983                 
984                 /* make sure the database is up to date */
985                 if (print_cache_expired(snum)) print_queue_update(snum);
986                 
987                 return True;
988         } else {
989                 /* The print job was not succesfully started. Cleanup */
990                 /* Still need to add proper error return propagation! 010122:JRR */
991                 unlink(pjob->filename);
992                 tdb_delete(tdb, print_key(jobid));
993                 return False;
994         }
995 }
996
997 /* utility fn to enumerate the print queue */
998 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
999 {
1000         struct traverse_struct *ts = (struct traverse_struct *)state;
1001         struct printjob pjob;
1002         int i, jobid;
1003
1004         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1005         memcpy(&jobid, key.dptr, sizeof(jobid));
1006         memcpy(&pjob,  data.dptr, sizeof(pjob));
1007
1008         /* maybe it isn't for this queue */
1009         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1010
1011         if (ts->qcount >= ts->maxcount) return 0;
1012
1013         i = ts->qcount;
1014
1015         ts->queue[i].job = jobid;
1016         ts->queue[i].size = pjob.size;
1017         ts->queue[i].status = pjob.status;
1018         ts->queue[i].priority = 1;
1019         ts->queue[i].time = pjob.starttime;
1020         fstrcpy(ts->queue[i].user, pjob.user);
1021         fstrcpy(ts->queue[i].file, pjob.jobname);
1022
1023         ts->qcount++;
1024
1025         return 0;
1026 }
1027
1028 struct traverse_count_struct {
1029         int snum, count;
1030 };
1031
1032 /* utility fn to count the number of entries in the print queue */
1033 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1034 {
1035         struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1036         struct printjob pjob;
1037         int jobid;
1038
1039         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1040         memcpy(&jobid, key.dptr, sizeof(jobid));
1041         memcpy(&pjob,  data.dptr, sizeof(pjob));
1042
1043         /* maybe it isn't for this queue */
1044         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1045
1046         ts->count++;
1047
1048         return 0;
1049 }
1050
1051 /* Sort print jobs by submittal time */
1052
1053 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1054 {
1055         /* Silly cases */
1056
1057         if (!j1 && !j2) return 0;
1058         if (!j1) return -1;
1059         if (!j2) return 1;
1060
1061         /* Sort on job start time */
1062
1063         if (j1->time == j2->time) return 0;
1064         return (j1->time > j2->time) ? 1 : -1;
1065 }
1066
1067 /****************************************************************************
1068 get a printer queue listing
1069 ****************************************************************************/
1070 int print_queue_status(int snum, 
1071                        print_queue_struct **queue,
1072                        print_status_struct *status)
1073 {
1074         struct traverse_struct tstruct;
1075         struct traverse_count_struct tsc;
1076         fstring keystr;
1077         TDB_DATA data, key;
1078
1079         /* make sure the database is up to date */
1080         if (print_cache_expired(snum)) print_queue_update(snum);
1081
1082         *queue = NULL;
1083         
1084         /*
1085          * Fetch the queue status.  We must do this first, as there may
1086          * be no jobs in the queue.
1087          */
1088         ZERO_STRUCTP(status);
1089         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1090         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
1091         key.dptr = keystr;
1092         key.dsize = strlen(keystr);
1093         data = tdb_fetch(tdb, key);
1094         if (data.dptr) {
1095                 if (data.dsize == sizeof(*status)) {
1096                         memcpy(status, data.dptr, sizeof(*status));
1097                 }
1098                 free(data.dptr);
1099         }
1100
1101         /*
1102          * Now, fetch the print queue information.  We first count the number
1103          * of entries, and then only retrieve the queue if necessary.
1104          */
1105         tsc.count = 0;
1106         tsc.snum = snum;
1107         
1108         tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1109
1110         if (tsc.count == 0)
1111                 return 0;
1112
1113         /* Allocate the queue size. */
1114         if ((tstruct.queue = (print_queue_struct *)
1115              malloc(sizeof(print_queue_struct)*tsc.count))
1116                                 == NULL)
1117                 return 0;
1118
1119         /*
1120          * Fill in the queue.
1121          * We need maxcount as the queue size may have changed between
1122          * the two calls to tdb_traverse.
1123          */
1124         tstruct.qcount = 0;
1125         tstruct.maxcount = tsc.count;
1126         tstruct.snum = snum;
1127
1128         tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1129
1130         /* Sort the queue by submission time otherwise they are displayed
1131            in hash order. */
1132
1133         qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1134               QSORT_CAST(printjob_comp));
1135
1136         *queue = tstruct.queue;
1137         return tstruct.qcount;
1138 }
1139
1140
1141 /****************************************************************************
1142 turn a queue name into a snum
1143 ****************************************************************************/
1144 int print_queue_snum(char *qname)
1145 {
1146         int snum = lp_servicenumber(qname);
1147         if (snum == -1 || !lp_print_ok(snum)) return -1;
1148         return snum;
1149 }
1150
1151
1152 /****************************************************************************
1153  pause a queue
1154 ****************************************************************************/
1155 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1156 {
1157         char *printer_name;
1158         int ret;
1159         
1160         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1161                 *errcode = ERROR_ACCESS_DENIED;
1162                 return False;
1163         }
1164
1165         ret = print_run_command(snum, lp_queuepausecommand(snum), NULL, 
1166                                 NULL);
1167
1168         if (ret != 0) {
1169                 *errcode = ERROR_INVALID_PARAMETER;
1170                 return False;
1171         }
1172
1173         /* force update the database */
1174         print_cache_flush(snum);
1175
1176         /* Send a printer notify message */
1177
1178         printer_name = PRINTERNAME(snum);
1179
1180         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1181
1182         return True;
1183 }
1184
1185 /****************************************************************************
1186  resume a queue
1187 ****************************************************************************/
1188 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1189 {
1190         char *printer_name;
1191         int ret;
1192
1193         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1194                 *errcode = ERROR_ACCESS_DENIED;
1195                 return False;
1196         }
1197
1198         ret = print_run_command(snum, lp_queueresumecommand(snum), NULL, 
1199                                 NULL);
1200
1201         if (ret != 0) {
1202                 *errcode = ERROR_INVALID_PARAMETER;
1203                 return False;
1204         }
1205
1206         /* make sure the database is up to date */
1207         if (print_cache_expired(snum)) print_queue_update(snum);
1208
1209         /* Send a printer notify message */
1210
1211         printer_name = PRINTERNAME(snum);
1212
1213         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1214
1215         return True;
1216 }
1217
1218 /****************************************************************************
1219  purge a queue - implemented by deleting all jobs that we can delete
1220 ****************************************************************************/
1221 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1222 {
1223         print_queue_struct *queue;
1224         print_status_struct status;
1225         char *printer_name;
1226         int njobs, i;
1227         BOOL can_job_admin;
1228
1229         can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
1230         njobs = print_queue_status(snum, &queue, &status);
1231
1232         for (i=0;i<njobs;i++) {
1233                 BOOL owner = is_owner(user, queue[i].job);
1234
1235                 if (owner || can_job_admin) {
1236                         print_job_delete1(queue[i].job);
1237                 }
1238         }
1239
1240         print_queue_update(snum);
1241         safe_free(queue);
1242
1243         /* Send a printer notify message */
1244
1245         printer_name = PRINTERNAME(snum);
1246
1247         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1248
1249         return True;
1250 }
1251 #undef OLD_NTDOMAIN