]> arthur.barton.de Git - netatalk.git/blob - etc/papd/queries.c
Use VERSION string instead of hard-coded value in gq_rbispoolerid response.
[netatalk.git] / etc / papd / queries.c
1 /*
2  * $Id: queries.c,v 1.13 2002-02-15 16:15:21 morgana Exp $
3  *
4  * Copyright (c) 1990,1994 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 <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <atalk/logger.h>
16 #include <sys/param.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <netatalk/at.h>
20 #include <atalk/atp.h>
21
22 #ifdef KRB
23 #ifdef SOLARIS
24 #include <kerberos/krb.h>
25 #else /* SOLARIS */
26 #include <krb.h>
27 #endif /* SOLARIS */
28 #endif /* KRB */
29
30 #include "file.h"
31 #include "comment.h"
32 #include "printer.h"
33 #include "ppd.h"
34 #include "lp.h"
35 #include "uam_auth.h"
36
37 int cq_default( struct papfile *, struct papfile * );
38 int cq_k4login( struct papfile *, struct papfile * );
39 int cq_uameth( struct papfile *, struct papfile * );
40
41 int gq_balance( struct papfile * );
42 int gq_pagecost( struct papfile * );
43 int gq_true( struct papfile * );
44 int gq_rbispoolerid( struct papfile * );
45 int gq_rbiuamlist( struct papfile * );
46
47 int cq_query( struct papfile *, struct papfile * );
48 void cq_font_answer( char *, char *, struct papfile * );
49 int cq_font( struct papfile *, struct papfile * );
50 int cq_feature( struct papfile *, struct papfile * );
51 int cq_printer( struct papfile *, struct papfile * );
52 int cq_rmjob( struct papfile *, struct papfile * );
53 int cq_listq( struct papfile *, struct papfile * );
54 int cq_rbilogin( struct papfile *, struct papfile * );
55
56
57
58 int cq_default( in, out )
59     struct papfile      *in, *out;
60 {
61     char                *start, *stop, *p;
62     int                 linelength, crlflength;
63     struct papd_comment *comment = compeek();
64
65     for (;;) {
66         switch ( markline( in, &start, &linelength, &crlflength )) {
67         case 0 :
68             return( 0 );
69
70         case -1 :
71             return( CH_MORE );
72         }
73
74         stop = start+linelength;
75
76         if ( comgetflags() == 0 ) {     /* started */
77             if ( comment->c_end ) {
78                 comsetflags( 1 );
79             } else {
80                 compop();
81                 CONSUME( in, linelength + crlflength );
82                 return( CH_DONE );
83             }
84         } else {
85             /* return default */
86             if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
87                 for ( p = start; p < stop; p++ ) {
88                     if ( *p == ':' ) {
89                         break;
90                     }
91                 }
92                 p++;
93                 while ( *p == ' ' ) {
94                     p++;
95                 }
96
97                 append( out, p, stop - p + crlflength );
98                 compop();
99                 CONSUME( in, linelength + crlflength );
100                 return( CH_DONE );
101             }
102         }
103
104         CONSUME( in, linelength + crlflength );
105     }
106 }
107
108 #ifdef KRB
109 char    *LoginOK = "LoginOK\n";
110 char    *LoginFailed = "LoginFailed\n";
111
112 #define h2b(x)  (isdigit((x))?(x)-'0':(isupper((x))?(x)-'A':(x)-'a')+10)
113
114 int cq_k4login( in, out )
115     struct papfile      *in, *out;
116 {
117     char                *start, *p;
118     int                 linelength, crlflength;
119     unsigned char       *t;
120     struct papd_comment *comment = compeek();
121     KTEXT_ST            tkt;
122     AUTH_DAT            ad;
123     int                 rc, i;
124
125     switch ( markline( in, &start, &linelength, &crlflength )) {
126     case 0 :
127         return( 0 );
128
129     case -1 :
130         return( CH_MORE );
131     }
132
133     p = start + strlen( comment->c_begin );
134     while ( *p == ' ' ) {
135         p++;
136     }
137
138     bzero( &tkt, sizeof( tkt ));
139     stop = start+linelength;
140     for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) {
141         *t = ( h2b( (unsigned char)*p ) << 4 ) +
142                 h2b( (unsigned char)*( p + 1 ));
143     }
144     tkt.length = i;
145
146     if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name,
147             0, &ad, "" )) != RD_AP_OK ) {
148         LOG(log_error, logtype_default, "cq_k4login: %s", krb_err_txt[ rc ] );
149         append( out, LoginFailed, strlen( LoginFailed ));
150         compop();
151         CONSUME( in, linelength + crlflength );
152         return( CH_DONE );
153     }
154     LOG(log_info, logtype_default, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst,
155             ad.prealm );
156     lp_person( ad.pname );
157     lp_host( ad.prealm );
158
159     append( out, LoginOK, strlen( LoginOK ));
160     compop();
161     CONSUME( in, linelength + crlflength);
162     return( CH_DONE );
163 }
164
165 char    *uameth = "UMICHKerberosIV\n*\n";
166
167 int cq_uameth( in, out )
168     struct papfile      *in, *out;
169 {
170     char                *start;
171     int                 linelength, crlflength;
172     struct papd_comment *c, *comment = compeek();
173
174     for (;;) {
175         switch ( markline( in, &start, &linelength, &crlflength )) {
176         case 0 :
177             return( 0 );
178
179         case -1 :
180             return( CH_MORE );
181         }
182
183         if ( comgetflags() == 0 ) {     /* start */
184             if (( printer->p_flags & P_KRB ) == 0 ) {   /* no kerberos */
185                 if ( comswitch( queries, cq_default ) < 0 ) {
186                     LOG(log_error, logtype_default, "cq_uameth: can't find default!" );
187                     exit( 1 );
188                 }
189                 return( CH_DONE );
190             }
191             comsetflags( 1 );
192         } else {
193             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */
194                 append( out, uameth, strlen( uameth ));
195                 compop();
196                 return( CH_DONE );
197             }
198         }
199
200         CONSUME( in, linelength + crlflength );
201     }
202 }
203 #endif /* KRB */
204
205 int gq_true( out )
206     struct papfile      *out;
207 {
208     if ( printer->p_flags & P_SPOOLED ) {
209         append( out, "true\n", 5 );
210         return( 0 );
211     } else {
212         return( -1 );
213     }
214 }
215
216 int gq_pagecost( out )
217     struct papfile      *out;
218 {
219     char                cost[ 60 ];
220
221     /* check for spooler? XXX */
222     if ( printer->p_pagecost_msg != NULL ) {
223         append( out, printer->p_pagecost_msg,
224                 strlen( printer->p_pagecost_msg ));
225     } else if ( printer->p_flags & P_ACCOUNT ) {
226 #ifdef ABS_PRINT
227         lp_pagecost();
228 #endif /* ABS_PRINT */
229         sprintf( cost, "%d", printer->p_pagecost );
230         append( out, cost, strlen( cost ));
231     } else {
232         return( -1 );
233     }
234     append( out, "\n", 1 );
235     return( 0 );
236 }
237
238 #ifdef ABS_PRINT
239 int gq_balance( out )
240     struct papfile      *out;
241 {
242     char                balance[ 60 ];
243
244     if ( lp_pagecost() != 0 ) {
245         return( -1 );
246     }
247     sprintf( balance, "$%1.2f\n", printer->p_balance );
248     append( out, balance, strlen( balance ));
249     return( 0 );
250 }
251 #endif /* ABS_PRINT */
252
253
254 /*
255  * Handler for RBISpoolerID
256  */
257
258 static const char *spoolerid = "(PAPD Spooler) VERSION\n";
259
260 int gq_rbispoolerid( out )
261     struct papfile      *out;
262 {
263     append( out, spoolerid, strlen( spoolerid ));
264     return(0);
265 }
266
267
268
269 /*
270  * Handler for RBIUAMListQuery
271  */
272
273 static const char *nouams = "*\n";
274
275 int gq_rbiuamlist( out )
276     struct papfile      *out;
277 {
278     char uamnames[128] = "\0";
279
280     if (printer->p_flags & P_AUTH_PSSP) {
281         if (getuamnames(UAM_SERVER_PRINTAUTH, uamnames) < 0) {
282             append(out, nouams, strlen(nouams));
283             return(0);
284         } else {
285             append(out, uamnames, strlen(uamnames));
286             return(0);
287         }
288     } else {
289         append(out, nouams, strlen(nouams));
290         return(0);
291     }
292 }
293
294
295 struct genquery {
296     char        *gq_name;
297     int         (*gq_handler)();
298 } genqueries[] = {
299     { "UMICHCostPerPage", gq_pagecost },
300 #ifdef notdef
301     { "UMICHUserBalance", gq_balance },
302 #endif /* notdef */
303     { "RBISpoolerID",   gq_rbispoolerid },
304     { "RBIUAMListQuery", gq_rbiuamlist },
305     { "ADOIsBinaryOK?", gq_true },
306     { "UMICHListQueue", gq_true },
307     { "UMICHDeleteJob", gq_true },
308     { NULL },
309 };
310
311 int cq_query( in, out )
312     struct papfile      *in, *out;
313 {
314     char                *start, *stop, *p, *q;
315     int                 linelength, crlflength;
316     struct papd_comment *comment = compeek();
317     struct genquery     *gq;
318
319
320     for (;;) {
321         switch ( markline( in, &start, &linelength, &crlflength )) {
322         case 0 :
323             return( 0 );
324
325         case -1 :
326             return( CH_MORE );
327         }
328
329         stop = start+linelength;
330
331         if ( comgetflags() == 0 ) {     /* started */
332             comsetflags( 1 );
333
334             for ( p = start; p < stop; p++ ) {
335                 if ( *p == ':' ) {
336                     break;
337                 }
338             }
339
340             for ( p++; p < stop; p++ ) {
341                 if ( *p != ' ' && *p != '\t' ) {
342                     break;
343                 }
344             }
345
346             for ( q = p; q < stop; q++ ) {
347                 if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) {
348                     break;
349                 }
350             }
351
352             for ( gq = genqueries; gq->gq_name; gq++ ) {
353                 if (( strlen( gq->gq_name ) == q - p ) &&
354                         ( strncmp( gq->gq_name, p, q - p ) == 0 )) {
355                     break;
356                 }
357             }
358             if ( gq->gq_name == NULL || gq->gq_handler == NULL ||
359                     (gq->gq_handler)( out ) < 0 ) {
360                 if ( comswitch( queries, cq_default ) < 0 ) {
361                     LOG(log_error, logtype_default, "cq_feature: can't find default!" );
362                     exit( 1 );
363                 }
364                 return( CH_DONE );
365             }
366         } else {
367             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
368                 compop();
369                 CONSUME( in, linelength + crlflength );
370                 return( CH_DONE );
371             }
372         }
373
374         CONSUME( in, linelength + crlflength );
375     }
376 }
377
378 void cq_font_answer( start, stop, out )
379     char                *start, *stop;
380     struct papfile      *out;
381 {
382     char                *p, *q, buf[ 256 ];
383     struct ppd_font     *pfo;
384
385     p = start;
386     while ( p < stop ) {
387         while (( *p == ' ' || *p == '\t' ) && p < stop ) {
388             p++;
389         }
390
391         q = buf;
392         while ( *p != ' ' && *p != '\t' &&
393                 *p != '\n' && *p != '\r' && p < stop ) {
394             *q++ = *p++;
395         }
396
397         if ( q != buf ) {
398             *q = '\0';
399
400             append( out, "/", 1 );
401             append( out, buf, strlen( buf ));
402             append( out, ":", 1 );
403
404             if (( pfo = ppd_font( buf )) == NULL ) {
405                 append( out, "No\n", 3 );
406             } else {
407                 append( out, "Yes\n", 4 );
408             }
409         }
410     }
411
412     return;
413 }
414
415 int cq_font( in, out )
416     struct papfile      *in, *out;
417 {
418     char                *start, *stop, *p;
419     int                 linelength, crlflength;
420     struct papd_comment *comment = compeek();
421
422     for (;;) {
423         switch ( markline( in, &start, &linelength, &crlflength )) {
424         case 0 :
425             return( 0 );
426
427         case -1 :
428             return( CH_MORE );
429         }
430
431         stop = start + linelength;
432
433         if ( comgetflags() == 0 ) {
434             comsetflags( 1 );
435
436             for ( p = start; p < stop; p++ ) {
437                 if ( *p == ':' ) {
438                     break;
439                 }
440             }
441             p++;
442
443             cq_font_answer( p, stop, out );
444         } else {
445             if ( comgetflags() == 1 &&
446                     comcmp( start, stop, comcont, 0 ) == 0 ) {
447                 /* continuation */
448
449                 for ( p = start; p < stop; p++ ) {
450                     if ( *p == ' ' ) {
451                         break;
452                     }
453                 }
454                 p++;
455
456                 cq_font_answer( p, stop, out );
457             } else {
458                 comsetflags( 2 );
459                 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
460                     append( out, "*\n", 2 );
461                     compop();
462                     CONSUME( in, linelength + crlflength );
463                     return( CH_DONE );
464                 }
465             }
466         }
467
468         CONSUME( in, linelength + crlflength );
469     }
470 }
471
472 int cq_feature( in, out )
473     struct papfile      *in, *out;
474 {
475     char                *start, *stop, *p;
476     int                 linelength, crlflength;
477     struct papd_comment *comment = compeek();
478     struct ppd_feature  *pfe;
479
480     for (;;) {
481         switch ( markline( in, &start, &linelength, &crlflength )) {
482         case 0 :
483             return( 0 );
484
485         case -1 :
486             return( CH_MORE );
487         }
488
489         stop = start + linelength;
490
491         if ( comgetflags() == 0 ) {
492             comsetflags( 1 );
493
494             /* parse for feature */
495             for ( p = start; p < stop; p++ ) {
496                 if ( *p == ':' ) {
497                     break;
498                 }
499             }
500             p++;
501             while ( *p == ' ' ) {
502                 p++;
503             }
504
505             if (( pfe = ppd_feature( p, stop - p )) == NULL ) {
506                 if ( comswitch( queries, cq_default ) < 0 ) {
507                     LOG(log_error, logtype_default, "cq_feature: can't find default!" );
508                     exit( 1 );
509                 }
510                 return( CH_DONE );
511             }
512
513             append( out, pfe->pd_value, strlen( pfe->pd_value ));
514             append( out, "\r", 1 );
515         } else {
516             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
517                 compop();
518                 CONSUME( in, linelength + crlflength );
519                 return( CH_DONE );
520             }
521         }
522
523         CONSUME( in, linelength + crlflength );
524     }
525 }
526
527 static const char       *psver = "*PSVersion\n";
528 static const char       *prod = "*Product\n";
529
530 int cq_printer( in, out )
531     struct papfile      *in, *out;
532 {
533     char                *start, *p;
534     int                 linelength, crlflength;
535     struct papd_comment *comment = compeek();
536     struct ppd_feature  *pdpsver, *pdprod;
537
538     for (;;) {
539         switch ( markline( in, &start, &linelength, &crlflength )) {
540         case 0 :
541             return( 0 );
542
543         case -1 :
544             return( CH_MORE );
545         }
546
547         if ( comgetflags() == 0 ) {
548             comsetflags( 1 );
549
550             if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) {
551                 if ( comswitch( queries, cq_default ) < 0 ) {
552                     LOG(log_error, logtype_default, "cq_printer: can't find default!" );
553                     exit( 1 );
554                 }
555                 return( CH_DONE );
556             }
557
558             for ( p = pdpsver->pd_value; *p != '\0'; p++ ) {
559                 if ( *p == ' ' ) {
560                     break;
561                 }
562             }
563             if ( *p == '\0' ) {
564                 LOG(log_error, logtype_default, "cq_printer: can't parse PSVersion!" );
565                 if ( comswitch( queries, cq_default ) < 0 ) {
566                     LOG(log_error, logtype_default, "cq_printer: can't find default!" );
567                     exit( 1 );
568                 }
569                 return( CH_DONE );
570             }
571
572             if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) {
573                 if ( comswitch( queries, cq_default ) < 0 ) {
574                     LOG(log_error, logtype_default, "cq_printer: can't find default!" );
575                     exit( 1 );
576                 }
577                 return( CH_DONE );
578             }
579
580             /* revision */
581             append( out, p + 1, strlen( p + 1 ));
582             append( out, "\r", 1 );
583
584             /* version */
585             append( out, pdpsver->pd_value, p - pdpsver->pd_value );
586             append( out, "\r", 1 );
587
588             /* product */
589             append( out, pdprod->pd_value, strlen( pdprod->pd_value ));
590             append( out, "\r", 1 );
591         } else {
592             if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
593                 compop();
594                 CONSUME( in, linelength + crlflength );
595                 return( CH_DONE );
596             }
597         }
598
599         CONSUME( in, linelength + crlflength );
600     }
601 }
602
603 static const char       *rmjobfailed = "Failed\n";
604 static const char       *rmjobok = "Ok\n";
605
606 int cq_rmjob( in, out )
607     struct papfile      *in, *out;
608 {
609     char                *start, *stop, *p;
610     int                 linelength, crlflength;
611     int                 job;
612
613     switch ( markline( in, &start, &linelength, &crlflength )) {
614     case 0 :
615         return( 0 );
616
617     case -1 :
618         return( CH_MORE );
619     }
620
621     stop = start + linelength;
622
623     for ( p = start; p < stop; p++ ) {
624         if ( *p == ' ' || *p == '\t' ) {
625             break;
626         }
627     }
628     for ( ; p < stop; p++ ) {
629         if ( *p != ' ' && *p != '\t' ) {
630             break;
631         }
632     }
633
634     *stop = '\0';
635     if ( p < stop && ( job = atoi( p )) > 0 ) {
636         lp_rmjob( job );
637         append( out, rmjobok, strlen( rmjobok ));
638     } else {
639         append( out, rmjobfailed, strlen( rmjobfailed ));
640     }
641
642     compop();
643     CONSUME( in, linelength + crlflength );
644     return( CH_DONE );
645 }
646
647 int cq_listq( in, out )
648     struct papfile      *in, *out;
649 {
650     char                *start;
651     int                 linelength, crlflength;
652
653     switch ( markline( in, &start, &linelength, &crlflength )) {
654     case 0 :
655         return( 0 );
656
657     case -1 :
658         return( CH_MORE );
659     }
660
661     if ( lp_queue( out )) {
662         LOG(log_error, logtype_default, "cq_listq: lp_queue failed" );
663     }
664
665     compop();
666     CONSUME( in, linelength + crlflength );
667     return( CH_DONE );
668 }
669
670
671 /*
672  * Handler for RBILogin
673  */
674
675 static struct uam_obj *papd_uam = NULL;
676 static const char *rbiloginok = "0\r";
677 static const char *rbiloginbad = "-1\r";
678 static const char *rbiloginerrstr = "%%[Error: SecurityError; \
679 SecurityViolation: Unknown user, incorrect password or log on is \
680 disabled ]%%\r%%[Flushing: rest of job (to end-of-file) will be \
681 ignored ]%%\r";
682
683 int cq_rbilogin( in, out )
684     struct papfile      *in, *out;
685 {
686     char                *start, *stop, *p, *begin;
687     int                 linelength, crlflength;
688     char                username[9] = "\0";
689     struct papd_comment *comment = compeek();
690     char                uamtype[20] = "\0";
691
692     for (;;) {
693         switch ( markline( in, &start, &linelength, &crlflength )) {
694         case 0 :
695             return( 0 );
696
697         case -1 :
698             return( CH_MORE );
699         }
700
701         stop = start + linelength;
702
703         if ( comgetflags() == 0 ) { /* first line */
704             begin = start + strlen(comment->c_begin);
705             p = begin;
706
707             while (*p != ' ') {
708                 p++;
709             }
710
711             strncat(uamtype, begin, p - begin);
712
713             if ((papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH,
714                                 uamtype, strlen(uamtype))) == NULL) {
715                 LOG(log_info, logtype_default, "Could not find uam: %s", uamtype);
716                 append(out, rbiloginbad, strlen(rbiloginbad));
717                 append(out, rbiloginerrstr, strlen(rbiloginerrstr));
718             } else {
719                 if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) {
720                     lp_person( username );
721                 } else {
722                     append(out, rbiloginbad, strlen( rbiloginbad));
723                     append(out, rbiloginerrstr, strlen(rbiloginerrstr));
724                 }
725             }
726             comsetflags( 1 );
727         } else {
728             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
729                 compop();
730                 return( CH_DONE );
731             }
732         }
733
734         CONSUME( in, linelength + crlflength );
735     }
736 }
737
738
739 /*
740  * All queries start with %%?Begin and end with %%?End.  Note that the
741  * "Begin"/"End" general queries have to be last.
742  */
743 struct papd_comment     queries[] = {
744 #ifdef KRB
745     { "%%Login: UMICHKerberosIV", 0,                    cq_k4login,     0 },
746     { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth, C_FULL },
747 #endif /* KRB */
748     { "%UMICHListQueue", 0,                             cq_listq, C_FULL },
749     { "%UMICHDeleteJob", 0,                             cq_rmjob,       0 },
750     { "%%?BeginQuery: RBILogin ", "%%?EndQuery",        cq_rbilogin,    0 },
751     { "%%?BeginQuery",          "%%?EndQuery",          cq_query,       0 },
752     { "%%?BeginFeatureQuery",   "%%?EndFeatureQuery",   cq_feature,     0 },
753     { "%%?BeginFontQuery",      "%%?EndFontQuery",      cq_font,        0 },
754     { "%%?BeginPrinterQuery",   "%%?EndPrinterQuery",   cq_printer, C_FULL },
755     { "%%?Begin",               "%%?End",               cq_default,     0 },
756     { 0 },
757 };