]> arthur.barton.de Git - netatalk.git/blob - etc/papd/queries.c
CVS id tags, define fixes, code beautification
[netatalk.git] / etc / papd / queries.c
1 /*
2  * $Id: queries.c,v 1.7 2001-06-25 20:13:45 rufustfirefly 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 <sys/syslog.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         syslog( LOG_ERR, "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     syslog( LOG_INFO, "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                     syslog( LOG_ERR, "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) 2.1 (2.1.4 pre-release)\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     { "UMICHListQueue", gq_true },
306     { "UMICHDeleteJob", gq_true },
307     { NULL },
308 };
309
310 int cq_query( in, out )
311     struct papfile      *in, *out;
312 {
313     char                *start, *stop, *p, *q;
314     int                 linelength, crlflength;
315     struct papd_comment *comment = compeek();
316     struct genquery     *gq;
317
318
319     for (;;) {
320         switch ( markline( in, &start, &linelength, &crlflength )) {
321         case 0 :
322             return( 0 );
323
324         case -1 :
325             return( CH_MORE );
326         }
327
328         stop = start+linelength;
329
330         if ( comgetflags() == 0 ) {     /* started */
331             comsetflags( 1 );
332
333             for ( p = start; p < stop; p++ ) {
334                 if ( *p == ':' ) {
335                     break;
336                 }
337             }
338
339             for ( p++; p < stop; p++ ) {
340                 if ( *p != ' ' && *p != '\t' ) {
341                     break;
342                 }
343             }
344
345             for ( q = p; q < stop; q++ ) {
346                 if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) {
347                     break;
348                 }
349             }
350
351             for ( gq = genqueries; gq->gq_name; gq++ ) {
352                 if (( strlen( gq->gq_name ) == q - p ) &&
353                         ( strncmp( gq->gq_name, p, q - p ) == 0 )) {
354                     break;
355                 }
356             }
357             if ( gq->gq_name == NULL || gq->gq_handler == NULL ||
358                     (gq->gq_handler)( out ) < 0 ) {
359                 if ( comswitch( queries, cq_default ) < 0 ) {
360                     syslog( LOG_ERR, "cq_feature: can't find default!" );
361                     exit( 1 );
362                 }
363                 return( CH_DONE );
364             }
365         } else {
366             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
367                 compop();
368                 CONSUME( in, linelength + crlflength );
369                 return( CH_DONE );
370             }
371         }
372
373         CONSUME( in, linelength + crlflength );
374     }
375 }
376
377 void cq_font_answer( start, stop, out )
378     char                *start, *stop;
379     struct papfile      *out;
380 {
381     char                *p, *q, buf[ 256 ];
382     struct ppd_font     *pfo;
383
384     p = start;
385     while ( p < stop ) {
386         while (( *p == ' ' || *p == '\t' ) && p < stop ) {
387             p++;
388         }
389
390         q = buf;
391         while ( *p != ' ' && *p != '\t' &&
392                 *p != '\n' && *p != '\r' && p < stop ) {
393             *q++ = *p++;
394         }
395
396         if ( q != buf ) {
397             *q = '\0';
398
399             append( out, "/", 1 );
400             append( out, buf, strlen( buf ));
401             append( out, ":", 1 );
402
403             if (( pfo = ppd_font( buf )) == NULL ) {
404                 append( out, "No\n", 3 );
405             } else {
406                 append( out, "Yes\n", 4 );
407             }
408         }
409     }
410
411     return;
412 }
413
414 int cq_font( in, out )
415     struct papfile      *in, *out;
416 {
417     char                *start, *stop, *p;
418     int                 linelength, crlflength;
419     struct papd_comment *comment = compeek();
420
421     for (;;) {
422         switch ( markline( in, &start, &linelength, &crlflength )) {
423         case 0 :
424             return( 0 );
425
426         case -1 :
427             return( CH_MORE );
428         }
429
430         stop = start + linelength;
431
432         if ( comgetflags() == 0 ) {
433             comsetflags( 1 );
434
435             for ( p = start; p < stop; p++ ) {
436                 if ( *p == ':' ) {
437                     break;
438                 }
439             }
440             p++;
441
442             cq_font_answer( p, stop, out );
443         } else {
444             if ( comgetflags() == 1 &&
445                     comcmp( start, stop, comcont, 0 ) == 0 ) {
446                 /* continuation */
447
448                 for ( p = start; p < stop; p++ ) {
449                     if ( *p == ' ' ) {
450                         break;
451                     }
452                 }
453                 p++;
454
455                 cq_font_answer( p, stop, out );
456             } else {
457                 comsetflags( 2 );
458                 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
459                     append( out, "*\n", 2 );
460                     compop();
461                     CONSUME( in, linelength + crlflength );
462                     return( CH_DONE );
463                 }
464             }
465         }
466
467         CONSUME( in, linelength + crlflength );
468     }
469 }
470
471 int cq_feature( in, out )
472     struct papfile      *in, *out;
473 {
474     char                *start, *stop, *p;
475     int                 linelength, crlflength;
476     struct papd_comment *comment = compeek();
477     struct ppd_feature  *pfe;
478
479     for (;;) {
480         switch ( markline( in, &start, &linelength, &crlflength )) {
481         case 0 :
482             return( 0 );
483
484         case -1 :
485             return( CH_MORE );
486         }
487
488         stop = start + linelength;
489
490         if ( comgetflags() == 0 ) {
491             comsetflags( 1 );
492
493             /* parse for feature */
494             for ( p = start; p < stop; p++ ) {
495                 if ( *p == ':' ) {
496                     break;
497                 }
498             }
499             p++;
500             while ( *p == ' ' ) {
501                 p++;
502             }
503
504             if (( pfe = ppd_feature( p, stop - p )) == NULL ) {
505                 if ( comswitch( queries, cq_default ) < 0 ) {
506                     syslog( LOG_ERR, "cq_feature: can't find default!" );
507                     exit( 1 );
508                 }
509                 return( CH_DONE );
510             }
511
512             append( out, pfe->pd_value, strlen( pfe->pd_value ));
513             append( out, "\r", 1 );
514         } else {
515             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
516                 compop();
517                 CONSUME( in, linelength + crlflength );
518                 return( CH_DONE );
519             }
520         }
521
522         CONSUME( in, linelength + crlflength );
523     }
524 }
525
526 static const char       *psver = "*PSVersion\n";
527 static const char       *prod = "*Product\n";
528
529 int cq_printer( in, out )
530     struct papfile      *in, *out;
531 {
532     char                *start, *p;
533     int                 linelength, crlflength;
534     struct papd_comment *comment = compeek();
535     struct ppd_feature  *pdpsver, *pdprod;
536
537     for (;;) {
538         switch ( markline( in, &start, &linelength, &crlflength )) {
539         case 0 :
540             return( 0 );
541
542         case -1 :
543             return( CH_MORE );
544         }
545
546         if ( comgetflags() == 0 ) {
547             comsetflags( 1 );
548
549             if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) {
550                 if ( comswitch( queries, cq_default ) < 0 ) {
551                     syslog( LOG_ERR, "cq_printer: can't find default!" );
552                     exit( 1 );
553                 }
554                 return( CH_DONE );
555             }
556
557             for ( p = pdpsver->pd_value; *p != '\0'; p++ ) {
558                 if ( *p == ' ' ) {
559                     break;
560                 }
561             }
562             if ( *p == '\0' ) {
563                 syslog( LOG_ERR, "cq_printer: can't parse PSVersion!" );
564                 if ( comswitch( queries, cq_default ) < 0 ) {
565                     syslog( LOG_ERR, "cq_printer: can't find default!" );
566                     exit( 1 );
567                 }
568                 return( CH_DONE );
569             }
570
571             if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) {
572                 if ( comswitch( queries, cq_default ) < 0 ) {
573                     syslog( LOG_ERR, "cq_printer: can't find default!" );
574                     exit( 1 );
575                 }
576                 return( CH_DONE );
577             }
578
579             /* revision */
580             append( out, p + 1, strlen( p + 1 ));
581             append( out, "\r", 1 );
582
583             /* version */
584             append( out, pdpsver->pd_value, p - pdpsver->pd_value );
585             append( out, "\r", 1 );
586
587             /* product */
588             append( out, pdprod->pd_value, strlen( pdprod->pd_value ));
589             append( out, "\r", 1 );
590         } else {
591             if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
592                 compop();
593                 CONSUME( in, linelength + crlflength );
594                 return( CH_DONE );
595             }
596         }
597
598         CONSUME( in, linelength + crlflength );
599     }
600 }
601
602 static const char       *rmjobfailed = "Failed\n";
603 static const char       *rmjobok = "Ok\n";
604
605 int cq_rmjob( in, out )
606     struct papfile      *in, *out;
607 {
608     char                *start, *stop, *p;
609     int                 linelength, crlflength;
610     int                 job;
611
612     switch ( markline( in, &start, &linelength, &crlflength )) {
613     case 0 :
614         return( 0 );
615
616     case -1 :
617         return( CH_MORE );
618     }
619
620     stop = start + linelength;
621
622     for ( p = start; p < stop; p++ ) {
623         if ( *p == ' ' || *p == '\t' ) {
624             break;
625         }
626     }
627     for ( ; p < stop; p++ ) {
628         if ( *p != ' ' && *p != '\t' ) {
629             break;
630         }
631     }
632
633     *stop = '\0';
634     if ( p < stop && ( job = atoi( p )) > 0 ) {
635         lp_rmjob( job );
636         append( out, rmjobok, strlen( rmjobok ));
637     } else {
638         append( out, rmjobfailed, strlen( rmjobfailed ));
639     }
640
641     compop();
642     CONSUME( in, linelength + crlflength );
643     return( CH_DONE );
644 }
645
646 int cq_listq( in, out )
647     struct papfile      *in, *out;
648 {
649     char                *start;
650     int                 linelength, crlflength;
651
652     switch ( markline( in, &start, &linelength, &crlflength )) {
653     case 0 :
654         return( 0 );
655
656     case -1 :
657         return( CH_MORE );
658     }
659
660     if ( lp_queue( out )) {
661         syslog( LOG_ERR, "cq_listq: lp_queue failed" );
662     }
663
664     compop();
665     CONSUME( in, linelength + crlflength );
666     return( CH_DONE );
667 }
668
669
670 /*
671  * Handler for RBILogin
672  */
673
674 static struct uam_obj *papd_uam = NULL;
675 static const char *rbiloginok = "0\r";
676 static const char *rbiloginbad = "-1\r";
677 static const char *rbiloginerrstr = "%%[Error: SecurityError; \
678 SecurityViolation: Unknown user, incorrect password or log on is \
679 disabled ]%%\r%%Flushing: rest of job (to end-of-file) will be \
680 ignored ]%%\r";
681
682 int cq_rbilogin( in, out )
683     struct papfile      *in, *out;
684 {
685     char                *start, *stop, *p, *begin;
686     int                 linelength, crlflength;
687     char                username[9] = "\0";
688     struct papd_comment *comment = compeek();
689     char                uamtype[20] = "\0";
690
691     for (;;) {
692         switch ( markline( in, &start, &linelength, &crlflength )) {
693         case 0 :
694             return( 0 );
695
696         case -1 :
697             return( CH_MORE );
698         }
699
700         stop = start + linelength;
701
702         if ( comgetflags() == 0 ) { /* first line */
703             begin = start + strlen(comment->c_begin);
704             p = begin;
705
706             while (*p != ' ') {
707                 p++;
708             }
709
710             strncat(uamtype, begin, p - begin);
711
712             if ((papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH,
713                                 uamtype, strlen(uamtype))) == NULL) {
714                 syslog(LOG_INFO, "Could not find uam: %s", uamtype);
715                 append(out, rbiloginbad, strlen(rbiloginbad));
716                 append(out, rbiloginerrstr, strlen(rbiloginerrstr));
717             } else {
718                 if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) {
719                     lp_person( username );
720                 } else {
721                     append(out, rbiloginbad, strlen( rbiloginbad));
722                     append(out, rbiloginerrstr, strlen(rbiloginerrstr));
723                 }
724             }
725             comsetflags( 1 );
726         } else {
727             if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
728                 compop();
729                 return( CH_DONE );
730             }
731         }
732
733         CONSUME( in, linelength + crlflength );
734     }
735 }
736
737
738 /*
739  * All queries start with %%?Begin and end with %%?End.  Note that the
740  * "Begin"/"End" general queries have to be last.
741  */
742 struct papd_comment     queries[] = {
743 #ifdef KRB
744     { "%%Login: UMICHKerberosIV", 0,                    cq_k4login,     0 },
745     { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth, C_FULL },
746 #endif KRB
747     { "%UMICHListQueue", 0,                             cq_listq, C_FULL },
748     { "%UMICHDeleteJob", 0,                             cq_rmjob,       0 },
749     { "%%?BeginQuery: RBILogin ", "%%?EndQuery",        cq_rbilogin,    0 },
750     { "%%?BeginQuery",          "%%?EndQuery",          cq_query,       0 },
751     { "%%?BeginFeatureQuery",   "%%?EndFeatureQuery",   cq_feature,     0 },
752     { "%%?BeginFontQuery",      "%%?EndFontQuery",      cq_font,        0 },
753     { "%%?BeginPrinterQuery",   "%%?EndPrinterQuery",   cq_printer, C_FULL },
754     { "%%?Begin",               "%%?End",               cq_default,     0 },
755     { 0 },
756 };