Changes 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   
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         if (pjob->spooled && pjob->sysjob != -1) {
538                 /* need to delete the spooled entry */
539                 fstring jobstr;
540                 slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
541                 print_run_command(snum, 
542                                   lp_lprmcommand(snum), NULL,
543                                   "%j", jobstr,
544                                   "%T", http_timestring(pjob->starttime),
545                                   NULL);
546         }
547
548         return True;
549 }
550
551 /****************************************************************************
552 return true if the current user owns the print job
553 ****************************************************************************/
554 static BOOL is_owner(struct current_user *user, int jobid)
555 {
556         struct printjob *pjob = print_job_find(jobid);
557         user_struct *vuser;
558
559         if (!pjob || !user) return False;
560
561         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
562                 return strequal(pjob->user, vuser->user.smb_name);
563         } else {
564                 return strequal(pjob->user, uidtoname(user->uid));
565         }
566 }
567
568 /****************************************************************************
569 delete a print job
570 ****************************************************************************/
571 BOOL print_job_delete(struct current_user *user, int jobid, int *errcode)
572 {
573         int snum = print_job_snum(jobid);
574         char *printer_name;
575         BOOL owner;
576         
577         owner = is_owner(user, jobid);
578         
579         /* Check access against security descriptor or whether the user
580            owns their job. */
581
582         if (!owner && 
583             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
584                 DEBUG(3, ("delete denied by security descriptor\n"));
585                 *errcode = ERROR_ACCESS_DENIED;
586                 return False;
587         }
588
589         if (!print_job_delete1(jobid)) return False;
590
591         /* force update the database and say the delete failed if the
592            job still exists */
593
594         print_queue_update(snum);
595
596         /* Send a printer notify message */
597
598         printer_name = PRINTERNAME(snum);
599
600         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
601
602         return !print_job_exists(jobid);
603 }
604
605
606 /****************************************************************************
607 pause a job
608 ****************************************************************************/
609 BOOL print_job_pause(struct current_user *user, int jobid, int *errcode)
610 {
611         struct printjob *pjob = print_job_find(jobid);
612         int snum, ret = -1;
613         char *printer_name;
614         fstring jobstr;
615         BOOL owner;
616         
617         if (!pjob || !user) return False;
618
619         if (!pjob->spooled || pjob->sysjob == -1) return False;
620
621         snum = print_job_snum(jobid);
622         owner = is_owner(user, jobid);
623
624         if (!owner &&
625             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
626                 DEBUG(3, ("pause denied by security descriptor\n"));
627                 *errcode = ERROR_ACCESS_DENIED;
628                 return False;
629         }
630
631         /* need to pause the spooled entry */
632         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
633         ret = print_run_command(snum, 
634                                 lp_lppausecommand(snum), NULL,
635                                 "%j", jobstr,
636                                 NULL);
637
638         if (ret != 0) {
639                 *errcode = ERROR_INVALID_PARAMETER;
640                 return False;
641         }
642
643         /* force update the database */
644         print_cache_flush(snum);
645
646         /* Send a printer notify message */
647
648         printer_name = PRINTERNAME(snum);
649
650         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
651
652         /* how do we tell if this succeeded? */
653
654         return True;
655 }
656
657 /****************************************************************************
658 resume a job
659 ****************************************************************************/
660 BOOL print_job_resume(struct current_user *user, int jobid, int *errcode)
661 {
662         struct printjob *pjob = print_job_find(jobid);
663         char *printer_name;
664         int snum, ret;
665         fstring jobstr;
666         BOOL owner;
667         
668         if (!pjob || !user) return False;
669
670         if (!pjob->spooled || pjob->sysjob == -1) return False;
671
672         snum = print_job_snum(jobid);
673         owner = is_owner(user, jobid);
674
675         if (!is_owner(user, jobid) &&
676             !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
677                 DEBUG(3, ("resume denied by security descriptor\n"));
678                 *errcode = ERROR_ACCESS_DENIED;
679                 return False;
680         }
681
682         slprintf(jobstr, sizeof(jobstr), "%d", pjob->sysjob);
683         ret = print_run_command(snum, 
684                                 lp_lpresumecommand(snum), NULL,
685                                 "%j", jobstr,
686                                 NULL);
687
688         if (ret != 0) {
689                 *errcode = ERROR_INVALID_PARAMETER;
690                 return False;
691         }
692
693         /* force update the database */
694         print_cache_flush(snum);
695
696         /* Send a printer notify message */
697
698         printer_name = PRINTERNAME(snum);
699
700         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
701
702         return True;
703 }
704
705 /****************************************************************************
706 write to a print file
707 ****************************************************************************/
708 int print_job_write(int jobid, const char *buf, int size)
709 {
710         int fd;
711
712         fd = print_job_fd(jobid);
713         if (fd == -1) return -1;
714
715         return write(fd, buf, size);
716 }
717
718 /****************************************************************************
719  Check if the print queue has been updated recently enough.
720 ****************************************************************************/
721
722 static BOOL print_cache_expired(int snum)
723 {
724         fstring key;
725         time_t t2, t = time(NULL);
726
727         slprintf(key, sizeof(key), "CACHE/%s", lp_servicename(snum));
728         dos_to_unix(key, True);                /* Convert key to unix-codepage */
729         t2 = tdb_fetch_int(tdb, key);
730         if (t2 == ((time_t)-1) || (t - t2) >= lp_lpqcachetime()) {
731                 DEBUG(3, ("print cache expired\n"));
732                 return True;
733         }
734         return False;
735 }
736
737 /****************************************************************************
738  Get the queue status - do not update if db is out of date.
739 ****************************************************************************/
740
741 static int get_queue_status(int snum, print_status_struct *status)
742 {
743         fstring keystr;
744         TDB_DATA data, key;
745
746         ZERO_STRUCTP(status);
747         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
748         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
749         key.dptr = keystr;
750         key.dsize = strlen(keystr);
751         data = tdb_fetch(tdb, key);
752         if (data.dptr) {
753                 if (data.dsize == sizeof(print_status_struct)) {
754                         memcpy(status, data.dptr, sizeof(print_status_struct));
755                 }
756                 free(data.dptr);
757         }
758         return status->qcount;
759 }
760
761 /****************************************************************************
762  Determine the number of jobs in a queue.
763 ****************************************************************************/
764
765 static int print_queue_length(int snum)
766 {
767         print_status_struct status;
768
769         /* make sure the database is up to date */
770         if (print_cache_expired(snum)) print_queue_update(snum);
771
772         /* also fetch the queue status */
773         return get_queue_status(snum, &status);
774 }
775
776 /***************************************************************************
777 start spooling a job - return the jobid
778 ***************************************************************************/
779 int print_job_start(struct current_user *user, int snum, char *jobname)
780 {
781         int jobid;
782         char *path;
783         struct printjob pjob;
784         int next_jobid;
785         user_struct *vuser;
786
787         errno = 0;
788
789         if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
790                 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
791                 return -1;
792         }
793
794         if (!print_time_access_check(snum)) {
795                 DEBUG(3, ("print_job_start: job start denied by time check\n"));
796                 return -1;
797         }
798
799         path = lp_pathname(snum);
800
801         /* see if we have sufficient disk space */
802         if (lp_minprintspace(snum)) {
803                 SMB_BIG_UINT dspace, dsize;
804                 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
805                     dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
806                         errno = ENOSPC;
807                         return -1;
808                 }
809         }
810
811         /* for autoloaded printers, check that the printcap entry still exists */
812         if (lp_autoloaded(snum) && !pcap_printername_ok(lp_servicename(snum), NULL)) {
813                 errno = ENOENT;
814                 return -1;
815         }
816
817         if (lp_maxprintjobs(snum) && print_queue_length(snum) > lp_maxprintjobs(snum)) {
818                 errno = ENOSPC;
819                 return -1;
820         }
821
822         /* create the database entry */
823         ZERO_STRUCT(pjob);
824         pjob.pid = local_pid;
825         pjob.sysjob = -1;
826         pjob.fd = -1;
827         pjob.starttime = time(NULL);
828         pjob.status = LPQ_QUEUED;
829         pjob.size = 0;
830         pjob.spooled = False;
831         pjob.smbjob = True;
832
833         fstrcpy(pjob.jobname, jobname);
834
835         if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
836                 fstrcpy(pjob.user, vuser->user.smb_name);
837         } else {
838                 fstrcpy(pjob.user, uidtoname(user->uid));
839         }
840
841         fstrcpy(pjob.qname, lp_servicename(snum));
842
843         /* lock the database */
844         tdb_lock_bystring(tdb, "INFO/nextjob");
845
846  next_jobnum:
847         next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
848         if (next_jobid == -1) next_jobid = 1;
849
850         for (jobid = next_jobid+1; jobid != next_jobid; ) {
851                 if (!print_job_exists(jobid)) break;
852                 jobid = (jobid + 1) % PRINT_MAX_JOBID;
853                 if (jobid == 0) jobid = 1;
854         }
855         if (jobid == next_jobid || !print_job_store(jobid, &pjob)) {
856                 jobid = -1;
857                 goto fail;
858         }
859
860         tdb_store_int(tdb, "INFO/nextjob", jobid);
861
862         /* we have a job entry - now create the spool file 
863
864            we unlink first to cope with old spool files and also to beat
865            a symlink security hole - it allows us to use O_EXCL 
866            There may be old spool files owned by other users lying around.
867         */
868         slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d", 
869                  path, PRINT_SPOOL_PREFIX, jobid);
870         if (unlink(pjob.filename) == -1 && errno != ENOENT) {
871                 goto next_jobnum;
872         }
873         pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
874         if (pjob.fd == -1) goto fail;
875
876         print_job_store(jobid, &pjob);
877
878         tdb_unlock_bystring(tdb, "INFO/nextjob");
879
880         /*
881          * If the printer is marked as postscript output a leading
882          * file identifier to ensure the file is treated as a raw
883          * postscript file.
884          * This has a similar effect as CtrlD=0 in WIN.INI file.
885          * tim@fsg.com 09/06/94
886          */
887         if (lp_postscript(snum)) {
888                 print_job_write(jobid, "%!\n",3);
889         }
890
891         return jobid;
892
893  fail:
894         if (jobid != -1) {
895                 tdb_delete(tdb, print_key(jobid));
896         }
897
898         tdb_unlock_bystring(tdb, "INFO/nextjob");
899         return -1;
900 }
901
902 /****************************************************************************
903  Print a file - called on closing the file. This spools the job.
904 ****************************************************************************/
905
906 BOOL print_job_end(int jobid)
907 {
908         struct printjob *pjob = print_job_find(jobid);
909         int snum;
910         SMB_STRUCT_STAT sbuf;
911         pstring current_directory;
912         pstring print_directory;
913         char *wd, *p, *printer_name;
914         pstring jobname;
915
916         if (!pjob)
917                 return False;
918
919         if (pjob->spooled || pjob->pid != local_pid)
920                 return False;
921
922         snum = print_job_snum(jobid);
923
924         if (sys_fstat(pjob->fd, &sbuf) == 0) {
925                 pjob->size = sbuf.st_size;
926                 close(pjob->fd);
927                 pjob->fd = -1;
928         } else {
929                 /* Couldn't stat the job file, so something has gone wrong. Cleanup */
930                 unlink(pjob->filename);
931                 tdb_delete(tdb, print_key(jobid));
932                 return False;
933         }
934         
935         if (pjob->size == 0) {
936                 /* don't bother spooling empty files */
937                 unlink(pjob->filename);
938                 tdb_delete(tdb, print_key(jobid));
939                 return True;
940         }
941
942         /* we print from the directory path to give the best chance of
943            parsing the lpq output */
944         wd = sys_getwd(current_directory);
945         if (!wd)
946                 return False;           
947
948         pstrcpy(print_directory, pjob->filename);
949         p = strrchr(print_directory,'/');
950         if (!p)
951                 return False;
952         *p++ = 0;
953
954         if (chdir(print_directory) != 0)
955                 return False;
956
957         pstrcpy(jobname, pjob->jobname);
958         pstring_sub(jobname, "'", "_");
959
960         /* send it to the system spooler */
961         print_run_command(snum, 
962                           lp_printcommand(snum), NULL,
963                           "%s", p,
964                           "%J", jobname,
965                           "%f", p,
966                           NULL);
967
968         chdir(wd);
969
970         pjob->spooled = True;
971         print_job_store(jobid, pjob);
972
973         /* make sure the database is up to date */
974         if (print_cache_expired(snum)) print_queue_update(snum);
975
976         /* Send a printer notify message */
977
978         printer_name = PRINTERNAME(snum);
979
980         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
981
982         return True;
983 }
984
985 /* utility fn to enumerate the print queue */
986 static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
987 {
988         struct traverse_struct *ts = (struct traverse_struct *)state;
989         struct printjob pjob;
990         int i, jobid;
991
992         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
993         memcpy(&jobid, key.dptr, sizeof(jobid));
994         memcpy(&pjob,  data.dptr, sizeof(pjob));
995
996         /* maybe it isn't for this queue */
997         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
998
999         if (ts->qcount >= ts->maxcount) return 0;
1000
1001         i = ts->qcount;
1002
1003         ts->queue[i].job = jobid;
1004         ts->queue[i].size = pjob.size;
1005         ts->queue[i].status = pjob.status;
1006         ts->queue[i].priority = 1;
1007         ts->queue[i].time = pjob.starttime;
1008         fstrcpy(ts->queue[i].user, pjob.user);
1009         fstrcpy(ts->queue[i].file, pjob.jobname);
1010
1011         ts->qcount++;
1012
1013         return 0;
1014 }
1015
1016 struct traverse_count_struct {
1017         int snum, count;
1018 };
1019
1020 /* utility fn to count the number of entries in the print queue */
1021 static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
1022 {
1023         struct traverse_count_struct *ts = (struct traverse_count_struct *)state;
1024         struct printjob pjob;
1025         int jobid;
1026
1027         if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int)) return 0;
1028         memcpy(&jobid, key.dptr, sizeof(jobid));
1029         memcpy(&pjob,  data.dptr, sizeof(pjob));
1030
1031         /* maybe it isn't for this queue */
1032         if (ts->snum != print_queue_snum(pjob.qname)) return 0;
1033
1034         ts->count++;
1035
1036         return 0;
1037 }
1038
1039 /* Sort print jobs by submittal time */
1040
1041 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1042 {
1043         /* Silly cases */
1044
1045         if (!j1 && !j2) return 0;
1046         if (!j1) return -1;
1047         if (!j2) return 1;
1048
1049         /* Sort on job start time */
1050
1051         if (j1->time == j2->time) return 0;
1052         return (j1->time > j2->time) ? 1 : -1;
1053 }
1054
1055 /****************************************************************************
1056 get a printer queue listing
1057 ****************************************************************************/
1058 int print_queue_status(int snum, 
1059                        print_queue_struct **queue,
1060                        print_status_struct *status)
1061 {
1062         struct traverse_struct tstruct;
1063         struct traverse_count_struct tsc;
1064         fstring keystr;
1065         TDB_DATA data, key;
1066
1067         /* make sure the database is up to date */
1068         if (print_cache_expired(snum)) print_queue_update(snum);
1069
1070         *queue = NULL;
1071         
1072         /*
1073          * Fetch the queue status.  We must do this first, as there may
1074          * be no jobs in the queue.
1075          */
1076         ZERO_STRUCTP(status);
1077         slprintf(keystr, sizeof(keystr), "STATUS/%s", lp_servicename(snum));
1078         dos_to_unix(keystr, True);             /* Convert key to unix-codepage */
1079         key.dptr = keystr;
1080         key.dsize = strlen(keystr);
1081         data = tdb_fetch(tdb, key);
1082         if (data.dptr) {
1083                 if (data.dsize == sizeof(*status)) {
1084                         memcpy(status, data.dptr, sizeof(*status));
1085                 }
1086                 free(data.dptr);
1087         }
1088
1089         /*
1090          * Now, fetch the print queue information.  We first count the number
1091          * of entries, and then only retrieve the queue if necessary.
1092          */
1093         tsc.count = 0;
1094         tsc.snum = snum;
1095         
1096         tdb_traverse(tdb, traverse_count_fn_queue, (void *)&tsc);
1097
1098         if (tsc.count == 0)
1099                 return 0;
1100
1101         /* Allocate the queue size. */
1102         if ((tstruct.queue = (print_queue_struct *)
1103              malloc(sizeof(print_queue_struct)*tsc.count))
1104                                 == NULL)
1105                 return 0;
1106
1107         /*
1108          * Fill in the queue.
1109          * We need maxcount as the queue size may have changed between
1110          * the two calls to tdb_traverse.
1111          */
1112         tstruct.qcount = 0;
1113         tstruct.maxcount = tsc.count;
1114         tstruct.snum = snum;
1115
1116         tdb_traverse(tdb, traverse_fn_queue, (void *)&tstruct);
1117
1118         /* Sort the queue by submission time otherwise they are displayed
1119            in hash order. */
1120
1121         qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct),
1122               QSORT_CAST(printjob_comp));
1123
1124         *queue = tstruct.queue;
1125         return tstruct.qcount;
1126 }
1127
1128
1129 /****************************************************************************
1130 turn a queue name into a snum
1131 ****************************************************************************/
1132 int print_queue_snum(char *qname)
1133 {
1134         int snum = lp_servicenumber(qname);
1135         if (snum == -1 || !lp_print_ok(snum)) return -1;
1136         return snum;
1137 }
1138
1139
1140 /****************************************************************************
1141  pause a queue
1142 ****************************************************************************/
1143 BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
1144 {
1145         char *printer_name;
1146         int ret;
1147         
1148         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1149                 *errcode = ERROR_ACCESS_DENIED;
1150                 return False;
1151         }
1152
1153         ret = print_run_command(snum, lp_queuepausecommand(snum), NULL, 
1154                                 NULL);
1155
1156         if (ret != 0) {
1157                 *errcode = ERROR_INVALID_PARAMETER;
1158                 return False;
1159         }
1160
1161         /* force update the database */
1162         print_cache_flush(snum);
1163
1164         /* Send a printer notify message */
1165
1166         printer_name = PRINTERNAME(snum);
1167
1168         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1169
1170         return True;
1171 }
1172
1173 /****************************************************************************
1174  resume a queue
1175 ****************************************************************************/
1176 BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
1177 {
1178         char *printer_name;
1179         int ret;
1180
1181         if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1182                 *errcode = ERROR_ACCESS_DENIED;
1183                 return False;
1184         }
1185
1186         ret = print_run_command(snum, lp_queueresumecommand(snum), NULL, 
1187                                 NULL);
1188
1189         if (ret != 0) {
1190                 *errcode = ERROR_INVALID_PARAMETER;
1191                 return False;
1192         }
1193
1194         /* make sure the database is up to date */
1195         if (print_cache_expired(snum)) print_queue_update(snum);
1196
1197         /* Send a printer notify message */
1198
1199         printer_name = PRINTERNAME(snum);
1200
1201         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1202
1203         return True;
1204 }
1205
1206 /****************************************************************************
1207  purge a queue - implemented by deleting all jobs that we can delete
1208 ****************************************************************************/
1209 BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
1210 {
1211         print_queue_struct *queue;
1212         print_status_struct status;
1213         char *printer_name;
1214         int njobs, i;
1215
1216         njobs = print_queue_status(snum, &queue, &status);
1217
1218         if (print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
1219                 for (i=0;i<njobs;i++) {
1220                         print_job_delete1(queue[i].job);
1221                 }
1222         }
1223
1224         print_queue_update(snum);
1225         safe_free(queue);
1226
1227         /* Send a printer notify message */
1228
1229         printer_name = PRINTERNAME(snum);
1230
1231         message_send_all(conn_tdb_ctx(),MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
1232
1233         return True;
1234 }
1235 #undef OLD_NTDOMAIN