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