]> arthur.barton.de Git - netatalk.git/blob - etc/papd/ppd.c
merge from HEAD: Fix off-by-one error in my_fgets() which is used to process PPD...
[netatalk.git] / etc / papd / ppd.c
1 /*
2  * $Id: ppd.c,v 1.9.8.1.2.4 2009-01-19 02:23:16 didg Exp $
3  *
4  * Copyright (c) 1995 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <atalk/logger.h>
17 #include <sys/types.h>
18 #include <sys/param.h>
19 #include <sys/time.h>
20 #include <netatalk/at.h>
21 #include <atalk/atp.h>
22
23 #include "printer.h"
24 #include "ppd.h"
25
26 struct ppd_font         *ppd_fonts = NULL;
27
28 struct ppd_feature      ppd_features[] = {
29     { "*LanguageLevel", 0 },
30     { "*PSVersion",     0 },
31 #ifdef HAVE_CUPS
32     { "*FreeVM",        "33554432" },
33 #else
34     { "*FreeVM",        0 },
35 #endif
36     { "*Product",       0 },
37     { "*PCFileName",    0 },
38     { "*ModelName",     0 },
39     { "*NickName",      0 },
40     { "*ColorDevice",   0 },
41     { "*FaxSupport",    0 },
42     { "*TTRasterizer",  0 },
43     { 0, 0 },
44 };
45
46 struct ppdent {
47     char        *pe_main;
48     char        *pe_option;
49     char        *pe_translation;
50     char        *pe_value;
51 };
52
53 #ifndef SHOWPPD
54 int ppd_inited = 0;
55
56 int ppd_init()
57 {
58     if ( ppd_inited ) {
59         return( -1 );
60     }
61     ppd_inited++;
62
63     return read_ppd( printer->p_ppdfile, 0 );
64 }
65 #endif /* SHOWPPD */
66
67
68 /* quick and ugly hack to be able to read
69    ppd files with Mac line ending */
70 static char* my_fgets(buf, bufsize, stream) 
71     char   *buf;
72     size_t bufsize;
73     FILE   *stream;
74 {
75     int p;           /* uninitialized, OK 310105 */
76     size_t count = 0;
77  
78     while (count < (bufsize - 1) && EOF != (p=fgetc(stream))) {
79         buf[count] = p;
80         count++;
81         if ( p == '\r' || p == '\n')
82            break;
83     }
84
85     if (p == EOF && count == 0)
86         return NULL;
87
88     /* translate line endings */
89     if ( buf[count - 1] == '\r')
90         buf[count - 1] = '\n';
91
92     buf[count] = 0;
93     return buf;
94 }
95
96 struct ppdent *getppdent( stream )
97     FILE        *stream;
98 {
99     static char                 buf[ 1024 ];
100     static struct ppdent        ppdent;
101     char                        *p, *q;
102
103     ppdent.pe_main = ppdent.pe_option = ppdent.pe_translation =
104             ppdent.pe_value = NULL;
105
106     while (( p = my_fgets( buf, sizeof( buf ), stream )) != NULL ) {
107         if ( *p != '*' ) {      /* main key word */
108             continue;
109         }
110         if ( p[ strlen( p ) - 1 ] != '\n' && p[ strlen( p ) - 1 ] != '\r') {
111             LOG(log_error, logtype_papd, "getppdent: line too long" );
112             continue;
113         }
114
115         q = p;
116         while ( (*p != ' ') && (*p != '\t') && (*p != ':') && (*p != '\n') ) {
117             p++;
118         }
119         if ( (*( q + 1 ) == '%') || (*( q + 1 ) == '?') ) {     /* comments & queries */
120             continue;
121         }
122         ppdent.pe_main = q;
123         if ( *p == '\n' ) {
124             *p = '\0';
125             ppdent.pe_option = ppdent.pe_translation = ppdent.pe_value = NULL;
126             return( &ppdent );
127         }
128
129         if ( *p != ':' ) {      /* option key word */
130             *p++ = '\0';
131
132             while ( (*p == ' ') || (*p == '\t') ) {
133                 p++;
134             }
135
136             q = p;
137             while ( (*p != ':') && (*p != '/') && (*p != '\n') ) {
138                 p++;
139             }
140
141             if ( *p == '\n' ) {
142                 continue;
143             }
144
145             ppdent.pe_option = q;
146             if ( *p == '/' ) {  /* translation string */
147                 *p++ = '\0';
148                 q = p;
149                 while ( *p != ':' && *p != '\n' ) {
150                     p++;
151                 }
152                 if ( *p != ':' ) {
153                     continue;
154                 }
155
156                 ppdent.pe_translation = q;
157             } else {
158                 ppdent.pe_translation = NULL;
159             }
160         }
161         *p++ = '\0';
162
163         while ( (*p == ' ') || (*p == '\t') ) {
164             p++;
165         }
166
167         /* value */
168         q = p;
169         while ( *p != '\n' ) {
170             p++;
171         }
172         *p = '\0';
173         ppdent.pe_value = q;
174
175         return( &ppdent );
176     }
177
178     return( NULL );
179 }
180
181 int read_ppd( file, fcnt )
182     char        *file;
183     int         fcnt;
184 {
185     FILE                *ppdfile;
186     struct ppdent       *pe;
187     struct ppd_feature  *pfe;
188     struct ppd_font     *pfo;
189
190     if ( fcnt > 20 ) {
191         LOG(log_error, logtype_papd, "read_ppd: %s: Too many files!", file );
192         return( -1 );
193     }
194
195     if (( ppdfile = fopen( file, "r" )) == NULL ) {
196         LOG(log_error, logtype_papd, "read_ppd %s: %s", file, strerror(errno) );
197         return( -1 );
198     }
199
200     while (( pe = getppdent( ppdfile )) != NULL ) {
201         /* *Include files */
202         if ( strcmp( pe->pe_main, "*Include" ) == 0 ) {
203             read_ppd( pe->pe_value, fcnt + 1 );
204             continue;
205         }
206
207         /* *Font */
208         if ( strcmp( pe->pe_main, "*Font" ) == 0 ) {
209             for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) {
210                 if ( strcmp( pfo->pd_font, pe->pe_option ) == 0 ) {
211                     break;
212                 }
213             }
214             if ( pfo ) {
215                 continue;
216             }
217
218             if (( pfo = (struct ppd_font *)malloc( sizeof( struct ppd_font )))
219                     == NULL ) {
220                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
221                 exit( 1 );
222             }
223             if (( pfo->pd_font =
224                     (char *)malloc( strlen( pe->pe_option ) + 1 )) == NULL ) {
225                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
226                 exit( 1 );
227             }
228             strcpy( pfo->pd_font, pe->pe_option );
229             pfo->pd_next = ppd_fonts;
230             ppd_fonts = pfo;
231             continue;
232         }
233
234
235         /* Features */
236         for ( pfe = ppd_features; pfe->pd_name; pfe++ ) {
237             if ( strcmp( pe->pe_main, pfe->pd_name ) == 0 ) {
238                 break;
239             }
240         }
241         if ( pfe->pd_name ) { /*&& (pfe->pd_value == NULL) ) { */
242             if (( pfe->pd_value =
243                     (char *)malloc( strlen( pe->pe_value ) + 1 )) == NULL ) {
244                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
245                 exit( 1 );
246             }
247
248             strcpy( pfe->pd_value, pe->pe_value );
249             continue;
250         }
251     }
252
253     fclose( ppdfile );
254     return( 0 );
255 }
256
257 struct ppd_font *ppd_font( font )
258     char        *font;
259 {
260     struct ppd_font     *pfo;
261
262 #ifndef SHOWPPD
263     if ( ! ppd_inited ) {
264         ppd_init();
265     }
266 #endif /* SHOWPPD */
267
268     for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) {
269         if ( strcmp( pfo->pd_font, font ) == 0 ) {
270             return( pfo );
271         }
272     }
273     return( NULL );
274 }
275
276 struct ppd_feature *ppd_feature( feature, len )
277     const char  *feature;
278     int         len;
279 {
280     struct ppd_feature  *pfe;
281     char                ppd_feature_main[ 256 ];
282     const char          *end, *p;
283     char                *q;
284
285 #ifndef SHOWPPD
286     if ( ! ppd_inited ) {
287         ppd_init();
288     }
289 #endif /* SHOWPPD */
290
291     for ( end = feature + len, p = feature, q = ppd_feature_main;
292             (p <= end) && (*p != '\n') && (*p != '\r'); p++, q++ ) {
293         *q = *p;
294     }
295     if ( p > end ) {
296         return( NULL );
297     }
298     *q = '\0';
299
300     for ( pfe = ppd_features; pfe->pd_name; pfe++ ) {
301         if ( (strcmp( pfe->pd_name, ppd_feature_main ) == 0) && pfe->pd_value ) {
302             return( pfe );
303         }
304     }
305
306     return( NULL );
307 }