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:
parent
846b8d4cfd
commit
d097ea4905
@ -397,7 +397,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
|
||||
$(REGISTRY_OBJ) $(POPT_LIB_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/lpq_parse.o printing/load.o
|
||||
|
||||
|
@ -21,45 +21,30 @@
|
||||
#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
|
||||
***************************************************************************/
|
||||
static void add_auto_printers(void)
|
||||
{
|
||||
const char *p;
|
||||
int printers;
|
||||
char *str = SMB_STRDUP(lp_auto_services());
|
||||
int pnum = lp_servicenumber(PRINTERS_NAME);
|
||||
char *str;
|
||||
|
||||
if (!str) return;
|
||||
|
||||
printers = lp_servicenumber(PRINTERS_NAME);
|
||||
|
||||
if (printers < 0) {
|
||||
SAFE_FREE(str);
|
||||
if (pnum < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
|
||||
if (lp_servicenumber(p) >= 0) continue;
|
||||
|
||||
if ((str = SMB_STRDUP(lp_auto_services())) == NULL)
|
||||
return;
|
||||
|
||||
for (p = strtok(str, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
|
||||
if (lp_servicenumber(p) >= 0)
|
||||
continue;
|
||||
|
||||
if (pcap_printername_ok(p,NULL)) {
|
||||
lp_add_printer(p,printers);
|
||||
}
|
||||
if (pcap_printername_ok(p))
|
||||
lp_add_printer(p, pnum);
|
||||
}
|
||||
|
||||
SAFE_FREE(str);
|
||||
SAFE_FREE(str);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -67,7 +52,12 @@ load automatic printer services
|
||||
***************************************************************************/
|
||||
void load_printers(void)
|
||||
{
|
||||
if (!pcap_cache_loaded())
|
||||
pcap_cache_reload();
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -2046,17 +2046,32 @@ static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
|
||||
handles are not affected.
|
||||
****************************************************************************/
|
||||
|
||||
uint32 del_a_printer(char *sharename)
|
||||
uint32 del_a_printer(const char *sharename)
|
||||
{
|
||||
pstring key;
|
||||
TDB_DATA kbuf;
|
||||
pstring printdb_path;
|
||||
|
||||
slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
|
||||
|
||||
kbuf.dptr=key;
|
||||
kbuf.dsize=strlen(key)+1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2899,7 +2914,8 @@ BOOL is_printer_published(Printer_entry *print_hnd, int snum,
|
||||
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));
|
||||
|
||||
free_a_printer(&printer, 2);
|
||||
|
@ -27,10 +27,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parse printcap file.
|
||||
*
|
||||
* This module does exactly one thing - it looks into the printcap file
|
||||
* and tells callers if a specified string appears as a printer name.
|
||||
* This module contains code to parse and cache printcap data, possibly
|
||||
* in concert with the CUPS/SYSV/AIX-specific code found elsewhere.
|
||||
*
|
||||
* The way this module looks at the printcap file is very simplistic.
|
||||
* Only the local printcap file is inspected (no searching of NIS
|
||||
@ -62,352 +60,194 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef AIX
|
||||
/* ******************************************
|
||||
Extend for AIX system and qconfig file
|
||||
from 'boulard@univ-rennes1.fr
|
||||
****************************************** */
|
||||
static int strlocate(char *xpLine,char *xpS)
|
||||
|
||||
typedef struct pcap_cache {
|
||||
char *name;
|
||||
char *comment;
|
||||
struct pcap_cache *next;
|
||||
} pcap_cache_t;
|
||||
|
||||
static pcap_cache_t *pcap_cache = NULL;
|
||||
|
||||
BOOL pcap_cache_add(const char *name, const char *comment)
|
||||
{
|
||||
int iS,iL,iRet;
|
||||
char *p;
|
||||
iS = strlen(xpS);
|
||||
iL = strlen(xpLine);
|
||||
pcap_cache_t *p;
|
||||
|
||||
iRet = 0;
|
||||
p = xpLine;
|
||||
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 (name == NULL || ((p = SMB_MALLOC_P(pcap_cache_t)) == NULL))
|
||||
return False;
|
||||
|
||||
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
|
||||
{
|
||||
DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
|
||||
return;
|
||||
}
|
||||
p->name = SMB_STRDUP(name);
|
||||
p->comment = (comment && *comment) ? SMB_STRDUP(comment) : NULL;
|
||||
|
||||
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 ??? */
|
||||
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);
|
||||
p->next = pcap_cache;
|
||||
pcap_cache = p;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Scan qconfig file and locate de printername */
|
||||
|
||||
static BOOL ScanQconfig(char *psz,char *pszPrintername)
|
||||
static void pcap_cache_destroy(pcap_cache_t *cache)
|
||||
{
|
||||
int iLg,iEtat;
|
||||
XFILE *pfile;
|
||||
char *pName;
|
||||
char *line;
|
||||
pcap_cache_t *p, *next;
|
||||
|
||||
pName = NULL;
|
||||
line = NULL;
|
||||
if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
|
||||
pName = malloc(iLg+10);
|
||||
if (pName == NULL)
|
||||
{
|
||||
DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
|
||||
return(False);
|
||||
for (p = cache; p != NULL; p = next) {
|
||||
next = p->next;
|
||||
|
||||
SAFE_FREE(p->name);
|
||||
SAFE_FREE(p->comment);
|
||||
SAFE_FREE(p);
|
||||
}
|
||||
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 */
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
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)
|
||||
BOOL pcap_cache_loaded(void)
|
||||
{
|
||||
char *line=NULL;
|
||||
const char *psz;
|
||||
char *p,*q;
|
||||
XFILE *pfile;
|
||||
return (pcap_cache != NULL);
|
||||
}
|
||||
|
||||
if (pszPrintername == NULL || pszPrintername[0] == '\0')
|
||||
{
|
||||
DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
|
||||
return(False);
|
||||
}
|
||||
void pcap_cache_reload(void)
|
||||
{
|
||||
const char *pcap_name = lp_printcapname();
|
||||
BOOL pcap_reloaded = False;
|
||||
pcap_cache_t *tmp_cache = NULL;
|
||||
XFILE *pcap_file;
|
||||
char *pcap_line;
|
||||
|
||||
/* only go looking if no printcap name supplied */
|
||||
if ((psz = pszPrintcapname) == NULL || psz[0] == '\0')
|
||||
if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
|
||||
{
|
||||
DEBUG(0,( "No printcap file name configured!\n"));
|
||||
return(False);
|
||||
}
|
||||
DEBUG(3, ("reloading printcap cache\n"));
|
||||
|
||||
/* only go looking if no printcap name supplied */
|
||||
if (pcap_name == NULL || *pcap_name == 0) {
|
||||
DEBUG(0, ("No printcap file name configured!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
tmp_cache = pcap_cache;
|
||||
pcap_cache = NULL;
|
||||
|
||||
#ifdef HAVE_CUPS
|
||||
if (strequal(psz, "cups"))
|
||||
return (cups_printername_ok(pszPrintername));
|
||||
#endif /* HAVE_CUPS */
|
||||
if (strequal(pcap_name, "cups")) {
|
||||
pcap_reloaded = cups_cache_reload();
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SYSV
|
||||
if (strequal(psz, "lpstat"))
|
||||
return (sysv_printername_ok(pszPrintername));
|
||||
if (strequal(pcap_name, "lpstat")) {
|
||||
pcap_reloaded = sysv_cache_reload();
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AIX
|
||||
if (strlocate(psz,"/qconfig"))
|
||||
return(ScanQconfig(psz,pszPrintername));
|
||||
if (strstr_m(pcap_name, "/qconfig") != NULL) {
|
||||
pcap_reloaded = aix_cache_reload();
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
|
||||
{
|
||||
DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
|
||||
return(False);
|
||||
}
|
||||
/* handle standard printcap - moved from pcap_printer_fn() */
|
||||
|
||||
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 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;
|
||||
if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) {
|
||||
DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
x_fclose(pfile);
|
||||
return(False);
|
||||
for (; (pcap_line = fgets_slash(NULL, sizeof(pstring), pcap_file)) != NULL; safe_free(pcap_line)) {
|
||||
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
|
||||
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
|
||||
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 *))
|
||||
{
|
||||
pstring name,comment;
|
||||
char *line;
|
||||
char *psz;
|
||||
char *p,*q;
|
||||
XFILE *pfile;
|
||||
pcap_cache_t *p;
|
||||
|
||||
/* only go looking if no printcap name supplied */
|
||||
if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
|
||||
{
|
||||
DEBUG(0,( "No printcap file name configured!\n"));
|
||||
return;
|
||||
}
|
||||
for (p = pcap_cache; p != NULL; p = p->next)
|
||||
fn(p->name, p->comment);
|
||||
|
||||
#ifdef HAVE_CUPS
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
111
source3/printing/print_aix.c
Normal file
111
source3/printing/print_aix.c
Normal 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 */
|
@ -52,14 +52,8 @@ static const char *cups_server(void)
|
||||
return cupsServer();
|
||||
}
|
||||
|
||||
/*
|
||||
* 'cups_printer_fn()' - Call a function for every printer known to the
|
||||
* system.
|
||||
*/
|
||||
|
||||
void cups_printer_fn(void (*fn)(char *, char *))
|
||||
BOOL cups_cache_reload(void)
|
||||
{
|
||||
/* I - Function to call */
|
||||
http_t *http; /* HTTP connection to server */
|
||||
ipp_t *request, /* IPP Request */
|
||||
*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...
|
||||
@ -90,7 +84,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
|
||||
{
|
||||
DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
|
||||
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",
|
||||
ippErrorString(cupsLastError())));
|
||||
httpClose(http);
|
||||
return;
|
||||
return False;
|
||||
}
|
||||
|
||||
for (attr = response->attrs; attr != NULL;)
|
||||
@ -171,7 +165,11 @@ void cups_printer_fn(void (*fn)(char *, char *))
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
(*fn)(name, info);
|
||||
if (!pcap_cache_add(name, info)) {
|
||||
ippDelete(response);
|
||||
httpClose(http);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
ippDelete(response);
|
||||
@ -213,7 +211,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
|
||||
DEBUG(0,("Unable to get printer list - %s\n",
|
||||
ippErrorString(cupsLastError())));
|
||||
httpClose(http);
|
||||
return;
|
||||
return False;
|
||||
}
|
||||
|
||||
for (attr = response->attrs; attr != NULL;)
|
||||
@ -255,7 +253,11 @@ void cups_printer_fn(void (*fn)(char *, char *))
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
(*fn)(name, info);
|
||||
if (!pcap_cache_add(name, info)) {
|
||||
ippDelete(response);
|
||||
httpClose(http);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
ippDelete(response);
|
||||
@ -265,100 +267,7 @@ void cups_printer_fn(void (*fn)(char *, char *))
|
||||
*/
|
||||
|
||||
httpClose(http);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* '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);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,23 +35,17 @@
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef SYSV
|
||||
|
||||
typedef struct printer {
|
||||
char *name;
|
||||
struct printer *next;
|
||||
} printer_t;
|
||||
static printer_t *printers = NULL;
|
||||
|
||||
static void populate_printers(void)
|
||||
BOOL sysv_cache_reload(void)
|
||||
{
|
||||
char **lines;
|
||||
int i;
|
||||
|
||||
lines = file_lines_pload("/usr/bin/lpstat -v", NULL);
|
||||
if (!lines) return;
|
||||
DEBUG(5, ("reloading sysv printcap cache\n"));
|
||||
|
||||
for (i=0;lines[i];i++) {
|
||||
printer_t *ptmp;
|
||||
if ((lines = file_lines_pload("/usr/bin/lpstat -v", NULL)) == NULL)
|
||||
return False;
|
||||
|
||||
for (i = 0; lines[i]; i++) {
|
||||
char *name, *tmp;
|
||||
char *buf = lines[i];
|
||||
|
||||
@ -64,7 +58,7 @@ static void populate_printers(void)
|
||||
* In case we're only at the "for ".
|
||||
*/
|
||||
|
||||
if(!strncmp("for ",++tmp,4)) {
|
||||
if(!strncmp("for ", ++tmp, 4)) {
|
||||
tmp=strchr_m(tmp, ' ');
|
||||
tmp++;
|
||||
}
|
||||
@ -78,7 +72,7 @@ static void populate_printers(void)
|
||||
* On HPUX there is an extra line that can be ignored.
|
||||
* d.thibadeau 2001/08/09
|
||||
*/
|
||||
if(!strncmp("remote to",tmp,9))
|
||||
if(!strncmp("remote to", tmp, 9))
|
||||
continue;
|
||||
|
||||
name = tmp;
|
||||
@ -88,53 +82,14 @@ static void populate_printers(void)
|
||||
*tmp = '\0';
|
||||
|
||||
/* add it to the cache */
|
||||
if ((ptmp = SMB_MALLOC_P(printer_t)) != NULL) {
|
||||
ZERO_STRUCTP(ptmp);
|
||||
if((ptmp->name = SMB_STRDUP(name)) == NULL)
|
||||
DEBUG(0,("populate_printers: malloc fail in strdup !\n"));
|
||||
ptmp->next = printers;
|
||||
printers = ptmp;
|
||||
} else {
|
||||
DEBUG(0,("populate_printers: malloc fail for ptmp\n"));
|
||||
if (!pcap_cache_add(name, NULL)) {
|
||||
file_lines_free(lines);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
file_lines_free(lines);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
return True;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -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 */
|
||||
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) ));
|
||||
release_print_db(pdb);
|
||||
errno = ENOENT;
|
||||
|
@ -1282,7 +1282,7 @@ static int setup_select_timeout(void)
|
||||
void check_reload(int t)
|
||||
{
|
||||
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();
|
||||
|
||||
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
|
||||
is performed. A lower initial interval circumvents this. */
|
||||
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
|
||||
last_load_printers_reload_time = t;
|
||||
last_printer_reload_time = t;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
if ( (t >= last_load_printers_reload_time+printcap_cache_time)
|
||||
|| (t-last_load_printers_reload_time < 0) )
|
||||
if ( (t >= last_printer_reload_time+printcap_cache_time)
|
||||
|| (t-last_printer_reload_time < 0) )
|
||||
{
|
||||
DEBUG( 3,( "Printcap cache time expired.\n"));
|
||||
remove_stale_printers();
|
||||
load_printers();
|
||||
last_load_printers_reload_time = t;
|
||||
reload_printers();
|
||||
last_printer_reload_time = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -463,6 +463,39 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
|
||||
/* 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.
|
||||
**************************************************************************/
|
||||
@ -490,8 +523,7 @@ BOOL reload_services(BOOL test)
|
||||
|
||||
ret = lp_load(dyn_CONFIGFILE, False, False, True);
|
||||
|
||||
remove_stale_printers();
|
||||
load_printers();
|
||||
reload_printers();
|
||||
|
||||
/* perhaps the config filename is now set */
|
||||
if (!test)
|
||||
|
@ -152,10 +152,8 @@ int find_service(fstring service)
|
||||
int iPrinterService;
|
||||
|
||||
if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
|
||||
const char *pszTemp = lp_printcapname();
|
||||
|
||||
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,("adding %s as a printer service\n", service));
|
||||
lp_add_printer(service, iPrinterService);
|
||||
@ -863,36 +861,3 @@ void close_cnum(connection_struct *conn, uint16 vuid)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,17 @@
|
||||
|
||||
#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[])
|
||||
{
|
||||
const char *pszTemp;
|
||||
|
||||
setup_logging(argv[0],True);
|
||||
|
||||
if (argc < 2 || argc > 3)
|
||||
printf("Usage: testprns printername [printcapfile]\n");
|
||||
if (argc != 2)
|
||||
printf("Usage: testprns printername\n");
|
||||
else
|
||||
{
|
||||
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");
|
||||
} else {
|
||||
DEBUGLEVEL = 3;
|
||||
pszTemp = (argc < 3) ? PRINTCAP_NAME : argv[2];
|
||||
printf("Looking for printer %s in printcap file %s\n",
|
||||
argv[1], pszTemp);
|
||||
if (!pcap_printername_ok(argv[1], pszTemp))
|
||||
printf("Looking for printer %s\n", argv[1]);
|
||||
load_printers();
|
||||
if (!pcap_printername_ok(argv[1]))
|
||||
printf("Printer name %s is not valid.\n", argv[1]);
|
||||
else
|
||||
printf("Printer name %s is valid.\n", argv[1]);
|
||||
|
Loading…
Reference in New Issue
Block a user