Line data Source code
1 : /*
2 : Unix SMB/Netbios implementation.
3 : Version 3.0
4 : printing backend routines
5 : Copyright (C) Tim Potter, 2002
6 : Copyright (C) Gerald Carter, 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 "printing.h"
24 : #include "../librpc/gen_ndr/spoolss.h"
25 : #include "nt_printing.h"
26 : #include "printing/notify.h"
27 : #include "messages.h"
28 : #include "util_tdb.h"
29 : #include "lib/util/string_wrappers.h"
30 :
31 : static TALLOC_CTX *send_ctx;
32 :
33 : static unsigned int num_messages;
34 :
35 : static struct notify_queue {
36 : struct notify_queue *next, *prev;
37 : struct spoolss_notify_msg *msg;
38 : struct timeval tv;
39 : uint8_t *buf;
40 : size_t buflen;
41 : } *notify_queue_head = NULL;
42 :
43 : static struct tevent_timer *notify_event;
44 :
45 : static bool print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx,
46 : size_t *p_num_pids, pid_t **pp_pid_list);
47 :
48 9900 : static bool create_send_ctx(void)
49 : {
50 9900 : if (!send_ctx)
51 27 : send_ctx = talloc_init("print notify queue");
52 :
53 9900 : if (!send_ctx)
54 0 : return False;
55 :
56 9900 : return True;
57 : }
58 :
59 : /****************************************************************************
60 : Turn a queue name into a snum.
61 : ****************************************************************************/
62 :
63 25004 : int print_queue_snum(const char *qname)
64 : {
65 25004 : int snum = lp_servicenumber(qname);
66 25004 : if (snum == -1 || !lp_printable(snum))
67 160 : return -1;
68 24844 : return snum;
69 : }
70 :
71 : /*******************************************************************
72 : Used to decide if we need a short select timeout.
73 : *******************************************************************/
74 :
75 718 : static bool print_notify_messages_pending(void)
76 : {
77 718 : return (notify_queue_head != NULL);
78 : }
79 :
80 : /*******************************************************************
81 : Flatten data into a message.
82 : *******************************************************************/
83 :
84 5850 : static bool flatten_message(struct notify_queue *q)
85 : {
86 5850 : struct spoolss_notify_msg *msg = q->msg;
87 5850 : uint8_t *buf = NULL;
88 5850 : size_t buflen = 0, len;
89 :
90 11700 : again:
91 11700 : len = 0;
92 :
93 : /* Pack header */
94 :
95 11700 : len += tdb_pack(buf ? buf + len : NULL,
96 11700 : buf ? buflen - len : 0, "f", msg->printer);
97 :
98 11700 : len += tdb_pack(buf ? buf + len : NULL,
99 5850 : buf ? buflen - len : 0, "ddddddd",
100 11700 : (uint32_t)q->tv.tv_sec, (uint32_t)q->tv.tv_usec,
101 : msg->type, msg->field, msg->id, msg->len, msg->flags);
102 :
103 : /* Pack data */
104 :
105 11700 : if (msg->len == 0)
106 10941 : len += tdb_pack(buf ? buf + len : NULL,
107 3647 : buf ? buflen - len : 0, "dd",
108 : msg->notify.value[0], msg->notify.value[1]);
109 : else
110 6609 : len += tdb_pack(buf ? buf + len : NULL,
111 2203 : buf ? buflen - len : 0, "B",
112 : msg->len, msg->notify.data);
113 :
114 11700 : if (buflen != len) {
115 5850 : buf = (uint8_t *)TALLOC_REALLOC(send_ctx, buf, len);
116 5850 : if (!buf)
117 0 : return False;
118 5850 : buflen = len;
119 5850 : goto again;
120 : }
121 :
122 5850 : q->buf = buf;
123 5850 : q->buflen = buflen;
124 :
125 5850 : return True;
126 : }
127 :
128 : /*******************************************************************
129 : Send the batched messages - on a per-printer basis.
130 : *******************************************************************/
131 :
132 242 : static void print_notify_send_messages_to_printer(struct messaging_context *msg_ctx,
133 : const char *printer,
134 : unsigned int timeout)
135 : {
136 0 : char *buf;
137 0 : struct notify_queue *pq, *pq_next;
138 242 : size_t msg_count = 0, offset = 0;
139 242 : size_t num_pids = 0;
140 0 : size_t i;
141 242 : pid_t *pid_list = NULL;
142 242 : struct timeval end_time = timeval_zero();
143 :
144 : /* Count the space needed to send the messages. */
145 6132 : for (pq = notify_queue_head; pq; pq = pq->next) {
146 5890 : if (strequal(printer, pq->msg->printer)) {
147 5850 : if (!flatten_message(pq)) {
148 0 : DEBUG(0,("print_notify_send_messages: Out of memory\n"));
149 0 : talloc_free_children(send_ctx);
150 0 : num_messages = 0;
151 0 : return;
152 : }
153 5850 : offset += (pq->buflen + 4);
154 5850 : msg_count++;
155 : }
156 : }
157 242 : offset += 4; /* For count. */
158 :
159 242 : buf = (char *)TALLOC(send_ctx, offset);
160 242 : if (!buf) {
161 0 : DEBUG(0,("print_notify_send_messages: Out of memory\n"));
162 0 : talloc_free_children(send_ctx);
163 0 : num_messages = 0;
164 0 : return;
165 : }
166 :
167 242 : offset = 0;
168 242 : SIVAL(buf,offset,msg_count);
169 242 : offset += 4;
170 6132 : for (pq = notify_queue_head; pq; pq = pq_next) {
171 5890 : pq_next = pq->next;
172 :
173 5890 : if (strequal(printer, pq->msg->printer)) {
174 5850 : SIVAL(buf,offset,pq->buflen);
175 5850 : offset += 4;
176 5850 : memcpy(buf + offset, pq->buf, pq->buflen);
177 5850 : offset += pq->buflen;
178 :
179 : /* Remove from list. */
180 5850 : DLIST_REMOVE(notify_queue_head, pq);
181 : }
182 : }
183 :
184 242 : DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n",
185 : (unsigned long)msg_count, msg_count != 1 ? "s" : "", printer));
186 :
187 : /*
188 : * Get the list of PID's to send to.
189 : */
190 :
191 242 : if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list))
192 0 : return;
193 :
194 242 : if (timeout != 0) {
195 0 : end_time = timeval_current_ofs(timeout, 0);
196 : }
197 :
198 242 : for (i = 0; i < num_pids; i++) {
199 0 : messaging_send_buf(msg_ctx,
200 0 : pid_to_procid(pid_list[i]),
201 : MSG_PRINTER_NOTIFY2 | MSG_FLAG_LOWPRIORITY,
202 : (uint8_t *)buf, offset);
203 :
204 0 : if ((timeout != 0) && timeval_expired(&end_time)) {
205 0 : break;
206 : }
207 : }
208 : }
209 :
210 : /*******************************************************************
211 : Actually send the batched messages.
212 : *******************************************************************/
213 :
214 238 : void print_notify_send_messages(struct messaging_context *msg_ctx,
215 : unsigned int timeout)
216 : {
217 238 : if (!print_notify_messages_pending())
218 0 : return;
219 :
220 238 : if (!create_send_ctx())
221 0 : return;
222 :
223 480 : while (print_notify_messages_pending())
224 242 : print_notify_send_messages_to_printer(
225 242 : msg_ctx, notify_queue_head->msg->printer, timeout);
226 :
227 238 : talloc_free_children(send_ctx);
228 238 : num_messages = 0;
229 : }
230 :
231 : /*******************************************************************
232 : Event handler to send the messages.
233 : *******************************************************************/
234 :
235 238 : static void print_notify_event_send_messages(struct tevent_context *event_ctx,
236 : struct tevent_timer *te,
237 : struct timeval now,
238 : void *private_data)
239 : {
240 238 : struct messaging_context *msg_ctx = talloc_get_type_abort(
241 : private_data, struct messaging_context);
242 : /* Remove this timed event handler. */
243 238 : TALLOC_FREE(notify_event);
244 :
245 238 : change_to_root_user();
246 238 : print_notify_send_messages(msg_ctx, 0);
247 238 : }
248 :
249 : /**********************************************************************
250 : deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX
251 : *********************************************************************/
252 :
253 5850 : static bool copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from )
254 : {
255 :
256 5850 : if ( !to || !from )
257 0 : return False;
258 :
259 5850 : memcpy( to, from, sizeof(SPOOLSS_NOTIFY_MSG) );
260 :
261 5850 : if ( from->len ) {
262 2203 : to->notify.data = (char *)talloc_memdup(send_ctx, from->notify.data, from->len );
263 2203 : if ( !to->notify.data ) {
264 0 : DEBUG(0,("copy_notify2_msg: talloc_memdup() of size [%d] failed!\n", from->len ));
265 0 : return False;
266 : }
267 : }
268 :
269 :
270 5850 : return True;
271 : }
272 :
273 : /*******************************************************************
274 : Batch up print notify messages.
275 : *******************************************************************/
276 :
277 9662 : static void send_spoolss_notify2_msg(struct tevent_context *ev,
278 : struct messaging_context *msg_ctx,
279 : SPOOLSS_NOTIFY_MSG *msg)
280 : {
281 0 : struct notify_queue *pnqueue, *tmp_ptr;
282 :
283 : /*
284 : * Ensure we only have one job total_bytes and job total_pages for
285 : * each job. There is no point in sending multiple messages that match
286 : * as they will just cause flickering updates in the client.
287 : */
288 :
289 9662 : if ((num_messages < 100) && (msg->type == JOB_NOTIFY_TYPE)
290 9436 : && (msg->field == JOB_NOTIFY_FIELD_TOTAL_BYTES
291 6815 : || msg->field == JOB_NOTIFY_FIELD_TOTAL_PAGES ))
292 : {
293 :
294 137019 : for (tmp_ptr = notify_queue_head; tmp_ptr; tmp_ptr = tmp_ptr->next)
295 : {
296 135611 : if (tmp_ptr->msg->type == msg->type &&
297 131902 : tmp_ptr->msg->field == msg->field &&
298 18646 : tmp_ptr->msg->id == msg->id &&
299 7636 : tmp_ptr->msg->flags == msg->flags &&
300 3818 : strequal(tmp_ptr->msg->printer, msg->printer)) {
301 :
302 3812 : DEBUG(5,("send_spoolss_notify2_msg: replacing message 0x%02x/0x%02x for "
303 : "printer %s in notify_queue\n", msg->type, msg->field, msg->printer));
304 :
305 3812 : tmp_ptr->msg = msg;
306 3812 : return;
307 : }
308 : }
309 : }
310 :
311 : /* Store the message on the pending queue. */
312 :
313 5850 : pnqueue = talloc(send_ctx, struct notify_queue);
314 5850 : if (!pnqueue) {
315 0 : DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n"));
316 0 : return;
317 : }
318 :
319 : /* allocate a new msg structure and copy the fields */
320 :
321 5850 : if ( !(pnqueue->msg = talloc(send_ctx, SPOOLSS_NOTIFY_MSG)) ) {
322 0 : DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%lu] failed!\n",
323 : (unsigned long)sizeof(SPOOLSS_NOTIFY_MSG)));
324 0 : return;
325 : }
326 5850 : copy_notify2_msg(pnqueue->msg, msg);
327 5850 : GetTimeOfDay(&pnqueue->tv);
328 5850 : pnqueue->buf = NULL;
329 5850 : pnqueue->buflen = 0;
330 :
331 5850 : DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \
332 : to notify_queue_head\n", msg->type, msg->field, msg->printer));
333 :
334 : /*
335 : * Note we add to the end of the list to ensure
336 : * the messages are sent in the order they were received. JRA.
337 : */
338 :
339 5850 : DLIST_ADD_END(notify_queue_head, pnqueue);
340 5850 : num_messages++;
341 :
342 5850 : if ((notify_event == NULL) && (ev != NULL)) {
343 : /* Add an event for 1 second's time to send this queue. */
344 238 : notify_event = tevent_add_timer(
345 : ev, NULL, timeval_current_ofs(1,0),
346 : print_notify_event_send_messages, msg_ctx);
347 : }
348 :
349 : }
350 :
351 7459 : static void send_notify_field_values(struct tevent_context *ev,
352 : struct messaging_context *msg_ctx,
353 : const char *sharename, uint32_t type,
354 : uint32_t field, uint32_t id, uint32_t value1,
355 : uint32_t value2, uint32_t flags)
356 : {
357 0 : struct spoolss_notify_msg *msg;
358 :
359 7459 : if (lp_disable_spoolss())
360 0 : return;
361 :
362 7459 : if (!create_send_ctx())
363 0 : return;
364 :
365 7459 : msg = talloc_zero(send_ctx, struct spoolss_notify_msg);
366 7459 : if (!msg)
367 0 : return;
368 :
369 7459 : fstrcpy(msg->printer, sharename);
370 7459 : msg->type = type;
371 7459 : msg->field = field;
372 7459 : msg->id = id;
373 7459 : msg->notify.value[0] = value1;
374 7459 : msg->notify.value[1] = value2;
375 7459 : msg->flags = flags;
376 :
377 7459 : send_spoolss_notify2_msg(ev, msg_ctx, msg);
378 : }
379 :
380 2203 : static void send_notify_field_buffer(struct tevent_context *ev,
381 : struct messaging_context *msg_ctx,
382 : const char *sharename, uint32_t type,
383 : uint32_t field, uint32_t id, uint32_t len,
384 : const char *buffer)
385 : {
386 0 : struct spoolss_notify_msg *msg;
387 :
388 2203 : if (lp_disable_spoolss())
389 0 : return;
390 :
391 2203 : if (!create_send_ctx())
392 0 : return;
393 :
394 2203 : msg = talloc_zero(send_ctx, struct spoolss_notify_msg);
395 2203 : if (!msg)
396 0 : return;
397 :
398 2203 : fstrcpy(msg->printer, sharename);
399 2203 : msg->type = type;
400 2203 : msg->field = field;
401 2203 : msg->id = id;
402 2203 : msg->len = len;
403 2203 : msg->notify.data = discard_const_p(char, buffer);
404 :
405 2203 : send_spoolss_notify2_msg(ev, msg_ctx, msg);
406 : }
407 :
408 : /* Send a message that the printer status has changed */
409 :
410 92 : void notify_printer_status_byname(struct tevent_context *ev,
411 : struct messaging_context *msg_ctx,
412 : const char *sharename, uint32_t status)
413 : {
414 : /* Printer status stored in value1 */
415 :
416 92 : int snum = print_queue_snum(sharename);
417 :
418 92 : send_notify_field_values(ev, msg_ctx, sharename, PRINTER_NOTIFY_TYPE,
419 : PRINTER_NOTIFY_FIELD_STATUS, snum,
420 : status, 0, 0);
421 92 : }
422 :
423 92 : void notify_printer_status(struct tevent_context *ev,
424 : struct messaging_context *msg_ctx,
425 : int snum, uint32_t status)
426 : {
427 0 : const struct loadparm_substitution *lp_sub =
428 92 : loadparm_s3_global_substitution();
429 92 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
430 :
431 92 : if (sharename)
432 92 : notify_printer_status_byname(ev, msg_ctx, sharename, status);
433 92 : }
434 :
435 2147 : void notify_job_status_byname(struct tevent_context *ev,
436 : struct messaging_context *msg_ctx,
437 : const char *sharename, uint32_t jobid,
438 : uint32_t status,
439 : uint32_t flags)
440 : {
441 : /* Job id stored in id field, status in value1 */
442 :
443 2147 : send_notify_field_values(ev, msg_ctx,
444 : sharename, JOB_NOTIFY_TYPE,
445 : JOB_NOTIFY_FIELD_STATUS, jobid,
446 : status, 0, flags);
447 2147 : }
448 :
449 2147 : void notify_job_status(struct tevent_context *ev,
450 : struct messaging_context *msg_ctx,
451 : const char *sharename, uint32_t jobid, uint32_t status)
452 : {
453 2147 : notify_job_status_byname(ev, msg_ctx, sharename, jobid, status, 0);
454 2147 : }
455 :
456 2621 : void notify_job_total_bytes(struct tevent_context *ev,
457 : struct messaging_context *msg_ctx,
458 : const char *sharename, uint32_t jobid,
459 : uint32_t size)
460 : {
461 : /* Job id stored in id field, status in value1 */
462 :
463 2621 : send_notify_field_values(ev, msg_ctx,
464 : sharename, JOB_NOTIFY_TYPE,
465 : JOB_NOTIFY_FIELD_TOTAL_BYTES, jobid,
466 : size, 0, 0);
467 2621 : }
468 :
469 2599 : void notify_job_total_pages(struct tevent_context *ev,
470 : struct messaging_context *msg_ctx,
471 : const char *sharename, uint32_t jobid,
472 : uint32_t pages)
473 : {
474 : /* Job id stored in id field, status in value1 */
475 :
476 2599 : send_notify_field_values(ev, msg_ctx,
477 : sharename, JOB_NOTIFY_TYPE,
478 : JOB_NOTIFY_FIELD_TOTAL_PAGES, jobid,
479 : pages, 0, 0);
480 2599 : }
481 :
482 679 : void notify_job_username(struct tevent_context *ev,
483 : struct messaging_context *msg_ctx,
484 : const char *sharename, uint32_t jobid, char *name)
485 : {
486 679 : send_notify_field_buffer(
487 : ev, msg_ctx,
488 : sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME,
489 679 : jobid, strlen(name) + 1, name);
490 679 : }
491 :
492 711 : void notify_job_name(struct tevent_context *ev,
493 : struct messaging_context *msg_ctx,
494 : const char *sharename, uint32_t jobid, char *name)
495 : {
496 711 : send_notify_field_buffer(
497 : ev, msg_ctx,
498 : sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT,
499 711 : jobid, strlen(name) + 1, name);
500 711 : }
501 :
502 679 : void notify_job_submitted(struct tevent_context *ev,
503 : struct messaging_context *msg_ctx,
504 : const char *sharename, uint32_t jobid,
505 : time_t submitted)
506 : {
507 679 : send_notify_field_buffer(
508 : ev, msg_ctx,
509 : sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED,
510 : jobid, sizeof(submitted), (char *)&submitted);
511 679 : }
512 :
513 8 : void notify_printer_driver(struct tevent_context *ev,
514 : struct messaging_context *msg_ctx,
515 : int snum, const char *driver_name)
516 : {
517 0 : const struct loadparm_substitution *lp_sub =
518 8 : loadparm_s3_global_substitution();
519 8 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
520 :
521 8 : send_notify_field_buffer(
522 : ev, msg_ctx,
523 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,
524 8 : snum, strlen(driver_name) + 1, driver_name);
525 8 : }
526 :
527 34 : void notify_printer_comment(struct tevent_context *ev,
528 : struct messaging_context *msg_ctx,
529 : int snum, const char *comment)
530 : {
531 0 : const struct loadparm_substitution *lp_sub =
532 34 : loadparm_s3_global_substitution();
533 34 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
534 :
535 34 : send_notify_field_buffer(
536 : ev, msg_ctx,
537 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,
538 34 : snum, strlen(comment) + 1, comment);
539 34 : }
540 :
541 0 : void notify_printer_sharename(struct tevent_context *ev,
542 : struct messaging_context *msg_ctx,
543 : int snum, const char *share_name)
544 : {
545 0 : const struct loadparm_substitution *lp_sub =
546 0 : loadparm_s3_global_substitution();
547 0 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
548 :
549 0 : send_notify_field_buffer(
550 : ev, msg_ctx,
551 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,
552 0 : snum, strlen(share_name) + 1, share_name);
553 0 : }
554 :
555 84 : void notify_printer_printername(struct tevent_context *ev,
556 : struct messaging_context *msg_ctx,
557 : int snum, const char *printername)
558 : {
559 0 : const struct loadparm_substitution *lp_sub =
560 84 : loadparm_s3_global_substitution();
561 84 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
562 :
563 84 : send_notify_field_buffer(
564 : ev, msg_ctx,
565 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,
566 84 : snum, strlen(printername) + 1, printername);
567 84 : }
568 :
569 0 : void notify_printer_port(struct tevent_context *ev,
570 : struct messaging_context *msg_ctx,
571 : int snum, const char *port_name)
572 : {
573 0 : const struct loadparm_substitution *lp_sub =
574 0 : loadparm_s3_global_substitution();
575 0 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
576 :
577 0 : send_notify_field_buffer(
578 : ev, msg_ctx,
579 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,
580 0 : snum, strlen(port_name) + 1, port_name);
581 0 : }
582 :
583 8 : void notify_printer_location(struct tevent_context *ev,
584 : struct messaging_context *msg_ctx,
585 : int snum, const char *location)
586 : {
587 0 : const struct loadparm_substitution *lp_sub =
588 8 : loadparm_s3_global_substitution();
589 8 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
590 :
591 8 : send_notify_field_buffer(
592 : ev, msg_ctx,
593 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,
594 8 : snum, strlen(location) + 1, location);
595 8 : }
596 :
597 0 : void notify_printer_sepfile(struct tevent_context *ev,
598 : struct messaging_context *msg_ctx,
599 : int snum, const char *sepfile)
600 : {
601 0 : const struct loadparm_substitution *lp_sub =
602 0 : loadparm_s3_global_substitution();
603 0 : const char *sharename = lp_servicename(talloc_tos(), lp_sub, snum);
604 :
605 0 : send_notify_field_buffer(
606 : ev, msg_ctx,
607 : sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,
608 0 : snum, strlen(sepfile) + 1, sepfile);
609 0 : }
610 :
611 :
612 0 : void notify_printer_byname(struct tevent_context *ev,
613 : struct messaging_context *msg_ctx,
614 : const char *printername, uint32_t change,
615 : const char *value)
616 : {
617 0 : int snum = print_queue_snum(printername);
618 0 : int type = PRINTER_NOTIFY_TYPE;
619 :
620 0 : if ( snum == -1 )
621 0 : return;
622 :
623 0 : send_notify_field_buffer(
624 : ev, msg_ctx,
625 0 : printername, type, change, snum, strlen(value)+1, value );
626 : }
627 :
628 :
629 : /****************************************************************************
630 : Return a malloced list of pid_t's that are interested in getting update
631 : messages on this print queue. Used in printing/notify to send the messages.
632 : ****************************************************************************/
633 :
634 242 : static bool print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx,
635 : size_t *p_num_pids, pid_t **pp_pid_list)
636 : {
637 242 : struct tdb_print_db *pdb = NULL;
638 242 : TDB_CONTEXT *tdb = NULL;
639 0 : TDB_DATA data;
640 242 : bool ret = True;
641 0 : size_t i, num_pids, offset;
642 0 : pid_t *pid_list;
643 :
644 242 : *p_num_pids = 0;
645 242 : *pp_pid_list = NULL;
646 :
647 242 : pdb = get_print_db_byname(printername);
648 242 : if (!pdb)
649 0 : return False;
650 242 : tdb = pdb->tdb;
651 :
652 242 : if (tdb_read_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
653 0 : DEBUG(0,("print_notify_pid_list: Failed to lock printer %s database\n",
654 : printername));
655 0 : if (pdb)
656 0 : release_print_db(pdb);
657 0 : return False;
658 : }
659 :
660 242 : data = get_printer_notify_pid_list( tdb, printername, True );
661 :
662 242 : if (!data.dptr) {
663 242 : ret = True;
664 242 : goto done;
665 : }
666 :
667 0 : num_pids = data.dsize / 8;
668 :
669 0 : if (num_pids) {
670 0 : if ((pid_list = talloc_array(mem_ctx, pid_t, num_pids)) == NULL) {
671 0 : ret = False;
672 0 : goto done;
673 : }
674 : } else {
675 0 : pid_list = NULL;
676 : }
677 :
678 0 : for( i = 0, offset = 0; i < num_pids; offset += 8, i++)
679 0 : pid_list[i] = (pid_t)IVAL(data.dptr, offset);
680 :
681 0 : *pp_pid_list = pid_list;
682 0 : *p_num_pids = num_pids;
683 :
684 0 : ret = True;
685 :
686 242 : done:
687 :
688 242 : tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
689 242 : if (pdb)
690 242 : release_print_db(pdb);
691 242 : SAFE_FREE(data.dptr);
692 242 : return ret;
693 : }
|