2002-06-28 04:17:15 +04:00
/*
Unix SMB / Netbios implementation .
Version 2.2
printing backend routines
Copyright ( C ) Tim Potter , 2002
2002-08-09 00:54:37 +04:00
Copyright ( C ) Gerald Carter , 2002
2002-06-28 04:17:15 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "printing.h"
2002-09-05 01:59:38 +04:00
static TALLOC_CTX * send_ctx ;
static struct notify_queue {
struct notify_queue * next , * prev ;
2002-11-07 05:38:42 +03:00
char * printername ;
2002-09-05 01:59:38 +04:00
void * buf ;
size_t buflen ;
} * notify_queue_head = NULL ;
/*******************************************************************
Used to decide if we need a short select timeout .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL print_notify_messages_pending ( void )
{
return ( notify_queue_head ! = NULL ) ;
}
/*******************************************************************
2002-11-07 05:38:42 +03:00
Send the batched messages - on a per - printer basis .
2002-09-05 01:59:38 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-07 05:38:42 +03:00
static void print_notify_send_messages_to_printer ( const char * printer )
2002-09-05 01:59:38 +04:00
{
char * buf ;
2002-11-07 05:38:42 +03:00
struct notify_queue * pq , * pq_next ;
2002-09-05 01:59:38 +04:00
size_t msg_count = 0 , offset = 0 ;
2002-11-07 05:38:42 +03:00
size_t num_pids = 0 ;
size_t i ;
pid_t * pid_list = NULL ;
2002-09-05 01:59:38 +04:00
/* Count the space needed to send the messages. */
2002-11-07 05:38:42 +03:00
for ( pq = notify_queue_head ; pq ; pq = pq - > next ) {
if ( strequal ( printer , pq - > printername ) ) {
offset + = ( pq - > buflen + 4 ) ;
msg_count + + ;
}
}
2002-09-05 01:59:38 +04:00
offset + = 4 ; /* For count. */
buf = talloc ( send_ctx , offset ) ;
if ( ! buf ) {
DEBUG ( 0 , ( " print_notify_send_messages: Out of memory \n " ) ) ;
talloc_destroy_pool ( send_ctx ) ;
return ;
}
offset = 0 ;
SIVAL ( buf , offset , msg_count ) ;
offset + = 4 ;
2002-11-07 05:38:42 +03:00
for ( pq = notify_queue_head ; pq ; pq = pq_next ) {
pq_next = pq - > next ;
if ( strequal ( printer , pq - > printername ) ) {
SIVAL ( buf , offset , pq - > buflen ) ;
offset + = 4 ;
memcpy ( buf + offset , pq - > buf , pq - > buflen ) ;
offset + = pq - > buflen ;
/* Remove from list. */
DLIST_REMOVE ( notify_queue_head , pq ) ;
}
2002-09-05 01:59:38 +04:00
}
2002-11-07 05:38:42 +03:00
DEBUG ( 5 , ( " print_notify_send_messages_to_printer: sending %d print notify message%s to printer %s \n " ,
msg_count , msg_count ! = 1 ? " s " : " " , printer ) ) ;
/*
* Get the list of PID ' s to send to .
*/
if ( ! print_notify_pid_list ( printer , send_ctx , & num_pids , & pid_list ) )
return ;
for ( i = 0 ; i < num_pids ; i + + )
message_send_pid ( pid_list [ i ] , MSG_PRINTER_NOTIFY2 , buf , offset , True ) ;
}
/*******************************************************************
Actually send the batched messages .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void print_notify_send_messages ( void )
{
if ( ! print_notify_messages_pending ( ) )
return ;
if ( ! send_ctx )
return ;
while ( print_notify_messages_pending ( ) )
print_notify_send_messages_to_printer ( notify_queue_head - > printername ) ;
2002-09-05 08:22:16 +04:00
2002-09-05 01:59:38 +04:00
talloc_destroy_pool ( send_ctx ) ;
}
/*******************************************************************
Batch up print notify messages .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-06-28 04:17:15 +04:00
static void send_spoolss_notify2_msg ( struct spoolss_notify_msg * msg )
{
char * buf = NULL ;
2002-09-05 01:59:38 +04:00
size_t buflen = 0 , len ;
2002-09-05 16:55:56 +04:00
struct notify_queue * pnqueue , * tmp_ptr ;
2002-06-28 04:17:15 +04:00
/* Let's not waste any time with this */
if ( lp_disable_spoolss ( ) )
return ;
2002-09-05 01:59:38 +04:00
if ( ! send_ctx )
send_ctx = talloc_init_named ( " print notify queue " ) ;
if ( ! send_ctx )
goto fail ;
2002-06-28 04:17:15 +04:00
/* Flatten data into a message */
again :
len = 0 ;
/* Pack header */
len + = tdb_pack ( buf + len , buflen - len , " f " , msg - > printer ) ;
len + = tdb_pack ( buf + len , buflen - len , " ddddd " ,
msg - > type , msg - > field , msg - > id , msg - > len , msg - > flags ) ;
/* Pack data */
if ( msg - > len = = 0 )
len + = tdb_pack ( buf + len , buflen - len , " dd " ,
msg - > notify . value [ 0 ] , msg - > notify . value [ 1 ] ) ;
else
len + = tdb_pack ( buf + len , buflen - len , " B " ,
msg - > len , msg - > notify . data ) ;
if ( buflen ! = len ) {
2002-09-05 01:59:38 +04:00
buf = talloc_realloc ( send_ctx , buf , len ) ;
if ( ! buf )
goto fail ;
2002-06-28 04:17:15 +04:00
buflen = len ;
goto again ;
}
2002-09-05 01:59:38 +04:00
/* Store the message on the pending queue. */
2002-06-28 04:17:15 +04:00
2002-09-05 01:59:38 +04:00
pnqueue = talloc ( send_ctx , sizeof ( * pnqueue ) ) ;
if ( ! pnqueue )
goto fail ;
2002-06-28 04:17:15 +04:00
2002-11-07 05:38:42 +03:00
pnqueue - > printername = talloc_strdup ( send_ctx , msg - > printer ) ;
if ( ! pnqueue - > printername )
goto fail ;
2002-09-05 01:59:38 +04:00
pnqueue - > buf = buf ;
pnqueue - > buflen = buflen ;
2002-09-05 08:22:16 +04:00
2002-11-07 05:38:42 +03:00
DEBUG ( 5 , ( " send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \
to notify_queue_head \ n " , msg->type, msg->field, msg->printer));
2002-09-05 08:22:16 +04:00
2002-09-05 16:55:56 +04:00
/* Note we add to the end of the list to ensure
* the messages are sent in the order they were received . JRA .
*/
DLIST_ADD_END ( notify_queue_head , pnqueue , tmp_ptr ) ;
2002-09-05 01:59:38 +04:00
return ;
fail :
2002-06-28 04:17:15 +04:00
2002-09-05 01:59:38 +04:00
DEBUG ( 0 , ( " send_spoolss_notify2_msg: Out of memory. \n " ) ) ;
2002-06-28 04:17:15 +04:00
}
static void send_notify_field_values ( const char * printer_name , uint32 type ,
uint32 field , uint32 id , uint32 value1 ,
uint32 value2 , uint32 flags )
{
struct spoolss_notify_msg msg ;
ZERO_STRUCT ( msg ) ;
fstrcpy ( msg . printer , printer_name ) ;
msg . type = type ;
msg . field = field ;
msg . id = id ;
msg . notify . value [ 0 ] = value1 ;
msg . notify . value [ 1 ] = value2 ;
msg . flags = flags ;
send_spoolss_notify2_msg ( & msg ) ;
}
static void send_notify_field_buffer ( const char * printer_name , uint32 type ,
uint32 field , uint32 id , uint32 len ,
char * buffer )
{
struct spoolss_notify_msg msg ;
ZERO_STRUCT ( msg ) ;
fstrcpy ( msg . printer , printer_name ) ;
msg . type = type ;
msg . field = field ;
msg . id = id ;
msg . len = len ;
msg . notify . data = buffer ;
send_spoolss_notify2_msg ( & msg ) ;
}
/* Send a message that the printer status has changed */
2002-07-11 04:06:29 +04:00
void notify_printer_status_byname ( const char * printer_name , uint32 status )
2002-06-28 04:17:15 +04:00
{
/* Printer status stored in value1 */
send_notify_field_values ( printer_name , PRINTER_NOTIFY_TYPE ,
PRINTER_NOTIFY_STATUS , 0 ,
status , 0 , 0 ) ;
}
void notify_printer_status ( int snum , uint32 status )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
if ( printer_name )
notify_printer_status_byname ( printer_name , status ) ;
}
2002-07-11 04:06:29 +04:00
void notify_job_status_byname ( const char * printer_name , uint32 jobid , uint32 status ,
2002-06-28 04:17:15 +04:00
uint32 flags )
{
/* Job id stored in id field, status in value1 */
send_notify_field_values ( printer_name , JOB_NOTIFY_TYPE ,
JOB_NOTIFY_STATUS , jobid ,
status , 0 , flags ) ;
}
void notify_job_status ( int snum , uint32 jobid , uint32 status )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
notify_job_status_byname ( printer_name , jobid , status , 0 ) ;
}
void notify_job_total_bytes ( int snum , uint32 jobid , uint32 size )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
/* Job id stored in id field, status in value1 */
send_notify_field_values ( printer_name , JOB_NOTIFY_TYPE ,
JOB_NOTIFY_TOTAL_BYTES , jobid ,
size , 0 , 0 ) ;
}
void notify_job_total_pages ( int snum , uint32 jobid , uint32 pages )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
/* Job id stored in id field, status in value1 */
send_notify_field_values ( printer_name , JOB_NOTIFY_TYPE ,
JOB_NOTIFY_TOTAL_PAGES , jobid ,
pages , 0 , 0 ) ;
}
void notify_job_username ( int snum , uint32 jobid , char * name )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
send_notify_field_buffer (
printer_name , JOB_NOTIFY_TYPE , JOB_NOTIFY_USER_NAME ,
jobid , strlen ( name ) + 1 , name ) ;
}
void notify_job_name ( int snum , uint32 jobid , char * name )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
send_notify_field_buffer (
printer_name , JOB_NOTIFY_TYPE , JOB_NOTIFY_DOCUMENT ,
jobid , strlen ( name ) + 1 , name ) ;
}
void notify_job_submitted ( int snum , uint32 jobid , time_t submitted )
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
send_notify_field_buffer (
printer_name , JOB_NOTIFY_TYPE , JOB_NOTIFY_SUBMITTED ,
jobid , sizeof ( submitted ) , ( char * ) & submitted ) ;
}
2002-08-09 00:54:37 +04:00
void notify_printer_driver ( int snum , char * driver_name )
2002-06-28 04:17:15 +04:00
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
2002-08-09 00:54:37 +04:00
send_notify_field_buffer (
printer_name , PRINTER_NOTIFY_TYPE , PRINTER_NOTIFY_DRIVER_NAME ,
snum , strlen ( driver_name ) + 1 , driver_name ) ;
2002-06-28 04:17:15 +04:00
}
2002-08-09 00:54:37 +04:00
void notify_printer_comment ( int snum , char * comment )
2002-06-28 04:17:15 +04:00
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
2002-06-28 04:17:15 +04:00
2002-08-09 00:54:37 +04:00
send_notify_field_buffer (
printer_name , PRINTER_NOTIFY_TYPE , PRINTER_NOTIFY_COMMENT ,
snum , strlen ( comment ) + 1 , comment ) ;
2002-06-28 04:17:15 +04:00
}
2002-08-09 00:54:37 +04:00
void notify_printer_sharename ( int snum , char * share_name )
2002-06-28 04:17:15 +04:00
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
send_notify_field_buffer (
printer_name , PRINTER_NOTIFY_TYPE , PRINTER_NOTIFY_SHARE_NAME ,
snum , strlen ( share_name ) + 1 , share_name ) ;
2002-06-28 04:17:15 +04:00
}
2002-08-09 00:54:37 +04:00
void notify_printer_port ( int snum , char * port_name )
2002-06-28 04:17:15 +04:00
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
send_notify_field_buffer (
printer_name , PRINTER_NOTIFY_TYPE , PRINTER_NOTIFY_PORT_NAME ,
snum , strlen ( port_name ) + 1 , port_name ) ;
2002-06-28 04:17:15 +04:00
}
2002-08-09 00:54:37 +04:00
void notify_printer_location ( int snum , char * location )
2002-06-28 04:17:15 +04:00
{
2002-08-09 00:54:37 +04:00
const char * printer_name = SERVICE ( snum ) ;
send_notify_field_buffer (
printer_name , PRINTER_NOTIFY_TYPE , PRINTER_NOTIFY_LOCATION ,
snum , strlen ( location ) + 1 , location ) ;
2002-06-28 04:17:15 +04:00
}