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