1996-05-04 11:50:46 +04:00
/*
2002-07-15 14:35:28 +04:00
Unix SMB / Netbios implementation .
Version 3.0
2000-04-16 10:20:02 +04:00
printing backend routines
Copyright ( C ) Andrew Tridgell 1992 - 2000
2002-07-15 14:35:28 +04:00
Copyright ( C ) Jeremy Allison 2002
1996-05-04 11:50:46 +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 .
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2001-03-16 08:55:30 +03:00
# include "printing.h"
2000-11-08 02:05:53 +03:00
2004-05-27 19:38:54 +04:00
extern SIG_ATOMIC_T got_sig_term ;
extern SIG_ATOMIC_T reload_after_sighup ;
2001-03-16 08:55:30 +03:00
/* Current printer interface */
2004-10-19 21:05:01 +04:00
static BOOL remove_from_jobs_changed ( const char * sharename , uint32 jobid ) ;
2001-03-16 08:55:30 +03:00
2000-04-16 10:20:02 +04:00
/*
the printing backend revolves around a tdb database that stores the
SMB view of the print queue
The key for this database is a jobid - a internally generated number that
uniquely identifies a print job
1996-05-04 11:50:46 +04:00
2000-04-16 10:20:02 +04:00
reading the print queue involves two steps :
- possibly running lpq and updating the internal database from that
- reading entries from the database
jobids are assigned when a job starts spooling .
*/
2002-08-17 21:00:51 +04:00
static TDB_CONTEXT * rap_tdb ;
static uint16 next_rap_jobid ;
2004-10-19 21:05:01 +04:00
struct rap_jobid_key {
fstring sharename ;
uint32 jobid ;
} ;
2002-07-15 14:35:28 +04:00
2004-12-01 23:11:31 +03:00
/***************************************************************************
Nightmare . LANMAN jobid ' s are 16 bit numbers . . . . . We must map them to 32
bit RPC jobids . . . . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
uint16 pjobid_to_rap ( const char * sharename , uint32 jobid )
2002-07-15 14:35:28 +04:00
{
2002-08-17 21:00:51 +04:00
uint16 rap_jobid ;
TDB_DATA data , key ;
2004-10-19 21:05:01 +04:00
struct rap_jobid_key jinfo ;
2005-04-26 18:14:16 +04:00
uint8 buf [ 2 ] ;
2002-07-15 14:35:28 +04:00
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " pjobid_to_rap: called. \n " ) ) ;
2002-08-17 21:00:51 +04:00
if ( ! rap_tdb ) {
/* Create the in-memory tdb. */
rap_tdb = tdb_open_log ( NULL , 0 , TDB_INTERNAL , ( O_RDWR | O_CREAT ) , 0644 ) ;
if ( ! rap_tdb )
return 0 ;
2002-07-15 14:35:28 +04:00
}
2004-10-19 21:05:01 +04:00
ZERO_STRUCT ( jinfo ) ;
fstrcpy ( jinfo . sharename , sharename ) ;
jinfo . jobid = jobid ;
key . dptr = ( char * ) & jinfo ;
2002-08-17 21:00:51 +04:00
key . dsize = sizeof ( jinfo ) ;
2004-10-19 21:05:01 +04:00
2002-08-17 21:00:51 +04:00
data = tdb_fetch ( rap_tdb , key ) ;
if ( data . dptr & & data . dsize = = sizeof ( uint16 ) ) {
2004-01-14 22:12:06 +03:00
rap_jobid = SVAL ( data . dptr , 0 ) ;
2002-08-17 21:00:51 +04:00
SAFE_FREE ( data . dptr ) ;
2002-12-06 01:32:15 +03:00
DEBUG ( 10 , ( " pjobid_to_rap: jobid %u maps to RAP jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) jobid , ( unsigned int ) rap_jobid ) ) ;
2002-08-17 21:00:51 +04:00
return rap_jobid ;
2002-07-15 14:35:28 +04:00
}
2002-11-23 05:52:36 +03:00
SAFE_FREE ( data . dptr ) ;
2002-08-17 21:00:51 +04:00
/* Not found - create and store mapping. */
rap_jobid = + + next_rap_jobid ;
if ( rap_jobid = = 0 )
rap_jobid = + + next_rap_jobid ;
2005-04-26 18:14:16 +04:00
SSVAL ( buf , 0 , rap_jobid ) ;
data . dptr = buf ;
2002-08-17 21:00:51 +04:00
data . dsize = sizeof ( rap_jobid ) ;
tdb_store ( rap_tdb , key , data , TDB_REPLACE ) ;
tdb_store ( rap_tdb , data , key , TDB_REPLACE ) ;
2002-12-05 07:00:16 +03:00
2002-12-06 01:32:15 +03:00
DEBUG ( 10 , ( " pjobid_to_rap: created jobid %u maps to RAP jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) jobid , ( unsigned int ) rap_jobid ) ) ;
2002-08-17 21:00:51 +04:00
return rap_jobid ;
2002-07-15 14:35:28 +04:00
}
2004-10-19 21:05:01 +04:00
BOOL rap_to_pjobid ( uint16 rap_jobid , fstring sharename , uint32 * pjobid )
2002-07-15 14:35:28 +04:00
{
2002-08-17 21:00:51 +04:00
TDB_DATA data , key ;
2005-04-26 18:14:16 +04:00
uint8 buf [ 2 ] ;
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_to_pjobid called. \n " ) ) ;
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
if ( ! rap_tdb )
return False ;
2002-07-15 14:35:28 +04:00
2005-04-26 18:14:16 +04:00
SSVAL ( buf , 0 , rap_jobid ) ;
key . dptr = buf ;
2002-08-17 21:00:51 +04:00
key . dsize = sizeof ( rap_jobid ) ;
data = tdb_fetch ( rap_tdb , key ) ;
2004-10-19 21:05:01 +04:00
if ( data . dptr & & data . dsize = = sizeof ( struct rap_jobid_key ) )
{
struct rap_jobid_key * jinfo = ( struct rap_jobid_key * ) data . dptr ;
fstrcpy ( sharename , jinfo - > sharename ) ;
* pjobid = jinfo - > jobid ;
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_to_pjobid: jobid %u maps to RAP jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) * pjobid , ( unsigned int ) rap_jobid ) ) ;
2002-08-17 21:00:51 +04:00
SAFE_FREE ( data . dptr ) ;
return True ;
2002-07-15 14:35:28 +04:00
}
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_to_pjobid: Failed to lookup RAP jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) rap_jobid ) ) ;
2002-11-23 05:52:36 +03:00
SAFE_FREE ( data . dptr ) ;
2002-08-17 21:00:51 +04:00
return False ;
2002-07-15 14:35:28 +04:00
}
2004-10-19 21:05:01 +04:00
static void rap_jobid_delete ( const char * sharename , uint32 jobid )
2002-07-15 14:35:28 +04:00
{
2002-08-17 21:00:51 +04:00
TDB_DATA key , data ;
uint16 rap_jobid ;
2004-10-19 21:05:01 +04:00
struct rap_jobid_key jinfo ;
2005-04-26 18:14:16 +04:00
uint8 buf [ 2 ] ;
2002-07-15 14:35:28 +04:00
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_jobid_delete: called. \n " ) ) ;
2002-08-17 21:00:51 +04:00
if ( ! rap_tdb )
return ;
2004-10-19 21:05:01 +04:00
ZERO_STRUCT ( jinfo ) ;
fstrcpy ( jinfo . sharename , sharename ) ;
jinfo . jobid = jobid ;
key . dptr = ( char * ) & jinfo ;
2002-08-17 21:00:51 +04:00
key . dsize = sizeof ( jinfo ) ;
2004-10-19 21:05:01 +04:00
2002-08-17 21:00:51 +04:00
data = tdb_fetch ( rap_tdb , key ) ;
2002-11-23 05:52:36 +03:00
if ( ! data . dptr | | ( data . dsize ! = sizeof ( uint16 ) ) ) {
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_jobid_delete: cannot find jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) jobid ) ) ;
2002-11-23 05:52:36 +03:00
SAFE_FREE ( data . dptr ) ;
2002-08-17 21:00:51 +04:00
return ;
2002-11-23 05:52:36 +03:00
}
2002-08-17 21:00:51 +04:00
2002-12-05 07:00:16 +03:00
DEBUG ( 10 , ( " rap_jobid_delete: deleting jobid %u \n " ,
2004-10-19 21:05:01 +04:00
( unsigned int ) jobid ) ) ;
2002-12-05 07:00:16 +03:00
2004-01-14 22:12:06 +03:00
rap_jobid = SVAL ( data . dptr , 0 ) ;
2002-08-17 21:00:51 +04:00
SAFE_FREE ( data . dptr ) ;
2005-04-26 18:14:16 +04:00
SSVAL ( buf , 0 , rap_jobid ) ;
data . dptr = buf ;
2002-08-17 21:00:51 +04:00
data . dsize = sizeof ( rap_jobid ) ;
tdb_delete ( rap_tdb , key ) ;
tdb_delete ( rap_tdb , data ) ;
2002-07-15 14:35:28 +04:00
}
2004-10-19 21:05:01 +04:00
static int get_queue_status ( const char * sharename , print_status_struct * ) ;
2000-11-21 03:30:15 +03:00
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-11-01 02:41:00 +03:00
Initialise the printing backend . Called once at startup before the fork ( ) .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-09 07:13:30 +03:00
2000-04-16 10:20:02 +04:00
BOOL print_backend_init ( void )
{
2003-01-03 11:28:12 +03:00
const char * sversion = " INFO/version " ;
2002-08-17 21:00:51 +04:00
pstring printing_path ;
int services = lp_numservices ( ) ;
int snum ;
2000-10-10 10:45:09 +04:00
2002-07-15 14:35:28 +04:00
unlink ( lock_path ( " printing.tdb " ) ) ;
2002-08-17 21:00:51 +04:00
pstrcpy ( printing_path , lock_path ( " printing " ) ) ;
mkdir ( printing_path , 0755 ) ;
2000-04-16 10:20:02 +04:00
/* handle a Samba upgrade */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
for ( snum = 0 ; snum < services ; snum + + ) {
struct tdb_print_db * pdb ;
if ( ! lp_print_ok ( snum ) )
continue ;
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
pdb = get_print_db_byname ( lp_const_servicename ( snum ) ) ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
continue ;
2002-10-05 02:53:18 +04:00
if ( tdb_lock_bystring ( pdb - > tdb , sversion , 0 ) = = - 1 ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 0 , ( " print_backend_init: Failed to open printer %s database \n " , lp_const_servicename ( snum ) ) ) ;
2002-10-26 04:29:04 +04:00
release_print_db ( pdb ) ;
2002-09-25 19:19:00 +04:00
return False ;
}
2002-07-15 14:35:28 +04:00
if ( tdb_fetch_int32 ( pdb - > tdb , sversion ) ! = PRINT_DATABASE_VERSION ) {
tdb_traverse ( pdb - > tdb , tdb_traverse_delete_fn , NULL ) ;
tdb_store_int32 ( pdb - > tdb , sversion , PRINT_DATABASE_VERSION ) ;
}
tdb_unlock_bystring ( pdb - > tdb , sversion ) ;
2002-10-26 04:29:04 +04:00
release_print_db ( pdb ) ;
2000-04-16 10:20:02 +04:00
}
2002-10-26 04:29:04 +04:00
close_all_print_db ( ) ; /* Don't leave any open. */
2001-03-16 08:55:30 +03:00
/* do NT print initialization... */
2000-05-24 10:10:21 +04:00
return nt_printing_init ( ) ;
1996-05-04 11:50:46 +04:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Shut down printing backend . Called once at shutdown to close the tdb .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void printing_end ( void )
{
2002-11-01 02:41:00 +03:00
close_all_print_db ( ) ; /* Don't leave any open. */
2002-07-15 14:35:28 +04:00
}
2004-03-02 17:26:45 +03:00
/****************************************************************************
Retrieve the set of printing functions for a given service . This allows
us to set the printer function table based on the value of the ' printing '
service parameter .
Use the generic interface as the default and only use cups interface only
when asked for ( and only when supported )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-03-22 17:54:12 +03:00
static struct printif * get_printer_fns_from_type ( int type )
2004-03-02 17:26:45 +03:00
{
struct printif * printer_fns = & generic_printif ;
# ifdef HAVE_CUPS
2004-10-19 21:05:01 +04:00
if ( type = = PRINT_CUPS ) {
2004-03-02 17:26:45 +03:00
printer_fns = & cups_printif ;
}
# endif /* HAVE_CUPS */
2004-10-19 21:05:01 +04:00
printer_fns - > type = type ;
2004-03-02 17:26:45 +03:00
return printer_fns ;
}
2004-10-19 21:05:01 +04:00
static struct printif * get_printer_fns ( int snum )
{
return get_printer_fns_from_type ( lp_printing ( snum ) ) ;
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
Useful function to generate a tdb key .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static TDB_DATA print_key ( uint32 jobid )
1996-05-04 11:50:46 +04:00
{
2002-07-15 14:35:28 +04:00
static uint32 j ;
2000-04-16 10:20:02 +04:00
TDB_DATA ret ;
2004-05-07 21:17:25 +04:00
SIVAL ( & j , 0 , jobid ) ;
2000-04-16 10:20:02 +04:00
ret . dptr = ( void * ) & j ;
ret . dsize = sizeof ( j ) ;
return ret ;
1996-05-04 11:50:46 +04:00
}
2002-09-25 19:19:00 +04:00
/***********************************************************************
unpack a pjob from a tdb buffer
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int unpack_pjob ( char * buf , int buflen , struct printjob * pjob )
{
int len = 0 ;
int used ;
2003-03-22 01:00:21 +03:00
uint32 pjpid , pjsysjob , pjfd , pjstarttime , pjstatus ;
uint32 pjsize , pjpage_count , pjspooled , pjsmbjob ;
2002-09-25 19:19:00 +04:00
if ( ! buf | | ! pjob )
return - 1 ;
len + = tdb_unpack ( buf + len , buflen - len , " dddddddddffff " ,
2003-03-22 01:00:21 +03:00
& pjpid ,
& pjsysjob ,
& pjfd ,
& pjstarttime ,
& pjstatus ,
& pjsize ,
& pjpage_count ,
& pjspooled ,
& pjsmbjob ,
2002-09-25 19:19:00 +04:00
pjob - > filename ,
pjob - > jobname ,
pjob - > user ,
pjob - > queuename ) ;
if ( len = = - 1 )
return - 1 ;
if ( ( used = unpack_devicemode ( & pjob - > nt_devmode , buf + len , buflen - len ) ) = = - 1 )
return - 1 ;
len + = used ;
2003-03-22 01:00:21 +03:00
pjob - > pid = pjpid ;
pjob - > sysjob = pjsysjob ;
pjob - > fd = pjfd ;
pjob - > starttime = pjstarttime ;
pjob - > status = pjstatus ;
pjob - > size = pjsize ;
pjob - > page_count = pjpage_count ;
pjob - > spooled = pjspooled ;
pjob - > smbjob = pjsmbjob ;
2002-09-25 19:19:00 +04:00
return len ;
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Useful function to find a print job in the database .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2004-10-19 21:05:01 +04:00
static struct printjob * print_job_find ( const char * sharename , uint32 jobid )
2000-04-16 10:20:02 +04:00
{
2002-09-25 19:19:00 +04:00
static struct printjob pjob ;
TDB_DATA ret ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2002-09-25 19:19:00 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return NULL ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
ret = tdb_fetch ( pdb - > tdb , print_key ( jobid ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-04-16 10:20:02 +04:00
2002-09-25 19:19:00 +04:00
if ( ! ret . dptr )
return NULL ;
if ( pjob . nt_devmode )
free_nt_devicemode ( & pjob . nt_devmode ) ;
ZERO_STRUCT ( pjob ) ;
2002-11-23 05:52:36 +03:00
if ( unpack_pjob ( ret . dptr , ret . dsize , & pjob ) = = - 1 ) {
SAFE_FREE ( ret . dptr ) ;
2002-09-25 19:19:00 +04:00
return NULL ;
2002-11-23 05:52:36 +03:00
}
2002-09-25 19:19:00 +04:00
SAFE_FREE ( ret . dptr ) ;
2000-04-16 10:20:02 +04:00
return & pjob ;
}
1996-05-04 11:50:46 +04:00
2002-07-15 14:35:28 +04:00
/* Convert a unix jobid to a smb jobid */
static uint32 sysjob_to_jobid_value ;
static int unixjob_traverse_fn ( TDB_CONTEXT * the_tdb , TDB_DATA key ,
TDB_DATA data , void * state )
{
2002-09-25 19:19:00 +04:00
struct printjob * pjob ;
2002-07-15 14:35:28 +04:00
int * sysjob = ( int * ) state ;
2002-09-25 19:19:00 +04:00
if ( ! data . dptr | | data . dsize = = 0 )
return 0 ;
pjob = ( struct printjob * ) data . dptr ;
2002-07-15 14:35:28 +04:00
if ( key . dsize ! = sizeof ( uint32 ) )
return 0 ;
if ( * sysjob = = pjob - > sysjob ) {
2004-05-07 21:17:25 +04:00
uint32 jobid = IVAL ( key . dptr , 0 ) ;
2002-07-15 14:35:28 +04:00
2004-05-07 21:17:25 +04:00
sysjob_to_jobid_value = jobid ;
2002-07-15 14:35:28 +04:00
return 1 ;
}
return 0 ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
This is a * horribly expensive call as we have to iterate through all the
current printer tdb ' s . Don ' t do this often ! JRA .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
uint32 sysjob_to_jobid ( int unix_jobid )
{
2002-08-17 21:00:51 +04:00
int services = lp_numservices ( ) ;
int snum ;
2002-07-15 14:35:28 +04:00
sysjob_to_jobid_value = ( uint32 ) - 1 ;
2002-08-17 21:00:51 +04:00
for ( snum = 0 ; snum < services ; snum + + ) {
struct tdb_print_db * pdb ;
if ( ! lp_print_ok ( snum ) )
continue ;
pdb = get_print_db_byname ( lp_const_servicename ( snum ) ) ;
2002-07-15 14:35:28 +04:00
if ( pdb )
tdb_traverse ( pdb - > tdb , unixjob_traverse_fn , & unix_jobid ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-07-15 14:35:28 +04:00
if ( sysjob_to_jobid_value ! = ( uint32 ) - 1 )
return sysjob_to_jobid_value ;
}
return ( uint32 ) - 1 ;
}
/****************************************************************************
Send notifications based on what has changed after a pjob_store .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct {
uint32 lpq_status ;
uint32 spoolss_status ;
} lpq_to_spoolss_status_map [ ] = {
{ LPQ_QUEUED , JOB_STATUS_QUEUED } ,
{ LPQ_PAUSED , JOB_STATUS_PAUSED } ,
{ LPQ_SPOOLING , JOB_STATUS_SPOOLING } ,
{ LPQ_PRINTING , JOB_STATUS_PRINTING } ,
{ LPQ_DELETING , JOB_STATUS_DELETING } ,
{ LPQ_OFFLINE , JOB_STATUS_OFFLINE } ,
{ LPQ_PAPEROUT , JOB_STATUS_PAPEROUT } ,
{ LPQ_PRINTED , JOB_STATUS_PRINTED } ,
{ LPQ_DELETED , JOB_STATUS_DELETED } ,
{ LPQ_BLOCKED , JOB_STATUS_BLOCKED } ,
{ LPQ_USER_INTERVENTION , JOB_STATUS_USER_INTERVENTION } ,
{ - 1 , 0 }
} ;
/* Convert a lpq status value stored in printing.tdb into the
appropriate win32 API constant . */
static uint32 map_to_spoolss_status ( uint32 lpq_status )
1996-05-04 11:50:46 +04:00
{
2002-07-15 14:35:28 +04:00
int i = 0 ;
while ( lpq_to_spoolss_status_map [ i ] . lpq_status ! = - 1 ) {
if ( lpq_to_spoolss_status_map [ i ] . lpq_status = = lpq_status )
return lpq_to_spoolss_status_map [ i ] . spoolss_status ;
i + + ;
}
return 0 ;
}
2004-10-19 21:05:01 +04:00
static void pjob_store_notify ( const char * sharename , uint32 jobid , struct printjob * old_data ,
2002-07-15 14:35:28 +04:00
struct printjob * new_data )
{
BOOL new_job = False ;
if ( ! old_data )
new_job = True ;
/* Job attributes that can't be changed. We only send
notification for these on a new job . */
2004-08-31 19:11:41 +04:00
/* ACHTUNG! Due to a bug in Samba's spoolss parsing of the
NOTIFY_INFO_DATA buffer , we * have * to send the job submission
time first or else we ' ll end up with potential alignment
errors . I don ' t think the systemtime should be spooled as
a string , but this gets us around that error .
- - jerry ( i ' ll feel dirty for this ) */
2002-07-15 14:35:28 +04:00
if ( new_job ) {
2004-10-19 21:05:01 +04:00
notify_job_submitted ( sharename , jobid , new_data - > starttime ) ;
notify_job_username ( sharename , jobid , new_data - > user ) ;
2002-07-15 14:35:28 +04:00
}
2004-08-31 19:11:41 +04:00
if ( new_job | | ! strequal ( old_data - > jobname , new_data - > jobname ) )
2004-10-19 21:05:01 +04:00
notify_job_name ( sharename , jobid , new_data - > jobname ) ;
2004-08-31 19:11:41 +04:00
2002-07-15 14:35:28 +04:00
/* Job attributes of a new job or attributes that can be
modified . */
2004-08-31 19:11:41 +04:00
if ( new_job | | ! strequal ( old_data - > jobname , new_data - > jobname ) )
2004-10-19 21:05:01 +04:00
notify_job_name ( sharename , jobid , new_data - > jobname ) ;
2004-08-31 19:11:41 +04:00
2002-07-15 14:35:28 +04:00
if ( new_job | | old_data - > status ! = new_data - > status )
2004-10-19 21:05:01 +04:00
notify_job_status ( sharename , jobid , map_to_spoolss_status ( new_data - > status ) ) ;
2002-07-15 14:35:28 +04:00
if ( new_job | | old_data - > size ! = new_data - > size )
2004-10-19 21:05:01 +04:00
notify_job_total_bytes ( sharename , jobid , new_data - > size ) ;
2002-07-15 14:35:28 +04:00
if ( new_job | | old_data - > page_count ! = new_data - > page_count )
2004-10-19 21:05:01 +04:00
notify_job_total_pages ( sharename , jobid , new_data - > page_count ) ;
2002-07-15 14:35:28 +04:00
}
/****************************************************************************
Store a job structure back to the database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
static BOOL pjob_store ( const char * sharename , uint32 jobid , struct printjob * pjob )
2002-07-15 14:35:28 +04:00
{
2002-09-25 19:19:00 +04:00
TDB_DATA old_data , new_data ;
BOOL ret = False ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2002-09-25 19:19:00 +04:00
char * buf = NULL ;
int len , newlen , buflen ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return False ;
/* Get old data */
old_data = tdb_fetch ( pdb - > tdb , print_key ( jobid ) ) ;
2002-09-25 19:19:00 +04:00
/* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
newlen = 0 ;
do {
len = 0 ;
buflen = newlen ;
len + = tdb_pack ( buf + len , buflen - len , " dddddddddffff " ,
2003-03-22 01:00:21 +03:00
( uint32 ) pjob - > pid ,
( uint32 ) pjob - > sysjob ,
( uint32 ) pjob - > fd ,
( uint32 ) pjob - > starttime ,
( uint32 ) pjob - > status ,
( uint32 ) pjob - > size ,
( uint32 ) pjob - > page_count ,
( uint32 ) pjob - > spooled ,
( uint32 ) pjob - > smbjob ,
2002-09-25 19:19:00 +04:00
pjob - > filename ,
pjob - > jobname ,
pjob - > user ,
pjob - > queuename ) ;
len + = pack_devicemode ( pjob - > nt_devmode , buf + len , buflen - len ) ;
2002-11-23 05:52:36 +03:00
if ( buflen ! = len ) {
2002-09-25 19:19:00 +04:00
char * tb ;
2004-12-07 21:25:53 +03:00
tb = ( char * ) SMB_REALLOC ( buf , len ) ;
2002-09-25 19:19:00 +04:00
if ( ! tb ) {
DEBUG ( 0 , ( " pjob_store: failed to enlarge buffer! \n " ) ) ;
goto done ;
}
else
buf = tb ;
newlen = len ;
}
2002-11-23 05:52:36 +03:00
} while ( buflen ! = len ) ;
2002-09-25 19:19:00 +04:00
2002-07-15 14:35:28 +04:00
/* Store new data */
2002-09-25 19:19:00 +04:00
new_data . dptr = buf ;
new_data . dsize = len ;
2002-07-15 14:35:28 +04:00
ret = ( tdb_store ( pdb - > tdb , print_key ( jobid ) , new_data , TDB_REPLACE ) = = 0 ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-07-15 14:35:28 +04:00
/* Send notify updates for what has changed */
2004-03-16 20:06:11 +03:00
if ( ret ) {
struct printjob old_pjob ;
if ( old_data . dsize )
{
if ( unpack_pjob ( old_data . dptr , old_data . dsize , & old_pjob ) ! = - 1 )
{
2004-10-19 21:05:01 +04:00
pjob_store_notify ( sharename , jobid , & old_pjob , pjob ) ;
2004-03-16 20:06:11 +03:00
free_nt_devicemode ( & old_pjob . nt_devmode ) ;
}
}
else {
/* new job */
2004-10-19 21:05:01 +04:00
pjob_store_notify ( sharename , jobid , NULL , pjob ) ;
2004-03-16 20:06:11 +03:00
}
}
2002-09-25 19:19:00 +04:00
done :
SAFE_FREE ( old_data . dptr ) ;
SAFE_FREE ( buf ) ;
2002-03-21 01:39:30 +03:00
return ret ;
2000-04-16 10:20:02 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Remove a job structure from the database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
void pjob_delete ( const char * sharename , uint32 jobid )
2002-07-15 14:35:28 +04:00
{
2004-10-19 21:05:01 +04:00
struct printjob * pjob ;
2002-07-15 14:35:28 +04:00
uint32 job_status = 0 ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb ;
pdb = get_print_db_byname ( sharename ) ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return ;
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2002-07-15 14:35:28 +04:00
if ( ! pjob ) {
2004-08-31 19:11:41 +04:00
DEBUG ( 5 , ( " pjob_delete: we were asked to delete nonexistent job %u \n " ,
2002-07-15 14:35:28 +04:00
( unsigned int ) jobid ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-07-15 14:35:28 +04:00
return ;
}
/* We must cycle through JOB_STATUS_DELETING and
JOB_STATUS_DELETED for the port monitor to delete the job
properly . */
2004-08-31 19:11:41 +04:00
job_status = JOB_STATUS_DELETING | JOB_STATUS_DELETED ;
2004-10-19 21:05:01 +04:00
notify_job_status ( sharename , jobid , job_status ) ;
2002-07-15 14:35:28 +04:00
/* Remove from printing.tdb */
tdb_delete ( pdb - > tdb , print_key ( jobid ) ) ;
2004-10-19 21:05:01 +04:00
remove_from_jobs_changed ( sharename , jobid ) ;
release_print_db ( pdb ) ;
rap_jobid_delete ( sharename , jobid ) ;
2002-07-15 14:35:28 +04:00
}
/****************************************************************************
Parse a file name from the system spooler to generate a jobid .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static uint32 print_parse_jobid ( char * fname )
1996-05-04 11:50:46 +04:00
{
2000-04-16 10:20:02 +04:00
int jobid ;
1996-05-04 11:50:46 +04:00
2002-07-15 14:35:28 +04:00
if ( strncmp ( fname , PRINT_SPOOL_PREFIX , strlen ( PRINT_SPOOL_PREFIX ) ) ! = 0 )
return ( uint32 ) - 1 ;
2000-04-16 10:20:02 +04:00
fname + = strlen ( PRINT_SPOOL_PREFIX ) ;
1996-05-04 11:50:46 +04:00
2000-04-16 10:20:02 +04:00
jobid = atoi ( fname ) ;
2002-07-15 14:35:28 +04:00
if ( jobid < = 0 )
return ( uint32 ) - 1 ;
1996-05-04 11:50:46 +04:00
2002-07-15 14:35:28 +04:00
return ( uint32 ) jobid ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
List a unix job in the print database .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2004-10-19 21:05:01 +04:00
static void print_unix_job ( const char * sharename , print_queue_struct * q , uint32 jobid )
1996-05-04 11:50:46 +04:00
{
2000-11-08 02:05:53 +03:00
struct printjob pj , * old_pj ;
2000-04-16 10:20:02 +04:00
2004-01-14 23:56:26 +03:00
if ( jobid = = ( uint32 ) - 1 )
2003-02-19 04:43:33 +03:00
jobid = q - > job + UNIX_JOB_START ;
2000-11-08 02:05:53 +03:00
/* Preserve the timestamp on an existing unix print job */
2000-11-04 22:48:53 +03:00
2004-10-19 21:05:01 +04:00
old_pj = print_job_find ( sharename , jobid ) ;
2000-11-04 22:48:53 +03:00
2000-04-16 10:20:02 +04:00
ZERO_STRUCT ( pj ) ;
pj . pid = ( pid_t ) - 1 ;
pj . sysjob = q - > job ;
pj . fd = - 1 ;
2000-11-08 02:05:53 +03:00
pj . starttime = old_pj ? old_pj - > starttime : q - > time ;
2000-04-16 10:20:02 +04:00
pj . status = q - > status ;
pj . size = q - > size ;
pj . spooled = True ;
2003-02-19 04:43:33 +03:00
fstrcpy ( pj . filename , old_pj ? old_pj - > filename : " " ) ;
2003-12-01 21:02:05 +03:00
if ( jobid < UNIX_JOB_START ) {
2004-01-14 22:12:06 +03:00
pj . smbjob = True ;
2003-02-19 04:43:33 +03:00
fstrcpy ( pj . jobname , old_pj ? old_pj - > jobname : " Remote Downlevel Document " ) ;
2003-12-01 21:02:05 +03:00
} else {
pj . smbjob = False ;
2003-02-19 04:43:33 +03:00
fstrcpy ( pj . jobname , old_pj ? old_pj - > jobname : q - > fs_file ) ;
2003-12-01 21:02:05 +03:00
}
2003-02-19 04:43:33 +03:00
fstrcpy ( pj . user , old_pj ? old_pj - > user : q - > fs_user ) ;
2004-10-19 21:05:01 +04:00
fstrcpy ( pj . queuename , old_pj ? old_pj - > queuename : sharename ) ;
2000-04-16 10:20:02 +04:00
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , & pj ) ;
2000-04-16 10:20:02 +04:00
}
1996-05-04 11:50:46 +04:00
2000-04-16 10:20:02 +04:00
struct traverse_struct {
print_queue_struct * queue ;
2001-01-23 23:25:25 +03:00
int qcount , snum , maxcount , total_jobs ;
2004-10-19 21:05:01 +04:00
const char * sharename ;
2003-01-10 04:21:59 +03:00
time_t lpq_time ;
2000-04-16 10:20:02 +04:00
} ;
2002-07-15 14:35:28 +04:00
/****************************************************************************
Utility fn to delete any jobs that are no longer active .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-16 10:20:02 +04:00
static int traverse_fn_delete ( TDB_CONTEXT * t , TDB_DATA key , TDB_DATA data , void * state )
{
struct traverse_struct * ts = ( struct traverse_struct * ) state ;
struct printjob pjob ;
2002-07-15 14:35:28 +04:00
uint32 jobid ;
2004-03-05 20:39:38 +03:00
int i = 0 ;
2000-04-16 10:20:02 +04:00
2002-09-25 19:19:00 +04:00
if ( key . dsize ! = sizeof ( jobid ) )
2002-07-15 14:35:28 +04:00
return 0 ;
2002-09-25 19:19:00 +04:00
2004-01-14 22:12:06 +03:00
jobid = IVAL ( key . dptr , 0 ) ;
2002-09-25 19:19:00 +04:00
if ( unpack_pjob ( data . dptr , data . dsize , & pjob ) = = - 1 )
return 0 ;
free_nt_devicemode ( & pjob . nt_devmode ) ;
1996-05-04 11:50:46 +04:00
2000-04-16 10:20:02 +04:00
if ( ! pjob . smbjob ) {
2001-01-23 23:25:25 +03:00
/* remove a unix job if it isn't in the system queue any more */
2000-11-08 02:05:53 +03:00
2000-04-16 10:20:02 +04:00
for ( i = 0 ; i < ts - > qcount ; i + + ) {
2002-08-17 21:00:51 +04:00
uint32 u_jobid = ( ts - > queue [ i ] . job + UNIX_JOB_START ) ;
2002-07-15 14:35:28 +04:00
if ( jobid = = u_jobid )
break ;
2000-04-16 10:20:02 +04:00
}
2003-04-02 06:31:51 +04:00
if ( i = = ts - > qcount ) {
DEBUG ( 10 , ( " traverse_fn_delete: pjob %u deleted due to !smbjob \n " ,
( unsigned int ) jobid ) ) ;
2004-10-19 21:05:01 +04:00
pjob_delete ( ts - > sharename , jobid ) ;
2004-01-14 23:56:26 +03:00
return 0 ;
}
/* need to continue the the bottom of the function to
save the correct attributes */
2000-04-16 10:20:02 +04:00
}
1996-05-04 11:50:46 +04:00
2000-04-16 10:20:02 +04:00
/* maybe it hasn't been spooled yet */
if ( ! pjob . spooled ) {
/* if a job is not spooled and the process doesn't
exist then kill it . This cleans up after smbd
deaths */
2003-04-02 06:31:51 +04:00
if ( ! process_exists ( pjob . pid ) ) {
DEBUG ( 10 , ( " traverse_fn_delete: pjob %u deleted due to !process_exists (%u) \n " ,
( unsigned int ) jobid , ( unsigned int ) pjob . pid ) ) ;
2004-10-19 21:05:01 +04:00
pjob_delete ( ts - > sharename , jobid ) ;
2003-04-02 06:31:51 +04:00
} else
2001-01-23 23:25:25 +03:00
ts - > total_jobs + + ;
2000-04-16 10:20:02 +04:00
return 0 ;
1996-05-04 11:50:46 +04:00
}
2004-01-14 23:56:26 +03:00
/* this check only makes sense for jobs submitted from Windows clients */
if ( pjob . smbjob ) {
for ( i = 0 ; i < ts - > qcount ; i + + ) {
uint32 curr_jobid = print_parse_jobid ( ts - > queue [ i ] . fs_file ) ;
if ( jobid = = curr_jobid )
break ;
}
1998-08-14 21:38:29 +04:00
}
2000-11-15 04:11:38 +03:00
/* The job isn't in the system queue - we have to assume it has
completed , so delete the database entry . */
2000-04-16 10:20:02 +04:00
if ( i = = ts - > qcount ) {
2000-11-15 04:11:38 +03:00
/* A race can occur between the time a job is spooled and
when it appears in the lpq output . This happens when
the job is added to printing . tdb when another smbd
running print_queue_update ( ) has completed a lpq and
is currently traversing the printing tdb and deleting jobs .
2003-01-10 04:21:59 +03:00
Don ' t delete the job if it was submitted after the lpq_time . */
2000-11-15 04:11:38 +03:00
2003-04-02 06:31:51 +04:00
if ( pjob . starttime < ts - > lpq_time ) {
DEBUG ( 10 , ( " traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u) \n " ,
( unsigned int ) jobid ,
( unsigned int ) pjob . starttime ,
( unsigned int ) ts - > lpq_time ) ) ;
2004-10-19 21:05:01 +04:00
pjob_delete ( ts - > sharename , jobid ) ;
2003-04-02 06:31:51 +04:00
} else
2001-01-23 23:25:25 +03:00
ts - > total_jobs + + ;
2003-04-04 05:02:20 +04:00
return 0 ;
2000-04-16 10:20:02 +04:00
}
2003-04-04 05:02:20 +04:00
/* Save the pjob attributes we will store. */
2004-01-14 23:56:26 +03:00
/* FIXME!!! This is the only place where queue->job
represents the SMB jobid - - jerry */
ts - > queue [ i ] . job = jobid ;
2003-04-04 05:02:20 +04:00
ts - > queue [ i ] . size = pjob . size ;
ts - > queue [ i ] . page_count = pjob . page_count ;
ts - > queue [ i ] . status = pjob . status ;
ts - > queue [ i ] . priority = 1 ;
ts - > queue [ i ] . time = pjob . starttime ;
fstrcpy ( ts - > queue [ i ] . fs_user , pjob . user ) ;
fstrcpy ( ts - > queue [ i ] . fs_file , pjob . jobname ) ;
ts - > total_jobs + + ;
2000-04-16 10:20:02 +04:00
return 0 ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Check if the print queue has been updated recently enough .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-16 10:20:02 +04:00
static void print_cache_flush ( int snum )
{
fstring key ;
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return ;
2004-10-19 21:05:01 +04:00
slprintf ( key , sizeof ( key ) - 1 , " CACHE/%s " , sharename ) ;
2002-07-15 14:35:28 +04:00
tdb_store_int32 ( pdb - > tdb , key , - 1 ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-04-16 10:20:02 +04:00
}
2001-02-22 20:39:36 +03:00
/****************************************************************************
Check if someone already thinks they are doing the update .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-03-08 20:22:39 +03:00
static pid_t get_updating_pid ( const char * sharename )
2001-02-22 20:39:36 +03:00
{
fstring keystr ;
TDB_DATA data , key ;
pid_t updating_pid ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2001-02-22 20:39:36 +03:00
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return ( pid_t ) - 1 ;
2004-10-19 21:05:01 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " UPDATING/%s " , sharename ) ;
2001-02-22 20:39:36 +03:00
key . dptr = keystr ;
key . dsize = strlen ( keystr ) ;
2002-07-15 14:35:28 +04:00
data = tdb_fetch ( pdb - > tdb , key ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-11-23 05:52:36 +03:00
if ( ! data . dptr | | data . dsize ! = sizeof ( pid_t ) ) {
SAFE_FREE ( data . dptr ) ;
2001-02-22 20:39:36 +03:00
return ( pid_t ) - 1 ;
2002-11-23 05:52:36 +03:00
}
2001-02-22 20:39:36 +03:00
2004-01-14 22:12:06 +03:00
updating_pid = IVAL ( data . dptr , 0 ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( data . dptr ) ;
2001-02-22 20:39:36 +03:00
if ( process_exists ( updating_pid ) )
return updating_pid ;
return ( pid_t ) - 1 ;
}
/****************************************************************************
Set the fact that we ' re doing the update , or have finished doing the update
2002-07-15 14:35:28 +04:00
in the tdb .
2001-02-22 20:39:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-12-01 23:11:31 +03:00
static void set_updating_pid ( const fstring sharename , BOOL updating )
2001-02-22 20:39:36 +03:00
{
fstring keystr ;
TDB_DATA key ;
TDB_DATA data ;
2002-03-14 04:53:04 +03:00
pid_t updating_pid = sys_getpid ( ) ;
2004-03-15 18:06:33 +03:00
uint8 buffer [ 4 ] ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return ;
2001-02-22 20:39:36 +03:00
2004-10-19 21:05:01 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " UPDATING/%s " , sharename ) ;
2001-02-22 20:39:36 +03:00
key . dptr = keystr ;
key . dsize = strlen ( keystr ) ;
2004-12-01 23:11:31 +03:00
DEBUG ( 5 , ( " set_updating_pid: %s updating lpq cache for print share %s \n " ,
updating ? " " : " not " ,
sharename ) ) ;
2001-02-22 20:39:36 +03:00
2004-12-01 23:11:31 +03:00
if ( ! updating ) {
2002-07-15 14:35:28 +04:00
tdb_delete ( pdb - > tdb , key ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2001-02-22 20:39:36 +03:00
return ;
}
2004-03-15 18:06:33 +03:00
SIVAL ( buffer , 0 , updating_pid ) ;
data . dptr = ( void * ) buffer ;
data . dsize = 4 ; /* we always assume this is a 4 byte value */
2001-02-22 20:39:36 +03:00
2002-07-15 14:35:28 +04:00
tdb_store ( pdb - > tdb , key , data , TDB_REPLACE ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-02-26 06:12:09 +03:00
}
2003-03-22 01:00:21 +03:00
/****************************************************************************
Sort print jobs by submittal time .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int printjob_comp ( print_queue_struct * j1 , print_queue_struct * j2 )
{
/* Silly cases */
if ( ! j1 & & ! j2 )
return 0 ;
if ( ! j1 )
return - 1 ;
if ( ! j2 )
return 1 ;
/* Sort on job start time */
if ( j1 - > time = = j2 - > time )
return 0 ;
return ( j1 - > time > j2 - > time ) ? 1 : - 1 ;
}
/****************************************************************************
Store the sorted queue representation for later portmon retrieval .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void store_queue_struct ( struct tdb_print_db * pdb , struct traverse_struct * pts )
{
2005-03-12 12:58:35 +03:00
TDB_DATA data ;
2003-03-22 01:00:21 +03:00
int max_reported_jobs = lp_max_reported_jobs ( pts - > snum ) ;
print_queue_struct * queue = pts - > queue ;
size_t len ;
size_t i ;
uint qcount ;
2003-11-13 23:15:17 +03:00
if ( max_reported_jobs & & ( max_reported_jobs < pts - > qcount ) )
2003-03-22 01:00:21 +03:00
pts - > qcount = max_reported_jobs ;
qcount = pts - > qcount ;
/* Work out the size. */
data . dsize = 0 ;
2003-04-10 23:34:52 +04:00
data . dsize + = tdb_pack ( NULL , 0 , " d " , qcount ) ;
2003-03-22 01:00:21 +03:00
for ( i = 0 ; i < pts - > qcount ; i + + ) {
2003-03-26 22:35:37 +03:00
data . dsize + = tdb_pack ( NULL , 0 , " ddddddff " ,
2003-03-22 01:00:21 +03:00
( uint32 ) queue [ i ] . job ,
( uint32 ) queue [ i ] . size ,
( uint32 ) queue [ i ] . page_count ,
( uint32 ) queue [ i ] . status ,
( uint32 ) queue [ i ] . priority ,
( uint32 ) queue [ i ] . time ,
queue [ i ] . fs_user ,
queue [ i ] . fs_file ) ;
}
2004-12-07 21:25:53 +03:00
if ( ( data . dptr = SMB_MALLOC ( data . dsize ) ) = = NULL )
2003-03-22 01:00:21 +03:00
return ;
len = 0 ;
2003-03-26 22:35:37 +03:00
len + = tdb_pack ( data . dptr + len , data . dsize - len , " d " , qcount ) ;
2003-03-22 01:00:21 +03:00
for ( i = 0 ; i < pts - > qcount ; i + + ) {
2003-03-26 22:35:37 +03:00
len + = tdb_pack ( data . dptr + len , data . dsize - len , " ddddddff " ,
2003-03-22 01:00:21 +03:00
( uint32 ) queue [ i ] . job ,
( uint32 ) queue [ i ] . size ,
( uint32 ) queue [ i ] . page_count ,
( uint32 ) queue [ i ] . status ,
( uint32 ) queue [ i ] . priority ,
( uint32 ) queue [ i ] . time ,
queue [ i ] . fs_user ,
queue [ i ] . fs_file ) ;
}
2005-03-12 12:58:35 +03:00
tdb_store ( pdb - > tdb , string_tdb_data ( " INFO/linear_queue_array " ) , data ,
TDB_REPLACE ) ;
2003-04-16 12:46:03 +04:00
SAFE_FREE ( data . dptr ) ;
2003-03-22 01:00:21 +03:00
return ;
}
2003-04-02 06:31:51 +04:00
static TDB_DATA get_jobs_changed_data ( struct tdb_print_db * pdb )
{
2005-03-12 12:58:35 +03:00
TDB_DATA data ;
2003-04-02 06:31:51 +04:00
ZERO_STRUCT ( data ) ;
2005-03-12 12:58:35 +03:00
data = tdb_fetch ( pdb - > tdb , string_tdb_data ( " INFO/jobs_changed " ) ) ;
2003-04-02 06:31:51 +04:00
if ( data . dptr = = NULL | | data . dsize = = 0 | | ( data . dsize % 4 ! = 0 ) ) {
SAFE_FREE ( data . dptr ) ;
ZERO_STRUCT ( data ) ;
}
return data ;
}
2004-10-19 21:05:01 +04:00
static void check_job_changed ( const char * sharename , TDB_DATA data , uint32 jobid )
2003-04-02 06:31:51 +04:00
{
unsigned int i ;
unsigned int job_count = data . dsize / 4 ;
for ( i = 0 ; i < job_count ; i + + ) {
uint32 ch_jobid ;
2004-01-14 22:12:06 +03:00
ch_jobid = IVAL ( data . dptr , i * 4 ) ;
2003-04-02 06:31:51 +04:00
if ( ch_jobid = = jobid )
2004-10-19 21:05:01 +04:00
remove_from_jobs_changed ( sharename , jobid ) ;
2003-04-02 06:31:51 +04:00
}
}
2004-12-01 23:11:31 +03:00
/****************************************************************************
Check if the print queue has been updated recently enough .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-12-08 06:02:29 +03:00
static BOOL print_cache_expired ( const char * sharename , BOOL check_pending )
2004-12-01 23:11:31 +03:00
{
fstring key ;
time_t last_qscan_time , time_now = time ( NULL ) ;
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2004-12-08 06:02:29 +03:00
BOOL result = False ;
2004-12-01 23:11:31 +03:00
if ( ! pdb )
return False ;
2004-12-08 06:02:29 +03:00
snprintf ( key , sizeof ( key ) , " CACHE/%s " , sharename ) ;
2004-12-01 23:11:31 +03:00
last_qscan_time = ( time_t ) tdb_fetch_int32 ( pdb - > tdb , key ) ;
/*
* Invalidate the queue for 3 reasons .
* ( 1 ) . last queue scan time = = - 1.
* ( 2 ) . Current time - last queue scan time > allowed cache time .
* ( 3 ) . last queue scan time > current time + MAX_CACHE_VALID_TIME ( 1 hour by default ) .
* This last test picks up machines for which the clock has been moved
* forward , an lpq scan done and then the clock moved back . Otherwise
* that last lpq scan would stay around for a loooong loooong time . . . : - ) . JRA .
*/
if ( last_qscan_time = = ( ( time_t ) - 1 )
| | ( time_now - last_qscan_time ) > = lp_lpqcachetime ( )
| | last_qscan_time > ( time_now + MAX_CACHE_VALID_TIME ) )
{
2004-12-08 06:02:29 +03:00
time_t msg_pending_time ;
DEBUG ( 4 , ( " print_cache_expired: cache expired for queue %s "
2004-12-01 23:11:31 +03:00
" (last_qscan_time = %d, time now = %d, qcachetime = %d) \n " ,
sharename , ( int ) last_qscan_time , ( int ) time_now ,
( int ) lp_lpqcachetime ( ) ) ) ;
2004-12-08 06:02:29 +03:00
/* check if another smbd has already sent a message to update the
queue . Give the pending message one minute to clear and
then send another message anyways . Make sure to check for
clocks that have been run forward and then back again . */
snprintf ( key , sizeof ( key ) , " MSG_PENDING/%s " , sharename ) ;
if ( check_pending
2005-03-15 23:27:17 +03:00
& & tdb_fetch_uint32 ( pdb - > tdb , key , ( uint32 * ) & msg_pending_time )
2004-12-08 06:02:29 +03:00
& & msg_pending_time > 0
& & msg_pending_time < = time_now
& & ( time_now - msg_pending_time ) < 60 )
{
DEBUG ( 4 , ( " print_cache_expired: message already pending for %s. Accepting cache \n " ,
sharename ) ) ;
goto done ;
}
result = True ;
2004-12-01 23:11:31 +03:00
}
2004-12-08 06:02:29 +03:00
done :
2004-12-01 23:11:31 +03:00
release_print_db ( pdb ) ;
2004-12-08 06:02:29 +03:00
return result ;
2004-12-01 23:11:31 +03:00
}
2004-10-19 21:05:01 +04:00
2000-04-16 10:20:02 +04:00
/****************************************************************************
2004-10-19 21:05:01 +04:00
main work for updating the lpq cahe for a printer queue
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-02-22 20:39:36 +03:00
2004-10-19 21:05:01 +04:00
static void print_queue_update_internal ( const char * sharename ,
struct printif * current_printif ,
char * lpq_command )
2000-04-16 10:20:02 +04:00
{
2001-03-16 08:55:30 +03:00
int i , qcount ;
2000-04-16 10:20:02 +04:00
print_queue_struct * queue = NULL ;
print_status_struct status ;
2000-11-21 03:30:15 +03:00
print_status_struct old_status ;
2000-04-16 10:20:02 +04:00
struct printjob * pjob ;
struct traverse_struct tstruct ;
TDB_DATA data , key ;
2003-04-02 06:31:51 +04:00
TDB_DATA jcdata ;
2004-10-19 21:05:01 +04:00
fstring keystr , cachestr ;
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2004-12-01 23:11:31 +03:00
DEBUG ( 5 , ( " print_queue_update_internal: printer = %s, type = %d, lpq command = [%s] \n " ,
sharename , current_printif - > type , lpq_command ) ) ;
2001-02-23 06:59:37 +03:00
/*
* Update the cache time FIRST ! Stops others even
* attempting to get the lock and doing this
* if the lpq takes a long time .
*/
2004-12-01 23:11:31 +03:00
2004-10-19 21:05:01 +04:00
slprintf ( cachestr , sizeof ( cachestr ) - 1 , " CACHE/%s " , sharename ) ;
2002-07-15 14:35:28 +04:00
tdb_store_int32 ( pdb - > tdb , cachestr , ( int ) time ( NULL ) ) ;
2000-10-11 01:52:31 +04:00
2001-03-16 08:55:30 +03:00
/* get the current queue using the appropriate interface */
2000-04-16 10:20:02 +04:00
ZERO_STRUCT ( status ) ;
2001-03-16 08:55:30 +03:00
2004-10-19 21:05:01 +04:00
qcount = ( * ( current_printif - > queue_get ) ) ( sharename ,
current_printif - > type ,
lpq_command , & queue , & status ) ;
2000-04-16 10:20:02 +04:00
2004-12-01 23:11:31 +03:00
DEBUG ( 3 , ( " print_queue_update_internal: %d job%s in queue for %s \n " ,
qcount , ( qcount ! = 1 ) ? " s " : " " , sharename ) ) ;
2000-11-11 01:05:08 +03:00
2003-03-22 01:00:21 +03:00
/* Sort the queue by submission time otherwise they are displayed
in hash order . */
qsort ( queue , qcount , sizeof ( print_queue_struct ) ,
2004-10-19 21:05:01 +04:00
QSORT_CAST ( printjob_comp ) ) ;
2003-03-22 01:00:21 +03:00
2000-04-16 10:20:02 +04:00
/*
any job in the internal database that is marked as spooled
and doesn ' t exist in the system queue is considered finished
and removed from the database
any job in the system database but not in the internal database
is added as a unix job
fill in any system job numbers as we go
*/
2003-04-02 06:31:51 +04:00
jcdata = get_jobs_changed_data ( pdb ) ;
2000-04-16 10:20:02 +04:00
for ( i = 0 ; i < qcount ; i + + ) {
2002-07-15 14:35:28 +04:00
uint32 jobid = print_parse_jobid ( queue [ i ] . fs_file ) ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
if ( jobid = = ( uint32 ) - 1 ) {
2000-04-16 10:20:02 +04:00
/* assume its a unix print job */
2004-10-19 21:05:01 +04:00
print_unix_job ( sharename , & queue [ i ] , jobid ) ;
2000-04-16 10:20:02 +04:00
continue ;
}
1998-08-14 21:38:29 +04:00
2000-04-16 10:20:02 +04:00
/* we have an active SMB print job - update its status */
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2000-04-16 10:20:02 +04:00
if ( ! pjob ) {
/* err, somethings wrong. Probably smbd was restarted
with jobs in the queue . All we can do is treat them
like unix jobs . Pity . */
2004-10-19 21:05:01 +04:00
print_unix_job ( sharename , & queue [ i ] , jobid ) ;
1998-08-14 21:38:29 +04:00
continue ;
2000-04-16 10:20:02 +04:00
}
1998-08-14 21:38:29 +04:00
2000-04-16 10:20:02 +04:00
pjob - > sysjob = queue [ i ] . job ;
pjob - > status = queue [ i ] . status ;
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , pjob ) ;
check_job_changed ( sharename , jcdata , jobid ) ;
1998-08-14 21:38:29 +04:00
}
2000-04-16 10:20:02 +04:00
2003-04-02 06:31:51 +04:00
SAFE_FREE ( jcdata . dptr ) ;
2000-04-16 10:20:02 +04:00
/* now delete any queued entries that don't appear in the
system queue */
tstruct . queue = queue ;
tstruct . qcount = qcount ;
2004-10-19 21:05:01 +04:00
tstruct . snum = - 1 ;
2001-01-23 23:25:25 +03:00
tstruct . total_jobs = 0 ;
2003-01-10 04:21:59 +03:00
tstruct . lpq_time = time ( NULL ) ;
2004-10-19 21:05:01 +04:00
tstruct . sharename = sharename ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
tdb_traverse ( pdb - > tdb , traverse_fn_delete , ( void * ) & tstruct ) ;
2000-04-16 10:20:02 +04:00
2003-03-22 01:00:21 +03:00
/* Store the linearised queue, max jobs only. */
store_queue_struct ( pdb , & tstruct ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( tstruct . queue ) ;
2001-01-23 23:25:25 +03:00
2004-12-01 23:11:31 +03:00
DEBUG ( 10 , ( " print_queue_update_internal: printer %s INFO/total_jobs = %d \n " ,
2004-10-19 21:05:01 +04:00
sharename , tstruct . total_jobs ) ) ;
2003-03-01 03:49:00 +03:00
2002-07-15 14:35:28 +04:00
tdb_store_int32 ( pdb - > tdb , " INFO/total_jobs " , tstruct . total_jobs ) ;
2000-11-21 03:30:15 +03:00
2004-10-19 21:05:01 +04:00
get_queue_status ( sharename , & old_status ) ;
2003-01-31 02:26:49 +03:00
if ( old_status . qcount ! = qcount )
2004-12-01 23:11:31 +03:00
DEBUG ( 10 , ( " print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s \n " ,
2004-10-19 21:05:01 +04:00
old_status . qcount , qcount , sharename ) ) ;
2000-11-21 03:30:15 +03:00
/* store the new queue status structure */
2004-10-19 21:05:01 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " STATUS/%s " , sharename ) ;
2001-02-22 20:39:36 +03:00
key . dptr = keystr ;
2000-04-16 10:20:02 +04:00
key . dsize = strlen ( keystr ) ;
2000-11-21 03:30:15 +03:00
status . qcount = qcount ;
data . dptr = ( void * ) & status ;
data . dsize = sizeof ( status ) ;
2002-07-15 14:35:28 +04:00
tdb_store ( pdb - > tdb , key , data , TDB_REPLACE ) ;
2000-04-16 10:20:02 +04:00
2000-10-11 01:52:31 +04:00
/*
* Update the cache time again . We want to do this call
* as little as possible . . .
*/
2004-10-19 21:05:01 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " CACHE/%s " , sharename ) ;
2002-07-15 14:35:28 +04:00
tdb_store_int32 ( pdb - > tdb , keystr , ( int32 ) time ( NULL ) ) ;
2001-02-22 20:39:36 +03:00
2004-12-08 06:02:29 +03:00
/* clear the msg pending record for this queue */
snprintf ( keystr , sizeof ( keystr ) , " MSG_PENDING/%s " , sharename ) ;
if ( ! tdb_store_uint32 ( pdb - > tdb , keystr , 0 ) ) {
/* log a message but continue on */
DEBUG ( 0 , ( " print_queue_update: failed to store MSG_PENDING flag for [%s]! \n " ,
sharename ) ) ;
}
release_print_db ( pdb ) ;
return ;
2004-10-19 21:05:01 +04:00
}
/****************************************************************************
Update the internal database from the system print queue for a queue .
obtain a lock on the print queue before proceeding ( needed when mutiple
smbd processes maytry to update the lpq cache concurrently ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-03-08 20:22:39 +03:00
static void print_queue_update_with_lock ( const char * sharename ,
struct printif * current_printif ,
char * lpq_command )
2004-10-19 21:05:01 +04:00
{
2005-03-08 20:22:39 +03:00
fstring keystr ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb ;
2004-12-01 23:11:31 +03:00
DEBUG ( 5 , ( " print_queue_update_with_lock: printer share = %s \n " , sharename ) ) ;
2004-10-19 21:05:01 +04:00
pdb = get_print_db_byname ( sharename ) ;
if ( ! pdb )
return ;
2005-03-08 20:22:39 +03:00
if ( ! print_cache_expired ( sharename , False ) ) {
DEBUG ( 5 , ( " print_queue_update_with_lock: print cache for %s is still ok \n " , sharename ) ) ;
release_print_db ( pdb ) ;
return ;
}
2004-10-19 21:05:01 +04:00
/*
* Check to see if someone else is doing this update .
* This is essentially a mutex on the update .
*/
if ( get_updating_pid ( sharename ) ! = - 1 ) {
release_print_db ( pdb ) ;
return ;
}
/* Lock the queue for the database update */
slprintf ( keystr , sizeof ( keystr ) - 1 , " LOCK/%s " , sharename ) ;
/* Only wait 10 seconds for this. */
if ( tdb_lock_bystring ( pdb - > tdb , keystr , 10 ) = = - 1 ) {
2004-12-01 23:11:31 +03:00
DEBUG ( 0 , ( " print_queue_update_with_lock: Failed to lock printer %s database \n " , sharename ) ) ;
2004-10-19 21:05:01 +04:00
release_print_db ( pdb ) ;
return ;
}
/*
* Ensure that no one else got in here .
* If the updating pid is still - 1 then we are
* the winner .
*/
if ( get_updating_pid ( sharename ) ! = - 1 ) {
/*
* Someone else is doing the update , exit .
*/
tdb_unlock_bystring ( pdb - > tdb , keystr ) ;
release_print_db ( pdb ) ;
return ;
}
/*
* We ' re going to do the update ourselves .
*/
/* Tell others we're doing the update. */
2004-12-01 23:11:31 +03:00
set_updating_pid ( sharename , True ) ;
2004-10-19 21:05:01 +04:00
/*
* Allow others to enter and notice we ' re doing
* the update .
*/
tdb_unlock_bystring ( pdb - > tdb , keystr ) ;
/* do the main work now */
print_queue_update_internal ( sharename , current_printif , lpq_command ) ;
2001-02-22 20:39:36 +03:00
/* Delete our pid from the db. */
2004-12-01 23:11:31 +03:00
set_updating_pid ( sharename , False ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-04-16 10:20:02 +04:00
}
2004-05-27 19:38:54 +04:00
/****************************************************************************
this is the receive function of the background lpq updater
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-12-08 06:02:29 +03:00
static void print_queue_receive ( int msg_type , pid_t src , void * buf , size_t msglen )
2004-05-27 19:38:54 +04:00
{
2004-12-08 06:02:29 +03:00
fstring sharename ;
pstring lpqcommand ;
2005-07-15 21:38:55 +04:00
int printing_type ;
2004-12-08 06:02:29 +03:00
size_t len ;
len = tdb_unpack ( buf , msglen , " fdP " ,
sharename ,
2005-07-15 21:38:55 +04:00
& printing_type ,
2004-12-08 06:02:29 +03:00
lpqcommand ) ;
2004-10-19 21:05:01 +04:00
2004-12-08 06:02:29 +03:00
if ( len = = - 1 ) {
DEBUG ( 0 , ( " print_queue_receive: Got invalid print queue update message \n " ) ) ;
2004-10-19 21:05:01 +04:00
return ;
}
2005-07-15 21:38:55 +04:00
print_queue_update_with_lock ( sharename ,
get_printer_fns_from_type ( printing_type ) ,
lpqcommand ) ;
2004-12-08 06:02:29 +03:00
return ;
2004-05-27 19:38:54 +04:00
}
static pid_t background_lpq_updater_pid = - 1 ;
/****************************************************************************
main thread of the background lpq updater
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void start_background_queue ( void )
{
DEBUG ( 3 , ( " start_background_queue: Starting background LPQ thread \n " ) ) ;
background_lpq_updater_pid = sys_fork ( ) ;
if ( background_lpq_updater_pid = = - 1 ) {
DEBUG ( 5 , ( " start_background_queue: background LPQ thread failed to start. %s \n " , strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
if ( background_lpq_updater_pid = = 0 ) {
/* Child. */
DEBUG ( 5 , ( " start_background_queue: background LPQ thread started \n " ) ) ;
claim_connection ( NULL , " smbd lpq backend " , 0 , False ,
2004-08-18 17:55:58 +04:00
FLAG_MSG_GENERAL | FLAG_MSG_SMBD | FLAG_MSG_PRINT_GENERAL ) ;
2004-05-27 19:38:54 +04:00
if ( ! locking_init ( 0 ) ) {
exit ( 1 ) ;
}
message_register ( MSG_PRINTER_UPDATE , print_queue_receive ) ;
DEBUG ( 5 , ( " start_background_queue: background LPQ thread waiting for messages \n " ) ) ;
while ( 1 ) {
pause ( ) ;
/* check for some essential signals first */
if ( got_sig_term ) {
exit_server ( " Caught TERM signal " ) ;
}
if ( reload_after_sighup ) {
change_to_root_user ( ) ;
DEBUG ( 1 , ( " Reloading services after SIGHUP \n " ) ) ;
reload_services ( False ) ;
reload_after_sighup = 0 ;
}
/* now check for messages */
DEBUG ( 10 , ( " start_background_queue: background LPQ thread got a message \n " ) ) ;
message_dispatch ( ) ;
2004-10-19 21:05:01 +04:00
/* process any pending print change notify messages */
print_notify_send_messages ( 0 ) ;
2004-05-27 19:38:54 +04:00
}
}
}
/****************************************************************************
update the internal database from the system print queue for a queue
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-03-08 20:22:39 +03:00
static void print_queue_update ( int snum , BOOL force )
2004-05-27 19:38:54 +04:00
{
2004-12-08 06:02:29 +03:00
fstring key ;
fstring sharename ;
pstring lpqcommand ;
char * buffer = NULL ;
size_t len = 0 ;
size_t newlen ;
struct tdb_print_db * pdb ;
2005-03-22 17:54:12 +03:00
int type ;
2005-03-08 20:22:39 +03:00
struct printif * current_printif ;
2004-10-19 21:05:01 +04:00
2005-03-08 20:22:39 +03:00
fstrcpy ( sharename , lp_const_servicename ( snum ) ) ;
2005-07-15 21:38:55 +04:00
/* don't strip out characters like '$' from the printername */
2005-03-08 20:22:39 +03:00
pstrcpy ( lpqcommand , lp_lpqcommand ( snum ) ) ;
2005-07-21 21:40:20 +04:00
string_sub2 ( lpqcommand , " %p " , PRINTERNAME ( snum ) , sizeof ( lpqcommand ) , False , False ) ;
2005-03-08 20:22:39 +03:00
standard_sub_snum ( snum , lpqcommand , sizeof ( lpqcommand ) ) ;
2004-05-27 19:38:54 +04:00
/*
2004-10-19 21:05:01 +04:00
* Make sure that the background queue process exists .
2004-05-27 19:38:54 +04:00
* Otherwise just do the update ourselves
*/
2004-12-08 06:02:29 +03:00
2005-03-08 20:22:39 +03:00
if ( force | | background_lpq_updater_pid = = - 1 ) {
DEBUG ( 4 , ( " print_queue_update: updating queue [%s] myself \n " , sharename ) ) ;
current_printif = get_printer_fns ( snum ) ;
print_queue_update_with_lock ( sharename , current_printif , lpqcommand ) ;
2004-12-08 06:02:29 +03:00
return ;
}
2005-03-08 20:22:39 +03:00
type = lp_printing ( snum ) ;
2004-12-08 06:02:29 +03:00
/* get the length */
len = tdb_pack ( buffer , len , " fdP " ,
2005-03-08 20:22:39 +03:00
sharename ,
type ,
lpqcommand ) ;
2004-10-19 21:05:01 +04:00
2004-12-08 06:02:29 +03:00
buffer = SMB_XMALLOC_ARRAY ( char , len ) ;
2004-12-01 23:11:31 +03:00
2004-12-08 06:02:29 +03:00
/* now pack the buffer */
newlen = tdb_pack ( buffer , len , " fdP " ,
2005-03-08 20:22:39 +03:00
sharename ,
type ,
lpqcommand ) ;
2004-12-08 06:02:29 +03:00
SMB_ASSERT ( newlen = = len ) ;
DEBUG ( 10 , ( " print_queue_update: Sending message -> printer = %s, "
2005-03-08 20:22:39 +03:00
" type = %d, lpq command = [%s] \n " , sharename , type , lpqcommand ) ) ;
2004-12-08 06:02:29 +03:00
/* here we set a msg pending record for other smbd processes
to throttle the number of duplicate print_queue_update msgs
sent . */
pdb = get_print_db_byname ( sharename ) ;
snprintf ( key , sizeof ( key ) , " MSG_PENDING/%s " , sharename ) ;
if ( ! tdb_store_uint32 ( pdb - > tdb , key , time ( NULL ) ) ) {
/* log a message but continue on */
DEBUG ( 0 , ( " print_queue_update: failed to store MSG_PENDING flag for [%s]! \n " ,
sharename ) ) ;
}
release_print_db ( pdb ) ;
2004-12-01 23:11:31 +03:00
2004-12-08 06:02:29 +03:00
/* finally send the message */
2004-10-19 21:05:01 +04:00
2004-12-08 06:02:29 +03:00
become_root ( ) ;
message_send_pid ( background_lpq_updater_pid ,
MSG_PRINTER_UPDATE , buffer , len , False ) ;
unbecome_root ( ) ;
SAFE_FREE ( buffer ) ;
return ;
2004-05-27 19:38:54 +04:00
}
2002-11-07 05:15:35 +03:00
/****************************************************************************
Create / Update an entry in the print tdb that will allow us to send notify
updates only to interested smbd ' s .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL print_notify_register_pid ( int snum )
{
TDB_DATA data ;
2002-11-11 01:24:00 +03:00
struct tdb_print_db * pdb = NULL ;
TDB_CONTEXT * tdb = NULL ;
const char * printername ;
2002-11-07 05:15:35 +03:00
uint32 mypid = ( uint32 ) sys_getpid ( ) ;
BOOL ret = False ;
size_t i ;
2002-11-26 03:46:31 +03:00
/* if (snum == -1), then the change notify request was
on a print server handle and we need to register on
all print queus */
if ( snum = = - 1 )
{
int num_services = lp_numservices ( ) ;
int idx ;
for ( idx = 0 ; idx < num_services ; idx + + ) {
if ( lp_snum_ok ( idx ) & & lp_print_ok ( idx ) )
print_notify_register_pid ( idx ) ;
}
return True ;
}
else /* register for a specific printer */
{
2002-11-11 01:24:00 +03:00
printername = lp_const_servicename ( snum ) ;
pdb = get_print_db_byname ( printername ) ;
if ( ! pdb )
return False ;
tdb = pdb - > tdb ;
}
2002-11-07 05:15:35 +03:00
2002-11-11 01:24:00 +03:00
if ( tdb_lock_bystring ( tdb , NOTIFY_PID_LIST_KEY , 10 ) = = - 1 ) {
DEBUG ( 0 , ( " print_notify_register_pid: Failed to lock printer %s \n " ,
printername ) ) ;
if ( pdb )
release_print_db ( pdb ) ;
2002-11-07 05:15:35 +03:00
return False ;
}
2002-11-11 01:24:00 +03:00
data = get_printer_notify_pid_list ( tdb , printername , True ) ;
2002-11-07 05:15:35 +03:00
/* Add ourselves and increase the refcount. */
for ( i = 0 ; i < data . dsize ; i + = 8 ) {
if ( IVAL ( data . dptr , i ) = = mypid ) {
uint32 new_refcount = IVAL ( data . dptr , i + 4 ) + 1 ;
SIVAL ( data . dptr , i + 4 , new_refcount ) ;
break ;
}
}
if ( i = = data . dsize ) {
/* We weren't in the list. Realloc. */
2004-12-07 21:25:53 +03:00
data . dptr = SMB_REALLOC ( data . dptr , data . dsize + 8 ) ;
2002-11-07 05:15:35 +03:00
if ( ! data . dptr ) {
2002-11-11 01:24:00 +03:00
DEBUG ( 0 , ( " print_notify_register_pid: Relloc fail for printer %s \n " ,
printername ) ) ;
2002-11-07 05:15:35 +03:00
goto done ;
}
data . dsize + = 8 ;
SIVAL ( data . dptr , data . dsize - 8 , mypid ) ;
SIVAL ( data . dptr , data . dsize - 4 , 1 ) ; /* Refcount. */
}
/* Store back the record. */
2003-07-11 00:37:01 +04:00
if ( tdb_store_bystring ( tdb , NOTIFY_PID_LIST_KEY , data , TDB_REPLACE ) = = - 1 ) {
2002-11-11 01:24:00 +03:00
DEBUG ( 0 , ( " print_notify_register_pid: Failed to update pid \
list for printer % s \ n " , printername));
2002-11-07 05:15:35 +03:00
goto done ;
}
ret = True ;
done :
2002-11-11 01:24:00 +03:00
tdb_unlock_bystring ( tdb , NOTIFY_PID_LIST_KEY ) ;
if ( pdb )
release_print_db ( pdb ) ;
2002-11-07 05:15:35 +03:00
SAFE_FREE ( data . dptr ) ;
return ret ;
}
/****************************************************************************
Update an entry in the print tdb that will allow us to send notify
updates only to interested smbd ' s .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL print_notify_deregister_pid ( int snum )
{
TDB_DATA data ;
2002-11-11 01:24:00 +03:00
struct tdb_print_db * pdb = NULL ;
TDB_CONTEXT * tdb = NULL ;
const char * printername ;
2002-11-07 05:15:35 +03:00
uint32 mypid = ( uint32 ) sys_getpid ( ) ;
size_t i ;
BOOL ret = False ;
2002-11-26 03:46:31 +03:00
/* if ( snum == -1 ), we are deregister a print server handle
which means to deregister on all print queues */
if ( snum = = - 1 )
{
int num_services = lp_numservices ( ) ;
int idx ;
for ( idx = 0 ; idx < num_services ; idx + + ) {
if ( lp_snum_ok ( idx ) & & lp_print_ok ( idx ) )
print_notify_deregister_pid ( idx ) ;
}
return True ;
}
else /* deregister a specific printer */
{
2002-11-11 01:24:00 +03:00
printername = lp_const_servicename ( snum ) ;
pdb = get_print_db_byname ( printername ) ;
if ( ! pdb )
return False ;
tdb = pdb - > tdb ;
}
2002-11-07 05:15:35 +03:00
2002-11-11 01:24:00 +03:00
if ( tdb_lock_bystring ( tdb , NOTIFY_PID_LIST_KEY , 10 ) = = - 1 ) {
DEBUG ( 0 , ( " print_notify_register_pid: Failed to lock \
printer % s database \ n " , printername));
if ( pdb )
release_print_db ( pdb ) ;
2002-11-07 05:15:35 +03:00
return False ;
}
2002-11-11 01:24:00 +03:00
data = get_printer_notify_pid_list ( tdb , printername , True ) ;
2002-11-07 05:15:35 +03:00
/* Reduce refcount. Remove ourselves if zero. */
for ( i = 0 ; i < data . dsize ; ) {
if ( IVAL ( data . dptr , i ) = = mypid ) {
uint32 refcount = IVAL ( data . dptr , i + 4 ) ;
refcount - - ;
if ( refcount = = 0 ) {
if ( data . dsize - i > 8 )
memmove ( & data . dptr [ i ] , & data . dptr [ i + 8 ] , data . dsize - i - 8 ) ;
data . dsize - = 8 ;
continue ;
}
SIVAL ( data . dptr , i + 4 , refcount ) ;
}
i + = 8 ;
}
if ( data . dsize = = 0 )
SAFE_FREE ( data . dptr ) ;
/* Store back the record. */
2003-07-11 00:37:01 +04:00
if ( tdb_store_bystring ( tdb , NOTIFY_PID_LIST_KEY , data , TDB_REPLACE ) = = - 1 ) {
2002-11-11 01:24:00 +03:00
DEBUG ( 0 , ( " print_notify_register_pid: Failed to update pid \
list for printer % s \ n " , printername));
2002-11-07 05:15:35 +03:00
goto done ;
}
ret = True ;
done :
2002-11-11 01:24:00 +03:00
tdb_unlock_bystring ( tdb , NOTIFY_PID_LIST_KEY ) ;
if ( pdb )
release_print_db ( pdb ) ;
2002-11-07 05:15:35 +03:00
SAFE_FREE ( data . dptr ) ;
return ret ;
}
2001-10-17 03:16:00 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Check if a jobid is valid . It is valid if it exists in the database .
2001-10-17 03:16:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-17 03:52:14 +04:00
2004-10-19 21:05:01 +04:00
BOOL print_job_exists ( const char * sharename , uint32 jobid )
2001-10-17 03:16:00 +04:00
{
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2002-09-25 19:19:00 +04:00
BOOL ret ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return False ;
2002-09-25 19:19:00 +04:00
ret = tdb_exists ( pdb - > tdb , print_key ( jobid ) ) ;
release_print_db ( pdb ) ;
return ret ;
2001-10-17 03:16:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Give the fd used for a jobid .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2004-10-19 21:05:01 +04:00
int print_job_fd ( const char * sharename , uint32 jobid )
2000-04-16 10:20:02 +04:00
{
2004-10-19 21:05:01 +04:00
struct printjob * pjob = print_job_find ( sharename , jobid ) ;
2002-07-15 14:35:28 +04:00
if ( ! pjob )
return - 1 ;
2000-04-16 10:20:02 +04:00
/* don't allow another process to get this info - it is meaningless */
2004-09-03 01:52:35 +04:00
if ( pjob - > pid ! = sys_getpid ( ) )
2002-07-15 14:35:28 +04:00
return - 1 ;
2000-04-16 10:20:02 +04:00
return pjob - > fd ;
1996-05-04 11:50:46 +04:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Give the filename used for a jobid .
Only valid for the process doing the spooling and when the job
has not been spooled .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2004-10-19 21:05:01 +04:00
char * print_job_fname ( const char * sharename , uint32 jobid )
2000-04-16 10:20:02 +04:00
{
2004-10-19 21:05:01 +04:00
struct printjob * pjob = print_job_find ( sharename , jobid ) ;
2004-09-03 01:52:35 +04:00
if ( ! pjob | | pjob - > spooled | | pjob - > pid ! = sys_getpid ( ) )
2002-07-15 14:35:28 +04:00
return NULL ;
2000-04-16 10:20:02 +04:00
return pjob - > filename ;
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
/****************************************************************************
Give the filename used for a jobid .
Only valid for the process doing the spooling and when the job
has not been spooled .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
NT_DEVICEMODE * print_job_devmode ( const char * sharename , uint32 jobid )
2002-09-25 19:19:00 +04:00
{
2004-10-19 21:05:01 +04:00
struct printjob * pjob = print_job_find ( sharename , jobid ) ;
2002-09-25 19:19:00 +04:00
if ( ! pjob )
return NULL ;
return pjob - > nt_devmode ;
}
1997-08-31 06:18:59 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Set the place in the queue for a job .
1997-08-31 06:18:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_set_place ( int snum , uint32 jobid , int place )
1997-08-31 06:18:59 +04:00
{
2000-04-16 10:20:02 +04:00
DEBUG ( 2 , ( " print_job_set_place not implemented yet \n " ) ) ;
return False ;
1997-08-31 06:18:59 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Set the name of a job . Only possible for owner .
1997-08-31 06:18:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_set_name ( int snum , uint32 jobid , char * name )
1997-08-31 06:18:59 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob ;
pjob = print_job_find ( sharename , jobid ) ;
2004-09-03 01:52:35 +04:00
if ( ! pjob | | pjob - > pid ! = sys_getpid ( ) )
2002-07-15 14:35:28 +04:00
return False ;
2000-04-16 10:20:02 +04:00
fstrcpy ( pjob - > jobname , name ) ;
2004-10-19 21:05:01 +04:00
return pjob_store ( sharename , jobid , pjob ) ;
1997-08-31 06:18:59 +04:00
}
1998-07-16 04:06:29 +04:00
2003-03-22 01:00:21 +03:00
/***************************************************************************
Remove a jobid from the ' jobs changed ' list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
static BOOL remove_from_jobs_changed ( const char * sharename , uint32 jobid )
2003-03-22 01:00:21 +03:00
{
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2003-03-22 01:00:21 +03:00
TDB_DATA data , key ;
size_t job_count , i ;
BOOL ret = False ;
BOOL gotlock = False ;
ZERO_STRUCT ( data ) ;
2005-03-15 23:27:17 +03:00
key = string_tdb_data ( " INFO/jobs_changed " ) ;
if ( tdb_chainlock_with_timeout ( pdb - > tdb , key , 5 ) = = - 1 )
2003-03-22 01:00:21 +03:00
goto out ;
gotlock = True ;
data = tdb_fetch ( pdb - > tdb , key ) ;
if ( data . dptr = = NULL | | data . dsize = = 0 | | ( data . dsize % 4 ! = 0 ) )
goto out ;
job_count = data . dsize / 4 ;
for ( i = 0 ; i < job_count ; i + + ) {
uint32 ch_jobid ;
2004-01-14 22:12:06 +03:00
ch_jobid = IVAL ( data . dptr , i * 4 ) ;
2003-03-22 01:00:21 +03:00
if ( ch_jobid = = jobid ) {
if ( i < job_count - 1 )
memmove ( data . dptr + ( i * 4 ) , data . dptr + ( i * 4 ) + 4 , ( job_count - i - 1 ) * 4 ) ;
data . dsize - = 4 ;
if ( tdb_store ( pdb - > tdb , key , data , TDB_REPLACE ) = = - 1 )
goto out ;
break ;
}
}
ret = True ;
out :
if ( gotlock )
tdb_chainunlock ( pdb - > tdb , key ) ;
SAFE_FREE ( data . dptr ) ;
release_print_db ( pdb ) ;
2003-04-02 06:31:51 +04:00
if ( ret )
DEBUG ( 10 , ( " remove_from_jobs_changed: removed jobid %u \n " , ( unsigned int ) jobid ) ) ;
else
DEBUG ( 10 , ( " remove_from_jobs_changed: Failed to remove jobid %u \n " , ( unsigned int ) jobid ) ) ;
2003-03-22 01:00:21 +03:00
return ret ;
}
1998-07-16 04:06:29 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Delete a print job - don ' t update queue .
1998-07-16 04:06:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
static BOOL print_job_delete1 ( int snum , uint32 jobid )
1998-07-16 04:06:29 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob = print_job_find ( sharename , jobid ) ;
2002-08-17 21:00:51 +04:00
int result = 0 ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
1998-07-16 04:06:29 +04:00
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2002-07-15 14:35:28 +04:00
if ( ! pjob )
return False ;
1998-07-16 04:06:29 +04:00
2001-02-23 06:59:37 +03:00
/*
* If already deleting just return .
*/
if ( pjob - > status = = LPQ_DELETING )
return True ;
2001-01-22 19:59:24 +03:00
/* Hrm - we need to be able to cope with deleting a job before it
has reached the spooler . */
if ( pjob - > sysjob = = - 1 ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " attempt to delete job %u not seen by lpr \n " , ( unsigned int ) jobid ) ) ;
2001-01-22 19:59:24 +03:00
}
2001-02-23 06:59:37 +03:00
/* Set the tdb entry to be deleting. */
pjob - > status = LPQ_DELETING ;
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , pjob ) ;
2001-02-23 06:59:37 +03:00
2001-03-16 08:55:30 +03:00
if ( pjob - > spooled & & pjob - > sysjob ! = - 1 )
2001-04-18 09:12:46 +04:00
result = ( * ( current_printif - > job_delete ) ) ( snum , pjob ) ;
2001-03-16 08:55:30 +03:00
2003-07-01 09:45:16 +04:00
/* Delete the tdb entry if the delete succeeded or the job hasn't
2001-03-16 08:55:30 +03:00
been spooled . */
2003-04-02 06:31:51 +04:00
if ( result = = 0 ) {
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2003-04-02 06:31:51 +04:00
int njobs = 1 ;
if ( ! pdb )
return False ;
2004-10-19 21:05:01 +04:00
pjob_delete ( sharename , jobid ) ;
2003-04-02 06:31:51 +04:00
/* Ensure we keep a rough count of the number of total jobs... */
tdb_change_int32_atomic ( pdb - > tdb , " INFO/total_jobs " , & njobs , - 1 ) ;
release_print_db ( pdb ) ;
}
2001-01-24 19:46:08 +03:00
return ( result = = 0 ) ;
1998-07-16 04:06:29 +04:00
}
1998-08-14 21:38:29 +04:00
2000-07-17 06:42:25 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Return true if the current user owns the print job .
2000-07-17 06:42:25 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
static BOOL is_owner ( struct current_user * user , int snum , uint32 jobid )
2000-07-10 09:08:21 +04:00
{
2004-10-19 21:05:01 +04:00
struct printjob * pjob = print_job_find ( lp_const_servicename ( snum ) , jobid ) ;
2000-09-13 08:42:06 +04:00
user_struct * vuser ;
2000-07-10 09:08:21 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pjob | | ! user )
return False ;
2000-07-10 09:08:21 +04:00
2000-09-13 08:42:06 +04:00
if ( ( vuser = get_valid_user_struct ( user - > vuid ) ) ! = NULL ) {
2001-07-04 11:15:53 +04:00
return strequal ( pjob - > user , vuser - > user . smb_name ) ;
2000-09-13 08:42:06 +04:00
} else {
2001-07-04 11:15:53 +04:00
return strequal ( pjob - > user , uidtoname ( user - > uid ) ) ;
2000-09-13 08:42:06 +04:00
}
2000-07-10 09:08:21 +04:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Delete a print job .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_delete ( struct current_user * user , int snum , uint32 jobid , WERROR * errcode )
1998-08-14 21:38:29 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
2002-09-25 19:19:00 +04:00
BOOL owner , deleted ;
char * fname ;
2002-03-21 00:55:57 +03:00
2002-09-25 19:19:00 +04:00
* errcode = WERR_OK ;
2002-08-17 21:00:51 +04:00
owner = is_owner ( user , snum , jobid ) ;
2000-07-17 06:42:25 +04:00
2000-07-10 09:08:21 +04:00
/* Check access against security descriptor or whether the user
owns their job . */
2000-07-17 06:42:25 +04:00
if ( ! owner & &
2001-01-19 19:57:39 +03:00
! print_access_check ( user , snum , JOB_ACCESS_ADMINISTER ) ) {
2000-06-16 12:21:51 +04:00
DEBUG ( 3 , ( " delete denied by security descriptor \n " ) ) ;
2001-09-03 14:38:13 +04:00
* errcode = WERR_ACCESS_DENIED ;
2002-11-10 06:00:43 +03:00
/* BEGIN_ADMIN_LOG */
2003-01-03 11:28:12 +03:00
sys_adminlog ( LOG_ERR ,
" Permission denied-- user not allowed to delete, \
2002-11-10 06:00:43 +03:00
pause , or resume print job . User name : % s . Printer name : % s . " ,
2003-01-03 11:28:12 +03:00
uidtoname ( user - > uid ) , PRINTERNAME ( snum ) ) ;
2002-11-10 06:00:43 +03:00
/* END_ADMIN_LOG */
2000-06-16 12:21:51 +04:00
return False ;
}
2002-09-25 19:19:00 +04:00
/*
* get the spooled filename of the print job
* if this works , then the file has not been spooled
* to the underlying print system . Just delete the
* spool file & return .
*/
2004-10-19 21:05:01 +04:00
if ( ( fname = print_job_fname ( sharename , jobid ) ) ! = NULL )
2002-09-25 19:19:00 +04:00
{
/* remove the spool file */
DEBUG ( 10 , ( " print_job_delete: Removing spool file [%s] \n " , fname ) ) ;
if ( unlink ( fname ) = = - 1 ) {
* errcode = map_werror_from_unix ( errno ) ;
return False ;
}
}
if ( ! print_job_delete1 ( snum , jobid ) ) {
* errcode = WERR_ACCESS_DENIED ;
2002-07-15 14:35:28 +04:00
return False ;
2002-09-25 19:19:00 +04:00
}
1998-08-14 21:38:29 +04:00
2000-04-16 10:20:02 +04:00
/* force update the database and say the delete failed if the
job still exists */
2000-07-17 06:42:25 +04:00
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , True ) ;
2002-09-25 19:19:00 +04:00
2004-10-19 21:05:01 +04:00
deleted = ! print_job_exists ( sharename , jobid ) ;
2002-09-25 19:19:00 +04:00
if ( ! deleted )
* errcode = WERR_ACCESS_DENIED ;
1998-08-14 21:38:29 +04:00
2002-09-25 19:19:00 +04:00
return deleted ;
1998-08-14 21:38:29 +04:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Pause a job .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_pause ( struct current_user * user , int snum , uint32 jobid , WERROR * errcode )
1998-08-14 21:38:29 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob ;
2002-08-17 21:00:51 +04:00
int ret = - 1 ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2000-07-17 06:42:25 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pjob | | ! user )
return False ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pjob - > spooled | | pjob - > sysjob = = - 1 )
return False ;
2000-04-16 12:03:37 +04:00
2002-08-17 21:00:51 +04:00
if ( ! is_owner ( user , snum , jobid ) & &
2001-01-19 19:57:39 +03:00
! print_access_check ( user , snum , JOB_ACCESS_ADMINISTER ) ) {
2000-06-16 12:21:51 +04:00
DEBUG ( 3 , ( " pause denied by security descriptor \n " ) ) ;
2002-11-10 06:00:43 +03:00
/* BEGIN_ADMIN_LOG */
2003-01-03 11:28:12 +03:00
sys_adminlog ( LOG_ERR ,
2002-11-10 06:00:43 +03:00
" Permission denied-- user not allowed to delete, \
pause , or resume print job . User name : % s . Printer name : % s . " ,
uidtoname ( user - > uid ) , PRINTERNAME ( snum ) ) ;
/* END_ADMIN_LOG */
2001-09-04 11:13:01 +04:00
* errcode = WERR_ACCESS_DENIED ;
2000-06-16 12:21:51 +04:00
return False ;
}
2000-04-16 12:03:37 +04:00
/* need to pause the spooled entry */
2001-04-18 09:12:46 +04:00
ret = ( * ( current_printif - > job_pause ) ) ( snum , pjob ) ;
1998-08-14 21:38:29 +04:00
2000-11-08 02:05:53 +03:00
if ( ret ! = 0 ) {
2001-09-04 11:13:01 +04:00
* errcode = WERR_INVALID_PARAM ;
2000-11-08 02:05:53 +03:00
return False ;
}
2000-04-16 10:20:02 +04:00
/* force update the database */
print_cache_flush ( snum ) ;
1998-08-14 21:38:29 +04:00
2000-11-08 02:05:53 +03:00
/* Send a printer notify message */
2004-10-19 21:05:01 +04:00
notify_job_status ( sharename , jobid , JOB_STATUS_PAUSED ) ;
2000-11-08 02:05:53 +03:00
2000-04-16 10:20:02 +04:00
/* how do we tell if this succeeded? */
2000-11-08 02:05:53 +03:00
return True ;
2000-04-16 10:20:02 +04:00
}
1998-08-14 21:38:29 +04:00
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Resume a job .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_resume ( struct current_user * user , int snum , uint32 jobid , WERROR * errcode )
2000-04-16 10:20:02 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob ;
2002-08-17 21:00:51 +04:00
int ret ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2000-07-17 06:42:25 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pjob | | ! user )
return False ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
if ( ! pjob - > spooled | | pjob - > sysjob = = - 1 )
return False ;
2000-04-16 12:03:37 +04:00
2002-08-17 21:00:51 +04:00
if ( ! is_owner ( user , snum , jobid ) & &
2001-01-19 19:57:39 +03:00
! print_access_check ( user , snum , JOB_ACCESS_ADMINISTER ) ) {
2000-06-16 12:21:51 +04:00
DEBUG ( 3 , ( " resume denied by security descriptor \n " ) ) ;
2001-09-04 11:13:01 +04:00
* errcode = WERR_ACCESS_DENIED ;
2002-11-10 06:00:43 +03:00
/* BEGIN_ADMIN_LOG */
2003-01-03 11:28:12 +03:00
sys_adminlog ( LOG_ERR ,
2002-11-10 06:00:43 +03:00
" Permission denied-- user not allowed to delete, \
pause , or resume print job . User name : % s . Printer name : % s . " ,
uidtoname ( user - > uid ) , PRINTERNAME ( snum ) ) ;
/* END_ADMIN_LOG */
2000-06-16 12:21:51 +04:00
return False ;
}
2001-03-16 08:55:30 +03:00
ret = ( * ( current_printif - > job_resume ) ) ( snum , pjob ) ;
2000-04-16 10:20:02 +04:00
2000-11-08 02:05:53 +03:00
if ( ret ! = 0 ) {
2001-09-04 11:13:01 +04:00
* errcode = WERR_INVALID_PARAM ;
2000-11-08 02:05:53 +03:00
return False ;
}
2000-04-16 10:20:02 +04:00
/* force update the database */
print_cache_flush ( snum ) ;
2000-11-08 02:05:53 +03:00
/* Send a printer notify message */
2004-10-19 21:05:01 +04:00
notify_job_status ( sharename , jobid , JOB_STATUS_QUEUED ) ;
2000-11-08 02:05:53 +03:00
return True ;
1998-08-14 21:38:29 +04:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Write to a print file .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2005-05-18 22:02:15 +04:00
ssize_t print_job_write ( int snum , uint32 jobid , const char * buf , SMB_OFF_T pos , size_t size )
1998-08-14 21:38:29 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
2002-03-19 05:35:12 +03:00
int return_code ;
2004-10-19 21:05:01 +04:00
struct printjob * pjob ;
pjob = print_job_find ( sharename , jobid ) ;
2000-04-16 10:20:02 +04:00
2002-03-19 05:35:12 +03:00
if ( ! pjob )
return - 1 ;
/* don't allow another process to get this info - it is meaningless */
2004-09-03 01:52:35 +04:00
if ( pjob - > pid ! = sys_getpid ( ) )
2002-03-19 05:35:12 +03:00
return - 1 ;
2000-04-16 10:20:02 +04:00
2005-05-18 22:02:15 +04:00
return_code = write_data_at_offset ( pjob - > fd , buf , size , pos ) ;
2002-03-19 05:35:12 +03:00
if ( return_code > 0 ) {
pjob - > size + = size ;
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , pjob ) ;
2002-03-19 05:35:12 +03:00
}
return return_code ;
1998-08-14 21:38:29 +04:00
}
2000-04-10 17:00:12 +04:00
2000-10-11 06:26:27 +04:00
/****************************************************************************
2000-11-21 03:30:15 +03:00
Get the queue status - do not update if db is out of date .
2000-10-11 06:26:27 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2004-10-19 21:05:01 +04:00
static int get_queue_status ( const char * sharename , print_status_struct * status )
2000-10-11 06:26:27 +04:00
{
fstring keystr ;
2005-03-12 12:58:35 +03:00
TDB_DATA data ;
2004-10-19 21:05:01 +04:00
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2003-01-31 02:26:49 +03:00
int len ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return 0 ;
2000-10-11 06:26:27 +04:00
2003-01-31 02:26:49 +03:00
if ( status ) {
ZERO_STRUCTP ( status ) ;
2005-03-12 12:58:35 +03:00
fstr_sprintf ( keystr , " STATUS/%s " , sharename ) ;
data = tdb_fetch ( pdb - > tdb , string_tdb_data ( keystr ) ) ;
2003-01-31 02:26:49 +03:00
if ( data . dptr ) {
if ( data . dsize = = sizeof ( print_status_struct ) )
2004-01-14 22:12:06 +03:00
/* this memcpy is ok since the status struct was
not packed before storing it in the tdb */
2003-01-31 02:26:49 +03:00
memcpy ( status , data . dptr , sizeof ( print_status_struct ) ) ;
SAFE_FREE ( data . dptr ) ;
}
2000-10-11 06:26:27 +04:00
}
2003-01-31 02:26:49 +03:00
len = tdb_fetch_int32 ( pdb - > tdb , " INFO/total_jobs " ) ;
release_print_db ( pdb ) ;
return ( len = = - 1 ? 0 : len ) ;
2000-11-21 03:30:15 +03:00
}
/****************************************************************************
Determine the number of jobs in a queue .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-12-05 03:54:33 +03:00
int print_queue_length ( int snum , print_status_struct * pstatus )
2000-11-21 03:30:15 +03:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
2000-11-21 03:30:15 +03:00
print_status_struct status ;
2001-12-05 03:54:33 +03:00
int len ;
2005-06-22 06:51:22 +04:00
ZERO_STRUCT ( status ) ;
2001-12-05 03:54:33 +03:00
2000-11-21 03:30:15 +03:00
/* make sure the database is up to date */
2004-12-08 06:02:29 +03:00
if ( print_cache_expired ( lp_const_servicename ( snum ) , True ) )
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , False ) ;
2001-12-05 03:54:33 +03:00
2000-11-21 03:30:15 +03:00
/* also fetch the queue status */
2001-12-05 05:11:03 +03:00
memset ( & status , 0 , sizeof ( status ) ) ;
2004-10-19 21:05:01 +04:00
len = get_queue_status ( sharename , & status ) ;
2003-01-31 02:26:49 +03:00
2001-12-05 03:54:33 +03:00
if ( pstatus )
* pstatus = status ;
2003-01-31 02:26:49 +03:00
2001-12-05 03:54:33 +03:00
return len ;
2000-10-11 06:26:27 +04:00
}
2000-04-10 17:00:12 +04:00
2003-02-05 02:52:49 +03:00
/***************************************************************************
Allocate a jobid . Hold the lock for as short a time as possible .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-19 21:05:01 +04:00
static BOOL allocate_print_jobid ( struct tdb_print_db * pdb , int snum , const char * sharename , uint32 * pjobid )
2003-02-05 02:52:49 +03:00
{
int i ;
uint32 jobid ;
* pjobid = ( uint32 ) - 1 ;
for ( i = 0 ; i < 3 ; i + + ) {
/* Lock the database - only wait 20 seconds. */
if ( tdb_lock_bystring ( pdb - > tdb , " INFO/nextjob " , 20 ) = = - 1 ) {
2004-10-19 21:05:01 +04:00
DEBUG ( 0 , ( " allocate_print_jobid: failed to lock printing database %s \n " , sharename ) ) ;
2003-02-05 02:52:49 +03:00
return False ;
}
if ( ! tdb_fetch_uint32 ( pdb - > tdb , " INFO/nextjob " , & jobid ) ) {
if ( tdb_error ( pdb - > tdb ) ! = TDB_ERR_NOEXIST ) {
DEBUG ( 0 , ( " allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s \n " ,
2004-10-19 21:05:01 +04:00
sharename ) ) ;
2003-02-05 02:52:49 +03:00
return False ;
}
jobid = 0 ;
}
jobid = NEXT_JOBID ( jobid ) ;
if ( tdb_store_int32 ( pdb - > tdb , " INFO/nextjob " , jobid ) = = - 1 ) {
DEBUG ( 3 , ( " allocate_print_jobid: failed to store INFO/nextjob. \n " ) ) ;
tdb_unlock_bystring ( pdb - > tdb , " INFO/nextjob " ) ;
return False ;
}
/* We've finished with the INFO/nextjob lock. */
tdb_unlock_bystring ( pdb - > tdb , " INFO/nextjob " ) ;
2004-10-19 21:05:01 +04:00
if ( ! print_job_exists ( sharename , jobid ) )
2003-02-05 02:52:49 +03:00
break ;
}
if ( i > 2 ) {
DEBUG ( 0 , ( " allocate_print_jobid: failed to allocate a print job for queue %s \n " ,
2004-10-19 21:05:01 +04:00
sharename ) ) ;
2003-02-08 04:04:43 +03:00
/* Probably full... */
errno = ENOSPC ;
2003-02-05 02:52:49 +03:00
return False ;
}
/* Store a dummy placeholder. */
{
TDB_DATA dum ;
dum . dptr = NULL ;
dum . dsize = 0 ;
if ( tdb_store ( pdb - > tdb , print_key ( jobid ) , dum , TDB_INSERT ) = = - 1 ) {
DEBUG ( 3 , ( " allocate_print_jobid: jobid (%d) failed to store placeholder. \n " ,
jobid ) ) ;
return False ;
}
}
* pjobid = jobid ;
return True ;
}
2003-03-22 01:00:21 +03:00
/***************************************************************************
Append a jobid to the ' jobs changed ' list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL add_to_jobs_changed ( struct tdb_print_db * pdb , uint32 jobid )
{
2005-03-12 12:58:35 +03:00
TDB_DATA data ;
2004-05-07 19:21:27 +04:00
uint32 store_jobid ;
2003-03-22 01:00:21 +03:00
2004-05-07 19:21:27 +04:00
SIVAL ( & store_jobid , 0 , jobid ) ;
data . dptr = ( char * ) & store_jobid ;
2003-03-22 01:00:21 +03:00
data . dsize = 4 ;
2003-04-02 06:31:51 +04:00
DEBUG ( 10 , ( " add_to_jobs_changed: Added jobid %u \n " , ( unsigned int ) jobid ) ) ;
2005-03-12 12:58:35 +03:00
return ( tdb_append ( pdb - > tdb , string_tdb_data ( " INFO/jobs_changed " ) ,
data ) = = 0 ) ;
2003-03-22 01:00:21 +03:00
}
2000-04-16 10:20:02 +04:00
/***************************************************************************
2002-07-15 14:35:28 +04:00
Start spooling a job - return the jobid .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
uint32 print_job_start ( struct current_user * user , int snum , char * jobname , NT_DEVICEMODE * nt_devmode )
2000-04-10 17:00:12 +04:00
{
2002-07-15 14:35:28 +04:00
uint32 jobid ;
2000-04-16 10:20:02 +04:00
char * path ;
struct printjob pjob ;
2000-09-13 08:42:06 +04:00
user_struct * vuser ;
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct tdb_print_db * pdb = get_print_db_byname ( sharename ) ;
2003-02-05 02:52:49 +03:00
int njobs ;
2000-04-10 17:00:12 +04:00
2000-08-24 03:05:49 +04:00
errno = 0 ;
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return ( uint32 ) - 1 ;
2000-09-01 22:49:26 +04:00
if ( ! print_access_check ( user , snum , PRINTER_ACCESS_USE ) ) {
2000-09-13 06:24:35 +04:00
DEBUG ( 3 , ( " print_job_start: job start denied by security descriptor \n " ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-07-15 14:35:28 +04:00
return ( uint32 ) - 1 ;
2000-09-13 06:24:35 +04:00
}
if ( ! print_time_access_check ( snum ) ) {
DEBUG ( 3 , ( " print_job_start: job start denied by time check \n " ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2002-07-15 14:35:28 +04:00
return ( uint32 ) - 1 ;
2000-06-16 12:21:51 +04:00
}
2000-04-16 10:20:02 +04:00
path = lp_pathname ( snum ) ;
2000-04-10 17:00:12 +04:00
/* see if we have sufficient disk space */
2000-04-16 10:20:02 +04:00
if ( lp_minprintspace ( snum ) ) {
2000-04-19 12:44:56 +04:00
SMB_BIG_UINT dspace , dsize ;
if ( sys_fsusage ( path , & dspace , & dsize ) = = 0 & &
dspace < 2 * ( SMB_BIG_UINT ) lp_minprintspace ( snum ) ) {
2001-06-28 23:23:43 +04:00
DEBUG ( 3 , ( " print_job_start: disk space check failed. \n " ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-04-10 17:00:12 +04:00
errno = ENOSPC ;
2002-07-15 14:35:28 +04:00
return ( uint32 ) - 1 ;
2000-04-10 17:00:12 +04:00
}
}
2000-05-10 15:49:06 +04:00
/* for autoloaded printers, check that the printcap entry still exists */
2005-01-05 19:20:35 +03:00
if ( lp_autoloaded ( snum ) & & ! pcap_printername_ok ( lp_const_servicename ( snum ) ) ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " print_job_start: printer name %s check failed. \n " , lp_const_servicename ( snum ) ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-05-10 15:49:06 +04:00
errno = ENOENT ;
2002-07-15 14:35:28 +04:00
return ( uint32 ) - 1 ;
2000-05-10 15:49:06 +04:00
}
2001-01-23 23:25:25 +03:00
/* Insure the maximum queue size is not violated */
2002-10-05 02:53:18 +04:00
if ( ( njobs = print_queue_length ( snum , NULL ) ) > lp_maxprintjobs ( snum ) ) {
2003-02-08 04:04:43 +03:00
DEBUG ( 3 , ( " print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d). \n " ,
2004-10-19 21:05:01 +04:00
sharename , njobs , lp_maxprintjobs ( snum ) ) ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-10-11 06:26:27 +04:00
errno = ENOSPC ;
2002-07-15 14:35:28 +04:00
return ( uint32 ) - 1 ;
2000-10-11 06:26:27 +04:00
}
2003-02-08 04:04:43 +03:00
DEBUG ( 10 , ( " print_job_start: Queue %s number of jobs (%d), max printjobs = %d \n " ,
2004-10-19 21:05:01 +04:00
sharename , njobs , lp_maxprintjobs ( snum ) ) ) ;
2003-02-08 04:04:43 +03:00
2004-10-19 21:05:01 +04:00
if ( ! allocate_print_jobid ( pdb , snum , sharename , & jobid ) )
2000-04-16 10:20:02 +04:00
goto fail ;
2002-09-25 19:19:00 +04:00
/* create the database entry */
ZERO_STRUCT ( pjob ) ;
2004-09-03 01:52:35 +04:00
pjob . pid = sys_getpid ( ) ;
2002-09-25 19:19:00 +04:00
pjob . sysjob = - 1 ;
pjob . fd = - 1 ;
pjob . starttime = time ( NULL ) ;
pjob . status = LPQ_SPOOLING ;
pjob . size = 0 ;
pjob . spooled = False ;
pjob . smbjob = True ;
pjob . nt_devmode = nt_devmode ;
fstrcpy ( pjob . jobname , jobname ) ;
if ( ( vuser = get_valid_user_struct ( user - > vuid ) ) ! = NULL ) {
fstrcpy ( pjob . user , vuser - > user . smb_name ) ;
} else {
fstrcpy ( pjob . user , uidtoname ( user - > uid ) ) ;
}
fstrcpy ( pjob . queuename , lp_const_servicename ( snum ) ) ;
2001-04-18 09:12:46 +04:00
/* we have a job entry - now create the spool file */
2002-07-15 14:35:28 +04:00
slprintf ( pjob . filename , sizeof ( pjob . filename ) - 1 , " %s/%s%.8u.XXXXXX " ,
path , PRINT_SPOOL_PREFIX , ( unsigned int ) jobid ) ;
2001-04-18 09:12:46 +04:00
pjob . fd = smb_mkstemp ( pjob . filename ) ;
2001-03-27 02:15:40 +04:00
if ( pjob . fd = = - 1 ) {
if ( errno = = EACCES ) {
/* Common setup error, force a report. */
DEBUG ( 0 , ( " print_job_start: insufficient permissions \
to open spool file % s . \ n " , pjob.filename));
} else {
/* Normal case, report at level 3 and above. */
DEBUG ( 3 , ( " print_job_start: can't open spool file %s, \n " , pjob . filename ) ) ;
DEBUGADD ( 3 , ( " errno = %d (%s). \n " , errno , strerror ( errno ) ) ) ;
}
goto fail ;
}
2000-04-16 10:20:02 +04:00
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , & pjob ) ;
2000-04-16 10:20:02 +04:00
2003-03-22 01:00:21 +03:00
/* Update the 'jobs changed' entry used by print_queue_status. */
add_to_jobs_changed ( pdb , jobid ) ;
2003-03-01 03:49:00 +03:00
/* Ensure we keep a rough count of the number of total jobs... */
tdb_change_int32_atomic ( pdb - > tdb , " INFO/total_jobs " , & njobs , 1 ) ;
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-09-01 22:49:26 +04:00
2000-04-16 10:20:02 +04:00
return jobid ;
fail :
2002-07-15 14:35:28 +04:00
if ( jobid ! = - 1 )
2004-10-19 21:05:01 +04:00
pjob_delete ( sharename , jobid ) ;
2000-04-16 10:20:02 +04:00
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2001-06-28 23:23:43 +04:00
DEBUG ( 3 , ( " print_job_start: returning fail. Error = %s \n " , strerror ( errno ) ) ) ;
2003-02-05 02:52:49 +03:00
return ( uint32 ) - 1 ;
2000-04-16 10:20:02 +04:00
}
2002-03-19 05:35:12 +03:00
/****************************************************************************
Update the number of pages spooled to jobid
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 21:00:51 +04:00
void print_job_endpage ( int snum , uint32 jobid )
2002-03-19 05:35:12 +03:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob ;
pjob = print_job_find ( sharename , jobid ) ;
2002-03-19 05:35:12 +03:00
if ( ! pjob )
return ;
/* don't allow another process to get this info - it is meaningless */
2004-09-03 01:52:35 +04:00
if ( pjob - > pid ! = sys_getpid ( ) )
2002-03-19 05:35:12 +03:00
return ;
pjob - > page_count + + ;
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , pjob ) ;
2002-03-19 05:35:12 +03:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2000-08-01 04:41:19 +04:00
Print a file - called on closing the file . This spools the job .
2001-01-30 00:34:08 +03:00
If normal close is false then we ' re tearing down the jobs - treat as an
error .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-08-01 04:41:19 +04:00
2002-08-17 21:00:51 +04:00
BOOL print_job_end ( int snum , uint32 jobid , BOOL normal_close )
2000-04-16 10:20:02 +04:00
{
2004-10-19 21:05:01 +04:00
const char * sharename = lp_const_servicename ( snum ) ;
struct printjob * pjob ;
2002-08-17 21:00:51 +04:00
int ret ;
2000-04-16 10:20:02 +04:00
SMB_STRUCT_STAT sbuf ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
2000-04-16 10:20:02 +04:00
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( sharename , jobid ) ;
2000-08-01 04:41:19 +04:00
if ( ! pjob )
return False ;
2000-04-16 10:20:02 +04:00
2004-09-03 01:52:35 +04:00
if ( pjob - > spooled | | pjob - > pid ! = sys_getpid ( ) )
2000-08-01 04:41:19 +04:00
return False ;
2000-04-16 10:20:02 +04:00
2001-01-30 00:34:08 +03:00
if ( normal_close & & ( sys_fstat ( pjob - > fd , & sbuf ) = = 0 ) ) {
2000-08-01 04:41:19 +04:00
pjob - > size = sbuf . st_size ;
2001-01-19 19:57:39 +03:00
close ( pjob - > fd ) ;
pjob - > fd = - 1 ;
} else {
2001-01-30 00:34:08 +03:00
/*
* Not a normal close or we couldn ' t stat the job file ,
* so something has gone wrong . Cleanup .
*/
2001-02-22 04:31:55 +03:00
close ( pjob - > fd ) ;
pjob - > fd = - 1 ;
2001-06-28 23:23:43 +04:00
DEBUG ( 3 , ( " print_job_end: failed to stat file for jobid %d \n " , jobid ) ) ;
2001-02-22 04:31:55 +03:00
goto fail ;
2001-01-19 19:57:39 +03:00
}
2001-02-22 04:31:55 +03:00
2002-07-15 14:35:28 +04:00
/* Technically, this is not quite right. If the printer has a separator
2001-02-22 04:31:55 +03:00
* page turned on , the NT spooler prints the separator page even if the
* print job is 0 bytes . 010215 JRR */
2001-02-23 06:59:37 +03:00
if ( pjob - > size = = 0 | | pjob - > status = = LPQ_DELETING ) {
/* don't bother spooling empty files or something being deleted. */
DEBUG ( 5 , ( " print_job_end: canceling spool of %s (%s) \n " ,
pjob - > filename , pjob - > size ? " deleted " : " zero length " ) ) ;
2000-04-16 10:20:02 +04:00
unlink ( pjob - > filename ) ;
2004-10-19 21:05:01 +04:00
pjob_delete ( sharename , jobid ) ;
2000-04-16 10:20:02 +04:00
return True ;
}
2003-11-25 22:16:35 +03:00
pjob - > smbjob = jobid ;
2001-03-16 08:55:30 +03:00
ret = ( * ( current_printif - > job_submit ) ) ( snum , pjob ) ;
2000-04-16 10:20:02 +04:00
2001-06-28 23:23:43 +04:00
if ( ret )
goto fail ;
2001-02-22 04:31:55 +03:00
/* The print job has been sucessfully handed over to the back-end */
pjob - > spooled = True ;
2001-02-23 06:59:37 +03:00
pjob - > status = LPQ_QUEUED ;
2004-10-19 21:05:01 +04:00
pjob_store ( sharename , jobid , pjob ) ;
2001-02-22 04:31:55 +03:00
/* make sure the database is up to date */
2004-12-08 06:02:29 +03:00
if ( print_cache_expired ( lp_const_servicename ( snum ) , True ) )
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , False ) ;
2001-02-22 04:31:55 +03:00
return True ;
fail :
2001-06-28 23:23:43 +04:00
2001-02-22 04:31:55 +03:00
/* The print job was not succesfully started. Cleanup */
/* Still need to add proper error return propagation! 010122:JRR */
unlink ( pjob - > filename ) ;
2004-10-19 21:05:01 +04:00
pjob_delete ( sharename , jobid ) ;
2001-02-22 04:31:55 +03:00
return False ;
2000-04-16 10:20:02 +04:00
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
2003-03-22 01:00:21 +03:00
Get a snapshot of jobs in the system without traversing .
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-22 01:00:21 +03:00
static BOOL get_stored_queue_info ( struct tdb_print_db * pdb , int snum , int * pcount , print_queue_struct * * ppqueue )
2000-04-16 10:20:02 +04:00
{
2005-03-12 12:58:35 +03:00
TDB_DATA data , cgdata ;
2003-03-22 01:00:21 +03:00
print_queue_struct * queue = NULL ;
uint32 qcount = 0 ;
uint32 extra_count = 0 ;
int total_count = 0 ;
2003-04-04 05:02:20 +04:00
size_t len = 0 ;
2003-03-22 01:00:21 +03:00
uint32 i ;
int max_reported_jobs = lp_max_reported_jobs ( snum ) ;
BOOL ret = False ;
2004-10-19 21:05:01 +04:00
const char * sharename = lp_servicename ( snum ) ;
2000-04-16 10:20:02 +04:00
2003-04-02 06:31:51 +04:00
/* make sure the database is up to date */
2004-12-08 06:02:29 +03:00
if ( print_cache_expired ( lp_const_servicename ( snum ) , True ) )
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , False ) ;
2003-04-02 06:31:51 +04:00
2003-03-22 01:00:21 +03:00
* pcount = 0 ;
* ppqueue = NULL ;
2000-04-16 10:20:02 +04:00
2003-03-22 01:00:21 +03:00
ZERO_STRUCT ( data ) ;
ZERO_STRUCT ( cgdata ) ;
2000-04-16 10:20:02 +04:00
2003-03-22 01:00:21 +03:00
/* Get the stored queue data. */
2005-03-12 12:58:35 +03:00
data = tdb_fetch ( pdb - > tdb , string_tdb_data ( " INFO/linear_queue_array " ) ) ;
2004-01-14 22:12:06 +03:00
if ( data . dptr & & data . dsize > = sizeof ( qcount ) )
len + = tdb_unpack ( data . dptr + len , data . dsize - len , " d " , & qcount ) ;
2003-03-22 01:00:21 +03:00
/* Get the changed jobs list. */
2005-03-12 12:58:35 +03:00
cgdata = tdb_fetch ( pdb - > tdb , string_tdb_data ( " INFO/jobs_changed " ) ) ;
2003-03-22 01:00:21 +03:00
if ( cgdata . dptr ! = NULL & & ( cgdata . dsize % 4 = = 0 ) )
extra_count = cgdata . dsize / 4 ;
2000-04-16 10:20:02 +04:00
2003-04-02 06:31:51 +04:00
DEBUG ( 5 , ( " get_stored_queue_info: qcount = %u, extra_count = %u \n " , ( unsigned int ) qcount , ( unsigned int ) extra_count ) ) ;
2003-03-22 01:00:21 +03:00
/* Allocate the queue size. */
if ( qcount = = 0 & & extra_count = = 0 )
goto out ;
2004-12-07 21:25:53 +03:00
if ( ( queue = SMB_MALLOC_ARRAY ( print_queue_struct , qcount + extra_count ) ) = = NULL )
2003-03-22 01:00:21 +03:00
goto out ;
/* Retrieve the linearised queue data. */
2004-01-14 22:12:06 +03:00
2003-03-22 01:00:21 +03:00
for ( i = 0 ; i < qcount ; i + + ) {
uint32 qjob , qsize , qpage_count , qstatus , qpriority , qtime ;
2004-01-14 22:12:06 +03:00
len + = tdb_unpack ( data . dptr + len , data . dsize - len , " ddddddff " ,
2003-03-22 01:00:21 +03:00
& qjob ,
& qsize ,
& qpage_count ,
& qstatus ,
& qpriority ,
& qtime ,
queue [ i ] . fs_user ,
queue [ i ] . fs_file ) ;
queue [ i ] . job = qjob ;
queue [ i ] . size = qsize ;
queue [ i ] . page_count = qpage_count ;
queue [ i ] . status = qstatus ;
queue [ i ] . priority = qpriority ;
queue [ i ] . time = qtime ;
}
2000-04-16 10:20:02 +04:00
2003-03-22 01:00:21 +03:00
total_count = qcount ;
2000-10-10 22:40:03 +04:00
2003-03-22 01:00:21 +03:00
/* Add in the changed jobids. */
for ( i = 0 ; i < extra_count ; i + + ) {
uint32 jobid ;
struct printjob * pjob ;
2000-10-10 22:40:03 +04:00
2004-03-01 20:03:05 +03:00
jobid = IVAL ( cgdata . dptr , i * 4 ) ;
2003-04-02 06:31:51 +04:00
DEBUG ( 5 , ( " get_stored_queue_info: changed job = %u \n " , ( unsigned int ) jobid ) ) ;
2004-10-19 21:05:01 +04:00
pjob = print_job_find ( lp_const_servicename ( snum ) , jobid ) ;
2003-04-02 06:31:51 +04:00
if ( ! pjob ) {
DEBUG ( 5 , ( " get_stored_queue_info: failed to find changed job = %u \n " , ( unsigned int ) jobid ) ) ;
2004-10-19 21:05:01 +04:00
remove_from_jobs_changed ( sharename , jobid ) ;
2003-03-22 01:00:21 +03:00
continue ;
2003-04-02 06:31:51 +04:00
}
2000-10-10 22:40:03 +04:00
2003-03-22 01:00:21 +03:00
queue [ total_count ] . job = jobid ;
queue [ total_count ] . size = pjob - > size ;
queue [ total_count ] . page_count = pjob - > page_count ;
queue [ total_count ] . status = pjob - > status ;
queue [ total_count ] . priority = 1 ;
2003-09-11 21:01:26 +04:00
queue [ total_count ] . time = pjob - > starttime ;
2003-03-22 01:00:21 +03:00
fstrcpy ( queue [ total_count ] . fs_user , pjob - > user ) ;
fstrcpy ( queue [ total_count ] . fs_file , pjob - > jobname ) ;
2003-04-02 06:31:51 +04:00
total_count + + ;
2003-03-22 01:00:21 +03:00
}
2000-10-10 22:40:03 +04:00
2003-03-22 01:00:21 +03:00
/* Sort the queue by submission time otherwise they are displayed
in hash order . */
2000-10-10 22:40:03 +04:00
2003-03-22 01:00:21 +03:00
qsort ( queue , total_count , sizeof ( print_queue_struct ) , QSORT_CAST ( printjob_comp ) ) ;
2000-10-10 22:40:03 +04:00
2003-04-02 06:31:51 +04:00
DEBUG ( 5 , ( " get_stored_queue_info: total_count = %u \n " , ( unsigned int ) total_count ) ) ;
2003-03-22 01:00:21 +03:00
if ( max_reported_jobs & & total_count > max_reported_jobs )
total_count = max_reported_jobs ;
2000-11-04 21:24:15 +03:00
2003-03-22 01:00:21 +03:00
* ppqueue = queue ;
* pcount = total_count ;
2000-11-04 21:24:15 +03:00
2003-03-22 01:00:21 +03:00
ret = True ;
2000-11-04 21:24:15 +03:00
2003-03-22 01:00:21 +03:00
out :
2000-11-04 21:24:15 +03:00
2003-03-22 01:00:21 +03:00
SAFE_FREE ( data . dptr ) ;
SAFE_FREE ( cgdata . dptr ) ;
return ret ;
2000-11-04 21:24:15 +03:00
}
2000-04-16 10:20:02 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Get a printer queue listing .
2003-01-11 05:38:36 +03:00
set queue = NULL and status = NULL if you just want to update the cache
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-16 10:20:02 +04:00
int print_queue_status ( int snum ,
2003-03-22 01:00:21 +03:00
print_queue_struct * * ppqueue ,
2000-04-16 10:20:02 +04:00
print_status_struct * status )
{
fstring keystr ;
TDB_DATA data , key ;
2004-10-19 21:05:01 +04:00
const char * sharename ;
2003-01-11 05:38:36 +03:00
struct tdb_print_db * pdb ;
2003-03-22 01:00:21 +03:00
int count = 0 ;
2003-01-11 05:38:36 +03:00
/* make sure the database is up to date */
2004-12-08 06:02:29 +03:00
if ( print_cache_expired ( lp_const_servicename ( snum ) , True ) )
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , False ) ;
2003-01-11 05:38:36 +03:00
/* return if we are done */
2003-03-22 01:00:21 +03:00
if ( ! ppqueue | | ! status )
2003-01-11 05:38:36 +03:00
return 0 ;
2000-11-10 22:36:34 +03:00
2003-03-22 01:00:21 +03:00
* ppqueue = NULL ;
2004-10-19 21:05:01 +04:00
sharename = lp_const_servicename ( snum ) ;
pdb = get_print_db_byname ( sharename ) ;
2003-01-14 11:53:59 +03:00
2002-07-15 14:35:28 +04:00
if ( ! pdb )
return 0 ;
2000-10-10 22:40:03 +04:00
/*
2000-12-14 00:24:06 +03:00
* Fetch the queue status . We must do this first , as there may
* be no jobs in the queue .
*/
2003-03-22 01:00:21 +03:00
2000-12-14 00:24:06 +03:00
ZERO_STRUCTP ( status ) ;
2004-10-19 21:05:01 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " STATUS/%s " , sharename ) ;
2000-12-14 00:24:06 +03:00
key . dptr = keystr ;
key . dsize = strlen ( keystr ) ;
2002-07-15 14:35:28 +04:00
data = tdb_fetch ( pdb - > tdb , key ) ;
2000-12-14 00:24:06 +03:00
if ( data . dptr ) {
if ( data . dsize = = sizeof ( * status ) ) {
2004-01-14 22:12:06 +03:00
/* this memcpy is ok since the status struct was
not packed before storing it in the tdb */
2000-12-14 00:24:06 +03:00
memcpy ( status , data . dptr , sizeof ( * status ) ) ;
}
2002-07-15 14:35:28 +04:00
SAFE_FREE ( data . dptr ) ;
2000-12-14 00:24:06 +03:00
}
/*
* Now , fetch the print queue information . We first count the number
* of entries , and then only retrieve the queue if necessary .
2000-10-10 22:40:03 +04:00
*/
2003-03-22 01:00:21 +03:00
if ( ! get_stored_queue_info ( pdb , snum , & count , ppqueue ) ) {
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2000-11-10 22:36:34 +03:00
return 0 ;
2002-09-25 19:19:00 +04:00
}
2000-11-10 22:36:34 +03:00
2002-09-25 19:19:00 +04:00
release_print_db ( pdb ) ;
2003-03-22 01:00:21 +03:00
return count ;
2000-04-16 10:20:02 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Pause a queue .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2001-09-03 14:38:13 +04:00
BOOL print_queue_pause ( struct current_user * user , int snum , WERROR * errcode )
2000-04-16 10:20:02 +04:00
{
2000-06-16 12:21:51 +04:00
int ret ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
2000-07-17 06:42:25 +04:00
2000-09-01 22:49:26 +04:00
if ( ! print_access_check ( user , snum , PRINTER_ACCESS_ADMINISTER ) ) {
2001-09-03 14:38:13 +04:00
* errcode = WERR_ACCESS_DENIED ;
2000-06-16 12:21:51 +04:00
return False ;
}
2005-03-08 20:22:39 +03:00
2000-06-16 12:21:51 +04:00
2005-03-08 20:22:39 +03:00
become_root ( ) ;
2001-03-16 08:55:30 +03:00
ret = ( * ( current_printif - > queue_pause ) ) ( snum ) ;
2000-04-16 12:03:37 +04:00
2005-03-08 20:22:39 +03:00
unbecome_root ( ) ;
2000-11-08 02:05:53 +03:00
if ( ret ! = 0 ) {
2001-09-03 14:38:13 +04:00
* errcode = WERR_INVALID_PARAM ;
2000-11-08 02:05:53 +03:00
return False ;
}
2000-04-16 12:03:37 +04:00
/* force update the database */
print_cache_flush ( snum ) ;
2000-11-04 21:24:15 +03:00
/* Send a printer notify message */
2002-07-15 14:35:28 +04:00
notify_printer_status ( snum , PRINTER_STATUS_PAUSED ) ;
2000-11-04 21:24:15 +03:00
2000-11-08 02:05:53 +03:00
return True ;
2000-04-16 10:20:02 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Resume a queue .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2001-09-03 14:38:13 +04:00
BOOL print_queue_resume ( struct current_user * user , int snum , WERROR * errcode )
2000-04-16 10:20:02 +04:00
{
2000-06-16 12:21:51 +04:00
int ret ;
2004-03-02 17:26:45 +03:00
struct printif * current_printif = get_printer_fns ( snum ) ;
2000-06-16 12:21:51 +04:00
2000-09-01 22:49:26 +04:00
if ( ! print_access_check ( user , snum , PRINTER_ACCESS_ADMINISTER ) ) {
2001-09-03 14:38:13 +04:00
* errcode = WERR_ACCESS_DENIED ;
2000-06-16 12:21:51 +04:00
return False ;
}
2005-03-08 20:22:39 +03:00
become_root ( ) ;
2001-03-16 08:55:30 +03:00
ret = ( * ( current_printif - > queue_resume ) ) ( snum ) ;
2000-04-16 12:03:37 +04:00
2005-03-08 20:22:39 +03:00
unbecome_root ( ) ;
2000-11-08 02:05:53 +03:00
if ( ret ! = 0 ) {
2001-09-03 14:38:13 +04:00
* errcode = WERR_INVALID_PARAM ;
2000-11-08 02:05:53 +03:00
return False ;
}
2001-01-19 19:57:39 +03:00
/* make sure the database is up to date */
2004-12-08 06:02:29 +03:00
if ( print_cache_expired ( lp_const_servicename ( snum ) , True ) )
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , True ) ;
2000-04-16 12:03:37 +04:00
2000-11-04 21:24:15 +03:00
/* Send a printer notify message */
2002-07-15 14:35:28 +04:00
notify_printer_status ( snum , PRINTER_STATUS_OK ) ;
2000-11-04 21:24:15 +03:00
2000-11-08 02:05:53 +03:00
return True ;
2000-04-16 10:20:02 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Purge a queue - implemented by deleting all jobs that we can delete .
2000-04-16 10:20:02 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2001-09-03 14:38:13 +04:00
BOOL print_queue_purge ( struct current_user * user , int snum , WERROR * errcode )
2000-04-16 10:20:02 +04:00
{
print_queue_struct * queue ;
print_status_struct status ;
int njobs , i ;
2001-01-22 19:59:24 +03:00
BOOL can_job_admin ;
2000-04-16 10:20:02 +04:00
2001-01-23 20:39:03 +03:00
/* Force and update so the count is accurate (i.e. not a cached count) */
2005-03-08 20:22:39 +03:00
print_queue_update ( snum , True ) ;
2001-01-23 20:39:03 +03:00
2001-01-22 19:59:24 +03:00
can_job_admin = print_access_check ( user , snum , JOB_ACCESS_ADMINISTER ) ;
2000-04-16 10:20:02 +04:00
njobs = print_queue_status ( snum , & queue , & status ) ;
2005-03-08 20:22:39 +03:00
if ( can_job_admin )
become_root ( ) ;
2001-01-11 23:41:19 +03:00
2001-01-22 19:59:24 +03:00
for ( i = 0 ; i < njobs ; i + + ) {
2002-08-17 21:00:51 +04:00
BOOL owner = is_owner ( user , snum , queue [ i ] . job ) ;
2001-01-22 19:59:24 +03:00
if ( owner | | can_job_admin ) {
2002-08-17 21:00:51 +04:00
print_job_delete1 ( snum , queue [ i ] . job ) ;
2000-09-01 22:49:26 +04:00
}
2000-04-16 10:20:02 +04:00
}
2005-03-08 20:22:39 +03:00
if ( can_job_admin )
unbecome_root ( ) ;
/* update the cache */
print_queue_update ( snum , True ) ;
2000-04-16 10:20:02 +04:00
2002-07-15 14:35:28 +04:00
SAFE_FREE ( queue ) ;
2000-11-04 21:24:15 +03:00
2000-04-16 10:20:02 +04:00
return True ;
}