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