source: trunk/server/source3/printing/printing.c

Last change on this file was 1037, checked in by Silvan Scherrer, 8 years ago

samba server: prevent extra LF in case of printing

File size: 94.2 KB
RevLine 
[862]1/*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
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 3 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, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "system/syslog.h"
24#include "system/filesys.h"
25#include "printing.h"
26#include "../librpc/gen_ndr/ndr_spoolss.h"
27#include "nt_printing.h"
28#include "../librpc/gen_ndr/netlogon.h"
29#include "printing/notify.h"
30#include "printing/pcap.h"
31#include "serverid.h"
32#include "smbd/smbd.h"
33#include "auth.h"
34#include "messages.h"
35#include "util_tdb.h"
36
37#ifdef __OS2__
38#define pipe(A) os2_pipe(A)
39#endif
40
41extern struct current_user current_user;
42extern userdom_struct current_user_info;
43
44/* Current printer interface */
45static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
46
47/*
48 the printing backend revolves around a tdb database that stores the
49 SMB view of the print queue
50
51 The key for this database is a jobid - a internally generated number that
52 uniquely identifies a print job
53
54 reading the print queue involves two steps:
55 - possibly running lpq and updating the internal database from that
56 - reading entries from the database
57
58 jobids are assigned when a job starts spooling.
59*/
60
61static TDB_CONTEXT *rap_tdb;
62static uint16 next_rap_jobid;
63struct rap_jobid_key {
64 fstring sharename;
65 uint32 jobid;
66};
67
68/***************************************************************************
69 Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
70 bit RPC jobids.... JRA.
71***************************************************************************/
72
73uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
74{
75 uint16 rap_jobid;
76 TDB_DATA data, key;
77 struct rap_jobid_key jinfo;
78 uint8 buf[2];
79
80 DEBUG(10,("pjobid_to_rap: called.\n"));
81
82 if (!rap_tdb) {
83 /* Create the in-memory tdb. */
84 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
85 if (!rap_tdb)
86 return 0;
87 }
88
89 ZERO_STRUCT( jinfo );
90 fstrcpy( jinfo.sharename, sharename );
91 jinfo.jobid = jobid;
92 key.dptr = (uint8 *)&jinfo;
93 key.dsize = sizeof(jinfo);
94
95 data = tdb_fetch(rap_tdb, key);
96 if (data.dptr && data.dsize == sizeof(uint16)) {
97 rap_jobid = SVAL(data.dptr, 0);
98 SAFE_FREE(data.dptr);
99 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
100 (unsigned int)jobid, (unsigned int)rap_jobid));
101 return rap_jobid;
102 }
103 SAFE_FREE(data.dptr);
104 /* Not found - create and store mapping. */
105 rap_jobid = ++next_rap_jobid;
106 if (rap_jobid == 0)
107 rap_jobid = ++next_rap_jobid;
108 SSVAL(buf,0,rap_jobid);
109 data.dptr = buf;
110 data.dsize = sizeof(rap_jobid);
111 tdb_store(rap_tdb, key, data, TDB_REPLACE);
112 tdb_store(rap_tdb, data, key, TDB_REPLACE);
113
114 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
115 (unsigned int)jobid, (unsigned int)rap_jobid));
116 return rap_jobid;
117}
118
119bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
120{
121 TDB_DATA data, key;
122 uint8 buf[2];
123
124 DEBUG(10,("rap_to_pjobid called.\n"));
125
126 if (!rap_tdb)
127 return False;
128
129 SSVAL(buf,0,rap_jobid);
130 key.dptr = buf;
131 key.dsize = sizeof(rap_jobid);
132 data = tdb_fetch(rap_tdb, key);
133 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
134 {
135 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
136 if (sharename != NULL) {
137 fstrcpy( sharename, jinfo->sharename );
138 }
139 *pjobid = jinfo->jobid;
140 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
141 (unsigned int)*pjobid, (unsigned int)rap_jobid));
142 SAFE_FREE(data.dptr);
143 return True;
144 }
145
146 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
147 (unsigned int)rap_jobid));
148 SAFE_FREE(data.dptr);
149 return False;
150}
151
152void rap_jobid_delete(const char* sharename, uint32 jobid)
153{
154 TDB_DATA key, data;
155 uint16 rap_jobid;
156 struct rap_jobid_key jinfo;
157 uint8 buf[2];
158
159 DEBUG(10,("rap_jobid_delete: called.\n"));
160
161 if (!rap_tdb)
162 return;
163
164 ZERO_STRUCT( jinfo );
165 fstrcpy( jinfo.sharename, sharename );
166 jinfo.jobid = jobid;
167 key.dptr = (uint8 *)&jinfo;
168 key.dsize = sizeof(jinfo);
169
170 data = tdb_fetch(rap_tdb, key);
171 if (!data.dptr || (data.dsize != sizeof(uint16))) {
172 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
173 (unsigned int)jobid ));
174 SAFE_FREE(data.dptr);
175 return;
176 }
177
178 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
179 (unsigned int)jobid ));
180
181 rap_jobid = SVAL(data.dptr, 0);
182 SAFE_FREE(data.dptr);
183 SSVAL(buf,0,rap_jobid);
184 data.dptr = buf;
185 data.dsize = sizeof(rap_jobid);
186 tdb_delete(rap_tdb, key);
187 tdb_delete(rap_tdb, data);
188}
189
190static int get_queue_status(const char* sharename, print_status_struct *);
191
192/****************************************************************************
193 Initialise the printing backend. Called once at startup before the fork().
194****************************************************************************/
195
196bool print_backend_init(struct messaging_context *msg_ctx)
197{
198 const char *sversion = "INFO/version";
199 int services = lp_numservices();
200 int snum;
201
202 unlink(cache_path("printing.tdb"));
203 mkdir(cache_path("printing"),0755);
204
205 /* handle a Samba upgrade */
206
207 for (snum = 0; snum < services; snum++) {
208 struct tdb_print_db *pdb;
209 if (!lp_print_ok(snum))
210 continue;
211
212 pdb = get_print_db_byname(lp_const_servicename(snum));
213 if (!pdb)
214 continue;
215 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
216 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
217 release_print_db(pdb);
218 return False;
219 }
220 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
221 tdb_wipe_all(pdb->tdb);
222 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
223 }
224 tdb_unlock_bystring(pdb->tdb, sversion);
225 release_print_db(pdb);
226 }
227
228 close_all_print_db(); /* Don't leave any open. */
229
230 /* do NT print initialization... */
231 return nt_printing_init(msg_ctx);
232}
233
234/****************************************************************************
235 Shut down printing backend. Called once at shutdown to close the tdb.
236****************************************************************************/
237
238void printing_end(void)
239{
240 close_all_print_db(); /* Don't leave any open. */
241}
242
243/****************************************************************************
244 Retrieve the set of printing functions for a given service. This allows
245 us to set the printer function table based on the value of the 'printing'
246 service parameter.
247
248 Use the generic interface as the default and only use cups interface only
249 when asked for (and only when supported)
250****************************************************************************/
251
252static struct printif *get_printer_fns_from_type( enum printing_types type )
253{
254 struct printif *printer_fns = &generic_printif;
255
256#ifdef HAVE_CUPS
257 if ( type == PRINT_CUPS ) {
258 printer_fns = &cups_printif;
259 }
260#endif /* HAVE_CUPS */
261
262#ifdef HAVE_IPRINT
263 if ( type == PRINT_IPRINT ) {
264 printer_fns = &iprint_printif;
265 }
266#endif /* HAVE_IPRINT */
267
268 printer_fns->type = type;
269
270 return printer_fns;
271}
272
273static struct printif *get_printer_fns( int snum )
274{
275 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
276}
277
278
279/****************************************************************************
280 Useful function to generate a tdb key.
281****************************************************************************/
282
283static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
284{
285 TDB_DATA ret;
286
287 SIVAL(tmp, 0, jobid);
288 ret.dptr = (uint8 *)tmp;
289 ret.dsize = sizeof(*tmp);
290 return ret;
291}
292
293/****************************************************************************
294 Pack the devicemode to store it in a tdb.
295****************************************************************************/
296static int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
297{
298 enum ndr_err_code ndr_err;
299 DATA_BLOB blob;
300 int len = 0;
301
302 if (devmode) {
303 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
304 devmode,
305 (ndr_push_flags_fn_t)
306 ndr_push_spoolss_DeviceMode);
307 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
308 DEBUG(10, ("pack_devicemode: "
309 "error encoding spoolss_DeviceMode\n"));
310 goto done;
311 }
312 } else {
313 ZERO_STRUCT(blob);
314 }
315
316 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
317
318 if (devmode) {
319 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
320 }
321
322done:
323 return len;
324}
325
326/****************************************************************************
327 Unpack the devicemode to store it in a tdb.
328****************************************************************************/
329static int unpack_devicemode(TALLOC_CTX *mem_ctx,
330 const uint8 *buf, int buflen,
331 struct spoolss_DeviceMode **devmode)
332{
333 struct spoolss_DeviceMode *dm;
334 enum ndr_err_code ndr_err;
335 char *data = NULL;
336 int data_len = 0;
337 DATA_BLOB blob;
338 int len = 0;
339
340 *devmode = NULL;
341
342 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
343 if (!data) {
344 return len;
345 }
346
347 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
348 if (!dm) {
349 goto done;
350 }
351
352 blob = data_blob_const(data, data_len);
353
354 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
355 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
356 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
357 DEBUG(10, ("unpack_devicemode: "
358 "error parsing spoolss_DeviceMode\n"));
359 goto done;
360 }
361
362 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
363 dm->devicename, dm->formname));
364 if (dm->driverextra_data.data) {
365 DEBUG(8, ("with a private section of %d bytes\n",
366 dm->__driverextra_length));
367 }
368
369 *devmode = dm;
370
371done:
372 SAFE_FREE(data);
373 return len;
374}
375
376/***********************************************************************
377 unpack a pjob from a tdb buffer
378***********************************************************************/
379
380static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
381 struct printjob *pjob)
382{
383 int len = 0;
384 int used;
385 uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
386 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
387
388 if (!buf || !pjob) {
389 return -1;
390 }
391
392 len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
393 &pjpid,
394 &pjjobid,
395 &pjsysjob,
396 &pjfd,
397 &pjstarttime,
398 &pjstatus,
399 &pjsize,
400 &pjpage_count,
401 &pjspooled,
402 &pjsmbjob,
403 pjob->filename,
404 pjob->jobname,
405 pjob->user,
406 pjob->clientmachine,
407 pjob->queuename);
408
409 if (len == -1) {
410 return -1;
411 }
412
413 used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
414 if (used == -1) {
415 return -1;
416 }
417
418 len += used;
419
420 pjob->pid = pjpid;
421 pjob->jobid = pjjobid;
422 pjob->sysjob = pjsysjob;
423 pjob->fd = pjfd;
424 pjob->starttime = pjstarttime;
425 pjob->status = pjstatus;
426 pjob->size = pjsize;
427 pjob->page_count = pjpage_count;
428 pjob->spooled = pjspooled;
429 pjob->smbjob = pjsmbjob;
430
431 return len;
432
433}
434
435/****************************************************************************
436 Useful function to find a print job in the database.
437****************************************************************************/
438
439static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
440 const char *sharename,
441 uint32 jobid)
442{
443 struct printjob *pjob;
444 uint32_t tmp;
445 TDB_DATA ret;
446 struct tdb_print_db *pdb = get_print_db_byname(sharename);
447
448 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
449 (unsigned int)jobid, sharename ));
450
451 if (!pdb) {
452 return NULL;
453 }
454
455 ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
456 release_print_db(pdb);
457
458 if (!ret.dptr) {
459 DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
460 jobid));
461 return NULL;
462 }
463
464 pjob = talloc_zero(mem_ctx, struct printjob);
465 if (pjob == NULL) {
466 goto err_out;
467 }
468
469 if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
470 DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
471 talloc_free(pjob);
472 pjob = NULL;
473 goto err_out;
474 }
475
476 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
477 pjob->sysjob, jobid));
478 SMB_ASSERT(pjob->jobid == jobid);
479
480err_out:
481 SAFE_FREE(ret.dptr);
482 return pjob;
483}
484
485/* Convert a unix jobid to a smb jobid */
486
487struct unixjob_traverse_state {
488 int sysjob;
489 uint32 sysjob_to_jobid_value;
490};
491
492static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
493 TDB_DATA data, void *private_data)
494{
495 struct printjob *pjob;
496 struct unixjob_traverse_state *state =
497 (struct unixjob_traverse_state *)private_data;
498
499 if (!data.dptr || data.dsize == 0)
500 return 0;
501
502 pjob = (struct printjob *)data.dptr;
503 if (key.dsize != sizeof(uint32))
504 return 0;
505
506 if (state->sysjob == pjob->sysjob) {
507 state->sysjob_to_jobid_value = pjob->jobid;
508 return 1;
509 }
510
511 return 0;
512}
513
514static uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
515{
516 struct unixjob_traverse_state state;
517
518 state.sysjob = sysjob;
519 state.sysjob_to_jobid_value = (uint32)-1;
520
521 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
522
523 return state.sysjob_to_jobid_value;
524}
525
526/****************************************************************************
527 This is a *horribly expensive call as we have to iterate through all the
528 current printer tdb's. Don't do this often ! JRA.
529****************************************************************************/
530
531uint32 sysjob_to_jobid(int unix_jobid)
532{
533 int services = lp_numservices();
534 int snum;
535 struct unixjob_traverse_state state;
536
537 state.sysjob = unix_jobid;
538 state.sysjob_to_jobid_value = (uint32)-1;
539
540 for (snum = 0; snum < services; snum++) {
541 struct tdb_print_db *pdb;
542 if (!lp_print_ok(snum))
543 continue;
544 pdb = get_print_db_byname(lp_const_servicename(snum));
545 if (!pdb) {
546 continue;
547 }
548 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
549 release_print_db(pdb);
550 if (state.sysjob_to_jobid_value != (uint32)-1)
551 return state.sysjob_to_jobid_value;
552 }
553 return (uint32)-1;
554}
555
556/****************************************************************************
557 Send notifications based on what has changed after a pjob_store.
558****************************************************************************/
559
560static const struct {
561 uint32_t lpq_status;
562 uint32_t spoolss_status;
563} lpq_to_spoolss_status_map[] = {
564 { LPQ_QUEUED, JOB_STATUS_QUEUED },
565 { LPQ_PAUSED, JOB_STATUS_PAUSED },
566 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
567 { LPQ_PRINTING, JOB_STATUS_PRINTING },
568 { LPQ_DELETING, JOB_STATUS_DELETING },
569 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
570 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
571 { LPQ_PRINTED, JOB_STATUS_PRINTED },
572 { LPQ_DELETED, JOB_STATUS_DELETED },
573 { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
574 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
575 { (uint32_t)-1, 0 }
576};
577
578/* Convert a lpq status value stored in printing.tdb into the
579 appropriate win32 API constant. */
580
581static uint32 map_to_spoolss_status(uint32 lpq_status)
582{
583 int i = 0;
584
585 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
586 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
587 return lpq_to_spoolss_status_map[i].spoolss_status;
588 i++;
589 }
590
591 return 0;
592}
593
594/***************************************************************************
595 Append a jobid to the 'jobs changed' list.
596***************************************************************************/
597
598static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
599{
600 TDB_DATA data;
601 uint32_t store_jobid;
602
603 SIVAL(&store_jobid, 0, jobid);
604 data.dptr = (uint8 *) &store_jobid;
605 data.dsize = 4;
606
607 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
608
609 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
610 data) == 0);
611}
612
613/***************************************************************************
614 Remove a jobid from the 'jobs changed' list.
615***************************************************************************/
616
617static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
618{
619 struct tdb_print_db *pdb = get_print_db_byname(sharename);
620 TDB_DATA data, key;
621 size_t job_count, i;
622 bool ret = False;
623 bool gotlock = False;
624
625 if (!pdb) {
626 return False;
627 }
628
629 ZERO_STRUCT(data);
630
631 key = string_tdb_data("INFO/jobs_changed");
632
633 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
634 goto out;
635
636 gotlock = True;
637
638 data = tdb_fetch(pdb->tdb, key);
639
640 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
641 goto out;
642
643 job_count = data.dsize / 4;
644 for (i = 0; i < job_count; i++) {
645 uint32 ch_jobid;
646
647 ch_jobid = IVAL(data.dptr, i*4);
648 if (ch_jobid == jobid) {
649 if (i < job_count -1 )
650 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
651 data.dsize -= 4;
652 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
653 goto out;
654 break;
655 }
656 }
657
658 ret = True;
659 out:
660
661 if (gotlock)
662 tdb_chainunlock(pdb->tdb, key);
663 SAFE_FREE(data.dptr);
664 release_print_db(pdb);
665 if (ret)
666 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
667 else
668 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
669 return ret;
670}
671
672static void pjob_store_notify(struct tevent_context *ev,
673 struct messaging_context *msg_ctx,
674 const char* sharename, uint32 jobid,
675 struct printjob *old_data,
676 struct printjob *new_data,
677 bool *pchanged)
678{
679 bool new_job = false;
680 bool changed = false;
681
682 if (old_data == NULL) {
683 new_job = true;
684 }
685
686 /* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
687 NOTIFY_INFO_DATA buffer, we *have* to send the job submission
688 time first or else we'll end up with potential alignment
689 errors. I don't think the systemtime should be spooled as
690 a string, but this gets us around that error.
691 --jerry (i'll feel dirty for this) */
692
693 if (new_job) {
694 notify_job_submitted(ev, msg_ctx,
695 sharename, jobid, new_data->starttime);
696 notify_job_username(ev, msg_ctx,
697 sharename, jobid, new_data->user);
698 notify_job_name(ev, msg_ctx,
699 sharename, jobid, new_data->jobname);
700 notify_job_status(ev, msg_ctx,
701 sharename, jobid, map_to_spoolss_status(new_data->status));
702 notify_job_total_bytes(ev, msg_ctx,
703 sharename, jobid, new_data->size);
704 notify_job_total_pages(ev, msg_ctx,
705 sharename, jobid, new_data->page_count);
706 } else {
707 if (!strequal(old_data->jobname, new_data->jobname)) {
708 notify_job_name(ev, msg_ctx, sharename,
709 jobid, new_data->jobname);
710 changed = true;
711 }
712
713 if (old_data->status != new_data->status) {
714 notify_job_status(ev, msg_ctx,
715 sharename, jobid,
716 map_to_spoolss_status(new_data->status));
717 }
718
719 if (old_data->size != new_data->size) {
720 notify_job_total_bytes(ev, msg_ctx,
721 sharename, jobid, new_data->size);
722 }
723
724 if (old_data->page_count != new_data->page_count) {
725 notify_job_total_pages(ev, msg_ctx,
726 sharename, jobid,
727 new_data->page_count);
728 }
729 }
730
731 *pchanged = changed;
732}
733
734/****************************************************************************
735 Store a job structure back to the database.
736****************************************************************************/
737
738static bool pjob_store(struct tevent_context *ev,
739 struct messaging_context *msg_ctx,
740 const char* sharename, uint32 jobid,
741 struct printjob *pjob)
742{
743 uint32_t tmp;
744 TDB_DATA old_data, new_data;
745 bool ret = False;
746 struct tdb_print_db *pdb = get_print_db_byname(sharename);
747 uint8 *buf = NULL;
748 int len, newlen, buflen;
749
750
751 if (!pdb)
752 return False;
753
754 /* Get old data */
755
756 old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
757
758 /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
759
760 newlen = 0;
761
762 do {
763 len = 0;
764 buflen = newlen;
765 len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
766 (uint32)pjob->pid,
767 (uint32)pjob->jobid,
768 (uint32)pjob->sysjob,
769 (uint32)pjob->fd,
770 (uint32)pjob->starttime,
771 (uint32)pjob->status,
772 (uint32)pjob->size,
773 (uint32)pjob->page_count,
774 (uint32)pjob->spooled,
775 (uint32)pjob->smbjob,
776 pjob->filename,
777 pjob->jobname,
778 pjob->user,
779 pjob->clientmachine,
780 pjob->queuename);
781
782 len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
783
784 if (buflen != len) {
785 buf = (uint8 *)SMB_REALLOC(buf, len);
786 if (!buf) {
787 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
788 goto done;
789 }
790 newlen = len;
791 }
792 } while ( buflen != len );
793
794
795 /* Store new data */
796
797 new_data.dptr = buf;
798 new_data.dsize = len;
799 ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
800 TDB_REPLACE) == 0);
801
802 /* Send notify updates for what has changed */
803
804 if (ret) {
805 bool changed = false;
806 struct printjob old_pjob;
807
808 if (old_data.dsize) {
809 TALLOC_CTX *tmp_ctx = talloc_new(ev);
810 if (tmp_ctx == NULL)
811 goto done;
812
813 len = unpack_pjob(tmp_ctx, old_data.dptr,
814 old_data.dsize, &old_pjob);
815 if (len != -1 ) {
816 pjob_store_notify(ev,
817 msg_ctx,
818 sharename, jobid, &old_pjob,
819 pjob,
820 &changed);
821 if (changed) {
822 add_to_jobs_changed(pdb, jobid);
823 }
824 }
825 talloc_free(tmp_ctx);
826
827 } else {
828 /* new job */
829 pjob_store_notify(ev, msg_ctx,
830 sharename, jobid, NULL, pjob,
831 &changed);
832 }
833 }
834
835done:
836 release_print_db(pdb);
837 SAFE_FREE( old_data.dptr );
838 SAFE_FREE( buf );
839
840 return ret;
841}
842
843/****************************************************************************
844 Remove a job structure from the database.
845****************************************************************************/
846
847static void pjob_delete(struct tevent_context *ev,
848 struct messaging_context *msg_ctx,
849 const char* sharename, uint32 jobid)
850{
851 uint32_t tmp;
852 struct printjob *pjob;
853 uint32 job_status = 0;
854 struct tdb_print_db *pdb;
855 TALLOC_CTX *tmp_ctx = talloc_new(ev);
856 if (tmp_ctx == NULL) {
857 return;
858 }
859
860 pdb = get_print_db_byname(sharename);
861 if (!pdb) {
862 goto err_out;
863 }
864
865 pjob = print_job_find(tmp_ctx, sharename, jobid);
866 if (!pjob) {
867 DEBUG(5, ("we were asked to delete nonexistent job %u\n",
868 jobid));
869 goto err_release;
870 }
871
872 /* We must cycle through JOB_STATUS_DELETING and
873 JOB_STATUS_DELETED for the port monitor to delete the job
874 properly. */
875
876 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
877 notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
878
879 /* Remove from printing.tdb */
880
881 tdb_delete(pdb->tdb, print_key(jobid, &tmp));
882 remove_from_jobs_added(sharename, jobid);
883 rap_jobid_delete(sharename, jobid);
884err_release:
885 release_print_db(pdb);
886err_out:
887 talloc_free(tmp_ctx);
888}
889
890/****************************************************************************
891 List a unix job in the print database.
892****************************************************************************/
893
894static void print_unix_job(struct tevent_context *ev,
895 struct messaging_context *msg_ctx,
896 const char *sharename, print_queue_struct *q,
897 uint32 jobid)
898{
899 struct printjob pj, *old_pj;
900 TALLOC_CTX *tmp_ctx = talloc_new(ev);
901 if (tmp_ctx == NULL) {
902 return;
903 }
904
905 if (jobid == (uint32)-1) {
906 jobid = q->sysjob + UNIX_JOB_START;
907 }
908
909 /* Preserve the timestamp on an existing unix print job */
910
911 old_pj = print_job_find(tmp_ctx, sharename, jobid);
912
913 ZERO_STRUCT(pj);
914
915 pj.pid = (pid_t)-1;
916 pj.jobid = jobid;
917 pj.sysjob = q->sysjob;
918 pj.fd = -1;
919 pj.starttime = old_pj ? old_pj->starttime : q->time;
920 pj.status = q->status;
921 pj.size = q->size;
922 pj.spooled = True;
923 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
924 if (jobid < UNIX_JOB_START) {
925 pj.smbjob = True;
926 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
927 } else {
928 pj.smbjob = False;
929 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
930 }
931 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
932 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
933
934 pjob_store(ev, msg_ctx, sharename, jobid, &pj);
935 talloc_free(tmp_ctx);
936}
937
938
939struct traverse_struct {
940 print_queue_struct *queue;
941 int qcount, snum, maxcount, total_jobs;
942 const char *sharename;
943 time_t lpq_time;
944 const char *lprm_command;
945 struct printif *print_if;
946 struct tevent_context *ev;
947 struct messaging_context *msg_ctx;
948 TALLOC_CTX *mem_ctx;
949};
950
951/****************************************************************************
952 Utility fn to delete any jobs that are no longer active.
953****************************************************************************/
954
955static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
956{
957 struct traverse_struct *ts = (struct traverse_struct *)state;
958 struct printjob pjob;
959 uint32 jobid;
960 int i = 0;
961
962 if ( key.dsize != sizeof(jobid) )
963 return 0;
964
965 if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
966 return 0;
967 talloc_free(pjob.devmode);
968 jobid = pjob.jobid;
969
970 if (!pjob.smbjob) {
971 /* remove a unix job if it isn't in the system queue any more */
972 for (i=0;i<ts->qcount;i++) {
973 if (ts->queue[i].sysjob == pjob.sysjob) {
974 break;
975 }
976 }
977 if (i == ts->qcount) {
978 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
979 (unsigned int)jobid ));
980 pjob_delete(ts->ev, ts->msg_ctx,
981 ts->sharename, jobid);
982 return 0;
983 }
984
985 /* need to continue the the bottom of the function to
986 save the correct attributes */
987 }
988
989 /* maybe it hasn't been spooled yet */
990 if (!pjob.spooled) {
991 /* if a job is not spooled and the process doesn't
992 exist then kill it. This cleans up after smbd
993 deaths */
994 if (!process_exists_by_pid(pjob.pid)) {
995 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
996 (unsigned int)jobid, (unsigned int)pjob.pid ));
997 pjob_delete(ts->ev, ts->msg_ctx,
998 ts->sharename, jobid);
999 } else
1000 ts->total_jobs++;
1001 return 0;
1002 }
1003
1004 /* this check only makes sense for jobs submitted from Windows clients */
1005
1006 if (pjob.smbjob) {
1007 for (i=0;i<ts->qcount;i++) {
1008 if ( pjob.status == LPQ_DELETED )
1009 continue;
1010
1011 if (ts->queue[i].sysjob == pjob.sysjob) {
1012
1013 /* try to clean up any jobs that need to be deleted */
1014
1015 if ( pjob.status == LPQ_DELETING ) {
1016 int result;
1017
1018 result = (*(ts->print_if->job_delete))(
1019 ts->sharename, ts->lprm_command, &pjob );
1020
1021 if ( result != 0 ) {
1022 /* if we can't delete, then reset the job status */
1023 pjob.status = LPQ_QUEUED;
1024 pjob_store(ts->ev, ts->msg_ctx,
1025 ts->sharename, jobid, &pjob);
1026 }
1027 else {
1028 /* if we deleted the job, the remove the tdb record */
1029 pjob_delete(ts->ev,
1030 ts->msg_ctx,
1031 ts->sharename, jobid);
1032 pjob.status = LPQ_DELETED;
1033 }
1034
1035 }
1036
1037 break;
1038 }
1039 }
1040 }
1041
1042 /* The job isn't in the system queue - we have to assume it has
1043 completed, so delete the database entry. */
1044
1045 if (i == ts->qcount) {
1046
1047 /* A race can occur between the time a job is spooled and
1048 when it appears in the lpq output. This happens when
1049 the job is added to printing.tdb when another smbd
1050 running print_queue_update() has completed a lpq and
1051 is currently traversing the printing tdb and deleting jobs.
1052 Don't delete the job if it was submitted after the lpq_time. */
1053
1054 if (pjob.starttime < ts->lpq_time) {
1055 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
1056 (unsigned int)jobid,
1057 (unsigned int)pjob.starttime,
1058 (unsigned int)ts->lpq_time ));
1059 pjob_delete(ts->ev, ts->msg_ctx,
1060 ts->sharename, jobid);
1061 } else
1062 ts->total_jobs++;
1063 return 0;
1064 }
1065
1066 /* Save the pjob attributes we will store. */
1067 ts->queue[i].sysjob = pjob.sysjob;
1068 ts->queue[i].size = pjob.size;
1069 ts->queue[i].page_count = pjob.page_count;
1070 ts->queue[i].status = pjob.status;
1071 ts->queue[i].priority = 1;
1072 ts->queue[i].time = pjob.starttime;
1073 fstrcpy(ts->queue[i].fs_user, pjob.user);
1074 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
1075
1076 ts->total_jobs++;
1077
1078 return 0;
1079}
1080
1081/****************************************************************************
1082 Check if the print queue has been updated recently enough.
1083****************************************************************************/
1084
1085static void print_cache_flush(const char *sharename)
1086{
1087 fstring key;
1088 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1089
1090 if (!pdb)
1091 return;
1092 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
1093 tdb_store_int32(pdb->tdb, key, -1);
1094 release_print_db(pdb);
1095}
1096
1097/****************************************************************************
1098 Check if someone already thinks they are doing the update.
1099****************************************************************************/
1100
1101static pid_t get_updating_pid(const char *sharename)
1102{
1103 fstring keystr;
1104 TDB_DATA data, key;
1105 pid_t updating_pid;
1106 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1107
1108 if (!pdb)
1109 return (pid_t)-1;
1110 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1111 key = string_tdb_data(keystr);
1112
1113 data = tdb_fetch(pdb->tdb, key);
1114 release_print_db(pdb);
1115 if (!data.dptr || data.dsize != sizeof(pid_t)) {
1116 SAFE_FREE(data.dptr);
1117 return (pid_t)-1;
1118 }
1119
1120 updating_pid = IVAL(data.dptr, 0);
1121 SAFE_FREE(data.dptr);
1122
1123 if (process_exists_by_pid(updating_pid))
1124 return updating_pid;
1125
1126 return (pid_t)-1;
1127}
1128
1129/****************************************************************************
1130 Set the fact that we're doing the update, or have finished doing the update
1131 in the tdb.
1132****************************************************************************/
1133
1134static void set_updating_pid(const fstring sharename, bool updating)
1135{
1136 fstring keystr;
1137 TDB_DATA key;
1138 TDB_DATA data;
1139 pid_t updating_pid = sys_getpid();
1140 uint8 buffer[4];
1141
1142 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1143
1144 if (!pdb)
1145 return;
1146
1147 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
1148 key = string_tdb_data(keystr);
1149
1150 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
1151 updating ? "" : "not ",
1152 sharename ));
1153
1154 if ( !updating ) {
1155 tdb_delete(pdb->tdb, key);
1156 release_print_db(pdb);
1157 return;
1158 }
1159
1160 SIVAL( buffer, 0, updating_pid);
1161 data.dptr = buffer;
1162 data.dsize = 4; /* we always assume this is a 4 byte value */
1163
1164 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1165 release_print_db(pdb);
1166}
1167
1168/****************************************************************************
1169 Sort print jobs by submittal time.
1170****************************************************************************/
1171
1172static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
1173{
1174 /* Silly cases */
1175
1176 if (!j1 && !j2)
1177 return 0;
1178 if (!j1)
1179 return -1;
1180 if (!j2)
1181 return 1;
1182
1183 /* Sort on job start time */
1184
1185 if (j1->time == j2->time)
1186 return 0;
1187 return (j1->time > j2->time) ? 1 : -1;
1188}
1189
1190/****************************************************************************
1191 Store the sorted queue representation for later portmon retrieval.
1192 Skip deleted jobs
1193****************************************************************************/
1194
1195static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
1196{
1197 TDB_DATA data;
1198 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
1199 print_queue_struct *queue = pts->queue;
1200 size_t len;
1201 size_t i;
1202 unsigned int qcount;
1203
1204 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
1205 pts->qcount = max_reported_jobs;
1206 qcount = 0;
1207
1208 /* Work out the size. */
1209 data.dsize = 0;
1210 data.dsize += tdb_pack(NULL, 0, "d", qcount);
1211
1212 for (i = 0; i < pts->qcount; i++) {
1213 if ( queue[i].status == LPQ_DELETED )
1214 continue;
1215
1216 qcount++;
1217 data.dsize += tdb_pack(NULL, 0, "ddddddff",
1218 (uint32)queue[i].sysjob,
1219 (uint32)queue[i].size,
1220 (uint32)queue[i].page_count,
1221 (uint32)queue[i].status,
1222 (uint32)queue[i].priority,
1223 (uint32)queue[i].time,
1224 queue[i].fs_user,
1225 queue[i].fs_file);
1226 }
1227
1228 if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
1229 return;
1230
1231 len = 0;
1232 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
1233 for (i = 0; i < pts->qcount; i++) {
1234 if ( queue[i].status == LPQ_DELETED )
1235 continue;
1236
1237 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
1238 (uint32)queue[i].sysjob,
1239 (uint32)queue[i].size,
1240 (uint32)queue[i].page_count,
1241 (uint32)queue[i].status,
1242 (uint32)queue[i].priority,
1243 (uint32)queue[i].time,
1244 queue[i].fs_user,
1245 queue[i].fs_file);
1246 }
1247
1248 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
1249 TDB_REPLACE);
1250 SAFE_FREE(data.dptr);
1251 return;
1252}
1253
1254static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
1255{
1256 TDB_DATA data;
1257
1258 ZERO_STRUCT(data);
1259
1260 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
1261 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
1262 SAFE_FREE(data.dptr);
1263 ZERO_STRUCT(data);
1264 }
1265
1266 return data;
1267}
1268
1269static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
1270{
1271 unsigned int i;
1272 unsigned int job_count = data.dsize / 4;
1273
1274 for (i = 0; i < job_count; i++) {
1275 uint32 ch_jobid;
1276
1277 ch_jobid = IVAL(data.dptr, i*4);
1278 if (ch_jobid == jobid)
1279 remove_from_jobs_added(sharename, jobid);
1280 }
1281}
1282
1283/****************************************************************************
1284 Check if the print queue has been updated recently enough.
1285****************************************************************************/
1286
1287static bool print_cache_expired(const char *sharename, bool check_pending)
1288{
1289 fstring key;
1290 time_t last_qscan_time, time_now = time(NULL);
1291 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1292 bool result = False;
1293
1294 if (!pdb)
1295 return False;
1296
1297 snprintf(key, sizeof(key), "CACHE/%s", sharename);
1298 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
1299
1300 /*
1301 * Invalidate the queue for 3 reasons.
1302 * (1). last queue scan time == -1.
1303 * (2). Current time - last queue scan time > allowed cache time.
1304 * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default).
1305 * This last test picks up machines for which the clock has been moved
1306 * forward, an lpq scan done and then the clock moved back. Otherwise
1307 * that last lpq scan would stay around for a loooong loooong time... :-). JRA.
1308 */
1309
1310 if (last_qscan_time == ((time_t)-1)
1311 || (time_now - last_qscan_time) >= lp_lpqcachetime()
1312 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
1313 {
1314 uint32 u;
1315 time_t msg_pending_time;
1316
1317 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
1318 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
1319 sharename, (int)last_qscan_time, (int)time_now,
1320 (int)lp_lpqcachetime() ));
1321
1322 /* check if another smbd has already sent a message to update the
1323 queue. Give the pending message one minute to clear and
1324 then send another message anyways. Make sure to check for
1325 clocks that have been run forward and then back again. */
1326
1327 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1328
1329 if ( check_pending
1330 && tdb_fetch_uint32( pdb->tdb, key, &u )
1331 && (msg_pending_time=u) > 0
1332 && msg_pending_time <= time_now
1333 && (time_now - msg_pending_time) < 60 )
1334 {
1335 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
1336 sharename));
1337 goto done;
1338 }
1339
1340 result = True;
1341 }
1342
1343done:
1344 release_print_db(pdb);
1345 return result;
1346}
1347
1348/****************************************************************************
1349 main work for updating the lpq cache for a printer queue
1350****************************************************************************/
1351
1352static void print_queue_update_internal(struct tevent_context *ev,
1353 struct messaging_context *msg_ctx,
1354 const char *sharename,
1355 struct printif *current_printif,
1356 char *lpq_command, char *lprm_command)
1357{
1358 int i, qcount;
1359 print_queue_struct *queue = NULL;
1360 print_status_struct status;
1361 print_status_struct old_status;
1362 struct printjob *pjob;
1363 struct traverse_struct tstruct;
1364 TDB_DATA data, key;
1365 TDB_DATA jcdata;
1366 fstring keystr, cachestr;
1367 struct tdb_print_db *pdb = get_print_db_byname(sharename);
1368 TALLOC_CTX *tmp_ctx = talloc_new(ev);
1369
1370 if ((pdb == NULL) || (tmp_ctx == NULL)) {
1371 return;
1372 }
1373
1374 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
1375 sharename, current_printif->type, lpq_command));
1376
1377 /*
1378 * Update the cache time FIRST ! Stops others even
1379 * attempting to get the lock and doing this
1380 * if the lpq takes a long time.
1381 */
1382
1383 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
1384 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
1385
1386 /* get the current queue using the appropriate interface */
1387 ZERO_STRUCT(status);
1388
1389 qcount = (*(current_printif->queue_get))(sharename,
1390 current_printif->type,
1391 lpq_command, &queue, &status);
1392
1393 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
1394 qcount, (qcount != 1) ? "s" : "", sharename));
1395
1396 /* Sort the queue by submission time otherwise they are displayed
1397 in hash order. */
1398
1399 TYPESAFE_QSORT(queue, qcount, printjob_comp);
1400
1401 /*
1402 any job in the internal database that is marked as spooled
1403 and doesn't exist in the system queue is considered finished
1404 and removed from the database
1405
1406 any job in the system database but not in the internal database
1407 is added as a unix job
1408
1409 fill in any system job numbers as we go
1410 */
1411 jcdata = get_jobs_added_data(pdb);
1412
1413 for (i=0; i<qcount; i++) {
1414 uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
1415 if (jobid == (uint32)-1) {
1416 /* assume its a unix print job */
1417 print_unix_job(ev, msg_ctx,
1418 sharename, &queue[i], jobid);
1419 continue;
1420 }
1421
1422 /* we have an active SMB print job - update its status */
1423 pjob = print_job_find(tmp_ctx, sharename, jobid);
1424 if (!pjob) {
1425 /* err, somethings wrong. Probably smbd was restarted
1426 with jobs in the queue. All we can do is treat them
1427 like unix jobs. Pity. */
1428 DEBUG(1, ("queued print job %d not found in jobs list, "
1429 "assuming unix job\n", jobid));
1430 print_unix_job(ev, msg_ctx,
1431 sharename, &queue[i], jobid);
1432 continue;
1433 }
1434
1435 /* don't reset the status on jobs to be deleted */
1436
1437 if ( pjob->status != LPQ_DELETING )
1438 pjob->status = queue[i].status;
1439
1440 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
1441
1442 check_job_added(sharename, jcdata, jobid);
1443 }
1444
1445 SAFE_FREE(jcdata.dptr);
1446
1447 /* now delete any queued entries that don't appear in the
1448 system queue */
1449 tstruct.queue = queue;
1450 tstruct.qcount = qcount;
1451 tstruct.snum = -1;
1452 tstruct.total_jobs = 0;
1453 tstruct.lpq_time = time(NULL);
1454 tstruct.sharename = sharename;
1455 tstruct.lprm_command = lprm_command;
1456 tstruct.print_if = current_printif;
1457 tstruct.ev = ev;
1458 tstruct.msg_ctx = msg_ctx;
1459 tstruct.mem_ctx = tmp_ctx;
1460
1461 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
1462
1463 /* Store the linearised queue, max jobs only. */
1464 store_queue_struct(pdb, &tstruct);
1465
1466 SAFE_FREE(tstruct.queue);
1467 talloc_free(tmp_ctx);
1468
1469 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
1470 sharename, tstruct.total_jobs ));
1471
1472 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
1473
1474 get_queue_status(sharename, &old_status);
1475 if (old_status.qcount != qcount)
1476 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
1477 old_status.qcount, qcount, sharename));
1478
1479 /* store the new queue status structure */
1480 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
1481 key = string_tdb_data(keystr);
1482
1483 status.qcount = qcount;
1484 data.dptr = (uint8 *)&status;
1485 data.dsize = sizeof(status);
1486 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
1487
1488 /*
1489 * Update the cache time again. We want to do this call
1490 * as little as possible...
1491 */
1492
1493 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
1494 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
1495
1496 /* clear the msg pending record for this queue */
1497
1498 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
1499
1500 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
1501 /* log a message but continue on */
1502
1503 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1504 sharename));
1505 }
1506
1507 release_print_db( pdb );
1508
1509 return;
1510}
1511
1512/****************************************************************************
1513 Update the internal database from the system print queue for a queue.
1514 obtain a lock on the print queue before proceeding (needed when mutiple
1515 smbd processes maytry to update the lpq cache concurrently).
1516****************************************************************************/
1517
1518static void print_queue_update_with_lock( struct tevent_context *ev,
1519 struct messaging_context *msg_ctx,
1520 const char *sharename,
1521 struct printif *current_printif,
1522 char *lpq_command, char *lprm_command )
1523{
1524 fstring keystr;
1525 struct tdb_print_db *pdb;
1526
1527 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
1528 pdb = get_print_db_byname(sharename);
1529 if (!pdb)
1530 return;
1531
1532 if ( !print_cache_expired(sharename, False) ) {
1533 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
1534 release_print_db(pdb);
1535 return;
1536 }
1537
1538 /*
1539 * Check to see if someone else is doing this update.
1540 * This is essentially a mutex on the update.
1541 */
1542
1543 if (get_updating_pid(sharename) != -1) {
1544 release_print_db(pdb);
1545 return;
1546 }
1547
1548 /* Lock the queue for the database update */
1549
1550 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
1551 /* Only wait 10 seconds for this. */
1552 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
1553 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
1554 release_print_db(pdb);
1555 return;
1556 }
1557
1558 /*
1559 * Ensure that no one else got in here.
1560 * If the updating pid is still -1 then we are
1561 * the winner.
1562 */
1563
1564 if (get_updating_pid(sharename) != -1) {
1565 /*
1566 * Someone else is doing the update, exit.
1567 */
1568 tdb_unlock_bystring(pdb->tdb, keystr);
1569 release_print_db(pdb);
1570 return;
1571 }
1572
1573 /*
1574 * We're going to do the update ourselves.
1575 */
1576
1577 /* Tell others we're doing the update. */
1578 set_updating_pid(sharename, True);
1579
1580 /*
1581 * Allow others to enter and notice we're doing
1582 * the update.
1583 */
1584
1585 tdb_unlock_bystring(pdb->tdb, keystr);
1586
1587 /* do the main work now */
1588
1589 print_queue_update_internal(ev, msg_ctx,
1590 sharename, current_printif,
1591 lpq_command, lprm_command);
1592
1593 /* Delete our pid from the db. */
1594 set_updating_pid(sharename, False);
1595 release_print_db(pdb);
1596}
1597
1598/****************************************************************************
1599this is the receive function of the background lpq updater
1600****************************************************************************/
1601void print_queue_receive(struct messaging_context *msg,
1602 void *private_data,
1603 uint32_t msg_type,
1604 struct server_id server_id,
1605 DATA_BLOB *data)
1606{
1607 fstring sharename;
1608 char *lpqcommand = NULL, *lprmcommand = NULL;
1609 int printing_type;
1610 size_t len;
1611
1612 len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
1613 sharename,
1614 &printing_type,
1615 &lpqcommand,
1616 &lprmcommand );
1617
1618 if ( len == -1 ) {
1619 SAFE_FREE(lpqcommand);
1620 SAFE_FREE(lprmcommand);
1621 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
1622 return;
1623 }
1624
1625 print_queue_update_with_lock(server_event_context(), msg, sharename,
1626 get_printer_fns_from_type((enum printing_types)printing_type),
1627 lpqcommand, lprmcommand );
1628
1629 SAFE_FREE(lpqcommand);
1630 SAFE_FREE(lprmcommand);
1631 return;
1632}
1633
1634static void printing_pause_fd_handler(struct tevent_context *ev,
1635 struct tevent_fd *fde,
1636 uint16_t flags,
1637 void *private_data)
1638{
1639 /*
1640 * If pause_pipe[1] is closed it means the parent smbd
1641 * and children exited or aborted.
1642 */
1643 exit_server_cleanly(NULL);
1644}
1645
1646extern struct child_pid *children;
1647extern int num_children;
1648
1649static void add_child_pid(pid_t pid)
1650{
1651 struct child_pid *child;
1652
1653 child = SMB_MALLOC_P(struct child_pid);
1654 if (child == NULL) {
1655 DEBUG(0, ("Could not add child struct -- malloc failed\n"));
1656 return;
1657 }
1658 child->pid = pid;
1659 DLIST_ADD(children, child);
1660 num_children += 1;
1661}
1662
1663/****************************************************************************
1664 Notify smbds of new printcap data
1665**************************************************************************/
1666static void reload_pcap_change_notify(struct tevent_context *ev,
1667 struct messaging_context *msg_ctx)
1668{
1669 /*
1670 * Reload the printers first in the background process so that
1671 * newly added printers get default values created in the registry.
1672 *
1673 * This will block the process for some time (~1 sec per printer), but
1674 * it doesn't block smbd's servering clients.
1675 */
1676 reload_printers_full(ev, msg_ctx);
1677
1678 message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL);
1679}
1680
1681static bool printer_housekeeping_fn(const struct timeval *now,
1682 void *private_data)
1683{
1684 static time_t last_pcap_reload_time = 0;
1685 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1686 time_t t = time_mono(NULL);
1687
1688 DEBUG(5, ("printer housekeeping\n"));
1689
1690 /* if periodic printcap rescan is enabled, see if it's time to reload */
1691 if ((printcap_cache_time != 0)
1692 && (t >= (last_pcap_reload_time + printcap_cache_time))) {
1693 DEBUG( 3,( "Printcap cache time expired.\n"));
1694 pcap_cache_reload(server_event_context(),
1695 smbd_messaging_context(),
1696 &reload_pcap_change_notify);
1697 last_pcap_reload_time = t;
1698 }
1699
1700 return true;
1701}
1702
1703static void printing_sig_term_handler(struct tevent_context *ev,
1704 struct tevent_signal *se,
1705 int signum,
1706 int count,
1707 void *siginfo,
1708 void *private_data)
1709{
1710 exit_server_cleanly("termination signal");
1711}
1712
1713static void printing_sig_hup_handler(struct tevent_context *ev,
1714 struct tevent_signal *se,
1715 int signum,
1716 int count,
1717 void *siginfo,
1718 void *private_data)
1719{
1720 struct messaging_context *msg_ctx = talloc_get_type_abort(
1721 private_data, struct messaging_context);
1722
1723 DEBUG(1,("Reloading printers after SIGHUP\n"));
1724 pcap_cache_reload(ev, msg_ctx,
1725 &reload_pcap_change_notify);
1726}
1727
1728static void printing_conf_updated(struct messaging_context *msg,
1729 void *private_data,
1730 uint32_t msg_type,
1731 struct server_id server_id,
1732 DATA_BLOB *data)
1733{
1734 DEBUG(5,("Reloading printers after conf change\n"));
1735 pcap_cache_reload(messaging_event_context(msg), msg,
1736 &reload_pcap_change_notify);
1737}
1738
1739
1740static pid_t background_lpq_updater_pid = -1;
1741
1742/****************************************************************************
1743main thread of the background lpq updater
1744****************************************************************************/
1745void start_background_queue(struct tevent_context *ev,
1746 struct messaging_context *msg_ctx)
1747{
1748 /* Use local variables for this as we don't
1749 * need to save the parent side of this, just
1750 * ensure it closes when the process exits.
1751 */
1752 int pause_pipe[2];
1753
1754 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
1755
1756 if (pipe(pause_pipe) == -1) {
1757 DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
1758 exit(1);
1759 }
1760
1761 background_lpq_updater_pid = sys_fork();
1762
1763 if (background_lpq_updater_pid == -1) {
1764 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
1765 exit(1);
1766 }
1767
1768 /* Track the printing pid along with other smbd children */
1769 add_child_pid(background_lpq_updater_pid);
1770
1771 if(background_lpq_updater_pid == 0) {
1772 struct tevent_fd *fde;
1773 int ret;
1774 NTSTATUS status;
1775 struct tevent_signal *se;
1776
1777 /* Child. */
1778 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
1779
1780 close(pause_pipe[0]);
1781 pause_pipe[0] = -1;
1782
1783 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
1784
1785 if (!NT_STATUS_IS_OK(status)) {
1786 DEBUG(0,("reinit_after_fork() failed\n"));
1787 smb_panic("reinit_after_fork() failed");
1788 }
1789
1790 se = tevent_add_signal(ev, ev, SIGTERM, 0,
1791 printing_sig_term_handler,
1792 NULL);
1793 if (se == NULL) {
1794 smb_panic("failed to setup SIGTERM handler");
1795 }
1796 se = tevent_add_signal(ev, ev, SIGHUP, 0,
1797 printing_sig_hup_handler,
1798 msg_ctx);
1799 if (se == NULL) {
1800 smb_panic("failed to setup SIGHUP handler");
1801 }
1802
1803 if (!serverid_register(procid_self(),
1804 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
1805 |FLAG_MSG_PRINT_GENERAL)) {
1806 exit(1);
1807 }
1808
1809 if (!locking_init()) {
1810 exit(1);
1811 }
1812
1813 messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
1814 print_queue_receive);
1815 messaging_register(msg_ctx, NULL, MSG_SMB_CONF_UPDATED,
1816 printing_conf_updated);
1817
1818 fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
1819 printing_pause_fd_handler,
1820 NULL);
1821 if (!fde) {
1822 DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
1823 smb_panic("tevent_add_fd() failed for pause_pipe");
1824 }
1825
1826 /* reload on startup to ensure parent smbd is refreshed */
1827 pcap_cache_reload(server_event_context(),
1828 smbd_messaging_context(),
1829 &reload_pcap_change_notify);
1830
1831 if (!(event_add_idle(ev, NULL,
1832 timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
1833 "printer_housekeeping",
1834 printer_housekeeping_fn,
1835 NULL))) {
1836 DEBUG(0, ("Could not add printing housekeeping event\n"));
1837 exit(1);
1838 }
1839
1840 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
1841 ret = tevent_loop_wait(ev);
1842 /* should not be reached */
1843 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
1844 ret, (ret == 0) ? "out of events" : strerror(errno)));
1845 exit(1);
1846 }
1847
1848 close(pause_pipe[1]);
1849}
1850
1851/****************************************************************************
1852update the internal database from the system print queue for a queue
1853****************************************************************************/
1854
1855static void print_queue_update(struct messaging_context *msg_ctx,
1856 int snum, bool force)
1857{
1858 fstring key;
1859 fstring sharename;
1860 char *lpqcommand = NULL;
1861 char *lprmcommand = NULL;
1862 uint8 *buffer = NULL;
1863 size_t len = 0;
1864 size_t newlen;
1865 struct tdb_print_db *pdb;
1866 int type;
1867 struct printif *current_printif;
1868 TALLOC_CTX *ctx = talloc_tos();
1869
1870 fstrcpy( sharename, lp_const_servicename(snum));
1871
1872 /* don't strip out characters like '$' from the printername */
1873
1874 lpqcommand = talloc_string_sub2(ctx,
1875 lp_lpqcommand(snum),
1876 "%p",
1877 lp_printername(snum),
1878 false, false, false);
1879 if (!lpqcommand) {
1880 return;
1881 }
1882 lpqcommand = talloc_sub_advanced(ctx,
1883 lp_servicename(snum),
1884 current_user_info.unix_name,
1885 "",
1886 current_user.ut.gid,
1887 get_current_username(),
1888 current_user_info.domain,
1889 lpqcommand);
1890 if (!lpqcommand) {
1891 return;
1892 }
1893
1894 lprmcommand = talloc_string_sub2(ctx,
1895 lp_lprmcommand(snum),
1896 "%p",
1897 lp_printername(snum),
1898 false, false, false);
1899 if (!lprmcommand) {
1900 return;
1901 }
1902 lprmcommand = talloc_sub_advanced(ctx,
1903 lp_servicename(snum),
1904 current_user_info.unix_name,
1905 "",
1906 current_user.ut.gid,
1907 get_current_username(),
1908 current_user_info.domain,
1909 lprmcommand);
1910 if (!lprmcommand) {
1911 return;
1912 }
1913
1914 /*
1915 * Make sure that the background queue process exists.
1916 * Otherwise just do the update ourselves
1917 */
1918
1919 if ( force || background_lpq_updater_pid == -1 ) {
1920 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
1921 current_printif = get_printer_fns( snum );
1922 print_queue_update_with_lock(server_event_context(), msg_ctx,
1923 sharename, current_printif,
1924 lpqcommand, lprmcommand);
1925
1926 return;
1927 }
1928
1929 type = lp_printing(snum);
1930
1931 /* get the length */
1932
1933 len = tdb_pack( NULL, 0, "fdPP",
1934 sharename,
1935 type,
1936 lpqcommand,
1937 lprmcommand );
1938
1939 buffer = SMB_XMALLOC_ARRAY( uint8, len );
1940
1941 /* now pack the buffer */
1942 newlen = tdb_pack( buffer, len, "fdPP",
1943 sharename,
1944 type,
1945 lpqcommand,
1946 lprmcommand );
1947
1948 SMB_ASSERT( newlen == len );
1949
1950 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
1951 "type = %d, lpq command = [%s] lprm command = [%s]\n",
1952 sharename, type, lpqcommand, lprmcommand ));
1953
1954 /* here we set a msg pending record for other smbd processes
1955 to throttle the number of duplicate print_queue_update msgs
1956 sent. */
1957
1958 pdb = get_print_db_byname(sharename);
1959 if (!pdb) {
1960 SAFE_FREE(buffer);
1961 return;
1962 }
1963
1964 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
1965
1966 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
1967 /* log a message but continue on */
1968
1969 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
1970 sharename));
1971 }
1972
1973 release_print_db( pdb );
1974
1975 /* finally send the message */
1976
1977 messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
1978 MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
1979
1980 SAFE_FREE( buffer );
1981
1982 return;
1983}
1984
1985/****************************************************************************
1986 Create/Update an entry in the print tdb that will allow us to send notify
1987 updates only to interested smbd's.
1988****************************************************************************/
1989
1990bool print_notify_register_pid(int snum)
1991{
1992 TDB_DATA data;
1993 struct tdb_print_db *pdb = NULL;
1994 TDB_CONTEXT *tdb = NULL;
1995 const char *printername;
1996 uint32 mypid = (uint32)sys_getpid();
1997 bool ret = False;
1998 size_t i;
1999
2000 /* if (snum == -1), then the change notify request was
2001 on a print server handle and we need to register on
2002 all print queus */
2003
2004 if (snum == -1)
2005 {
2006 int num_services = lp_numservices();
2007 int idx;
2008
2009 for ( idx=0; idx<num_services; idx++ ) {
2010 if (lp_snum_ok(idx) && lp_print_ok(idx) )
2011 print_notify_register_pid(idx);
2012 }
2013
2014 return True;
2015 }
2016 else /* register for a specific printer */
2017 {
2018 printername = lp_const_servicename(snum);
2019 pdb = get_print_db_byname(printername);
2020 if (!pdb)
2021 return False;
2022 tdb = pdb->tdb;
2023 }
2024
2025 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
2026 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
2027 printername));
2028 if (pdb)
2029 release_print_db(pdb);
2030 return False;
2031 }
2032
2033 data = get_printer_notify_pid_list( tdb, printername, True );
2034
2035 /* Add ourselves and increase the refcount. */
2036
2037 for (i = 0; i < data.dsize; i += 8) {
2038 if (IVAL(data.dptr,i) == mypid) {
2039 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
2040 SIVAL(data.dptr, i+4, new_refcount);
2041 break;
2042 }
2043 }
2044
2045 if (i == data.dsize) {
2046 /* We weren't in the list. Realloc. */
2047 data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
2048 if (!data.dptr) {
2049 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
2050 printername));
2051 goto done;
2052 }
2053 data.dsize += 8;
2054 SIVAL(data.dptr,data.dsize - 8,mypid);
2055 SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */
2056 }
2057
2058 /* Store back the record. */
2059 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2060 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2061list for printer %s\n", printername));
2062 goto done;
2063 }
2064
2065 ret = True;
2066
2067 done:
2068
2069 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2070 if (pdb)
2071 release_print_db(pdb);
2072 SAFE_FREE(data.dptr);
2073 return ret;
2074}
2075
2076/****************************************************************************
2077 Update an entry in the print tdb that will allow us to send notify
2078 updates only to interested smbd's.
2079****************************************************************************/
2080
2081bool print_notify_deregister_pid(int snum)
2082{
2083 TDB_DATA data;
2084 struct tdb_print_db *pdb = NULL;
2085 TDB_CONTEXT *tdb = NULL;
2086 const char *printername;
2087 uint32 mypid = (uint32)sys_getpid();
2088 size_t i;
2089 bool ret = False;
2090
2091 /* if ( snum == -1 ), we are deregister a print server handle
2092 which means to deregister on all print queues */
2093
2094 if (snum == -1)
2095 {
2096 int num_services = lp_numservices();
2097 int idx;
2098
2099 for ( idx=0; idx<num_services; idx++ ) {
2100 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
2101 print_notify_deregister_pid(idx);
2102 }
2103
2104 return True;
2105 }
2106 else /* deregister a specific printer */
2107 {
2108 printername = lp_const_servicename(snum);
2109 pdb = get_print_db_byname(printername);
2110 if (!pdb)
2111 return False;
2112 tdb = pdb->tdb;
2113 }
2114
2115 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
2116 DEBUG(0,("print_notify_register_pid: Failed to lock \
2117printer %s database\n", printername));
2118 if (pdb)
2119 release_print_db(pdb);
2120 return False;
2121 }
2122
2123 data = get_printer_notify_pid_list( tdb, printername, True );
2124
2125 /* Reduce refcount. Remove ourselves if zero. */
2126
2127 for (i = 0; i < data.dsize; ) {
2128 if (IVAL(data.dptr,i) == mypid) {
2129 uint32 refcount = IVAL(data.dptr, i+4);
2130
2131 refcount--;
2132
2133 if (refcount == 0) {
2134 if (data.dsize - i > 8)
2135 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
2136 data.dsize -= 8;
2137 continue;
2138 }
2139 SIVAL(data.dptr, i+4, refcount);
2140 }
2141
2142 i += 8;
2143 }
2144
2145 if (data.dsize == 0)
2146 SAFE_FREE(data.dptr);
2147
2148 /* Store back the record. */
2149 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
2150 DEBUG(0,("print_notify_register_pid: Failed to update pid \
2151list for printer %s\n", printername));
2152 goto done;
2153 }
2154
2155 ret = True;
2156
2157 done:
2158
2159 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
2160 if (pdb)
2161 release_print_db(pdb);
2162 SAFE_FREE(data.dptr);
2163 return ret;
2164}
2165
2166/****************************************************************************
2167 Check if a jobid is valid. It is valid if it exists in the database.
2168****************************************************************************/
2169
2170bool print_job_exists(const char* sharename, uint32 jobid)
2171{
2172 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2173 bool ret;
2174 uint32_t tmp;
2175
2176 if (!pdb)
2177 return False;
2178 ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
2179 release_print_db(pdb);
2180 return ret;
2181}
2182
2183/****************************************************************************
2184 Return the device mode asigned to a specific print job.
2185 Only valid for the process doing the spooling and when the job
2186 has not been spooled.
2187****************************************************************************/
2188
2189struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
2190 const char *sharename,
2191 uint32 jobid)
2192{
2193 struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
2194 if (pjob == NULL) {
2195 return NULL;
2196 }
2197
2198 return pjob->devmode;
2199}
2200
2201/****************************************************************************
2202 Set the name of a job. Only possible for owner.
2203****************************************************************************/
2204
2205bool print_job_set_name(struct tevent_context *ev,
2206 struct messaging_context *msg_ctx,
2207 const char *sharename, uint32 jobid, const char *name)
2208{
2209 struct printjob *pjob;
2210 bool ret;
2211 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2212 if (tmp_ctx == NULL) {
2213 return false;
2214 }
2215
2216 pjob = print_job_find(tmp_ctx, sharename, jobid);
2217 if (!pjob || pjob->pid != sys_getpid()) {
2218 ret = false;
2219 goto err_out;
2220 }
2221
2222 fstrcpy(pjob->jobname, name);
2223 ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2224err_out:
2225 talloc_free(tmp_ctx);
2226 return ret;
2227}
2228
2229/****************************************************************************
2230 Get the name of a job. Only possible for owner.
2231****************************************************************************/
2232
2233bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t jobid, char **name)
2234{
2235 struct printjob *pjob;
2236
2237 pjob = print_job_find(mem_ctx, sharename, jobid);
2238 if (!pjob || pjob->pid != sys_getpid()) {
2239 return false;
2240 }
2241
2242 *name = pjob->jobname;
2243 return true;
2244}
2245
2246
2247/***************************************************************************
2248 Remove a jobid from the 'jobs added' list.
2249***************************************************************************/
2250
2251static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
2252{
2253 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2254 TDB_DATA data, key;
2255 size_t job_count, i;
2256 bool ret = False;
2257 bool gotlock = False;
2258
2259 if (!pdb) {
2260 return False;
2261 }
2262
2263 ZERO_STRUCT(data);
2264
2265 key = string_tdb_data("INFO/jobs_added");
2266
2267 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
2268 goto out;
2269
2270 gotlock = True;
2271
2272 data = tdb_fetch(pdb->tdb, key);
2273
2274 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
2275 goto out;
2276
2277 job_count = data.dsize / 4;
2278 for (i = 0; i < job_count; i++) {
2279 uint32 ch_jobid;
2280
2281 ch_jobid = IVAL(data.dptr, i*4);
2282 if (ch_jobid == jobid) {
2283 if (i < job_count -1 )
2284 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
2285 data.dsize -= 4;
2286 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
2287 goto out;
2288 break;
2289 }
2290 }
2291
2292 ret = True;
2293 out:
2294
2295 if (gotlock)
2296 tdb_chainunlock(pdb->tdb, key);
2297 SAFE_FREE(data.dptr);
2298 release_print_db(pdb);
2299 if (ret)
2300 DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
2301 else
2302 DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
2303 return ret;
2304}
2305
2306/****************************************************************************
2307 Delete a print job - don't update queue.
2308****************************************************************************/
2309
2310static bool print_job_delete1(struct tevent_context *ev,
2311 struct messaging_context *msg_ctx,
2312 int snum, uint32 jobid)
2313{
2314 const char* sharename = lp_const_servicename(snum);
2315 struct printjob *pjob;
2316 int result = 0;
2317 struct printif *current_printif = get_printer_fns( snum );
2318 bool ret;
2319 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2320 if (tmp_ctx == NULL) {
2321 return false;
2322 }
2323
2324 pjob = print_job_find(tmp_ctx, sharename, jobid);
2325 if (!pjob) {
2326 ret = false;
2327 goto err_out;
2328 }
2329
2330 /*
2331 * If already deleting just return.
2332 */
2333
2334 if (pjob->status == LPQ_DELETING) {
2335 ret = true;
2336 goto err_out;
2337 }
2338
2339 /* Hrm - we need to be able to cope with deleting a job before it
2340 has reached the spooler. Just mark it as LPQ_DELETING and
2341 let the print_queue_update() code rmeove the record */
2342
2343
2344 if (pjob->sysjob == -1) {
2345 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
2346 }
2347
2348 /* Set the tdb entry to be deleting. */
2349
2350 pjob->status = LPQ_DELETING;
2351 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2352
2353 if (pjob->spooled && pjob->sysjob != -1)
2354 {
2355 result = (*(current_printif->job_delete))(
2356 lp_printername(snum),
2357 lp_lprmcommand(snum),
2358 pjob);
2359
2360 /* Delete the tdb entry if the delete succeeded or the job hasn't
2361 been spooled. */
2362
2363 if (result == 0) {
2364 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2365 int njobs = 1;
2366
2367 if (!pdb) {
2368 ret = false;
2369 goto err_out;
2370 }
2371 pjob_delete(ev, msg_ctx, sharename, jobid);
2372 /* Ensure we keep a rough count of the number of total jobs... */
2373 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
2374 release_print_db(pdb);
2375 }
2376 }
2377
2378 remove_from_jobs_added( sharename, jobid );
2379
2380 ret = (result == 0);
2381err_out:
2382 talloc_free(tmp_ctx);
2383 return ret;
2384}
2385
2386/****************************************************************************
2387 Return true if the current user owns the print job.
2388****************************************************************************/
2389
2390static bool is_owner(const struct auth_serversupplied_info *server_info,
2391 const char *servicename,
2392 uint32 jobid)
2393{
2394 struct printjob *pjob;
2395 bool ret;
2396 TALLOC_CTX *tmp_ctx = talloc_new(server_info);
2397 if (tmp_ctx == NULL) {
2398 return false;
2399 }
2400
2401 pjob = print_job_find(tmp_ctx, servicename, jobid);
2402 if (!pjob || !server_info) {
2403 ret = false;
2404 goto err_out;
2405 }
2406
2407 ret = strequal(pjob->user, server_info->sanitized_username);
2408err_out:
2409 talloc_free(tmp_ctx);
2410 return ret;
2411}
2412
2413/****************************************************************************
2414 Delete a print job.
2415****************************************************************************/
2416
2417WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
2418 struct messaging_context *msg_ctx,
2419 int snum, uint32_t jobid)
2420{
2421 const char* sharename = lp_const_servicename(snum);
2422 struct printjob *pjob;
2423 bool owner;
2424 WERROR werr;
2425 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2426 if (tmp_ctx == NULL) {
2427 return WERR_NOT_ENOUGH_MEMORY;
2428 }
2429
2430 owner = is_owner(server_info, lp_const_servicename(snum), jobid);
2431
2432 /* Check access against security descriptor or whether the user
2433 owns their job. */
2434
2435 if (!owner &&
2436 !print_access_check(server_info, msg_ctx, snum,
2437 JOB_ACCESS_ADMINISTER)) {
2438 DEBUG(3, ("delete denied by security descriptor\n"));
2439
2440 /* BEGIN_ADMIN_LOG */
2441 sys_adminlog( LOG_ERR,
2442 "Permission denied-- user not allowed to delete, \
2443pause, or resume print job. User name: %s. Printer name: %s.",
2444 uidtoname(server_info->utok.uid),
2445 lp_printername(snum) );
2446 /* END_ADMIN_LOG */
2447
2448 werr = WERR_ACCESS_DENIED;
2449 goto err_out;
2450 }
2451
2452 /*
2453 * get the spooled filename of the print job
2454 * if this works, then the file has not been spooled
2455 * to the underlying print system. Just delete the
2456 * spool file & return.
2457 */
2458
2459 pjob = print_job_find(tmp_ctx, sharename, jobid);
2460 if (!pjob || pjob->spooled || pjob->pid != getpid()) {
2461 DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
2462 } else {
2463 DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
2464 if (unlink(pjob->filename) == -1) {
2465 werr = map_werror_from_unix(errno);
2466 goto err_out;
2467 }
2468 }
2469
2470 if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
2471 werr = WERR_ACCESS_DENIED;
2472 goto err_out;
2473 }
2474
2475 /* force update the database and say the delete failed if the
2476 job still exists */
2477
2478 print_queue_update(msg_ctx, snum, True);
2479
2480 pjob = print_job_find(tmp_ctx, sharename, jobid);
2481 if (pjob && (pjob->status != LPQ_DELETING)) {
2482 werr = WERR_ACCESS_DENIED;
2483 goto err_out;
2484 }
2485 werr = WERR_PRINTER_HAS_JOBS_QUEUED;
2486
2487err_out:
2488 talloc_free(tmp_ctx);
2489 return werr;
2490}
2491
2492/****************************************************************************
2493 Pause a job.
2494****************************************************************************/
2495
2496WERROR print_job_pause(const struct auth_serversupplied_info *server_info,
2497 struct messaging_context *msg_ctx,
2498 int snum, uint32 jobid)
2499{
2500 const char* sharename = lp_const_servicename(snum);
2501 struct printjob *pjob;
2502 int ret = -1;
2503 struct printif *current_printif = get_printer_fns( snum );
2504 WERROR werr;
2505 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2506 if (tmp_ctx == NULL) {
2507 return WERR_NOT_ENOUGH_MEMORY;
2508 }
2509
2510 pjob = print_job_find(tmp_ctx, sharename, jobid);
2511 if (!pjob || !server_info) {
2512 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
2513 (unsigned int)jobid ));
2514 werr = WERR_INVALID_PARAM;
2515 goto err_out;
2516 }
2517
2518 if (!pjob->spooled || pjob->sysjob == -1) {
2519 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
2520 (int)pjob->sysjob, (unsigned int)jobid ));
2521 werr = WERR_INVALID_PARAM;
2522 goto err_out;
2523 }
2524
2525 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2526 !print_access_check(server_info, msg_ctx, snum,
2527 JOB_ACCESS_ADMINISTER)) {
2528 DEBUG(3, ("pause denied by security descriptor\n"));
2529
2530 /* BEGIN_ADMIN_LOG */
2531 sys_adminlog( LOG_ERR,
2532 "Permission denied-- user not allowed to delete, \
2533pause, or resume print job. User name: %s. Printer name: %s.",
2534 uidtoname(server_info->utok.uid),
2535 lp_printername(snum) );
2536 /* END_ADMIN_LOG */
2537
2538 werr = WERR_ACCESS_DENIED;
2539 goto err_out;
2540 }
2541
2542 /* need to pause the spooled entry */
2543 ret = (*(current_printif->job_pause))(snum, pjob);
2544
2545 if (ret != 0) {
2546 werr = WERR_INVALID_PARAM;
2547 goto err_out;
2548 }
2549
2550 /* force update the database */
2551 print_cache_flush(lp_const_servicename(snum));
2552
2553 /* Send a printer notify message */
2554
2555 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2556 JOB_STATUS_PAUSED);
2557
2558 /* how do we tell if this succeeded? */
2559 werr = WERR_OK;
2560err_out:
2561 talloc_free(tmp_ctx);
2562 return werr;
2563}
2564
2565/****************************************************************************
2566 Resume a job.
2567****************************************************************************/
2568
2569WERROR print_job_resume(const struct auth_serversupplied_info *server_info,
2570 struct messaging_context *msg_ctx,
2571 int snum, uint32 jobid)
2572{
2573 const char *sharename = lp_const_servicename(snum);
2574 struct printjob *pjob;
2575 int ret;
2576 struct printif *current_printif = get_printer_fns( snum );
2577 WERROR werr;
2578 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
2579 if (tmp_ctx == NULL)
2580 return WERR_NOT_ENOUGH_MEMORY;
2581
2582 pjob = print_job_find(tmp_ctx, sharename, jobid);
2583 if (!pjob || !server_info) {
2584 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
2585 (unsigned int)jobid ));
2586 werr = WERR_INVALID_PARAM;
2587 goto err_out;
2588 }
2589
2590 if (!pjob->spooled || pjob->sysjob == -1) {
2591 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
2592 (int)pjob->sysjob, (unsigned int)jobid ));
2593 werr = WERR_INVALID_PARAM;
2594 goto err_out;
2595 }
2596
2597 if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
2598 !print_access_check(server_info, msg_ctx, snum,
2599 JOB_ACCESS_ADMINISTER)) {
2600 DEBUG(3, ("resume denied by security descriptor\n"));
2601
2602 /* BEGIN_ADMIN_LOG */
2603 sys_adminlog( LOG_ERR,
2604 "Permission denied-- user not allowed to delete, \
2605pause, or resume print job. User name: %s. Printer name: %s.",
2606 uidtoname(server_info->utok.uid),
2607 lp_printername(snum) );
2608 /* END_ADMIN_LOG */
2609 werr = WERR_ACCESS_DENIED;
2610 goto err_out;
2611 }
2612
2613 ret = (*(current_printif->job_resume))(snum, pjob);
2614
2615 if (ret != 0) {
2616 werr = WERR_INVALID_PARAM;
2617 goto err_out;
2618 }
2619
2620 /* force update the database */
2621 print_cache_flush(lp_const_servicename(snum));
2622
2623 /* Send a printer notify message */
2624
2625 notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
2626 JOB_STATUS_QUEUED);
2627
2628 werr = WERR_OK;
2629err_out:
2630 talloc_free(tmp_ctx);
2631 return werr;
2632}
2633
2634/****************************************************************************
2635 Write to a print file.
2636****************************************************************************/
2637
2638ssize_t print_job_write(struct tevent_context *ev,
2639 struct messaging_context *msg_ctx,
2640 int snum, uint32 jobid, const char *buf, size_t size)
2641{
2642 const char* sharename = lp_const_servicename(snum);
2643 ssize_t return_code;
2644 struct printjob *pjob;
2645 TALLOC_CTX *tmp_ctx = talloc_new(ev);
2646 if (tmp_ctx == NULL) {
2647 return -1;
2648 }
2649
2650 pjob = print_job_find(tmp_ctx, sharename, jobid);
2651 if (!pjob) {
2652 return_code = -1;
2653 goto err_out;
2654 }
2655
2656 /* don't allow another process to get this info - it is meaningless */
2657 if (pjob->pid != sys_getpid()) {
2658 return_code = -1;
2659 goto err_out;
2660 }
2661
2662 /* if SMBD is spooling this can't be allowed */
2663 if (pjob->status == PJOB_SMBD_SPOOLING) {
2664 return_code = -1;
2665 goto err_out;
2666 }
2667
2668 return_code = write_data(pjob->fd, buf, size);
2669 if (return_code > 0) {
2670 pjob->size += size;
2671 pjob_store(ev, msg_ctx, sharename, jobid, pjob);
2672 }
2673err_out:
2674 talloc_free(tmp_ctx);
2675 return return_code;
2676}
2677
2678/****************************************************************************
2679 Get the queue status - do not update if db is out of date.
2680****************************************************************************/
2681
2682static int get_queue_status(const char* sharename, print_status_struct *status)
2683{
2684 fstring keystr;
2685 TDB_DATA data;
2686 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2687 int len;
2688
2689 if (status) {
2690 ZERO_STRUCTP(status);
2691 }
2692
2693 if (!pdb)
2694 return 0;
2695
2696 if (status) {
2697 fstr_sprintf(keystr, "STATUS/%s", sharename);
2698 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
2699 if (data.dptr) {
2700 if (data.dsize == sizeof(print_status_struct))
2701 /* this memcpy is ok since the status struct was
2702 not packed before storing it in the tdb */
2703 memcpy(status, data.dptr, sizeof(print_status_struct));
2704 SAFE_FREE(data.dptr);
2705 }
2706 }
2707 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
2708 release_print_db(pdb);
2709 return (len == -1 ? 0 : len);
2710}
2711
2712/****************************************************************************
2713 Determine the number of jobs in a queue.
2714****************************************************************************/
2715
2716int print_queue_length(struct messaging_context *msg_ctx, int snum,
2717 print_status_struct *pstatus)
2718{
2719 const char* sharename = lp_const_servicename( snum );
2720 print_status_struct status;
2721 int len;
2722
2723 ZERO_STRUCT( status );
2724
2725 /* make sure the database is up to date */
2726 if (print_cache_expired(lp_const_servicename(snum), True))
2727 print_queue_update(msg_ctx, snum, False);
2728
2729 /* also fetch the queue status */
2730 memset(&status, 0, sizeof(status));
2731 len = get_queue_status(sharename, &status);
2732
2733 if (pstatus)
2734 *pstatus = status;
2735
2736 return len;
2737}
2738
2739/***************************************************************************
2740 Allocate a jobid. Hold the lock for as short a time as possible.
2741***************************************************************************/
2742
2743static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
2744 const char *sharename, uint32 *pjobid)
2745{
2746 int i;
2747 uint32 jobid;
2748 enum TDB_ERROR terr;
2749 int ret;
2750
2751 *pjobid = (uint32)-1;
2752
2753 for (i = 0; i < 3; i++) {
2754 /* Lock the database - only wait 20 seconds. */
2755 ret = tdb_lock_bystring_with_timeout(pdb->tdb,
2756 "INFO/nextjob", 20);
2757 if (ret == -1) {
2758 DEBUG(0, ("allocate_print_jobid: "
2759 "Failed to lock printing database %s\n",
2760 sharename));
2761 terr = tdb_error(pdb->tdb);
2762 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2763 }
2764
2765 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
2766 terr = tdb_error(pdb->tdb);
2767 if (terr != TDB_ERR_NOEXIST) {
2768 DEBUG(0, ("allocate_print_jobid: "
2769 "Failed to fetch INFO/nextjob "
2770 "for print queue %s\n", sharename));
2771 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2772 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2773 }
2774 DEBUG(10, ("allocate_print_jobid: "
2775 "No existing jobid in %s\n", sharename));
2776 jobid = 0;
2777 }
2778
2779 DEBUG(10, ("allocate_print_jobid: "
2780 "Read jobid %u from %s\n", jobid, sharename));
2781
2782 jobid = NEXT_JOBID(jobid);
2783
2784 ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
2785 if (ret == -1) {
2786 terr = tdb_error(pdb->tdb);
2787 DEBUG(3, ("allocate_print_jobid: "
2788 "Failed to store INFO/nextjob.\n"));
2789 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2790 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2791 }
2792
2793 /* We've finished with the INFO/nextjob lock. */
2794 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
2795
2796 if (!print_job_exists(sharename, jobid)) {
2797 break;
2798 }
2799 DEBUG(10, ("allocate_print_jobid: "
2800 "Found jobid %u in %s\n", jobid, sharename));
2801 }
2802
2803 if (i > 2) {
2804 DEBUG(0, ("allocate_print_jobid: "
2805 "Failed to allocate a print job for queue %s\n",
2806 sharename));
2807 /* Probably full... */
2808 return WERR_NO_SPOOL_SPACE;
2809 }
2810
2811 /* Store a dummy placeholder. */
2812 {
2813 uint32_t tmp;
2814 TDB_DATA dum;
2815 dum.dptr = NULL;
2816 dum.dsize = 0;
2817 if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
2818 TDB_INSERT) == -1) {
2819 DEBUG(3, ("allocate_print_jobid: "
2820 "jobid (%d) failed to store placeholder.\n",
2821 jobid ));
2822 terr = tdb_error(pdb->tdb);
2823 return ntstatus_to_werror(map_nt_error_from_tdb(terr));
2824 }
2825 }
2826
2827 *pjobid = jobid;
2828 return WERR_OK;
2829}
2830
2831/***************************************************************************
2832 Append a jobid to the 'jobs added' list.
2833***************************************************************************/
2834
2835static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
2836{
2837 TDB_DATA data;
2838 uint32 store_jobid;
2839
2840 SIVAL(&store_jobid, 0, jobid);
2841 data.dptr = (uint8 *)&store_jobid;
2842 data.dsize = 4;
2843
2844 DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
2845
2846 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
2847 data) == 0);
2848}
2849
2850
2851/***************************************************************************
2852 Do all checks needed to determine if we can start a job.
2853***************************************************************************/
2854
2855static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
2856 struct messaging_context *msg_ctx,
2857 int snum, int *njobs)
2858{
2859 const char *sharename = lp_const_servicename(snum);
2860 uint64_t dspace, dsize;
2861 uint64_t minspace;
2862 int ret;
2863
2864 if (!print_access_check(server_info, msg_ctx, snum,
2865 PRINTER_ACCESS_USE)) {
2866 DEBUG(3, ("print_job_checks: "
2867 "job start denied by security descriptor\n"));
2868 return WERR_ACCESS_DENIED;
2869 }
2870
2871 if (!print_time_access_check(server_info, msg_ctx, sharename)) {
2872 DEBUG(3, ("print_job_checks: "
2873 "job start denied by time check\n"));
2874 return WERR_ACCESS_DENIED;
2875 }
2876
2877 /* see if we have sufficient disk space */
2878 if (lp_minprintspace(snum)) {
2879 minspace = lp_minprintspace(snum);
2880 ret = sys_fsusage(lp_pathname(snum), &dspace, &dsize);
2881 if (ret == 0 && dspace < 2*minspace) {
2882 DEBUG(3, ("print_job_checks: "
2883 "disk space check failed.\n"));
2884 return WERR_NO_SPOOL_SPACE;
2885 }
2886 }
2887
2888 /* for autoloaded printers, check that the printcap entry still exists */
2889 if (lp_autoloaded(snum) && !pcap_printername_ok(sharename)) {
2890 DEBUG(3, ("print_job_checks: printer name %s check failed.\n",
2891 sharename));
2892 return WERR_ACCESS_DENIED;
2893 }
2894
2895 /* Insure the maximum queue size is not violated */
2896 *njobs = print_queue_length(msg_ctx, snum, NULL);
2897 if (*njobs > lp_maxprintjobs(snum)) {
2898 DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
2899 "larger than max printjobs per queue (%d).\n",
2900 sharename, *njobs, lp_maxprintjobs(snum)));
2901 return WERR_NO_SPOOL_SPACE;
2902 }
2903
2904 return WERR_OK;
2905}
2906
2907/***************************************************************************
2908 Create a job file.
2909***************************************************************************/
2910
2911static WERROR print_job_spool_file(int snum, uint32_t jobid,
2912 const char *output_file,
2913 struct printjob *pjob)
2914{
2915 WERROR werr;
2916 SMB_STRUCT_STAT st;
2917 const char *path;
2918 int len;
2919
2920 /* if this file is within the printer path, it means that smbd
2921 * is spooling it and will pass us control when it is finished.
2922 * Verify that the file name is ok, within path, and it is
2923 * already already there */
2924 if (output_file) {
2925 path = lp_pathname(snum);
2926 len = strlen(path);
2927 if (strncmp(output_file, path, len) == 0 &&
2928 (output_file[len - 1] == '/' || output_file[len] == '/')) {
2929
2930 /* verify path is not too long */
2931 if (strlen(output_file) >= sizeof(pjob->filename)) {
2932 return WERR_INVALID_NAME;
2933 }
2934
2935 /* verify that the file exists */
2936 if (sys_stat(output_file, &st, false) != 0) {
2937 return WERR_INVALID_NAME;
2938 }
2939
2940 fstrcpy(pjob->filename, output_file);
2941
2942 DEBUG(3, ("print_job_spool_file:"
2943 "External spooling activated"));
2944
2945 /* we do not open the file until spooling is done */
2946 pjob->fd = -1;
2947 pjob->status = PJOB_SMBD_SPOOLING;
2948
2949 return WERR_OK;
2950 }
2951 }
2952
2953 slprintf(pjob->filename, sizeof(pjob->filename)-1,
2954 "%s/%sXXXXXX", lp_pathname(snum), PRINT_SPOOL_PREFIX);
2955 pjob->fd = mkstemp(pjob->filename);
2956
[1037]2957#ifdef __OS2__
2958 if (pjob->fd >= 0)
2959 setmode(pjob->fd, O_BINARY);
2960#endif
[862]2961 if (pjob->fd == -1) {
2962 werr = map_werror_from_unix(errno);
2963 if (W_ERROR_EQUAL(werr, WERR_ACCESS_DENIED)) {
2964 /* Common setup error, force a report. */
2965 DEBUG(0, ("print_job_spool_file: "
2966 "insufficient permissions to open spool "
2967 "file %s.\n", pjob->filename));
2968 } else {
2969 /* Normal case, report at level 3 and above. */
2970 DEBUG(3, ("print_job_spool_file: "
2971 "can't open spool file %s\n",
2972 pjob->filename));
2973 }
2974 return werr;
2975 }
2976
2977 return WERR_OK;
2978}
2979
2980/***************************************************************************
2981 Start spooling a job - return the jobid.
2982***************************************************************************/
2983
2984WERROR print_job_start(const struct auth_serversupplied_info *server_info,
2985 struct messaging_context *msg_ctx,
2986 const char *clientmachine,
2987 int snum, const char *docname, const char *filename,
2988 struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
2989{
2990 uint32_t jobid;
2991 char *path;
2992 struct printjob pjob;
2993 const char *sharename = lp_const_servicename(snum);
2994 struct tdb_print_db *pdb = get_print_db_byname(sharename);
2995 int njobs;
2996 WERROR werr;
2997
2998 if (!pdb) {
2999 return WERR_INTERNAL_DB_CORRUPTION;
3000 }
3001
3002 path = lp_pathname(snum);
3003
3004 werr = print_job_checks(server_info, msg_ctx, snum, &njobs);
3005 if (!W_ERROR_IS_OK(werr)) {
3006 release_print_db(pdb);
3007 return werr;
3008 }
3009
3010 DEBUG(10, ("print_job_start: "
3011 "Queue %s number of jobs (%d), max printjobs = %d\n",
3012 sharename, njobs, lp_maxprintjobs(snum)));
3013
3014 werr = allocate_print_jobid(pdb, snum, sharename, &jobid);
3015 if (!W_ERROR_IS_OK(werr)) {
3016 goto fail;
3017 }
3018
3019 /* create the database entry */
3020
3021 ZERO_STRUCT(pjob);
3022
3023 pjob.pid = sys_getpid();
3024 pjob.jobid = jobid;
3025 pjob.sysjob = -1;
3026 pjob.fd = -1;
3027 pjob.starttime = time(NULL);
3028 pjob.status = LPQ_SPOOLING;
3029 pjob.size = 0;
3030 pjob.spooled = False;
3031 pjob.smbjob = True;
3032 pjob.devmode = devmode;
3033
3034 fstrcpy(pjob.jobname, docname);
3035
3036 fstrcpy(pjob.clientmachine, clientmachine);
3037
3038 fstrcpy(pjob.user, lp_printjob_username(snum));
3039 standard_sub_advanced(sharename, server_info->sanitized_username,
3040 path, server_info->utok.gid,
3041 server_info->sanitized_username,
3042 server_info->info3->base.domain.string,
3043 pjob.user, sizeof(pjob.user)-1);
3044 /* ensure NULL termination */
3045 pjob.user[sizeof(pjob.user)-1] = '\0';
3046
3047 fstrcpy(pjob.queuename, lp_const_servicename(snum));
3048
3049 /* we have a job entry - now create the spool file */
3050 werr = print_job_spool_file(snum, jobid, filename, &pjob);
3051 if (!W_ERROR_IS_OK(werr)) {
3052 goto fail;
3053 }
3054
3055 pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
3056
3057 /* Update the 'jobs added' entry used by print_queue_status. */
3058 add_to_jobs_added(pdb, jobid);
3059
3060 /* Ensure we keep a rough count of the number of total jobs... */
3061 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
3062
3063 release_print_db(pdb);
3064
3065 *_jobid = jobid;
3066 return WERR_OK;
3067
3068fail:
3069 if (jobid != -1) {
3070 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3071 }
3072
3073 release_print_db(pdb);
3074
3075 DEBUG(3, ("print_job_start: returning fail. "
3076 "Error = %s\n", win_errstr(werr)));
3077 return werr;
3078}
3079
3080/****************************************************************************
3081 Update the number of pages spooled to jobid
3082****************************************************************************/
3083
3084void print_job_endpage(struct messaging_context *msg_ctx,
3085 int snum, uint32 jobid)
3086{
3087 const char* sharename = lp_const_servicename(snum);
3088 struct printjob *pjob;
3089 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3090 if (tmp_ctx == NULL) {
3091 return;
3092 }
3093
3094 pjob = print_job_find(tmp_ctx, sharename, jobid);
3095 if (!pjob) {
3096 goto err_out;
3097 }
3098 /* don't allow another process to get this info - it is meaningless */
3099 if (pjob->pid != sys_getpid()) {
3100 goto err_out;
3101 }
3102
3103 pjob->page_count++;
3104 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3105err_out:
3106 talloc_free(tmp_ctx);
3107}
3108
3109/****************************************************************************
3110 Print a file - called on closing the file. This spools the job.
3111 If normal close is false then we're tearing down the jobs - treat as an
3112 error.
3113****************************************************************************/
3114
3115NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
3116 uint32 jobid, enum file_close_type close_type)
3117{
3118 const char* sharename = lp_const_servicename(snum);
3119 struct printjob *pjob;
3120 int ret;
3121 SMB_STRUCT_STAT sbuf;
3122 struct printif *current_printif = get_printer_fns(snum);
3123 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
3124 char *lpq_cmd;
3125 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3126 if (tmp_ctx == NULL) {
3127 return NT_STATUS_NO_MEMORY;
3128 }
3129
3130 pjob = print_job_find(tmp_ctx, sharename, jobid);
3131 if (!pjob) {
3132 status = NT_STATUS_PRINT_CANCELLED;
3133 goto err_out;
3134 }
3135
3136 if (pjob->spooled || pjob->pid != sys_getpid()) {
3137 status = NT_STATUS_ACCESS_DENIED;
3138 goto err_out;
3139 }
3140
3141 if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
3142 if (pjob->status == PJOB_SMBD_SPOOLING) {
3143 /* take over the file now, smbd is done */
3144 if (sys_stat(pjob->filename, &sbuf, false) != 0) {
3145 status = map_nt_error_from_unix(errno);
3146 DEBUG(3, ("print_job_end: "
3147 "stat file failed for jobid %d\n",
3148 jobid));
3149 goto fail;
3150 }
3151
3152 pjob->status = LPQ_SPOOLING;
3153
3154 } else {
3155
3156 if ((sys_fstat(pjob->fd, &sbuf, false) != 0)) {
3157 status = map_nt_error_from_unix(errno);
3158 close(pjob->fd);
3159 DEBUG(3, ("print_job_end: "
3160 "stat file failed for jobid %d\n",
3161 jobid));
3162 goto fail;
3163 }
3164
3165 close(pjob->fd);
3166 }
3167
3168 pjob->size = sbuf.st_ex_size;
3169 } else {
3170
3171 /*
3172 * Not a normal close, something has gone wrong. Cleanup.
3173 */
3174 if (pjob->fd != -1) {
3175 close(pjob->fd);
3176 }
3177 goto fail;
3178 }
3179
3180 /* Technically, this is not quite right. If the printer has a separator
3181 * page turned on, the NT spooler prints the separator page even if the
3182 * print job is 0 bytes. 010215 JRR */
3183 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
3184 /* don't bother spooling empty files or something being deleted. */
3185 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
3186 pjob->filename, pjob->size ? "deleted" : "zero length" ));
3187 unlink(pjob->filename);
3188 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3189 return NT_STATUS_OK;
3190 }
3191
3192 /* don't strip out characters like '$' from the printername */
3193 lpq_cmd = talloc_string_sub2(tmp_ctx,
3194 lp_lpqcommand(snum),
3195 "%p",
3196 lp_printername(snum),
3197 false, false, false);
3198 if (lpq_cmd == NULL) {
3199 status = NT_STATUS_PRINT_CANCELLED;
3200 goto fail;
3201 }
3202 lpq_cmd = talloc_sub_advanced(tmp_ctx,
3203 lp_servicename(snum),
3204 current_user_info.unix_name,
3205 "",
3206 current_user.ut.gid,
3207 get_current_username(),
3208 current_user_info.domain,
3209 lpq_cmd);
3210 if (lpq_cmd == NULL) {
3211 status = NT_STATUS_PRINT_CANCELLED;
3212 goto fail;
3213 }
3214
3215 ret = (*(current_printif->job_submit))(snum, pjob,
3216 current_printif->type, lpq_cmd);
3217 if (ret) {
3218 status = NT_STATUS_PRINT_CANCELLED;
3219 goto fail;
3220 }
3221
3222 /* The print job has been successfully handed over to the back-end */
3223
3224 pjob->spooled = True;
3225 pjob->status = LPQ_QUEUED;
3226 pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
3227
3228 /* make sure the database is up to date */
3229 if (print_cache_expired(lp_const_servicename(snum), True))
3230 print_queue_update(msg_ctx, snum, False);
3231
3232 return NT_STATUS_OK;
3233
3234fail:
3235
3236 /* The print job was not successfully started. Cleanup */
3237 /* Still need to add proper error return propagation! 010122:JRR */
3238 pjob->fd = -1;
3239 unlink(pjob->filename);
3240 pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
3241err_out:
3242 talloc_free(tmp_ctx);
3243 return status;
3244}
3245
3246/****************************************************************************
3247 Get a snapshot of jobs in the system without traversing.
3248****************************************************************************/
3249
3250static bool get_stored_queue_info(struct messaging_context *msg_ctx,
3251 struct tdb_print_db *pdb, int snum,
3252 int *pcount, print_queue_struct **ppqueue)
3253{
3254 TDB_DATA data, cgdata, jcdata;
3255 print_queue_struct *queue = NULL;
3256 uint32 qcount = 0;
3257 uint32 extra_count = 0;
3258 uint32_t changed_count = 0;
3259 int total_count = 0;
3260 size_t len = 0;
3261 uint32 i;
3262 int max_reported_jobs = lp_max_reported_jobs(snum);
3263 bool ret = False;
3264 const char* sharename = lp_servicename(snum);
3265 TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
3266 if (tmp_ctx == NULL) {
3267 return false;
3268 }
3269
3270 /* make sure the database is up to date */
3271 if (print_cache_expired(lp_const_servicename(snum), True))
3272 print_queue_update(msg_ctx, snum, False);
3273
3274 *pcount = 0;
3275 *ppqueue = NULL;
3276
3277 ZERO_STRUCT(data);
3278 ZERO_STRUCT(cgdata);
3279
3280 /* Get the stored queue data. */
3281 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
3282
3283 if (data.dptr && data.dsize >= sizeof(qcount))
3284 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
3285
3286 /* Get the added jobs list. */
3287 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_added"));
3288 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
3289 extra_count = cgdata.dsize/4;
3290
3291 /* Get the changed jobs list. */
3292 jcdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
3293 if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
3294 changed_count = jcdata.dsize / 4;
3295
3296 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
3297
3298 /* Allocate the queue size. */
3299 if (qcount == 0 && extra_count == 0)
3300 goto out;
3301
3302 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
3303 goto out;
3304
3305 /* Retrieve the linearised queue data. */
3306
3307 for( i = 0; i < qcount; i++) {
3308 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
3309 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
3310 &qjob,
3311 &qsize,
3312 &qpage_count,
3313 &qstatus,
3314 &qpriority,
3315 &qtime,
3316 queue[i].fs_user,
3317 queue[i].fs_file);
3318 queue[i].sysjob = qjob;
3319 queue[i].size = qsize;
3320 queue[i].page_count = qpage_count;
3321 queue[i].status = qstatus;
3322 queue[i].priority = qpriority;
3323 queue[i].time = qtime;
3324 }
3325
3326 total_count = qcount;
3327
3328 /* Add new jobids to the queue. */
3329 for( i = 0; i < extra_count; i++) {
3330 uint32 jobid;
3331 struct printjob *pjob;
3332
3333 jobid = IVAL(cgdata.dptr, i*4);
3334 DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
3335 pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
3336 if (!pjob) {
3337 DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
3338 remove_from_jobs_added(sharename, jobid);
3339 continue;
3340 }
3341
3342 queue[total_count].sysjob = jobid;
3343 queue[total_count].size = pjob->size;
3344 queue[total_count].page_count = pjob->page_count;
3345 queue[total_count].status = pjob->status;
3346 queue[total_count].priority = 1;
3347 queue[total_count].time = pjob->starttime;
3348 fstrcpy(queue[total_count].fs_user, pjob->user);
3349 fstrcpy(queue[total_count].fs_file, pjob->jobname);
3350 total_count++;
3351 talloc_free(pjob);
3352 }
3353
3354 /* Update the changed jobids. */
3355 for (i = 0; i < changed_count; i++) {
3356 uint32_t jobid = IVAL(jcdata.dptr, i * 4);
3357 uint32_t j;
3358 bool found = false;
3359
3360 for (j = 0; j < total_count; j++) {
3361 if (queue[j].sysjob == jobid) {
3362 found = true;
3363 break;
3364 }
3365 }
3366
3367 if (found) {
3368 struct printjob *pjob;
3369
3370 DEBUG(5,("get_stored_queue_info: changed job: %u\n",
3371 (unsigned int) jobid));
3372
3373 pjob = print_job_find(tmp_ctx, sharename, jobid);
3374 if (pjob == NULL) {
3375 DEBUG(5,("get_stored_queue_info: failed to find "
3376 "changed job = %u\n",
3377 (unsigned int) jobid));
3378 remove_from_jobs_changed(sharename, jobid);
3379 continue;
3380 }
3381
3382 queue[j].sysjob = jobid;
3383 queue[j].size = pjob->size;
3384 queue[j].page_count = pjob->page_count;
3385 queue[j].status = pjob->status;
3386 queue[j].priority = 1;
3387 queue[j].time = pjob->starttime;
3388 fstrcpy(queue[j].fs_user, pjob->user);
3389 fstrcpy(queue[j].fs_file, pjob->jobname);
3390 talloc_free(pjob);
3391
3392 DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
3393 (unsigned int) j, (unsigned int) jobid, pjob->jobname));
3394 }
3395
3396 remove_from_jobs_changed(sharename, jobid);
3397 }
3398
3399 /* Sort the queue by submission time otherwise they are displayed
3400 in hash order. */
3401
3402 TYPESAFE_QSORT(queue, total_count, printjob_comp);
3403
3404 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
3405
3406 if (max_reported_jobs && total_count > max_reported_jobs)
3407 total_count = max_reported_jobs;
3408
3409 *ppqueue = queue;
3410 *pcount = total_count;
3411
3412 ret = True;
3413
3414 out:
3415
3416 SAFE_FREE(data.dptr);
3417 SAFE_FREE(cgdata.dptr);
3418 talloc_free(tmp_ctx);
3419 return ret;
3420}
3421
3422/****************************************************************************
3423 Get a printer queue listing.
3424 set queue = NULL and status = NULL if you just want to update the cache
3425****************************************************************************/
3426
3427int print_queue_status(struct messaging_context *msg_ctx, int snum,
3428 print_queue_struct **ppqueue,
3429 print_status_struct *status)
3430{
3431 fstring keystr;
3432 TDB_DATA data, key;
3433 const char *sharename;
3434 struct tdb_print_db *pdb;
3435 int count = 0;
3436
3437 /* make sure the database is up to date */
3438
3439 if (print_cache_expired(lp_const_servicename(snum), True))
3440 print_queue_update(msg_ctx, snum, False);
3441
3442 /* return if we are done */
3443 if ( !ppqueue || !status )
3444 return 0;
3445
3446 *ppqueue = NULL;
3447 sharename = lp_const_servicename(snum);
3448 pdb = get_print_db_byname(sharename);
3449
3450 if (!pdb)
3451 return 0;
3452
3453 /*
3454 * Fetch the queue status. We must do this first, as there may
3455 * be no jobs in the queue.
3456 */
3457
3458 ZERO_STRUCTP(status);
3459 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
3460 key = string_tdb_data(keystr);
3461
3462 data = tdb_fetch(pdb->tdb, key);
3463 if (data.dptr) {
3464 if (data.dsize == sizeof(*status)) {
3465 /* this memcpy is ok since the status struct was
3466 not packed before storing it in the tdb */
3467 memcpy(status, data.dptr, sizeof(*status));
3468 }
3469 SAFE_FREE(data.dptr);
3470 }
3471
3472 /*
3473 * Now, fetch the print queue information. We first count the number
3474 * of entries, and then only retrieve the queue if necessary.
3475 */
3476
3477 if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
3478 release_print_db(pdb);
3479 return 0;
3480 }
3481
3482 release_print_db(pdb);
3483 return count;
3484}
3485
3486/****************************************************************************
3487 Pause a queue.
3488****************************************************************************/
3489
3490WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
3491 struct messaging_context *msg_ctx, int snum)
3492{
3493 int ret;
3494 struct printif *current_printif = get_printer_fns( snum );
3495
3496 if (!print_access_check(server_info, msg_ctx, snum,
3497 PRINTER_ACCESS_ADMINISTER)) {
3498 return WERR_ACCESS_DENIED;
3499 }
3500
3501
3502 become_root();
3503
3504 ret = (*(current_printif->queue_pause))(snum);
3505
3506 unbecome_root();
3507
3508 if (ret != 0) {
3509 return WERR_INVALID_PARAM;
3510 }
3511
3512 /* force update the database */
3513 print_cache_flush(lp_const_servicename(snum));
3514
3515 /* Send a printer notify message */
3516
3517 notify_printer_status(server_event_context(), msg_ctx, snum,
3518 PRINTER_STATUS_PAUSED);
3519
3520 return WERR_OK;
3521}
3522
3523/****************************************************************************
3524 Resume a queue.
3525****************************************************************************/
3526
3527WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
3528 struct messaging_context *msg_ctx, int snum)
3529{
3530 int ret;
3531 struct printif *current_printif = get_printer_fns( snum );
3532
3533 if (!print_access_check(server_info, msg_ctx, snum,
3534 PRINTER_ACCESS_ADMINISTER)) {
3535 return WERR_ACCESS_DENIED;
3536 }
3537
3538 become_root();
3539
3540 ret = (*(current_printif->queue_resume))(snum);
3541
3542 unbecome_root();
3543
3544 if (ret != 0) {
3545 return WERR_INVALID_PARAM;
3546 }
3547
3548 /* make sure the database is up to date */
3549 if (print_cache_expired(lp_const_servicename(snum), True))
3550 print_queue_update(msg_ctx, snum, True);
3551
3552 /* Send a printer notify message */
3553
3554 notify_printer_status(server_event_context(), msg_ctx, snum,
3555 PRINTER_STATUS_OK);
3556
3557 return WERR_OK;
3558}
3559
3560/****************************************************************************
3561 Purge a queue - implemented by deleting all jobs that we can delete.
3562****************************************************************************/
3563
3564WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
3565 struct messaging_context *msg_ctx, int snum)
3566{
3567 print_queue_struct *queue;
3568 print_status_struct status;
3569 int njobs, i;
3570 bool can_job_admin;
3571
3572 /* Force and update so the count is accurate (i.e. not a cached count) */
3573 print_queue_update(msg_ctx, snum, True);
3574
3575 can_job_admin = print_access_check(server_info,
3576 msg_ctx,
3577 snum,
3578 JOB_ACCESS_ADMINISTER);
3579 njobs = print_queue_status(msg_ctx, snum, &queue, &status);
3580
3581 if ( can_job_admin )
3582 become_root();
3583
3584 for (i=0;i<njobs;i++) {
3585 bool owner = is_owner(server_info, lp_const_servicename(snum),
3586 queue[i].sysjob);
3587
3588 if (owner || can_job_admin) {
3589 print_job_delete1(server_event_context(), msg_ctx,
3590 snum, queue[i].sysjob);
3591 }
3592 }
3593
3594 if ( can_job_admin )
3595 unbecome_root();
3596
3597 /* update the cache */
3598 print_queue_update(msg_ctx, snum, True);
3599
3600 SAFE_FREE(queue);
3601
3602 return WERR_OK;
3603}
Note: See TracBrowser for help on using the repository browser.