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