]> arthur.barton.de Git - netatalk.git/blob - etc/papd/ppd.c
786ee9c69e4b888e6c039c61da03cc36cecb9f15
[netatalk.git] / etc / papd / ppd.c
1 /*
2  * $Id: ppd.c,v 1.14 2009-01-21 04:04:20 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 static int ppd_inited;
55
56 static void ppd_init()
57 {
58     if (ppd_inited)
59         return;
60
61     ppd_inited++;
62
63     if (printer->p_ppdfile)
64         read_ppd( printer->p_ppdfile, 0 );
65 }
66 #endif /* SHOWPPD */
67
68
69 /* quick and ugly hack to be able to read
70    ppd files with Mac line ending */
71 static char* my_fgets(buf, bufsize, stream) 
72     char   *buf;
73     size_t bufsize;
74     FILE   *stream;
75 {
76     int p;           /* uninitialized, OK 310105 */
77     size_t count = 0;
78  
79     while (count < (bufsize - 1) && EOF != (p=fgetc(stream))) {
80         buf[count] = p;
81         count++;
82         if ( p == '\r' || p == '\n')
83            break;
84     }
85
86     if (p == EOF && count == 0)
87         return NULL;
88
89     /* translate line endings */
90     if ( buf[count - 1] == '\r')
91         buf[count - 1] = '\n';
92
93     buf[count] = 0;
94     return buf;
95 }
96
97 static struct ppdent *getppdent( stream )
98     FILE        *stream;
99 {
100     static char                 buf[ 1024 ];
101     static struct ppdent        ppdent;
102     char                        *p, *q;
103
104     ppdent.pe_main = ppdent.pe_option = ppdent.pe_translation =
105             ppdent.pe_value = NULL;
106
107     while (( p = my_fgets( buf, sizeof( buf ), stream )) != NULL ) {
108         if ( *p != '*' ) {      /* main key word */
109             continue;
110         }
111         if ( p[ strlen( p ) - 1 ] != '\n') {
112             LOG(log_error, logtype_papd, "getppdent: line too long" );
113             continue;
114         }
115
116         q = p;
117         while ( (*p != ' ') && (*p != '\t') && (*p != ':') && (*p != '\n') ) {
118             p++;
119         }
120         if ( (*( q + 1 ) == '%') || (*( q + 1 ) == '?') ) {     /* comments & queries */
121             continue;
122         }
123         ppdent.pe_main = q;
124         if ( *p == '\n' ) {
125             *p = '\0';
126             ppdent.pe_option = ppdent.pe_translation = ppdent.pe_value = NULL;
127             return( &ppdent );
128         }
129
130         if ( *p != ':' ) {      /* option key word */
131             *p++ = '\0';
132
133             while ( (*p == ' ') || (*p == '\t') ) {
134                 p++;
135             }
136
137             q = p;
138             while ( (*p != ':') && (*p != '/') && (*p != '\n') ) {
139                 p++;
140             }
141
142             if ( *p == '\n' ) {
143                 continue;
144             }
145
146             ppdent.pe_option = q;
147             if ( *p == '/' ) {  /* translation string */
148                 *p++ = '\0';
149                 q = p;
150                 while ( *p != ':' && *p != '\n' ) {
151                     p++;
152                 }
153                 if ( *p != ':' ) {
154                     continue;
155                 }
156
157                 ppdent.pe_translation = q;
158             } else {
159                 ppdent.pe_translation = NULL;
160             }
161         }
162         *p++ = '\0';
163
164         while ( (*p == ' ') || (*p == '\t') ) {
165             p++;
166         }
167
168         /* value */
169         q = p;
170         while ( *p != '\n' ) {
171             p++;
172         }
173         *p = '\0';
174         ppdent.pe_value = q;
175
176         return( &ppdent );
177     }
178
179     return( NULL );
180 }
181
182 int read_ppd( file, fcnt )
183     char        *file;
184     int         fcnt;
185 {
186     FILE                *ppdfile;
187     struct ppdent       *pe;
188     struct ppd_feature  *pfe;
189     struct ppd_font     *pfo;
190
191     if ( fcnt > 20 ) {
192         LOG(log_error, logtype_papd, "read_ppd: %s: Too many files!", file );
193         return( -1 );
194     }
195
196     if (( ppdfile = fopen( file, "r" )) == NULL ) {
197         LOG(log_error, logtype_papd, "read_ppd %s: %s", file, strerror(errno) );
198         return( -1 );
199     }
200
201     while (( pe = getppdent( ppdfile )) != NULL ) {
202         /* *Include files */
203         if ( strcmp( pe->pe_main, "*Include" ) == 0 ) {
204             read_ppd( pe->pe_value, fcnt + 1 );
205             continue;
206         }
207
208         /* *Font */
209         if ( strcmp( pe->pe_main, "*Font" ) == 0 && pe->pe_option ) {
210             for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) {
211                 if ( strcmp( pfo->pd_font, pe->pe_option ) == 0 ) {
212                     break;
213                 }
214             }
215             if ( pfo ) {
216                 continue;
217             }
218
219             if (( pfo = (struct ppd_font *)malloc( sizeof( struct ppd_font )))
220                     == NULL ) {
221                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
222                 exit( 1 );
223             }
224             if (( pfo->pd_font =
225                     (char *)malloc( strlen( pe->pe_option ) + 1 )) == NULL ) {
226                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
227                 exit( 1 );
228             }
229             strcpy( pfo->pd_font, pe->pe_option );
230             pfo->pd_next = ppd_fonts;
231             ppd_fonts = pfo;
232             continue;
233         }
234
235
236         /* Features */
237         for ( pfe = ppd_features; pfe->pd_name; pfe++ ) {
238             if ( strcmp( pe->pe_main, pfe->pd_name ) == 0 ) {
239                 break;
240             }
241         }
242         if ( pfe->pd_name && pe->pe_value ) { 
243             if (( pfe->pd_value =
244                     (char *)malloc( strlen( pe->pe_value ) + 1 )) == NULL ) {
245                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
246                 exit( 1 );
247             }
248
249             strcpy( pfe->pd_value, pe->pe_value );
250             continue;
251         }
252     }
253
254     fclose( ppdfile );
255     return( 0 );
256 }
257
258 struct ppd_font *ppd_font( font )
259     char        *font;
260 {
261     struct ppd_font     *pfo;
262
263 #ifndef SHOWPPD
264     if ( ! ppd_inited ) {
265         ppd_init();
266     }
267 #endif /* SHOWPPD */
268
269     for ( pfo = ppd_fonts; pfo; pfo = pfo->pd_next ) {
270         if ( strcmp( pfo->pd_font, font ) == 0 ) {
271             return( pfo );
272         }
273     }
274     return( NULL );
275 }
276
277 struct ppd_feature *ppd_feature( feature, len )
278     const char  *feature;
279     int         len;
280 {
281     struct ppd_feature  *pfe;
282     char                ppd_feature_main[ 256 ];
283     const char          *end, *p;
284     char                *q;
285
286 #ifndef SHOWPPD
287     if ( ! ppd_inited ) {
288         ppd_init();
289     }
290 #endif /* SHOWPPD */
291
292     for ( end = feature + len, p = feature, q = ppd_feature_main;
293             (p <= end) && (*p != '\n') && (*p != '\r'); p++, q++ ) {
294         *q = *p;
295     }
296     if ( p > end ) {
297         return( NULL );
298     }
299     *q = '\0';
300
301     for ( pfe = ppd_features; pfe->pd_name; pfe++ ) {
302         if ( (strcmp( pfe->pd_name, ppd_feature_main ) == 0) && pfe->pd_value ) {
303             return( pfe );
304         }
305     }
306
307     return( NULL );
308 }