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