2001-03-16 03:35:57 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-03-16 03:35:57 +03:00
printing command routines
Copyright ( C ) Andrew Tridgell 1992 - 2000
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-03-16 03:35:57 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-03-16 03:35:57 +03:00
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2001-03-16 03:35:57 +03:00
# include "printing.h"
2006-12-12 20:38:42 +03:00
extern struct current_user current_user ;
extern userdom_struct current_user_info ;
2001-03-16 03:35:57 +03:00
/****************************************************************************
2007-11-22 00:56:36 +03:00
Run a given print command
a null terminated list of value / substitute pairs is provided
for local substitution strings
2001-03-16 03:35:57 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static int print_run_command ( int snum , const char * printername , bool do_sub ,
2005-09-30 21:13:37 +04:00
const char * command , int * outfd , . . . )
2001-03-16 03:35:57 +03:00
{
2007-11-22 00:56:36 +03:00
char * syscmd ;
2002-07-15 14:35:28 +04:00
char * arg ;
2001-03-16 03:35:57 +03:00
int ret ;
2007-11-22 00:56:36 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2001-03-16 03:35:57 +03:00
va_list ap ;
2001-04-13 23:12:06 +04:00
va_start ( ap , outfd ) ;
2001-04-11 02:01:53 +04:00
2004-10-19 21:05:01 +04:00
/* check for a valid system printername and valid command to run */
2001-03-16 03:35:57 +03:00
2007-11-22 00:56:36 +03:00
if ( ! printername | | ! * printername ) {
2008-01-27 09:31:56 +03:00
va_end ( ap ) ;
2004-10-19 21:05:01 +04:00
return - 1 ;
2007-11-22 00:56:36 +03:00
}
2004-10-19 21:05:01 +04:00
2007-11-22 00:56:36 +03:00
if ( ! command | | ! * command ) {
2008-01-27 09:31:56 +03:00
va_end ( ap ) ;
2001-03-16 03:35:57 +03:00
return - 1 ;
2007-11-22 00:56:36 +03:00
}
2001-03-16 03:35:57 +03:00
2007-11-22 00:56:36 +03:00
syscmd = talloc_strdup ( ctx , command ) ;
if ( ! syscmd ) {
2008-01-27 09:31:56 +03:00
va_end ( ap ) ;
2007-11-22 00:56:36 +03:00
return - 1 ;
}
2001-03-16 03:35:57 +03:00
while ( ( arg = va_arg ( ap , char * ) ) ) {
char * value = va_arg ( ap , char * ) ;
2007-11-22 00:56:36 +03:00
syscmd = talloc_string_sub ( ctx , syscmd , arg , value ) ;
if ( ! syscmd ) {
2008-01-27 09:31:56 +03:00
va_end ( ap ) ;
2007-11-22 00:56:36 +03:00
return - 1 ;
}
2001-03-16 03:35:57 +03:00
}
va_end ( ap ) ;
2007-11-22 00:56:36 +03:00
syscmd = talloc_string_sub ( ctx , syscmd , " %p " , printername ) ;
if ( ! syscmd ) {
return - 1 ;
}
if ( do_sub & & snum ! = - 1 ) {
syscmd = talloc_sub_advanced ( ctx ,
2012-07-18 09:37:23 +04:00
lp_servicename ( talloc_tos ( ) , snum ) ,
2007-11-22 00:56:36 +03:00
current_user_info . unix_name ,
" " ,
current_user . ut . gid ,
get_current_username ( ) ,
current_user_info . domain ,
syscmd ) ;
if ( ! syscmd ) {
return - 1 ;
}
}
2007-05-14 18:23:51 +04:00
ret = smbrun_no_sanitize ( syscmd , outfd ) ;
2001-03-16 03:35:57 +03:00
DEBUG ( 3 , ( " Running the command `%s' gave %d \n " , syscmd , ret ) ) ;
return ret ;
}
/****************************************************************************
delete a print job
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
static int generic_job_delete ( const char * sharename , const char * lprm_command , struct printjob * pjob )
2001-03-16 03:35:57 +03:00
{
fstring jobstr ;
/* need to delete the spooled entry */
slprintf ( jobstr , sizeof ( jobstr ) - 1 , " %d " , pjob - > sysjob ) ;
2005-09-30 21:13:37 +04:00
return print_run_command ( - 1 , sharename , False , lprm_command , NULL ,
2001-03-16 03:35:57 +03:00
" %j " , jobstr ,
2008-10-12 01:57:44 +04:00
" %T " , http_timestring ( talloc_tos ( ) , pjob - > starttime ) ,
2001-03-16 03:35:57 +03:00
NULL ) ;
}
/****************************************************************************
pause a job
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int generic_job_pause ( int snum , struct printjob * pjob )
{
fstring jobstr ;
/* need to pause the spooled entry */
slprintf ( jobstr , sizeof ( jobstr ) - 1 , " %d " , pjob - > sysjob ) ;
2012-07-18 09:37:23 +04:00
return print_run_command ( snum , lp_printername ( talloc_tos ( ) , snum ) , True ,
2014-02-04 06:09:06 +04:00
lp_lppause_command ( talloc_tos ( ) , snum ) , NULL ,
2001-03-16 03:35:57 +03:00
" %j " , jobstr ,
NULL ) ;
}
/****************************************************************************
resume a job
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int generic_job_resume ( int snum , struct printjob * pjob )
{
fstring jobstr ;
2007-11-22 00:56:36 +03:00
2001-03-16 03:35:57 +03:00
/* need to pause the spooled entry */
slprintf ( jobstr , sizeof ( jobstr ) - 1 , " %d " , pjob - > sysjob ) ;
2012-07-18 09:37:23 +04:00
return print_run_command ( snum , lp_printername ( talloc_tos ( ) , snum ) , True ,
2014-02-04 06:09:06 +04:00
lp_lpresume_command ( talloc_tos ( ) , snum ) , NULL ,
2001-03-16 03:35:57 +03:00
" %j " , jobstr ,
NULL ) ;
}
2012-02-09 15:08:27 +04:00
/****************************************************************************
get the current list of queued jobs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int generic_queue_get ( const char * printer_name ,
enum printing_types printing_type ,
char * lpq_command ,
print_queue_struct * * q ,
print_status_struct * status )
{
char * * qlines ;
int fd ;
int numlines , i , qcount ;
print_queue_struct * queue = NULL ;
/* never do substitution when running the 'lpq command' since we can't
get it rigt when using the background update daemon . Make the caller
do it before passing off the command string to us here . */
print_run_command ( - 1 , printer_name , False , lpq_command , & fd , NULL ) ;
if ( fd = = - 1 ) {
DEBUG ( 5 , ( " generic_queue_get: Can't read print queue status for printer %s \n " ,
printer_name ) ) ;
return 0 ;
}
numlines = 0 ;
qlines = fd_lines_load ( fd , & numlines , 0 , NULL ) ;
close ( fd ) ;
/* turn the lpq output into a series of job structures */
qcount = 0 ;
ZERO_STRUCTP ( status ) ;
if ( numlines & & qlines ) {
queue = SMB_MALLOC_ARRAY ( print_queue_struct , numlines + 1 ) ;
if ( ! queue ) {
TALLOC_FREE ( qlines ) ;
* q = NULL ;
return 0 ;
}
memset ( queue , ' \0 ' , sizeof ( print_queue_struct ) * ( numlines + 1 ) ) ;
for ( i = 0 ; i < numlines ; i + + ) {
/* parse the line */
if ( parse_lpq_entry ( printing_type , qlines [ i ] ,
& queue [ qcount ] , status , qcount = = 0 ) ) {
qcount + + ;
}
}
}
TALLOC_FREE ( qlines ) ;
* q = queue ;
return qcount ;
}
2001-03-16 03:35:57 +03:00
/****************************************************************************
Submit a file for printing - called from print_job_end ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-02-08 21:47:11 +04:00
static int generic_job_submit ( int snum , struct printjob * pjob ,
enum printing_types printing_type ,
char * lpq_cmd )
2001-03-16 03:35:57 +03:00
{
2007-11-22 00:56:36 +03:00
int ret = - 1 ;
char * current_directory = NULL ;
char * print_directory = NULL ;
char * wd = NULL ;
char * p = NULL ;
char * jobname = NULL ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-03-20 02:33:32 +03:00
fstring job_page_count , job_size ;
2012-02-09 15:08:27 +04:00
print_queue_struct * q ;
print_status_struct status ;
2001-03-16 03:35:57 +03:00
/* we print from the directory path to give the best chance of
parsing the lpq output */
2011-06-01 03:14:04 +04:00
wd = sys_getwd ( ) ;
2007-11-22 00:56:36 +03:00
if ( ! wd ) {
return - 1 ;
}
2001-03-16 03:35:57 +03:00
2011-06-01 03:14:04 +04:00
current_directory = talloc_strdup ( ctx , wd ) ;
SAFE_FREE ( wd ) ;
if ( ! current_directory ) {
return - 1 ;
}
2007-11-22 00:56:36 +03:00
print_directory = talloc_strdup ( ctx , pjob - > filename ) ;
if ( ! print_directory ) {
return - 1 ;
}
2001-07-04 11:36:09 +04:00
p = strrchr_m ( print_directory , ' / ' ) ;
2007-11-22 00:56:36 +03:00
if ( ! p ) {
return - 1 ;
}
2001-03-16 03:35:57 +03:00
* p + + = 0 ;
2007-11-22 00:56:36 +03:00
if ( chdir ( print_directory ) ! = 0 ) {
return - 1 ;
}
2001-03-16 03:35:57 +03:00
2007-11-22 00:56:36 +03:00
jobname = talloc_strdup ( ctx , pjob - > jobname ) ;
if ( ! jobname ) {
ret = - 1 ;
goto out ;
}
jobname = talloc_string_sub ( ctx , jobname , " ' " , " _ " ) ;
if ( ! jobname ) {
ret = - 1 ;
goto out ;
}
2002-03-20 02:33:32 +03:00
slprintf ( job_page_count , sizeof ( job_page_count ) - 1 , " %d " , pjob - > page_count ) ;
2003-11-03 17:34:25 +03:00
slprintf ( job_size , sizeof ( job_size ) - 1 , " %lu " , ( unsigned long ) pjob - > size ) ;
2001-03-16 03:35:57 +03:00
/* send it to the system spooler */
2012-07-18 09:37:23 +04:00
ret = print_run_command ( snum , lp_printername ( talloc_tos ( ) , snum ) , True ,
2014-02-04 06:09:07 +04:00
lp_print_command ( talloc_tos ( ) , snum ) , NULL ,
2002-03-20 02:33:32 +03:00
" %s " , p ,
" %J " , jobname ,
" %f " , p ,
" %z " , job_size ,
" %c " , job_page_count ,
NULL ) ;
2012-02-09 15:08:27 +04:00
if ( ret ! = 0 ) {
ret = - 1 ;
goto out ;
}
/*
* check the queue for the newly submitted job , this allows us to
* determine the backend job identifier ( sysjob ) .
*/
pjob - > sysjob = - 1 ;
2012-07-18 09:37:23 +04:00
ret = generic_queue_get ( lp_printername ( talloc_tos ( ) , snum ) ,
printing_type , lpq_cmd , & q , & status ) ;
2012-02-09 15:08:27 +04:00
if ( ret > 0 ) {
int i ;
for ( i = 0 ; i < ret ; i + + ) {
if ( strcmp ( q [ i ] . fs_file , p ) = = 0 ) {
pjob - > sysjob = q [ i ] . sysjob ;
DEBUG ( 5 , ( " new job %u (%s) matches sysjob %d \n " ,
pjob - > jobid , jobname , pjob - > sysjob ) ) ;
break ;
}
}
SAFE_FREE ( q ) ;
ret = 0 ;
}
if ( pjob - > sysjob = = - 1 ) {
2012-08-28 20:58:24 +04:00
DEBUG ( 2 , ( " failed to get sysjob for job %u (%s), tracking as "
2012-02-09 15:08:27 +04:00
" Unix job \n " , pjob - > jobid , jobname ) ) ;
}
2001-03-16 03:35:57 +03:00
2007-11-22 00:56:36 +03:00
out :
2001-03-16 03:35:57 +03:00
2011-06-01 03:14:04 +04:00
if ( chdir ( current_directory ) = = - 1 ) {
2008-12-23 23:11:12 +03:00
smb_panic ( " chdir failed in generic_job_submit " ) ;
}
2007-11-22 00:56:36 +03:00
TALLOC_FREE ( current_directory ) ;
2001-03-16 03:35:57 +03:00
return ret ;
}
/****************************************************************************
pause a queue
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int generic_queue_pause ( int snum )
{
2012-07-18 09:37:23 +04:00
return print_run_command ( snum , lp_printername ( talloc_tos ( ) , snum ) , True ,
2014-02-04 06:09:07 +04:00
lp_queuepause_command ( talloc_tos ( ) , snum ) , NULL , NULL ) ;
2001-03-16 03:35:57 +03:00
}
/****************************************************************************
resume a queue
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int generic_queue_resume ( int snum )
{
2012-07-18 09:37:23 +04:00
return print_run_command ( snum , lp_printername ( talloc_tos ( ) , snum ) , True ,
2014-02-04 06:09:08 +04:00
lp_queueresume_command ( talloc_tos ( ) , snum ) , NULL , NULL ) ;
2001-03-16 03:35:57 +03:00
}
2004-10-19 21:05:01 +04:00
/****************************************************************************
* Generic printing interface definitions . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct printif generic_printif =
{
DEFAULT_PRINTING ,
generic_queue_get ,
generic_queue_pause ,
generic_queue_resume ,
generic_job_delete ,
generic_job_pause ,
generic_job_resume ,
generic_job_submit ,
} ;