s3:smbd: use signal events for SIGTERM, SIGHUP and SIGCHLD
[metze/samba/wip.git] / source3 / printing / printing.c
index 588641358f38fea04e16d1a5c4a909d5494533b1..0721713c019da7b1126779c76982a4317c15406a 100644 (file)
@@ -7,7 +7,7 @@
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "printing.h"
 
-extern SIG_ATOMIC_T got_sig_term;
-extern SIG_ATOMIC_T reload_after_sighup;
 extern struct current_user current_user;
 extern userdom_struct current_user_info;
 
 /* Current printer interface */
-static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid);
+static bool remove_from_jobs_changed(const char* sharename, uint32 jobid);
 
 /* 
    the printing backend revolves around a tdb database that stores the
@@ -76,7 +73,7 @@ uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
        ZERO_STRUCT( jinfo );
        fstrcpy( jinfo.sharename, sharename );
        jinfo.jobid = jobid;
-       key.dptr = (char*)&jinfo;
+       key.dptr = (uint8 *)&jinfo;
        key.dsize = sizeof(jinfo);
 
        data = tdb_fetch(rap_tdb, key);
@@ -93,7 +90,7 @@ uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
        if (rap_jobid == 0)
                rap_jobid = ++next_rap_jobid;
        SSVAL(buf,0,rap_jobid);
-       data.dptr = (char*)buf;
+       data.dptr = buf;
        data.dsize = sizeof(rap_jobid);
        tdb_store(rap_tdb, key, data, TDB_REPLACE);
        tdb_store(rap_tdb, data, key, TDB_REPLACE);
@@ -103,7 +100,7 @@ uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
        return rap_jobid;
 }
 
-BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
+bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
 {
        TDB_DATA data, key;
        uint8 buf[2];
@@ -114,7 +111,7 @@ BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
                return False;
 
        SSVAL(buf,0,rap_jobid);
-       key.dptr = (char*)buf;
+       key.dptr = buf;
        key.dsize = sizeof(rap_jobid);
        data = tdb_fetch(rap_tdb, key);
        if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) ) 
@@ -149,7 +146,7 @@ static void rap_jobid_delete(const char* sharename, uint32 jobid)
        ZERO_STRUCT( jinfo );
        fstrcpy( jinfo.sharename, sharename );
        jinfo.jobid = jobid;
-       key.dptr = (char*)&jinfo;
+       key.dptr = (uint8 *)&jinfo;
        key.dsize = sizeof(jinfo);
 
        data = tdb_fetch(rap_tdb, key);
@@ -166,7 +163,7 @@ static void rap_jobid_delete(const char* sharename, uint32 jobid)
        rap_jobid = SVAL(data.dptr, 0);
        SAFE_FREE(data.dptr);
        SSVAL(buf,0,rap_jobid);
-       data.dptr = (char*)buf;
+       data.dptr = buf;
        data.dsize = sizeof(rap_jobid);
        tdb_delete(rap_tdb, key);
        tdb_delete(rap_tdb, data);
@@ -178,16 +175,14 @@ 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)
+bool print_backend_init(struct messaging_context *msg_ctx)
 {
        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);
+       unlink(cache_path("printing.tdb"));
+       mkdir(cache_path("printing"),0755);
 
        /* handle a Samba upgrade */
 
@@ -205,7 +200,7 @@ BOOL print_backend_init(void)
                        return False;
                }
                if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
-                       tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
+                       tdb_wipe_all(pdb->tdb);
                        tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
                }
                tdb_unlock_bystring(pdb->tdb, sversion);
@@ -215,7 +210,7 @@ BOOL print_backend_init(void)
        close_all_print_db(); /* Don't leave any open. */
 
        /* do NT print initialization... */
-       return nt_printing_init();
+       return nt_printing_init(msg_ctx);
 }
 
 /****************************************************************************
@@ -267,14 +262,13 @@ static struct printif *get_printer_fns( int snum )
  Useful function to generate a tdb key.
 ****************************************************************************/
 
-static TDB_DATA print_key(uint32 jobid)
+static TDB_DATA print_key(uint32 jobid, uint32 *tmp)
 {
-       static uint32 j;
        TDB_DATA ret;
 
-       SIVAL(&j, 0, jobid);
-       ret.dptr = (char *)&j;
-       ret.dsize = sizeof(j);
+       SIVAL(tmp, 0, jobid);
+       ret.dptr = (uint8 *)tmp;
+       ret.dsize = sizeof(*tmp);
        return ret;
 }
 
@@ -282,7 +276,7 @@ static TDB_DATA print_key(uint32 jobid)
  unpack a pjob from a tdb buffer 
 ***********************************************************************/
  
-int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
+int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
 {
        int     len = 0;
        int     used;
@@ -336,9 +330,10 @@ int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
 {
        static struct printjob  pjob;
+       uint32_t tmp;
        TDB_DATA                ret;
        struct tdb_print_db     *pdb = get_print_db_byname(sharename);
-       
+
        DEBUG(10,("print_job_find: looking up job %u for share %s\n",
                        (unsigned int)jobid, sharename ));
 
@@ -346,26 +341,26 @@ static struct printjob *print_job_find(const char *sharename, uint32 jobid)
                return NULL;
        }
 
-       ret = tdb_fetch(pdb->tdb, print_key(jobid));
+       ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
        release_print_db(pdb);
 
        if (!ret.dptr) {
                DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
                return NULL;
        }
-       
+
        if ( pjob.nt_devmode ) {
                free_nt_devicemode( &pjob.nt_devmode );
        }
-               
+
        ZERO_STRUCT( pjob );
-       
+
        if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
                DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
                SAFE_FREE(ret.dptr);
                return NULL;
        }
-       
+
        SAFE_FREE(ret.dptr);
 
        DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
@@ -376,13 +371,17 @@ static struct printjob *print_job_find(const char *sharename, uint32 jobid)
 
 /* Convert a unix jobid to a smb jobid */
 
-static uint32 sysjob_to_jobid_value;
+struct unixjob_traverse_state {
+       int sysjob;
+       uint32 sysjob_to_jobid_value;
+};
 
 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
-                              TDB_DATA data, void *state)
+                              TDB_DATA data, void *private_data)
 {
        struct printjob *pjob;
-       int *sysjob = (int *)state;
+       struct unixjob_traverse_state *state =
+               (struct unixjob_traverse_state *)private_data;
 
        if (!data.dptr || data.dsize == 0)
                return 0;
@@ -391,10 +390,10 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
        if (key.dsize != sizeof(uint32))
                return 0;
 
-       if (*sysjob == pjob->sysjob) {
+       if (state->sysjob == pjob->sysjob) {
                uint32 jobid = IVAL(key.dptr,0);
 
-               sysjob_to_jobid_value = jobid;
+               state->sysjob_to_jobid_value = jobid;
                return 1;
        }
 
@@ -410,8 +409,10 @@ uint32 sysjob_to_jobid(int unix_jobid)
 {
        int services = lp_numservices();
        int snum;
+       struct unixjob_traverse_state state;
 
-       sysjob_to_jobid_value = (uint32)-1;
+       state.sysjob = unix_jobid;
+       state.sysjob_to_jobid_value = (uint32)-1;
 
        for (snum = 0; snum < services; snum++) {
                struct tdb_print_db *pdb;
@@ -421,10 +422,10 @@ uint32 sysjob_to_jobid(int unix_jobid)
                if (!pdb) {
                        continue;
                }
-               tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
+               tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
                release_print_db(pdb);
-               if (sysjob_to_jobid_value != (uint32)-1)
-                       return sysjob_to_jobid_value;
+               if (state.sysjob_to_jobid_value != (uint32)-1)
+                       return state.sysjob_to_jobid_value;
        }
        return (uint32)-1;
 }
@@ -433,7 +434,7 @@ uint32 sysjob_to_jobid(int unix_jobid)
  Send notifications based on what has changed after a pjob_store.
 ****************************************************************************/
 
-static struct {
+static const struct {
        uint32 lpq_status;
        uint32 spoolss_status;
 } lpq_to_spoolss_status_map[] = {
@@ -470,7 +471,7 @@ static uint32 map_to_spoolss_status(uint32 lpq_status)
 static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
                              struct printjob *new_data)
 {
-       BOOL new_job = False;
+       bool new_job = False;
 
        if (!old_data)
                new_job = True;
@@ -513,12 +514,13 @@ static void pjob_store_notify(const char* sharename, uint32 jobid, struct printj
  Store a job structure back to the database.
 ****************************************************************************/
 
-static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
+static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
 {
+       uint32_t tmp;
        TDB_DATA                old_data, new_data;
-       BOOL                    ret = False;
+       bool                    ret = False;
        struct tdb_print_db     *pdb = get_print_db_byname(sharename);
-       char                    *buf = NULL;
+       uint8                   *buf = NULL;
        int                     len, newlen, buflen;
        
 
@@ -527,7 +529,7 @@ static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
 
        /* Get old data */
 
-       old_data = tdb_fetch(pdb->tdb, print_key(jobid));
+       old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
 
        /* Doh!  Now we have to pack/unpack data since the NT_DEVICEMODE was added */
 
@@ -554,7 +556,7 @@ static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
                len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
        
                if (buflen != len) {
-                       buf = (char *)SMB_REALLOC(buf, len);
+                       buf = (uint8 *)SMB_REALLOC(buf, len);
                        if (!buf) {
                                DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
                                goto done;
@@ -568,7 +570,8 @@ static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
 
        new_data.dptr = buf;
        new_data.dsize = len;
-       ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
+       ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
+                        TDB_REPLACE) == 0);
 
        release_print_db(pdb);
 
@@ -604,6 +607,7 @@ done:
 
 void pjob_delete(const char* sharename, uint32 jobid)
 {
+       uint32_t tmp;
        struct printjob *pjob;
        uint32 job_status = 0;
        struct tdb_print_db *pdb;
@@ -631,7 +635,7 @@ void pjob_delete(const char* sharename, uint32 jobid)
        
        /* Remove from printing.tdb */
 
-       tdb_delete(pdb->tdb, print_key(jobid));
+       tdb_delete(pdb->tdb, print_key(jobid, &tmp));
        remove_from_jobs_changed(sharename, jobid);
        release_print_db( pdb );
        rap_jobid_delete(sharename, jobid);
@@ -867,8 +871,7 @@ static pid_t get_updating_pid(const char *sharename)
        if (!pdb)
                return (pid_t)-1;
        slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
-       key.dptr = keystr;
-       key.dsize = strlen(keystr);
+       key = string_tdb_data(keystr);
 
        data = tdb_fetch(pdb->tdb, key);
        release_print_db(pdb);
@@ -891,7 +894,7 @@ static pid_t get_updating_pid(const char *sharename)
  in the tdb.
 ****************************************************************************/
 
-static void set_updating_pid(const fstring sharename, BOOL updating)
+static void set_updating_pid(const fstring sharename, bool updating)
 {
        fstring keystr;
        TDB_DATA key;
@@ -905,8 +908,7 @@ static void set_updating_pid(const fstring sharename, BOOL updating)
                return;
 
        slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
-       key.dptr = keystr;
-       key.dsize = strlen(keystr);
+       key = string_tdb_data(keystr);
        
        DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n", 
                updating ? "" : "not ",
@@ -919,7 +921,7 @@ static void set_updating_pid(const fstring sharename, BOOL updating)
        }
        
        SIVAL( buffer, 0, updating_pid);
-       data.dptr = (char *)buffer;
+       data.dptr = buffer;
        data.dsize = 4;         /* we always assume this is a 4 byte value */
 
        tdb_store(pdb->tdb, key, data, TDB_REPLACE);    
@@ -960,7 +962,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
        print_queue_struct *queue = pts->queue;
        size_t len;
        size_t i;
-       uint qcount;
+       unsigned int qcount;
 
        if (max_reported_jobs && (max_reported_jobs < pts->qcount))
                pts->qcount = max_reported_jobs;
@@ -986,7 +988,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
                                queue[i].fs_file);
        }
 
-       if ((data.dptr = (char *)SMB_MALLOC(data.dsize)) == NULL)
+       if ((data.dptr = (uint8 *)SMB_MALLOC(data.dsize)) == NULL)
                return;
 
         len = 0;
@@ -1045,12 +1047,12 @@ static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid
  Check if the print queue has been updated recently enough.
 ****************************************************************************/
 
-static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
+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;
+       bool result = False;
 
        if (!pdb)
                return False;
@@ -1233,11 +1235,10 @@ static void print_queue_update_internal( const char *sharename,
 
        /* store the new queue status structure */
        slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
-       key.dptr = keystr;
-       key.dsize = strlen(keystr);
+       key = string_tdb_data(keystr);
 
        status.qcount = qcount;
-       data.dptr = (char *)&status;
+       data.dptr = (uint8 *)&status;
        data.dsize = sizeof(status);
        tdb_store(pdb->tdb, key, data, TDB_REPLACE);    
 
@@ -1351,22 +1352,26 @@ static void print_queue_update_with_lock( const char *sharename,
 /****************************************************************************
 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,
-                               void *private_data)
+static void print_queue_receive(struct messaging_context *msg,
+                               void *private_data,
+                               uint32_t msg_type,
+                               struct server_id server_id,
+                               DATA_BLOB *data)
 {
        fstring sharename;
-       pstring lpqcommand, lprmcommand;
+       char *lpqcommand = NULL, *lprmcommand = NULL;
        int printing_type;
        size_t len;
 
-       len = tdb_unpack( (char *)buf, msglen, "fdPP",
+       len = tdb_unpack( (uint8 *)data->data, data->length, "fdPP",
                sharename,
                &printing_type,
-               lpqcommand,
-               lprmcommand );
+               &lpqcommand,
+               &lprmcommand );
 
        if ( len == -1 ) {
+               SAFE_FREE(lpqcommand);
+               SAFE_FREE(lprmcommand);
                DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
                return;
        }
@@ -1375,6 +1380,8 @@ static void print_queue_receive(int msg_type, struct process_id src,
                get_printer_fns_from_type((enum printing_types)printing_type),
                lpqcommand, lprmcommand );
 
+       SAFE_FREE(lpqcommand);
+       SAFE_FREE(lprmcommand);
        return;
 }
 
@@ -1385,7 +1392,19 @@ main thread of the background lpq updater
 ****************************************************************************/
 void start_background_queue(void)
 {
+       /* 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) {
@@ -1397,90 +1416,150 @@ void start_background_queue(void)
                /* Child. */
                DEBUG(5,("start_background_queue: background LPQ thread started\n"));
 
-               claim_connection( NULL, "smbd lpq backend", 0, False, 
+               close(pause_pipe[0]);
+               pause_pipe[0] = -1;
+
+               if (!reinit_after_fork(smbd_messaging_context(),
+                                      smbd_event_context(), true)) {
+                       DEBUG(0,("reinit_after_fork() failed\n"));
+                       smb_panic("reinit_after_fork() failed");
+               }
+
+               smbd_setup_sig_term_handler();
+               smbd_setup_sig_hup_handler();
+
+               claim_connection( NULL, "smbd lpq backend",
                        FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
 
-               if (!locking_init(0)) {
+               if (!locking_init()) {
                        exit(1);
                }
 
-               message_register(MSG_PRINTER_UPDATE, print_queue_receive,
-                                NULL);
-               
+               messaging_register(smbd_messaging_context(), NULL,
+                                  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) {
+                       fd_set r_fds, w_fds;
+                       int ret;
+                       struct timeval to;
+                       int maxfd = 0;
+
+                       /* Process a signal and timed events now... */
+                       if (run_events(smbd_event_context(), 0, NULL, NULL)) {
+                               continue;
+                       }
+
+                       to.tv_sec = SMBD_SELECT_TIMEOUT;
+                       to.tv_usec = 0;
+
+                       /*
+                        * Setup the select fd sets.
+                        */
+
+                       FD_ZERO(&r_fds);
+                       FD_ZERO(&w_fds);
+
+                       /*
+                        * Are there any timed events waiting ? If so, ensure we don't
+                        * select for longer than it would take to wait for them.
+                        */
+
+                       {
+                               struct timeval now;
+                               GetTimeOfDay(&now);
+
+                               event_add_to_select_args(smbd_event_context(), &now,
+                                                        &r_fds, &w_fds, &to, &maxfd);
+                       }
+
+                       FD_SET(pause_pipe[1], &r_fds);
+                       maxfd = MAX(pause_pipe[1], maxfd);
+
+                       ret = sys_select(maxfd, &r_fds, &w_fds, NULL, &to);
+
+                       /* If pause_pipe[1] is closed it means the parent smbd
+                        * and children exited or aborted. */
+                       if (ret == 1 && FD_ISSET(pause_pipe[1], &r_fds)) {
                                 exit_server_cleanly(NULL);
-                        }
-
-                        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);
+                       }
+
+                       if (run_events(smbd_event_context(), ret, &r_fds, &w_fds)) {
+                               continue;
+                       }
                }
        }
+
+       close(pause_pipe[1]);
 }
 
 /****************************************************************************
 update the internal database from the system print queue for a queue
 ****************************************************************************/
 
-static void print_queue_update(int snum, BOOL force)
+static void print_queue_update(int snum, bool force)
 {
        fstring key;
        fstring sharename;
-       pstring lpqcommand, lprmcommand;
-       char *buffer = NULL;
+       char *lpqcommand = NULL;
+       char *lprmcommand = NULL;
+       uint8 *buffer = NULL;
        size_t len = 0;
        size_t newlen;
        struct tdb_print_db *pdb;
        int type;
        struct printif *current_printif;
+       TALLOC_CTX *ctx = talloc_tos();
 
        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, False );
-       standard_sub_advanced(lp_servicename(snum),
-                             current_user_info.unix_name, "",
-                             current_user.ut.gid,
-                             get_current_username(),
-                             current_user_info.domain,
-                             lpqcommand, sizeof(lpqcommand) );
-       
-       pstrcpy( lprmcommand, lp_lprmcommand(snum));
-       string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), 
-                    False, False, False );
-       standard_sub_advanced(lp_servicename(snum),
-                             current_user_info.unix_name, "",
-                             current_user.ut.gid,
-                             get_current_username(),
-                             current_user_info.domain,
-                             lprmcommand, sizeof(lprmcommand) );
-       
-       /* 
-        * Make sure that the background queue process exists.  
-        * Otherwise just do the update ourselves 
+
+       lpqcommand = talloc_string_sub2(ctx,
+                       lp_lpqcommand(snum),
+                       "%p",
+                       PRINTERNAME(snum),
+                       false, false, false);
+       if (!lpqcommand) {
+               return;
+       }
+       lpqcommand = talloc_sub_advanced(ctx,
+                       lp_servicename(snum),
+                       current_user_info.unix_name,
+                       "",
+                       current_user.ut.gid,
+                       get_current_username(),
+                       current_user_info.domain,
+                       lpqcommand);
+       if (!lpqcommand) {
+               return;
+       }
+
+       lprmcommand = talloc_string_sub2(ctx,
+                       lp_lprmcommand(snum),
+                       "%p",
+                       PRINTERNAME(snum),
+                       false, false, false);
+       if (!lprmcommand) {
+               return;
+       }
+       lprmcommand = talloc_sub_advanced(ctx,
+                       lp_servicename(snum),
+                       current_user_info.unix_name,
+                       "",
+                       current_user.ut.gid,
+                       get_current_username(),
+                       current_user_info.domain,
+                       lprmcommand);
+       if (!lprmcommand) {
+               return;
+       }
+
+       /*
+        * 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 );
@@ -1490,16 +1569,16 @@ static void print_queue_update(int snum, BOOL force)
        }
 
        type = lp_printing(snum);
-       
+
        /* get the length */
 
        len = tdb_pack( NULL, 0, "fdPP",
                sharename,
                type,
-               lpqcommand, 
+               lpqcommand,
                lprmcommand );
 
-       buffer = SMB_XMALLOC_ARRAY( char, len );
+       buffer = SMB_XMALLOC_ARRAY( uint8, len );
 
        /* now pack the buffer */
        newlen = tdb_pack( buffer, len, "fdPP",
@@ -1537,8 +1616,9 @@ static void print_queue_update(int snum, BOOL force)
 
        /* finally send the message */
        
-       message_send_pid(pid_to_procid(background_lpq_updater_pid),
-                MSG_PRINTER_UPDATE, buffer, len, False);
+       messaging_send_buf(smbd_messaging_context(),
+                          pid_to_procid(background_lpq_updater_pid),
+                          MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
 
        SAFE_FREE( buffer );
 
@@ -1550,14 +1630,14 @@ static void print_queue_update(int snum, BOOL force)
  updates only to interested smbd's. 
 ****************************************************************************/
 
-BOOL print_notify_register_pid(int snum)
+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;
+       bool ret = False;
        size_t i;
 
        /* if (snum == -1), then the change notify request was
@@ -1607,7 +1687,7 @@ BOOL print_notify_register_pid(int snum)
 
        if (i == data.dsize) {
                /* We weren't in the list. Realloc. */
-               data.dptr = (char *)SMB_REALLOC(data.dptr, data.dsize + 8);
+               data.dptr = (uint8 *)SMB_REALLOC(data.dptr, data.dsize + 8);
                if (!data.dptr) {
                        DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
                                                printername));
@@ -1641,7 +1721,7 @@ list for printer %s\n", printername));
  updates only to interested smbd's. 
 ****************************************************************************/
 
-BOOL print_notify_deregister_pid(int snum)
+bool print_notify_deregister_pid(int snum)
 {
        TDB_DATA data;
        struct tdb_print_db *pdb = NULL;
@@ -1649,7 +1729,7 @@ BOOL print_notify_deregister_pid(int snum)
        const char *printername;
        uint32 mypid = (uint32)sys_getpid();
        size_t i;
-       BOOL ret = False;
+       bool ret = False;
 
        /* if ( snum == -1 ), we are deregister a print server handle
           which means to deregister on all print queues */
@@ -1730,14 +1810,15 @@ list for printer %s\n", printername));
  Check if a jobid is valid. It is valid if it exists in the database.
 ****************************************************************************/
 
-BOOL print_job_exists(const char* sharename, uint32 jobid)
+bool print_job_exists(const char* sharename, uint32 jobid)
 {
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
-       BOOL ret;
+       bool ret;
+       uint32_t tmp;
 
        if (!pdb)
                return False;
-       ret = tdb_exists(pdb->tdb, print_key(jobid));
+       ret = tdb_exists(pdb->tdb, print_key(jobid, &tmp));
        release_print_db(pdb);
        return ret;
 }
@@ -1792,7 +1873,7 @@ NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
  Set the place in the queue for a job.
 ****************************************************************************/
 
-BOOL print_job_set_place(const char *sharename, uint32 jobid, int place)
+bool print_job_set_place(const char *sharename, uint32 jobid, int place)
 {
        DEBUG(2,("print_job_set_place not implemented yet\n"));
        return False;
@@ -1802,7 +1883,7 @@ BOOL print_job_set_place(const char *sharename, uint32 jobid, int place)
  Set the name of a job. Only possible for owner.
 ****************************************************************************/
 
-BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name)
+bool print_job_set_name(const char *sharename, uint32 jobid, char *name)
 {
        struct printjob *pjob;
 
@@ -1818,13 +1899,13 @@ BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name)
  Remove a jobid from the 'jobs changed' list.
 ***************************************************************************/
 
-static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid)
+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;
+       bool ret = False;
+       bool gotlock = False;
 
        if (!pdb) {
                return False;
@@ -1877,7 +1958,7 @@ static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid)
  Delete a print job - don't update queue.
 ****************************************************************************/
 
-static BOOL print_job_delete1(int snum, uint32 jobid)
+static bool print_job_delete1(int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob = print_job_find(sharename, jobid);
@@ -1940,42 +2021,39 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
  Return true if the current user owns the print job.
 ****************************************************************************/
 
-static BOOL is_owner(struct current_user *user, const char *servicename,
+static bool is_owner(struct auth_serversupplied_info *server_info,
+                    const char *servicename,
                     uint32 jobid)
 {
        struct printjob *pjob = print_job_find(servicename, jobid);
-       user_struct *vuser;
 
-       if (!pjob || !user)
+       if (!pjob || !server_info)
                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->ut.uid));
-       }
+       return strequal(pjob->user, server_info->sanitized_username);
 }
 
 /****************************************************************************
  Delete a print job.
 ****************************************************************************/
 
-BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
+bool print_job_delete(struct auth_serversupplied_info *server_info, int snum,
+                     uint32 jobid, WERROR *errcode)
 {
        const char* sharename = lp_const_servicename( snum );
        struct printjob *pjob;
-       BOOL    owner;
+       bool    owner;
        char    *fname;
 
        *errcode = WERR_OK;
                
-       owner = is_owner(user, lp_const_servicename(snum), jobid);
+       owner = is_owner(server_info, lp_const_servicename(snum), jobid);
        
        /* Check access against security descriptor or whether the user
           owns their job. */
 
        if (!owner && 
-           !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
+           !print_access_check(server_info, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("delete denied by security descriptor\n"));
                *errcode = WERR_ACCESS_DENIED;
 
@@ -1983,7 +2061,8 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR
                sys_adminlog( LOG_ERR, 
                              "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                             uidtoname(user->ut.uid), PRINTERNAME(snum) );
+                             uidtoname(server_info->utok.uid),
+                             PRINTERNAME(snum) );
                /* END_ADMIN_LOG */
 
                return False;
@@ -2027,7 +2106,8 @@ pause, or resume print job. User name: %s. Printer name: %s.",
  Pause a job.
 ****************************************************************************/
 
-BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
+bool print_job_pause(struct auth_serversupplied_info *server_info, int snum,
+                    uint32 jobid, WERROR *errcode)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
@@ -2036,7 +2116,7 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *
 
        pjob = print_job_find(sharename, jobid);
        
-       if (!pjob || !user) {
+       if (!pjob || !server_info) {
                DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
                return False;
@@ -2048,15 +2128,16 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *
                return False;
        }
 
-       if (!is_owner(user, lp_const_servicename(snum), jobid) &&
-           !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
+       if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
+           !print_access_check(server_info, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("pause denied by security descriptor\n"));
 
                /* BEGIN_ADMIN_LOG */
                sys_adminlog( LOG_ERR, 
                        "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                               uidtoname(user->ut.uid), PRINTERNAME(snum) );
+                             uidtoname(server_info->utok.uid),
+                             PRINTERNAME(snum) );
                /* END_ADMIN_LOG */
 
                *errcode = WERR_ACCESS_DENIED;
@@ -2087,7 +2168,8 @@ pause, or resume print job. User name: %s. Printer name: %s.",
  Resume a job.
 ****************************************************************************/
 
-BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
+bool print_job_resume(struct auth_serversupplied_info *server_info, int snum,
+                     uint32 jobid, WERROR *errcode)
 {
        const char *sharename = lp_const_servicename(snum);
        struct printjob *pjob;
@@ -2095,8 +2177,8 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
        struct printif *current_printif = get_printer_fns( snum );
 
        pjob = print_job_find(sharename, jobid);
-       
-       if (!pjob || !user) {
+
+       if (!pjob || !server_info) {
                DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
                return False;
@@ -2108,8 +2190,8 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
                return False;
        }
 
-       if (!is_owner(user, lp_const_servicename(snum), jobid) &&
-           !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
+       if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
+           !print_access_check(server_info, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("resume denied by security descriptor\n"));
                *errcode = WERR_ACCESS_DENIED;
 
@@ -2117,7 +2199,8 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
                sys_adminlog( LOG_ERR, 
                         "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                       uidtoname(user->ut.uid), PRINTERNAME(snum) );
+                             uidtoname(server_info->utok.uid),
+                             PRINTERNAME(snum) );
                /* END_ADMIN_LOG */
                return False;
        }
@@ -2230,7 +2313,7 @@ int print_queue_length(int snum, print_status_struct *pstatus)
  Allocate a jobid. Hold the lock for as short a time as possible.
 ***************************************************************************/
 
-static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
+static bool allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
 {
        int i;
        uint32 jobid;
@@ -2278,10 +2361,12 @@ static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char
 
        /* Store a dummy placeholder. */
        {
+               uint32_t tmp;
                TDB_DATA dum;
                dum.dptr = NULL;
                dum.dsize = 0;
-               if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
+               if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
+                             TDB_INSERT) == -1) {
                        DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n",
                                jobid ));
                        return False;
@@ -2296,13 +2381,13 @@ static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char
  Append a jobid to the 'jobs changed' list.
 ***************************************************************************/
 
-static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
+static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
 {
        TDB_DATA data;
        uint32 store_jobid;
 
        SIVAL(&store_jobid, 0, jobid);
-       data.dptr = (char *)&store_jobid;
+       data.dptr = (uint8 *)&store_jobid;
        data.dsize = 4;
 
        DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
@@ -2315,12 +2400,12 @@ static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
  Start spooling a job - return the jobid.
 ***************************************************************************/
 
-uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
+uint32 print_job_start(struct auth_serversupplied_info *server_info, int snum,
+                      char *jobname, NT_DEVICEMODE *nt_devmode )
 {
        uint32 jobid;
        char *path;
        struct printjob pjob;
-       user_struct *vuser;
        const char *sharename = lp_const_servicename(snum);
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
        int njobs;
@@ -2330,7 +2415,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
        if (!pdb)
                return (uint32)-1;
 
-       if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
+       if (!print_access_check(server_info, snum, PRINTER_ACCESS_USE)) {
                DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
                release_print_db(pdb);
                return (uint32)-1;
@@ -2346,9 +2431,9 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
 
        /* see if we have sufficient disk space */
        if (lp_minprintspace(snum)) {
-               SMB_BIG_UINT dspace, dsize;
+               uint64_t dspace, dsize;
                if (sys_fsusage(path, &dspace, &dsize) == 0 &&
-                   dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
+                   dspace < 2*(uint64_t)lp_minprintspace(snum)) {
                        DEBUG(3, ("print_job_start: disk space check failed.\n"));
                        release_print_db(pdb);
                        errno = ENOSPC;
@@ -2395,11 +2480,14 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
        
        fstrcpy(pjob.jobname, jobname);
 
-       if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
-               fstrcpy(pjob.user, vuser->user.smb_name);
-       } else {
-               fstrcpy(pjob.user, uidtoname(user->ut.uid));
-       }
+       fstrcpy(pjob.user, lp_printjob_username(snum));
+       standard_sub_advanced(sharename, server_info->sanitized_username,
+                             path, server_info->utok.gid, 
+                             server_info->sanitized_username,
+                             pdb_get_domain(server_info->sam_account),
+                             pjob.user, sizeof(pjob.user)-1);
+       /* ensure NULL termination */
+       pjob.user[sizeof(pjob.user)-1] = '\0';
 
        fstrcpy(pjob.queuename, lp_const_servicename(snum));
 
@@ -2469,7 +2557,7 @@ void print_job_endpage(int snum, uint32 jobid)
  error.
 ****************************************************************************/
 
-BOOL print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
+bool print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
@@ -2521,7 +2609,7 @@ BOOL print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
        if (ret)
                goto fail;
 
-       /* The print job has been sucessfully handed over to the back-end */
+       /* The print job has been successfully handed over to the back-end */
        
        pjob->spooled = True;
        pjob->status = LPQ_QUEUED;
@@ -2535,7 +2623,7 @@ BOOL print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
 
 fail:
 
-       /* The print job was not succesfully started. Cleanup */
+       /* The print job was not successfully started. Cleanup */
        /* Still need to add proper error return propagation! 010122:JRR */
        unlink(pjob->filename);
        pjob_delete(sharename, jobid);
@@ -2546,7 +2634,7 @@ fail:
  Get a snapshot of jobs in the system without traversing.
 ****************************************************************************/
 
-static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
+static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
 {
        TDB_DATA data, cgdata;
        print_queue_struct *queue = NULL;
@@ -2556,7 +2644,7 @@ static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
        size_t len = 0;
        uint32 i;
        int max_reported_jobs = lp_max_reported_jobs(snum);
-       BOOL ret = False;
+       bool ret = False;
        const char* sharename = lp_servicename(snum);
 
        /* make sure the database is up to date */
@@ -2697,8 +2785,8 @@ int print_queue_status(int snum,
 
        ZERO_STRUCTP(status);
        slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
-       key.dptr = keystr;
-       key.dsize = strlen(keystr);
+       key = string_tdb_data(keystr);
+
        data = tdb_fetch(pdb->tdb, key);
        if (data.dptr) {
                if (data.dsize == sizeof(*status)) {
@@ -2727,12 +2815,14 @@ int print_queue_status(int snum,
  Pause a queue.
 ****************************************************************************/
 
-BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
+bool print_queue_pause(struct auth_serversupplied_info *server_info, int snum,
+                      WERROR *errcode)
 {
        int ret;
        struct printif *current_printif = get_printer_fns( snum );
        
-       if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
+       if (!print_access_check(server_info, snum,
+                               PRINTER_ACCESS_ADMINISTER)) {
                *errcode = WERR_ACCESS_DENIED;
                return False;
        }
@@ -2763,12 +2853,14 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
  Resume a queue.
 ****************************************************************************/
 
-BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
+bool print_queue_resume(struct auth_serversupplied_info *server_info, int snum,
+                       WERROR *errcode)
 {
        int ret;
        struct printif *current_printif = get_printer_fns( snum );
 
-       if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
+       if (!print_access_check(server_info, snum,
+                               PRINTER_ACCESS_ADMINISTER)) {
                *errcode = WERR_ACCESS_DENIED;
                return False;
        }
@@ -2799,24 +2891,27 @@ BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
  Purge a queue - implemented by deleting all jobs that we can delete.
 ****************************************************************************/
 
-BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
+bool print_queue_purge(struct auth_serversupplied_info *server_info, int snum,
+                      WERROR *errcode)
 {
        print_queue_struct *queue;
        print_status_struct status;
        int njobs, i;
-       BOOL can_job_admin;
+       bool can_job_admin;
 
        /* Force and update so the count is accurate (i.e. not a cached count) */
        print_queue_update(snum, True);
        
-       can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
+       can_job_admin = print_access_check(server_info, snum,
+                                          JOB_ACCESS_ADMINISTER);
        njobs = print_queue_status(snum, &queue, &status);
        
        if ( can_job_admin )
                become_root();
 
        for (i=0;i<njobs;i++) {
-               BOOL owner = is_owner(user, lp_const_servicename(snum), queue[i].job);
+               bool owner = is_owner(server_info, lp_const_servicename(snum),
+                                     queue[i].job);
 
                if (owner || can_job_admin) {
                        print_job_delete1(snum, queue[i].job);