1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r4539: patch from Rob -- adding real printcap name cache function to speed up printcap reloads

(This used to be commit 1cad525093)
This commit is contained in:
Gerald Carter 2005-01-05 16:20:35 +00:00 committed by Gerald (Jerry) Carter
parent 846b8d4cfd
commit d097ea4905
12 changed files with 386 additions and 567 deletions

View File

@ -397,7 +397,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
$(BUILDOPT_OBJ) $(SMBLDAP_OBJ) $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
PRINTING_OBJ = printing/pcap.o printing/print_svid.o \ PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \
printing/print_cups.o printing/print_generic.o \ printing/print_cups.o printing/print_generic.o \
printing/lpq_parse.o printing/load.o printing/lpq_parse.o printing/load.o

View File

@ -21,45 +21,30 @@
#include "includes.h" #include "includes.h"
/***************************************************************************
auto-load printer services
***************************************************************************/
void add_all_printers(void)
{
int printers = lp_servicenumber(PRINTERS_NAME);
if (printers < 0) return;
pcap_printer_fn(lp_add_one_printer);
}
/*************************************************************************** /***************************************************************************
auto-load some homes and printer services auto-load some homes and printer services
***************************************************************************/ ***************************************************************************/
static void add_auto_printers(void) static void add_auto_printers(void)
{ {
const char *p; const char *p;
int printers; int pnum = lp_servicenumber(PRINTERS_NAME);
char *str = SMB_STRDUP(lp_auto_services()); char *str;
if (!str) return; if (pnum < 0)
printers = lp_servicenumber(PRINTERS_NAME);
if (printers < 0) {
SAFE_FREE(str);
return; return;
}
if ((str = SMB_STRDUP(lp_auto_services())) == NULL)
for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) { return;
if (lp_servicenumber(p) >= 0) continue;
for (p = strtok(str, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
if (lp_servicenumber(p) >= 0)
continue;
if (pcap_printername_ok(p,NULL)) { if (pcap_printername_ok(p))
lp_add_printer(p,printers); lp_add_printer(p, pnum);
}
} }
SAFE_FREE(str); SAFE_FREE(str);
} }
/*************************************************************************** /***************************************************************************
@ -67,7 +52,12 @@ load automatic printer services
***************************************************************************/ ***************************************************************************/
void load_printers(void) void load_printers(void)
{ {
if (!pcap_cache_loaded())
pcap_cache_reload();
add_auto_printers(); add_auto_printers();
if (lp_load_printers())
add_all_printers(); /* load all printcap printers */
if (lp_load_printers() && lp_servicenumber(PRINTERS_NAME) >= 0)
pcap_printer_fn(lp_add_one_printer);
} }

View File

@ -2046,17 +2046,32 @@ static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
handles are not affected. handles are not affected.
****************************************************************************/ ****************************************************************************/
uint32 del_a_printer(char *sharename) uint32 del_a_printer(const char *sharename)
{ {
pstring key; pstring key;
TDB_DATA kbuf; TDB_DATA kbuf;
pstring printdb_path;
slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename); slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
kbuf.dptr=key; kbuf.dptr=key;
kbuf.dsize=strlen(key)+1; kbuf.dsize=strlen(key)+1;
tdb_delete(tdb_printers, kbuf); tdb_delete(tdb_printers, kbuf);
slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
kbuf.dptr=key;
kbuf.dsize=strlen(key)+1;
tdb_delete(tdb_printers, kbuf);
close_all_print_db();
if (geteuid() == 0) {
pstrcpy(printdb_path, lock_path("printing/"));
pstrcat(printdb_path, sharename);
pstrcat(printdb_path, ".tdb");
unlink(printdb_path);
}
return 0; return 0;
} }
@ -2899,7 +2914,8 @@ BOOL is_printer_published(Printer_entry *print_hnd, int snum,
return False; return False;
} }
if (regval_size(guid_val) == sizeof(struct uuid)) /* fetching printer guids really ought to be a separate function.. */
if (guid && regval_size(guid_val) == sizeof(struct uuid))
memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid)); memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
free_a_printer(&printer, 2); free_a_printer(&printer, 2);

View File

@ -27,10 +27,8 @@
*/ */
/* /*
* Parse printcap file. * This module contains code to parse and cache printcap data, possibly
* * in concert with the CUPS/SYSV/AIX-specific code found elsewhere.
* This module does exactly one thing - it looks into the printcap file
* and tells callers if a specified string appears as a printer name.
* *
* The way this module looks at the printcap file is very simplistic. * The way this module looks at the printcap file is very simplistic.
* Only the local printcap file is inspected (no searching of NIS * Only the local printcap file is inspected (no searching of NIS
@ -62,352 +60,194 @@
#include "includes.h" #include "includes.h"
#ifdef AIX
/* ****************************************** typedef struct pcap_cache {
Extend for AIX system and qconfig file char *name;
from 'boulard@univ-rennes1.fr char *comment;
****************************************** */ struct pcap_cache *next;
static int strlocate(char *xpLine,char *xpS) } pcap_cache_t;
static pcap_cache_t *pcap_cache = NULL;
BOOL pcap_cache_add(const char *name, const char *comment)
{ {
int iS,iL,iRet; pcap_cache_t *p;
char *p;
iS = strlen(xpS);
iL = strlen(xpLine);
iRet = 0; if (name == NULL || ((p = SMB_MALLOC_P(pcap_cache_t)) == NULL))
p = xpLine; return False;
while (iL >= iS)
{
if (strncmp(p,xpS,iS) == 0) {iRet =1;break;};
p++;
iL--;
}
/*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
return(iRet);
}
/* ******************************************************************* */
/* * Scan qconfig and search all virtual printer (device printer) * */
/* ******************************************************************* */
static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))
{
int iEtat;
XFILE *pfile;
char *line,*p;
pstring name,comment;
line = NULL;
*name = 0;
*comment = 0;
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) p->name = SMB_STRDUP(name);
{ p->comment = (comment && *comment) ? SMB_STRDUP(comment) : NULL;
DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
return;
}
iEtat = 0; p->next = pcap_cache;
/* scan qconfig file for searching <printername>: */ pcap_cache = p;
for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
{ return True;
if (*line == '*' || *line == 0)
continue;
switch (iEtat)
{
case 0: /* locate an entry */
if (*line == '\t' || *line == ' ') continue;
if ((p=strchr_m(line,':')))
{
*p = '\0';
p = strtok(line,":");
if (strcmp(p,"bsh")!=0)
{
pstrcpy(name,p);
iEtat = 1;
continue;
}
}
break;
case 1: /* scanning device stanza */
if (*line == '*' || *line == 0) continue;
if (*line != '\t' && *line != ' ')
{
/* name is found without stanza device */
/* probably a good printer ??? */
fn(name,comment);
iEtat = 0;
continue;
}
if (strlocate(line,"backend"))
{
/* it's a device, not a virtual printer*/
iEtat = 0;
}
else if (strlocate(line,"device"))
{
/* it's a good virtual printer */
fn(name,comment);
iEtat = 0;
continue;
}
break;
}
}
x_fclose(pfile);
} }
/* Scan qconfig file and locate de printername */ static void pcap_cache_destroy(pcap_cache_t *cache)
static BOOL ScanQconfig(char *psz,char *pszPrintername)
{ {
int iLg,iEtat; pcap_cache_t *p, *next;
XFILE *pfile;
char *pName;
char *line;
pName = NULL; for (p = cache; p != NULL; p = next) {
line = NULL; next = p->next;
if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
pName = malloc(iLg+10); SAFE_FREE(p->name);
if (pName == NULL) SAFE_FREE(p->comment);
{ SAFE_FREE(p);
DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
return(False);
} }
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
{
DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
SAFE_FREE(pName);
return(False);
}
slprintf(pName, iLg + 9, "%s:",pszPrintername);
iLg = strlen(pName);
/*DEBUG(3,( " Looking for entry %s\n",pName));*/
iEtat = 0;
/* scan qconfig file for searching <printername>: */
for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
{
if (*line == '*' || *line == 0)
continue;
switch (iEtat)
{
case 0: /* scanning entry */
if (strncmp(line,pName,iLg) == 0)
{
iEtat = 1;
continue;
}
break;
case 1: /* scanning device stanza */
if (*line == '*' || *line == 0) continue;
if (*line != '\t' && *line != ' ')
{
/* name is found without stanza device */
/* probably a good printer ??? */
free (line);
SAFE_FREE(pName);
x_fclose(pfile);
return(True);
}
if (strlocate(line,"backend"))
{
/* it's a device, not a virtual printer*/
iEtat = 0;
}
else if (strlocate(line,"device"))
{
/* it's a good virtual printer */
free (line);
SAFE_FREE(pName);
x_fclose(pfile);
return(True);
}
break;
}
}
free (pName);
x_fclose(pfile);
return(False);
} }
#endif /* AIX */
BOOL pcap_cache_loaded(void)
/***************************************************************************
Scan printcap file pszPrintcapname for a printer called pszPrintername.
Return True if found, else False. Returns False on error, too, after logging
the error at level 0. For generality, the printcap name may be passed - if
passed as NULL, the configuration will be queried for the name.
***************************************************************************/
BOOL pcap_printername_ok(const char *pszPrintername, const char *pszPrintcapname)
{ {
char *line=NULL; return (pcap_cache != NULL);
const char *psz; }
char *p,*q;
XFILE *pfile;
if (pszPrintername == NULL || pszPrintername[0] == '\0') void pcap_cache_reload(void)
{ {
DEBUG(0,( "Attempt to locate null printername! Internal error?\n")); const char *pcap_name = lp_printcapname();
return(False); BOOL pcap_reloaded = False;
} pcap_cache_t *tmp_cache = NULL;
XFILE *pcap_file;
char *pcap_line;
/* only go looking if no printcap name supplied */ DEBUG(3, ("reloading printcap cache\n"));
if ((psz = pszPrintcapname) == NULL || psz[0] == '\0')
if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) /* only go looking if no printcap name supplied */
{ if (pcap_name == NULL || *pcap_name == 0) {
DEBUG(0,( "No printcap file name configured!\n")); DEBUG(0, ("No printcap file name configured!\n"));
return(False); return;
} }
tmp_cache = pcap_cache;
pcap_cache = NULL;
#ifdef HAVE_CUPS #ifdef HAVE_CUPS
if (strequal(psz, "cups")) if (strequal(pcap_name, "cups")) {
return (cups_printername_ok(pszPrintername)); pcap_reloaded = cups_cache_reload();
#endif /* HAVE_CUPS */ goto done;
}
#endif
#ifdef SYSV #ifdef SYSV
if (strequal(psz, "lpstat")) if (strequal(pcap_name, "lpstat")) {
return (sysv_printername_ok(pszPrintername)); pcap_reloaded = sysv_cache_reload();
goto done;
}
#endif #endif
#ifdef AIX #ifdef AIX
if (strlocate(psz,"/qconfig")) if (strstr_m(pcap_name, "/qconfig") != NULL) {
return(ScanQconfig(psz,pszPrintername)); pcap_reloaded = aix_cache_reload();
goto done;
}
#endif #endif
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) /* handle standard printcap - moved from pcap_printer_fn() */
{
DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
return(False);
}
for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) {
{ DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name));
if (*line == '#' || *line == 0) goto done;
continue;
/* now we have a real printer line - cut it off at the first : */
p = strchr_m(line,':');
if (p) *p = 0;
/* now just check if the name is in the list */
/* NOTE: I avoid strtok as the fn calling this one may be using it */
for (p=line; p; p=q)
{
if ((q = strchr_m(p,'|'))) *q++ = 0;
if (strequal(p,pszPrintername))
{
SAFE_FREE(line);
x_fclose(pfile);
return(True);
}
p = q;
} }
}
x_fclose(pfile); for (; (pcap_line = fgets_slash(NULL, sizeof(pstring), pcap_file)) != NULL; safe_free(pcap_line)) {
return(False); pstring name, comment;
char *p, *q;
if (*pcap_line == '#' || *pcap_line == 0)
continue;
/* now we have a real printer line - cut at the first : */
if ((p = strchr_m(pcap_line, ':')) != NULL)
*p = 0;
/*
* now find the most likely printer name and comment
* this is pure guesswork, but it's better than nothing
*/
for (*name = *comment = 0, p = pcap_line; p != NULL; p = q) {
BOOL has_punctuation;
if ((q = strchr_m(p, '|')) != NULL)
*q++ = 0;
has_punctuation = (strchr_m(p, ' ') ||
strchr_m(p, '\t') ||
strchr_m(p, '(') ||
strchr_m(p, ')'));
if (strlen(p) > strlen(comment) && has_punctuation) {
pstrcpy(comment, p);
continue;
}
if (strlen(p) <= MAXPRINTERLEN &&
strlen(p) > strlen(name) && !has_punctuation) {
if (!*comment)
pstrcpy(comment, name);
pstrcpy(name, p);
continue;
}
if (!strchr_m(comment, ' ') &&
strlen(p) > strlen(comment)) {
pstrcpy(comment, p);
continue;
}
}
comment[60] = 0;
name[MAXPRINTERLEN] = 0;
if (*name && !pcap_cache_add(name, comment)) {
x_fclose(pcap_file);
goto done;
}
}
x_fclose(pcap_file);
pcap_reloaded = True;
done:
DEBUG(3, ("reload status: %s\n", (pcap_reloaded) ? "ok" : "error"));
if (pcap_reloaded)
pcap_cache_destroy(tmp_cache);
else {
pcap_cache_destroy(pcap_cache);
pcap_cache = tmp_cache;
}
return;
} }
BOOL pcap_printername_ok(const char *printername)
{
pcap_cache_t *p;
for (p = pcap_cache; p != NULL; p = p->next)
if (strequal(p->name, printername))
return True;
return False;
}
/*************************************************************************** /***************************************************************************
run a function on each printer name in the printcap file. The function is run a function on each printer name in the printcap file. The function is
passed the primary name and the comment (if possible). Note the fn() takes passed the primary name and the comment (if possible). Note the fn() takes
strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed
to return DOS codepage. FIXME !! JRA. to return DOS codepage. FIXME !! JRA.
XXX: I'm not sure if this comment still applies.. Anyone? -Rob
***************************************************************************/ ***************************************************************************/
void pcap_printer_fn(void (*fn)(char *, char *)) void pcap_printer_fn(void (*fn)(char *, char *))
{ {
pstring name,comment; pcap_cache_t *p;
char *line;
char *psz;
char *p,*q;
XFILE *pfile;
/* only go looking if no printcap name supplied */ for (p = pcap_cache; p != NULL; p = p->next)
if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) fn(p->name, p->comment);
{
DEBUG(0,( "No printcap file name configured!\n"));
return;
}
#ifdef HAVE_CUPS return;
if (strequal(psz, "cups")) {
cups_printer_fn(fn);
return;
}
#endif /* HAVE_CUPS */
#ifdef SYSV
if (strequal(psz, "lpstat")) {
sysv_printer_fn(fn);
return;
}
#endif
#ifdef AIX
if (strlocate(psz,"/qconfig"))
{
ScanQconfig_fn(psz,fn);
return;
}
#endif
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
{
DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
return;
}
for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
{
if (*line == '#' || *line == 0)
continue;
/* now we have a real printer line - cut it off at the first : */
p = strchr_m(line,':');
if (p) *p = 0;
/* now find the most likely printer name and comment
this is pure guesswork, but it's better than nothing */
*name = 0;
*comment = 0;
for (p=line; p; p=q)
{
BOOL has_punctuation;
if ((q = strchr_m(p,'|'))) *q++ = 0;
has_punctuation = (strchr_m(p,' ') || strchr_m(p,'\t') || strchr_m(p,'(') || strchr_m(p,')'));
if (strlen(p)>strlen(comment) && has_punctuation)
{
pstrcpy(comment,p);
continue;
}
if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation)
{
if (!*comment) pstrcpy(comment,name);
pstrcpy(name,p);
continue;
}
if (!strchr_m(comment,' ') &&
strlen(p) > strlen(comment))
{
pstrcpy(comment,p);
continue;
}
}
comment[60] = 0;
name[MAXPRINTERLEN] = 0;
if (*name)
fn(name,comment);
}
x_fclose(pfile);
} }

View File

@ -0,0 +1,111 @@
/*
AIX-specific printcap loading
Copyright (C) Jean-Pierre.Boulard@univ-rennes1.fr 1996
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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.
*/
/*
* This module implements AIX-specific printcap loading. Most of the code
* here was originally provided by Jean-Pierre.Boulard@univ-rennes1.fr in
* the Samba 1.9.14 release, and was formerly contained in pcap.c. It has
* been moved here and condensed as part of a larger effort to clean up and
* simplify the printcap code. -- Rob Foehl, 2004/12/06
*/
#include "includes.h"
#ifdef AIX
BOOL aix_cache_reload(void)
{
int iEtat;
XFILE *pfile;
char *line = NULL, *p;
pstring name, comment;
*name = 0;
*comment = 0;
DEBUG(5, ("reloading aix printcap cache\n"));
if ((pfile = x_fopen(lp_printcapname(), O_RDONLY, 0)) == NULL) {
DEBUG(0,( "Unable to open qconfig file %s for read!\n", lp_printcapname()));
return False;
}
iEtat = 0;
/* scan qconfig file for searching <printername>: */
for (;(line = fgets_slash(NULL, sizeof(pstring), pfile)); safe_free(line)) {
if (*line == '*' || *line == 0)
continue;
switch (iEtat) {
case 0: /* locate an entry */
if (*line == '\t' || *line == ' ')
continue;
if ((p = strchr_m(line, ':'))) {
*p = '\0';
p = strtok(line, ":");
if (strcmp(p, "bsh") != 0) {
pstrcpy(name, p);
iEtat = 1;
continue;
}
}
break;
case 1: /* scanning device stanza */
if (*line == '*' || *line == 0)
continue;
if (*line != '\t' && *line != ' ') {
/* name is found without stanza device */
/* probably a good printer ??? */
iEtat = 0;
if (!pcap_cache_add(name, NULL)) {
safe_free(line);
x_fclose(pfile);
return False;
}
continue;
}
if (strstr_m(line, "backend")) {
/* it's a device, not a virtual printer */
iEtat = 0;
} else if (strstr_m(line, "device")) {
/* it's a good virtual printer */
iEtat = 0;
if (!pcap_cache_add(name, NULL)) {
safe_free(line);
x_fclose(pfile);
return False;
}
continue;
}
break;
}
}
x_fclose(pfile);
return True;
}
#else
/* this keeps fussy compilers happy */
void print_aix_dummy(void);
void print_aix_dummy(void) {}
#endif /* AIX */

View File

@ -52,14 +52,8 @@ static const char *cups_server(void)
return cupsServer(); return cupsServer();
} }
/* BOOL cups_cache_reload(void)
* 'cups_printer_fn()' - Call a function for every printer known to the
* system.
*/
void cups_printer_fn(void (*fn)(char *, char *))
{ {
/* I - Function to call */
http_t *http; /* HTTP connection to server */ http_t *http; /* HTTP connection to server */
ipp_t *request, /* IPP Request */ ipp_t *request, /* IPP Request */
*response; /* IPP Response */ *response; /* IPP Response */
@ -74,7 +68,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
}; };
DEBUG(5,("cups_printer_fn(%p)\n", fn)); DEBUG(5, ("reloading cups printcap cache\n"));
/* /*
* Make sure we don't ask for passwords... * Make sure we don't ask for passwords...
@ -90,7 +84,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
{ {
DEBUG(0,("Unable to connect to CUPS server %s - %s\n", DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
cups_server(), strerror(errno))); cups_server(), strerror(errno)));
return; return False;
} }
/* /*
@ -129,7 +123,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
DEBUG(0,("Unable to get printer list - %s\n", DEBUG(0,("Unable to get printer list - %s\n",
ippErrorString(cupsLastError()))); ippErrorString(cupsLastError())));
httpClose(http); httpClose(http);
return; return False;
} }
for (attr = response->attrs; attr != NULL;) for (attr = response->attrs; attr != NULL;)
@ -171,7 +165,11 @@ void cups_printer_fn(void (*fn)(char *, char *))
if (name == NULL) if (name == NULL)
break; break;
(*fn)(name, info); if (!pcap_cache_add(name, info)) {
ippDelete(response);
httpClose(http);
return False;
}
} }
ippDelete(response); ippDelete(response);
@ -213,7 +211,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
DEBUG(0,("Unable to get printer list - %s\n", DEBUG(0,("Unable to get printer list - %s\n",
ippErrorString(cupsLastError()))); ippErrorString(cupsLastError())));
httpClose(http); httpClose(http);
return; return False;
} }
for (attr = response->attrs; attr != NULL;) for (attr = response->attrs; attr != NULL;)
@ -255,7 +253,11 @@ void cups_printer_fn(void (*fn)(char *, char *))
if (name == NULL) if (name == NULL)
break; break;
(*fn)(name, info); if (!pcap_cache_add(name, info)) {
ippDelete(response);
httpClose(http);
return False;
}
} }
ippDelete(response); ippDelete(response);
@ -265,100 +267,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
*/ */
httpClose(http); httpClose(http);
} return True;
/*
* 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok()
* for CUPS.
* O - 1 if printer name OK
* I - Name of printer
*/
int cups_printername_ok(const char *name)
{
http_t *http; /* HTTP connection to server */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
cups_lang_t *language; /* Default language */
char uri[HTTP_MAX_URI]; /* printer-uri attribute */
DEBUG(5,("cups_printername_ok(\"%s\")\n", name));
/*
* Make sure we don't ask for passwords...
*/
cupsSetPasswordCB(cups_passwd_cb);
/*
* Try to connect to the server...
*/
if ((http = httpConnect(cups_server(), ippPort())) == NULL)
{
DEBUG(3,("Unable to connect to CUPS server %s - %s\n",
cups_server(), strerror(errno)));
return (0);
}
/*
* Build an IPP_GET_PRINTER_ATTRS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* printer-uri
*/
request = ippNew();
request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
request->request.op.request_id = 1;
language = cupsLangDefault();
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
"attributes-charset", NULL, cupsLangEncoding(language));
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, language->language);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
"requested-attributes", NULL, "printer-uri");
slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, uri);
/*
* Do the request and get back a response...
*/
if ((response = cupsDoRequest(http, request, "/")) == NULL)
{
DEBUG(3,("Unable to get printer status for %s - %s\n", name,
ippErrorString(cupsLastError())));
httpClose(http);
return (0);
}
httpClose(http);
if (response->request.status.status_code >= IPP_OK_CONFLICT)
{
DEBUG(3,("Unable to get printer status for %s - %s\n", name,
ippErrorString(response->request.status.status_code)));
ippDelete(response);
return (0);
}
else
{
ippDelete(response);
return (1);
}
} }

View File

@ -35,23 +35,17 @@
#include "includes.h" #include "includes.h"
#ifdef SYSV #ifdef SYSV
BOOL sysv_cache_reload(void)
typedef struct printer {
char *name;
struct printer *next;
} printer_t;
static printer_t *printers = NULL;
static void populate_printers(void)
{ {
char **lines; char **lines;
int i; int i;
lines = file_lines_pload("/usr/bin/lpstat -v", NULL); DEBUG(5, ("reloading sysv printcap cache\n"));
if (!lines) return;
for (i=0;lines[i];i++) { if ((lines = file_lines_pload("/usr/bin/lpstat -v", NULL)) == NULL)
printer_t *ptmp; return False;
for (i = 0; lines[i]; i++) {
char *name, *tmp; char *name, *tmp;
char *buf = lines[i]; char *buf = lines[i];
@ -64,7 +58,7 @@ static void populate_printers(void)
* In case we're only at the "for ". * In case we're only at the "for ".
*/ */
if(!strncmp("for ",++tmp,4)) { if(!strncmp("for ", ++tmp, 4)) {
tmp=strchr_m(tmp, ' '); tmp=strchr_m(tmp, ' ');
tmp++; tmp++;
} }
@ -78,7 +72,7 @@ static void populate_printers(void)
* On HPUX there is an extra line that can be ignored. * On HPUX there is an extra line that can be ignored.
* d.thibadeau 2001/08/09 * d.thibadeau 2001/08/09
*/ */
if(!strncmp("remote to",tmp,9)) if(!strncmp("remote to", tmp, 9))
continue; continue;
name = tmp; name = tmp;
@ -88,53 +82,14 @@ static void populate_printers(void)
*tmp = '\0'; *tmp = '\0';
/* add it to the cache */ /* add it to the cache */
if ((ptmp = SMB_MALLOC_P(printer_t)) != NULL) { if (!pcap_cache_add(name, NULL)) {
ZERO_STRUCTP(ptmp); file_lines_free(lines);
if((ptmp->name = SMB_STRDUP(name)) == NULL) return False;
DEBUG(0,("populate_printers: malloc fail in strdup !\n"));
ptmp->next = printers;
printers = ptmp;
} else {
DEBUG(0,("populate_printers: malloc fail for ptmp\n"));
} }
} }
file_lines_free(lines); file_lines_free(lines);
} return True;
/*
* provide the equivalent of pcap_printer_fn() for SVID/XPG4 conforming
* systems. It was unclear why pcap_printer_fn() was tossing names longer
* than 8 characters. I suspect that its a protocol limit, but amazingly
* names longer than 8 characters appear to work with my test
* clients (Win95/NT).
*/
void sysv_printer_fn(void (*fn)(char *, char *))
{
printer_t *tmp;
if (printers == NULL)
populate_printers();
for (tmp = printers; tmp != NULL; tmp = tmp->next)
(fn)(tmp->name, "");
}
/*
* provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming
* systems.
*/
int sysv_printername_ok(const char *name)
{
printer_t *tmp;
if (printers == NULL)
populate_printers();
for (tmp = printers; tmp != NULL; tmp = tmp->next)
if (strcmp(tmp->name, name) == 0)
return (True);
return (False);
} }
#else #else

View File

@ -2247,7 +2247,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
} }
/* for autoloaded printers, check that the printcap entry still exists */ /* for autoloaded printers, check that the printcap entry still exists */
if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum), NULL)) { if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) {
DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) )); DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
release_print_db(pdb); release_print_db(pdb);
errno = ENOENT; errno = ENOENT;

View File

@ -1282,7 +1282,7 @@ static int setup_select_timeout(void)
void check_reload(int t) void check_reload(int t)
{ {
static time_t last_smb_conf_reload_time = 0; static time_t last_smb_conf_reload_time = 0;
static time_t last_load_printers_reload_time = 0; static time_t last_printer_reload_time = 0;
time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
if(last_smb_conf_reload_time == 0) { if(last_smb_conf_reload_time == 0) {
@ -1291,9 +1291,9 @@ void check_reload(int t)
Then no printer is available till the first printers check Then no printer is available till the first printers check
is performed. A lower initial interval circumvents this. */ is performed. A lower initial interval circumvents this. */
if ( printcap_cache_time > 60 ) if ( printcap_cache_time > 60 )
last_load_printers_reload_time = t - printcap_cache_time + 60; last_printer_reload_time = t - printcap_cache_time + 60;
else else
last_load_printers_reload_time = t; last_printer_reload_time = t;
} }
if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
@ -1308,13 +1308,12 @@ void check_reload(int t)
{ {
/* see if it's time to reload or if the clock has been set back */ /* see if it's time to reload or if the clock has been set back */
if ( (t >= last_load_printers_reload_time+printcap_cache_time) if ( (t >= last_printer_reload_time+printcap_cache_time)
|| (t-last_load_printers_reload_time < 0) ) || (t-last_printer_reload_time < 0) )
{ {
DEBUG( 3,( "Printcap cache time expired.\n")); DEBUG( 3,( "Printcap cache time expired.\n"));
remove_stale_printers(); reload_printers();
load_printers(); last_printer_reload_time = t;
last_load_printers_reload_time = t;
} }
} }
} }

View File

@ -463,6 +463,39 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
/* NOTREACHED return True; */ /* NOTREACHED return True; */
} }
/****************************************************************************
Reload printers
**************************************************************************/
void reload_printers(void)
{
int snum;
int n_services = lp_numservices();
int pnum = lp_servicenumber(PRINTERS_NAME);
const char *pname;
pcap_cache_reload();
/* remove stale printers */
for (snum = 0; snum < n_services; snum++) {
/* avoid removing PRINTERS_NAME or non-autoloaded printers */
if (snum == pnum || !(lp_snum_ok(snum) && lp_print_ok(snum) &&
lp_autoloaded(snum)))
continue;
pname = lp_printername(snum);
if (!pcap_printername_ok(pname)) {
DEBUG(3, ("removing stale printer %s\n", pname));
if (is_printer_published(NULL, snum, NULL))
nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH);
del_a_printer(pname);
lp_killservice(snum);
}
}
load_printers();
}
/**************************************************************************** /****************************************************************************
Reload the services file. Reload the services file.
**************************************************************************/ **************************************************************************/
@ -490,8 +523,7 @@ BOOL reload_services(BOOL test)
ret = lp_load(dyn_CONFIGFILE, False, False, True); ret = lp_load(dyn_CONFIGFILE, False, False, True);
remove_stale_printers(); reload_printers();
load_printers();
/* perhaps the config filename is now set */ /* perhaps the config filename is now set */
if (!test) if (!test)

View File

@ -152,10 +152,8 @@ int find_service(fstring service)
int iPrinterService; int iPrinterService;
if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
const char *pszTemp = lp_printcapname();
DEBUG(3,("checking whether %s is a valid printer name...\n", service)); DEBUG(3,("checking whether %s is a valid printer name...\n", service));
if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { if (pcap_printername_ok(service)) {
DEBUG(3,("%s is a valid printer name\n", service)); DEBUG(3,("%s is a valid printer name\n", service));
DEBUG(3,("adding %s as a printer service\n", service)); DEBUG(3,("adding %s as a printer service\n", service));
lp_add_printer(service, iPrinterService); lp_add_printer(service, iPrinterService);
@ -863,36 +861,3 @@ void close_cnum(connection_struct *conn, uint16 vuid)
conn_free(conn); conn_free(conn);
} }
/****************************************************************************
Remove stale printers
****************************************************************************/
void remove_stale_printers( void )
{
int snum, iNumServices, printersServiceNum;
const char *pname;
iNumServices = lp_numservices();
printersServiceNum = lp_servicenumber( PRINTERS_NAME);
for( snum = 0; snum < iNumServices; snum++) {
/* Never remove PRINTERS_NAME */
if ( snum == printersServiceNum)
continue;
pname = lp_printername( snum);
/* Is snum an autoloaded print service and still
in the printing subsystem? */
if ( lp_snum_ok(snum)
&& lp_print_ok(snum)
&& lp_autoloaded(snum)
&& !pcap_printername_ok( pname, NULL))
{
DEBUG( 3, ( "Removing printer: %s\n", pname));
lp_killservice( snum);
}
}
}

View File

@ -32,14 +32,17 @@
#include "includes.h" #include "includes.h"
/*
* NOTE: this code is likely to be removed, and no longer supports
* checking against non-configured printcap files. -Rob
*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const char *pszTemp;
setup_logging(argv[0],True); setup_logging(argv[0],True);
if (argc < 2 || argc > 3) if (argc != 2)
printf("Usage: testprns printername [printcapfile]\n"); printf("Usage: testprns printername\n");
else else
{ {
dbf = x_fopen("test.log", O_WRONLY|O_CREAT|O_TRUNC, 0644); dbf = x_fopen("test.log", O_WRONLY|O_CREAT|O_TRUNC, 0644);
@ -47,10 +50,9 @@ int main(int argc, char *argv[])
printf("Unable to open logfile.\n"); printf("Unable to open logfile.\n");
} else { } else {
DEBUGLEVEL = 3; DEBUGLEVEL = 3;
pszTemp = (argc < 3) ? PRINTCAP_NAME : argv[2]; printf("Looking for printer %s\n", argv[1]);
printf("Looking for printer %s in printcap file %s\n", load_printers();
argv[1], pszTemp); if (!pcap_printername_ok(argv[1]))
if (!pcap_printername_ok(argv[1], pszTemp))
printf("Printer name %s is not valid.\n", argv[1]); printf("Printer name %s is not valid.\n", argv[1]);
else else
printf("Printer name %s is valid.\n", argv[1]); printf("Printer name %s is valid.\n", argv[1]);