~ubuntu-branches/ubuntu/oneiric/samba/oneiric-security

« back to all changes in this revision

Viewing changes to source/printing/pcap.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-07-21 17:53:23 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050721175323-m3oh6aoigywohfnq
Tags: 3.0.14a-6ubuntu1
Resynchronise with Debian, resolving merge conflicts (#12360)

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
*/
28
28
 
29
29
/*
30
 
 *  Parse printcap file.
31
 
 *
32
 
 *  This module does exactly one thing - it looks into the printcap file
33
 
 *  and tells callers if a specified string appears as a printer name.
 
30
 *  This module contains code to parse and cache printcap data, possibly
 
31
 *  in concert with the CUPS/SYSV/AIX-specific code found elsewhere.
34
32
 *
35
33
 *  The way this module looks at the printcap file is very simplistic.
36
34
 *  Only the local printcap file is inspected (no searching of NIS
62
60
 
63
61
#include "includes.h"
64
62
 
65
 
#ifdef AIX
66
 
/*  ******************************************
67
 
     Extend for AIX system and qconfig file
68
 
       from 'boulard@univ-rennes1.fr
69
 
    ****************************************** */
70
 
static int strlocate(char *xpLine,char *xpS)
71
 
{
72
 
        int iS,iL,iRet;
73
 
        char *p;
74
 
        iS = strlen(xpS);
75
 
        iL = strlen(xpLine);
76
 
 
77
 
        iRet = 0;
78
 
        p = xpLine;
79
 
        while (iL >= iS)
80
 
        {
81
 
                if (strncmp(p,xpS,iS) == 0) {iRet =1;break;};
82
 
                p++;
83
 
                iL--;
84
 
        }
85
 
        /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
86
 
        
87
 
        return(iRet);
88
 
}
89
 
        
90
 
        
91
 
/* ******************************************************************* */
92
 
/* *    Scan qconfig and search all virtual printer (device printer) * */
93
 
/* ******************************************************************* */
94
 
static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))
95
 
{
96
 
        int iEtat;
97
 
        XFILE *pfile;
98
 
        char *line,*p;
99
 
        pstring name,comment;
100
 
        line  = NULL;
101
 
        *name = 0;
102
 
        *comment = 0;
103
 
 
104
 
        if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
105
 
        {
106
 
              DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
107
 
              return;
108
 
        }
109
 
 
110
 
        iEtat = 0;
111
 
        /* scan qconfig file for searching <printername>:       */
112
 
        for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
113
 
        {
114
 
                if (*line == '*' || *line == 0)
115
 
                continue;
116
 
                switch (iEtat)
117
 
                {
118
 
                        case 0: /* locate an entry */
119
 
                         if (*line == '\t' || *line == ' ') continue;
120
 
                         if ((p=strchr_m(line,':')))
121
 
                         {
122
 
                                *p = '\0';
123
 
                                p = strtok(line,":");
124
 
                                if (strcmp(p,"bsh")!=0)
125
 
                                  {
126
 
                                    pstrcpy(name,p);
127
 
                                    iEtat = 1;
128
 
                                    continue;
129
 
                                  }
130
 
                         }
131
 
                         break;
132
 
                        case 1: /* scanning device stanza */
133
 
                         if (*line == '*' || *line == 0) continue;
134
 
                         if (*line != '\t' && *line != ' ')
135
 
                         {
136
 
                           /* name is found without stanza device  */
137
 
                           /* probably a good printer ???               */
138
 
                           fn(name,comment);
139
 
                           iEtat = 0;
140
 
                           continue;
141
 
                          }
142
 
                        
143
 
                          if (strlocate(line,"backend"))
144
 
                          {
145
 
                                /* it's a device, not a virtual printer*/
146
 
                                iEtat = 0;
147
 
                          }
148
 
                          else if (strlocate(line,"device"))
149
 
                          {
150
 
                                /* it's a good virtual printer */
151
 
                                fn(name,comment);
152
 
                                iEtat = 0;
153
 
                                continue;
154
 
                          }
155
 
                          break;
156
 
                }
157
 
        }
158
 
        x_fclose(pfile);
159
 
}
160
 
 
161
 
/* Scan qconfig file and locate de printername */
162
 
 
163
 
static BOOL ScanQconfig(char *psz,char *pszPrintername)
164
 
{
165
 
        int iLg,iEtat;
166
 
        XFILE *pfile;
167
 
        char *pName;
168
 
        char *line;
169
 
 
170
 
        pName = NULL;
171
 
        line  = NULL;
172
 
        if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
173
 
         pName = malloc(iLg+10);
174
 
        if (pName == NULL)
175
 
        {
176
 
                DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
177
 
                return(False);
178
 
        }
179
 
        if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
180
 
        {
181
 
              DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
182
 
              SAFE_FREE(pName);
183
 
              return(False);
184
 
        }
185
 
        slprintf(pName, iLg + 9, "%s:",pszPrintername);
186
 
        iLg = strlen(pName);
187
 
        /*DEBUG(3,( " Looking for entry %s\n",pName));*/
188
 
        iEtat = 0;
189
 
        /* scan qconfig file for searching <printername>:       */
190
 
        for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
191
 
        {
192
 
                if (*line == '*' || *line == 0)
193
 
                continue;
194
 
                switch (iEtat)
195
 
                {
196
 
                        case 0: /* scanning entry */
197
 
                         if (strncmp(line,pName,iLg) == 0)
198
 
                         {
199
 
                                iEtat = 1;
200
 
                                continue;
201
 
                         }
202
 
                         break;
203
 
                        case 1: /* scanning device stanza */
204
 
                         if (*line == '*' || *line == 0) continue;
205
 
                         if (*line != '\t' && *line != ' ')
206
 
                         {
207
 
                           /* name is found without stanza device  */
208
 
                           /* probably a good printer ???               */
209
 
                           free (line);
210
 
                           SAFE_FREE(pName);
211
 
                           x_fclose(pfile);
212
 
                           return(True);
213
 
                          }
214
 
                        
215
 
                          if (strlocate(line,"backend"))
216
 
                          {
217
 
                                /* it's a device, not a virtual printer*/
218
 
                                iEtat = 0;
219
 
                          }
220
 
                          else if (strlocate(line,"device"))
221
 
                          {
222
 
                                /* it's a good virtual printer */
223
 
                                free (line);
224
 
                                SAFE_FREE(pName);
225
 
                                x_fclose(pfile);
226
 
                                return(True);
227
 
                          }
228
 
                          break;
229
 
                }
230
 
        }
231
 
        free (pName);
232
 
        x_fclose(pfile);
233
 
        return(False);
234
 
}
235
 
#endif /* AIX */
236
 
 
237
 
 
238
 
/***************************************************************************
239
 
Scan printcap file pszPrintcapname for a printer called pszPrintername. 
240
 
Return True if found, else False. Returns False on error, too, after logging 
241
 
the error at level 0. For generality, the printcap name may be passed - if
242
 
passed as NULL, the configuration will be queried for the name. 
243
 
***************************************************************************/
244
 
BOOL pcap_printername_ok(const char *pszPrintername, const char *pszPrintcapname)
245
 
{
246
 
  char *line=NULL;
247
 
  const char *psz;
248
 
  char *p,*q;
249
 
  XFILE *pfile;
250
 
 
251
 
  if (pszPrintername == NULL || pszPrintername[0] == '\0')
252
 
    {
253
 
      DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
254
 
      return(False);
255
 
    }
256
 
 
257
 
  /* only go looking if no printcap name supplied */
258
 
  if ((psz = pszPrintcapname) == NULL || psz[0] == '\0')
259
 
    if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
260
 
      {
261
 
        DEBUG(0,( "No printcap file name configured!\n"));
262
 
        return(False);
263
 
      }
 
63
 
 
64
typedef struct pcap_cache {
 
65
        char *name;
 
66
        char *comment;
 
67
        struct pcap_cache *next;
 
68
} pcap_cache_t;
 
69
 
 
70
static pcap_cache_t *pcap_cache = NULL;
 
71
 
 
72
BOOL pcap_cache_add(const char *name, const char *comment)
 
73
{
 
74
        pcap_cache_t *p;
 
75
 
 
76
        if (name == NULL || ((p = SMB_MALLOC_P(pcap_cache_t)) == NULL))
 
77
                return False;
 
78
 
 
79
        p->name = SMB_STRDUP(name);
 
80
        p->comment = (comment && *comment) ? SMB_STRDUP(comment) : NULL;
 
81
 
 
82
        p->next = pcap_cache;
 
83
        pcap_cache = p;
 
84
 
 
85
        return True;
 
86
}
 
87
 
 
88
static void pcap_cache_destroy(pcap_cache_t *cache)
 
89
{
 
90
        pcap_cache_t *p, *next;
 
91
 
 
92
        for (p = cache; p != NULL; p = next) {
 
93
                next = p->next;
 
94
 
 
95
                SAFE_FREE(p->name);
 
96
                SAFE_FREE(p->comment);
 
97
                SAFE_FREE(p);
 
98
        }
 
99
}
 
100
 
 
101
BOOL pcap_cache_loaded(void)
 
102
{
 
103
        return (pcap_cache != NULL);
 
104
}
 
105
 
 
106
void pcap_cache_reload(void)
 
107
{
 
108
        const char *pcap_name = lp_printcapname();
 
109
        BOOL pcap_reloaded = False;
 
110
        pcap_cache_t *tmp_cache = NULL;
 
111
        XFILE *pcap_file;
 
112
        char *pcap_line;
 
113
 
 
114
        DEBUG(3, ("reloading printcap cache\n"));
 
115
 
 
116
        /* only go looking if no printcap name supplied */
 
117
        if (pcap_name == NULL || *pcap_name == 0) {
 
118
                DEBUG(0, ("No printcap file name configured!\n"));
 
119
                return;
 
120
        }
 
121
 
 
122
        tmp_cache = pcap_cache;
 
123
        pcap_cache = NULL;
264
124
 
265
125
#ifdef HAVE_CUPS
266
 
    if (strequal(psz, "cups"))
267
 
       return (cups_printername_ok(pszPrintername));
268
 
#endif /* HAVE_CUPS */
 
126
        if (strequal(pcap_name, "cups")) {
 
127
                pcap_reloaded = cups_cache_reload();
 
128
                goto done;
 
129
        }
 
130
#endif
269
131
 
270
 
#ifdef SYSV
271
 
    if (strequal(psz, "lpstat"))
272
 
       return (sysv_printername_ok(pszPrintername));
 
132
#if defined(SYSV) || defined(HPUX)
 
133
        if (strequal(pcap_name, "lpstat")) {
 
134
                pcap_reloaded = sysv_cache_reload();
 
135
                goto done;
 
136
        }
273
137
#endif
274
138
 
275
139
#ifdef AIX
276
 
  if (strlocate(psz,"/qconfig"))
277
 
     return(ScanQconfig(psz,pszPrintername));
 
140
        if (strstr_m(pcap_name, "/qconfig") != NULL) {
 
141
                pcap_reloaded = aix_cache_reload();
 
142
                goto done;
 
143
        }
278
144
#endif
279
145
 
280
 
  if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
281
 
    {
282
 
      DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
283
 
      return(False);
284
 
    }
285
 
 
286
 
  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
287
 
    {
288
 
      if (*line == '#' || *line == 0)
289
 
        continue;
290
 
 
291
 
      /* now we have a real printer line - cut it off at the first : */      
292
 
      p = strchr_m(line,':');
293
 
      if (p) *p = 0;
 
146
        /* handle standard printcap - moved from pcap_printer_fn() */
 
147
 
 
148
        if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) {
 
149
                DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name));
 
150
                goto done;
 
151
        }
 
152
 
 
153
        for (; (pcap_line = fgets_slash(NULL, sizeof(pstring), pcap_file)) != NULL; safe_free(pcap_line)) {
 
154
                pstring name, comment;
 
155
                char *p, *q;
 
156
 
 
157
                if (*pcap_line == '#' || *pcap_line == 0)
 
158
                        continue;
 
159
 
 
160
                /* now we have a real printer line - cut at the first : */      
 
161
                if ((p = strchr_m(pcap_line, ':')) != NULL)
 
162
                        *p = 0;
294
163
      
295
 
      /* now just check if the name is in the list */
296
 
      /* NOTE: I avoid strtok as the fn calling this one may be using it */
297
 
      for (p=line; p; p=q)
298
 
        {
299
 
          if ((q = strchr_m(p,'|'))) *q++ = 0;
300
 
 
301
 
          if (strequal(p,pszPrintername))
302
 
            {
303
 
              SAFE_FREE(line);
304
 
              x_fclose(pfile);
305
 
              return(True);           
306
 
            }
307
 
          p = q;
308
 
        }
309
 
    }
310
 
 
311
 
  x_fclose(pfile);
312
 
  return(False);
313
 
}
314
 
 
 
164
                /*
 
165
                 * now find the most likely printer name and comment 
 
166
                 * this is pure guesswork, but it's better than nothing
 
167
                 */
 
168
                for (*name = *comment = 0, p = pcap_line; p != NULL; p = q) {
 
169
                        BOOL has_punctuation;
 
170
 
 
171
                        if ((q = strchr_m(p, '|')) != NULL)
 
172
                                *q++ = 0;
 
173
 
 
174
                        has_punctuation = (strchr_m(p, ' ') ||
 
175
                                           strchr_m(p, '\t') ||
 
176
                                           strchr_m(p, '(') ||
 
177
                                           strchr_m(p, ')'));
 
178
 
 
179
                        if (strlen(p) > strlen(comment) && has_punctuation) {
 
180
                                pstrcpy(comment, p);
 
181
                                continue;
 
182
                        }
 
183
 
 
184
                        if (strlen(p) <= MAXPRINTERLEN &&
 
185
                            strlen(p) > strlen(name) && !has_punctuation) {
 
186
                                if (!*comment)
 
187
                                        pstrcpy(comment, name);
 
188
 
 
189
                                pstrcpy(name, p);
 
190
                                continue;
 
191
                        }
 
192
 
 
193
                        if (!strchr_m(comment, ' ') &&
 
194
                            strlen(p) > strlen(comment)) {
 
195
                                pstrcpy(comment, p);
 
196
                                continue;
 
197
                        }
 
198
                }
 
199
 
 
200
                comment[60] = 0;
 
201
                name[MAXPRINTERLEN] = 0;
 
202
 
 
203
                if (*name && !pcap_cache_add(name, comment)) {
 
204
                        x_fclose(pcap_file);
 
205
                        goto done;
 
206
                }
 
207
        }
 
208
 
 
209
        x_fclose(pcap_file);
 
210
        pcap_reloaded = True;
 
211
 
 
212
done:
 
213
        DEBUG(3, ("reload status: %s\n", (pcap_reloaded) ? "ok" : "error"));
 
214
 
 
215
        if (pcap_reloaded)
 
216
                pcap_cache_destroy(tmp_cache);
 
217
        else {
 
218
                pcap_cache_destroy(pcap_cache);
 
219
                pcap_cache = tmp_cache;
 
220
        }
 
221
 
 
222
        return;
 
223
}
 
224
 
 
225
 
 
226
BOOL pcap_printername_ok(const char *printername)
 
227
{
 
228
        pcap_cache_t *p;
 
229
 
 
230
        for (p = pcap_cache; p != NULL; p = p->next)
 
231
                if (strequal(p->name, printername))
 
232
                        return True;
 
233
 
 
234
        return False;
 
235
}
315
236
 
316
237
/***************************************************************************
317
238
run a function on each printer name in the printcap file. The function is 
318
239
passed the primary name and the comment (if possible). Note the fn() takes
319
240
strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed
320
241
to return DOS codepage. FIXME !! JRA.
 
242
 
 
243
XXX: I'm not sure if this comment still applies.. Anyone?  -Rob
321
244
***************************************************************************/
322
245
void pcap_printer_fn(void (*fn)(char *, char *))
323
246
{
324
 
  pstring name,comment;
325
 
  char *line;
326
 
  char *psz;
327
 
  char *p,*q;
328
 
  XFILE *pfile;
329
 
 
330
 
  /* only go looking if no printcap name supplied */
331
 
  if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
332
 
    {
333
 
      DEBUG(0,( "No printcap file name configured!\n"));
334
 
      return;
335
 
    }
336
 
 
337
 
#ifdef HAVE_CUPS
338
 
    if (strequal(psz, "cups")) {
339
 
      cups_printer_fn(fn);
340
 
      return;
341
 
    }
342
 
#endif /* HAVE_CUPS */
343
 
 
344
 
#ifdef SYSV
345
 
    if (strequal(psz, "lpstat")) {
346
 
      sysv_printer_fn(fn);
347
 
      return;
348
 
    }
349
 
#endif
350
 
 
351
 
#ifdef AIX
352
 
  if (strlocate(psz,"/qconfig"))
353
 
  {
354
 
        ScanQconfig_fn(psz,fn);
355
 
     return;
356
 
  }
357
 
#endif
358
 
 
359
 
  if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
360
 
    {
361
 
      DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
362
 
      return;
363
 
    }
364
 
 
365
 
  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
366
 
    {
367
 
      if (*line == '#' || *line == 0)
368
 
        continue;
369
 
 
370
 
      /* now we have a real printer line - cut it off at the first : */      
371
 
      p = strchr_m(line,':');
372
 
      if (p) *p = 0;
373
 
      
374
 
      /* now find the most likely printer name and comment 
375
 
       this is pure guesswork, but it's better than nothing */
376
 
      *name = 0;
377
 
      *comment = 0;
378
 
      for (p=line; p; p=q)
379
 
        {
380
 
          BOOL has_punctuation;
381
 
          if ((q = strchr_m(p,'|'))) *q++ = 0;
382
 
 
383
 
          has_punctuation = (strchr_m(p,' ') || strchr_m(p,'\t') || strchr_m(p,'(') || strchr_m(p,')'));
384
 
 
385
 
          if (strlen(p)>strlen(comment) && has_punctuation)
386
 
            {
387
 
              pstrcpy(comment,p);
388
 
              continue;
389
 
            }
390
 
 
391
 
          if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation)
392
 
            {
393
 
              if (!*comment) pstrcpy(comment,name);
394
 
              pstrcpy(name,p);
395
 
              continue;
396
 
            }
397
 
 
398
 
          if (!strchr_m(comment,' ') && 
399
 
              strlen(p) > strlen(comment))
400
 
            {
401
 
                    pstrcpy(comment,p);
402
 
                    continue;
403
 
            }
404
 
        }
405
 
 
406
 
      comment[60] = 0;
407
 
      name[MAXPRINTERLEN] = 0;
408
 
 
409
 
      if (*name) 
410
 
        fn(name,comment);
411
 
    }
412
 
  x_fclose(pfile);
 
247
        pcap_cache_t *p;
 
248
 
 
249
        for (p = pcap_cache; p != NULL; p = p->next)
 
250
                fn(p->name, p->comment);
 
251
 
 
252
        return;
413
253
}