summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2000-07-31 20:41:51 +0000
committerJeremy Allison <jra@samba.org>2000-07-31 20:41:51 +0000
commit49fcb300de40d6da8682b485fd2c51236bcbb3dd (patch)
tree22f8c92ec9d8e81f67fadf5ac3e7b0ba81cdceef
parent2759822674174007dafa84c99e77e0c5919d6c60 (diff)
downloadsamba-49fcb300de40d6da8682b485fd2c51236bcbb3dd.tar.gz
samba-49fcb300de40d6da8682b485fd2c51236bcbb3dd.tar.bz2
samba-49fcb300de40d6da8682b485fd2c51236bcbb3dd.zip
Added John Reilly's enumports/addprinter/delprinter scripting code plus the
fix for the Win9x printer drivers. Changed command names to add "command" string on the end for some consistancy with the other scripting commands. Added '%P' option to tdbpack/unpack to store long comment string. Made port name be "Samba Printer Port" if no enum port script given. Fixed prs_uint32_pre code to cope with null args. Jeremy. (This used to be commit 902ada63799cf27924c72e24e7593a8c9fb5eba9)
-rw-r--r--source3/include/nt_printing.h2
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/param/loadparm.c22
-rw-r--r--source3/printing/load.c2
-rw-r--r--source3/printing/nt_printing.c71
-rw-r--r--source3/rpc_parse/parse_prs.c2
-rw-r--r--source3/rpc_parse/parse_spoolss.c4
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c296
-rw-r--r--source3/smbd/lanman.c92
-rw-r--r--source3/tdb/tdbutil.c14
10 files changed, 359 insertions, 151 deletions
diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h
index 58a4dec3a0..04d669f822 100644
--- a/source3/include/nt_printing.h
+++ b/source3/include/nt_printing.h
@@ -239,7 +239,7 @@ typedef struct nt_printer_info_level_2
fstring sharename;
fstring portname;
fstring drivername;
- fstring comment;
+ pstring comment;
fstring location;
NT_DEVICEMODE *devmode;
fstring sepfile;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index af1c671e62..9b526608f4 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1302,6 +1302,9 @@ char *lp_configfile(void);
char *lp_smb_passwd_file(void);
char *lp_serverstring(void);
char *lp_printcapname(void);
+char *lp_enumports_cmd(void);
+char *lp_addprinter_cmd(void);
+char *lp_deleteprinter_cmd(void);
char *lp_lockdir(void);
char *lp_utmpdir(void);
char *lp_rootdir(void);
@@ -1530,6 +1533,7 @@ BOOL lp_snum_ok(int iService);
void lp_add_one_printer(char *name, char *comment);
BOOL lp_loaded(void);
void lp_killunused(BOOL (*snumused) (int));
+void lp_killservice(int iServiceIn);
BOOL lp_load(char *pszFname, BOOL global_only, BOOL save_defaults,
BOOL add_ipc);
void lp_resetnumservices(void);
@@ -1654,6 +1658,7 @@ BOOL trust_password_delete(char *domain);
/*The following definitions come from printing/load.c */
+void add_all_printers(void);
void load_printers(void);
/*The following definitions come from printing/lpq_parse.c */
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 61e38bea60..318c1ea534 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -104,6 +104,9 @@ static BOOL defaults_saved = False;
typedef struct
{
char *szPrintcapname;
+ char *szEnumPortsCommand;
+ char *szAddPrinterCommand;
+ char *szDeletePrinterCommand;
char *szLockDir;
char *szRootdir;
char *szDefaultService;
@@ -793,6 +796,10 @@ static struct parm_struct parm_table[] = {
{"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
{"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
+ {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, 0},
+ {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, 0},
+ {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, 0},
+
{"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
{"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, 0},
{"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL, NULL, FLAG_PRINT},
@@ -1317,6 +1324,9 @@ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
+FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
+FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
+FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
#ifdef WITH_UTMP
FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
@@ -3008,6 +3018,18 @@ void lp_killunused(BOOL (*snumused) (int))
/***************************************************************************
+unload a service
+***************************************************************************/
+void lp_killservice(int iServiceIn)
+{
+ if (VALID(iServiceIn))
+ {
+ iSERVICE(iServiceIn).valid = False;
+ free_service(pSERVICE(iServiceIn));
+ }
+}
+
+/***************************************************************************
save the curent values of all global and sDefault parameters into the
defaults union. This allows swat and testparm to show only the
changed (ie. non-default) parameters.
diff --git a/source3/printing/load.c b/source3/printing/load.c
index 3d50f6d42a..fbf10d22b8 100644
--- a/source3/printing/load.c
+++ b/source3/printing/load.c
@@ -25,7 +25,7 @@
/***************************************************************************
auto-load printer services
***************************************************************************/
-static void add_all_printers(void)
+void add_all_printers(void)
{
int printers = lp_servicenumber(PRINTERS_NAME);
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 2fb1cbc998..1b9fe8b15f 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -387,7 +387,6 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
fstring architecture;
- fstring clean_driver_name;
pstring new_dir;
pstring old_name;
pstring new_name;
@@ -406,10 +405,6 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
get_short_archi(architecture, driver->environment);
- /* clean up the driver's name */
- fstrcpy(clean_driver_name, driver->name);
- all_string_sub(clean_driver_name, "/", "#", 0);
-
/* connect to the print$ share under the same account as the user connected to the rpc pipe */
fstrcpy(user_name, uidtoname(user->uid));
DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
@@ -447,18 +442,22 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
slprintf(new_dir, sizeof(new_dir), "%s\\%d", architecture, driver->cversion);
mkdir_internal(conn, inbuf, outbuf, new_dir);
- slprintf(new_dir, sizeof(new_dir), "%s\\%d\\%s", architecture, driver->cversion, clean_driver_name);
- mkdir_internal(conn, inbuf, outbuf, new_dir);
-
/* move all the files, one by one,
* from archi\filexxx.yyy to
- * archi\version\driver name\filexxx.yyy
+ * archi\version\filexxx.yyy
+ *
+ * Note: drivers may list the same file name in several places. This
+ * causes problems on a second attempt to move the file. JRR
+ *
+ * Note: use the replace flag on rename_internals() call, otherwise it
+ * is very difficult to change previously installed drivers... the Windows
+ * GUI offers the user the choice to replace or keep exisitng driver. JRR
*/
DEBUG(5,("Moving file now !\n"));
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->driverpath);
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->driverpath);
- if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
+ if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
old_name, new_name ));
close_cnum(conn, user->vuid);
@@ -466,45 +465,61 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
return False;
}
+ if (!strequal(driver->datafile, driver->driverpath)) {
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->datafile);
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->datafile);
- if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
+ if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
old_name, new_name ));
close_cnum(conn, user->vuid);
unbecome_root();
return False;
}
+ }
+ if (!strequal(driver->configfile, driver->driverpath) &&
+ !strequal(driver->configfile, driver->datafile)) {
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->configfile);
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->configfile);
- if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
+ if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
old_name, new_name ));
close_cnum(conn, user->vuid);
unbecome_root();
return False;
}
+ }
+ if (!strequal(driver->helpfile, driver->driverpath) &&
+ !strequal(driver->helpfile, driver->datafile) &&
+ !strequal(driver->helpfile, driver->configfile)) {
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->helpfile);
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->helpfile);
- if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
+ if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
old_name, new_name ));
close_cnum(conn, user->vuid);
unbecome_root();
return False;
}
+ }
if (driver->dependentfiles) {
for (i=0; *driver->dependentfiles[i]; i++) {
+ if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
+ !strequal(driver->dependentfiles[i], driver->datafile) &&
+ !strequal(driver->dependentfiles[i], driver->configfile) &&
+ !strequal(driver->dependentfiles[i], driver->helpfile)) {
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->dependentfiles[i]);
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->dependentfiles[i]);
- /*
- * We don't check the error returns here as several of these
- * files may have already been moved in the list above...
- */
- rename_internals(conn, inbuf, outbuf, old_name, new_name, False);
+ if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
+ DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
+ old_name, new_name ));
+ close_cnum(conn, user->vuid);
+ unbecome_root();
+ return False;
+ }
+ }
}
}
@@ -521,7 +536,6 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
int len, buflen;
fstring architecture;
pstring directory;
- fstring clean_driver_name;
pstring temp_name;
pstring key;
char *buf;
@@ -530,16 +544,12 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
get_short_archi(architecture, driver->environment);
- /* The names are relative. We store them in the form: \print$\arch\version\printer-name\driver.xxx
+ /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
* \\server is added in the rpc server layer.
* It does make sense to NOT store the server's name in the printer TDB.
*/
- /* clean up the driver's name */
- fstrcpy(clean_driver_name, driver->name);
- all_string_sub(clean_driver_name, "/", "#", 0);
-
- slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\%s\\", architecture, driver->cversion, clean_driver_name);
+ slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
fstrcpy(temp_name, driver->driverpath);
@@ -752,12 +762,16 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
/*pstrcat(line, info3->name); pstrcat(line, ":");*/
+ trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->configfile);
pstrcat(line, ":");
+ trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->datafile);
pstrcat(line, ":");
+ trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->helpfile);
pstrcat(line, ":");
+ trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->monitorname);
pstrcat(line, ":");
pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
@@ -766,6 +780,7 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
for (i=0; info3->dependentfiles &&
*info3->dependentfiles[i]; i++) {
if (i) pstrcat(line, ","); /* don't end in a "," */
+ trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->dependentfiles[i]);
}
@@ -969,7 +984,7 @@ static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
again:
len = 0;
- len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffffffff",
+ len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
info->attributes,
info->priority,
info->default_priority,
@@ -1367,7 +1382,7 @@ static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin
fstrcpy(info.printername, sharename);
fstrcpy(info.portname, sharename);
fstrcpy(info.drivername, lp_printerdriver(snum));
- fstrcpy(info.comment, "");
+ pstrcpy(info.comment, "");
fstrcpy(info.printprocessor, "winprint");
fstrcpy(info.datatype, "RAW");
@@ -1428,7 +1443,7 @@ static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
if (!dbuf.dptr) return 1;
#endif
- len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffffffff",
+ len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
&info.attributes,
&info.priority,
&info.default_priority,
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index bf36b5b346..71806e422e 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -867,7 +867,7 @@ BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
{
*offset = ps->data_offset;
- if (UNMARSHALLING(ps)) {
+ if (UNMARSHALLING(ps) && (data32 != NULL)) {
/* reading. */
return prs_uint32(name, ps, depth, data32);
} else {
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index 2adfc65eeb..d0a745d095 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -1778,7 +1778,7 @@ BOOL new_smb_io_printer_info_2(char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *i
{
uint32 sec_offset;
prs_struct *ps=&buffer->prs;
- int i = 0;
+ uint32 dummy = 0;
prs_debug(ps, depth, desc, "new_smb_io_printer_info_2");
depth++;
@@ -1814,7 +1814,7 @@ BOOL new_smb_io_printer_info_2(char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *i
return False;
#if 1 /* JFMTEST */
- if (!prs_uint32_pre("secdesc_ptr ", ps, depth, &i, &sec_offset))
+ if (!prs_uint32_pre("secdesc_ptr ", ps, depth, &dummy, &sec_offset))
return False;
#else
if (!new_smb_io_relsecdesc("secdesc", buffer, depth, &info->secdesc))
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index c9d81e1cba..b675175544 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -28,6 +28,10 @@
extern int DEBUGLEVEL;
extern pstring global_myname;
+#ifndef SAMBA_PRINTER_PORT_NAME
+#define SAMBA_PRINTER_PORT_NAME "Samba Printer Port"
+#endif
+
#ifndef MAX_OPEN_PRINTER_EXS
#define MAX_OPEN_PRINTER_EXS 50
#endif
@@ -217,6 +221,45 @@ static BOOL delete_printer_handle(POLICY_HND *hnd)
return False;
}
+ if (*lp_deleteprinter_cmd()) {
+
+ pid_t local_pid = sys_getpid();
+ char *cmd = lp_deleteprinter_cmd();
+ char *path;
+ pstring tmp_file;
+ pstring command;
+ int ret;
+ int i;
+
+ if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ /* Printer->dev.handlename equals portname equals sharename */
+ slprintf(command, sizeof(command), "%s \"%s\"", cmd,
+ Printer->dev.handlename);
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+
+ unlink(tmp_file);
+ DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
+ ret = smbrun(command, tmp_file, False);
+ if (ret != 0) {
+ unlink(tmp_file);
+ return False;
+ }
+ DEBUGADD(10,("returned [%d]\n", ret));
+ DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
+ unlink(tmp_file);
+
+ if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
+ lp_remove_service( i );
+ lp_killservice( i );
+ return True;
+ } else
+ return False;
+ }
+
return True;
}
@@ -3204,7 +3247,7 @@ static uint32 update_printer(POLICY_HND *handle, uint32 level,
*/
if (!check_printer_ok(printer->info_2, snum)) {
- result = ERROR_ACCESS_DENIED;
+ result = ERROR_INVALID_PARAMETER;
goto done;
}
@@ -3914,46 +3957,71 @@ static void fill_port_2(PORT_INFO_2 *port, char *name)
****************************************************************************/
static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- int n_services=lp_numservices();
- int snum;
- int i=0;
-
PORT_INFO_1 *ports=NULL;
+ int i=0;
- for (snum=0; snum<n_services; snum++)
- if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
- (*returned)++;
+ if (*lp_enumports_cmd()) {
+ pid_t local_pid = sys_getpid();
+ char *cmd = lp_enumports_cmd();
+ char *path;
+ char **qlines;
+ pstring tmp_file;
+ pstring command;
+ int numlines;
+ int ret;
+
+ if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+ slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
+
+ unlink(tmp_file);
+ DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
+ ret = smbrun(command, tmp_file, False);
+ DEBUG(10,("Returned [%d]\n", ret));
+ if (ret != 0) {
+ unlink(tmp_file);
+ // Is this the best error to return here?
+ return ERROR_ACCESS_DENIED;
+ }
- if((ports=(PORT_INFO_1 *)malloc( (*returned+1) * sizeof(PORT_INFO_1) )) == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- for (snum=0; snum<n_services; snum++) {
- if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
- /*
- * Ensure this port name is unique.
- */
- int j;
+ numlines = 0;
+ qlines = file_lines_load(tmp_file, &numlines);
+ DEBUGADD(10,("Lines returned = [%d]\n", numlines));
+ DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
+ DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
+ unlink(tmp_file);
+
+ if(numlines) {
+ if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
+ DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
+ file_lines_free(qlines);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
- DEBUG(10,("enumports_level_1: port name %s\n", PRINTERNAME(snum)));
+ for (i=0; i<numlines; i++) {
+ DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
+ fill_port_1(&ports[i], qlines[i]);
+ }
- for(j = 0; j < i; j++) {
- fstring port_name;
- unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
+ file_lines_free(qlines);
+ }
- if (strequal(port_name, PRINTERNAME(snum)))
- break;
- }
+ *returned = numlines;
- if (j < i)
- continue;
+ } else {
+ *returned = 1; /* Sole Samba port returned. */
- DEBUGADD(6,("Filling port number [%d]\n", i));
- fill_port_1(&ports[i], PRINTERNAME(snum));
- i++;
- }
- }
+ if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
- *returned = i;
+ fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
+ }
/* check the required size. */
for (i=0; i<*returned; i++) {
@@ -3988,46 +4056,72 @@ static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need
static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- int n_services=lp_numservices();
- int snum;
- int i=0;
-
PORT_INFO_2 *ports=NULL;
+ int i=0;
- for (snum=0; snum<n_services; snum++)
- if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
- (*returned)++;
+ if (*lp_enumports_cmd()) {
+ pid_t local_pid = sys_getpid();
+ char *cmd = lp_enumports_cmd();
+ char *path;
+ char **qlines;
+ pstring tmp_file;
+ pstring command;
+ int numlines;
+ int ret;
+
+ if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+ slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
+
+ unlink(tmp_file);
+ DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
+ ret = smbrun(command, tmp_file, False);
+ DEBUGADD(10,("returned [%d]\n", ret));
+ if (ret != 0) {
+ unlink(tmp_file);
+ // Is this the best error to return here?
+ return ERROR_ACCESS_DENIED;
+ }
- if((ports=(PORT_INFO_2 *)malloc( (*returned+1) * sizeof(PORT_INFO_2) )) == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- for (snum=0; snum<n_services; snum++) {
- if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
- /*
- * Ensure this port name is unique.
- */
- int j;
+ numlines = 0;
+ qlines = file_lines_load(tmp_file, &numlines);
+ DEBUGADD(10,("Lines returned = [%d]\n", numlines));
+ DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
+ DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
+ unlink(tmp_file);
+
+ if(numlines) {
+ if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
+ DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
+ file_lines_free(qlines);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
- DEBUG(10,("enumports_level_2: port name %s\n", PRINTERNAME(snum)));
+ for (i=0; i<numlines; i++) {
+ DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
+ fill_port_2(&(ports[i]), qlines[i]);
+ }
- for(j = 0; j < i; j++) {
- fstring port_name;
- unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
+ file_lines_free(qlines);
+ }
- if (strequal(port_name, PRINTERNAME(snum)))
- break;
- }
+ *returned = numlines;
- if (j < i)
- continue;
+ } else {
- DEBUGADD(6,("Filling port number [%d]\n", i));
- fill_port_2(&ports[i], PRINTERNAME(snum));
- i++;
- }
- }
+ *returned = 1;
+
+ if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
- *returned = i;
+ fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
+ }
/* check the required size. */
for (i=0; i<*returned; i++) {
@@ -4083,6 +4177,68 @@ uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
/****************************************************************************
****************************************************************************/
+static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
+{
+ pid_t local_pid = sys_getpid();
+ char *cmd = lp_addprinter_cmd();
+ char *path;
+ char **qlines;
+ pstring tmp_file;
+ pstring command;
+ pstring driverlocation;
+ int numlines;
+ int ret;
+
+ if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ /* build driver path... only 9X architecture is needed for legacy reasons */
+ slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
+ global_myname);
+ /* change \ to \\ for the shell */
+ all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+ slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
+ cmd, printer->info_2->printername, printer->info_2->sharename,
+ printer->info_2->portname, printer->info_2->drivername,
+ printer->info_2->location, driverlocation);
+
+ unlink(tmp_file);
+ DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
+ ret = smbrun(command, tmp_file, False);
+ DEBUGADD(10,("returned [%d]\n", ret));
+
+ if ( ret != 0 ) {
+ unlink(tmp_file);
+ free_a_printer(&printer,2);
+ return False;
+ }
+
+ numlines = 0;
+ qlines = file_lines_load(tmp_file, &numlines);
+ DEBUGADD(10,("Lines returned = [%d]\n", numlines));
+ DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
+ DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
+ unlink(tmp_file);
+
+ if(numlines) {
+ // Set the portname to what the script says the portname should be
+ strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
+
+ // Send SIGHUP to process group... is there a better way?
+ kill(0, SIGHUP);
+ add_all_printers();
+ }
+
+ file_lines_free(qlines);
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
const SPOOL_PRINTER_INFO_LEVEL *info,
uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
@@ -4091,7 +4247,6 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
fstring name;
- fstring share_name;
int snum;
if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
@@ -4104,11 +4259,14 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
/* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
convert_printer_info(info, printer, 2);
- unistr2_to_ascii(share_name, &info->info_2->sharename, sizeof(share_name)-1);
+ if (*lp_addprinter_cmd() )
+ if ( !add_printer_hook(printer) )
+ return ERROR_ACCESS_DENIED;
- slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname, share_name);
+ slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
+ printer->info_2->sharename);
- if ((snum = print_queue_snum(share_name)) == -1) {
+ if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
free_a_printer(&printer,2);
return ERROR_ACCESS_DENIED;
}
@@ -4119,7 +4277,7 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
if (!check_printer_ok(printer->info_2, snum)) {
free_a_printer(&printer,2);
- return ERROR_ACCESS_DENIED;
+ return ERROR_INVALID_PARAMETER;
}
/* write the ASCII on disk */
@@ -4130,7 +4288,7 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
if (!open_printer_hnd(handle, name)) {
/* Handle open failed - remove addition. */
- del_a_printer(share_name);
+ del_a_printer(printer->info_2->sharename);
free_a_printer(&printer,2);
return ERROR_ACCESS_DENIED;
}
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 6cb63f18f7..ab2fd4d55d 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -495,11 +495,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
print_status_struct* status)
{
int i;
- BOOL ok = False;
+ BOOL ok;
pstring tok,driver,datafile,langmon,helpfile,datatype;
char *p;
- char **lines;
- char *line = NULL;
+ char **lines = NULL;
pstring gen_line;
/*
@@ -512,23 +511,18 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
p = gen_line;
DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
} else {
- /* didn't find driver in tdb either... oh well */
- DEBUG(10,("9x driver not found in tdb\n"));
- }
+ /* didn't find driver in tdb */
DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
snum, lp_printerdriver(snum), lp_driverfile(snum)));
lines = file_lines_load(lp_driverfile(snum),NULL);
-
if (!lines) {
- DEBUG(3,("fill_printq_info: Can't open %s - %s\n",
- lp_driverfile(snum),strerror(errno)));
+ DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
desc->errcode=NERR_notsupported;
return;
} else {
- /* lookup the long printer driver name in the file
- description */
+ /* lookup the long printer driver name in the file description */
for (i=0;lines[i] && !ok;i++) {
p = lines[i];
if (next_token(&p,tok,":",sizeof(tok)) &&
@@ -537,16 +531,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
ok = True;
}
}
+ }
- if (!ok)
- goto err;
-
- if ((line = strdup(p)) == NULL)
- goto err;
-
- p = line;
- file_lines_free(lines);
-
+ if (ok)
+ {
/* driver file name */
if (!next_token(&p,driver,":",sizeof(driver)))
goto err;
@@ -588,9 +576,11 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
PACKS(desc,"z",datatype); /* default data type */
PACKS(desc,"z",helpfile); /* helpfile name */
PACKS(desc,"z",driver); /* driver name */
+ DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum)));
DEBUG(3,("Driver:%s:\n",driver));
DEBUG(3,("Data File:%s:\n",datafile));
DEBUG(3,("Language Monitor:%s:\n",langmon));
+ DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
DEBUG(3,("Data Type:%s:\n",datatype));
DEBUG(3,("Help File:%s:\n",helpfile));
PACKI(desc,"N",count); /* number of files to copy */
@@ -607,15 +597,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
SERVICE(snum),count));
- free(line);
+ desc->errcode=NERR_Success;
+ file_lines_free(lines);
return;
+ }
err:
DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
desc->errcode=NERR_notsupported;
- if (line)
- free(line);
+ file_lines_free(lines);
}
@@ -697,64 +688,67 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
/* This function returns the number of files for a given driver */
static int get_printerdrivernumber(int snum)
{
- int i=0,ok=0;
+ int i;
+ BOOL ok;
pstring tok;
char *p;
- char **lines, *line;
+ char **lines = NULL;
pstring gen_line;
+ /*
+ * Check in the tdb *first* before checking the legacy
+ * files. This allows an NT upload to take precedence over
+ * the existing fileset. JRA.
+ */
+
+ if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum))) == True ) {
+ p = gen_line;
+ DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
+ } else {
+ /* didn't find driver in tdb */
+
DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
snum, lp_printerdriver(snum), lp_driverfile(snum)));
+
lines = file_lines_load(lp_driverfile(snum), NULL);
if (!lines) {
- DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",
- lp_driverfile(snum),strerror(errno)));
+ DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
}
else
{
- /* lookup the long printer driver name in the file
- description */
+ /* lookup the long printer driver name in the file description */
for (i=0;lines[i] && !ok;i++) {
p = lines[i];
if (next_token(&p,tok,":",sizeof(tok)) &&
(strlen(lp_printerdriver(snum)) == strlen(tok)) &&
(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
- ok=1;
+ ok = True;
}
- }
-
- if( !ok ) {
- /* no printers.def, or driver not found, check the NT driver tdb */
- if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)))==True ) {
- p = gen_line;
- DEBUG(10,("9x compatable driver line for [%s]: [%s]\n",
- lp_printerdriver(snum), gen_line));
- } else {
- /* didn't find driver in tdb either... oh well */
- DEBUG(10,("9x driver not found in tdb\n"));
- return (0);
}
}
- line = strdup(p);
- p = line;
- file_lines_free(lines);
- if (ok) {
+ if( ok ) {
/* skip 5 fields */
i = 5;
while (*p && i) {
if (*p++ == ':') i--;
}
if (!*p || i)
- return(0);
+ goto err;
/* count the number of files */
while (next_token(&p,tok,",",sizeof(tok)))
i++;
- }
- free(line);
+ file_lines_free(lines);
return(i);
+ }
+
+ err:
+
+ DEBUG(3,("Can't determine number of printer driver files\n"));
+ file_lines_free(lines);
+ return (0);
}
static BOOL api_DosPrintQGetInfo(connection_struct *conn,
diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c
index 3e973337b9..e426aa51cd 100644
--- a/source3/tdb/tdbutil.c
+++ b/source3/tdb/tdbutil.c
@@ -136,6 +136,14 @@ size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
SIVAL(buf, 0, d);
}
break;
+ case 'P':
+ s = va_arg(ap,char *);
+ w = strlen(s);
+ len = w + 1;
+ if (bufsize >= len) {
+ memcpy(buf, s, len);
+ }
+ break;
case 'f':
s = va_arg(ap,char *);
w = strlen(s);
@@ -211,6 +219,12 @@ int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
if (bufsize < len) goto no_space;
*p = (void *)IVAL(buf, 0);
break;
+ case 'P':
+ s = va_arg(ap,char *);
+ len = strlen(buf) + 1;
+ if (bufsize < len || len > sizeof(pstring)) goto no_space;
+ memcpy(s, buf, len);
+ break;
case 'f':
s = va_arg(ap,char *);
len = strlen(buf) + 1;