]> arthur.barton.de Git - netatalk.git/blob - etc/papd/queries.c
Stop papd from stripping '"' from PPD values. This prevented proper
[netatalk.git] / etc / papd / queries.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #include <string.h>
7 #include <sys/syslog.h>
8 #include <sys/param.h>
9 #include <sys/time.h>
10 #include <sys/types.h>
11 #include <netatalk/at.h>
12 #include <atalk/atp.h>
13
14 #ifdef KRB
15 #ifdef SOLARIS
16 #include <kerberos/krb.h>
17 #else
18 #include <krb.h>
19 #endif
20 #endif KRB
21
22 #include "file.h"
23 #include "comment.h"
24 #include "printer.h"
25 #include "ppd.h"
26
27 cq_default( in, out )
28     struct papfile      *in, *out;
29 {
30     char                *start, *stop, *p;
31     struct comment      *comment = compeek();
32
33     for (;;) {
34         switch ( markline( &start, &stop, in )) {
35         case 0 :
36             return( 0 );
37
38         case -1 :
39             return( CH_MORE );
40         }
41
42         if ( comgetflags() == 0 ) {     /* started */
43             if ( comment->c_end ) {
44                 comsetflags( 1 );
45             } else {
46                 compop();
47                 consumetomark( start, stop, in );
48                 return( CH_DONE );
49             }
50         } else {
51             /* return default */
52             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
53                 for ( p = start; p < stop; p++ ) {
54                     if ( *p == ':' ) {
55                         break;
56                     }
57                 }
58                 p++;
59                 while ( *p == ' ' ) {
60                     p++;
61                 }
62
63                 *stop = '\n';
64                 APPEND( out, p, stop - p + 1 );
65                 compop();
66                 consumetomark( start, stop, in );
67                 return( CH_DONE );
68             }
69         }
70
71         consumetomark( start, stop, in );
72     }
73 }
74
75 #ifdef KRB
76 char    *LoginOK = "LoginOK\n";
77 char    *LoginFailed = "LoginFailed\n";
78
79 #define h2b(x)  (isdigit((x))?(x)-'0':(isupper((x))?(x)-'A':(x)-'a')+10)
80
81 cq_k4login( in, out )
82     struct papfile      *in, *out;
83 {
84     char                *start, *stop, *p;
85     unsigned char       *t;
86     struct comment      *comment = compeek();
87     KTEXT_ST            tkt;
88     AUTH_DAT            ad;
89     int                 rc, i;
90
91     switch ( markline( &start, &stop, in )) {
92     case 0 :
93         return( 0 );
94
95     case -1 :
96         return( CH_MORE );
97     }
98
99     p = start + strlen( comment->c_begin );
100     while ( *p == ' ' ) {
101         p++;
102     }
103
104     bzero( &tkt, sizeof( tkt ));
105     for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) {
106         *t = ( h2b( (unsigned char)*p ) << 4 ) +
107                 h2b( (unsigned char)*( p + 1 ));
108     }
109     tkt.length = i;
110
111     if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name,
112             0, &ad, "" )) != RD_AP_OK ) {
113         syslog( LOG_ERR, "cq_k4login: %s", krb_err_txt[ rc ] );
114         APPEND( out, LoginFailed, strlen( LoginFailed ));
115         compop();
116         consumetomark( start, stop, in );
117         return( CH_DONE );
118     }
119     syslog( LOG_INFO, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst,
120             ad.prealm );
121     lp_person( ad.pname );
122     lp_host( ad.prealm );
123
124     APPEND( out, LoginOK, strlen( LoginOK ));
125     compop();
126     consumetomark( start, stop, in );
127     return( CH_DONE );
128 }
129
130 char    *uameth = "UMICHKerberosIV\n*\n";
131
132 cq_uameth( in, out )
133     struct papfile      *in, *out;
134 {
135     char                *start, *stop;
136     struct comment      *c, *comment = compeek();
137
138     for (;;) {
139         switch ( markline( &start, &stop, in )) {
140         case 0 :
141             return( 0 );
142
143         case -1 :
144             return( CH_MORE );
145         }
146
147         if ( comgetflags() == 0 ) {     /* start */
148             if (( printer->p_flags & P_AUTH ) == 0 ) {  /* no kerberos */
149                 if ( comswitch( queries, cq_default ) < 0 ) {
150                     syslog( LOG_ERR, "cq_uameth: can't find default!" );
151                     exit( 1 );
152                 }
153                 return( CH_DONE );
154             }
155             comsetflags( 1 );
156         } else {
157             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */
158                 APPEND( out, uameth, strlen( uameth ));
159                 compop();
160                 return( CH_DONE );
161             }
162         }
163
164         consumetomark( start, stop, in );
165     }
166 }
167 #endif KRB
168
169 gq_true( out )
170     struct papfile      *out;
171 {
172     if ( printer->p_flags & P_SPOOLED ) {
173         APPEND( out, "true\n", 5 );
174         return( 0 );
175     } else {
176         return( -1 );
177     }
178 }
179
180 gq_pagecost( out )
181     struct papfile      *out;
182 {
183     char                cost[ 60 ];
184
185     /* check for spooler? XXX */
186     if ( printer->p_pagecost_msg != NULL ) {
187         APPEND( out, printer->p_pagecost_msg,
188                 strlen( printer->p_pagecost_msg ));
189     } else if ( printer->p_flags & P_ACCOUNT ) {
190 #ifdef ABS_PRINT
191         lp_pagecost();
192 #endif ABS_PRINT
193         sprintf( cost, "%d", printer->p_pagecost );
194         APPEND( out, cost, strlen( cost ));
195     } else {
196         return( -1 );
197     }
198     APPEND( out, "\n", 1 );
199     return( 0 );
200 }
201
202 #ifdef ABS_PRINT
203 gq_balance( out )
204     struct papfile      *out;
205 {
206     char                balance[ 60 ];
207
208     if ( lp_pagecost() != 0 ) {
209         return( -1 );
210     }
211     sprintf( balance, "$%1.2f\n", printer->p_balance );
212     APPEND( out, balance, strlen( balance ));
213     return( 0 );
214 }
215 #endif ABS_PRINT
216
217 struct genquery {
218     char        *gq_name;
219     int         (*gq_handler)();
220 } genqueries[] = {
221     { "UMICHCostPerPage", gq_pagecost },
222 #ifdef notdef
223     { "UMICHUserBalance", gq_balance },
224 #endif 
225     { "UMICHListQueue", gq_true },
226     { "UMICHDeleteJob", gq_true },
227     { NULL },
228 };
229
230 cq_query( in, out )
231     struct papfile      *in, *out;
232 {
233     char                *start, *stop, *p, *q;
234     struct comment      *comment = compeek();
235     struct genquery     *gq;
236
237
238     for (;;) {
239         switch ( markline( &start, &stop, in )) {
240         case 0 :
241             return( 0 );
242
243         case -1 :
244             return( CH_MORE );
245         }
246
247         if ( comgetflags() == 0 ) {     /* started */
248             comsetflags( 1 );
249
250             for ( p = start; p < stop; p++ ) {
251                 if ( *p == ':' ) {
252                     break;
253                 }
254             }
255
256             for ( p++; p < stop; p++ ) {
257                 if ( *p != ' ' && *p != '\t' ) {
258                     break;
259                 }
260             }
261
262             for ( q = p; q < stop; q++ ) {
263                 if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) {
264                     break;
265                 }
266             }
267
268             for ( gq = genqueries; gq->gq_name; gq++ ) {
269                 if (( strlen( gq->gq_name ) == q - p ) &&
270                         ( strncmp( gq->gq_name, p, q - p ) == 0 )) {
271                     break;
272                 }
273             }
274             if ( gq->gq_name == NULL || gq->gq_handler == NULL ||
275                     (gq->gq_handler)( out ) < 0 ) {
276                 if ( comswitch( queries, cq_default ) < 0 ) {
277                     syslog( LOG_ERR, "cq_feature: can't find default!" );
278                     exit( 1 );
279                 }
280                 return( CH_DONE );
281             }
282         } else {
283             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
284                 compop();
285                 consumetomark( start, stop, in );
286                 return( CH_DONE );
287             }
288         }
289
290         consumetomark( start, stop, in );
291     }
292 }
293
294 cq_font_answer( start, stop, out )
295     char                *start, *stop;
296     struct papfile      *out;
297 {
298     char                *p, *q, buf[ 256 ];
299     struct ppd_font     *pfo;
300
301     p = start;
302     while ( p < stop ) {
303         while (( *p == ' ' || *p == '\t' ) && p < stop ) {
304             p++;
305         }
306
307         q = buf;
308         while ( *p != ' ' && *p != '\t' &&
309                 *p != '\n' && *p != '\r' && p < stop ) {
310             *q++ = *p++;
311         }
312
313         if ( q != buf ) {
314             *q = '\0';
315
316             APPEND( out, "/", 1 );
317             APPEND( out, buf, strlen( buf ));
318             APPEND( out, ":", 1 );
319
320             if (( pfo = ppd_font( buf )) == NULL ) {
321                 APPEND( out, "No\n", 3 );
322             } else {
323                 APPEND( out, "Yes\n", 4 );
324             }
325         }
326     }
327
328     return;
329 }
330
331 cq_font( in, out )
332     struct papfile      *in, *out;
333 {
334     char                *start, *stop, *p;
335     struct comment      *comment = compeek();
336
337     for (;;) {
338         switch ( markline( &start, &stop, in )) {
339         case 0 :
340             return( 0 );
341
342         case -1 :
343             return( CH_MORE );
344         }
345
346         if ( comgetflags() == 0 ) {
347             comsetflags( 1 );
348
349             for ( p = start; p < stop; p++ ) {
350                 if ( *p == ':' ) {
351                     break;
352                 }
353             }
354             p++;
355
356             cq_font_answer( p, stop, out );
357         } else {
358             if ( comgetflags() == 1 &&
359                     comcmp( start, stop, comcont, 0 ) == 0 ) {
360                 /* continuation */
361
362                 for ( p = start; p < stop; p++ ) {
363                     if ( *p == ' ' ) {
364                         break;
365                     }
366                 }
367                 p++;
368
369                 cq_font_answer( p, stop, out );
370             } else {
371                 comsetflags( 2 );
372                 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
373                     APPEND( out, "*\n", 2 );
374                     compop();
375                     consumetomark( start, stop, in );
376                     return( CH_DONE );
377                 }
378             }
379         }
380
381         consumetomark( start, stop, in );
382     }
383 }
384
385 cq_feature( in, out )
386     struct papfile      *in, *out;
387 {
388     char                *start, *stop, *p;
389     struct comment      *comment = compeek();
390     struct ppd_feature  *pfe;
391
392     for (;;) {
393         switch ( markline( &start, &stop, in )) {
394         case 0 :
395             return( 0 );
396
397         case -1 :
398             return( CH_MORE );
399         }
400
401         if ( comgetflags() == 0 ) {
402             comsetflags( 1 );
403
404             /* parse for feature */
405             for ( p = start; p < stop; p++ ) {
406                 if ( *p == ':' ) {
407                     break;
408                 }
409             }
410             p++;
411             while ( *p == ' ' ) {
412                 p++;
413             }
414
415             if (( pfe = ppd_feature( p, stop - p )) == NULL ) {
416                 if ( comswitch( queries, cq_default ) < 0 ) {
417                     syslog( LOG_ERR, "cq_feature: can't find default!" );
418                     exit( 1 );
419                 }
420                 return( CH_DONE );
421             }
422
423             APPEND( out, pfe->pd_value, strlen( pfe->pd_value ));
424             APPEND( out, "\r", 1 );
425         } else {
426             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
427                 compop();
428                 consumetomark( start, stop, in );
429                 return( CH_DONE );
430             }
431         }
432
433         consumetomark( start, stop, in );
434     }
435 }
436
437 static const char       *psver = "*PSVersion\n";
438 static const char       *prod = "*Product\n";
439
440 cq_printer( in, out )
441     struct papfile      *in, *out;
442 {
443     char                *start, *stop, *p;
444     struct comment      *c, *comment = compeek();
445     struct ppd_feature  *pdpsver, *pdprod;
446
447     for (;;) {
448         switch ( markline( &start, &stop, in )) {
449         case 0 :
450             return( 0 );
451
452         case -1 :
453             return( CH_MORE );
454         }
455
456         if ( comgetflags() == 0 ) {
457             comsetflags( 1 );
458
459             if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) {
460                 if ( comswitch( queries, cq_default ) < 0 ) {
461                     syslog( LOG_ERR, "cq_printer: can't find default!" );
462                     exit( 1 );
463                 }
464                 return( CH_DONE );
465             }
466
467             for ( p = pdpsver->pd_value; *p != '\0'; p++ ) {
468                 if ( *p == ' ' ) {
469                     break;
470                 }
471             }
472             if ( *p == '\0' ) {
473                 syslog( LOG_ERR, "cq_printer: can't parse PSVersion!" );
474                 if ( comswitch( queries, cq_default ) < 0 ) {
475                     syslog( LOG_ERR, "cq_printer: can't find default!" );
476                     exit( 1 );
477                 }
478                 return( CH_DONE );
479             }
480
481             if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) {
482                 if ( comswitch( queries, cq_default ) < 0 ) {
483                     syslog( LOG_ERR, "cq_printer: can't find default!" );
484                     exit( 1 );
485                 }
486                 return( CH_DONE );
487             }
488
489             /* revision */
490             APPEND( out, p + 1, strlen( p + 1 ));
491             APPEND( out, "\r", 1 );
492
493             /* version */
494             APPEND( out, pdpsver->pd_value, p - pdpsver->pd_value );
495             APPEND( out, "\r", 1 );
496
497             /* product */
498             APPEND( out, pdprod->pd_value, strlen( pdprod->pd_value ));
499             APPEND( out, "\r", 1 );
500         } else {
501             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
502                 compop();
503                 consumetomark( start, stop, in );
504                 return( CH_DONE );
505             }
506         }
507
508         consumetomark( start, stop, in );
509     }
510 }
511
512 static const char       *rmjobfailed = "Failed\n";
513 static const char       *rmjobok = "Ok\n";
514
515 cq_rmjob( in, out )
516     struct papfile      *in, *out;
517 {
518     char                *start, *stop, *p;
519     int                 job;
520
521     switch ( markline( &start, &stop, in )) {
522     case 0 :
523         return( 0 );
524
525     case -1 :
526         return( CH_MORE );
527     }
528
529     for ( p = start; p < stop; p++ ) {
530         if ( *p == ' ' || *p == '\t' ) {
531             break;
532         }
533     }
534     for ( ; p < stop; p++ ) {
535         if ( *p != ' ' && *p != '\t' ) {
536             break;
537         }
538     }
539
540     *stop = '\0';
541     if ( p < stop && ( job = atoi( p )) > 0 ) {
542         lp_rmjob( job );
543         APPEND( out, rmjobok, strlen( rmjobok ));
544     } else {
545         APPEND( out, rmjobfailed, strlen( rmjobfailed ));
546     }
547
548     compop();
549     consumetomark( start, stop, in );
550     return( CH_DONE );
551 }
552
553 cq_listq( in, out )
554     struct papfile      *in, *out;
555 {
556     char                *start, *stop;
557
558     switch ( markline( &start, &stop, in )) {
559     case 0 :
560         return( 0 );
561
562     case -1 :
563         return( CH_MORE );
564     }
565
566     if ( lp_queue( out )) {
567         syslog( LOG_ERR, "cq_listq: lp_queue failed" );
568     }
569
570     compop();
571     consumetomark( start, stop, in );
572     return( CH_DONE );
573 }
574
575 /*
576  * All queries start with %%?Begin and end with %%?End.  Note that the
577  * "Begin"/"End" general queries have to be last.
578  */
579 struct comment  queries[] = {
580 #ifdef KRB
581     { "%%Login: UMICHKerberosIV", 0,                    cq_k4login,     0 },
582     { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth, C_FULL },
583 #endif KRB
584     { "%UMICHListQueue", 0,                             cq_listq, C_FULL },
585     { "%UMICHDeleteJob", 0,                             cq_rmjob,       0 },
586     { "%%?BeginQuery",          "%%?EndQuery",          cq_query,       0 },
587     { "%%?BeginFeatureQuery",   "%%?EndFeatureQuery",   cq_feature,     0 },
588     { "%%?BeginFontQuery",      "%%?EndFontQuery",      cq_font,        0 },
589     { "%%?BeginPrinterQuery",   "%%?EndPrinterQuery",   cq_printer, C_FULL },
590     { "%%?Begin",               "%%?End",               cq_default,     0 },
591     { 0 },
592 };