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