#include "../librpc/gen_ndr/netlogon.h"
#include "printing/notify.h"
#include "printing/pcap.h"
+#include "printing/printer_list.h"
+#include "printing/queue_process.h"
#include "serverid.h"
#include "smbd/smbd.h"
#include "auth.h"
#include "messages.h"
#include "util_tdb.h"
+#include "lib/param/loadparm.h"
extern struct current_user current_user;
extern userdom_struct current_user_info;
int services = lp_numservices();
int snum;
+ if (!printer_list_parent_init()) {
+ return false;
+ }
+
unlink(cache_path("printing.tdb"));
mkdir(cache_path("printing"),0755);
unpack a pjob from a tdb buffer
***********************************************************************/
-static int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
+static int unpack_pjob(uint8 *buf, int buflen, struct printjob *pjob)
{
int len = 0;
int used;
- uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
+ uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
- if ( !buf || !pjob )
+ if (!buf || !pjob) {
return -1;
+ }
- len += tdb_unpack(buf+len, buflen-len, "dddddddddfffff",
+ len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
&pjpid,
+ &pjjobid,
&pjsysjob,
&pjfd,
&pjstarttime,
pjob->clientmachine,
pjob->queuename);
- if ( len == -1 )
+ if (len == -1) {
return -1;
+ }
used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
if (used == -1) {
len += used;
pjob->pid = pjpid;
+ pjob->jobid = pjjobid;
pjob->sysjob = pjsysjob;
pjob->fd = pjfd;
pjob->starttime = pjstarttime;
DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
(int)pjob.sysjob, (unsigned int)jobid ));
+ SMB_ASSERT(pjob.jobid == jobid);
return &pjob;
}
return 0;
if (state->sysjob == pjob->sysjob) {
- uint32 jobid = IVAL(key.dptr,0);
-
- state->sysjob_to_jobid_value = jobid;
+ state->sysjob_to_jobid_value = pjob->jobid;
return 1;
}
return 0;
}
+static uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
+{
+ struct unixjob_traverse_state state;
+
+ state.sysjob = sysjob;
+ state.sysjob_to_jobid_value = (uint32)-1;
+
+ tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
+
+ return state.sysjob_to_jobid_value;
+}
+
/****************************************************************************
This is a *horribly expensive call as we have to iterate through all the
current printer tdb's. Don't do this often ! JRA.
do {
len = 0;
buflen = newlen;
- len += tdb_pack(buf+len, buflen-len, "dddddddddfffff",
+ len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
(uint32)pjob->pid,
+ (uint32)pjob->jobid,
(uint32)pjob->sysjob,
(uint32)pjob->fd,
(uint32)pjob->starttime,
struct printjob pj, *old_pj;
if (jobid == (uint32)-1)
- jobid = q->job + UNIX_JOB_START;
+ jobid = q->sysjob + UNIX_JOB_START;
/* Preserve the timestamp on an existing unix print job */
ZERO_STRUCT(pj);
pj.pid = (pid_t)-1;
- pj.sysjob = q->job;
+ pj.jobid = jobid;
+ pj.sysjob = q->sysjob;
pj.fd = -1;
pj.starttime = old_pj ? old_pj->starttime : q->time;
pj.status = q->status;
if ( key.dsize != sizeof(jobid) )
return 0;
- jobid = IVAL(key.dptr, 0);
- if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+ if (unpack_pjob(data.dptr, data.dsize, &pjob) == -1)
return 0;
talloc_free(pjob.devmode);
-
+ jobid = pjob.jobid;
if (!pjob.smbjob) {
/* remove a unix job if it isn't in the system queue any more */
-
for (i=0;i<ts->qcount;i++) {
- uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
- if (jobid == u_jobid)
+ if (ts->queue[i].sysjob == pjob.sysjob) {
break;
+ }
}
if (i == ts->qcount) {
DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
/* this check only makes sense for jobs submitted from Windows clients */
- if ( pjob.smbjob ) {
+ if (pjob.smbjob) {
for (i=0;i<ts->qcount;i++) {
- uint32 curr_jobid;
-
if ( pjob.status == LPQ_DELETED )
continue;
- curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
-
- if (jobid == curr_jobid) {
+ if (ts->queue[i].sysjob == pjob.sysjob) {
/* try to clean up any jobs that need to be deleted */
return 0;
}
- /* Save the pjob attributes we will store.
- FIXME!!! This is the only place where queue->job
- represents the SMB jobid --jerry */
-
- ts->queue[i].job = jobid;
+ /* Save the pjob attributes we will store. */
+ ts->queue[i].sysjob = pjob.sysjob;
ts->queue[i].size = pjob.size;
ts->queue[i].page_count = pjob.page_count;
ts->queue[i].status = pjob.status;
fstring keystr;
TDB_DATA key;
TDB_DATA data;
- pid_t updating_pid = sys_getpid();
+ pid_t updating_pid = getpid();
uint8 buffer[4];
struct tdb_print_db *pdb = get_print_db_byname(sharename);
qcount++;
data.dsize += tdb_pack(NULL, 0, "ddddddff",
- (uint32)queue[i].job,
+ (uint32)queue[i].sysjob,
(uint32)queue[i].size,
(uint32)queue[i].page_count,
(uint32)queue[i].status,
continue;
len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
- (uint32)queue[i].job,
+ (uint32)queue[i].sysjob,
(uint32)queue[i].size,
(uint32)queue[i].page_count,
(uint32)queue[i].status,
main work for updating the lpq cache for a printer queue
****************************************************************************/
-static void print_queue_update_internal( struct tevent_context *ev,
- struct messaging_context *msg_ctx,
- const char *sharename,
- struct printif *current_printif,
- char *lpq_command, char *lprm_command )
+static void print_queue_update_internal(struct tevent_context *ev,
+ struct messaging_context *msg_ctx,
+ const char *sharename,
+ struct printif *current_printif,
+ char *lpq_command, char *lprm_command)
{
int i, qcount;
print_queue_struct *queue = NULL;
jcdata = get_jobs_added_data(pdb);
for (i=0; i<qcount; i++) {
- uint32 jobid = print_parse_jobid(queue[i].fs_file);
-
+ uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
if (jobid == (uint32)-1) {
/* assume its a unix print job */
print_unix_job(ev, msg_ctx,
/* err, somethings wrong. Probably smbd was restarted
with jobs in the queue. All we can do is treat them
like unix jobs. Pity. */
+ DEBUG(1, ("queued print job %d not found in jobs list, "
+ "assuming unix job\n", jobid));
print_unix_job(ev, msg_ctx,
sharename, &queue[i], jobid);
continue;
}
- pjob->sysjob = queue[i].job;
+ /* FIXME this is already confirmed by sysjob_to_jobid_pdb() */
+ pjob->sysjob = queue[i].sysjob;
/* don't reset the status on jobs to be deleted */
return;
}
-static void printing_pause_fd_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags,
- void *private_data)
-{
- /*
- * If pause_pipe[1] is closed it means the parent smbd
- * and children exited or aborted.
- */
- exit_server_cleanly(NULL);
-}
-
-extern struct child_pid *children;
-extern int num_children;
-
-static void add_child_pid(pid_t pid)
-{
- struct child_pid *child;
-
- child = SMB_MALLOC_P(struct child_pid);
- if (child == NULL) {
- DEBUG(0, ("Could not add child struct -- malloc failed\n"));
- return;
- }
- child->pid = pid;
- DLIST_ADD(children, child);
- num_children += 1;
-}
-
-static pid_t background_lpq_updater_pid = -1;
-
-/****************************************************************************
-main thread of the background lpq updater
-****************************************************************************/
-void start_background_queue(struct tevent_context *ev,
- struct messaging_context *msg_ctx)
-{
- /* Use local variables for this as we don't
- * need to save the parent side of this, just
- * ensure it closes when the process exits.
- */
- int pause_pipe[2];
-
- DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
-
- if (pipe(pause_pipe) == -1) {
- DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
- exit(1);
- }
-
- 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);
- }
-
- /* Track the printing pid along with other smbd children */
- add_child_pid(background_lpq_updater_pid);
-
- if(background_lpq_updater_pid == 0) {
- struct tevent_fd *fde;
- int ret;
- NTSTATUS status;
-
- /* Child. */
- DEBUG(5,("start_background_queue: background LPQ thread started\n"));
-
- close(pause_pipe[0]);
- pause_pipe[0] = -1;
-
- status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("reinit_after_fork() failed\n"));
- smb_panic("reinit_after_fork() failed");
- }
-
- smbd_setup_sig_term_handler();
- smbd_setup_sig_hup_handler(ev, msg_ctx);
-
- if (!serverid_register(procid_self(),
- FLAG_MSG_GENERAL|FLAG_MSG_SMBD
- |FLAG_MSG_PRINT_GENERAL)) {
- exit(1);
- }
-
- if (!locking_init()) {
- exit(1);
- }
-
- messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
- print_queue_receive);
-
- fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
- printing_pause_fd_handler,
- NULL);
- if (!fde) {
- DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
- smb_panic("tevent_add_fd() failed for pause_pipe");
- }
-
- DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
- ret = tevent_loop_wait(ev);
- /* should not be reached */
- DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
- ret, (ret == 0) ? "out of events" : strerror(errno)));
- exit(1);
- }
-
- close(pause_pipe[1]);
-}
-
/****************************************************************************
update the internal database from the system print queue for a queue
****************************************************************************/
+extern pid_t background_lpq_updater_pid;
+
static void print_queue_update(struct messaging_context *msg_ctx,
int snum, bool force)
{
struct tdb_print_db *pdb = NULL;
TDB_CONTEXT *tdb = NULL;
const char *printername;
- uint32 mypid = (uint32)sys_getpid();
+ uint32_t mypid = (uint32_t)getpid();
bool ret = False;
size_t i;
struct tdb_print_db *pdb = NULL;
TDB_CONTEXT *tdb = NULL;
const char *printername;
- uint32 mypid = (uint32)sys_getpid();
+ uint32_t mypid = (uint32_t)getpid();
size_t i;
bool ret = False;
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())
+ if (!pjob || pjob->spooled || pjob->pid != getpid())
return NULL;
return pjob->filename;
}
struct printjob *pjob;
pjob = print_job_find(sharename, jobid);
- if (!pjob || pjob->pid != sys_getpid())
+ if (!pjob || pjob->pid != getpid())
return False;
fstrcpy(pjob->jobname, name);
struct printjob *pjob;
pjob = print_job_find(sharename, jobid);
- if (!pjob || pjob->pid != sys_getpid()) {
+ if (!pjob || pjob->pid != getpid()) {
return false;
}
Return true if the current user owns the print job.
****************************************************************************/
-static bool is_owner(const struct auth_serversupplied_info *server_info,
+static bool is_owner(const struct auth_session_info *server_info,
const char *servicename,
uint32 jobid)
{
if (!pjob || !server_info)
return False;
- return strequal(pjob->user, server_info->sanitized_username);
+ return strequal(pjob->user, server_info->unix_info->sanitized_username);
}
/****************************************************************************
Delete a print job.
****************************************************************************/
-WERROR print_job_delete(const struct auth_serversupplied_info *server_info,
+WERROR print_job_delete(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32_t jobid)
{
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(server_info->utok.uid),
+ uidtoname(server_info->unix_token->uid),
lp_printername(snum) );
/* END_ADMIN_LOG */
Pause a job.
****************************************************************************/
-bool print_job_pause(const struct auth_serversupplied_info *server_info,
+bool print_job_pause(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32 jobid, WERROR *errcode)
{
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(server_info->utok.uid),
+ uidtoname(server_info->unix_token->uid),
lp_printername(snum) );
/* END_ADMIN_LOG */
Resume a job.
****************************************************************************/
-bool print_job_resume(const struct auth_serversupplied_info *server_info,
+bool print_job_resume(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx,
int snum, uint32 jobid, WERROR *errcode)
{
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(server_info->utok.uid),
+ uidtoname(server_info->unix_token->uid),
lp_printername(snum) );
/* END_ADMIN_LOG */
return False;
if (!pjob)
return -1;
/* don't allow another process to get this info - it is meaningless */
- if (pjob->pid != sys_getpid())
+ if (pjob->pid != getpid())
return -1;
/* if SMBD is spooling this can't be allowed */
Do all checks needed to determine if we can start a job.
***************************************************************************/
-static WERROR print_job_checks(const struct auth_serversupplied_info *server_info,
+static WERROR print_job_checks(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx,
int snum, int *njobs)
{
Start spooling a job - return the jobid.
***************************************************************************/
-WERROR print_job_start(const struct auth_serversupplied_info *server_info,
+WERROR print_job_start(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx,
const char *clientmachine,
int snum, const char *docname, const char *filename,
ZERO_STRUCT(pjob);
- pjob.pid = sys_getpid();
+ pjob.pid = getpid();
+ pjob.jobid = jobid;
pjob.sysjob = -1;
pjob.fd = -1;
pjob.starttime = time(NULL);
fstrcpy(pjob.clientmachine, clientmachine);
fstrcpy(pjob.user, lp_printjob_username(snum));
- standard_sub_advanced(sharename, server_info->sanitized_username,
- path, server_info->utok.gid,
- server_info->sanitized_username,
- server_info->info3->base.domain.string,
- pjob.user, sizeof(pjob.user)-1);
- /* ensure NULL termination */
- pjob.user[sizeof(pjob.user)-1] = '\0';
+ standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
+ path, server_info->unix_token->gid,
+ server_info->unix_info->sanitized_username,
+ server_info->info->domain_name,
+ pjob.user, sizeof(pjob.user));
fstrcpy(pjob.queuename, lp_const_servicename(snum));
if (!pjob)
return;
/* don't allow another process to get this info - it is meaningless */
- if (pjob->pid != sys_getpid())
+ if (pjob->pid != getpid())
return;
pjob->page_count++;
return NT_STATUS_PRINT_CANCELLED;
}
- if (pjob->spooled || pjob->pid != sys_getpid()) {
+ if (pjob->spooled || pjob->pid != getpid()) {
return NT_STATUS_ACCESS_DENIED;
}
&qtime,
queue[i].fs_user,
queue[i].fs_file);
- queue[i].job = qjob;
+ queue[i].sysjob = qjob;
queue[i].size = qsize;
queue[i].page_count = qpage_count;
queue[i].status = qstatus;
continue;
}
- queue[total_count].job = jobid;
+ queue[total_count].sysjob = jobid;
queue[total_count].size = pjob->size;
queue[total_count].page_count = pjob->page_count;
queue[total_count].status = pjob->status;
bool found = false;
for (j = 0; j < total_count; j++) {
- if (queue[j].job == jobid) {
+ if (queue[j].sysjob == jobid) {
found = true;
break;
}
continue;
}
- queue[j].job = jobid;
+ queue[j].sysjob = jobid;
queue[j].size = pjob->size;
queue[j].page_count = pjob->page_count;
queue[j].status = pjob->status;
Pause a queue.
****************************************************************************/
-WERROR print_queue_pause(const struct auth_serversupplied_info *server_info,
+WERROR print_queue_pause(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
int ret;
Resume a queue.
****************************************************************************/
-WERROR print_queue_resume(const struct auth_serversupplied_info *server_info,
+WERROR print_queue_resume(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
int ret;
Purge a queue - implemented by deleting all jobs that we can delete.
****************************************************************************/
-WERROR print_queue_purge(const struct auth_serversupplied_info *server_info,
+WERROR print_queue_purge(const struct auth_session_info *server_info,
struct messaging_context *msg_ctx, int snum)
{
print_queue_struct *queue;
for (i=0;i<njobs;i++) {
bool owner = is_owner(server_info, lp_const_servicename(snum),
- queue[i].job);
+ queue[i].sysjob);
if (owner || can_job_admin) {
print_job_delete1(server_event_context(), msg_ctx,
- snum, queue[i].job);
+ snum, queue[i].sysjob);
}
}