📄 printing.c
字号:
pstrcpy( lprmcommand, lp_lprmcommand(snum)); string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), False, False ); standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) ); /* * Make sure that the background queue process exists. * Otherwise just do the update ourselves */ 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, lprmcommand ); return; } type = lp_printing(snum); /* get the length */ len = tdb_pack( buffer, len, "fdPP", sharename, type, lpqcommand, lprmcommand ); buffer = SMB_XMALLOC_ARRAY( char, len ); /* now pack the buffer */ newlen = tdb_pack( buffer, len, "fdPP", sharename, type, lpqcommand, lprmcommand ); SMB_ASSERT( newlen == len ); DEBUG(10,("print_queue_update: Sending message -> printer = %s, " "type = %d, lpq command = [%s] lprm command = [%s]\n", sharename, type, lpqcommand, lprmcommand )); /* 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); if (!pdb) { SAFE_FREE(buffer); return; } 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 ); /* finally send the message */ become_root(); message_send_pid(pid_to_procid(background_lpq_updater_pid), MSG_PRINTER_UPDATE, buffer, len, False); unbecome_root(); SAFE_FREE( buffer ); return;}/**************************************************************************** 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; struct tdb_print_db *pdb = NULL; TDB_CONTEXT *tdb = NULL; const char *printername; uint32 mypid = (uint32)sys_getpid(); BOOL ret = False; size_t i; /* 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 */ { printername = lp_const_servicename(snum); pdb = get_print_db_byname(printername); if (!pdb) return False; tdb = pdb->tdb; } 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); return False; } data = get_printer_notify_pid_list( tdb, printername, True ); /* 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. */ data.dptr = SMB_REALLOC(data.dptr, data.dsize + 8); if (!data.dptr) { DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n", printername)); goto done; } data.dsize += 8; SIVAL(data.dptr,data.dsize - 8,mypid); SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */ } /* Store back the record. */ if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { DEBUG(0,("print_notify_register_pid: Failed to update pid \list for printer %s\n", printername)); goto done; } ret = True; done: tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); if (pdb) release_print_db(pdb); 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; struct tdb_print_db *pdb = NULL; TDB_CONTEXT *tdb = NULL; const char *printername; uint32 mypid = (uint32)sys_getpid(); size_t i; BOOL ret = False; /* 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 */ { printername = lp_const_servicename(snum); pdb = get_print_db_byname(printername); if (!pdb) return False; tdb = pdb->tdb; } 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); return False; } data = get_printer_notify_pid_list( tdb, printername, True ); /* 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. */ if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { DEBUG(0,("print_notify_register_pid: Failed to update pid \list for printer %s\n", printername)); goto done; } ret = True; done: tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); if (pdb) release_print_db(pdb); SAFE_FREE(data.dptr); return ret;}/**************************************************************************** Check if a jobid is valid. It is valid if it exists in the database.****************************************************************************/BOOL print_job_exists(const char* sharename, uint32 jobid){ struct tdb_print_db *pdb = get_print_db_byname(sharename); BOOL ret; if (!pdb) return False; ret = tdb_exists(pdb->tdb, print_key(jobid)); release_print_db(pdb); return ret;}/**************************************************************************** Give the fd used for a jobid.****************************************************************************/int print_job_fd(const char* sharename, uint32 jobid){ struct printjob *pjob = print_job_find(sharename, jobid); if (!pjob) return -1; /* don't allow another process to get this info - it is meaningless */ if (pjob->pid != sys_getpid()) return -1; return pjob->fd;}/**************************************************************************** Give the filename used for a jobid. Only valid for the process doing the spooling and when the job has not been spooled.****************************************************************************/char *print_job_fname(const char* sharename, uint32 jobid){ struct printjob *pjob = print_job_find(sharename, jobid); if (!pjob || pjob->spooled || pjob->pid != sys_getpid()) return NULL; return pjob->filename;}/**************************************************************************** Give the filename used for a jobid. Only valid for the process doing the spooling and when the job has not been spooled.****************************************************************************/NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid){ struct printjob *pjob = print_job_find(sharename, jobid); if ( !pjob ) return NULL; return pjob->nt_devmode;}/**************************************************************************** Set the place in the queue for a job.****************************************************************************/BOOL print_job_set_place(int snum, uint32 jobid, int place){ DEBUG(2,("print_job_set_place not implemented yet\n")); return False;}/**************************************************************************** Set the name of a job. Only possible for owner.****************************************************************************/BOOL print_job_set_name(int snum, uint32 jobid, char *name){ const char* sharename = lp_const_servicename(snum); struct printjob *pjob; pjob = print_job_find(sharename, jobid); if (!pjob || pjob->pid != sys_getpid()) return False; fstrcpy(pjob->jobname, name); return pjob_store(sharename, jobid, pjob);}/*************************************************************************** Remove a jobid from the 'jobs changed' list.***************************************************************************/static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid){ struct tdb_print_db *pdb = get_print_db_byname(sharename); TDB_DATA data, key; size_t job_count, i; BOOL ret = False; BOOL gotlock = False; if (!pdb) { return False; } ZERO_STRUCT(data); key = string_tdb_data("INFO/jobs_changed"); if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1) 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; ch_jobid = IVAL(data.dptr, i*4); 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); 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 )); return ret;}/**************************************************************************** Delete a print job - don't update queue.****************************************************************************/static BOOL print_job_delete1(int snum, uint32 jobid){ const char* sharename = lp_const_servicename(snum); struct printjob *pjob = print_job_find(sharename, jobid); int result = 0; struct printif *current_printif = get_printer_fns( snum ); if (!pjob) return False; /* * If already deleting just return. */ if (pjob->status == LPQ_DELETING) return True; /* Hrm - we need to be able to cope with deleting a job before it has reached the spooler. Just mark it as LPQ_DELETING and let the print_queue_update() code rmeove the record */ if (pjob->sysjob == -1) { DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid)); } /* Set the tdb entry to be deleting. */ pjob->status = LPQ_DELETING; pjob_store(sharename, jobid, pjob); if (pjob->spooled && pjob->sysjob != -1) { result = (*(current_printif->job_delete))( PRINTERNAME(snum), lp_lprmcommand(snum), pjob); /* Delete the tdb entry if the delete succeeded or the job hasn't been spooled. */ if (result == 0) { struct tdb_print_db *pdb = get_print_db_byname(sharename); int njobs = 1; if (!pdb) return False; pjob_delete(sharename, jobid); /* 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); } } remove_from_jobs_changed( sharename, jobid ); return (result == 0);}/**************************************************************************** Return true if the current user owns the print job.****************************************************************************/static BOOL is_owner(struct current_user *user, int snum, uint32 jobid){ struct printjob *pjob = print_job_find(lp_const_servicename(snum), jobid); user_struct *vuser; if (!pjob || !user) return False; if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { return strequal(pjob->user, vuser->user.smb_name); } else { return strequal(pjob->user, uidtoname(user->uid)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -