2
Unix SMB/Netbios implementation.
4
printing backend routines
5
Copyright (C) Tim Potter, 2002
6
Copyright (C) Gerald Carter, 2002
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
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.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
static TALLOC_CTX *send_ctx;
28
static unsigned int num_messages;
30
static struct notify_queue {
31
struct notify_queue *next, *prev;
32
struct spoolss_notify_msg *msg;
36
} *notify_queue_head = NULL;
39
static BOOL create_send_ctx(void)
42
send_ctx = talloc_init("print notify queue");
50
/****************************************************************************
51
Turn a queue name into a snum.
52
****************************************************************************/
54
int print_queue_snum(const char *qname)
56
int snum = lp_servicenumber(qname);
57
if (snum == -1 || !lp_print_ok(snum))
62
/*******************************************************************
63
Used to decide if we need a short select timeout.
64
*******************************************************************/
66
BOOL print_notify_messages_pending(void)
68
return (notify_queue_head != NULL);
71
/*******************************************************************
72
Flatten data into a message.
73
*******************************************************************/
75
static BOOL flatten_message(struct notify_queue *q)
77
struct spoolss_notify_msg *msg = q->msg;
79
size_t buflen = 0, len;
86
len += tdb_pack(buf + len, buflen - len, "f", msg->printer);
88
len += tdb_pack(buf + len, buflen - len, "ddddddd",
89
(uint32)q->tv.tv_sec, (uint32)q->tv.tv_usec,
90
msg->type, msg->field, msg->id, msg->len, msg->flags);
95
len += tdb_pack(buf + len, buflen - len, "dd",
96
msg->notify.value[0], msg->notify.value[1]);
98
len += tdb_pack(buf + len, buflen - len, "B",
99
msg->len, msg->notify.data);
102
buf = TALLOC_REALLOC(send_ctx, buf, len);
115
/*******************************************************************
116
Send the batched messages - on a per-printer basis.
117
*******************************************************************/
119
static void print_notify_send_messages_to_printer(const char *printer, unsigned int timeout)
122
struct notify_queue *pq, *pq_next;
123
size_t msg_count = 0, offset = 0;
126
pid_t *pid_list = NULL;
128
/* Count the space needed to send the messages. */
129
for (pq = notify_queue_head; pq; pq = pq->next) {
130
if (strequal(printer, pq->msg->printer)) {
131
if (!flatten_message(pq)) {
132
DEBUG(0,("print_notify_send_messages: Out of memory\n"));
133
talloc_free_children(send_ctx);
137
offset += (pq->buflen + 4);
141
offset += 4; /* For count. */
143
buf = TALLOC(send_ctx, offset);
145
DEBUG(0,("print_notify_send_messages: Out of memory\n"));
146
talloc_free_children(send_ctx);
152
SIVAL(buf,offset,msg_count);
154
for (pq = notify_queue_head; pq; pq = pq_next) {
157
if (strequal(printer, pq->msg->printer)) {
158
SIVAL(buf,offset,pq->buflen);
160
memcpy(buf + offset, pq->buf, pq->buflen);
161
offset += pq->buflen;
163
/* Remove from list. */
164
DLIST_REMOVE(notify_queue_head, pq);
168
DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n",
169
(unsigned long)msg_count, msg_count != 1 ? "s" : "", printer));
172
* Get the list of PID's to send to.
175
if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list))
178
for (i = 0; i < num_pids; i++) {
179
unsigned int q_len = messages_pending_for_pid(pid_to_procid(pid_list[i]));
181
DEBUG(5, ("print_notify_send_messages_to_printer: discarding notify to printer %s as queue length = %u\n",
185
message_send_pid_with_timeout(pid_to_procid(pid_list[i]),
187
buf, offset, True, timeout);
191
/*******************************************************************
192
Actually send the batched messages.
193
*******************************************************************/
195
void print_notify_send_messages(unsigned int timeout)
197
if (!print_notify_messages_pending())
200
if (!create_send_ctx())
203
while (print_notify_messages_pending())
204
print_notify_send_messages_to_printer(notify_queue_head->msg->printer, timeout);
206
talloc_free_children(send_ctx);
210
/**********************************************************************
211
deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX
212
*********************************************************************/
214
static BOOL copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from )
220
memcpy( to, from, sizeof(SPOOLSS_NOTIFY_MSG) );
223
to->notify.data = TALLOC_MEMDUP(send_ctx, from->notify.data, from->len );
224
if ( !to->notify.data ) {
225
DEBUG(0,("copy_notify2_msg: talloc_memdup() of size [%d] failed!\n", from->len ));
234
/*******************************************************************
235
Batch up print notify messages.
236
*******************************************************************/
238
static void send_spoolss_notify2_msg(SPOOLSS_NOTIFY_MSG *msg)
240
struct notify_queue *pnqueue, *tmp_ptr;
243
* Ensure we only have one job total_bytes and job total_pages for
244
* each job. There is no point in sending multiple messages that match
245
* as they will just cause flickering updates in the client.
248
if ((num_messages < 100) && (msg->type == JOB_NOTIFY_TYPE)
249
&& (msg->field == JOB_NOTIFY_TOTAL_BYTES
250
|| msg->field == JOB_NOTIFY_TOTAL_PAGES ))
253
for (tmp_ptr = notify_queue_head; tmp_ptr; tmp_ptr = tmp_ptr->next)
255
if (tmp_ptr->msg->type == msg->type &&
256
tmp_ptr->msg->field == msg->field &&
257
tmp_ptr->msg->id == msg->id &&
258
tmp_ptr->msg->flags == msg->flags &&
259
strequal(tmp_ptr->msg->printer, msg->printer)) {
261
DEBUG(5,("send_spoolss_notify2_msg: replacing message 0x%02x/0x%02x for "
262
"printer %s in notify_queue\n", msg->type, msg->field, msg->printer));
270
/* Store the message on the pending queue. */
272
pnqueue = TALLOC_P(send_ctx, struct notify_queue);
274
DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n"));
278
/* allocate a new msg structure and copy the fields */
280
if ( !(pnqueue->msg = TALLOC_P(send_ctx, SPOOLSS_NOTIFY_MSG)) ) {
281
DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%lu] failed!\n",
282
(unsigned long)sizeof(SPOOLSS_NOTIFY_MSG)));
285
copy_notify2_msg(pnqueue->msg, msg);
286
GetTimeOfDay(&pnqueue->tv);
290
DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \
291
to notify_queue_head\n", msg->type, msg->field, msg->printer));
294
* Note we add to the end of the list to ensure
295
* the messages are sent in the order they were received. JRA.
298
DLIST_ADD_END(notify_queue_head, pnqueue, tmp_ptr);
302
static void send_notify_field_values(const char *sharename, uint32 type,
303
uint32 field, uint32 id, uint32 value1,
304
uint32 value2, uint32 flags)
306
struct spoolss_notify_msg *msg;
308
if (lp_disable_spoolss())
311
if (!create_send_ctx())
314
msg = TALLOC_P(send_ctx, struct spoolss_notify_msg);
320
fstrcpy(msg->printer, sharename);
324
msg->notify.value[0] = value1;
325
msg->notify.value[1] = value2;
328
send_spoolss_notify2_msg(msg);
331
static void send_notify_field_buffer(const char *sharename, uint32 type,
332
uint32 field, uint32 id, uint32 len,
335
struct spoolss_notify_msg *msg;
337
if (lp_disable_spoolss())
340
if (!create_send_ctx())
343
msg = TALLOC_P(send_ctx, struct spoolss_notify_msg);
349
fstrcpy(msg->printer, sharename);
354
msg->notify.data = CONST_DISCARD(char *,buffer);
356
send_spoolss_notify2_msg(msg);
359
/* Send a message that the printer status has changed */
361
void notify_printer_status_byname(const char *sharename, uint32 status)
363
/* Printer status stored in value1 */
365
send_notify_field_values(sharename, PRINTER_NOTIFY_TYPE,
366
PRINTER_NOTIFY_STATUS, 0,
370
void notify_printer_status(int snum, uint32 status)
372
const char *sharename = SERVICE(snum);
375
notify_printer_status_byname(sharename, status);
378
void notify_job_status_byname(const char *sharename, uint32 jobid, uint32 status,
381
/* Job id stored in id field, status in value1 */
383
send_notify_field_values(sharename, JOB_NOTIFY_TYPE,
384
JOB_NOTIFY_STATUS, jobid,
388
void notify_job_status(const char *sharename, uint32 jobid, uint32 status)
390
notify_job_status_byname(sharename, jobid, status, 0);
393
void notify_job_total_bytes(const char *sharename, uint32 jobid,
396
/* Job id stored in id field, status in value1 */
398
send_notify_field_values(sharename, JOB_NOTIFY_TYPE,
399
JOB_NOTIFY_TOTAL_BYTES, jobid,
403
void notify_job_total_pages(const char *sharename, uint32 jobid,
406
/* Job id stored in id field, status in value1 */
408
send_notify_field_values(sharename, JOB_NOTIFY_TYPE,
409
JOB_NOTIFY_TOTAL_PAGES, jobid,
413
void notify_job_username(const char *sharename, uint32 jobid, char *name)
415
send_notify_field_buffer(
416
sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME,
417
jobid, strlen(name) + 1, name);
420
void notify_job_name(const char *sharename, uint32 jobid, char *name)
422
send_notify_field_buffer(
423
sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT,
424
jobid, strlen(name) + 1, name);
427
void notify_job_submitted(const char *sharename, uint32 jobid,
430
send_notify_field_buffer(
431
sharename, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED,
432
jobid, sizeof(submitted), (char *)&submitted);
435
void notify_printer_driver(int snum, char *driver_name)
437
const char *sharename = SERVICE(snum);
439
send_notify_field_buffer(
440
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,
441
snum, strlen(driver_name) + 1, driver_name);
444
void notify_printer_comment(int snum, char *comment)
446
const char *sharename = SERVICE(snum);
448
send_notify_field_buffer(
449
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,
450
snum, strlen(comment) + 1, comment);
453
void notify_printer_sharename(int snum, char *share_name)
455
const char *sharename = SERVICE(snum);
457
send_notify_field_buffer(
458
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,
459
snum, strlen(share_name) + 1, share_name);
462
void notify_printer_printername(int snum, char *printername)
464
const char *sharename = SERVICE(snum);
466
send_notify_field_buffer(
467
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,
468
snum, strlen(printername) + 1, printername);
471
void notify_printer_port(int snum, char *port_name)
473
const char *sharename = SERVICE(snum);
475
send_notify_field_buffer(
476
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,
477
snum, strlen(port_name) + 1, port_name);
480
void notify_printer_location(int snum, char *location)
482
const char *sharename = SERVICE(snum);
484
send_notify_field_buffer(
485
sharename, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,
486
snum, strlen(location) + 1, location);
489
void notify_printer_byname( const char *printername, uint32 change, const char *value )
491
int snum = print_queue_snum(printername);
492
int type = PRINTER_NOTIFY_TYPE;
497
send_notify_field_buffer( printername, type, change, snum, strlen(value)+1, value );
501
/****************************************************************************
502
Return a malloced list of pid_t's that are interested in getting update
503
messages on this print queue. Used in printing/notify to send the messages.
504
****************************************************************************/
506
BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t *p_num_pids, pid_t **pp_pid_list)
508
struct tdb_print_db *pdb = NULL;
509
TDB_CONTEXT *tdb = NULL;
512
size_t i, num_pids, offset;
518
pdb = get_print_db_byname(printername);
523
if (tdb_read_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
524
DEBUG(0,("print_notify_pid_list: Failed to lock printer %s database\n",
527
release_print_db(pdb);
531
data = get_printer_notify_pid_list( tdb, printername, True );
538
num_pids = data.dsize / 8;
540
if ((pid_list = TALLOC_ARRAY(mem_ctx, pid_t, num_pids)) == NULL) {
545
for( i = 0, offset = 0; offset < data.dsize; offset += 8, i++)
546
pid_list[i] = (pid_t)IVAL(data.dptr, offset);
548
*pp_pid_list = pid_list;
549
*p_num_pids = num_pids;
555
tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
557
release_print_db(pdb);
558
SAFE_FREE(data.dptr);