summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-11-26 00:46:31 +0000
committerGerald Carter <jerry@samba.org>2002-11-26 00:46:31 +0000
commitafc5f1aefbddf68252f4b9a0a2cee2d5601d8057 (patch)
tree54a37b79338a875e6375a276540768587d73b77c
parent3ab6fcc5c6160d322bdfd2ca771dcf7954e92df7 (diff)
downloadsamba-afc5f1aefbddf68252f4b9a0a2cee2d5601d8057.tar.gz
samba-afc5f1aefbddf68252f4b9a0a2cee2d5601d8057.tar.bz2
samba-afc5f1aefbddf68252f4b9a0a2cee2d5601d8057.zip
[print notify fixes from APP_HEAD]
* fixing change notify on print server handle * adding change notify support into smbcontrol for sending comment changes, etc... All part of CR 1159/1160 (This used to be commit f1062e79de8a3046c6e3f22b3d1a4819afe6809b)
-rw-r--r--source3/Makefile.in8
-rw-r--r--source3/include/printing.h16
-rw-r--r--source3/printing/notify.c87
-rw-r--r--source3/printing/printing.c314
-rw-r--r--source3/utils/smbcontrol.c52
5 files changed, 191 insertions, 286 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index f9b4b48346..5973faa330 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -283,7 +283,8 @@ PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
printing/print_cups.o printing/print_generic.o \
printing/lpq_parse.o printing/load.o
-PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o printing/notify.o
+PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o printing/notify.o \
+ printing/printing_db.o
MSDFS_OBJ = msdfs/msdfs.o
@@ -325,7 +326,8 @@ STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ)
SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
- $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
+ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) printing/notify.o \
+ printing/printing_db.o
SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ)
@@ -682,7 +684,7 @@ bin/smbstatus: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy
bin/smbcontrol: $(SMBCONTROL_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(SMBCONTROL_OBJ) $(LDFLAGS) $(LIBS)
+ @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ $(SMBCONTROL_OBJ) $(LDFLAGS) $(LIBS)
bin/smbtree: $(SMBTREE_OBJ) bin/.dummy
@echo Linking $@
diff --git a/source3/include/printing.h b/source3/include/printing.h
index 38ff7eac36..1d658a0768 100644
--- a/source3/include/printing.h
+++ b/source3/include/printing.h
@@ -74,4 +74,20 @@ extern struct printif cups_printif;
#define PRINT_SPOOL_PREFIX "smbprn."
#define PRINT_DATABASE_VERSION 5
+/* There can be this many printing tdb's open, plus any locked ones. */
+#define MAX_PRINT_DBS_OPEN 1
+
+struct tdb_print_db {
+ struct tdb_print_db *next, *prev;
+ TDB_CONTEXT *tdb;
+ int ref_count;
+ fstring printer_name;
+};
+
+/*
+ * Used for print notify
+ */
+
+#define NOTIFY_PID_LIST_KEY "NOTIFY_PID_LIST"
+
#endif /* PRINTING_H_ */
diff --git a/source3/printing/notify.c b/source3/printing/notify.c
index a4111831d9..f55dbff47e 100644
--- a/source3/printing/notify.c
+++ b/source3/printing/notify.c
@@ -31,6 +31,18 @@ static struct notify_queue {
size_t buflen;
} *notify_queue_head = NULL;
+/****************************************************************************
+ Turn a queue name into a snum.
+****************************************************************************/
+
+int print_queue_snum(const char *qname)
+{
+ int snum = lp_servicenumber(qname);
+ if (snum == -1 || !lp_print_ok(snum))
+ return -1;
+ return snum;
+}
+
/*******************************************************************
Used to decide if we need a short select timeout.
*******************************************************************/
@@ -362,3 +374,78 @@ void notify_printer_location(int snum, char *location)
printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,
snum, strlen(location) + 1, location);
}
+
+void notify_printer_byname( char *printername, uint32 change, char *value )
+{
+ int snum = print_queue_snum(printername);
+ int type = PRINTER_NOTIFY_TYPE;
+
+ if ( snum == -1 )
+ return;
+
+ send_notify_field_buffer( printername, type, change, snum, strlen(value), value );
+}
+
+
+/****************************************************************************
+ Return a malloced list of pid_t's that are interested in getting update
+ messages on this print queue. Used in printing/notify to send the messages.
+****************************************************************************/
+
+BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t *p_num_pids, pid_t **pp_pid_list)
+{
+ struct tdb_print_db *pdb = NULL;
+ TDB_CONTEXT *tdb = NULL;
+ TDB_DATA data;
+ BOOL ret = True;
+ size_t i, num_pids, offset;
+ pid_t *pid_list;
+
+ *p_num_pids = 0;
+ *pp_pid_list = NULL;
+
+ pdb = get_print_db_byname(printername);
+ if (!pdb)
+ return False;
+ tdb = pdb->tdb;
+
+ if (tdb_read_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+ DEBUG(0,("print_notify_pid_list: 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 );
+
+ if (!data.dptr) {
+ ret = True;
+ goto done;
+ }
+
+ num_pids = data.dsize / 8;
+
+ if ((pid_list = (pid_t *)talloc(mem_ctx, sizeof(pid_t) * num_pids)) == NULL) {
+ ret = False;
+ goto done;
+ }
+
+ for( i = 0, offset = 0; offset < data.dsize; offset += 8, i++)
+ pid_list[i] = (pid_t)IVAL(data.dptr, offset);
+
+ *pp_pid_list = pid_list;
+ *p_num_pids = num_pids;
+
+ ret = True;
+
+ done:
+
+ tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
+ if (pdb)
+ release_print_db(pdb);
+ SAFE_FREE(data.dptr);
+ return ret;
+}
+
+
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index a8f9097255..a6b5e5cb83 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -136,135 +136,6 @@ static pid_t local_pid;
static int get_queue_status(int, print_status_struct *);
-/* There can be this many printing tdb's open, plus any locked ones. */
-#define MAX_PRINT_DBS_OPEN 1
-
-struct tdb_print_db {
- struct tdb_print_db *next, *prev;
- TDB_CONTEXT *tdb;
- int ref_count;
- fstring printer_name;
-};
-
-static struct tdb_print_db *print_db_head;
-
-/****************************************************************************
- Function to find or create the printer specific job tdb given a printername.
- Limits the number of tdb's open to MAX_PRINT_DBS_OPEN.
-****************************************************************************/
-
-static struct tdb_print_db *get_print_db_byname(const char *printername)
-{
- struct tdb_print_db *p = NULL, *last_entry = NULL;
- int num_open = 0;
- pstring printdb_path;
- BOOL done_become_root = False;
-
- for (p = print_db_head, last_entry = print_db_head; p; p = p->next) {
- /* Ensure the list terminates... JRA. */
- SMB_ASSERT(p->next != print_db_head);
-
- if (p->tdb && strequal(p->printer_name, printername)) {
- DLIST_PROMOTE(print_db_head, p);
- p->ref_count++;
- return p;
- }
- num_open++;
- last_entry = p;
- }
-
- /* Not found. */
- if (num_open >= MAX_PRINT_DBS_OPEN) {
- /* Try and recycle the last entry. */
- DLIST_PROMOTE(print_db_head, last_entry);
-
- for (p = print_db_head; p; p = p->next) {
- if (p->ref_count)
- continue;
- if (p->tdb) {
- if (tdb_close(print_db_head->tdb)) {
- DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
- print_db_head->printer_name ));
- return NULL;
- }
- }
- p->tdb = NULL;
- p->ref_count = 0;
- memset(p->printer_name, '\0', sizeof(p->printer_name));
- break;
- }
- if (p) {
- DLIST_PROMOTE(print_db_head, p);
- p = print_db_head;
- }
- }
-
- if (!p) {
- /* Create one. */
- p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db));
- if (!p) {
- DEBUG(0,("get_print_db: malloc fail !\n"));
- return NULL;
- }
- ZERO_STRUCTP(p);
- DLIST_ADD(print_db_head, p);
- }
-
- pstrcpy(printdb_path, lock_path("printing/"));
- pstrcat(printdb_path, printername);
- pstrcat(printdb_path, ".tdb");
-
- if (geteuid() != 0) {
- become_root();
- done_become_root = True;
- }
-
- p->tdb = tdb_open_log(printdb_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-
- if (done_become_root)
- unbecome_root();
-
- if (!p->tdb) {
- DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n",
- printdb_path ));
- DLIST_REMOVE(print_db_head, p);
- SAFE_FREE(p);
- return NULL;
- }
- fstrcpy(p->printer_name, printername);
- p->ref_count++;
- return p;
-}
-
-/***************************************************************************
- Remove a reference count.
-****************************************************************************/
-
-static void release_print_db( struct tdb_print_db *pdb)
-{
- pdb->ref_count--;
- SMB_ASSERT(pdb->ref_count >= 0);
-}
-
-/***************************************************************************
- Close all open print db entries.
-****************************************************************************/
-
-static void close_all_print_db(void)
-{
- struct tdb_print_db *p = NULL, *next_p = NULL;
-
- for (p = print_db_head; p; p = next_p) {
- next_p = p->next;
-
- if (p->tdb)
- tdb_close(p->tdb);
- DLIST_REMOVE(print_db_head, p);
- ZERO_STRUCTP(p);
- SAFE_FREE(p);
- }
-}
-
/****************************************************************************
Initialise the printing backend. Called once at startup before the fork().
****************************************************************************/
@@ -1047,134 +918,6 @@ static void print_queue_update(int snum)
}
/****************************************************************************
- Fetch and clean the pid_t record list for all pids interested in notify
- messages. data needs freeing on exit.
-****************************************************************************/
-
-#define NOTIFY_PID_LIST_KEY "NOTIFY_PID_LIST"
-#define PRINT_SERVER_ENTRY_NAME "___PRINT_SERVER_ENTRY___"
-
-static TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, BOOL cleanlist)
-{
- TDB_DATA data;
- size_t i;
-
- ZERO_STRUCT(data);
-
- data = tdb_fetch_by_string( tdb, NOTIFY_PID_LIST_KEY );
-
- if (!data.dptr) {
- ZERO_STRUCT(data);
- return data;
- }
-
- if (data.dsize % 8) {
- DEBUG(0,("get_printer_notify_pid_list: Size of record for printer %s not a multiple of 8 !\n", printer_name ));
- tdb_delete_by_string(tdb, NOTIFY_PID_LIST_KEY );
- SAFE_FREE(data.dptr);
- ZERO_STRUCT(data);
- return data;
- }
-
- if (!cleanlist)
- return data;
-
- /*
- * Weed out all dead entries.
- */
-
- for( i = 0; i < data.dsize; i += 8) {
- pid_t pid = (pid_t)IVAL(data.dptr, i);
-
- if (pid == sys_getpid())
- continue;
-
- /* Entry is dead if process doesn't exist or refcount is zero. */
-
- while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) {
-
- /* Refcount == zero is a logic error and should never happen. */
- if (IVAL(data.dptr, i + 4) == 0) {
- DEBUG(0,("get_printer_notify_pid_list: Refcount == 0 for pid = %u printer %s !\n",
- (unsigned int)pid, printer_name ));
- }
-
- if (data.dsize - i > 8)
- memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
- data.dsize -= 8;
- }
- }
-
- return data;
-}
-
-/****************************************************************************
- Return a malloced list of pid_t's that are interested in getting update
- messages on this print queue. Used in printing/notify to send the messages.
-****************************************************************************/
-
-BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t *p_num_pids, pid_t **pp_pid_list)
-{
- struct tdb_print_db *pdb = NULL;
- TDB_CONTEXT *tdb = NULL;
- TDB_DATA data;
- BOOL ret = True;
- size_t i, num_pids, offset;
- pid_t *pid_list;
-
- *p_num_pids = 0;
- *pp_pid_list = NULL;
-
- if (strequal(printername, PRINT_SERVER_ENTRY_NAME)) {
- pdb = NULL;
- tdb = conn_tdb_ctx();
- } else {
- pdb = get_print_db_byname(printername);
- if (!pdb)
- return False;
- tdb = pdb->tdb;
- }
-
- if (tdb_read_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
- DEBUG(0,("print_notify_pid_list: 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 );
-
- if (!data.dptr) {
- ret = True;
- goto done;
- }
-
- num_pids = data.dsize / 8;
-
- if ((pid_list = (pid_t *)talloc(mem_ctx, sizeof(pid_t) * num_pids)) == NULL) {
- ret = False;
- goto done;
- }
-
- for( i = 0, offset = 0; offset < data.dsize; offset += 8, i++)
- pid_list[i] = (pid_t)IVAL(data.dptr, offset);
-
- *pp_pid_list = pid_list;
- *p_num_pids = num_pids;
-
- ret = True;
-
- done:
-
- tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
- if (pdb)
- release_print_db(pdb);
- SAFE_FREE(data.dptr);
- return ret;
-}
-
-/****************************************************************************
Create/Update an entry in the print tdb that will allow us to send notify
updates only to interested smbd's.
****************************************************************************/
@@ -1189,16 +932,29 @@ BOOL print_notify_register_pid(int snum)
BOOL ret = False;
size_t i;
- if (snum != -1) {
+ /* 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;
- } else {
- printername = PRINT_SERVER_ENTRY_NAME;
- pdb = NULL;
- tdb = conn_tdb_ctx();
}
if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
@@ -1267,16 +1023,28 @@ BOOL print_notify_deregister_pid(int snum)
size_t i;
BOOL ret = False;
- if (snum != -1) {
+ /* 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;
- } else {
- printername = PRINT_SERVER_ENTRY_NAME;
- pdb = NULL;
- tdb = conn_tdb_ctx();
}
if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
@@ -2198,18 +1966,6 @@ int print_queue_status(int snum,
}
/****************************************************************************
- Turn a queue name into a snum.
-****************************************************************************/
-
-int print_queue_snum(const char *qname)
-{
- int snum = lp_servicenumber(qname);
- if (snum == -1 || !lp_print_ok(snum))
- return -1;
- return snum;
-}
-
-/****************************************************************************
Pause a queue.
****************************************************************************/
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index 034de91ce0..2f3bb2e0da 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -42,7 +42,7 @@ static struct {
{"dmalloc-mark", MSG_REQ_DMALLOC_MARK },
{"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED },
{"shutdown", MSG_SHUTDOWN },
- {"change_id", MSG_PRINTER_DRVUPGRADE},
+ {"drvupgrade", MSG_PRINTER_DRVUPGRADE},
{NULL, -1}
};
@@ -50,6 +50,12 @@ time_t timeout_start;
#define MAX_WAIT 10
+/* we need these because we link to printing*.o */
+
+void become_root(void) {}
+void unbecome_root(void) {}
+
+
static void usage(BOOL doexit)
{
int i;
@@ -250,6 +256,7 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
int i, n, v;
int mtype;
BOOL retval=False;
+ BOOL check_notify_msgs = False;
mtype = parse_type(msg_name);
if (mtype == -1) {
@@ -360,9 +367,7 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
break;
/* Send a notification message to a printer */
- /* NB. None of these currently work due to changes in the printing notify mechanisms. */
-#if 0
case MSG_PRINTER_NOTIFY2: {
char *cmd;
@@ -380,6 +385,8 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
cmd = params[0];
+ check_notify_msgs = True;
+
/* Pause a print queue */
if (strequal(cmd, "queuepause")) {
@@ -421,6 +428,7 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
notify_job_status_byname(
params[1], jobid, JOB_STATUS_PAUSED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
+ break;
}
/* Resume a print job */
@@ -438,6 +446,7 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
notify_job_status_byname(
params[1], jobid, JOB_STATUS_QUEUED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
+ break;
}
/* Delete a print job */
@@ -462,9 +471,39 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
}
+ /* printer change notify */
+
+ if (strequal(cmd, "printer")) {
+ int attribute = -1;
+
+ if (!params[1] || !params[2] || !params[3]) {
+ fprintf(stderr, "printer command requires an and attribute name and value!\n");
+ fprintf(stderr, "supported attributes:\n");
+ fprintf(stderr, "\tcomment:\n");
+ fprintf(stderr, "\tport:\n");
+ fprintf(stderr, "\tdriver:\n");
+ return False;
+ }
+ if ( strequal(params[2], "comment") )
+ attribute = PRINTER_NOTIFY_COMMENT;
+ else if ( strequal(params[2], "port") )
+ attribute = PRINTER_NOTIFY_PORT_NAME;
+ else if ( strequal(params[2], "driver") )
+ attribute = PRINTER_NOTIFY_DRIVER_NAME;
+
+ if ( attribute == -1 ) {
+ fprintf(stderr, "bad attribute!\n");
+ return False;
+ }
+
+ notify_printer_byname( params[1], attribute, params[3]);
+
+ break;
+ }
+
break;
}
-#endif
+
case MSG_SMB_FORCE_TDIS:
if (!strequal(dest, "smbd")) {
@@ -563,6 +602,11 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
break;
}
+ /* check if we have any pending print notify messages */
+
+ if ( check_notify_msgs )
+ print_notify_send_messages();
+
return (True);
}