diff options
author | Jeremy Allison <jra@samba.org> | 2000-07-31 20:41:51 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2000-07-31 20:41:51 +0000 |
commit | 902ada63799cf27924c72e24e7593a8c9fb5eba9 (patch) | |
tree | 87e85c0029cd8dae2f517284132f11187bfc57a7 /source | |
parent | 38b07395566a2c114ccda173fb0fe88cf7683588 (diff) | |
download | samba-902ada63799cf27924c72e24e7593a8c9fb5eba9.tar.gz |
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.
Diffstat (limited to 'source')
-rw-r--r-- | source/include/nt_printing.h | 2 | ||||
-rw-r--r-- | source/include/proto.h | 5 | ||||
-rw-r--r-- | source/param/loadparm.c | 22 | ||||
-rw-r--r-- | source/printing/load.c | 2 | ||||
-rw-r--r-- | source/printing/nt_printing.c | 71 | ||||
-rw-r--r-- | source/rpc_parse/parse_prs.c | 2 | ||||
-rw-r--r-- | source/rpc_parse/parse_spoolss.c | 4 | ||||
-rw-r--r-- | source/rpc_server/srv_spoolss_nt.c | 296 | ||||
-rw-r--r-- | source/smbd/lanman.c | 92 | ||||
-rw-r--r-- | source/tdb/tdbutil.c | 14 |
10 files changed, 359 insertions, 151 deletions
diff --git a/source/include/nt_printing.h b/source/include/nt_printing.h index 58a4dec3a06..04d669f822d 100644 --- a/source/include/nt_printing.h +++ b/source/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/source/include/proto.h b/source/include/proto.h index af1c671e624..9b526608f47 100644 --- a/source/include/proto.h +++ b/source/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/source/param/loadparm.c b/source/param/loadparm.c index 61e38bea602..318c1ea5347 100644 --- a/source/param/loadparm.c +++ b/source/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/source/printing/load.c b/source/printing/load.c index 3d50f6d42a8..fbf10d22b87 100644 --- a/source/printing/load.c +++ b/source/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/source/printing/nt_printing.c b/source/printing/nt_printing.c index 2fb1cbc9981..1b9fe8b15fe 100644 --- a/source/printing/nt_printing.c +++ b/source/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/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c index bf36b5b3467..71806e422e2 100644 --- a/source/rpc_parse/parse_prs.c +++ b/source/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/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c index 2adfc65eeb8..d0a745d095d 100644 --- a/source/rpc_parse/parse_spoolss.c +++ b/source/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/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index c9d81e1cba4..b675175544a 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/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/source/smbd/lanman.c b/source/smbd/lanman.c index 6cb63f18f77..ab2fd4d55dd 100644 --- a/source/smbd/lanman.c +++ b/source/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/source/tdb/tdbutil.c b/source/tdb/tdbutil.c index 3e973337b9c..e426aa51cd9 100644 --- a/source/tdb/tdbutil.c +++ b/source/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; |