⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printing.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    Unix SMB/Netbios implementation.   Version 3.0   printing backend routines   Copyright (C) Andrew Tridgell 1992-2000   Copyright (C) Jeremy Allison 2002      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 02139, USA.*/#include "includes.h"#include "printing.h"extern SIG_ATOMIC_T got_sig_term;extern SIG_ATOMIC_T reload_after_sighup;/* Current printer interface */static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid);/*    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   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. */static TDB_CONTEXT *rap_tdb;static uint16 next_rap_jobid;struct rap_jobid_key {	fstring sharename;	uint32  jobid;};/*************************************************************************** Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32 bit RPC jobids.... JRA.***************************************************************************/uint16 pjobid_to_rap(const char* sharename, uint32 jobid){	uint16 rap_jobid;	TDB_DATA data, key;	struct rap_jobid_key jinfo;	uint8 buf[2];	DEBUG(10,("pjobid_to_rap: called.\n"));	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;	}	ZERO_STRUCT( jinfo );	fstrcpy( jinfo.sharename, sharename );	jinfo.jobid = jobid;	key.dptr = (char*)&jinfo;	key.dsize = sizeof(jinfo);	data = tdb_fetch(rap_tdb, key);	if (data.dptr && data.dsize == sizeof(uint16)) {		rap_jobid = SVAL(data.dptr, 0);		SAFE_FREE(data.dptr);		DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",			(unsigned int)jobid, (unsigned int)rap_jobid));		return rap_jobid;	}	SAFE_FREE(data.dptr);	/* Not found - create and store mapping. */	rap_jobid = ++next_rap_jobid;	if (rap_jobid == 0)		rap_jobid = ++next_rap_jobid;	SSVAL(buf,0,rap_jobid);	data.dptr = (char*)buf;	data.dsize = sizeof(rap_jobid);	tdb_store(rap_tdb, key, data, TDB_REPLACE);	tdb_store(rap_tdb, data, key, TDB_REPLACE);	DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",		(unsigned int)jobid, (unsigned int)rap_jobid));	return rap_jobid;}BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid){	TDB_DATA data, key;	uint8 buf[2];	DEBUG(10,("rap_to_pjobid called.\n"));	if (!rap_tdb)		return False;	SSVAL(buf,0,rap_jobid);	key.dptr = (char*)buf;	key.dsize = sizeof(rap_jobid);	data = tdb_fetch(rap_tdb, key);	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;		DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",			(unsigned int)*pjobid, (unsigned int)rap_jobid));		SAFE_FREE(data.dptr);		return True;	}	DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",		(unsigned int)rap_jobid));	SAFE_FREE(data.dptr);	return False;}static void rap_jobid_delete(const char* sharename, uint32 jobid){	TDB_DATA key, data;	uint16 rap_jobid;	struct rap_jobid_key jinfo;	uint8 buf[2];	DEBUG(10,("rap_jobid_delete: called.\n"));	if (!rap_tdb)		return;	ZERO_STRUCT( jinfo );	fstrcpy( jinfo.sharename, sharename );	jinfo.jobid = jobid;	key.dptr = (char*)&jinfo;	key.dsize = sizeof(jinfo);	data = tdb_fetch(rap_tdb, key);	if (!data.dptr || (data.dsize != sizeof(uint16))) {		DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",			(unsigned int)jobid ));		SAFE_FREE(data.dptr);		return;	}	DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",		(unsigned int)jobid ));	rap_jobid = SVAL(data.dptr, 0);	SAFE_FREE(data.dptr);	SSVAL(buf,0,rap_jobid);	data.dptr = (char*)buf;	data.dsize = sizeof(rap_jobid);	tdb_delete(rap_tdb, key);	tdb_delete(rap_tdb, data);}static int get_queue_status(const char* sharename, print_status_struct *);/**************************************************************************** Initialise the printing backend. Called once at startup before the fork().****************************************************************************/BOOL print_backend_init(void){	const char *sversion = "INFO/version";	pstring printing_path;	int services = lp_numservices();	int snum;	unlink(lock_path("printing.tdb"));	pstrcpy(printing_path,lock_path("printing"));	mkdir(printing_path,0755);	/* handle a Samba upgrade */	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));		if (!pdb)			continue;		if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) {			DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));			release_print_db(pdb);			return False;		}		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);		release_print_db(pdb);	}	close_all_print_db(); /* Don't leave any open. */	/* do NT print initialization... */	return nt_printing_init();}/**************************************************************************** Shut down printing backend. Called once at shutdown to close the tdb.****************************************************************************/void printing_end(void){	close_all_print_db(); /* Don't leave any open. */}/**************************************************************************** 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)****************************************************************************/static struct printif *get_printer_fns_from_type( int type ){	struct printif *printer_fns = &generic_printif;#ifdef HAVE_CUPS	if ( type == PRINT_CUPS ) {		printer_fns = &cups_printif;	}#endif /* HAVE_CUPS */#ifdef HAVE_IPRINT	if ( type == PRINT_IPRINT ) {		printer_fns = &iprint_printif;	}#endif /* HAVE_IPRINT */	printer_fns->type = type;		return printer_fns;}static struct printif *get_printer_fns( int snum ){	return get_printer_fns_from_type( lp_printing(snum) );}/**************************************************************************** Useful function to generate a tdb key.****************************************************************************/static TDB_DATA print_key(uint32 jobid){	static uint32 j;	TDB_DATA ret;	SIVAL(&j, 0, jobid);	ret.dptr = (void *)&j;	ret.dsize = sizeof(j);	return ret;}/*********************************************************************** unpack a pjob from a tdb buffer ***********************************************************************/ int unpack_pjob( char* buf, int buflen, struct printjob *pjob ){	int	len = 0;	int	used;	uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;	uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;	if ( !buf || !pjob )		return -1;			len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",				&pjpid,				&pjsysjob,				&pjfd,				&pjstarttime,				&pjstatus,				&pjsize,				&pjpage_count,				&pjspooled,				&pjsmbjob,				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;	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;		return len;}/**************************************************************************** Useful function to find a print job in the database.****************************************************************************/static struct printjob *print_job_find(const char *sharename, uint32 jobid){	static struct printjob 	pjob;	TDB_DATA 		ret;	struct tdb_print_db 	*pdb = get_print_db_byname(sharename);		if (!pdb)		return NULL;	ret = tdb_fetch(pdb->tdb, print_key(jobid));	release_print_db(pdb);	if (!ret.dptr)		return NULL;		if ( pjob.nt_devmode )		free_nt_devicemode( &pjob.nt_devmode );			ZERO_STRUCT( pjob );		if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {		SAFE_FREE(ret.dptr);		return NULL;	}		SAFE_FREE(ret.dptr);		return &pjob;}/* 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){	struct printjob *pjob;	int *sysjob = (int *)state;	if (!data.dptr || data.dsize == 0)		return 0;	pjob = (struct printjob *)data.dptr;	if (key.dsize != sizeof(uint32))		return 0;	if (*sysjob == pjob->sysjob) {		uint32 jobid = IVAL(key.dptr,0);		sysjob_to_jobid_value = jobid;		return 1;	}	return 0;}/**************************************************************************** This is a *horribly expensive call as we have to iterate through all the current printer tdb's. Don't do this often ! JRA.****************************************************************************/uint32 sysjob_to_jobid(int unix_jobid){	int services = lp_numservices();	int snum;	sysjob_to_jobid_value = (uint32)-1;	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));		if (!pdb) {			continue;		}		tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);		release_print_db(pdb);		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){	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;}static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,			      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. */ 	/* 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) */ 	if (new_job) {		notify_job_submitted(sharename, jobid, new_data->starttime);		notify_job_username(sharename, jobid, new_data->user);	}	if (new_job || !strequal(old_data->jobname, new_data->jobname))		notify_job_name(sharename, jobid, new_data->jobname);	/* Job attributes of a new job or attributes that can be	   modified. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -