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

📄 printing.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		qcount++;		data.dsize += tdb_pack(NULL, 0, "ddddddff",				(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);	}	if ((data.dptr = SMB_MALLOC(data.dsize)) == NULL)		return;        len = 0;	len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);	for (i = 0; i < pts->qcount; i++) {		if ( queue[i].status == LPQ_DELETED )			continue;		len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",				(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);	}	tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,		  TDB_REPLACE);	SAFE_FREE(data.dptr);	return;}static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb){	TDB_DATA data;	ZERO_STRUCT(data);	data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));	if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {		SAFE_FREE(data.dptr);		ZERO_STRUCT(data);	}	return data;}static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid){	unsigned int i;	unsigned int job_count = data.dsize / 4;	for (i = 0; i < job_count; i++) {		uint32 ch_jobid;		ch_jobid = IVAL(data.dptr, i*4);		if (ch_jobid == jobid)			remove_from_jobs_changed(sharename, jobid);	}}/**************************************************************************** Check if the print queue has been updated recently enough.****************************************************************************/static BOOL print_cache_expired(const char *sharename, BOOL check_pending){	fstring key;	time_t last_qscan_time, time_now = time(NULL);	struct tdb_print_db *pdb = get_print_db_byname(sharename);	BOOL result = False;	if (!pdb)		return False;	snprintf(key, sizeof(key), "CACHE/%s", sharename);	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)) 	{		uint32 u;		time_t msg_pending_time;		DEBUG(4, ("print_cache_expired: cache expired for queue %s " 			"(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", 			sharename, (int)last_qscan_time, (int)time_now, 			(int)lp_lpqcachetime() ));		/* 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 			&& tdb_fetch_uint32( pdb->tdb, key, &u ) 			&& (msg_pending_time=u) > 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;	}done:	release_print_db(pdb);	return result;}/**************************************************************************** main work for updating the lpq cahe for a printer queue****************************************************************************/static void print_queue_update_internal( const char *sharename,                                          struct printif *current_printif,                                         char *lpq_command, char *lprm_command ){	int i, qcount;	print_queue_struct *queue = NULL;	print_status_struct status;	print_status_struct old_status;	struct printjob *pjob;	struct traverse_struct tstruct;	TDB_DATA data, key;	TDB_DATA jcdata;	fstring keystr, cachestr;	struct tdb_print_db *pdb = get_print_db_byname(sharename);	if (!pdb) {		return;	}		DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",		sharename, current_printif->type, lpq_command));	/*	 * Update the cache time FIRST ! Stops others even	 * attempting to get the lock and doing this	 * if the lpq takes a long time.	 */	 	slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);	tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));        /* get the current queue using the appropriate interface */	ZERO_STRUCT(status);	qcount = (*(current_printif->queue_get))(sharename, 		current_printif->type, 		lpq_command, &queue, &status);	DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n", 		qcount, (qcount != 1) ?	"s" : "", sharename));	/* Sort the queue by submission time otherwise they are displayed	   in hash order. */	qsort(queue, qcount, sizeof(print_queue_struct),		QSORT_CAST(printjob_comp));	/*	  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	*/	jcdata = get_jobs_changed_data(pdb);	for (i=0; i<qcount; i++) {		uint32 jobid = print_parse_jobid(queue[i].fs_file);		if (jobid == (uint32)-1) {			/* assume its a unix print job */			print_unix_job(sharename, &queue[i], jobid);			continue;		}		/* we have an active SMB print job - update its status */		pjob = print_job_find(sharename, jobid);		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. */			print_unix_job(sharename, &queue[i], jobid);			continue;		}		pjob->sysjob = queue[i].job;		/* don't reset the status on jobs to be deleted */		if ( pjob->status != LPQ_DELETING )			pjob->status = queue[i].status;		pjob_store(sharename, jobid, pjob);		check_job_changed(sharename, jcdata, jobid);	}	SAFE_FREE(jcdata.dptr);	/* now delete any queued entries that don't appear in the           system queue */	tstruct.queue = queue;	tstruct.qcount = qcount;	tstruct.snum = -1;	tstruct.total_jobs = 0;	tstruct.lpq_time = time(NULL);	tstruct.sharename = sharename;	tstruct.lprm_command = lprm_command;	tstruct.print_if = current_printif;	tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);	/* Store the linearised queue, max jobs only. */	store_queue_struct(pdb, &tstruct);	SAFE_FREE(tstruct.queue);	DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",				sharename, tstruct.total_jobs ));	tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);	get_queue_status(sharename, &old_status);	if (old_status.qcount != qcount)		DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",					old_status.qcount, qcount, sharename));	/* store the new queue status structure */	slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);	key.dptr = keystr;	key.dsize = strlen(keystr);	status.qcount = qcount;	data.dptr = (void *)&status;	data.dsize = sizeof(status);	tdb_store(pdb->tdb, key, data, TDB_REPLACE);		/*	 * Update the cache time again. We want to do this call	 * as little as possible...	 */	slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);	tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));	/* 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;}/**************************************************************************** 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).****************************************************************************/static void print_queue_update_with_lock( const char *sharename,                                           struct printif *current_printif,                                          char *lpq_command, char *lprm_command ){	fstring keystr;	struct tdb_print_db *pdb;	DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));	pdb = get_print_db_byname(sharename);	if (!pdb)		return;	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;	}		/*	 * 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) {		DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));		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. */	set_updating_pid(sharename, True);	/*	 * 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, lprm_command );		/* Delete our pid from the db. */	set_updating_pid(sharename, False);	release_print_db(pdb);}/****************************************************************************this is the receive function of the background lpq updater****************************************************************************/static void print_queue_receive(int msg_type, struct process_id src,				void *buf, size_t msglen){	fstring sharename;	pstring lpqcommand, lprmcommand;	int printing_type;	size_t len;	len = tdb_unpack( buf, msglen, "fdPP",		sharename,		&printing_type,		lpqcommand,		lprmcommand );	if ( len == -1 ) {		DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));		return;	}	print_queue_update_with_lock(sharename, 		get_printer_fns_from_type(printing_type),		lpqcommand, lprmcommand );	return;}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, 			FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);		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();			/* process any pending print change notify messages */			print_notify_send_messages(0);		}	}}/****************************************************************************update the internal database from the system print queue for a queue****************************************************************************/static void print_queue_update(int snum, BOOL force){	fstring key;	fstring sharename;	pstring lpqcommand, lprmcommand;	char *buffer = NULL;	size_t len = 0;	size_t newlen;	struct tdb_print_db *pdb;	int type;	struct printif *current_printif;	fstrcpy( sharename, lp_const_servicename(snum));	/* don't strip out characters like '$' from the printername */		pstrcpy( lpqcommand, lp_lpqcommand(snum));	string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False );	standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );	

⌨️ 快捷键说明

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