printing/pcap.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    printcap parsing
00004    Copyright (C) Karl Auer 1993-1998
00005 
00006    Re-working by Martin Kiff, 1994
00007    
00008    Re-written again by Andrew Tridgell
00009 
00010    Modified for SVID support by Norm Jacobs, 1997
00011 
00012    Modified for CUPS support by Michael Sweet, 1999
00013    
00014    This program is free software; you can redistribute it and/or modify
00015    it under the terms of the GNU General Public License as published by
00016    the Free Software Foundation; either version 2 of the License, or
00017    (at your option) any later version.
00018    
00019    This program is distributed in the hope that it will be useful,
00020    but WITHOUT ANY WARRANTY; without even the implied warranty of
00021    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022    GNU General Public License for more details.
00023    
00024    You should have received a copy of the GNU General Public License
00025    along with this program; if not, write to the Free Software
00026    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00027 */
00028 
00029 /*
00030  *  This module contains code to parse and cache printcap data, possibly
00031  *  in concert with the CUPS/SYSV/AIX-specific code found elsewhere.
00032  *
00033  *  The way this module looks at the printcap file is very simplistic.
00034  *  Only the local printcap file is inspected (no searching of NIS
00035  *  databases etc).
00036  *
00037  *  There are assumed to be one or more printer names per record, held
00038  *  as a set of sub-fields separated by vertical bar symbols ('|') in the
00039  *  first field of the record. The field separator is assumed to be a colon
00040  *  ':' and the record separator a newline.
00041  * 
00042  *  Lines ending with a backspace '\' are assumed to flag that the following
00043  *  line is a continuation line so that a set of lines can be read as one
00044  *  printcap entry.
00045  *
00046  *  A line stating with a hash '#' is assumed to be a comment and is ignored
00047  *  Comments are discarded before the record is strung together from the
00048  *  set of continuation lines.
00049  *
00050  *  Opening a pipe for "lpc status" and reading that would probably 
00051  *  be pretty effective. Code to do this already exists in the freely
00052  *  distributable PCNFS server code.
00053  *
00054  *  Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
00055  *  in smb.conf under Solaris.
00056  *
00057  *  Modified to call CUPS support if printcap name is set to "cups"
00058  *  in smb.conf.
00059  *
00060  *  Modified to call iPrint support if printcap name is set to "iprint"
00061  *  in smb.conf.
00062  */
00063 
00064 #include "includes.h"
00065 
00066 
00067 typedef struct pcap_cache {
00068         char *name;
00069         char *comment;
00070         struct pcap_cache *next;
00071 } pcap_cache_t;
00072 
00073 static pcap_cache_t *pcap_cache = NULL;
00074 
00075 BOOL pcap_cache_add(const char *name, const char *comment)
00076 {
00077         pcap_cache_t *p;
00078 
00079         if (name == NULL || ((p = SMB_MALLOC_P(pcap_cache_t)) == NULL))
00080                 return False;
00081 
00082         p->name = SMB_STRDUP(name);
00083         p->comment = (comment && *comment) ? SMB_STRDUP(comment) : NULL;
00084 
00085         p->next = pcap_cache;
00086         pcap_cache = p;
00087 
00088         return True;
00089 }
00090 
00091 static void pcap_cache_destroy(pcap_cache_t *cache)
00092 {
00093         pcap_cache_t *p, *next;
00094 
00095         for (p = cache; p != NULL; p = next) {
00096                 next = p->next;
00097 
00098                 SAFE_FREE(p->name);
00099                 SAFE_FREE(p->comment);
00100                 SAFE_FREE(p);
00101         }
00102 }
00103 
00104 BOOL pcap_cache_loaded(void)
00105 {
00106         return (pcap_cache != NULL);
00107 }
00108 
00109 void pcap_cache_reload(void)
00110 {
00111         const char *pcap_name = lp_printcapname();
00112         BOOL pcap_reloaded = False;
00113         pcap_cache_t *tmp_cache = NULL;
00114         XFILE *pcap_file;
00115         char *pcap_line;
00116 
00117         DEBUG(3, ("reloading printcap cache\n"));
00118 
00119         /* only go looking if no printcap name supplied */
00120         if (pcap_name == NULL || *pcap_name == 0) {
00121                 DEBUG(0, ("No printcap file name configured!\n"));
00122                 return;
00123         }
00124 
00125         tmp_cache = pcap_cache;
00126         pcap_cache = NULL;
00127 
00128 #ifdef HAVE_CUPS
00129         if (strequal(pcap_name, "cups")) {
00130                 pcap_reloaded = cups_cache_reload();
00131                 goto done;
00132         }
00133 #endif
00134 
00135 #ifdef HAVE_IPRINT
00136         if (strequal(pcap_name, "iprint")) {
00137                 pcap_reloaded = iprint_cache_reload();
00138                 goto done;
00139         }
00140 #endif
00141 
00142 #if defined(SYSV) || defined(HPUX)
00143         if (strequal(pcap_name, "lpstat")) {
00144                 pcap_reloaded = sysv_cache_reload();
00145                 goto done;
00146         }
00147 #endif
00148 
00149 #ifdef AIX
00150         if (strstr_m(pcap_name, "/qconfig") != NULL) {
00151                 pcap_reloaded = aix_cache_reload();
00152                 goto done;
00153         }
00154 #endif
00155 
00156         /* handle standard printcap - moved from pcap_printer_fn() */
00157 
00158         if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) {
00159                 DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name));
00160                 goto done;
00161         }
00162 
00163         for (; (pcap_line = fgets_slash(NULL, sizeof(pstring), pcap_file)) != NULL; safe_free(pcap_line)) {
00164                 pstring name, comment;
00165                 char *p, *q;
00166 
00167                 if (*pcap_line == '#' || *pcap_line == 0)
00168                         continue;
00169 
00170                 /* now we have a real printer line - cut at the first : */      
00171                 if ((p = strchr_m(pcap_line, ':')) != NULL)
00172                         *p = 0;
00173       
00174                 /*
00175                  * now find the most likely printer name and comment 
00176                  * this is pure guesswork, but it's better than nothing
00177                  */
00178                 for (*name = *comment = 0, p = pcap_line; p != NULL; p = q) {
00179                         BOOL has_punctuation;
00180 
00181                         if ((q = strchr_m(p, '|')) != NULL)
00182                                 *q++ = 0;
00183 
00184                         has_punctuation = (strchr_m(p, ' ') ||
00185                                            strchr_m(p, '\t') ||
00186                                            strchr_m(p, '(') ||
00187                                            strchr_m(p, ')'));
00188 
00189                         if (strlen(p) > strlen(comment) && has_punctuation) {
00190                                 pstrcpy(comment, p);
00191                                 continue;
00192                         }
00193 
00194                         if (strlen(p) <= MAXPRINTERLEN &&
00195                             strlen(p) > strlen(name) && !has_punctuation) {
00196                                 if (!*comment)
00197                                         pstrcpy(comment, name);
00198 
00199                                 pstrcpy(name, p);
00200                                 continue;
00201                         }
00202 
00203                         if (!strchr_m(comment, ' ') &&
00204                             strlen(p) > strlen(comment)) {
00205                                 pstrcpy(comment, p);
00206                                 continue;
00207                         }
00208                 }
00209 
00210                 comment[60] = 0;
00211                 name[MAXPRINTERLEN] = 0;
00212 
00213                 if (*name && !pcap_cache_add(name, comment)) {
00214                         x_fclose(pcap_file);
00215                         goto done;
00216                 }
00217         }
00218 
00219         x_fclose(pcap_file);
00220         pcap_reloaded = True;
00221 
00222 done:
00223         DEBUG(3, ("reload status: %s\n", (pcap_reloaded) ? "ok" : "error"));
00224 
00225         if (pcap_reloaded)
00226                 pcap_cache_destroy(tmp_cache);
00227         else {
00228                 pcap_cache_destroy(pcap_cache);
00229                 pcap_cache = tmp_cache;
00230         }
00231 
00232         return;
00233 }
00234 
00235 
00236 BOOL pcap_printername_ok(const char *printername)
00237 {
00238         pcap_cache_t *p;
00239 
00240         for (p = pcap_cache; p != NULL; p = p->next)
00241                 if (strequal(p->name, printername))
00242                         return True;
00243 
00244         return False;
00245 }
00246 
00247 /***************************************************************************
00248 run a function on each printer name in the printcap file. The function is 
00249 passed the primary name and the comment (if possible). Note the fn() takes
00250 strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed
00251 to return DOS codepage. FIXME !! JRA.
00252 
00253 XXX: I'm not sure if this comment still applies.. Anyone?  -Rob
00254 ***************************************************************************/
00255 void pcap_printer_fn(void (*fn)(char *, char *))
00256 {
00257         pcap_cache_t *p;
00258 
00259         for (p = pcap_cache; p != NULL; p = p->next)
00260                 fn(p->name, p->comment);
00261 
00262         return;
00263 }

Sambaに対してSat Aug 29 21:23:14 2009に生成されました。  doxygen 1.4.7